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.7-r511"
32 version_date="Oct 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
484 args.keypair_auto = None
485 return instance_create(args)
487 # #print "scenario-deploy",args
488 # headers_req = {'content-type': 'application/json'}
492 # actionCmd="reserve"
493 # action[actionCmd] = {}
494 # action[actionCmd]["instance_name"] = args.name
495 # if args.datacenter != None:
496 # action[actionCmd]["datacenter"] = args.datacenter
497 # elif mano_datacenter != None:
498 # action[actionCmd]["datacenter"] = mano_datacenter
500 # if args.description:
501 # action[actionCmd]["description"] = args.description
502 # payload_req = json.dumps(action, indent=4)
505 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
506 # logger.debug("openmano request: %s", payload_req)
507 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
508 # logger.debug("openmano response: %s", mano_response.text )
509 # if args.verbose==None:
512 # result = 0 if mano_response.status_code==200 else mano_response.status_code
513 # content = mano_response.json()
514 # #print json.dumps(content, indent=4)
515 # if args.verbose >= 3:
516 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
519 # if mano_response.status_code == 200:
520 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
521 # if args.verbose >=1:
522 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
523 # if args.verbose >=2:
524 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
527 # print "To check the status, run the following command:"
528 # print "openmano instance-scenario-list <instance_id>"
530 # print content['error']['description']
533 def scenario_verify(args):
534 #print "scenario-verify",args
535 headers_req = {'content-type': 'application/json'}
537 action["verify"] = {}
538 action["verify"]["instance_name"] = "scen-verify-return5"
539 payload_req = json.dumps(action, indent=4)
542 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
543 logger.debug("openmano request: %s", payload_req)
544 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
545 logger.debug("openmano response: %s", mano_response.text )
547 result = 0 if mano_response.status_code==200 else mano_response.status_code
548 content = mano_response.json()
549 #print json.dumps(content, indent=4)
550 if mano_response.status_code == 200:
551 print content['result']
553 print content['error']['description']
556 def instance_create(args):
557 tenant = _get_tenant()
558 headers_req = {'content-type': 'application/yaml'}
559 myInstance={"instance": {}, "schema_version": "0.1"}
561 instance_dict = _load_file_or_yaml(args.file)
562 if "instance" not in instance_dict:
563 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
565 myInstance = instance_dict
567 myInstance["instance"]['name'] = args.name
569 myInstance["instance"]['description'] = args.description
571 myInstance["instance"]['action'] = "reserve"
573 datacenter = myInstance["instance"].get("datacenter")
574 if args.datacenter != None:
575 datacenter = args.datacenter
576 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
578 scenario = myInstance["instance"].get("scenario")
579 if args.scenario != None:
580 scenario = args.scenario
582 print "you must provide an scenario in the file descriptor or with --scenario"
584 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
586 if "networks" not in myInstance["instance"]:
587 myInstance["instance"]["networks"] = {}
588 for net in args.netmap_use:
589 net_comma_list = net.split(",")
590 for net_comma in net_comma_list:
591 net_tuple = net_comma.split("=")
592 if len(net_tuple) != 2:
593 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
595 net_scenario = net_tuple[0].strip()
596 net_datacenter = net_tuple[1].strip()
597 if net_scenario not in myInstance["instance"]["networks"]:
598 myInstance["instance"]["networks"][net_scenario] = {}
599 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
600 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
601 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
602 if args.netmap_create:
603 if "networks" not in myInstance["instance"]:
604 myInstance["instance"]["networks"] = {}
605 for net in args.netmap_create:
606 net_comma_list = net.split(",")
607 for net_comma in net_comma_list:
608 net_tuple = net_comma.split("=")
609 if len(net_tuple) == 1:
610 net_scenario = net_tuple[0].strip()
611 net_datacenter = None
612 elif len(net_tuple) == 2:
613 net_scenario = net_tuple[0].strip()
614 net_datacenter = net_tuple[1].strip()
616 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
618 if net_scenario not in myInstance["instance"]["networks"]:
619 myInstance["instance"]["networks"][net_scenario] = {}
620 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
621 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
622 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
624 if "cloud-config" not in myInstance["instance"]:
625 myInstance["instance"]["cloud-config"] = {}
626 cloud_config = myInstance["instance"]["cloud-config"]
627 for key in args.keypair:
628 index = key.find(":")
630 if "key-pairs" not in cloud_config:
631 cloud_config["key-pairs"] = []
632 cloud_config["key-pairs"].append(key)
636 key_list = key_.split(",")
637 if "users" not in cloud_config:
638 cloud_config["users"] = []
639 cloud_config["users"].append({"name": user, "key-pairs": key_list })
640 if args.keypair_auto:
643 home = os.getenv("HOME")
644 user = os.getenv("USER")
645 files = os.listdir(home+'/.ssh')
647 if file[-4:] == ".pub":
648 with open(home+'/.ssh/'+file, 'r') as f:
649 keys.append(f.read())
651 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
653 except Exception as e:
654 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
657 if "cloud-config" not in myInstance["instance"]:
658 myInstance["instance"]["cloud-config"] = {}
659 cloud_config = myInstance["instance"]["cloud-config"]
660 if "key-pairs" not in cloud_config:
661 cloud_config["key-pairs"] = []
663 if "users" not in cloud_config:
664 cloud_config["users"] = []
665 cloud_config["users"].append({"name": user, "key-pairs": keys })
667 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
668 logger.debug("openmano request: %s", payload_req)
669 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
670 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
671 logger.debug("openmano response: %s", mano_response.text )
672 if args.verbose==None:
675 result = 0 if mano_response.status_code==200 else mano_response.status_code
676 content = mano_response.json()
677 #print json.dumps(content, indent=4)
678 if args.verbose >= 3:
679 print yaml.safe_dump(content, indent=4, default_flow_style=False)
682 if mano_response.status_code == 200:
683 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
685 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
687 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
690 print content['error']['description']
693 def instance_scenario_list(args):
694 #print "instance-scenario-list",args
698 tenant = _get_tenant()
700 toshow = _get_item_uuid("instances", args.name, tenant)
701 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
703 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
704 mano_response = requests.get(URLrequest)
705 logger.debug("openmano response: %s", mano_response.text )
706 content = mano_response.json()
707 #print json.dumps(content, indent=4)
708 if args.verbose==None:
711 result = 0 if mano_response.status_code==200 else mano_response.status_code
712 if mano_response.status_code == 200:
714 if args.verbose >= 3:
715 print yaml.safe_dump(content, indent=4, default_flow_style=False)
717 if len(content['instances']) == 0:
718 print "No scenario instances were found."
720 for instance in content['instances']:
721 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
723 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
726 print "Description: %s" %instance['description']
729 print yaml.safe_dump(content, indent=4, default_flow_style=False)
732 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
733 print "Description: %s" %instance['description']
734 print "Template scenario id: %s" %instance['scenario_id']
735 print "Template scenario name: %s" %instance['scenario_name']
736 print "---------------------------------------"
737 print "VNF instances: %d" %len(instance['vnfs'])
738 for vnf in instance['vnfs']:
739 #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))
740 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
741 if len(instance['nets'])>0:
742 print "---------------------------------------"
743 print "Internal nets:"
744 for net in instance['nets']:
746 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
747 print "---------------------------------------"
748 print "External nets:"
749 for net in instance['nets']:
750 if not net['created']:
751 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
752 print "---------------------------------------"
753 print "VM instances:"
754 for vnf in instance['vnfs']:
755 for vm in vnf['vms']:
756 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'])
758 print content['error']['description']
760 print yaml.safe_dump(content, indent=4, default_flow_style=False)
763 def instance_scenario_status(args):
764 print "instance-scenario-status"
767 def instance_scenario_delete(args):
771 tenant = _get_tenant()
772 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
773 #print "instance-scenario-delete",args
775 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
776 if not (len(r)>0 and r[0].lower()=="y"):
778 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
779 mano_response = requests.delete(URLrequest)
780 logger.debug("openmano response: %s", mano_response.text )
781 result = 0 if mano_response.status_code==200 else mano_response.status_code
782 content = mano_response.json()
783 #print json.dumps(content, indent=4)
784 if mano_response.status_code == 200:
785 print content['result']
787 print content['error']['description']
790 def instance_scenario_action(args):
791 #print "instance-scenario-action", args
792 tenant = _get_tenant()
793 toact = _get_item_uuid("instances", args.name, tenant=tenant)
795 action[ args.action ] = args.param
797 action["vnfs"] = args.vnf
799 action["vms"] = args.vm
801 headers_req = {'content-type': 'application/json'}
802 payload_req = json.dumps(action, indent=4)
803 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
804 logger.debug("openmano request: %s", payload_req)
805 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
806 logger.debug("openmano response: %s", mano_response.text )
807 result = 0 if mano_response.status_code==200 else mano_response.status_code
808 content = mano_response.json()
809 #print json.dumps(content, indent=4)
810 if mano_response.status_code == 200:
812 print yaml.safe_dump(content, indent=4, default_flow_style=False)
814 for uuid,c in content.iteritems():
815 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
817 print content['error']['description']
821 def instance_vnf_list(args):
822 print "instance-vnf-list"
825 def instance_vnf_status(args):
826 print "instance-vnf-status"
829 def tenant_create(args):
830 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
831 tenant_dict={"name": args.name}
832 if args.description!=None:
833 tenant_dict["description"] = args.description
834 payload_req = json.dumps( {"tenant": tenant_dict })
838 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
839 logger.debug("openmano request: %s", payload_req)
840 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
841 logger.debug("openmano response: %s", mano_response.text )
842 return _print_verbose(mano_response, args.verbose)
844 def tenant_list(args):
845 #print "tenant-list",args
847 toshow = _get_item_uuid("tenants", args.name)
848 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
850 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
851 mano_response = requests.get(URLrequest)
852 logger.debug("openmano response: %s", mano_response.text )
853 if args.verbose==None:
857 return _print_verbose(mano_response, args.verbose)
859 def tenant_delete(args):
860 #print "tenant-delete",args
861 todelete = _get_item_uuid("tenants", args.name)
863 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
864 if not (len(r)>0 and r[0].lower()=="y"):
866 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
867 mano_response = requests.delete(URLrequest)
868 logger.debug("openmano response: %s", mano_response.text )
869 result = 0 if mano_response.status_code==200 else mano_response.status_code
870 content = mano_response.json()
871 #print json.dumps(content, indent=4)
872 if mano_response.status_code == 200:
873 print content['result']
875 print content['error']['description']
878 def datacenter_attach(args):
879 tenant = _get_tenant()
880 datacenter = _get_datacenter(args.name)
881 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
884 if args.vim_tenant_id != None:
885 datacenter_dict['vim_tenant'] = args.vim_tenant_id
886 if args.vim_tenant_name != None:
887 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
888 if args.user != None:
889 datacenter_dict['vim_username'] = args.user
890 if args.password != None:
891 datacenter_dict['vim_password'] = args.password
892 if args.config!=None:
893 datacenter_dict["config"] = _load_file_or_yaml(args.config)
894 payload_req = json.dumps( {"datacenter": datacenter_dict })
898 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
899 logger.debug("openmano request: %s", payload_req)
900 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
901 logger.debug("openmano response: %s", mano_response.text )
902 result = _print_verbose(mano_response, args.verbose)
903 #provide addional information if error
904 if mano_response.status_code != 200:
905 content = mano_response.json()
906 if "already in use for 'name'" in content['error']['description'] and \
907 "to database vim_tenants table" in content['error']['description']:
908 print "Try to specify a different name with --vim-tenant-name"
911 def datacenter_detach(args):
915 tenant = _get_tenant()
916 datacenter = _get_datacenter(args.name, tenant)
917 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
918 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
919 mano_response = requests.delete(URLrequest, headers=headers_req)
920 logger.debug("openmano response: %s", mano_response.text )
921 content = mano_response.json()
922 #print json.dumps(content, indent=4)
923 result = 0 if mano_response.status_code==200 else mano_response.status_code
924 if mano_response.status_code == 200:
925 print content['result']
927 print content['error']['description']
930 def datacenter_create(args):
931 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
932 datacenter_dict={"name": args.name, "vim_url": args.url}
933 if args.description!=None:
934 datacenter_dict["description"] = args.description
936 datacenter_dict["type"] = args.type
938 datacenter_dict["vim_url_admin"] = args.url_admin
939 if args.config!=None:
940 datacenter_dict["config"] = _load_file_or_yaml(args.config)
941 payload_req = json.dumps( {"datacenter": datacenter_dict })
945 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
946 logger.debug("openmano request: %s", payload_req)
947 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
948 logger.debug("openmano response: %s", mano_response.text )
949 return _print_verbose(mano_response, args.verbose)
951 def datacenter_delete(args):
952 #print "datacenter-delete",args
953 todelete = _get_item_uuid("datacenters", args.name, "any")
955 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
956 if not (len(r)>0 and r[0].lower()=="y"):
958 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
959 mano_response = requests.delete(URLrequest)
960 logger.debug("openmano response: %s", mano_response.text )
961 result = 0 if mano_response.status_code==200 else mano_response.status_code
962 content = mano_response.json()
963 #print json.dumps(content, indent=4)
964 if mano_response.status_code == 200:
965 print content['result']
967 print content['error']['description']
970 def datacenter_list(args):
971 #print "datacenter-list",args
972 tenant='any' if args.all else _get_tenant()
975 toshow = _get_item_uuid("datacenters", args.name, tenant)
976 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
978 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
979 mano_response = requests.get(URLrequest)
980 logger.debug("openmano response: %s", mano_response.text )
981 if args.verbose==None:
985 return _print_verbose(mano_response, args.verbose)
987 def vim_action(args):
988 #print "datacenter-net-action",args
989 tenant = _get_tenant()
990 datacenter = _get_datacenter(args.datacenter, tenant)
991 if args.verbose==None:
993 if args.action=="list":
994 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
997 URLrequest += "/" + args.name
998 mano_response = requests.get(URLrequest)
999 logger.debug("openmano response: %s", mano_response.text )
1000 return _print_verbose(mano_response, args.verbose)
1001 elif args.action=="delete":
1002 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1003 mano_response = requests.delete(URLrequest)
1004 logger.debug("openmano response: %s", mano_response.text )
1005 result = 0 if mano_response.status_code==200 else mano_response.status_code
1006 content = mano_response.json()
1007 #print json.dumps(content, indent=4)
1008 if mano_response.status_code == 200:
1009 print content['result']
1011 print content['error']['description']
1013 elif args.action=="create":
1014 headers_req = {'content-type': 'application/yaml'}
1016 create_dict = _load_file_or_yaml(args.file)
1017 if args.item not in create_dict:
1018 create_dict = {args.item: create_dict}
1020 create_dict = {args.item:{}}
1022 create_dict[args.item]['name'] = args.name
1023 #if args.description:
1024 # create_dict[args.item]['description'] = args.description
1025 if args.item=="vim-net":
1027 create_dict[args.item]['bind_net'] = args.bind_net
1029 create_dict[args.item]['bind_type'] = args.bind_type
1031 create_dict[args.item]['shared'] = args.shared
1032 if "name" not in create_dict[args.item]:
1033 print "You must provide a name in the descriptor file or with the --name option"
1035 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1036 logger.debug("openmano request: %s", payload_req)
1037 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1038 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1039 logger.debug("openmano response: %s", mano_response.text )
1040 if args.verbose==None:
1042 return _print_verbose(mano_response, args.verbose)
1045 def datacenter_net_action(args):
1046 if args.action == "net-update":
1047 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1049 args.action = "netmap-delete"
1052 r = datacenter_netmap_action(args)
1055 args.action = "netmap-import"
1056 r = datacenter_netmap_action(args)
1059 if args.action == "net-edit":
1060 args.netmap = args.net
1062 elif args.action == "net-list":
1064 elif args.action == "net-delete":
1065 args.netmap = args.net
1068 args.action = "netmap" + args.action[3:]
1071 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1073 return datacenter_netmap_action(args)
1075 def datacenter_netmap_action(args):
1076 tenant = _get_tenant()
1077 datacenter = _get_datacenter(args.datacenter, tenant)
1078 #print "datacenter_netmap_action",args
1080 if args.verbose==None:
1082 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1083 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1085 if args.action=="netmap-list":
1087 URLrequest += "/" + args.netmap
1089 mano_response = requests.get(URLrequest)
1091 elif args.action=="netmap-delete":
1092 if args.netmap and args.all:
1093 print "you can not use a netmap name and the option --all at the same time"
1096 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1097 URLrequest += "/" + args.netmap
1099 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1101 print "you must specify a netmap name or the option --all"
1104 r = raw_input(force_text)
1105 if len(r)>0 and r[0].lower()=="y":
1109 mano_response = requests.delete(URLrequest, headers=headers_req)
1110 elif args.action=="netmap-import":
1112 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1113 if len(r)>0 and r[0].lower()=="y":
1117 URLrequest += "/upload"
1118 mano_response = requests.post(URLrequest, headers=headers_req)
1119 elif args.action=="netmap-edit" or args.action=="netmap-create":
1121 payload = _load_file_or_yaml(args.file)
1124 if "netmap" not in payload:
1125 payload = {"netmap": payload}
1127 payload["netmap"]["name"] = args.name
1129 payload["netmap"]["vim_id"] = args.vim_id
1130 if args.action=="netmap-create" and args.vim_name:
1131 payload["netmap"]["vim_name"] = args.vim_name
1132 payload_req = json.dumps(payload)
1133 logger.debug("openmano request: %s", payload_req)
1135 if args.action=="netmap-edit" and not args.force:
1136 if len(payload["netmap"]) == 0:
1137 print "You must supply some parameter to edit"
1139 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1140 if len(r)>0 and r[0].lower()=="y":
1144 URLrequest += "/" + args.netmap
1145 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1146 else: #netmap-create
1147 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1148 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1150 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1152 logger.debug("openmano response: %s", mano_response.text )
1153 return _print_verbose(mano_response, args.verbose)
1155 def element_edit(args):
1156 element = _get_item_uuid(args.element, args.name)
1157 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1158 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1159 payload=_load_file_or_yaml(args.file)
1160 if args.element[:-1] not in payload:
1161 payload = {args.element[:-1]: payload }
1162 payload_req = json.dumps(payload)
1165 if not args.force or (args.name==None and args.filer==None):
1166 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1167 if len(r)>0 and r[0].lower()=="y":
1171 logger.debug("openmano request: %s", payload_req)
1172 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1173 logger.debug("openmano response: %s", mano_response.text )
1174 if args.verbose==None:
1178 return _print_verbose(mano_response, args.verbose)
1185 if __name__=="__main__":
1187 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1188 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1189 mano_port = os.getenv('OPENMANO_PORT',"9090")
1190 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1192 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1193 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1195 subparsers = main_parser.add_subparsers(help='commands')
1197 parent_parser = argparse.ArgumentParser(add_help=False)
1198 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1199 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1201 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1202 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1203 config_parser.set_defaults(func=config)
1205 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1206 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1207 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1208 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1209 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1210 vnf_create_parser.set_defaults(func=vnf_create)
1212 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1213 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1214 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1215 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1216 vnf_list_parser.set_defaults(func=vnf_list)
1218 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1219 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1220 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1221 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1222 vnf_delete_parser.set_defaults(func=vnf_delete)
1224 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1225 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1226 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1227 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1228 scenario_create_parser.set_defaults(func=scenario_create)
1230 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1231 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1232 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1233 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1234 scenario_list_parser.set_defaults(func=scenario_list)
1236 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1237 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1238 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1239 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1240 scenario_delete_parser.set_defaults(func=scenario_delete)
1242 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1243 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1244 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1245 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1246 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1247 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1248 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1250 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1251 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1252 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1253 scenario_deploy_parser.set_defaults(func=scenario_verify)
1255 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1256 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1257 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1258 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1259 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1260 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1261 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")
1262 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")
1263 instance_scenario_create_parser.add_argument("--keypair", action="append", type=str, dest="keypair", help="public key for ssh access. Format '[user:]key1[,key2...]'. Can be used several times")
1264 instance_scenario_create_parser.add_argument("--keypair-auto", action="store_true", dest="keypair_auto", help="Inject the user ssh-keys found at $HOME/.ssh directory")
1265 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1266 instance_scenario_create_parser.set_defaults(func=instance_create)
1268 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1269 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1270 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1271 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1273 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)")
1274 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1275 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1276 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1277 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1279 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1280 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1281 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1282 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1283 help="action to send")
1284 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1285 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1286 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1287 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1289 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1290 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1291 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1293 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1294 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1295 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1296 tenant_create_parser.set_defaults(func=tenant_create)
1298 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1299 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1300 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1301 tenant_delete_parser.set_defaults(func=tenant_delete)
1303 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1304 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1305 tenant_list_parser.set_defaults(func=tenant_list)
1307 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1308 for item in item_list:
1309 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1310 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1311 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1312 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1313 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1315 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1316 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1317 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1318 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1319 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1320 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1321 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1322 datacenter_create_parser.set_defaults(func=datacenter_create)
1324 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1325 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1326 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1327 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1329 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1330 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1331 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1332 datacenter_list_parser.set_defaults(func=datacenter_list)
1334 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1335 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1336 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1337 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1338 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1339 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1340 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1341 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1343 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1344 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1345 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1346 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1349 action_dict={'net-update': 'retrieves external networks from datacenter',
1350 'net-edit': 'edits an external network',
1351 'net-delete': 'deletes an external network',
1352 'net-list': 'lists external networks from a datacenter'
1354 for item in action_dict:
1355 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1356 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1357 if item=='net-edit' or item=='net-delete':
1358 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1359 if item=='net-edit':
1360 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1361 if item!='net-list':
1362 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1363 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1366 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1367 'netmap-create': 'create a new network senario netmap',
1368 'netmap-edit': 'edit name of a network senario netmap',
1369 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1370 'netmap-list': 'list/show network scenario netmaps'
1372 for item in action_dict:
1373 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1374 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1375 #if item=='net-add':
1376 # datacenter_action_parser.add_argument("net", help="name of the network")
1377 if item=='netmap-delete':
1378 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1379 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1380 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1381 if item=='netmap-edit':
1382 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1383 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1384 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1385 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1386 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1387 if item=='netmap-list':
1388 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1389 if item=='netmap-create':
1390 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1391 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1392 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1393 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1394 if item=='netmap-import':
1395 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1396 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1398 for item in ("network", "tenant"):
1400 commnad_name = 'vim-net'
1402 commnad_name = 'vim-'+item
1403 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1404 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1405 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1406 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1408 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1409 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1410 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1411 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1413 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1414 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1415 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1416 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1418 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1419 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1420 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>'")
1422 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1423 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1425 argcomplete.autocomplete(main_parser)
1428 args = main_parser.parse_args()
1430 level = logging.CRITICAL
1431 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1432 if "debug" in args and args.debug:
1433 level = logging.DEBUG
1434 logging.basicConfig(format=streamformat, level= level)
1435 logger = logging.getLogger('mano')
1436 logger.setLevel(level)
1437 result = args.func(args)
1440 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1441 except (requests.exceptions.ConnectionError):
1442 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1444 except (KeyboardInterrupt):
1445 print 'Exiting openmano'
1447 except (SystemExit, ArgumentParserError):
1449 except OpenmanoCLIError as e: