2 # -*- coding: utf-8 -*-
3 # PYTHON_ARGCOMPLETE_OK
6 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
7 # This file is part of openmano
10 # Licensed under the Apache License, Version 2.0 (the "License"); you may
11 # not use this file except in compliance with the License. You may obtain
12 # a copy of the License at
14 # http://www.apache.org/licenses/LICENSE-2.0
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19 # License for the specific language governing permissions and limitations
22 # For those usages not covered by the Apache License, Version 2.0 please
23 # contact with: nfvlabs@tid.es
27 openmano client used to interact with openmano-server (openmanod)
29 __author__="Alfonso Tierno, Gerardo Garcia"
30 __date__ ="$09-oct-2014 09:09:48$"
31 __version__="0.4.3-r467"
32 version_date="Mar 2016"
34 from argcomplete.completers import FilesCompleter
42 #from jsonschema import validate as js_v, exceptions as js_e
44 class ArgumentParserError(Exception): pass
46 class OpenmanoCLIError(Exception): pass
48 class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
62 print "OPENMANO_TENANT: %s" %mano_tenant
63 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
65 def _print_verbose(mano_response, verbose_level=0):
66 content = mano_response.json()
67 result = 0 if mano_response.status_code==200 else mano_response.status_code
68 if type(content)!=dict or len(content)!=1:
69 #print "Non expected format output"
73 val=content.values()[0]
77 elif type(val) == list:
82 #print "Non expected dict/list format output"
87 if verbose_level==None:
89 if verbose_level >= 3:
90 print yaml.safe_dump(content, indent=4, default_flow_style=False)
93 if mano_response.status_code == 200:
94 for content in content_list:
96 uuid = content['uuid']
99 elif "vim_id" in content:
100 uuid = content['vim_id']
101 myoutput = "%s %s" %(uuid.ljust(38),content['name'].ljust(20))
102 if "status" in content:
103 myoutput += " " + content['status'].ljust(20)
104 elif "enabled" in content and not content["enabled"]:
105 myoutput += " enabled=False".ljust(20)
106 if verbose_level >=1:
107 if 'created_at' in content:
108 myoutput += " " + content['created_at'].ljust(20)
109 if verbose_level >=2:
111 if 'type' in content and content['type']!=None:
112 myoutput += new_line + " Type: " + content['type'].ljust(29)
114 if 'description' in content and content['description']!=None:
115 myoutput += new_line + " Description: " + content['description'].ljust(20)
118 print content['error']['description']
121 def parser_json_yaml(file_name):
123 f = file(file_name, "r")
126 except Exception as e:
127 return (False, str(e))
130 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
132 config = yaml.load(text)
133 except yaml.YAMLError as exc:
135 if hasattr(exc, 'problem_mark'):
136 mark = exc.problem_mark
137 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
138 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
141 config = json.loads(text)
142 except Exception as e:
143 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
147 def _load_file_or_yaml(content):
149 'content' can be or a yaml/json file or a text containing a yaml/json text format
150 This function autodetect, trying to load and parse the file,
151 if fails trying to parse the 'content' text
152 Returns the dictionary once parsed, or print an error and finish the program
154 #Check config file exists
155 if os.path.isfile(content):
156 r,payload = parser_json_yaml(content)
160 elif "{" in content or ":" in content:
162 payload = yaml.load(content)
163 except yaml.YAMLError as exc:
165 if hasattr(exc, 'problem_mark'):
166 mark = exc.problem_mark
167 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
168 print "Error loading yaml/json text"+error_pos
171 print "'%s' is neither a valid file nor a yaml/json content" % content
175 def _get_item_uuid(item, item_name_id, tenant=None):
177 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
179 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
180 mano_response = requests.get(URLrequest)
181 logger.debug("openmano response: %s", mano_response.text )
182 content = mano_response.json()
185 for i in content[item]:
186 if i["uuid"] == item_name_id:
188 if i["name"] == item_name_id:
192 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
194 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
197 # def check_valid_uuid(uuid):
198 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
200 # js_v(uuid, id_schema)
202 # except js_e.ValidationError:
205 def _get_tenant(tenant_name_id = None):
206 if not tenant_name_id:
207 tenant_name_id = mano_tenant
209 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
210 return _get_item_uuid("tenants", tenant_name_id)
212 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
213 if not datacenter_name_id:
214 datacenter_name_id = mano_datacenter
215 if not datacenter_name_id:
216 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
217 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
219 def vnf_create(args):
220 #print "vnf-create",args
221 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
222 tenant = _get_tenant()
223 myvnf = _load_file_or_yaml(args.file)
225 if args.name or args.description or args.image_path:
229 myvnf['vnf']['name'] = args.name
231 myvnf['vnf']['description'] = args.description
234 for image_path_ in args.image_path.split(","):
235 #print "image-path", image_path_
236 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
238 except (KeyError, TypeError), e:
239 if str(e)=='vnf': error_pos= "missing field 'vnf'"
240 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
241 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
242 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
243 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
244 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
245 else: error_pos="wrong format"
246 print "Wrong VNF descriptor: " + error_pos
248 payload_req = json.dumps(myvnf)
252 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
253 logger.debug("openmano request: %s", payload_req)
254 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
255 logger.debug("openmano response: %s", mano_response.text )
257 return _print_verbose(mano_response, args.verbose)
260 #print "vnf-list",args
264 tenant = _get_tenant()
266 toshow = _get_item_uuid("vnfs", args.name, tenant)
267 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
269 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
270 mano_response = requests.get(URLrequest)
271 logger.debug("openmano response: %s", mano_response.text )
272 content = mano_response.json()
273 #print json.dumps(content, indent=4)
274 if args.verbose==None:
276 result = 0 if mano_response.status_code==200 else mano_response.status_code
277 if mano_response.status_code == 200:
279 if args.verbose >= 3:
280 print yaml.safe_dump(content, indent=4, default_flow_style=False)
282 if len(content['vnfs']) == 0:
283 print "No VNFs were found."
284 return 404 #HTTP_Not_Found
285 for vnf in content['vnfs']:
286 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
288 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
291 print " Description: %s" %vnf['description']
292 print " VNF descriptor file: %s" %vnf['path']
295 print yaml.safe_dump(content, indent=4, default_flow_style=False)
298 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
299 print " Description: %s" %vnf['description']
300 #print " VNF descriptor file: %s" %vnf['path']
302 for vm in vnf['VNFC']:
303 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
304 print " %s %s" %(vm['name'].ljust(20), vm['description'])
305 if len(vnf['nets'])>0:
306 print " Internal nets:"
307 for net in vnf['nets']:
308 print " %s %s" %(net['name'].ljust(20), net['description'])
309 if len(vnf['external-connections'])>0:
310 print " External interfaces:"
311 for interface in vnf['external-connections']:
312 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
313 interface['vpci'].ljust(14))
315 print content['error']['description']
317 print yaml.safe_dump(content, indent=4, default_flow_style=False)
320 def vnf_delete(args):
321 #print "vnf-delete",args
325 tenant = _get_tenant()
326 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
328 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
329 if not (len(r)>0 and r[0].lower()=="y"):
331 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
332 mano_response = requests.delete(URLrequest)
333 logger.debug("openmano response: %s", mano_response.text )
334 result = 0 if mano_response.status_code==200 else mano_response.status_code
335 content = mano_response.json()
336 #print json.dumps(content, indent=4)
337 if mano_response.status_code == 200:
338 print content['result']
340 print content['error']['description']
343 def scenario_create(args):
344 #print "scenario-create",args
345 tenant = _get_tenant()
346 headers_req = {'content-type': 'application/yaml'}
347 myscenario = _load_file_or_yaml(args.file)
350 myscenario['name'] = args.name
352 myscenario['description'] = args.description
353 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
357 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
358 logger.debug("openmano request: %s", payload_req)
359 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
360 logger.debug("openmano response: %s", mano_response.text )
361 return _print_verbose(mano_response, args.verbose)
363 def scenario_list(args):
364 #print "scenario-list",args
368 tenant = _get_tenant()
370 toshow = _get_item_uuid("scenarios", args.name, tenant)
371 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
373 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
374 mano_response = requests.get(URLrequest)
375 logger.debug("openmano response: %s", mano_response.text )
376 content = mano_response.json()
377 #print json.dumps(content, indent=4)
378 if args.verbose==None:
381 result = 0 if mano_response.status_code==200 else mano_response.status_code
382 if mano_response.status_code == 200:
384 if args.verbose >= 3:
385 print yaml.safe_dump(content, indent=4, default_flow_style=False)
387 if len(content['scenarios']) == 0:
388 print "No scenarios were found."
389 return 404 #HTTP_Not_Found
390 for scenario in content['scenarios']:
391 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
393 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
396 print " Description: %s" %scenario['description']
399 print yaml.safe_dump(content, indent=4, default_flow_style=False)
401 scenario = content['scenario']
402 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
404 print " Description: %s" %scenario['description']
406 for vnf in scenario['vnfs']:
407 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
408 if len(scenario['nets'])>0:
409 print " Internal nets:"
410 for net in scenario['nets']:
411 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
412 net['description'] = '-'
413 if not net['external']:
414 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
415 print " External nets:"
416 for net in scenario['nets']:
418 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
420 print content['error']['description']
422 print yaml.safe_dump(content, indent=4, default_flow_style=False)
425 def scenario_delete(args):
426 #print "scenario-delete",args
430 tenant = _get_tenant()
431 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
433 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
434 if not (len(r)>0 and r[0].lower()=="y"):
436 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
437 mano_response = requests.delete(URLrequest)
438 logger.debug("openmano response: %s", mano_response.text )
439 result = 0 if mano_response.status_code==200 else mano_response.status_code
440 content = mano_response.json()
441 #print json.dumps(content, indent=4)
442 if mano_response.status_code == 200:
443 print content['result']
445 print content['error']['description']
448 def scenario_deploy(args):
449 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
452 args.netmap_use = None
453 args.netmap_create = None
454 return instance_create(args)
456 # #print "scenario-deploy",args
457 # headers_req = {'content-type': 'application/json'}
461 # actionCmd="reserve"
462 # action[actionCmd] = {}
463 # action[actionCmd]["instance_name"] = args.name
464 # if args.datacenter != None:
465 # action[actionCmd]["datacenter"] = args.datacenter
466 # elif mano_datacenter != None:
467 # action[actionCmd]["datacenter"] = mano_datacenter
469 # if args.description:
470 # action[actionCmd]["description"] = args.description
471 # payload_req = json.dumps(action, indent=4)
474 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
475 # logger.debug("openmano request: %s", payload_req)
476 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
477 # logger.debug("openmano response: %s", mano_response.text )
478 # if args.verbose==None:
481 # result = 0 if mano_response.status_code==200 else mano_response.status_code
482 # content = mano_response.json()
483 # #print json.dumps(content, indent=4)
484 # if args.verbose >= 3:
485 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
488 # if mano_response.status_code == 200:
489 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
490 # if args.verbose >=1:
491 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
492 # if args.verbose >=2:
493 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
496 # print "To check the status, run the following command:"
497 # print "openmano instance-scenario-list <instance_id>"
499 # print content['error']['description']
502 def scenario_verify(args):
503 #print "scenario-verify",args
504 headers_req = {'content-type': 'application/json'}
506 action["verify"] = {}
507 action["verify"]["instance_name"] = "scen-verify-return5"
508 payload_req = json.dumps(action, indent=4)
511 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
512 logger.debug("openmano request: %s", payload_req)
513 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
514 logger.debug("openmano response: %s", mano_response.text )
516 result = 0 if mano_response.status_code==200 else mano_response.status_code
517 content = mano_response.json()
518 #print json.dumps(content, indent=4)
519 if mano_response.status_code == 200:
520 print content['result']
522 print content['error']['description']
525 def instance_create(args):
526 tenant = _get_tenant()
527 headers_req = {'content-type': 'application/yaml'}
528 myInstance={"instance": {}, "schema_version": "0.1"}
530 instance_dict = _load_file_or_yaml(args.file)
531 if "instance" not in instance_dict:
532 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
534 myInstance = instance_dict
536 myInstance["instance"]['name'] = args.name
538 myInstance["instance"]['description'] = args.description
540 myInstance["instance"]['action'] = "reserve"
542 datacenter = myInstance["instance"].get("datacenter")
543 if args.datacenter != None:
544 datacenter = args.datacenter
545 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
547 scenario = myInstance["instance"].get("scenario")
548 if args.scenario != None:
549 scenario = args.scenario
551 print "you must provide an scenario in the file descriptor or with --scenario"
553 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
555 if "networks" not in myInstance["instance"]:
556 myInstance["instance"]["networks"] = {}
557 for net in args.netmap_use:
558 net_comma_list = net.split(",")
559 for net_comma in net_comma_list:
560 net_tuple = net_comma.split("=")
561 if len(net_tuple) != 2:
562 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
564 net_scenario = net_tuple[0].strip()
565 net_datacenter = net_tuple[1].strip()
566 if net_scenario not in myInstance["instance"]["networks"]:
567 myInstance["instance"]["networks"][net_scenario] = {}
568 myInstance["instance"]["networks"][net_scenario]["netmap-use"] = net_datacenter
569 if args.netmap_create:
570 if "networks" not in myInstance["instance"]:
571 myInstance["instance"]["networks"] = {}
572 for net in args.netmap_create:
573 net_comma_list = net.split(",")
574 for net_comma in net_comma_list:
575 net_tuple = net_comma.split("=")
576 if len(net_tuple) == 1:
577 net_scenario = net_tuple[0].strip()
578 net_datacenter = None
579 elif len(net_tuple) == 2:
580 net_scenario = net_tuple[0].strip()
581 net_datacenter = net_tuple[1].strip()
583 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
585 if net_scenario not in myInstance["instance"]["networks"]:
586 myInstance["instance"]["networks"][net_scenario] = {}
587 myInstance["instance"]["networks"][net_scenario]["netmap-create"] = net_datacenter
589 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
590 logger.debug("openmano request: %s", payload_req)
591 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
592 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
593 logger.debug("openmano response: %s", mano_response.text )
594 if args.verbose==None:
597 result = 0 if mano_response.status_code==200 else mano_response.status_code
598 content = mano_response.json()
599 #print json.dumps(content, indent=4)
600 if args.verbose >= 3:
601 print yaml.safe_dump(content, indent=4, default_flow_style=False)
604 if mano_response.status_code == 200:
605 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
607 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
609 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
612 print content['error']['description']
615 def instance_scenario_list(args):
616 #print "instance-scenario-list",args
620 tenant = _get_tenant()
622 toshow = _get_item_uuid("instances", args.name, tenant)
623 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
625 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
626 mano_response = requests.get(URLrequest)
627 logger.debug("openmano response: %s", mano_response.text )
628 content = mano_response.json()
629 #print json.dumps(content, indent=4)
630 if args.verbose==None:
633 result = 0 if mano_response.status_code==200 else mano_response.status_code
634 if mano_response.status_code == 200:
636 if args.verbose >= 3:
637 print yaml.safe_dump(content, indent=4, default_flow_style=False)
639 if len(content['instances']) == 0:
640 print "No scenario instances were found."
642 for instance in content['instances']:
643 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
645 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
648 print "Description: %s" %instance['description']
651 print yaml.safe_dump(content, indent=4, default_flow_style=False)
654 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
655 print "Description: %s" %instance['description']
656 print "Template scenario id: %s" %instance['scenario_id']
657 print "Template scenario name: %s" %instance['scenario_name']
658 print "---------------------------------------"
659 print "VNF instances: %d" %len(instance['vnfs'])
660 for vnf in instance['vnfs']:
661 #print " %s %s Template vnf name: %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['name'].ljust(20), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
662 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
663 if len(instance['nets'])>0:
664 print "---------------------------------------"
665 print "Internal nets:"
666 for net in instance['nets']:
667 if not net['external']:
668 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
669 print "---------------------------------------"
670 print "External nets:"
671 for net in instance['nets']:
673 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
674 print "---------------------------------------"
675 print "VM instances:"
676 for vnf in instance['vnfs']:
677 for vm in vnf['vms']:
678 print " %s %s %s %s VIM ID: %s" %(vm['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vm['name'].ljust(20), vm['status'].ljust(12), vm['vim_vm_id'])
680 print content['error']['description']
682 print yaml.safe_dump(content, indent=4, default_flow_style=False)
685 def instance_scenario_status(args):
686 print "instance-scenario-status"
689 def instance_scenario_delete(args):
693 tenant = _get_tenant()
694 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
695 #print "instance-scenario-delete",args
697 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
698 if not (len(r)>0 and r[0].lower()=="y"):
700 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
701 mano_response = requests.delete(URLrequest)
702 logger.debug("openmano response: %s", mano_response.text )
703 result = 0 if mano_response.status_code==200 else mano_response.status_code
704 content = mano_response.json()
705 #print json.dumps(content, indent=4)
706 if mano_response.status_code == 200:
707 print content['result']
709 print content['error']['description']
712 def instance_scenario_action(args):
713 #print "instance-scenario-action", args
714 tenant = _get_tenant()
715 toact = _get_item_uuid("instances", args.name, tenant=tenant)
717 action[ args.action ] = args.param
719 action["vnfs"] = args.vnf
721 action["vms"] = args.vm
723 headers_req = {'content-type': 'application/json'}
724 payload_req = json.dumps(action, indent=4)
725 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
726 logger.debug("openmano request: %s", payload_req)
727 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
728 logger.debug("openmano response: %s", mano_response.text )
729 result = 0 if mano_response.status_code==200 else mano_response.status_code
730 content = mano_response.json()
731 #print json.dumps(content, indent=4)
732 if mano_response.status_code == 200:
734 print yaml.safe_dump(content, indent=4, default_flow_style=False)
736 for uuid,c in content.iteritems():
737 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
739 print content['error']['description']
743 def instance_vnf_list(args):
744 print "instance-vnf-list"
747 def instance_vnf_status(args):
748 print "instance-vnf-status"
751 def tenant_create(args):
752 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
753 tenant_dict={"name": args.name}
754 if args.description!=None:
755 tenant_dict["description"] = args.description
756 payload_req = json.dumps( {"tenant": tenant_dict })
760 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
761 logger.debug("openmano request: %s", payload_req)
762 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
763 logger.debug("openmano response: %s", mano_response.text )
764 return _print_verbose(mano_response, args.verbose)
766 def tenant_list(args):
767 #print "tenant-list",args
769 toshow = _get_item_uuid("vnfs", args.name)
770 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
772 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
773 mano_response = requests.get(URLrequest)
774 logger.debug("openmano response: %s", mano_response.text )
775 if args.verbose==None:
779 return _print_verbose(mano_response, args.verbose)
781 def tenant_delete(args):
782 #print "tenant-delete",args
783 todelete = _get_item_uuid("tenants", args.name)
785 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
786 if not (len(r)>0 and r[0].lower()=="y"):
788 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
789 mano_response = requests.delete(URLrequest)
790 logger.debug("openmano response: %s", mano_response.text )
791 result = 0 if mano_response.status_code==200 else mano_response.status_code
792 content = mano_response.json()
793 #print json.dumps(content, indent=4)
794 if mano_response.status_code == 200:
795 print content['result']
797 print content['error']['description']
800 def datacenter_attach(args):
801 tenant = _get_tenant()
802 datacenter = _get_datacenter(args.name)
803 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
806 if args.vim_tenant_id != None:
807 datacenter_dict['vim_tenant'] = args.vim_tenant_id
808 if args.vim_tenant_name != None:
809 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
810 if args.user != None:
811 datacenter_dict['vim_username'] = args.user
812 if args.password != None:
813 datacenter_dict['vim_password'] = args.password
814 payload_req = json.dumps( {"datacenter": datacenter_dict })
818 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
819 logger.debug("openmano request: %s", payload_req)
820 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
821 logger.debug("openmano response: %s", mano_response.text )
822 result = _print_verbose(mano_response, args.verbose)
823 #provide addional information if error
824 if mano_response.status_code != 200:
825 content = mano_response.json()
826 if "already in use for 'name'" in content['error']['description'] and \
827 "to database vim_tenants table" in content['error']['description']:
828 print "Try to specify a different name with --vim-tenant-name"
831 def datacenter_detach(args):
835 tenant = _get_tenant()
836 datacenter = _get_datacenter(args.name, tenant)
837 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
838 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
839 mano_response = requests.delete(URLrequest, headers=headers_req)
840 logger.debug("openmano response: %s", mano_response.text )
841 content = mano_response.json()
842 #print json.dumps(content, indent=4)
843 result = 0 if mano_response.status_code==200 else mano_response.status_code
844 if mano_response.status_code == 200:
845 print content['result']
847 print content['error']['description']
850 def datacenter_create(args):
851 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
852 datacenter_dict={"name": args.name, "vim_url": args.url}
853 if args.description!=None:
854 datacenter_dict["description"] = args.description
856 datacenter_dict["type"] = args.type
858 datacenter_dict["vim_url_admin"] = args.url_admin
859 if args.config!=None:
860 datacenter_dict["config"] = _load_file_or_yaml(args.config)
861 payload_req = json.dumps( {"datacenter": datacenter_dict })
865 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
866 logger.debug("openmano request: %s", payload_req)
867 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
868 logger.debug("openmano response: %s", mano_response.text )
869 return _print_verbose(mano_response, args.verbose)
871 def datacenter_delete(args):
872 #print "datacenter-delete",args
873 todelete = _get_item_uuid("datacenters", args.name, "any")
875 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
876 if not (len(r)>0 and r[0].lower()=="y"):
878 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
879 mano_response = requests.delete(URLrequest)
880 logger.debug("openmano response: %s", mano_response.text )
881 result = 0 if mano_response.status_code==200 else mano_response.status_code
882 content = mano_response.json()
883 #print json.dumps(content, indent=4)
884 if mano_response.status_code == 200:
885 print content['result']
887 print content['error']['description']
890 def datacenter_list(args):
891 #print "datacenter-list",args
892 tenant='any' if args.all else _get_tenant()
895 toshow = _get_item_uuid("datacenters", args.name, tenant)
896 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
898 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
899 mano_response = requests.get(URLrequest)
900 logger.debug("openmano response: %s", mano_response.text )
901 if args.verbose==None:
905 return _print_verbose(mano_response, args.verbose)
907 def vim_action(args):
908 #print "datacenter-net-action",args
909 tenant = _get_tenant()
910 datacenter = _get_datacenter(args.datacenter, tenant)
911 if args.verbose==None:
913 if args.action=="list":
914 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
917 URLrequest += "/" + args.name
918 mano_response = requests.get(URLrequest)
919 logger.debug("openmano response: %s", mano_response.text )
920 return _print_verbose(mano_response, args.verbose)
921 elif args.action=="delete":
922 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
923 mano_response = requests.delete(URLrequest)
924 logger.debug("openmano response: %s", mano_response.text )
925 result = 0 if mano_response.status_code==200 else mano_response.status_code
926 content = mano_response.json()
927 #print json.dumps(content, indent=4)
928 if mano_response.status_code == 200:
929 print content['result']
931 print content['error']['description']
933 elif args.action=="create":
934 headers_req = {'content-type': 'application/yaml'}
936 create_dict = _load_file_or_yaml(args.file)
937 if args.item not in create_dict:
938 create_dict = {args.item: create_dict}
940 create_dict = {args.item:{}}
942 create_dict[args.item]['name'] = args.name
943 #if args.description:
944 # create_dict[args.item]['description'] = args.description
945 if args.item=="vim-net":
947 create_dict[args.item]['bind_net'] = args.bind_net
949 create_dict[args.item]['bind_type'] = args.bind_type
951 create_dict[args.item]['shared'] = args.shared
952 if "name" not in create_dict[args.item]:
953 print "You must provide a name in the descriptor file or with the --name option"
955 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
956 logger.debug("openmano request: %s", payload_req)
957 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
958 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
959 logger.debug("openmano response: %s", mano_response.text )
960 if args.verbose==None:
962 return _print_verbose(mano_response, args.verbose)
965 def datacenter_net_action(args):
966 if args.action == "net-update":
967 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-upload' instead!!!"
969 args.action = "netmap-delete"
972 r = datacenter_netmap_action(args)
975 args.action = "netmap-upload"
976 r = datacenter_netmap_action(args)
979 if args.action == "net-edit":
980 args.netmap = args.net
982 elif args.action == "net-list":
984 elif args.action == "net-delete":
985 args.netmap = args.net
988 args.action = "netmap" + args.action[3:]
991 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
993 return datacenter_netmap_action(args)
995 def datacenter_netmap_action(args):
996 tenant = _get_tenant()
997 datacenter = _get_datacenter(args.datacenter, tenant)
998 #print "datacenter_netmap_action",args
1000 if args.verbose==None:
1002 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1003 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1005 if args.action=="netmap-list":
1007 URLrequest += "/" + args.netmap
1009 mano_response = requests.get(URLrequest)
1011 elif args.action=="netmap-delete":
1012 if args.netmap and args.all:
1013 print "you can not use a netmap name and the option --all at the same time"
1016 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1017 URLrequest += "/" + args.netmap
1019 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1021 print "you must a netmap name or the option --all"
1024 r = raw_input(force_text)
1025 if len(r)>0 and r[0].lower()=="y":
1029 mano_response = requests.delete(URLrequest, headers=headers_req)
1030 elif args.action=="netmap-upload":
1032 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1033 if len(r)>0 and r[0].lower()=="y":
1037 URLrequest += "/upload"
1038 mano_response = requests.post(URLrequest, headers=headers_req)
1039 elif args.action=="netmap-edit" or args.action=="netmap-create":
1041 payload = _load_file_or_yaml(args.file)
1044 if "netmap" not in payload:
1045 payload = {"netmap": payload}
1047 payload["netmap"]["name"] = args.name
1049 payload["netmap"]["vim_id"] = args.vim_id
1050 if args.action=="netmap-create" and args.vim_name:
1051 payload["netmap"]["vim_name"] = args.vim_name
1052 payload_req = json.dumps(payload)
1053 logger.debug("openmano request: %s", payload_req)
1055 if args.action=="netmap-edit" and not args.force:
1056 if len(payload["netmap"]) == 0:
1057 print "You must supply some parameter to edit"
1059 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1060 if len(r)>0 and r[0].lower()=="y":
1064 URLrequest += "/" + args.netmap
1065 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1066 else: #netmap-create
1067 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1068 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1070 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1072 logger.debug("openmano response: %s", mano_response.text )
1073 return _print_verbose(mano_response, args.verbose)
1075 def element_edit(args):
1076 element = _get_item_uuid(args.element, args.name)
1077 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1078 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1079 payload=_load_file_or_yaml(args.file)
1080 if args.element[:-1] not in payload:
1081 payload = {args.element[:-1]: payload }
1082 payload_req = json.dumps(payload)
1085 if not args.force or (args.name==None and args.filer==None):
1086 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1087 if len(r)>0 and r[0].lower()=="y":
1091 logger.debug("openmano request: %s", payload_req)
1092 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1093 logger.debug("openmano response: %s", mano_response.text )
1094 if args.verbose==None:
1098 return _print_verbose(mano_response, args.verbose)
1105 if __name__=="__main__":
1107 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1108 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1109 mano_port = os.getenv('OPENMANO_PORT',"9090")
1110 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1112 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1113 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1115 subparsers = main_parser.add_subparsers(help='commands')
1117 config_parser = subparsers.add_parser('config', help="prints configuration values")
1118 config_parser.set_defaults(func=config)
1120 parent_parser = argparse.ArgumentParser(add_help=False)
1121 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1122 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1124 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1125 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1126 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1127 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1128 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1129 vnf_create_parser.set_defaults(func=vnf_create)
1131 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1132 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1133 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1134 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1135 vnf_list_parser.set_defaults(func=vnf_list)
1137 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1138 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1139 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1140 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1141 vnf_delete_parser.set_defaults(func=vnf_delete)
1143 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1144 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1145 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1146 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1147 scenario_create_parser.set_defaults(func=scenario_create)
1149 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1150 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1151 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1152 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1153 scenario_list_parser.set_defaults(func=scenario_list)
1155 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1156 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1157 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1158 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1159 scenario_delete_parser.set_defaults(func=scenario_delete)
1161 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1162 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1163 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1164 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1165 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1166 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1167 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1169 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1170 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1171 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1172 scenario_deploy_parser.set_defaults(func=scenario_verify)
1174 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1175 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1176 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1177 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1178 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1179 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1180 instance_scenario_create_parser.add_argument("--netmap-use", action="append", type=str, dest="netmap_use", help="indicates a datacenter network to map a scenario network 'scenario-network=datacenter-network'. Can be used several times")
1181 instance_scenario_create_parser.add_argument("--netmap-create", action="append", type=str, dest="netmap_create", help="the scenario network must be created at datacenter 'scenario-network[=datacenter-network-name]' . Can be used several times")
1182 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1183 instance_scenario_create_parser.set_defaults(func=instance_create)
1185 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1186 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1187 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1188 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1190 instance_scenario_delete_parser = subparsers.add_parser('instance-scenario-delete', parents=[parent_parser], help="deletes a scenario instance (and deletes all VM and net instances in VIM)")
1191 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1192 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1193 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1194 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1196 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1197 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1198 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1199 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1200 help="action to send")
1201 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1202 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1203 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1204 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1206 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1207 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1208 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1210 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1211 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1212 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1213 tenant_create_parser.set_defaults(func=tenant_create)
1215 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1216 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1217 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1218 tenant_delete_parser.set_defaults(func=tenant_delete)
1220 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1221 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1222 tenant_list_parser.set_defaults(func=tenant_list)
1224 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1225 for item in item_list:
1226 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1227 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1228 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1229 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1230 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1232 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1233 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1234 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1235 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1236 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1237 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1238 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1239 datacenter_create_parser.set_defaults(func=datacenter_create)
1241 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1242 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1243 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1244 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1246 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1247 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1248 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1249 datacenter_list_parser.set_defaults(func=datacenter_list)
1251 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1252 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1253 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1254 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1255 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1256 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1257 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1259 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1260 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1261 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1262 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1265 action_dict={'net-update': 'retrieves external networks from datacenter',
1266 'net-edit': 'edits an external network',
1267 'net-delete': 'deletes an external network',
1268 'net-list': 'lists external networks from a datacenter'
1270 for item in action_dict:
1271 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1272 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1273 if item=='net-edit' or item=='net-delete':
1274 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1275 if item=='net-edit':
1276 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1277 if item!='net-list':
1278 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1279 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1282 action_dict={'netmap-upload': 'create network senario netmap base on the datacenter networks',
1283 'netmap-create': 'create a new network senario netmap',
1284 'netmap-edit': 'edit name of a network senario netmap',
1285 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1286 'netmap-list': 'list/show network scenario netmaps'
1288 for item in action_dict:
1289 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1290 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1291 #if item=='net-add':
1292 # datacenter_action_parser.add_argument("net", help="name of the network")
1293 if item=='netmap-delete':
1294 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1295 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1296 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1297 if item=='netmap-edit':
1298 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1299 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1300 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1301 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1302 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1303 if item=='netmap-list':
1304 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1305 if item=='netmap-create':
1306 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1307 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1308 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1309 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1310 if item=='netmap-upload':
1311 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1312 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1314 for item in ("network", "tenant"):
1316 commnad_name = 'vim-net'
1318 commnad_name = 'vim-'+item
1319 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1320 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1321 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1322 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1324 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1325 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1326 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1327 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1329 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1330 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1331 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1332 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1334 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1335 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1336 vim_item_create_parser.add_argument("--bind-net", action="store", help="For openvim datacenter type, net to be bind to, for vlan type, use sufix ':<vlan_tag>'")
1338 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1339 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1341 argcomplete.autocomplete(main_parser)
1344 args = main_parser.parse_args()
1346 level = logging.CRITICAL
1347 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1348 if "debug" in args and args.debug:
1349 level = logging.DEBUG
1350 logging.basicConfig(format=streamformat, level= level)
1351 logger = logging.getLogger('mano')
1352 logger.setLevel(level)
1353 result = args.func(args)
1356 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1357 except (requests.exceptions.ConnectionError):
1358 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1360 except (KeyboardInterrupt):
1361 print 'Exiting openmano'
1363 except (SystemExit, ArgumentParserError):
1365 except OpenmanoCLIError as e: