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.9-r515"
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 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_
266 if "image name" in myvnf['vnf']['VNFC'][index]:
267 del myvnf['vnf']['VNFC'][index]["image name"]
268 if "image checksum" in myvnf['vnf']['VNFC'][index]:
269 del myvnf['vnf']['VNFC'][index]["image checksum"]
271 if args.image_name: #image name precedes if both are supplied
273 for image_name_ in args.image_name.split(","):
274 myvnf['vnf']['VNFC'][index]['image name']=image_name_
275 if "VNFC image" in myvnf['vnf']['VNFC'][index]:
276 del myvnf['vnf']['VNFC'][index]["VNFC image"]
278 if args.image_checksum:
280 for image_checksum_ in args.image_checksum.split(","):
281 myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
283 except (KeyError, TypeError), e:
284 if str(e)=='vnf': error_pos= "missing field 'vnf'"
285 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
286 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
287 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
288 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
289 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
290 elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
291 elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
292 else: error_pos="wrong format"
293 print "Wrong VNF descriptor: " + error_pos
295 payload_req = json.dumps(myvnf)
299 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
300 logger.debug("openmano request: %s", payload_req)
301 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
302 logger.debug("openmano response: %s", mano_response.text )
304 return _print_verbose(mano_response, args.verbose)
307 #print "vnf-list",args
311 tenant = _get_tenant()
313 toshow = _get_item_uuid("vnfs", args.name, tenant)
314 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
316 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
317 mano_response = requests.get(URLrequest)
318 logger.debug("openmano response: %s", mano_response.text )
319 content = mano_response.json()
320 #print json.dumps(content, indent=4)
321 if args.verbose==None:
323 result = 0 if mano_response.status_code==200 else mano_response.status_code
324 if mano_response.status_code == 200:
326 if args.verbose >= 3:
327 print yaml.safe_dump(content, indent=4, default_flow_style=False)
329 if len(content['vnfs']) == 0:
330 print "No VNFs were found."
331 return 404 #HTTP_Not_Found
332 for vnf in content['vnfs']:
333 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
335 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
338 print " Description: %s" %vnf['description']
339 print " VNF descriptor file: %s" %vnf['path']
342 print yaml.safe_dump(content, indent=4, default_flow_style=False)
345 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
346 print " Description: %s" %vnf['description']
347 #print " VNF descriptor file: %s" %vnf['path']
349 for vm in vnf['VNFC']:
350 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
351 print " %s %s" %(vm['name'].ljust(20), vm['description'])
352 if len(vnf['nets'])>0:
353 print " Internal nets:"
354 for net in vnf['nets']:
355 print " %s %s" %(net['name'].ljust(20), net['description'])
356 if len(vnf['external-connections'])>0:
357 print " External interfaces:"
358 for interface in vnf['external-connections']:
359 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
360 interface['vpci'].ljust(14))
362 print content['error']['description']
364 print yaml.safe_dump(content, indent=4, default_flow_style=False)
367 def vnf_delete(args):
368 #print "vnf-delete",args
372 tenant = _get_tenant()
373 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
375 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
376 if not (len(r)>0 and r[0].lower()=="y"):
378 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
379 mano_response = requests.delete(URLrequest)
380 logger.debug("openmano response: %s", mano_response.text )
381 result = 0 if mano_response.status_code==200 else mano_response.status_code
382 content = mano_response.json()
383 #print json.dumps(content, indent=4)
384 if mano_response.status_code == 200:
385 print content['result']
387 print content['error']['description']
390 def scenario_create(args):
391 #print "scenario-create",args
392 tenant = _get_tenant()
393 headers_req = {'content-type': 'application/yaml'}
394 myscenario = _load_file_or_yaml(args.file)
397 myscenario['name'] = args.name
399 myscenario['description'] = args.description
400 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
404 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
405 logger.debug("openmano request: %s", payload_req)
406 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
407 logger.debug("openmano response: %s", mano_response.text )
408 return _print_verbose(mano_response, args.verbose)
410 def scenario_list(args):
411 #print "scenario-list",args
415 tenant = _get_tenant()
417 toshow = _get_item_uuid("scenarios", args.name, tenant)
418 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
420 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
421 mano_response = requests.get(URLrequest)
422 logger.debug("openmano response: %s", mano_response.text )
423 content = mano_response.json()
424 #print json.dumps(content, indent=4)
425 if args.verbose==None:
428 result = 0 if mano_response.status_code==200 else mano_response.status_code
429 if mano_response.status_code == 200:
431 if args.verbose >= 3:
432 print yaml.safe_dump(content, indent=4, default_flow_style=False)
434 if len(content['scenarios']) == 0:
435 print "No scenarios were found."
436 return 404 #HTTP_Not_Found
437 for scenario in content['scenarios']:
438 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
440 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
443 print " Description: %s" %scenario['description']
446 print yaml.safe_dump(content, indent=4, default_flow_style=False)
448 scenario = content['scenario']
449 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
451 print " Description: %s" %scenario['description']
453 for vnf in scenario['vnfs']:
454 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
455 if len(scenario['nets'])>0:
456 print " Internal nets:"
457 for net in scenario['nets']:
458 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
459 net['description'] = '-'
460 if not net['external']:
461 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
462 print " External nets:"
463 for net in scenario['nets']:
465 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
467 print content['error']['description']
469 print yaml.safe_dump(content, indent=4, default_flow_style=False)
472 def scenario_delete(args):
473 #print "scenario-delete",args
477 tenant = _get_tenant()
478 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
480 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
481 if not (len(r)>0 and r[0].lower()=="y"):
483 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
484 mano_response = requests.delete(URLrequest)
485 logger.debug("openmano response: %s", mano_response.text )
486 result = 0 if mano_response.status_code==200 else mano_response.status_code
487 content = mano_response.json()
488 #print json.dumps(content, indent=4)
489 if mano_response.status_code == 200:
490 print content['result']
492 print content['error']['description']
495 def scenario_deploy(args):
496 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
499 args.netmap_use = None
500 args.netmap_create = None
502 args.keypair_auto = None
503 return instance_create(args)
505 # #print "scenario-deploy",args
506 # headers_req = {'content-type': 'application/json'}
510 # actionCmd="reserve"
511 # action[actionCmd] = {}
512 # action[actionCmd]["instance_name"] = args.name
513 # if args.datacenter != None:
514 # action[actionCmd]["datacenter"] = args.datacenter
515 # elif mano_datacenter != None:
516 # action[actionCmd]["datacenter"] = mano_datacenter
518 # if args.description:
519 # action[actionCmd]["description"] = args.description
520 # payload_req = json.dumps(action, indent=4)
523 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
524 # logger.debug("openmano request: %s", payload_req)
525 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
526 # logger.debug("openmano response: %s", mano_response.text )
527 # if args.verbose==None:
530 # result = 0 if mano_response.status_code==200 else mano_response.status_code
531 # content = mano_response.json()
532 # #print json.dumps(content, indent=4)
533 # if args.verbose >= 3:
534 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
537 # if mano_response.status_code == 200:
538 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
539 # if args.verbose >=1:
540 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
541 # if args.verbose >=2:
542 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
545 # print "To check the status, run the following command:"
546 # print "openmano instance-scenario-list <instance_id>"
548 # print content['error']['description']
551 def scenario_verify(args):
552 #print "scenario-verify",args
553 headers_req = {'content-type': 'application/json'}
555 action["verify"] = {}
556 action["verify"]["instance_name"] = "scen-verify-return5"
557 payload_req = json.dumps(action, indent=4)
560 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
561 logger.debug("openmano request: %s", payload_req)
562 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
563 logger.debug("openmano response: %s", mano_response.text )
565 result = 0 if mano_response.status_code==200 else mano_response.status_code
566 content = mano_response.json()
567 #print json.dumps(content, indent=4)
568 if mano_response.status_code == 200:
569 print content['result']
571 print content['error']['description']
574 def instance_create(args):
575 tenant = _get_tenant()
576 headers_req = {'content-type': 'application/yaml'}
577 myInstance={"instance": {}, "schema_version": "0.1"}
579 instance_dict = _load_file_or_yaml(args.file)
580 if "instance" not in instance_dict:
581 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
583 myInstance = instance_dict
585 myInstance["instance"]['name'] = args.name
587 myInstance["instance"]['description'] = args.description
589 myInstance["instance"]['action'] = "reserve"
591 datacenter = myInstance["instance"].get("datacenter")
592 if args.datacenter != None:
593 datacenter = args.datacenter
594 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
596 scenario = myInstance["instance"].get("scenario")
597 if args.scenario != None:
598 scenario = args.scenario
600 print "you must provide a scenario in the file descriptor or with --scenario"
602 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
604 if "networks" not in myInstance["instance"]:
605 myInstance["instance"]["networks"] = {}
606 for net in args.netmap_use:
607 net_comma_list = net.split(",")
608 for net_comma in net_comma_list:
609 net_tuple = net_comma.split("=")
610 if len(net_tuple) != 2:
611 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
613 net_scenario = net_tuple[0].strip()
614 net_datacenter = net_tuple[1].strip()
615 if net_scenario not in myInstance["instance"]["networks"]:
616 myInstance["instance"]["networks"][net_scenario] = {}
617 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
618 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
619 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
620 if args.netmap_create:
621 if "networks" not in myInstance["instance"]:
622 myInstance["instance"]["networks"] = {}
623 for net in args.netmap_create:
624 net_comma_list = net.split(",")
625 for net_comma in net_comma_list:
626 net_tuple = net_comma.split("=")
627 if len(net_tuple) == 1:
628 net_scenario = net_tuple[0].strip()
629 net_datacenter = None
630 elif len(net_tuple) == 2:
631 net_scenario = net_tuple[0].strip()
632 net_datacenter = net_tuple[1].strip()
634 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
636 if net_scenario not in myInstance["instance"]["networks"]:
637 myInstance["instance"]["networks"][net_scenario] = {}
638 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
639 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
640 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
642 if "cloud-config" not in myInstance["instance"]:
643 myInstance["instance"]["cloud-config"] = {}
644 cloud_config = myInstance["instance"]["cloud-config"]
645 for key in args.keypair:
646 index = key.find(":")
648 if "key-pairs" not in cloud_config:
649 cloud_config["key-pairs"] = []
650 cloud_config["key-pairs"].append(key)
654 key_list = key_.split(",")
655 if "users" not in cloud_config:
656 cloud_config["users"] = []
657 cloud_config["users"].append({"name": user, "key-pairs": key_list })
658 if args.keypair_auto:
661 home = os.getenv("HOME")
662 user = os.getenv("USER")
663 files = os.listdir(home+'/.ssh')
665 if file[-4:] == ".pub":
666 with open(home+'/.ssh/'+file, 'r') as f:
667 keys.append(f.read())
669 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
671 except Exception as e:
672 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
675 if "cloud-config" not in myInstance["instance"]:
676 myInstance["instance"]["cloud-config"] = {}
677 cloud_config = myInstance["instance"]["cloud-config"]
678 if "key-pairs" not in cloud_config:
679 cloud_config["key-pairs"] = []
681 if "users" not in cloud_config:
682 cloud_config["users"] = []
683 cloud_config["users"].append({"name": user, "key-pairs": keys })
685 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
686 logger.debug("openmano request: %s", payload_req)
687 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
688 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
689 logger.debug("openmano response: %s", mano_response.text )
690 if args.verbose==None:
693 result = 0 if mano_response.status_code==200 else mano_response.status_code
694 content = mano_response.json()
695 #print json.dumps(content, indent=4)
696 if args.verbose >= 3:
697 print yaml.safe_dump(content, indent=4, default_flow_style=False)
700 if mano_response.status_code == 200:
701 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
703 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
705 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
708 print content['error']['description']
711 def instance_scenario_list(args):
712 #print "instance-scenario-list",args
716 tenant = _get_tenant()
718 toshow = _get_item_uuid("instances", args.name, tenant)
719 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
721 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
722 mano_response = requests.get(URLrequest)
723 logger.debug("openmano response: %s", mano_response.text )
724 content = mano_response.json()
725 #print json.dumps(content, indent=4)
726 if args.verbose==None:
729 result = 0 if mano_response.status_code==200 else mano_response.status_code
730 if mano_response.status_code == 200:
732 if args.verbose >= 3:
733 print yaml.safe_dump(content, indent=4, default_flow_style=False)
735 if len(content['instances']) == 0:
736 print "No scenario instances were found."
738 for instance in content['instances']:
739 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
741 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
744 print "Description: %s" %instance['description']
747 print yaml.safe_dump(content, indent=4, default_flow_style=False)
750 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
751 print "Description: %s" %instance['description']
752 print "Template scenario id: %s" %instance['scenario_id']
753 print "Template scenario name: %s" %instance['scenario_name']
754 print "---------------------------------------"
755 print "VNF instances: %d" %len(instance['vnfs'])
756 for vnf in instance['vnfs']:
757 #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))
758 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
759 if len(instance['nets'])>0:
760 print "---------------------------------------"
761 print "Internal nets:"
762 for net in instance['nets']:
764 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
765 print "---------------------------------------"
766 print "External nets:"
767 for net in instance['nets']:
768 if not net['created']:
769 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
770 print "---------------------------------------"
771 print "VM instances:"
772 for vnf in instance['vnfs']:
773 for vm in vnf['vms']:
774 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'])
776 print content['error']['description']
778 print yaml.safe_dump(content, indent=4, default_flow_style=False)
781 def instance_scenario_status(args):
782 print "instance-scenario-status"
785 def instance_scenario_delete(args):
789 tenant = _get_tenant()
790 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
791 #print "instance-scenario-delete",args
793 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
794 if not (len(r)>0 and r[0].lower()=="y"):
796 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
797 mano_response = requests.delete(URLrequest)
798 logger.debug("openmano response: %s", mano_response.text )
799 result = 0 if mano_response.status_code==200 else mano_response.status_code
800 content = mano_response.json()
801 #print json.dumps(content, indent=4)
802 if mano_response.status_code == 200:
803 print content['result']
805 print content['error']['description']
808 def instance_scenario_action(args):
809 #print "instance-scenario-action", args
810 tenant = _get_tenant()
811 toact = _get_item_uuid("instances", args.name, tenant=tenant)
813 action[ args.action ] = args.param
815 action["vnfs"] = args.vnf
817 action["vms"] = args.vm
819 headers_req = {'content-type': 'application/json'}
820 payload_req = json.dumps(action, indent=4)
821 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
822 logger.debug("openmano request: %s", payload_req)
823 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
824 logger.debug("openmano response: %s", mano_response.text )
825 result = 0 if mano_response.status_code==200 else mano_response.status_code
826 content = mano_response.json()
827 #print json.dumps(content, indent=4)
828 if mano_response.status_code == 200:
830 print yaml.safe_dump(content, indent=4, default_flow_style=False)
832 for uuid,c in content.iteritems():
833 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
835 print content['error']['description']
839 def instance_vnf_list(args):
840 print "instance-vnf-list"
843 def instance_vnf_status(args):
844 print "instance-vnf-status"
847 def tenant_create(args):
848 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
849 tenant_dict={"name": args.name}
850 if args.description!=None:
851 tenant_dict["description"] = args.description
852 payload_req = json.dumps( {"tenant": tenant_dict })
856 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
857 logger.debug("openmano request: %s", payload_req)
858 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
859 logger.debug("openmano response: %s", mano_response.text )
860 return _print_verbose(mano_response, args.verbose)
862 def tenant_list(args):
863 #print "tenant-list",args
865 toshow = _get_item_uuid("tenants", args.name)
866 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
868 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
869 mano_response = requests.get(URLrequest)
870 logger.debug("openmano response: %s", mano_response.text )
871 if args.verbose==None:
875 return _print_verbose(mano_response, args.verbose)
877 def tenant_delete(args):
878 #print "tenant-delete",args
879 todelete = _get_item_uuid("tenants", args.name)
881 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
882 if not (len(r)>0 and r[0].lower()=="y"):
884 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
885 mano_response = requests.delete(URLrequest)
886 logger.debug("openmano response: %s", mano_response.text )
887 result = 0 if mano_response.status_code==200 else mano_response.status_code
888 content = mano_response.json()
889 #print json.dumps(content, indent=4)
890 if mano_response.status_code == 200:
891 print content['result']
893 print content['error']['description']
896 def datacenter_attach(args):
897 tenant = _get_tenant()
898 datacenter = _get_datacenter(args.name)
899 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
902 if args.vim_tenant_id != None:
903 datacenter_dict['vim_tenant'] = args.vim_tenant_id
904 if args.vim_tenant_name != None:
905 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
906 if args.user != None:
907 datacenter_dict['vim_username'] = args.user
908 if args.password != None:
909 datacenter_dict['vim_password'] = args.password
910 if args.config!=None:
911 datacenter_dict["config"] = _load_file_or_yaml(args.config)
912 payload_req = json.dumps( {"datacenter": datacenter_dict })
916 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
917 logger.debug("openmano request: %s", payload_req)
918 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
919 logger.debug("openmano response: %s", mano_response.text )
920 result = _print_verbose(mano_response, args.verbose)
921 #provide addional information if error
922 if mano_response.status_code != 200:
923 content = mano_response.json()
924 if "already in use for 'name'" in content['error']['description'] and \
925 "to database vim_tenants table" in content['error']['description']:
926 print "Try to specify a different name with --vim-tenant-name"
929 def datacenter_detach(args):
933 tenant = _get_tenant()
934 datacenter = _get_datacenter(args.name, tenant)
935 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
936 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
937 mano_response = requests.delete(URLrequest, headers=headers_req)
938 logger.debug("openmano response: %s", mano_response.text )
939 content = mano_response.json()
940 #print json.dumps(content, indent=4)
941 result = 0 if mano_response.status_code==200 else mano_response.status_code
942 if mano_response.status_code == 200:
943 print content['result']
945 print content['error']['description']
948 def datacenter_create(args):
949 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
950 datacenter_dict={"name": args.name, "vim_url": args.url}
951 if args.description!=None:
952 datacenter_dict["description"] = args.description
954 datacenter_dict["type"] = args.type
956 datacenter_dict["vim_url_admin"] = args.url_admin
957 if args.config!=None:
958 datacenter_dict["config"] = _load_file_or_yaml(args.config)
959 payload_req = json.dumps( {"datacenter": datacenter_dict })
963 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
964 logger.debug("openmano request: %s", payload_req)
965 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
966 logger.debug("openmano response: %s", mano_response.text )
967 return _print_verbose(mano_response, args.verbose)
969 def datacenter_delete(args):
970 #print "datacenter-delete",args
971 todelete = _get_item_uuid("datacenters", args.name, "any")
973 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
974 if not (len(r)>0 and r[0].lower()=="y"):
976 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
977 mano_response = requests.delete(URLrequest)
978 logger.debug("openmano response: %s", mano_response.text )
979 result = 0 if mano_response.status_code==200 else mano_response.status_code
980 content = mano_response.json()
981 #print json.dumps(content, indent=4)
982 if mano_response.status_code == 200:
983 print content['result']
985 print content['error']['description']
988 def datacenter_list(args):
989 #print "datacenter-list",args
990 tenant='any' if args.all else _get_tenant()
993 toshow = _get_item_uuid("datacenters", args.name, tenant)
994 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
996 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
997 mano_response = requests.get(URLrequest)
998 logger.debug("openmano response: %s", mano_response.text )
999 if args.verbose==None:
1003 return _print_verbose(mano_response, args.verbose)
1005 def vim_action(args):
1006 #print "datacenter-net-action",args
1007 tenant = _get_tenant()
1008 datacenter = _get_datacenter(args.datacenter, tenant)
1009 if args.verbose==None:
1011 if args.action=="list":
1012 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1015 URLrequest += "/" + args.name
1016 mano_response = requests.get(URLrequest)
1017 logger.debug("openmano response: %s", mano_response.text )
1018 return _print_verbose(mano_response, args.verbose)
1019 elif args.action=="delete":
1020 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1021 mano_response = requests.delete(URLrequest)
1022 logger.debug("openmano response: %s", mano_response.text )
1023 result = 0 if mano_response.status_code==200 else mano_response.status_code
1024 content = mano_response.json()
1025 #print json.dumps(content, indent=4)
1026 if mano_response.status_code == 200:
1027 print content['result']
1029 print content['error']['description']
1031 elif args.action=="create":
1032 headers_req = {'content-type': 'application/yaml'}
1034 create_dict = _load_file_or_yaml(args.file)
1035 if args.item not in create_dict:
1036 create_dict = {args.item: create_dict}
1038 create_dict = {args.item:{}}
1040 create_dict[args.item]['name'] = args.name
1041 #if args.description:
1042 # create_dict[args.item]['description'] = args.description
1043 if args.item=="vim-net":
1045 create_dict[args.item]['bind_net'] = args.bind_net
1047 create_dict[args.item]['bind_type'] = args.bind_type
1049 create_dict[args.item]['shared'] = args.shared
1050 if "name" not in create_dict[args.item]:
1051 print "You must provide a name in the descriptor file or with the --name option"
1053 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1054 logger.debug("openmano request: %s", payload_req)
1055 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1056 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1057 logger.debug("openmano response: %s", mano_response.text )
1058 if args.verbose==None:
1060 return _print_verbose(mano_response, args.verbose)
1063 def datacenter_net_action(args):
1064 if args.action == "net-update":
1065 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1067 args.action = "netmap-delete"
1070 r = datacenter_netmap_action(args)
1073 args.action = "netmap-import"
1074 r = datacenter_netmap_action(args)
1077 if args.action == "net-edit":
1078 args.netmap = args.net
1080 elif args.action == "net-list":
1082 elif args.action == "net-delete":
1083 args.netmap = args.net
1086 args.action = "netmap" + args.action[3:]
1089 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1091 return datacenter_netmap_action(args)
1093 def datacenter_netmap_action(args):
1094 tenant = _get_tenant()
1095 datacenter = _get_datacenter(args.datacenter, tenant)
1096 #print "datacenter_netmap_action",args
1098 if args.verbose==None:
1100 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1101 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1103 if args.action=="netmap-list":
1105 URLrequest += "/" + args.netmap
1107 mano_response = requests.get(URLrequest)
1109 elif args.action=="netmap-delete":
1110 if args.netmap and args.all:
1111 print "you can not use a netmap name and the option --all at the same time"
1114 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1115 URLrequest += "/" + args.netmap
1117 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1119 print "you must specify a netmap name or the option --all"
1122 r = raw_input(force_text)
1123 if len(r)>0 and r[0].lower()=="y":
1127 mano_response = requests.delete(URLrequest, headers=headers_req)
1128 elif args.action=="netmap-import":
1130 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1131 if len(r)>0 and r[0].lower()=="y":
1135 URLrequest += "/upload"
1136 mano_response = requests.post(URLrequest, headers=headers_req)
1137 elif args.action=="netmap-edit" or args.action=="netmap-create":
1139 payload = _load_file_or_yaml(args.file)
1142 if "netmap" not in payload:
1143 payload = {"netmap": payload}
1145 payload["netmap"]["name"] = args.name
1147 payload["netmap"]["vim_id"] = args.vim_id
1148 if args.action=="netmap-create" and args.vim_name:
1149 payload["netmap"]["vim_name"] = args.vim_name
1150 payload_req = json.dumps(payload)
1151 logger.debug("openmano request: %s", payload_req)
1153 if args.action=="netmap-edit" and not args.force:
1154 if len(payload["netmap"]) == 0:
1155 print "You must supply some parameter to edit"
1157 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1158 if len(r)>0 and r[0].lower()=="y":
1162 URLrequest += "/" + args.netmap
1163 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1164 else: #netmap-create
1165 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1166 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1168 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1170 logger.debug("openmano response: %s", mano_response.text )
1171 return _print_verbose(mano_response, args.verbose)
1173 def element_edit(args):
1174 element = _get_item_uuid(args.element, args.name)
1175 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1176 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1177 payload=_load_file_or_yaml(args.file)
1178 if args.element[:-1] not in payload:
1179 payload = {args.element[:-1]: payload }
1180 payload_req = json.dumps(payload)
1183 if not args.force or (args.name==None and args.filer==None):
1184 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1185 if len(r)>0 and r[0].lower()=="y":
1189 logger.debug("openmano request: %s", payload_req)
1190 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1191 logger.debug("openmano response: %s", mano_response.text )
1192 if args.verbose==None:
1196 return _print_verbose(mano_response, args.verbose)
1203 if __name__=="__main__":
1205 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1206 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1207 mano_port = os.getenv('OPENMANO_PORT',"9090")
1208 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1210 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1211 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1213 subparsers = main_parser.add_subparsers(help='commands')
1215 parent_parser = argparse.ArgumentParser(add_help=False)
1216 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1217 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1219 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1220 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1221 config_parser.set_defaults(func=config)
1223 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1224 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1225 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1226 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1227 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1228 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1229 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1230 vnf_create_parser.set_defaults(func=vnf_create)
1232 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1233 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1234 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1235 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1236 vnf_list_parser.set_defaults(func=vnf_list)
1238 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1239 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1240 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1241 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1242 vnf_delete_parser.set_defaults(func=vnf_delete)
1244 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1245 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1246 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1247 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1248 scenario_create_parser.set_defaults(func=scenario_create)
1250 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1251 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1252 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1253 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1254 scenario_list_parser.set_defaults(func=scenario_list)
1256 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1257 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1258 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1259 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1260 scenario_delete_parser.set_defaults(func=scenario_delete)
1262 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1263 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1264 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1265 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1266 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1267 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1268 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1270 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1271 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1272 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1273 scenario_deploy_parser.set_defaults(func=scenario_verify)
1275 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1276 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1277 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1278 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1279 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1280 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1281 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")
1282 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")
1283 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")
1284 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")
1285 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1286 instance_scenario_create_parser.set_defaults(func=instance_create)
1288 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1289 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1290 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1291 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1293 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)")
1294 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1295 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1296 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1297 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1299 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1300 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1301 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1302 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1303 help="action to send")
1304 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1305 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1306 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1307 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1309 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1310 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1311 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1313 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1314 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1315 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1316 tenant_create_parser.set_defaults(func=tenant_create)
1318 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1319 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1320 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1321 tenant_delete_parser.set_defaults(func=tenant_delete)
1323 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1324 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1325 tenant_list_parser.set_defaults(func=tenant_list)
1327 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1328 for item in item_list:
1329 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1330 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1331 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1332 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1333 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1335 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1336 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1337 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1338 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1339 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1340 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1341 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1342 datacenter_create_parser.set_defaults(func=datacenter_create)
1344 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1345 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1346 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1347 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1349 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1350 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1351 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1352 datacenter_list_parser.set_defaults(func=datacenter_list)
1354 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1355 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1356 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1357 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1358 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1359 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1360 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1361 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1363 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1364 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1365 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1366 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1369 action_dict={'net-update': 'retrieves external networks from datacenter',
1370 'net-edit': 'edits an external network',
1371 'net-delete': 'deletes an external network',
1372 'net-list': 'lists external networks from a datacenter'
1374 for item in action_dict:
1375 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1376 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1377 if item=='net-edit' or item=='net-delete':
1378 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1379 if item=='net-edit':
1380 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1381 if item!='net-list':
1382 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1383 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1386 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1387 'netmap-create': 'create a new network senario netmap',
1388 'netmap-edit': 'edit name of a network senario netmap',
1389 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1390 'netmap-list': 'list/show network scenario netmaps'
1392 for item in action_dict:
1393 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1394 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1395 #if item=='net-add':
1396 # datacenter_action_parser.add_argument("net", help="name of the network")
1397 if item=='netmap-delete':
1398 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1399 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1400 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1401 if item=='netmap-edit':
1402 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1403 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1404 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1405 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1406 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1407 if item=='netmap-list':
1408 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1409 if item=='netmap-create':
1410 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1411 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1412 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1413 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1414 if item=='netmap-import':
1415 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1416 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1418 for item in ("network", "tenant"):
1420 commnad_name = 'vim-net'
1422 commnad_name = 'vim-'+item
1423 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1424 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1425 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1426 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1428 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1429 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1430 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1431 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1433 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1434 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1435 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1436 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1438 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1439 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1440 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>'")
1442 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1443 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1445 argcomplete.autocomplete(main_parser)
1448 args = main_parser.parse_args()
1450 level = logging.CRITICAL
1451 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1452 if "debug" in args and args.debug:
1453 level = logging.DEBUG
1454 logging.basicConfig(format=streamformat, level= level)
1455 logger = logging.getLogger('mano')
1456 logger.setLevel(level)
1457 result = args.func(args)
1460 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1461 except (requests.exceptions.ConnectionError):
1462 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1464 except (KeyboardInterrupt):
1465 print 'Exiting openmano'
1467 except (SystemExit, ArgumentParserError):
1469 except OpenmanoCLIError as e: