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.8-r512"
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 or args.image_name or args.image_checksum:
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_
269 for image_name_ in args.image_name.split(","):
270 myvnf['vnf']['VNFC'][index]['image name']=image_name_
272 if args.image_checksum:
274 for image_checksum_ in args.image_checksum.split(","):
275 myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
277 except (KeyError, TypeError), e:
278 if str(e)=='vnf': error_pos= "missing field 'vnf'"
279 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
280 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
281 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
282 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
283 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
284 elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
285 elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
286 else: error_pos="wrong format"
287 print "Wrong VNF descriptor: " + error_pos
289 payload_req = json.dumps(myvnf)
293 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
294 logger.debug("openmano request: %s", payload_req)
295 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
296 logger.debug("openmano response: %s", mano_response.text )
298 return _print_verbose(mano_response, args.verbose)
301 #print "vnf-list",args
305 tenant = _get_tenant()
307 toshow = _get_item_uuid("vnfs", args.name, tenant)
308 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
310 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
311 mano_response = requests.get(URLrequest)
312 logger.debug("openmano response: %s", mano_response.text )
313 content = mano_response.json()
314 #print json.dumps(content, indent=4)
315 if args.verbose==None:
317 result = 0 if mano_response.status_code==200 else mano_response.status_code
318 if mano_response.status_code == 200:
320 if args.verbose >= 3:
321 print yaml.safe_dump(content, indent=4, default_flow_style=False)
323 if len(content['vnfs']) == 0:
324 print "No VNFs were found."
325 return 404 #HTTP_Not_Found
326 for vnf in content['vnfs']:
327 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
329 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
332 print " Description: %s" %vnf['description']
333 print " VNF descriptor file: %s" %vnf['path']
336 print yaml.safe_dump(content, indent=4, default_flow_style=False)
339 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
340 print " Description: %s" %vnf['description']
341 #print " VNF descriptor file: %s" %vnf['path']
343 for vm in vnf['VNFC']:
344 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
345 print " %s %s" %(vm['name'].ljust(20), vm['description'])
346 if len(vnf['nets'])>0:
347 print " Internal nets:"
348 for net in vnf['nets']:
349 print " %s %s" %(net['name'].ljust(20), net['description'])
350 if len(vnf['external-connections'])>0:
351 print " External interfaces:"
352 for interface in vnf['external-connections']:
353 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
354 interface['vpci'].ljust(14))
356 print content['error']['description']
358 print yaml.safe_dump(content, indent=4, default_flow_style=False)
361 def vnf_delete(args):
362 #print "vnf-delete",args
366 tenant = _get_tenant()
367 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
369 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
370 if not (len(r)>0 and r[0].lower()=="y"):
372 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
373 mano_response = requests.delete(URLrequest)
374 logger.debug("openmano response: %s", mano_response.text )
375 result = 0 if mano_response.status_code==200 else mano_response.status_code
376 content = mano_response.json()
377 #print json.dumps(content, indent=4)
378 if mano_response.status_code == 200:
379 print content['result']
381 print content['error']['description']
384 def scenario_create(args):
385 #print "scenario-create",args
386 tenant = _get_tenant()
387 headers_req = {'content-type': 'application/yaml'}
388 myscenario = _load_file_or_yaml(args.file)
391 myscenario['name'] = args.name
393 myscenario['description'] = args.description
394 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
398 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
399 logger.debug("openmano request: %s", payload_req)
400 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
401 logger.debug("openmano response: %s", mano_response.text )
402 return _print_verbose(mano_response, args.verbose)
404 def scenario_list(args):
405 #print "scenario-list",args
409 tenant = _get_tenant()
411 toshow = _get_item_uuid("scenarios", args.name, tenant)
412 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
414 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
415 mano_response = requests.get(URLrequest)
416 logger.debug("openmano response: %s", mano_response.text )
417 content = mano_response.json()
418 #print json.dumps(content, indent=4)
419 if args.verbose==None:
422 result = 0 if mano_response.status_code==200 else mano_response.status_code
423 if mano_response.status_code == 200:
425 if args.verbose >= 3:
426 print yaml.safe_dump(content, indent=4, default_flow_style=False)
428 if len(content['scenarios']) == 0:
429 print "No scenarios were found."
430 return 404 #HTTP_Not_Found
431 for scenario in content['scenarios']:
432 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
434 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
437 print " Description: %s" %scenario['description']
440 print yaml.safe_dump(content, indent=4, default_flow_style=False)
442 scenario = content['scenario']
443 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
445 print " Description: %s" %scenario['description']
447 for vnf in scenario['vnfs']:
448 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
449 if len(scenario['nets'])>0:
450 print " Internal nets:"
451 for net in scenario['nets']:
452 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
453 net['description'] = '-'
454 if not net['external']:
455 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
456 print " External nets:"
457 for net in scenario['nets']:
459 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
461 print content['error']['description']
463 print yaml.safe_dump(content, indent=4, default_flow_style=False)
466 def scenario_delete(args):
467 #print "scenario-delete",args
471 tenant = _get_tenant()
472 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
474 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
475 if not (len(r)>0 and r[0].lower()=="y"):
477 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
478 mano_response = requests.delete(URLrequest)
479 logger.debug("openmano response: %s", mano_response.text )
480 result = 0 if mano_response.status_code==200 else mano_response.status_code
481 content = mano_response.json()
482 #print json.dumps(content, indent=4)
483 if mano_response.status_code == 200:
484 print content['result']
486 print content['error']['description']
489 def scenario_deploy(args):
490 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
493 args.netmap_use = None
494 args.netmap_create = None
496 args.keypair_auto = None
497 return instance_create(args)
499 # #print "scenario-deploy",args
500 # headers_req = {'content-type': 'application/json'}
504 # actionCmd="reserve"
505 # action[actionCmd] = {}
506 # action[actionCmd]["instance_name"] = args.name
507 # if args.datacenter != None:
508 # action[actionCmd]["datacenter"] = args.datacenter
509 # elif mano_datacenter != None:
510 # action[actionCmd]["datacenter"] = mano_datacenter
512 # if args.description:
513 # action[actionCmd]["description"] = args.description
514 # payload_req = json.dumps(action, indent=4)
517 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
518 # logger.debug("openmano request: %s", payload_req)
519 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
520 # logger.debug("openmano response: %s", mano_response.text )
521 # if args.verbose==None:
524 # result = 0 if mano_response.status_code==200 else mano_response.status_code
525 # content = mano_response.json()
526 # #print json.dumps(content, indent=4)
527 # if args.verbose >= 3:
528 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
531 # if mano_response.status_code == 200:
532 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
533 # if args.verbose >=1:
534 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
535 # if args.verbose >=2:
536 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
539 # print "To check the status, run the following command:"
540 # print "openmano instance-scenario-list <instance_id>"
542 # print content['error']['description']
545 def scenario_verify(args):
546 #print "scenario-verify",args
547 headers_req = {'content-type': 'application/json'}
549 action["verify"] = {}
550 action["verify"]["instance_name"] = "scen-verify-return5"
551 payload_req = json.dumps(action, indent=4)
554 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
555 logger.debug("openmano request: %s", payload_req)
556 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
557 logger.debug("openmano response: %s", mano_response.text )
559 result = 0 if mano_response.status_code==200 else mano_response.status_code
560 content = mano_response.json()
561 #print json.dumps(content, indent=4)
562 if mano_response.status_code == 200:
563 print content['result']
565 print content['error']['description']
568 def instance_create(args):
569 tenant = _get_tenant()
570 headers_req = {'content-type': 'application/yaml'}
571 myInstance={"instance": {}, "schema_version": "0.1"}
573 instance_dict = _load_file_or_yaml(args.file)
574 if "instance" not in instance_dict:
575 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
577 myInstance = instance_dict
579 myInstance["instance"]['name'] = args.name
581 myInstance["instance"]['description'] = args.description
583 myInstance["instance"]['action'] = "reserve"
585 datacenter = myInstance["instance"].get("datacenter")
586 if args.datacenter != None:
587 datacenter = args.datacenter
588 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
590 scenario = myInstance["instance"].get("scenario")
591 if args.scenario != None:
592 scenario = args.scenario
594 print "you must provide an scenario in the file descriptor or with --scenario"
596 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
598 if "networks" not in myInstance["instance"]:
599 myInstance["instance"]["networks"] = {}
600 for net in args.netmap_use:
601 net_comma_list = net.split(",")
602 for net_comma in net_comma_list:
603 net_tuple = net_comma.split("=")
604 if len(net_tuple) != 2:
605 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
607 net_scenario = net_tuple[0].strip()
608 net_datacenter = net_tuple[1].strip()
609 if net_scenario not in myInstance["instance"]["networks"]:
610 myInstance["instance"]["networks"][net_scenario] = {}
611 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
612 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
613 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
614 if args.netmap_create:
615 if "networks" not in myInstance["instance"]:
616 myInstance["instance"]["networks"] = {}
617 for net in args.netmap_create:
618 net_comma_list = net.split(",")
619 for net_comma in net_comma_list:
620 net_tuple = net_comma.split("=")
621 if len(net_tuple) == 1:
622 net_scenario = net_tuple[0].strip()
623 net_datacenter = None
624 elif len(net_tuple) == 2:
625 net_scenario = net_tuple[0].strip()
626 net_datacenter = net_tuple[1].strip()
628 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
630 if net_scenario not in myInstance["instance"]["networks"]:
631 myInstance["instance"]["networks"][net_scenario] = {}
632 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
633 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
634 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
636 if "cloud-config" not in myInstance["instance"]:
637 myInstance["instance"]["cloud-config"] = {}
638 cloud_config = myInstance["instance"]["cloud-config"]
639 for key in args.keypair:
640 index = key.find(":")
642 if "key-pairs" not in cloud_config:
643 cloud_config["key-pairs"] = []
644 cloud_config["key-pairs"].append(key)
648 key_list = key_.split(",")
649 if "users" not in cloud_config:
650 cloud_config["users"] = []
651 cloud_config["users"].append({"name": user, "key-pairs": key_list })
652 if args.keypair_auto:
655 home = os.getenv("HOME")
656 user = os.getenv("USER")
657 files = os.listdir(home+'/.ssh')
659 if file[-4:] == ".pub":
660 with open(home+'/.ssh/'+file, 'r') as f:
661 keys.append(f.read())
663 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
665 except Exception as e:
666 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
669 if "cloud-config" not in myInstance["instance"]:
670 myInstance["instance"]["cloud-config"] = {}
671 cloud_config = myInstance["instance"]["cloud-config"]
672 if "key-pairs" not in cloud_config:
673 cloud_config["key-pairs"] = []
675 if "users" not in cloud_config:
676 cloud_config["users"] = []
677 cloud_config["users"].append({"name": user, "key-pairs": keys })
679 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
680 logger.debug("openmano request: %s", payload_req)
681 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
682 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
683 logger.debug("openmano response: %s", mano_response.text )
684 if args.verbose==None:
687 result = 0 if mano_response.status_code==200 else mano_response.status_code
688 content = mano_response.json()
689 #print json.dumps(content, indent=4)
690 if args.verbose >= 3:
691 print yaml.safe_dump(content, indent=4, default_flow_style=False)
694 if mano_response.status_code == 200:
695 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
697 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
699 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
702 print content['error']['description']
705 def instance_scenario_list(args):
706 #print "instance-scenario-list",args
710 tenant = _get_tenant()
712 toshow = _get_item_uuid("instances", args.name, tenant)
713 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
715 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
716 mano_response = requests.get(URLrequest)
717 logger.debug("openmano response: %s", mano_response.text )
718 content = mano_response.json()
719 #print json.dumps(content, indent=4)
720 if args.verbose==None:
723 result = 0 if mano_response.status_code==200 else mano_response.status_code
724 if mano_response.status_code == 200:
726 if args.verbose >= 3:
727 print yaml.safe_dump(content, indent=4, default_flow_style=False)
729 if len(content['instances']) == 0:
730 print "No scenario instances were found."
732 for instance in content['instances']:
733 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
735 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
738 print "Description: %s" %instance['description']
741 print yaml.safe_dump(content, indent=4, default_flow_style=False)
744 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
745 print "Description: %s" %instance['description']
746 print "Template scenario id: %s" %instance['scenario_id']
747 print "Template scenario name: %s" %instance['scenario_name']
748 print "---------------------------------------"
749 print "VNF instances: %d" %len(instance['vnfs'])
750 for vnf in instance['vnfs']:
751 #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))
752 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
753 if len(instance['nets'])>0:
754 print "---------------------------------------"
755 print "Internal nets:"
756 for net in instance['nets']:
758 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
759 print "---------------------------------------"
760 print "External nets:"
761 for net in instance['nets']:
762 if not net['created']:
763 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
764 print "---------------------------------------"
765 print "VM instances:"
766 for vnf in instance['vnfs']:
767 for vm in vnf['vms']:
768 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'])
770 print content['error']['description']
772 print yaml.safe_dump(content, indent=4, default_flow_style=False)
775 def instance_scenario_status(args):
776 print "instance-scenario-status"
779 def instance_scenario_delete(args):
783 tenant = _get_tenant()
784 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
785 #print "instance-scenario-delete",args
787 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
788 if not (len(r)>0 and r[0].lower()=="y"):
790 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
791 mano_response = requests.delete(URLrequest)
792 logger.debug("openmano response: %s", mano_response.text )
793 result = 0 if mano_response.status_code==200 else mano_response.status_code
794 content = mano_response.json()
795 #print json.dumps(content, indent=4)
796 if mano_response.status_code == 200:
797 print content['result']
799 print content['error']['description']
802 def instance_scenario_action(args):
803 #print "instance-scenario-action", args
804 tenant = _get_tenant()
805 toact = _get_item_uuid("instances", args.name, tenant=tenant)
807 action[ args.action ] = args.param
809 action["vnfs"] = args.vnf
811 action["vms"] = args.vm
813 headers_req = {'content-type': 'application/json'}
814 payload_req = json.dumps(action, indent=4)
815 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
816 logger.debug("openmano request: %s", payload_req)
817 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
818 logger.debug("openmano response: %s", mano_response.text )
819 result = 0 if mano_response.status_code==200 else mano_response.status_code
820 content = mano_response.json()
821 #print json.dumps(content, indent=4)
822 if mano_response.status_code == 200:
824 print yaml.safe_dump(content, indent=4, default_flow_style=False)
826 for uuid,c in content.iteritems():
827 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
829 print content['error']['description']
833 def instance_vnf_list(args):
834 print "instance-vnf-list"
837 def instance_vnf_status(args):
838 print "instance-vnf-status"
841 def tenant_create(args):
842 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
843 tenant_dict={"name": args.name}
844 if args.description!=None:
845 tenant_dict["description"] = args.description
846 payload_req = json.dumps( {"tenant": tenant_dict })
850 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
851 logger.debug("openmano request: %s", payload_req)
852 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
853 logger.debug("openmano response: %s", mano_response.text )
854 return _print_verbose(mano_response, args.verbose)
856 def tenant_list(args):
857 #print "tenant-list",args
859 toshow = _get_item_uuid("tenants", args.name)
860 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
862 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
863 mano_response = requests.get(URLrequest)
864 logger.debug("openmano response: %s", mano_response.text )
865 if args.verbose==None:
869 return _print_verbose(mano_response, args.verbose)
871 def tenant_delete(args):
872 #print "tenant-delete",args
873 todelete = _get_item_uuid("tenants", args.name)
875 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
876 if not (len(r)>0 and r[0].lower()=="y"):
878 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
879 mano_response = requests.delete(URLrequest)
880 logger.debug("openmano response: %s", mano_response.text )
881 result = 0 if mano_response.status_code==200 else mano_response.status_code
882 content = mano_response.json()
883 #print json.dumps(content, indent=4)
884 if mano_response.status_code == 200:
885 print content['result']
887 print content['error']['description']
890 def datacenter_attach(args):
891 tenant = _get_tenant()
892 datacenter = _get_datacenter(args.name)
893 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
896 if args.vim_tenant_id != None:
897 datacenter_dict['vim_tenant'] = args.vim_tenant_id
898 if args.vim_tenant_name != None:
899 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
900 if args.user != None:
901 datacenter_dict['vim_username'] = args.user
902 if args.password != None:
903 datacenter_dict['vim_password'] = args.password
904 if args.config!=None:
905 datacenter_dict["config"] = _load_file_or_yaml(args.config)
906 payload_req = json.dumps( {"datacenter": datacenter_dict })
910 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
911 logger.debug("openmano request: %s", payload_req)
912 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
913 logger.debug("openmano response: %s", mano_response.text )
914 result = _print_verbose(mano_response, args.verbose)
915 #provide addional information if error
916 if mano_response.status_code != 200:
917 content = mano_response.json()
918 if "already in use for 'name'" in content['error']['description'] and \
919 "to database vim_tenants table" in content['error']['description']:
920 print "Try to specify a different name with --vim-tenant-name"
923 def datacenter_detach(args):
927 tenant = _get_tenant()
928 datacenter = _get_datacenter(args.name, tenant)
929 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
930 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
931 mano_response = requests.delete(URLrequest, headers=headers_req)
932 logger.debug("openmano response: %s", mano_response.text )
933 content = mano_response.json()
934 #print json.dumps(content, indent=4)
935 result = 0 if mano_response.status_code==200 else mano_response.status_code
936 if mano_response.status_code == 200:
937 print content['result']
939 print content['error']['description']
942 def datacenter_create(args):
943 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
944 datacenter_dict={"name": args.name, "vim_url": args.url}
945 if args.description!=None:
946 datacenter_dict["description"] = args.description
948 datacenter_dict["type"] = args.type
950 datacenter_dict["vim_url_admin"] = args.url_admin
951 if args.config!=None:
952 datacenter_dict["config"] = _load_file_or_yaml(args.config)
953 payload_req = json.dumps( {"datacenter": datacenter_dict })
957 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
958 logger.debug("openmano request: %s", payload_req)
959 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
960 logger.debug("openmano response: %s", mano_response.text )
961 return _print_verbose(mano_response, args.verbose)
963 def datacenter_delete(args):
964 #print "datacenter-delete",args
965 todelete = _get_item_uuid("datacenters", args.name, "any")
967 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
968 if not (len(r)>0 and r[0].lower()=="y"):
970 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
971 mano_response = requests.delete(URLrequest)
972 logger.debug("openmano response: %s", mano_response.text )
973 result = 0 if mano_response.status_code==200 else mano_response.status_code
974 content = mano_response.json()
975 #print json.dumps(content, indent=4)
976 if mano_response.status_code == 200:
977 print content['result']
979 print content['error']['description']
982 def datacenter_list(args):
983 #print "datacenter-list",args
984 tenant='any' if args.all else _get_tenant()
987 toshow = _get_item_uuid("datacenters", args.name, tenant)
988 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
990 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
991 mano_response = requests.get(URLrequest)
992 logger.debug("openmano response: %s", mano_response.text )
993 if args.verbose==None:
997 return _print_verbose(mano_response, args.verbose)
999 def vim_action(args):
1000 #print "datacenter-net-action",args
1001 tenant = _get_tenant()
1002 datacenter = _get_datacenter(args.datacenter, tenant)
1003 if args.verbose==None:
1005 if args.action=="list":
1006 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1009 URLrequest += "/" + args.name
1010 mano_response = requests.get(URLrequest)
1011 logger.debug("openmano response: %s", mano_response.text )
1012 return _print_verbose(mano_response, args.verbose)
1013 elif args.action=="delete":
1014 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1015 mano_response = requests.delete(URLrequest)
1016 logger.debug("openmano response: %s", mano_response.text )
1017 result = 0 if mano_response.status_code==200 else mano_response.status_code
1018 content = mano_response.json()
1019 #print json.dumps(content, indent=4)
1020 if mano_response.status_code == 200:
1021 print content['result']
1023 print content['error']['description']
1025 elif args.action=="create":
1026 headers_req = {'content-type': 'application/yaml'}
1028 create_dict = _load_file_or_yaml(args.file)
1029 if args.item not in create_dict:
1030 create_dict = {args.item: create_dict}
1032 create_dict = {args.item:{}}
1034 create_dict[args.item]['name'] = args.name
1035 #if args.description:
1036 # create_dict[args.item]['description'] = args.description
1037 if args.item=="vim-net":
1039 create_dict[args.item]['bind_net'] = args.bind_net
1041 create_dict[args.item]['bind_type'] = args.bind_type
1043 create_dict[args.item]['shared'] = args.shared
1044 if "name" not in create_dict[args.item]:
1045 print "You must provide a name in the descriptor file or with the --name option"
1047 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1048 logger.debug("openmano request: %s", payload_req)
1049 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1050 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1051 logger.debug("openmano response: %s", mano_response.text )
1052 if args.verbose==None:
1054 return _print_verbose(mano_response, args.verbose)
1057 def datacenter_net_action(args):
1058 if args.action == "net-update":
1059 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1061 args.action = "netmap-delete"
1064 r = datacenter_netmap_action(args)
1067 args.action = "netmap-import"
1068 r = datacenter_netmap_action(args)
1071 if args.action == "net-edit":
1072 args.netmap = args.net
1074 elif args.action == "net-list":
1076 elif args.action == "net-delete":
1077 args.netmap = args.net
1080 args.action = "netmap" + args.action[3:]
1083 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1085 return datacenter_netmap_action(args)
1087 def datacenter_netmap_action(args):
1088 tenant = _get_tenant()
1089 datacenter = _get_datacenter(args.datacenter, tenant)
1090 #print "datacenter_netmap_action",args
1092 if args.verbose==None:
1094 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1095 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1097 if args.action=="netmap-list":
1099 URLrequest += "/" + args.netmap
1101 mano_response = requests.get(URLrequest)
1103 elif args.action=="netmap-delete":
1104 if args.netmap and args.all:
1105 print "you can not use a netmap name and the option --all at the same time"
1108 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1109 URLrequest += "/" + args.netmap
1111 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1113 print "you must specify a netmap name or the option --all"
1116 r = raw_input(force_text)
1117 if len(r)>0 and r[0].lower()=="y":
1121 mano_response = requests.delete(URLrequest, headers=headers_req)
1122 elif args.action=="netmap-import":
1124 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1125 if len(r)>0 and r[0].lower()=="y":
1129 URLrequest += "/upload"
1130 mano_response = requests.post(URLrequest, headers=headers_req)
1131 elif args.action=="netmap-edit" or args.action=="netmap-create":
1133 payload = _load_file_or_yaml(args.file)
1136 if "netmap" not in payload:
1137 payload = {"netmap": payload}
1139 payload["netmap"]["name"] = args.name
1141 payload["netmap"]["vim_id"] = args.vim_id
1142 if args.action=="netmap-create" and args.vim_name:
1143 payload["netmap"]["vim_name"] = args.vim_name
1144 payload_req = json.dumps(payload)
1145 logger.debug("openmano request: %s", payload_req)
1147 if args.action=="netmap-edit" and not args.force:
1148 if len(payload["netmap"]) == 0:
1149 print "You must supply some parameter to edit"
1151 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1152 if len(r)>0 and r[0].lower()=="y":
1156 URLrequest += "/" + args.netmap
1157 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1158 else: #netmap-create
1159 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1160 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1162 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1164 logger.debug("openmano response: %s", mano_response.text )
1165 return _print_verbose(mano_response, args.verbose)
1167 def element_edit(args):
1168 element = _get_item_uuid(args.element, args.name)
1169 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1170 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1171 payload=_load_file_or_yaml(args.file)
1172 if args.element[:-1] not in payload:
1173 payload = {args.element[:-1]: payload }
1174 payload_req = json.dumps(payload)
1177 if not args.force or (args.name==None and args.filer==None):
1178 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1179 if len(r)>0 and r[0].lower()=="y":
1183 logger.debug("openmano request: %s", payload_req)
1184 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1185 logger.debug("openmano response: %s", mano_response.text )
1186 if args.verbose==None:
1190 return _print_verbose(mano_response, args.verbose)
1197 if __name__=="__main__":
1199 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1200 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1201 mano_port = os.getenv('OPENMANO_PORT',"9090")
1202 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1204 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1205 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1207 subparsers = main_parser.add_subparsers(help='commands')
1209 parent_parser = argparse.ArgumentParser(add_help=False)
1210 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1211 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1213 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1214 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1215 config_parser.set_defaults(func=config)
1217 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1218 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1219 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1220 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1221 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1222 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1223 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1224 vnf_create_parser.set_defaults(func=vnf_create)
1226 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1227 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1228 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1229 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1230 vnf_list_parser.set_defaults(func=vnf_list)
1232 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1233 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1234 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1235 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1236 vnf_delete_parser.set_defaults(func=vnf_delete)
1238 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1239 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1240 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1241 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1242 scenario_create_parser.set_defaults(func=scenario_create)
1244 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1245 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1246 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1247 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1248 scenario_list_parser.set_defaults(func=scenario_list)
1250 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1251 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1252 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1253 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1254 scenario_delete_parser.set_defaults(func=scenario_delete)
1256 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1257 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1258 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1259 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1260 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1261 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1262 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1264 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1265 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1266 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1267 scenario_deploy_parser.set_defaults(func=scenario_verify)
1269 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1270 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1271 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1272 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1273 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1274 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1275 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")
1276 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")
1277 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")
1278 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")
1279 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1280 instance_scenario_create_parser.set_defaults(func=instance_create)
1282 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1283 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1284 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1285 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1287 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)")
1288 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1289 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1290 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1291 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1293 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1294 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1295 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1296 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1297 help="action to send")
1298 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1299 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1300 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1301 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1303 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1304 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1305 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1307 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1308 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1309 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1310 tenant_create_parser.set_defaults(func=tenant_create)
1312 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1313 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1314 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1315 tenant_delete_parser.set_defaults(func=tenant_delete)
1317 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1318 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1319 tenant_list_parser.set_defaults(func=tenant_list)
1321 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1322 for item in item_list:
1323 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1324 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1325 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1326 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1327 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1329 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1330 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1331 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1332 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1333 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1334 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1335 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1336 datacenter_create_parser.set_defaults(func=datacenter_create)
1338 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1339 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1340 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1341 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1343 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1344 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1345 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1346 datacenter_list_parser.set_defaults(func=datacenter_list)
1348 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1349 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1350 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1351 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1352 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1353 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1354 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1355 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1357 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1358 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1359 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1360 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1363 action_dict={'net-update': 'retrieves external networks from datacenter',
1364 'net-edit': 'edits an external network',
1365 'net-delete': 'deletes an external network',
1366 'net-list': 'lists external networks from a datacenter'
1368 for item in action_dict:
1369 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1370 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1371 if item=='net-edit' or item=='net-delete':
1372 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1373 if item=='net-edit':
1374 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1375 if item!='net-list':
1376 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1377 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1380 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1381 'netmap-create': 'create a new network senario netmap',
1382 'netmap-edit': 'edit name of a network senario netmap',
1383 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1384 'netmap-list': 'list/show network scenario netmaps'
1386 for item in action_dict:
1387 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1388 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1389 #if item=='net-add':
1390 # datacenter_action_parser.add_argument("net", help="name of the network")
1391 if item=='netmap-delete':
1392 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1393 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1394 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1395 if item=='netmap-edit':
1396 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1397 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1398 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1399 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1400 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1401 if item=='netmap-list':
1402 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1403 if item=='netmap-create':
1404 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1405 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1406 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1407 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1408 if item=='netmap-import':
1409 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1410 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1412 for item in ("network", "tenant"):
1414 commnad_name = 'vim-net'
1416 commnad_name = 'vim-'+item
1417 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1418 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1419 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1420 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1422 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1423 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1424 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1425 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1427 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1428 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1429 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1430 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1432 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1433 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1434 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>'")
1436 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1437 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1439 argcomplete.autocomplete(main_parser)
1442 args = main_parser.parse_args()
1444 level = logging.CRITICAL
1445 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1446 if "debug" in args and args.debug:
1447 level = logging.DEBUG
1448 logging.basicConfig(format=streamformat, level= level)
1449 logger = logging.getLogger('mano')
1450 logger.setLevel(level)
1451 result = args.func(args)
1454 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1455 except (requests.exceptions.ConnectionError):
1456 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1458 except (KeyboardInterrupt):
1459 print 'Exiting openmano'
1461 except (SystemExit, ArgumentParserError):
1463 except OpenmanoCLIError as e: