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.11-r517"
32 version_date="Jan 2017"
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 name = content.get('name');
135 myoutput = "%s %s" %(uuid.ljust(38),name.ljust(20))
136 if content.get("status"):
137 myoutput += " " + content['status'].ljust(20)
138 elif "enabled" in content and not content["enabled"]:
139 myoutput += " enabled=False".ljust(20)
140 if verbose_level >=1:
141 if content.get('created_at'):
142 myoutput += " " + content['created_at'].ljust(20)
143 if verbose_level >=2:
145 if content.get('type'):
146 myoutput += new_line + " Type: " + content['type'].ljust(29)
148 if content.get('description'):
149 myoutput += new_line + " Description: " + content['description'].ljust(20)
152 print content['error']['description']
155 def parser_json_yaml(file_name):
157 f = file(file_name, "r")
160 except Exception as e:
161 return (False, str(e))
164 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
166 config = yaml.load(text)
167 except yaml.YAMLError as exc:
169 if hasattr(exc, 'problem_mark'):
170 mark = exc.problem_mark
171 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
172 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
175 config = json.loads(text)
176 except Exception as e:
177 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
181 def _load_file_or_yaml(content):
183 'content' can be or a yaml/json file or a text containing a yaml/json text format
184 This function autodetect, trying to load and parse the file,
185 if fails trying to parse the 'content' text
186 Returns the dictionary once parsed, or print an error and finish the program
188 #Check config file exists
189 if os.path.isfile(content):
190 r,payload = parser_json_yaml(content)
194 elif "{" in content or ":" in content:
196 payload = yaml.load(content)
197 except yaml.YAMLError as exc:
199 if hasattr(exc, 'problem_mark'):
200 mark = exc.problem_mark
201 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
202 print "Error loading yaml/json text"+error_pos
205 print "'%s' is neither a valid file nor a yaml/json content" % content
209 def _get_item_uuid(item, item_name_id, tenant=None):
211 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
213 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
214 mano_response = requests.get(URLrequest)
215 logger.debug("openmano response: %s", mano_response.text )
216 content = mano_response.json()
219 for i in content[item]:
220 if i["uuid"] == item_name_id:
222 if i["name"] == item_name_id:
226 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
228 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
231 # def check_valid_uuid(uuid):
232 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
234 # js_v(uuid, id_schema)
236 # except js_e.ValidationError:
239 def _get_tenant(tenant_name_id = None):
240 if not tenant_name_id:
241 tenant_name_id = mano_tenant
243 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
244 return _get_item_uuid("tenants", tenant_name_id)
246 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
247 if not datacenter_name_id:
248 datacenter_name_id = mano_datacenter
249 if not datacenter_name_id:
250 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
251 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
253 def vnf_create(args):
254 #print "vnf-create",args
255 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
256 tenant = _get_tenant()
257 myvnf = _load_file_or_yaml(args.file)
259 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
263 myvnf['vnf']['name'] = args.name
265 myvnf['vnf']['description'] = args.description
268 for image_path_ in args.image_path.split(","):
269 #print "image-path", image_path_
270 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
271 if "image name" in myvnf['vnf']['VNFC'][index]:
272 del myvnf['vnf']['VNFC'][index]["image name"]
273 if "image checksum" in myvnf['vnf']['VNFC'][index]:
274 del myvnf['vnf']['VNFC'][index]["image checksum"]
276 if args.image_name: #image name precedes if both are supplied
278 for image_name_ in args.image_name.split(","):
279 myvnf['vnf']['VNFC'][index]['image name']=image_name_
280 if "VNFC image" in myvnf['vnf']['VNFC'][index]:
281 del myvnf['vnf']['VNFC'][index]["VNFC image"]
283 if args.image_checksum:
285 for image_checksum_ in args.image_checksum.split(","):
286 myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
288 except (KeyError, TypeError), e:
289 if str(e)=='vnf': error_pos= "missing field 'vnf'"
290 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
291 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
292 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
293 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
294 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
295 elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
296 elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
297 else: error_pos="wrong format"
298 print "Wrong VNF descriptor: " + error_pos
300 payload_req = json.dumps(myvnf)
304 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
305 logger.debug("openmano request: %s", payload_req)
306 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
307 logger.debug("openmano response: %s", mano_response.text )
309 return _print_verbose(mano_response, args.verbose)
312 #print "vnf-list",args
316 tenant = _get_tenant()
318 toshow = _get_item_uuid("vnfs", args.name, tenant)
319 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
321 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
322 mano_response = requests.get(URLrequest)
323 logger.debug("openmano response: %s", mano_response.text )
324 content = mano_response.json()
325 #print json.dumps(content, indent=4)
326 if args.verbose==None:
328 result = 0 if mano_response.status_code==200 else mano_response.status_code
329 if mano_response.status_code == 200:
331 if args.verbose >= 3:
332 print yaml.safe_dump(content, indent=4, default_flow_style=False)
334 if len(content['vnfs']) == 0:
335 print "No VNFs were found."
336 return 404 #HTTP_Not_Found
337 for vnf in content['vnfs']:
338 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
340 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
343 print " Description: %s" %vnf['description']
344 print " VNF descriptor file: %s" %vnf['path']
347 print yaml.safe_dump(content, indent=4, default_flow_style=False)
350 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
351 print " Description: %s" %vnf['description']
352 #print " VNF descriptor file: %s" %vnf['path']
354 for vm in vnf['VNFC']:
355 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
356 print " %s %s" %(vm['name'].ljust(20), vm['description'])
357 if len(vnf['nets'])>0:
358 print " Internal nets:"
359 for net in vnf['nets']:
360 print " %s %s" %(net['name'].ljust(20), net['description'])
361 if len(vnf['external-connections'])>0:
362 print " External interfaces:"
363 for interface in vnf['external-connections']:
364 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
365 interface.get('vpci',"").ljust(14))
367 print content['error']['description']
369 print yaml.safe_dump(content, indent=4, default_flow_style=False)
372 def vnf_delete(args):
373 #print "vnf-delete",args
377 tenant = _get_tenant()
378 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
380 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
381 if not (len(r)>0 and r[0].lower()=="y"):
383 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
384 mano_response = requests.delete(URLrequest)
385 logger.debug("openmano response: %s", mano_response.text )
386 result = 0 if mano_response.status_code==200 else mano_response.status_code
387 content = mano_response.json()
388 #print json.dumps(content, indent=4)
389 if mano_response.status_code == 200:
390 print content['result']
392 print content['error']['description']
395 def scenario_create(args):
396 #print "scenario-create",args
397 tenant = _get_tenant()
398 headers_req = {'content-type': 'application/yaml'}
399 myscenario = _load_file_or_yaml(args.file)
402 myscenario['name'] = args.name
404 myscenario['description'] = args.description
405 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
409 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
410 logger.debug("openmano request: %s", payload_req)
411 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
412 logger.debug("openmano response: %s", mano_response.text )
413 return _print_verbose(mano_response, args.verbose)
415 def scenario_list(args):
416 #print "scenario-list",args
420 tenant = _get_tenant()
422 toshow = _get_item_uuid("scenarios", args.name, tenant)
423 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
425 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
426 mano_response = requests.get(URLrequest)
427 logger.debug("openmano response: %s", mano_response.text )
428 content = mano_response.json()
429 #print json.dumps(content, indent=4)
430 if args.verbose==None:
433 result = 0 if mano_response.status_code==200 else mano_response.status_code
434 if mano_response.status_code == 200:
436 if args.verbose >= 3:
437 print yaml.safe_dump(content, indent=4, default_flow_style=False)
439 if len(content['scenarios']) == 0:
440 print "No scenarios were found."
441 return 404 #HTTP_Not_Found
442 for scenario in content['scenarios']:
443 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
445 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
448 print " Description: %s" %scenario['description']
451 print yaml.safe_dump(content, indent=4, default_flow_style=False)
453 scenario = content['scenario']
454 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
456 print " Description: %s" %scenario['description']
458 for vnf in scenario['vnfs']:
459 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
460 if len(scenario['nets'])>0:
461 print " Internal nets:"
462 for net in scenario['nets']:
463 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
464 net['description'] = '-'
465 if not net['external']:
466 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
467 print " External nets:"
468 for net in scenario['nets']:
470 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
472 print content['error']['description']
474 print yaml.safe_dump(content, indent=4, default_flow_style=False)
477 def scenario_delete(args):
478 #print "scenario-delete",args
482 tenant = _get_tenant()
483 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
485 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
486 if not (len(r)>0 and r[0].lower()=="y"):
488 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
489 mano_response = requests.delete(URLrequest)
490 logger.debug("openmano response: %s", mano_response.text )
491 result = 0 if mano_response.status_code==200 else mano_response.status_code
492 content = mano_response.json()
493 #print json.dumps(content, indent=4)
494 if mano_response.status_code == 200:
495 print content['result']
497 print content['error']['description']
500 def scenario_deploy(args):
501 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
504 args.netmap_use = None
505 args.netmap_create = None
507 args.keypair_auto = None
508 return instance_create(args)
510 # #print "scenario-deploy",args
511 # headers_req = {'content-type': 'application/json'}
515 # actionCmd="reserve"
516 # action[actionCmd] = {}
517 # action[actionCmd]["instance_name"] = args.name
518 # if args.datacenter != None:
519 # action[actionCmd]["datacenter"] = args.datacenter
520 # elif mano_datacenter != None:
521 # action[actionCmd]["datacenter"] = mano_datacenter
523 # if args.description:
524 # action[actionCmd]["description"] = args.description
525 # payload_req = json.dumps(action, indent=4)
528 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
529 # logger.debug("openmano request: %s", payload_req)
530 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
531 # logger.debug("openmano response: %s", mano_response.text )
532 # if args.verbose==None:
535 # result = 0 if mano_response.status_code==200 else mano_response.status_code
536 # content = mano_response.json()
537 # #print json.dumps(content, indent=4)
538 # if args.verbose >= 3:
539 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
542 # if mano_response.status_code == 200:
543 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
544 # if args.verbose >=1:
545 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
546 # if args.verbose >=2:
547 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
550 # print "To check the status, run the following command:"
551 # print "openmano instance-scenario-list <instance_id>"
553 # print content['error']['description']
556 def scenario_verify(args):
557 #print "scenario-verify",args
558 headers_req = {'content-type': 'application/json'}
560 action["verify"] = {}
561 action["verify"]["instance_name"] = "scen-verify-return5"
562 payload_req = json.dumps(action, indent=4)
565 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
566 logger.debug("openmano request: %s", payload_req)
567 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
568 logger.debug("openmano response: %s", mano_response.text )
570 result = 0 if mano_response.status_code==200 else mano_response.status_code
571 content = mano_response.json()
572 #print json.dumps(content, indent=4)
573 if mano_response.status_code == 200:
574 print content['result']
576 print content['error']['description']
579 def instance_create(args):
580 tenant = _get_tenant()
581 headers_req = {'content-type': 'application/yaml'}
582 myInstance={"instance": {}, "schema_version": "0.1"}
584 instance_dict = _load_file_or_yaml(args.file)
585 if "instance" not in instance_dict:
586 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
588 myInstance = instance_dict
590 myInstance["instance"]['name'] = args.name
592 myInstance["instance"]['description'] = args.description
594 myInstance["instance"]['action'] = "reserve"
596 datacenter = myInstance["instance"].get("datacenter")
597 if args.datacenter != None:
598 datacenter = args.datacenter
599 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
601 scenario = myInstance["instance"].get("scenario")
602 if args.scenario != None:
603 scenario = args.scenario
605 print "you must provide a scenario in the file descriptor or with --scenario"
607 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
609 if "networks" not in myInstance["instance"]:
610 myInstance["instance"]["networks"] = {}
611 for net in args.netmap_use:
612 net_comma_list = net.split(",")
613 for net_comma in net_comma_list:
614 net_tuple = net_comma.split("=")
615 if len(net_tuple) != 2:
616 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
618 net_scenario = net_tuple[0].strip()
619 net_datacenter = net_tuple[1].strip()
620 if net_scenario not in myInstance["instance"]["networks"]:
621 myInstance["instance"]["networks"][net_scenario] = {}
622 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
623 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
624 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
625 if args.netmap_create:
626 if "networks" not in myInstance["instance"]:
627 myInstance["instance"]["networks"] = {}
628 for net in args.netmap_create:
629 net_comma_list = net.split(",")
630 for net_comma in net_comma_list:
631 net_tuple = net_comma.split("=")
632 if len(net_tuple) == 1:
633 net_scenario = net_tuple[0].strip()
634 net_datacenter = None
635 elif len(net_tuple) == 2:
636 net_scenario = net_tuple[0].strip()
637 net_datacenter = net_tuple[1].strip()
639 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
641 if net_scenario not in myInstance["instance"]["networks"]:
642 myInstance["instance"]["networks"][net_scenario] = {}
643 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
644 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
645 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
647 if "cloud-config" not in myInstance["instance"]:
648 myInstance["instance"]["cloud-config"] = {}
649 cloud_config = myInstance["instance"]["cloud-config"]
650 for key in args.keypair:
651 index = key.find(":")
653 if "key-pairs" not in cloud_config:
654 cloud_config["key-pairs"] = []
655 cloud_config["key-pairs"].append(key)
659 key_list = key_.split(",")
660 if "users" not in cloud_config:
661 cloud_config["users"] = []
662 cloud_config["users"].append({"name": user, "key-pairs": key_list })
663 if args.keypair_auto:
666 home = os.getenv("HOME")
667 user = os.getenv("USER")
668 files = os.listdir(home+'/.ssh')
670 if file[-4:] == ".pub":
671 with open(home+'/.ssh/'+file, 'r') as f:
672 keys.append(f.read())
674 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
676 except Exception as e:
677 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
680 if "cloud-config" not in myInstance["instance"]:
681 myInstance["instance"]["cloud-config"] = {}
682 cloud_config = myInstance["instance"]["cloud-config"]
683 if "key-pairs" not in cloud_config:
684 cloud_config["key-pairs"] = []
686 if "users" not in cloud_config:
687 cloud_config["users"] = []
688 cloud_config["users"].append({"name": user, "key-pairs": keys })
690 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
691 logger.debug("openmano request: %s", payload_req)
692 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
693 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
694 logger.debug("openmano response: %s", mano_response.text )
695 if args.verbose==None:
698 result = 0 if mano_response.status_code==200 else mano_response.status_code
699 content = mano_response.json()
700 #print json.dumps(content, indent=4)
701 if args.verbose >= 3:
702 print yaml.safe_dump(content, indent=4, default_flow_style=False)
705 if mano_response.status_code == 200:
706 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
708 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
710 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
713 print content['error']['description']
716 def instance_scenario_list(args):
717 #print "instance-scenario-list",args
721 tenant = _get_tenant()
723 toshow = _get_item_uuid("instances", args.name, tenant)
724 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
726 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
727 mano_response = requests.get(URLrequest)
728 logger.debug("openmano response: %s", mano_response.text )
729 content = mano_response.json()
730 #print json.dumps(content, indent=4)
731 if args.verbose==None:
734 result = 0 if mano_response.status_code==200 else mano_response.status_code
735 if mano_response.status_code == 200:
737 if args.verbose >= 3:
738 print yaml.safe_dump(content, indent=4, default_flow_style=False)
740 if len(content['instances']) == 0:
741 print "No scenario instances were found."
743 for instance in content['instances']:
744 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
746 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
749 print "Description: %s" %instance['description']
752 print yaml.safe_dump(content, indent=4, default_flow_style=False)
755 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
756 print "Description: %s" %instance['description']
757 print "Template scenario id: %s" %instance['scenario_id']
758 print "Template scenario name: %s" %instance['scenario_name']
759 print "---------------------------------------"
760 print "VNF instances: %d" %len(instance['vnfs'])
761 for vnf in instance['vnfs']:
762 #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))
763 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
764 if len(instance['nets'])>0:
765 print "---------------------------------------"
766 print "Internal nets:"
767 for net in instance['nets']:
769 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
770 print "---------------------------------------"
771 print "External nets:"
772 for net in instance['nets']:
773 if not net['created']:
774 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
775 print "---------------------------------------"
776 print "VM instances:"
777 for vnf in instance['vnfs']:
778 for vm in vnf['vms']:
779 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'])
781 print content['error']['description']
783 print yaml.safe_dump(content, indent=4, default_flow_style=False)
786 def instance_scenario_status(args):
787 print "instance-scenario-status"
790 def instance_scenario_delete(args):
794 tenant = _get_tenant()
795 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
796 #print "instance-scenario-delete",args
798 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
799 if not (len(r)>0 and r[0].lower()=="y"):
801 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
802 mano_response = requests.delete(URLrequest)
803 logger.debug("openmano response: %s", mano_response.text )
804 result = 0 if mano_response.status_code==200 else mano_response.status_code
805 content = mano_response.json()
806 #print json.dumps(content, indent=4)
807 if mano_response.status_code == 200:
808 print content['result']
810 print content['error']['description']
813 def instance_scenario_action(args):
814 #print "instance-scenario-action", args
815 tenant = _get_tenant()
816 toact = _get_item_uuid("instances", args.name, tenant=tenant)
818 action[ args.action ] = args.param
820 action["vnfs"] = args.vnf
822 action["vms"] = args.vm
824 headers_req = {'content-type': 'application/json'}
825 payload_req = json.dumps(action, indent=4)
826 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
827 logger.debug("openmano request: %s", payload_req)
828 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
829 logger.debug("openmano response: %s", mano_response.text )
830 result = 0 if mano_response.status_code==200 else mano_response.status_code
831 content = mano_response.json()
832 #print json.dumps(content, indent=4)
833 if mano_response.status_code == 200:
835 print yaml.safe_dump(content, indent=4, default_flow_style=False)
837 for uuid,c in content.iteritems():
838 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
840 print content['error']['description']
844 def instance_vnf_list(args):
845 print "instance-vnf-list"
848 def instance_vnf_status(args):
849 print "instance-vnf-status"
852 def tenant_create(args):
853 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
854 tenant_dict={"name": args.name}
855 if args.description!=None:
856 tenant_dict["description"] = args.description
857 payload_req = json.dumps( {"tenant": tenant_dict })
861 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
862 logger.debug("openmano request: %s", payload_req)
863 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
864 logger.debug("openmano response: %s", mano_response.text )
865 return _print_verbose(mano_response, args.verbose)
867 def tenant_list(args):
868 #print "tenant-list",args
870 toshow = _get_item_uuid("tenants", args.name)
871 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
873 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
874 mano_response = requests.get(URLrequest)
875 logger.debug("openmano response: %s", mano_response.text )
876 if args.verbose==None:
880 return _print_verbose(mano_response, args.verbose)
882 def tenant_delete(args):
883 #print "tenant-delete",args
884 todelete = _get_item_uuid("tenants", args.name)
886 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
887 if not (len(r)>0 and r[0].lower()=="y"):
889 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
890 mano_response = requests.delete(URLrequest)
891 logger.debug("openmano response: %s", mano_response.text )
892 result = 0 if mano_response.status_code==200 else mano_response.status_code
893 content = mano_response.json()
894 #print json.dumps(content, indent=4)
895 if mano_response.status_code == 200:
896 print content['result']
898 print content['error']['description']
901 def datacenter_attach(args):
902 tenant = _get_tenant()
903 datacenter = _get_datacenter(args.name)
904 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
907 if args.vim_tenant_id != None:
908 datacenter_dict['vim_tenant'] = args.vim_tenant_id
909 if args.vim_tenant_name != None:
910 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
911 if args.user != None:
912 datacenter_dict['vim_username'] = args.user
913 if args.password != None:
914 datacenter_dict['vim_password'] = args.password
915 if args.config!=None:
916 datacenter_dict["config"] = _load_file_or_yaml(args.config)
917 payload_req = json.dumps( {"datacenter": datacenter_dict })
921 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
922 logger.debug("openmano request: %s", payload_req)
923 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
924 logger.debug("openmano response: %s", mano_response.text )
925 result = _print_verbose(mano_response, args.verbose)
926 #provide addional information if error
927 if mano_response.status_code != 200:
928 content = mano_response.json()
929 if "already in use for 'name'" in content['error']['description'] and \
930 "to database vim_tenants table" in content['error']['description']:
931 print "Try to specify a different name with --vim-tenant-name"
934 def datacenter_detach(args):
938 tenant = _get_tenant()
939 datacenter = _get_datacenter(args.name, tenant)
940 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
941 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
942 mano_response = requests.delete(URLrequest, headers=headers_req)
943 logger.debug("openmano response: %s", mano_response.text )
944 content = mano_response.json()
945 #print json.dumps(content, indent=4)
946 result = 0 if mano_response.status_code==200 else mano_response.status_code
947 if mano_response.status_code == 200:
948 print content['result']
950 print content['error']['description']
953 def datacenter_create(args):
954 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
955 datacenter_dict={"name": args.name, "vim_url": args.url}
956 if args.description!=None:
957 datacenter_dict["description"] = args.description
959 datacenter_dict["type"] = args.type
961 datacenter_dict["vim_url_admin"] = args.url_admin
962 if args.config!=None:
963 datacenter_dict["config"] = _load_file_or_yaml(args.config)
964 payload_req = json.dumps( {"datacenter": datacenter_dict })
968 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
969 logger.debug("openmano request: %s", payload_req)
970 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
971 logger.debug("openmano response: %s", mano_response.text )
972 return _print_verbose(mano_response, args.verbose)
974 def datacenter_delete(args):
975 #print "datacenter-delete",args
976 todelete = _get_item_uuid("datacenters", args.name, "any")
978 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
979 if not (len(r)>0 and r[0].lower()=="y"):
981 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
982 mano_response = requests.delete(URLrequest)
983 logger.debug("openmano response: %s", mano_response.text )
984 result = 0 if mano_response.status_code==200 else mano_response.status_code
985 content = mano_response.json()
986 #print json.dumps(content, indent=4)
987 if mano_response.status_code == 200:
988 print content['result']
990 print content['error']['description']
993 def datacenter_list(args):
994 #print "datacenter-list",args
995 tenant='any' if args.all else _get_tenant()
998 toshow = _get_item_uuid("datacenters", args.name, tenant)
999 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1001 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1002 mano_response = requests.get(URLrequest)
1003 logger.debug("openmano response: %s", mano_response.text )
1004 if args.verbose==None:
1008 return _print_verbose(mano_response, args.verbose)
1010 def vim_action(args):
1011 #print "datacenter-net-action",args
1012 tenant = _get_tenant()
1013 datacenter = _get_datacenter(args.datacenter, tenant)
1014 if args.verbose==None:
1016 if args.action=="list":
1017 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1020 URLrequest += "/" + args.name
1021 mano_response = requests.get(URLrequest)
1022 logger.debug("openmano response: %s", mano_response.text )
1023 return _print_verbose(mano_response, args.verbose)
1024 elif args.action=="delete":
1025 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1026 mano_response = requests.delete(URLrequest)
1027 logger.debug("openmano response: %s", mano_response.text )
1028 result = 0 if mano_response.status_code==200 else mano_response.status_code
1029 content = mano_response.json()
1030 #print json.dumps(content, indent=4)
1031 if mano_response.status_code == 200:
1032 print content['result']
1034 print content['error']['description']
1036 elif args.action=="create":
1037 headers_req = {'content-type': 'application/yaml'}
1039 create_dict = _load_file_or_yaml(args.file)
1040 if args.item not in create_dict:
1041 create_dict = {args.item: create_dict}
1043 create_dict = {args.item:{}}
1045 create_dict[args.item]['name'] = args.name
1046 #if args.description:
1047 # create_dict[args.item]['description'] = args.description
1048 if args.item=="vim-net":
1050 create_dict[args.item]['bind_net'] = args.bind_net
1052 create_dict[args.item]['bind_type'] = args.bind_type
1054 create_dict[args.item]['shared'] = args.shared
1055 if "name" not in create_dict[args.item]:
1056 print "You must provide a name in the descriptor file or with the --name option"
1058 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1059 logger.debug("openmano request: %s", payload_req)
1060 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1061 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1062 logger.debug("openmano response: %s", mano_response.text )
1063 if args.verbose==None:
1065 return _print_verbose(mano_response, args.verbose)
1068 def datacenter_net_action(args):
1069 if args.action == "net-update":
1070 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1072 args.action = "netmap-delete"
1075 r = datacenter_netmap_action(args)
1078 args.action = "netmap-import"
1079 r = datacenter_netmap_action(args)
1082 if args.action == "net-edit":
1083 args.netmap = args.net
1085 elif args.action == "net-list":
1087 elif args.action == "net-delete":
1088 args.netmap = args.net
1091 args.action = "netmap" + args.action[3:]
1094 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1096 return datacenter_netmap_action(args)
1098 def datacenter_netmap_action(args):
1099 tenant = _get_tenant()
1100 datacenter = _get_datacenter(args.datacenter, tenant)
1101 #print "datacenter_netmap_action",args
1103 if args.verbose==None:
1105 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1106 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1108 if args.action=="netmap-list":
1110 URLrequest += "/" + args.netmap
1112 mano_response = requests.get(URLrequest)
1114 elif args.action=="netmap-delete":
1115 if args.netmap and args.all:
1116 print "you can not use a netmap name and the option --all at the same time"
1119 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1120 URLrequest += "/" + args.netmap
1122 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1124 print "you must specify a netmap name or the option --all"
1127 r = raw_input(force_text)
1128 if len(r)>0 and r[0].lower()=="y":
1132 mano_response = requests.delete(URLrequest, headers=headers_req)
1133 elif args.action=="netmap-import":
1135 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1136 if len(r)>0 and r[0].lower()=="y":
1140 URLrequest += "/upload"
1141 mano_response = requests.post(URLrequest, headers=headers_req)
1142 elif args.action=="netmap-edit" or args.action=="netmap-create":
1144 payload = _load_file_or_yaml(args.file)
1147 if "netmap" not in payload:
1148 payload = {"netmap": payload}
1150 payload["netmap"]["name"] = args.name
1152 payload["netmap"]["vim_id"] = args.vim_id
1153 if args.action=="netmap-create" and args.vim_name:
1154 payload["netmap"]["vim_name"] = args.vim_name
1155 payload_req = json.dumps(payload)
1156 logger.debug("openmano request: %s", payload_req)
1158 if args.action=="netmap-edit" and not args.force:
1159 if len(payload["netmap"]) == 0:
1160 print "You must supply some parameter to edit"
1162 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1163 if len(r)>0 and r[0].lower()=="y":
1167 URLrequest += "/" + args.netmap
1168 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1169 else: #netmap-create
1170 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1171 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1173 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1175 logger.debug("openmano response: %s", mano_response.text )
1176 return _print_verbose(mano_response, args.verbose)
1178 def element_edit(args):
1179 element = _get_item_uuid(args.element, args.name)
1180 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1181 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1182 payload=_load_file_or_yaml(args.file)
1183 if args.element[:-1] not in payload:
1184 payload = {args.element[:-1]: payload }
1185 payload_req = json.dumps(payload)
1188 if not args.force or (args.name==None and args.filer==None):
1189 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1190 if len(r)>0 and r[0].lower()=="y":
1194 logger.debug("openmano request: %s", payload_req)
1195 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1196 logger.debug("openmano response: %s", mano_response.text )
1197 if args.verbose==None:
1201 return _print_verbose(mano_response, args.verbose)
1208 if __name__=="__main__":
1210 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1211 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1212 mano_port = os.getenv('OPENMANO_PORT',"9090")
1213 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1215 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1216 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1218 subparsers = main_parser.add_subparsers(help='commands')
1220 parent_parser = argparse.ArgumentParser(add_help=False)
1221 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1222 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1224 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1225 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1226 config_parser.set_defaults(func=config)
1228 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1229 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1230 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1231 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1232 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1233 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1234 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1235 vnf_create_parser.set_defaults(func=vnf_create)
1237 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1238 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1239 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1240 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1241 vnf_list_parser.set_defaults(func=vnf_list)
1243 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1244 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1245 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1246 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1247 vnf_delete_parser.set_defaults(func=vnf_delete)
1249 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1250 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1251 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1252 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1253 scenario_create_parser.set_defaults(func=scenario_create)
1255 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1256 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1257 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1258 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1259 scenario_list_parser.set_defaults(func=scenario_list)
1261 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1262 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1263 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1264 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1265 scenario_delete_parser.set_defaults(func=scenario_delete)
1267 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1268 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1269 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1270 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1271 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1272 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1273 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1275 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1276 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1277 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1278 scenario_deploy_parser.set_defaults(func=scenario_verify)
1280 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1281 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1282 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1283 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1284 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1285 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1286 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")
1287 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")
1288 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")
1289 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")
1290 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1291 instance_scenario_create_parser.set_defaults(func=instance_create)
1293 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1294 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1295 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1296 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1298 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)")
1299 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1300 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1301 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1302 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1304 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1305 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1306 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1307 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1308 help="action to send")
1309 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1310 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1311 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1312 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1314 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1315 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1316 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1318 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1319 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1320 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1321 tenant_create_parser.set_defaults(func=tenant_create)
1323 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1324 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1325 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1326 tenant_delete_parser.set_defaults(func=tenant_delete)
1328 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1329 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1330 tenant_list_parser.set_defaults(func=tenant_list)
1332 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1333 for item in item_list:
1334 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1335 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1336 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1337 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1338 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1340 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1341 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1342 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1343 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1344 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1345 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1346 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1347 datacenter_create_parser.set_defaults(func=datacenter_create)
1349 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1350 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1351 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1352 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1354 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1355 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1356 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1357 datacenter_list_parser.set_defaults(func=datacenter_list)
1359 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1360 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1361 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1362 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1363 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1364 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1365 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1366 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1368 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1369 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1370 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1371 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1374 action_dict={'net-update': 'retrieves external networks from datacenter',
1375 'net-edit': 'edits an external network',
1376 'net-delete': 'deletes an external network',
1377 'net-list': 'lists external networks from a datacenter'
1379 for item in action_dict:
1380 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1381 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1382 if item=='net-edit' or item=='net-delete':
1383 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1384 if item=='net-edit':
1385 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1386 if item!='net-list':
1387 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1388 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1391 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1392 'netmap-create': 'create a new network senario netmap',
1393 'netmap-edit': 'edit name of a network senario netmap',
1394 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1395 'netmap-list': 'list/show network scenario netmaps'
1397 for item in action_dict:
1398 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1399 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1400 #if item=='net-add':
1401 # datacenter_action_parser.add_argument("net", help="name of the network")
1402 if item=='netmap-delete':
1403 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1404 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1405 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1406 if item=='netmap-edit':
1407 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1408 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1409 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1410 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1411 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1412 if item=='netmap-list':
1413 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1414 if item=='netmap-create':
1415 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1416 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1417 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1418 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1419 if item=='netmap-import':
1420 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1421 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1423 for item in ("network", "tenant", "image"):
1425 commnad_name = 'vim-net'
1427 commnad_name = 'vim-'+item
1428 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1429 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1430 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1431 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1433 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1434 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1435 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1436 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1438 if item == "network" or item == "tenant":
1439 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1440 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1441 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1442 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1444 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1445 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1446 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>'")
1448 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1449 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1451 argcomplete.autocomplete(main_parser)
1454 args = main_parser.parse_args()
1456 level = logging.CRITICAL
1457 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1458 if "debug" in args and args.debug:
1459 level = logging.DEBUG
1460 logging.basicConfig(format=streamformat, level= level)
1461 logger = logging.getLogger('mano')
1462 logger.setLevel(level)
1463 result = args.func(args)
1466 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1467 except (requests.exceptions.ConnectionError):
1468 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1470 except (KeyboardInterrupt):
1471 print 'Exiting openmano'
1473 except (SystemExit, ArgumentParserError):
1475 except OpenmanoCLIError as e: