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.6-r500"
32 version_date="Sep 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 payload_req = json.dumps( {"datacenter": datacenter_dict })
896 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
897 logger.debug("openmano request: %s", payload_req)
898 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
899 logger.debug("openmano response: %s", mano_response.text )
900 result = _print_verbose(mano_response, args.verbose)
901 #provide addional information if error
902 if mano_response.status_code != 200:
903 content = mano_response.json()
904 if "already in use for 'name'" in content['error']['description'] and \
905 "to database vim_tenants table" in content['error']['description']:
906 print "Try to specify a different name with --vim-tenant-name"
909 def datacenter_detach(args):
913 tenant = _get_tenant()
914 datacenter = _get_datacenter(args.name, tenant)
915 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
916 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
917 mano_response = requests.delete(URLrequest, headers=headers_req)
918 logger.debug("openmano response: %s", mano_response.text )
919 content = mano_response.json()
920 #print json.dumps(content, indent=4)
921 result = 0 if mano_response.status_code==200 else mano_response.status_code
922 if mano_response.status_code == 200:
923 print content['result']
925 print content['error']['description']
928 def datacenter_create(args):
929 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
930 datacenter_dict={"name": args.name, "vim_url": args.url}
931 if args.description!=None:
932 datacenter_dict["description"] = args.description
934 datacenter_dict["type"] = args.type
936 datacenter_dict["vim_url_admin"] = args.url_admin
937 if args.config!=None:
938 datacenter_dict["config"] = _load_file_or_yaml(args.config)
939 payload_req = json.dumps( {"datacenter": datacenter_dict })
943 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
944 logger.debug("openmano request: %s", payload_req)
945 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
946 logger.debug("openmano response: %s", mano_response.text )
947 return _print_verbose(mano_response, args.verbose)
949 def datacenter_delete(args):
950 #print "datacenter-delete",args
951 todelete = _get_item_uuid("datacenters", args.name, "any")
953 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
954 if not (len(r)>0 and r[0].lower()=="y"):
956 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
957 mano_response = requests.delete(URLrequest)
958 logger.debug("openmano response: %s", mano_response.text )
959 result = 0 if mano_response.status_code==200 else mano_response.status_code
960 content = mano_response.json()
961 #print json.dumps(content, indent=4)
962 if mano_response.status_code == 200:
963 print content['result']
965 print content['error']['description']
968 def datacenter_list(args):
969 #print "datacenter-list",args
970 tenant='any' if args.all else _get_tenant()
973 toshow = _get_item_uuid("datacenters", args.name, tenant)
974 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
976 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
977 mano_response = requests.get(URLrequest)
978 logger.debug("openmano response: %s", mano_response.text )
979 if args.verbose==None:
983 return _print_verbose(mano_response, args.verbose)
985 def vim_action(args):
986 #print "datacenter-net-action",args
987 tenant = _get_tenant()
988 datacenter = _get_datacenter(args.datacenter, tenant)
989 if args.verbose==None:
991 if args.action=="list":
992 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
995 URLrequest += "/" + args.name
996 mano_response = requests.get(URLrequest)
997 logger.debug("openmano response: %s", mano_response.text )
998 return _print_verbose(mano_response, args.verbose)
999 elif args.action=="delete":
1000 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1001 mano_response = requests.delete(URLrequest)
1002 logger.debug("openmano response: %s", mano_response.text )
1003 result = 0 if mano_response.status_code==200 else mano_response.status_code
1004 content = mano_response.json()
1005 #print json.dumps(content, indent=4)
1006 if mano_response.status_code == 200:
1007 print content['result']
1009 print content['error']['description']
1011 elif args.action=="create":
1012 headers_req = {'content-type': 'application/yaml'}
1014 create_dict = _load_file_or_yaml(args.file)
1015 if args.item not in create_dict:
1016 create_dict = {args.item: create_dict}
1018 create_dict = {args.item:{}}
1020 create_dict[args.item]['name'] = args.name
1021 #if args.description:
1022 # create_dict[args.item]['description'] = args.description
1023 if args.item=="vim-net":
1025 create_dict[args.item]['bind_net'] = args.bind_net
1027 create_dict[args.item]['bind_type'] = args.bind_type
1029 create_dict[args.item]['shared'] = args.shared
1030 if "name" not in create_dict[args.item]:
1031 print "You must provide a name in the descriptor file or with the --name option"
1033 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1034 logger.debug("openmano request: %s", payload_req)
1035 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1036 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1037 logger.debug("openmano response: %s", mano_response.text )
1038 if args.verbose==None:
1040 return _print_verbose(mano_response, args.verbose)
1043 def datacenter_net_action(args):
1044 if args.action == "net-update":
1045 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1047 args.action = "netmap-delete"
1050 r = datacenter_netmap_action(args)
1053 args.action = "netmap-import"
1054 r = datacenter_netmap_action(args)
1057 if args.action == "net-edit":
1058 args.netmap = args.net
1060 elif args.action == "net-list":
1062 elif args.action == "net-delete":
1063 args.netmap = args.net
1066 args.action = "netmap" + args.action[3:]
1069 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1071 return datacenter_netmap_action(args)
1073 def datacenter_netmap_action(args):
1074 tenant = _get_tenant()
1075 datacenter = _get_datacenter(args.datacenter, tenant)
1076 #print "datacenter_netmap_action",args
1078 if args.verbose==None:
1080 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1081 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1083 if args.action=="netmap-list":
1085 URLrequest += "/" + args.netmap
1087 mano_response = requests.get(URLrequest)
1089 elif args.action=="netmap-delete":
1090 if args.netmap and args.all:
1091 print "you can not use a netmap name and the option --all at the same time"
1094 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1095 URLrequest += "/" + args.netmap
1097 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1099 print "you must specify a netmap name or the option --all"
1102 r = raw_input(force_text)
1103 if len(r)>0 and r[0].lower()=="y":
1107 mano_response = requests.delete(URLrequest, headers=headers_req)
1108 elif args.action=="netmap-import":
1110 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1111 if len(r)>0 and r[0].lower()=="y":
1115 URLrequest += "/upload"
1116 mano_response = requests.post(URLrequest, headers=headers_req)
1117 elif args.action=="netmap-edit" or args.action=="netmap-create":
1119 payload = _load_file_or_yaml(args.file)
1122 if "netmap" not in payload:
1123 payload = {"netmap": payload}
1125 payload["netmap"]["name"] = args.name
1127 payload["netmap"]["vim_id"] = args.vim_id
1128 if args.action=="netmap-create" and args.vim_name:
1129 payload["netmap"]["vim_name"] = args.vim_name
1130 payload_req = json.dumps(payload)
1131 logger.debug("openmano request: %s", payload_req)
1133 if args.action=="netmap-edit" and not args.force:
1134 if len(payload["netmap"]) == 0:
1135 print "You must supply some parameter to edit"
1137 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1138 if len(r)>0 and r[0].lower()=="y":
1142 URLrequest += "/" + args.netmap
1143 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1144 else: #netmap-create
1145 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1146 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1148 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1150 logger.debug("openmano response: %s", mano_response.text )
1151 return _print_verbose(mano_response, args.verbose)
1153 def element_edit(args):
1154 element = _get_item_uuid(args.element, args.name)
1155 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1156 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1157 payload=_load_file_or_yaml(args.file)
1158 if args.element[:-1] not in payload:
1159 payload = {args.element[:-1]: payload }
1160 payload_req = json.dumps(payload)
1163 if not args.force or (args.name==None and args.filer==None):
1164 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1165 if len(r)>0 and r[0].lower()=="y":
1169 logger.debug("openmano request: %s", payload_req)
1170 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1171 logger.debug("openmano response: %s", mano_response.text )
1172 if args.verbose==None:
1176 return _print_verbose(mano_response, args.verbose)
1183 if __name__=="__main__":
1185 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1186 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1187 mano_port = os.getenv('OPENMANO_PORT',"9090")
1188 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1190 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1191 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1193 subparsers = main_parser.add_subparsers(help='commands')
1195 parent_parser = argparse.ArgumentParser(add_help=False)
1196 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1197 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1199 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1200 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1201 config_parser.set_defaults(func=config)
1203 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1204 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1205 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1206 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1207 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1208 vnf_create_parser.set_defaults(func=vnf_create)
1210 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1211 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1212 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1213 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1214 vnf_list_parser.set_defaults(func=vnf_list)
1216 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1217 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1218 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1219 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1220 vnf_delete_parser.set_defaults(func=vnf_delete)
1222 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1223 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1224 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1225 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1226 scenario_create_parser.set_defaults(func=scenario_create)
1228 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1229 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1230 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1231 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1232 scenario_list_parser.set_defaults(func=scenario_list)
1234 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1235 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1236 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1237 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1238 scenario_delete_parser.set_defaults(func=scenario_delete)
1240 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1241 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1242 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1243 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1244 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1245 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1246 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1248 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1249 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1250 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1251 scenario_deploy_parser.set_defaults(func=scenario_verify)
1253 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1254 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1255 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1256 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1257 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1258 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1259 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")
1260 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")
1261 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")
1262 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")
1263 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1264 instance_scenario_create_parser.set_defaults(func=instance_create)
1266 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1267 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1268 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1269 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1271 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)")
1272 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1273 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1274 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1275 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1277 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1278 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1279 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1280 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1281 help="action to send")
1282 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1283 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1284 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1285 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1287 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1288 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1289 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1291 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1292 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1293 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1294 tenant_create_parser.set_defaults(func=tenant_create)
1296 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1297 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1298 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1299 tenant_delete_parser.set_defaults(func=tenant_delete)
1301 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1302 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1303 tenant_list_parser.set_defaults(func=tenant_list)
1305 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1306 for item in item_list:
1307 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1308 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1309 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1310 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1311 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1313 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1314 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1315 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1316 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1317 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1318 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1319 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1320 datacenter_create_parser.set_defaults(func=datacenter_create)
1322 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1323 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1324 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1325 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1327 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1328 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1329 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1330 datacenter_list_parser.set_defaults(func=datacenter_list)
1332 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1333 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1334 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1335 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1336 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1337 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1338 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1340 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1341 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1342 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1343 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1346 action_dict={'net-update': 'retrieves external networks from datacenter',
1347 'net-edit': 'edits an external network',
1348 'net-delete': 'deletes an external network',
1349 'net-list': 'lists external networks from a datacenter'
1351 for item in action_dict:
1352 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1353 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1354 if item=='net-edit' or item=='net-delete':
1355 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1356 if item=='net-edit':
1357 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1358 if item!='net-list':
1359 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1360 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1363 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1364 'netmap-create': 'create a new network senario netmap',
1365 'netmap-edit': 'edit name of a network senario netmap',
1366 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1367 'netmap-list': 'list/show network scenario netmaps'
1369 for item in action_dict:
1370 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1371 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1372 #if item=='net-add':
1373 # datacenter_action_parser.add_argument("net", help="name of the network")
1374 if item=='netmap-delete':
1375 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1376 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1377 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1378 if item=='netmap-edit':
1379 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1380 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1381 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1382 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1383 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1384 if item=='netmap-list':
1385 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1386 if item=='netmap-create':
1387 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1388 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1389 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1390 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1391 if item=='netmap-import':
1392 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1393 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1395 for item in ("network", "tenant"):
1397 commnad_name = 'vim-net'
1399 commnad_name = 'vim-'+item
1400 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1401 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1402 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1403 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1405 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1406 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1407 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1408 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1410 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1411 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1412 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1413 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1415 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1416 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1417 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>'")
1419 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1420 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1422 argcomplete.autocomplete(main_parser)
1425 args = main_parser.parse_args()
1427 level = logging.CRITICAL
1428 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1429 if "debug" in args and args.debug:
1430 level = logging.DEBUG
1431 logging.basicConfig(format=streamformat, level= level)
1432 logger = logging.getLogger('mano')
1433 logger.setLevel(level)
1434 result = args.func(args)
1437 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1438 except (requests.exceptions.ConnectionError):
1439 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1441 except (KeyboardInterrupt):
1442 print 'Exiting openmano'
1444 except (SystemExit, ArgumentParserError):
1446 except OpenmanoCLIError as e: