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
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
69 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
70 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
71 mano_response = requests.get(URLrequest)
72 logger.debug("openmano response: %s", mano_response.text )
73 content = mano_response.json()
74 mano_tenant_name = content["tenant"]["name"]
75 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
76 mano_response = requests.get(URLrequest)
77 logger.debug("openmano response: %s", mano_response.text )
78 content = mano_response.json()
79 if "error" not in content:
80 mano_datacenter_id = content["datacenter"]["uuid"]
81 mano_datacenter_name = content["datacenter"]["name"]
82 except OpenmanoCLIError:
84 print "OPENMANO_TENANT: %s" %mano_tenant
85 print " Id: %s" %mano_tenant_id
86 print " Name: %s" %mano_tenant_name
87 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
88 print " Id: %s" %mano_datacenter_id
89 print " Name: %s" %mano_datacenter_name
91 print "OPENMANO_TENANT: %s" %mano_tenant
92 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
94 def _print_verbose(mano_response, verbose_level=0):
95 content = mano_response.json()
96 result = 0 if mano_response.status_code==200 else mano_response.status_code
97 if type(content)!=dict or len(content)!=1:
98 #print "Non expected format output"
102 val=content.values()[0]
106 elif type(val) == list:
108 elif type(val)==dict:
111 #print "Non expected dict/list format output"
116 if verbose_level==None:
118 if verbose_level >= 3:
119 print yaml.safe_dump(content, indent=4, default_flow_style=False)
122 if mano_response.status_code == 200:
123 for content in content_list:
124 if "uuid" in content:
125 uuid = content['uuid']
126 elif "id" in content:
128 elif "vim_id" in content:
129 uuid = content['vim_id']
130 myoutput = "%s %s" %(uuid.ljust(38),content['name'].ljust(20))
131 if "status" in content:
132 myoutput += " " + content['status'].ljust(20)
133 elif "enabled" in content and not content["enabled"]:
134 myoutput += " enabled=False".ljust(20)
135 if verbose_level >=1:
136 if 'created_at' in content:
137 myoutput += " " + content['created_at'].ljust(20)
138 if verbose_level >=2:
140 if 'type' in content and content['type']!=None:
141 myoutput += new_line + " Type: " + content['type'].ljust(29)
143 if 'description' in content and content['description']!=None:
144 myoutput += new_line + " Description: " + content['description'].ljust(20)
147 print content['error']['description']
150 def parser_json_yaml(file_name):
152 f = file(file_name, "r")
155 except Exception as e:
156 return (False, str(e))
159 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
161 config = yaml.load(text)
162 except yaml.YAMLError as exc:
164 if hasattr(exc, 'problem_mark'):
165 mark = exc.problem_mark
166 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
167 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
170 config = json.loads(text)
171 except Exception as e:
172 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
176 def _load_file_or_yaml(content):
178 'content' can be or a yaml/json file or a text containing a yaml/json text format
179 This function autodetect, trying to load and parse the file,
180 if fails trying to parse the 'content' text
181 Returns the dictionary once parsed, or print an error and finish the program
183 #Check config file exists
184 if os.path.isfile(content):
185 r,payload = parser_json_yaml(content)
189 elif "{" in content or ":" in content:
191 payload = yaml.load(content)
192 except yaml.YAMLError as exc:
194 if hasattr(exc, 'problem_mark'):
195 mark = exc.problem_mark
196 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
197 print "Error loading yaml/json text"+error_pos
200 print "'%s' is neither a valid file nor a yaml/json content" % content
204 def _get_item_uuid(item, item_name_id, tenant=None):
206 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
208 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
209 mano_response = requests.get(URLrequest)
210 logger.debug("openmano response: %s", mano_response.text )
211 content = mano_response.json()
214 for i in content[item]:
215 if i["uuid"] == item_name_id:
217 if i["name"] == item_name_id:
221 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
223 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
226 # def check_valid_uuid(uuid):
227 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
229 # js_v(uuid, id_schema)
231 # except js_e.ValidationError:
234 def _get_tenant(tenant_name_id = None):
235 if not tenant_name_id:
236 tenant_name_id = mano_tenant
238 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
239 return _get_item_uuid("tenants", tenant_name_id)
241 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
242 if not datacenter_name_id:
243 datacenter_name_id = mano_datacenter
244 if not datacenter_name_id:
245 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
246 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
248 def vnf_create(args):
249 #print "vnf-create",args
250 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
251 tenant = _get_tenant()
252 myvnf = _load_file_or_yaml(args.file)
254 if args.name or args.description or args.image_path:
258 myvnf['vnf']['name'] = args.name
260 myvnf['vnf']['description'] = args.description
263 for image_path_ in args.image_path.split(","):
264 #print "image-path", image_path_
265 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
267 except (KeyError, TypeError), e:
268 if str(e)=='vnf': error_pos= "missing field 'vnf'"
269 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
270 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
271 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
272 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
273 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
274 else: error_pos="wrong format"
275 print "Wrong VNF descriptor: " + error_pos
277 payload_req = json.dumps(myvnf)
281 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
282 logger.debug("openmano request: %s", payload_req)
283 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
284 logger.debug("openmano response: %s", mano_response.text )
286 return _print_verbose(mano_response, args.verbose)
289 #print "vnf-list",args
293 tenant = _get_tenant()
295 toshow = _get_item_uuid("vnfs", args.name, tenant)
296 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
298 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
299 mano_response = requests.get(URLrequest)
300 logger.debug("openmano response: %s", mano_response.text )
301 content = mano_response.json()
302 #print json.dumps(content, indent=4)
303 if args.verbose==None:
305 result = 0 if mano_response.status_code==200 else mano_response.status_code
306 if mano_response.status_code == 200:
308 if args.verbose >= 3:
309 print yaml.safe_dump(content, indent=4, default_flow_style=False)
311 if len(content['vnfs']) == 0:
312 print "No VNFs were found."
313 return 404 #HTTP_Not_Found
314 for vnf in content['vnfs']:
315 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
317 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
320 print " Description: %s" %vnf['description']
321 print " VNF descriptor file: %s" %vnf['path']
324 print yaml.safe_dump(content, indent=4, default_flow_style=False)
327 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
328 print " Description: %s" %vnf['description']
329 #print " VNF descriptor file: %s" %vnf['path']
331 for vm in vnf['VNFC']:
332 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
333 print " %s %s" %(vm['name'].ljust(20), vm['description'])
334 if len(vnf['nets'])>0:
335 print " Internal nets:"
336 for net in vnf['nets']:
337 print " %s %s" %(net['name'].ljust(20), net['description'])
338 if len(vnf['external-connections'])>0:
339 print " External interfaces:"
340 for interface in vnf['external-connections']:
341 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
342 interface['vpci'].ljust(14))
344 print content['error']['description']
346 print yaml.safe_dump(content, indent=4, default_flow_style=False)
349 def vnf_delete(args):
350 #print "vnf-delete",args
354 tenant = _get_tenant()
355 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
357 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
358 if not (len(r)>0 and r[0].lower()=="y"):
360 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
361 mano_response = requests.delete(URLrequest)
362 logger.debug("openmano response: %s", mano_response.text )
363 result = 0 if mano_response.status_code==200 else mano_response.status_code
364 content = mano_response.json()
365 #print json.dumps(content, indent=4)
366 if mano_response.status_code == 200:
367 print content['result']
369 print content['error']['description']
372 def scenario_create(args):
373 #print "scenario-create",args
374 tenant = _get_tenant()
375 headers_req = {'content-type': 'application/yaml'}
376 myscenario = _load_file_or_yaml(args.file)
379 myscenario['name'] = args.name
381 myscenario['description'] = args.description
382 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
386 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
387 logger.debug("openmano request: %s", payload_req)
388 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
389 logger.debug("openmano response: %s", mano_response.text )
390 return _print_verbose(mano_response, args.verbose)
392 def scenario_list(args):
393 #print "scenario-list",args
397 tenant = _get_tenant()
399 toshow = _get_item_uuid("scenarios", args.name, tenant)
400 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
402 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
403 mano_response = requests.get(URLrequest)
404 logger.debug("openmano response: %s", mano_response.text )
405 content = mano_response.json()
406 #print json.dumps(content, indent=4)
407 if args.verbose==None:
410 result = 0 if mano_response.status_code==200 else mano_response.status_code
411 if mano_response.status_code == 200:
413 if args.verbose >= 3:
414 print yaml.safe_dump(content, indent=4, default_flow_style=False)
416 if len(content['scenarios']) == 0:
417 print "No scenarios were found."
418 return 404 #HTTP_Not_Found
419 for scenario in content['scenarios']:
420 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
422 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
425 print " Description: %s" %scenario['description']
428 print yaml.safe_dump(content, indent=4, default_flow_style=False)
430 scenario = content['scenario']
431 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
433 print " Description: %s" %scenario['description']
435 for vnf in scenario['vnfs']:
436 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
437 if len(scenario['nets'])>0:
438 print " Internal nets:"
439 for net in scenario['nets']:
440 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
441 net['description'] = '-'
442 if not net['external']:
443 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
444 print " External nets:"
445 for net in scenario['nets']:
447 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
449 print content['error']['description']
451 print yaml.safe_dump(content, indent=4, default_flow_style=False)
454 def scenario_delete(args):
455 #print "scenario-delete",args
459 tenant = _get_tenant()
460 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
462 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
463 if not (len(r)>0 and r[0].lower()=="y"):
465 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
466 mano_response = requests.delete(URLrequest)
467 logger.debug("openmano response: %s", mano_response.text )
468 result = 0 if mano_response.status_code==200 else mano_response.status_code
469 content = mano_response.json()
470 #print json.dumps(content, indent=4)
471 if mano_response.status_code == 200:
472 print content['result']
474 print content['error']['description']
477 def scenario_deploy(args):
478 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
481 args.netmap_use = None
482 args.netmap_create = None
483 return instance_create(args)
485 # #print "scenario-deploy",args
486 # headers_req = {'content-type': 'application/json'}
490 # actionCmd="reserve"
491 # action[actionCmd] = {}
492 # action[actionCmd]["instance_name"] = args.name
493 # if args.datacenter != None:
494 # action[actionCmd]["datacenter"] = args.datacenter
495 # elif mano_datacenter != None:
496 # action[actionCmd]["datacenter"] = mano_datacenter
498 # if args.description:
499 # action[actionCmd]["description"] = args.description
500 # payload_req = json.dumps(action, indent=4)
503 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
504 # logger.debug("openmano request: %s", payload_req)
505 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
506 # logger.debug("openmano response: %s", mano_response.text )
507 # if args.verbose==None:
510 # result = 0 if mano_response.status_code==200 else mano_response.status_code
511 # content = mano_response.json()
512 # #print json.dumps(content, indent=4)
513 # if args.verbose >= 3:
514 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
517 # if mano_response.status_code == 200:
518 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
519 # if args.verbose >=1:
520 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
521 # if args.verbose >=2:
522 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
525 # print "To check the status, run the following command:"
526 # print "openmano instance-scenario-list <instance_id>"
528 # print content['error']['description']
531 def scenario_verify(args):
532 #print "scenario-verify",args
533 headers_req = {'content-type': 'application/json'}
535 action["verify"] = {}
536 action["verify"]["instance_name"] = "scen-verify-return5"
537 payload_req = json.dumps(action, indent=4)
540 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
541 logger.debug("openmano request: %s", payload_req)
542 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
543 logger.debug("openmano response: %s", mano_response.text )
545 result = 0 if mano_response.status_code==200 else mano_response.status_code
546 content = mano_response.json()
547 #print json.dumps(content, indent=4)
548 if mano_response.status_code == 200:
549 print content['result']
551 print content['error']['description']
554 def instance_create(args):
555 tenant = _get_tenant()
556 headers_req = {'content-type': 'application/yaml'}
557 myInstance={"instance": {}, "schema_version": "0.1"}
559 instance_dict = _load_file_or_yaml(args.file)
560 if "instance" not in instance_dict:
561 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
563 myInstance = instance_dict
565 myInstance["instance"]['name'] = args.name
567 myInstance["instance"]['description'] = args.description
569 myInstance["instance"]['action'] = "reserve"
571 datacenter = myInstance["instance"].get("datacenter")
572 if args.datacenter != None:
573 datacenter = args.datacenter
574 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
576 scenario = myInstance["instance"].get("scenario")
577 if args.scenario != None:
578 scenario = args.scenario
580 print "you must provide an scenario in the file descriptor or with --scenario"
582 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
584 if "networks" not in myInstance["instance"]:
585 myInstance["instance"]["networks"] = {}
586 for net in args.netmap_use:
587 net_comma_list = net.split(",")
588 for net_comma in net_comma_list:
589 net_tuple = net_comma.split("=")
590 if len(net_tuple) != 2:
591 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
593 net_scenario = net_tuple[0].strip()
594 net_datacenter = net_tuple[1].strip()
595 if net_scenario not in myInstance["instance"]["networks"]:
596 myInstance["instance"]["networks"][net_scenario] = {}
597 myInstance["instance"]["networks"][net_scenario]["netmap-use"] = net_datacenter
598 if args.netmap_create:
599 if "networks" not in myInstance["instance"]:
600 myInstance["instance"]["networks"] = {}
601 for net in args.netmap_create:
602 net_comma_list = net.split(",")
603 for net_comma in net_comma_list:
604 net_tuple = net_comma.split("=")
605 if len(net_tuple) == 1:
606 net_scenario = net_tuple[0].strip()
607 net_datacenter = None
608 elif len(net_tuple) == 2:
609 net_scenario = net_tuple[0].strip()
610 net_datacenter = net_tuple[1].strip()
612 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
614 if net_scenario not in myInstance["instance"]["networks"]:
615 myInstance["instance"]["networks"][net_scenario] = {}
616 myInstance["instance"]["networks"][net_scenario]["netmap-create"] = net_datacenter
618 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
619 logger.debug("openmano request: %s", payload_req)
620 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
621 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
622 logger.debug("openmano response: %s", mano_response.text )
623 if args.verbose==None:
626 result = 0 if mano_response.status_code==200 else mano_response.status_code
627 content = mano_response.json()
628 #print json.dumps(content, indent=4)
629 if args.verbose >= 3:
630 print yaml.safe_dump(content, indent=4, default_flow_style=False)
633 if mano_response.status_code == 200:
634 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
636 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
638 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
641 print content['error']['description']
644 def instance_scenario_list(args):
645 #print "instance-scenario-list",args
649 tenant = _get_tenant()
651 toshow = _get_item_uuid("instances", args.name, tenant)
652 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
654 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
655 mano_response = requests.get(URLrequest)
656 logger.debug("openmano response: %s", mano_response.text )
657 content = mano_response.json()
658 #print json.dumps(content, indent=4)
659 if args.verbose==None:
662 result = 0 if mano_response.status_code==200 else mano_response.status_code
663 if mano_response.status_code == 200:
665 if args.verbose >= 3:
666 print yaml.safe_dump(content, indent=4, default_flow_style=False)
668 if len(content['instances']) == 0:
669 print "No scenario instances were found."
671 for instance in content['instances']:
672 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
674 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
677 print "Description: %s" %instance['description']
680 print yaml.safe_dump(content, indent=4, default_flow_style=False)
683 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
684 print "Description: %s" %instance['description']
685 print "Template scenario id: %s" %instance['scenario_id']
686 print "Template scenario name: %s" %instance['scenario_name']
687 print "---------------------------------------"
688 print "VNF instances: %d" %len(instance['vnfs'])
689 for vnf in instance['vnfs']:
690 #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))
691 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
692 if len(instance['nets'])>0:
693 print "---------------------------------------"
694 print "Internal nets:"
695 for net in instance['nets']:
696 if not net['external']:
697 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
698 print "---------------------------------------"
699 print "External nets:"
700 for net in instance['nets']:
702 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
703 print "---------------------------------------"
704 print "VM instances:"
705 for vnf in instance['vnfs']:
706 for vm in vnf['vms']:
707 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'])
709 print content['error']['description']
711 print yaml.safe_dump(content, indent=4, default_flow_style=False)
714 def instance_scenario_status(args):
715 print "instance-scenario-status"
718 def instance_scenario_delete(args):
722 tenant = _get_tenant()
723 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
724 #print "instance-scenario-delete",args
726 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
727 if not (len(r)>0 and r[0].lower()=="y"):
729 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
730 mano_response = requests.delete(URLrequest)
731 logger.debug("openmano response: %s", mano_response.text )
732 result = 0 if mano_response.status_code==200 else mano_response.status_code
733 content = mano_response.json()
734 #print json.dumps(content, indent=4)
735 if mano_response.status_code == 200:
736 print content['result']
738 print content['error']['description']
741 def instance_scenario_action(args):
742 #print "instance-scenario-action", args
743 tenant = _get_tenant()
744 toact = _get_item_uuid("instances", args.name, tenant=tenant)
746 action[ args.action ] = args.param
748 action["vnfs"] = args.vnf
750 action["vms"] = args.vm
752 headers_req = {'content-type': 'application/json'}
753 payload_req = json.dumps(action, indent=4)
754 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
755 logger.debug("openmano request: %s", payload_req)
756 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
757 logger.debug("openmano response: %s", mano_response.text )
758 result = 0 if mano_response.status_code==200 else mano_response.status_code
759 content = mano_response.json()
760 #print json.dumps(content, indent=4)
761 if mano_response.status_code == 200:
763 print yaml.safe_dump(content, indent=4, default_flow_style=False)
765 for uuid,c in content.iteritems():
766 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
768 print content['error']['description']
772 def instance_vnf_list(args):
773 print "instance-vnf-list"
776 def instance_vnf_status(args):
777 print "instance-vnf-status"
780 def tenant_create(args):
781 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
782 tenant_dict={"name": args.name}
783 if args.description!=None:
784 tenant_dict["description"] = args.description
785 payload_req = json.dumps( {"tenant": tenant_dict })
789 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
790 logger.debug("openmano request: %s", payload_req)
791 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
792 logger.debug("openmano response: %s", mano_response.text )
793 return _print_verbose(mano_response, args.verbose)
795 def tenant_list(args):
796 #print "tenant-list",args
798 toshow = _get_item_uuid("tenants", args.name)
799 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
801 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
802 mano_response = requests.get(URLrequest)
803 logger.debug("openmano response: %s", mano_response.text )
804 if args.verbose==None:
808 return _print_verbose(mano_response, args.verbose)
810 def tenant_delete(args):
811 #print "tenant-delete",args
812 todelete = _get_item_uuid("tenants", args.name)
814 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
815 if not (len(r)>0 and r[0].lower()=="y"):
817 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
818 mano_response = requests.delete(URLrequest)
819 logger.debug("openmano response: %s", mano_response.text )
820 result = 0 if mano_response.status_code==200 else mano_response.status_code
821 content = mano_response.json()
822 #print json.dumps(content, indent=4)
823 if mano_response.status_code == 200:
824 print content['result']
826 print content['error']['description']
829 def datacenter_attach(args):
830 tenant = _get_tenant()
831 datacenter = _get_datacenter(args.name)
832 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
835 if args.vim_tenant_id != None:
836 datacenter_dict['vim_tenant'] = args.vim_tenant_id
837 if args.vim_tenant_name != None:
838 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
839 if args.user != None:
840 datacenter_dict['vim_username'] = args.user
841 if args.password != None:
842 datacenter_dict['vim_password'] = args.password
843 payload_req = json.dumps( {"datacenter": datacenter_dict })
847 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
848 logger.debug("openmano request: %s", payload_req)
849 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
850 logger.debug("openmano response: %s", mano_response.text )
851 result = _print_verbose(mano_response, args.verbose)
852 #provide addional information if error
853 if mano_response.status_code != 200:
854 content = mano_response.json()
855 if "already in use for 'name'" in content['error']['description'] and \
856 "to database vim_tenants table" in content['error']['description']:
857 print "Try to specify a different name with --vim-tenant-name"
860 def datacenter_detach(args):
864 tenant = _get_tenant()
865 datacenter = _get_datacenter(args.name, tenant)
866 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
867 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
868 mano_response = requests.delete(URLrequest, headers=headers_req)
869 logger.debug("openmano response: %s", mano_response.text )
870 content = mano_response.json()
871 #print json.dumps(content, indent=4)
872 result = 0 if mano_response.status_code==200 else mano_response.status_code
873 if mano_response.status_code == 200:
874 print content['result']
876 print content['error']['description']
879 def datacenter_create(args):
880 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
881 datacenter_dict={"name": args.name, "vim_url": args.url}
882 if args.description!=None:
883 datacenter_dict["description"] = args.description
885 datacenter_dict["type"] = args.type
887 datacenter_dict["vim_url_admin"] = args.url_admin
888 if args.config!=None:
889 datacenter_dict["config"] = _load_file_or_yaml(args.config)
890 payload_req = json.dumps( {"datacenter": datacenter_dict })
894 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
895 logger.debug("openmano request: %s", payload_req)
896 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
897 logger.debug("openmano response: %s", mano_response.text )
898 return _print_verbose(mano_response, args.verbose)
900 def datacenter_delete(args):
901 #print "datacenter-delete",args
902 todelete = _get_item_uuid("datacenters", args.name, "any")
904 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
905 if not (len(r)>0 and r[0].lower()=="y"):
907 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
908 mano_response = requests.delete(URLrequest)
909 logger.debug("openmano response: %s", mano_response.text )
910 result = 0 if mano_response.status_code==200 else mano_response.status_code
911 content = mano_response.json()
912 #print json.dumps(content, indent=4)
913 if mano_response.status_code == 200:
914 print content['result']
916 print content['error']['description']
919 def datacenter_list(args):
920 #print "datacenter-list",args
921 tenant='any' if args.all else _get_tenant()
924 toshow = _get_item_uuid("datacenters", args.name, tenant)
925 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
927 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
928 mano_response = requests.get(URLrequest)
929 logger.debug("openmano response: %s", mano_response.text )
930 if args.verbose==None:
934 return _print_verbose(mano_response, args.verbose)
936 def vim_action(args):
937 #print "datacenter-net-action",args
938 tenant = _get_tenant()
939 datacenter = _get_datacenter(args.datacenter, tenant)
940 if args.verbose==None:
942 if args.action=="list":
943 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
946 URLrequest += "/" + args.name
947 mano_response = requests.get(URLrequest)
948 logger.debug("openmano response: %s", mano_response.text )
949 return _print_verbose(mano_response, args.verbose)
950 elif args.action=="delete":
951 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
952 mano_response = requests.delete(URLrequest)
953 logger.debug("openmano response: %s", mano_response.text )
954 result = 0 if mano_response.status_code==200 else mano_response.status_code
955 content = mano_response.json()
956 #print json.dumps(content, indent=4)
957 if mano_response.status_code == 200:
958 print content['result']
960 print content['error']['description']
962 elif args.action=="create":
963 headers_req = {'content-type': 'application/yaml'}
965 create_dict = _load_file_or_yaml(args.file)
966 if args.item not in create_dict:
967 create_dict = {args.item: create_dict}
969 create_dict = {args.item:{}}
971 create_dict[args.item]['name'] = args.name
972 #if args.description:
973 # create_dict[args.item]['description'] = args.description
974 if args.item=="vim-net":
976 create_dict[args.item]['bind_net'] = args.bind_net
978 create_dict[args.item]['bind_type'] = args.bind_type
980 create_dict[args.item]['shared'] = args.shared
981 if "name" not in create_dict[args.item]:
982 print "You must provide a name in the descriptor file or with the --name option"
984 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
985 logger.debug("openmano request: %s", payload_req)
986 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
987 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
988 logger.debug("openmano response: %s", mano_response.text )
989 if args.verbose==None:
991 return _print_verbose(mano_response, args.verbose)
994 def datacenter_net_action(args):
995 if args.action == "net-update":
996 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-upload' instead!!!"
998 args.action = "netmap-delete"
1001 r = datacenter_netmap_action(args)
1004 args.action = "netmap-upload"
1005 r = datacenter_netmap_action(args)
1008 if args.action == "net-edit":
1009 args.netmap = args.net
1011 elif args.action == "net-list":
1013 elif args.action == "net-delete":
1014 args.netmap = args.net
1017 args.action = "netmap" + args.action[3:]
1020 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1022 return datacenter_netmap_action(args)
1024 def datacenter_netmap_action(args):
1025 tenant = _get_tenant()
1026 datacenter = _get_datacenter(args.datacenter, tenant)
1027 #print "datacenter_netmap_action",args
1029 if args.verbose==None:
1031 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1032 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1034 if args.action=="netmap-list":
1036 URLrequest += "/" + args.netmap
1038 mano_response = requests.get(URLrequest)
1040 elif args.action=="netmap-delete":
1041 if args.netmap and args.all:
1042 print "you can not use a netmap name and the option --all at the same time"
1045 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1046 URLrequest += "/" + args.netmap
1048 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1050 print "you must specify a netmap name or the option --all"
1053 r = raw_input(force_text)
1054 if len(r)>0 and r[0].lower()=="y":
1058 mano_response = requests.delete(URLrequest, headers=headers_req)
1059 elif args.action=="netmap-upload":
1061 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1062 if len(r)>0 and r[0].lower()=="y":
1066 URLrequest += "/upload"
1067 mano_response = requests.post(URLrequest, headers=headers_req)
1068 elif args.action=="netmap-edit" or args.action=="netmap-create":
1070 payload = _load_file_or_yaml(args.file)
1073 if "netmap" not in payload:
1074 payload = {"netmap": payload}
1076 payload["netmap"]["name"] = args.name
1078 payload["netmap"]["vim_id"] = args.vim_id
1079 if args.action=="netmap-create" and args.vim_name:
1080 payload["netmap"]["vim_name"] = args.vim_name
1081 payload_req = json.dumps(payload)
1082 logger.debug("openmano request: %s", payload_req)
1084 if args.action=="netmap-edit" and not args.force:
1085 if len(payload["netmap"]) == 0:
1086 print "You must supply some parameter to edit"
1088 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1089 if len(r)>0 and r[0].lower()=="y":
1093 URLrequest += "/" + args.netmap
1094 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1095 else: #netmap-create
1096 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1097 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1099 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1101 logger.debug("openmano response: %s", mano_response.text )
1102 return _print_verbose(mano_response, args.verbose)
1104 def element_edit(args):
1105 element = _get_item_uuid(args.element, args.name)
1106 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1107 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1108 payload=_load_file_or_yaml(args.file)
1109 if args.element[:-1] not in payload:
1110 payload = {args.element[:-1]: payload }
1111 payload_req = json.dumps(payload)
1114 if not args.force or (args.name==None and args.filer==None):
1115 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1116 if len(r)>0 and r[0].lower()=="y":
1120 logger.debug("openmano request: %s", payload_req)
1121 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1122 logger.debug("openmano response: %s", mano_response.text )
1123 if args.verbose==None:
1127 return _print_verbose(mano_response, args.verbose)
1134 if __name__=="__main__":
1136 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1137 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1138 mano_port = os.getenv('OPENMANO_PORT',"9090")
1139 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1141 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1142 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1144 subparsers = main_parser.add_subparsers(help='commands')
1146 parent_parser = argparse.ArgumentParser(add_help=False)
1147 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1148 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1150 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1151 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1152 config_parser.set_defaults(func=config)
1154 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1155 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1156 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1157 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1158 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1159 vnf_create_parser.set_defaults(func=vnf_create)
1161 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1162 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1163 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1164 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1165 vnf_list_parser.set_defaults(func=vnf_list)
1167 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1168 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1169 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1170 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1171 vnf_delete_parser.set_defaults(func=vnf_delete)
1173 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1174 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1175 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1176 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1177 scenario_create_parser.set_defaults(func=scenario_create)
1179 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1180 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1181 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1182 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1183 scenario_list_parser.set_defaults(func=scenario_list)
1185 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1186 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1187 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1188 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1189 scenario_delete_parser.set_defaults(func=scenario_delete)
1191 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1192 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1193 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1194 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1195 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1196 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1197 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1199 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1200 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1201 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1202 scenario_deploy_parser.set_defaults(func=scenario_verify)
1204 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1205 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1206 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1207 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1208 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1209 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1210 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")
1211 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")
1212 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1213 instance_scenario_create_parser.set_defaults(func=instance_create)
1215 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1216 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1217 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1218 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1220 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)")
1221 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1222 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1223 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1224 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1226 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1227 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1228 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1229 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1230 help="action to send")
1231 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1232 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1233 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1234 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1236 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1237 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1238 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1240 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1241 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1242 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1243 tenant_create_parser.set_defaults(func=tenant_create)
1245 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1246 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1247 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1248 tenant_delete_parser.set_defaults(func=tenant_delete)
1250 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1251 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1252 tenant_list_parser.set_defaults(func=tenant_list)
1254 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1255 for item in item_list:
1256 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1257 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1258 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1259 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1260 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1262 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1263 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1264 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1265 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1266 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1267 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1268 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1269 datacenter_create_parser.set_defaults(func=datacenter_create)
1271 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1272 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1273 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1274 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1276 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1277 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1278 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1279 datacenter_list_parser.set_defaults(func=datacenter_list)
1281 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1282 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1283 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1284 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1285 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1286 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1287 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1289 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1290 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1291 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1292 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1295 action_dict={'net-update': 'retrieves external networks from datacenter',
1296 'net-edit': 'edits an external network',
1297 'net-delete': 'deletes an external network',
1298 'net-list': 'lists external networks from a datacenter'
1300 for item in action_dict:
1301 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1302 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1303 if item=='net-edit' or item=='net-delete':
1304 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1305 if item=='net-edit':
1306 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1307 if item!='net-list':
1308 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1309 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1312 action_dict={'netmap-upload': 'create network senario netmap base on the datacenter networks',
1313 'netmap-create': 'create a new network senario netmap',
1314 'netmap-edit': 'edit name of a network senario netmap',
1315 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1316 'netmap-list': 'list/show network scenario netmaps'
1318 for item in action_dict:
1319 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1320 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1321 #if item=='net-add':
1322 # datacenter_action_parser.add_argument("net", help="name of the network")
1323 if item=='netmap-delete':
1324 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1325 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1326 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1327 if item=='netmap-edit':
1328 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1329 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1330 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1331 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1332 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1333 if item=='netmap-list':
1334 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1335 if item=='netmap-create':
1336 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1337 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1338 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1339 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1340 if item=='netmap-upload':
1341 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1342 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1344 for item in ("network", "tenant"):
1346 commnad_name = 'vim-net'
1348 commnad_name = 'vim-'+item
1349 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1350 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1351 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1352 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1354 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1355 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1356 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1357 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1359 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1360 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1361 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1362 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1364 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1365 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1366 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>'")
1368 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1369 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1371 argcomplete.autocomplete(main_parser)
1374 args = main_parser.parse_args()
1376 level = logging.CRITICAL
1377 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1378 if "debug" in args and args.debug:
1379 level = logging.DEBUG
1380 logging.basicConfig(format=streamformat, level= level)
1381 logger = logging.getLogger('mano')
1382 logger.setLevel(level)
1383 result = args.func(args)
1386 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1387 except (requests.exceptions.ConnectionError):
1388 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1390 except (KeyboardInterrupt):
1391 print 'Exiting openmano'
1393 except (SystemExit, ArgumentParserError):
1395 except OpenmanoCLIError as e: