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.5-r489"
32 version_date="Aug 2016"
34 from argcomplete.completers import FilesCompleter
42 #from jsonschema import validate as js_v, exceptions as js_e
44 class ArgumentParserError(Exception): pass
46 class OpenmanoCLIError(Exception): pass
48 class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
69 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
70 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
71 mano_response = requests.get(URLrequest)
72 logger.debug("openmano response: %s", mano_response.text )
73 content = mano_response.json()
74 mano_tenant_name = content["tenant"]["name"]
75 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
76 mano_response = requests.get(URLrequest)
77 logger.debug("openmano response: %s", mano_response.text )
78 content = mano_response.json()
79 if "error" not in content:
80 mano_datacenter_id = content["datacenter"]["uuid"]
81 mano_datacenter_name = content["datacenter"]["name"]
82 except OpenmanoCLIError:
84 print "OPENMANO_TENANT: %s" %mano_tenant
85 print " Id: %s" %mano_tenant_id
86 print " Name: %s" %mano_tenant_name
87 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
88 print " Id: %s" %mano_datacenter_id
89 print " Name: %s" %mano_datacenter_name
91 print "OPENMANO_TENANT: %s" %mano_tenant
92 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
94 def _print_verbose(mano_response, verbose_level=0):
95 content = mano_response.json()
96 result = 0 if mano_response.status_code==200 else mano_response.status_code
97 if type(content)!=dict or len(content)!=1:
98 #print "Non expected format output"
102 val=content.values()[0]
106 elif type(val) == list:
108 elif type(val)==dict:
111 #print "Non expected dict/list format output"
116 if verbose_level==None:
118 if verbose_level >= 3:
119 print yaml.safe_dump(content, indent=4, default_flow_style=False)
122 if mano_response.status_code == 200:
123 for content in content_list:
124 if "uuid" in content:
125 uuid = content['uuid']
126 elif "id" in content:
128 elif "vim_id" in content:
129 uuid = content['vim_id']
130 myoutput = "%s %s" %(uuid.ljust(38),content['name'].ljust(20))
131 if "status" in content:
132 myoutput += " " + content['status'].ljust(20)
133 elif "enabled" in content and not content["enabled"]:
134 myoutput += " enabled=False".ljust(20)
135 if verbose_level >=1:
136 if 'created_at' in content:
137 myoutput += " " + content['created_at'].ljust(20)
138 if verbose_level >=2:
140 if 'type' in content and content['type']!=None:
141 myoutput += new_line + " Type: " + content['type'].ljust(29)
143 if 'description' in content and content['description']!=None:
144 myoutput += new_line + " Description: " + content['description'].ljust(20)
147 print content['error']['description']
150 def parser_json_yaml(file_name):
152 f = file(file_name, "r")
155 except Exception as e:
156 return (False, str(e))
159 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
161 config = yaml.load(text)
162 except yaml.YAMLError as exc:
164 if hasattr(exc, 'problem_mark'):
165 mark = exc.problem_mark
166 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
167 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
170 config = json.loads(text)
171 except Exception as e:
172 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
176 def _load_file_or_yaml(content):
178 'content' can be or a yaml/json file or a text containing a yaml/json text format
179 This function autodetect, trying to load and parse the file,
180 if fails trying to parse the 'content' text
181 Returns the dictionary once parsed, or print an error and finish the program
183 #Check config file exists
184 if os.path.isfile(content):
185 r,payload = parser_json_yaml(content)
189 elif "{" in content or ":" in content:
191 payload = yaml.load(content)
192 except yaml.YAMLError as exc:
194 if hasattr(exc, 'problem_mark'):
195 mark = exc.problem_mark
196 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
197 print "Error loading yaml/json text"+error_pos
200 print "'%s' is neither a valid file nor a yaml/json content" % content
204 def _get_item_uuid(item, item_name_id, tenant=None):
206 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
208 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
209 mano_response = requests.get(URLrequest)
210 logger.debug("openmano response: %s", mano_response.text )
211 content = mano_response.json()
214 for i in content[item]:
215 if i["uuid"] == item_name_id:
217 if i["name"] == item_name_id:
221 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
223 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
226 # def check_valid_uuid(uuid):
227 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
229 # js_v(uuid, id_schema)
231 # except js_e.ValidationError:
234 def _get_tenant(tenant_name_id = None):
235 if not tenant_name_id:
236 tenant_name_id = mano_tenant
238 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
239 return _get_item_uuid("tenants", tenant_name_id)
241 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
242 if not datacenter_name_id:
243 datacenter_name_id = mano_datacenter
244 if not datacenter_name_id:
245 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
246 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
248 def vnf_create(args):
249 #print "vnf-create",args
250 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
251 tenant = _get_tenant()
252 myvnf = _load_file_or_yaml(args.file)
254 if args.name or args.description or args.image_path:
258 myvnf['vnf']['name'] = args.name
260 myvnf['vnf']['description'] = args.description
263 for image_path_ in args.image_path.split(","):
264 #print "image-path", image_path_
265 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
267 except (KeyError, TypeError), e:
268 if str(e)=='vnf': error_pos= "missing field 'vnf'"
269 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
270 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
271 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
272 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
273 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
274 else: error_pos="wrong format"
275 print "Wrong VNF descriptor: " + error_pos
277 payload_req = json.dumps(myvnf)
281 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
282 logger.debug("openmano request: %s", payload_req)
283 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
284 logger.debug("openmano response: %s", mano_response.text )
286 return _print_verbose(mano_response, args.verbose)
289 #print "vnf-list",args
293 tenant = _get_tenant()
295 toshow = _get_item_uuid("vnfs", args.name, tenant)
296 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
298 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
299 mano_response = requests.get(URLrequest)
300 logger.debug("openmano response: %s", mano_response.text )
301 content = mano_response.json()
302 #print json.dumps(content, indent=4)
303 if args.verbose==None:
305 result = 0 if mano_response.status_code==200 else mano_response.status_code
306 if mano_response.status_code == 200:
308 if args.verbose >= 3:
309 print yaml.safe_dump(content, indent=4, default_flow_style=False)
311 if len(content['vnfs']) == 0:
312 print "No VNFs were found."
313 return 404 #HTTP_Not_Found
314 for vnf in content['vnfs']:
315 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
317 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
320 print " Description: %s" %vnf['description']
321 print " VNF descriptor file: %s" %vnf['path']
324 print yaml.safe_dump(content, indent=4, default_flow_style=False)
327 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
328 print " Description: %s" %vnf['description']
329 #print " VNF descriptor file: %s" %vnf['path']
331 for vm in vnf['VNFC']:
332 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
333 print " %s %s" %(vm['name'].ljust(20), vm['description'])
334 if len(vnf['nets'])>0:
335 print " Internal nets:"
336 for net in vnf['nets']:
337 print " %s %s" %(net['name'].ljust(20), net['description'])
338 if len(vnf['external-connections'])>0:
339 print " External interfaces:"
340 for interface in vnf['external-connections']:
341 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
342 interface['vpci'].ljust(14))
344 print content['error']['description']
346 print yaml.safe_dump(content, indent=4, default_flow_style=False)
349 def vnf_delete(args):
350 #print "vnf-delete",args
354 tenant = _get_tenant()
355 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
357 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
358 if not (len(r)>0 and r[0].lower()=="y"):
360 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
361 mano_response = requests.delete(URLrequest)
362 logger.debug("openmano response: %s", mano_response.text )
363 result = 0 if mano_response.status_code==200 else mano_response.status_code
364 content = mano_response.json()
365 #print json.dumps(content, indent=4)
366 if mano_response.status_code == 200:
367 print content['result']
369 print content['error']['description']
372 def scenario_create(args):
373 #print "scenario-create",args
374 tenant = _get_tenant()
375 headers_req = {'content-type': 'application/yaml'}
376 myscenario = _load_file_or_yaml(args.file)
379 myscenario['name'] = args.name
381 myscenario['description'] = args.description
382 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
386 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
387 logger.debug("openmano request: %s", payload_req)
388 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
389 logger.debug("openmano response: %s", mano_response.text )
390 return _print_verbose(mano_response, args.verbose)
392 def scenario_list(args):
393 #print "scenario-list",args
397 tenant = _get_tenant()
399 toshow = _get_item_uuid("scenarios", args.name, tenant)
400 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
402 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
403 mano_response = requests.get(URLrequest)
404 logger.debug("openmano response: %s", mano_response.text )
405 content = mano_response.json()
406 #print json.dumps(content, indent=4)
407 if args.verbose==None:
410 result = 0 if mano_response.status_code==200 else mano_response.status_code
411 if mano_response.status_code == 200:
413 if args.verbose >= 3:
414 print yaml.safe_dump(content, indent=4, default_flow_style=False)
416 if len(content['scenarios']) == 0:
417 print "No scenarios were found."
418 return 404 #HTTP_Not_Found
419 for scenario in content['scenarios']:
420 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
422 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
425 print " Description: %s" %scenario['description']
428 print yaml.safe_dump(content, indent=4, default_flow_style=False)
430 scenario = content['scenario']
431 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
433 print " Description: %s" %scenario['description']
435 for vnf in scenario['vnfs']:
436 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
437 if len(scenario['nets'])>0:
438 print " Internal nets:"
439 for net in scenario['nets']:
440 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
441 net['description'] = '-'
442 if not net['external']:
443 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
444 print " External nets:"
445 for net in scenario['nets']:
447 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
449 print content['error']['description']
451 print yaml.safe_dump(content, indent=4, default_flow_style=False)
454 def scenario_delete(args):
455 #print "scenario-delete",args
459 tenant = _get_tenant()
460 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
462 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
463 if not (len(r)>0 and r[0].lower()=="y"):
465 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
466 mano_response = requests.delete(URLrequest)
467 logger.debug("openmano response: %s", mano_response.text )
468 result = 0 if mano_response.status_code==200 else mano_response.status_code
469 content = mano_response.json()
470 #print json.dumps(content, indent=4)
471 if mano_response.status_code == 200:
472 print content['result']
474 print content['error']['description']
477 def scenario_deploy(args):
478 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
481 args.netmap_use = None
482 args.netmap_create = None
483 return instance_create(args)
485 # #print "scenario-deploy",args
486 # headers_req = {'content-type': 'application/json'}
490 # actionCmd="reserve"
491 # action[actionCmd] = {}
492 # action[actionCmd]["instance_name"] = args.name
493 # if args.datacenter != None:
494 # action[actionCmd]["datacenter"] = args.datacenter
495 # elif mano_datacenter != None:
496 # action[actionCmd]["datacenter"] = mano_datacenter
498 # if args.description:
499 # action[actionCmd]["description"] = args.description
500 # payload_req = json.dumps(action, indent=4)
503 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
504 # logger.debug("openmano request: %s", payload_req)
505 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
506 # logger.debug("openmano response: %s", mano_response.text )
507 # if args.verbose==None:
510 # result = 0 if mano_response.status_code==200 else mano_response.status_code
511 # content = mano_response.json()
512 # #print json.dumps(content, indent=4)
513 # if args.verbose >= 3:
514 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
517 # if mano_response.status_code == 200:
518 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
519 # if args.verbose >=1:
520 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
521 # if args.verbose >=2:
522 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
525 # print "To check the status, run the following command:"
526 # print "openmano instance-scenario-list <instance_id>"
528 # print content['error']['description']
531 def scenario_verify(args):
532 #print "scenario-verify",args
533 headers_req = {'content-type': 'application/json'}
535 action["verify"] = {}
536 action["verify"]["instance_name"] = "scen-verify-return5"
537 payload_req = json.dumps(action, indent=4)
540 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
541 logger.debug("openmano request: %s", payload_req)
542 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
543 logger.debug("openmano response: %s", mano_response.text )
545 result = 0 if mano_response.status_code==200 else mano_response.status_code
546 content = mano_response.json()
547 #print json.dumps(content, indent=4)
548 if mano_response.status_code == 200:
549 print content['result']
551 print content['error']['description']
554 def instance_create(args):
555 tenant = _get_tenant()
556 headers_req = {'content-type': 'application/yaml'}
557 myInstance={"instance": {}, "schema_version": "0.1"}
559 instance_dict = _load_file_or_yaml(args.file)
560 if "instance" not in instance_dict:
561 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
563 myInstance = instance_dict
565 myInstance["instance"]['name'] = args.name
567 myInstance["instance"]['description'] = args.description
569 myInstance["instance"]['action'] = "reserve"
571 datacenter = myInstance["instance"].get("datacenter")
572 if args.datacenter != None:
573 datacenter = args.datacenter
574 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
576 scenario = myInstance["instance"].get("scenario")
577 if args.scenario != None:
578 scenario = args.scenario
580 print "you must provide an scenario in the file descriptor or with --scenario"
582 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
584 if "networks" not in myInstance["instance"]:
585 myInstance["instance"]["networks"] = {}
586 for net in args.netmap_use:
587 net_comma_list = net.split(",")
588 for net_comma in net_comma_list:
589 net_tuple = net_comma.split("=")
590 if len(net_tuple) != 2:
591 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
593 net_scenario = net_tuple[0].strip()
594 net_datacenter = net_tuple[1].strip()
595 if net_scenario not in myInstance["instance"]["networks"]:
596 myInstance["instance"]["networks"][net_scenario] = {}
597 myInstance["instance"]["networks"][net_scenario]["netmap-use"] = net_datacenter
598 if args.netmap_create:
599 if "networks" not in myInstance["instance"]:
600 myInstance["instance"]["networks"] = {}
601 for net in args.netmap_create:
602 net_comma_list = net.split(",")
603 for net_comma in net_comma_list:
604 net_tuple = net_comma.split("=")
605 if len(net_tuple) == 1:
606 net_scenario = net_tuple[0].strip()
607 net_datacenter = None
608 elif len(net_tuple) == 2:
609 net_scenario = net_tuple[0].strip()
610 net_datacenter = net_tuple[1].strip()
612 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
614 if net_scenario not in myInstance["instance"]["networks"]:
615 myInstance["instance"]["networks"][net_scenario] = {}
616 myInstance["instance"]["networks"][net_scenario]["netmap-create"] = net_datacenter
618 if "cloud-config" not in myInstance["instance"]:
619 myInstance["instance"]["cloud-config"] = {}
620 cloud_config = myInstance["instance"]["cloud-config"]
621 for key in args.keypair:
622 index = key.find(":")
624 if "key-pairs" not in cloud_config:
625 cloud_config["key-pairs"] = []
626 cloud_config["key-pairs"].append(key)
630 key_list = key_.split(",")
631 if "users" not in cloud_config:
632 cloud_config["users"] = []
633 cloud_config["users"].append({"name": user, "key-pairs": key_list })
634 if args.keypair_auto:
637 home = os.getenv("HOME")
638 user = os.getenv("USER")
639 files = os.listdir(home+'/.ssh')
641 if file[-4:] == ".pub":
642 with open(home+'/.ssh/'+file, 'r') as f:
643 keys.append(f.read())
645 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
647 except Exception as e:
648 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
651 if "cloud-config" not in myInstance["instance"]:
652 myInstance["instance"]["cloud-config"] = {}
653 cloud_config = myInstance["instance"]["cloud-config"]
654 if "key-pairs" not in cloud_config:
655 cloud_config["key-pairs"] = []
657 if "users" not in cloud_config:
658 cloud_config["users"] = []
659 cloud_config["users"].append({"name": user, "key-pairs": keys })
661 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
662 logger.debug("openmano request: %s", payload_req)
663 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
664 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
665 logger.debug("openmano response: %s", mano_response.text )
666 if args.verbose==None:
669 result = 0 if mano_response.status_code==200 else mano_response.status_code
670 content = mano_response.json()
671 #print json.dumps(content, indent=4)
672 if args.verbose >= 3:
673 print yaml.safe_dump(content, indent=4, default_flow_style=False)
676 if mano_response.status_code == 200:
677 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
679 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
681 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
684 print content['error']['description']
687 def instance_scenario_list(args):
688 #print "instance-scenario-list",args
692 tenant = _get_tenant()
694 toshow = _get_item_uuid("instances", args.name, tenant)
695 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
697 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
698 mano_response = requests.get(URLrequest)
699 logger.debug("openmano response: %s", mano_response.text )
700 content = mano_response.json()
701 #print json.dumps(content, indent=4)
702 if args.verbose==None:
705 result = 0 if mano_response.status_code==200 else mano_response.status_code
706 if mano_response.status_code == 200:
708 if args.verbose >= 3:
709 print yaml.safe_dump(content, indent=4, default_flow_style=False)
711 if len(content['instances']) == 0:
712 print "No scenario instances were found."
714 for instance in content['instances']:
715 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
717 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
720 print "Description: %s" %instance['description']
723 print yaml.safe_dump(content, indent=4, default_flow_style=False)
726 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
727 print "Description: %s" %instance['description']
728 print "Template scenario id: %s" %instance['scenario_id']
729 print "Template scenario name: %s" %instance['scenario_name']
730 print "---------------------------------------"
731 print "VNF instances: %d" %len(instance['vnfs'])
732 for vnf in instance['vnfs']:
733 #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))
734 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
735 if len(instance['nets'])>0:
736 print "---------------------------------------"
737 print "Internal nets:"
738 for net in instance['nets']:
739 if not net['external']:
740 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
741 print "---------------------------------------"
742 print "External nets:"
743 for net in instance['nets']:
745 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
746 print "---------------------------------------"
747 print "VM instances:"
748 for vnf in instance['vnfs']:
749 for vm in vnf['vms']:
750 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'])
752 print content['error']['description']
754 print yaml.safe_dump(content, indent=4, default_flow_style=False)
757 def instance_scenario_status(args):
758 print "instance-scenario-status"
761 def instance_scenario_delete(args):
765 tenant = _get_tenant()
766 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
767 #print "instance-scenario-delete",args
769 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
770 if not (len(r)>0 and r[0].lower()=="y"):
772 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
773 mano_response = requests.delete(URLrequest)
774 logger.debug("openmano response: %s", mano_response.text )
775 result = 0 if mano_response.status_code==200 else mano_response.status_code
776 content = mano_response.json()
777 #print json.dumps(content, indent=4)
778 if mano_response.status_code == 200:
779 print content['result']
781 print content['error']['description']
784 def instance_scenario_action(args):
785 #print "instance-scenario-action", args
786 tenant = _get_tenant()
787 toact = _get_item_uuid("instances", args.name, tenant=tenant)
789 action[ args.action ] = args.param
791 action["vnfs"] = args.vnf
793 action["vms"] = args.vm
795 headers_req = {'content-type': 'application/json'}
796 payload_req = json.dumps(action, indent=4)
797 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
798 logger.debug("openmano request: %s", payload_req)
799 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
800 logger.debug("openmano response: %s", mano_response.text )
801 result = 0 if mano_response.status_code==200 else mano_response.status_code
802 content = mano_response.json()
803 #print json.dumps(content, indent=4)
804 if mano_response.status_code == 200:
806 print yaml.safe_dump(content, indent=4, default_flow_style=False)
808 for uuid,c in content.iteritems():
809 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
811 print content['error']['description']
815 def instance_vnf_list(args):
816 print "instance-vnf-list"
819 def instance_vnf_status(args):
820 print "instance-vnf-status"
823 def tenant_create(args):
824 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
825 tenant_dict={"name": args.name}
826 if args.description!=None:
827 tenant_dict["description"] = args.description
828 payload_req = json.dumps( {"tenant": tenant_dict })
832 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
833 logger.debug("openmano request: %s", payload_req)
834 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
835 logger.debug("openmano response: %s", mano_response.text )
836 return _print_verbose(mano_response, args.verbose)
838 def tenant_list(args):
839 #print "tenant-list",args
841 toshow = _get_item_uuid("tenants", args.name)
842 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
844 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
845 mano_response = requests.get(URLrequest)
846 logger.debug("openmano response: %s", mano_response.text )
847 if args.verbose==None:
851 return _print_verbose(mano_response, args.verbose)
853 def tenant_delete(args):
854 #print "tenant-delete",args
855 todelete = _get_item_uuid("tenants", args.name)
857 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
858 if not (len(r)>0 and r[0].lower()=="y"):
860 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
861 mano_response = requests.delete(URLrequest)
862 logger.debug("openmano response: %s", mano_response.text )
863 result = 0 if mano_response.status_code==200 else mano_response.status_code
864 content = mano_response.json()
865 #print json.dumps(content, indent=4)
866 if mano_response.status_code == 200:
867 print content['result']
869 print content['error']['description']
872 def datacenter_attach(args):
873 tenant = _get_tenant()
874 datacenter = _get_datacenter(args.name)
875 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
878 if args.vim_tenant_id != None:
879 datacenter_dict['vim_tenant'] = args.vim_tenant_id
880 if args.vim_tenant_name != None:
881 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
882 if args.user != None:
883 datacenter_dict['vim_username'] = args.user
884 if args.password != None:
885 datacenter_dict['vim_password'] = args.password
886 payload_req = json.dumps( {"datacenter": datacenter_dict })
890 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
891 logger.debug("openmano request: %s", payload_req)
892 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
893 logger.debug("openmano response: %s", mano_response.text )
894 result = _print_verbose(mano_response, args.verbose)
895 #provide addional information if error
896 if mano_response.status_code != 200:
897 content = mano_response.json()
898 if "already in use for 'name'" in content['error']['description'] and \
899 "to database vim_tenants table" in content['error']['description']:
900 print "Try to specify a different name with --vim-tenant-name"
903 def datacenter_detach(args):
907 tenant = _get_tenant()
908 datacenter = _get_datacenter(args.name, tenant)
909 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
910 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
911 mano_response = requests.delete(URLrequest, headers=headers_req)
912 logger.debug("openmano response: %s", mano_response.text )
913 content = mano_response.json()
914 #print json.dumps(content, indent=4)
915 result = 0 if mano_response.status_code==200 else mano_response.status_code
916 if mano_response.status_code == 200:
917 print content['result']
919 print content['error']['description']
922 def datacenter_create(args):
923 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
924 datacenter_dict={"name": args.name, "vim_url": args.url}
925 if args.description!=None:
926 datacenter_dict["description"] = args.description
928 datacenter_dict["type"] = args.type
930 datacenter_dict["vim_url_admin"] = args.url_admin
931 if args.config!=None:
932 datacenter_dict["config"] = _load_file_or_yaml(args.config)
933 payload_req = json.dumps( {"datacenter": datacenter_dict })
937 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
938 logger.debug("openmano request: %s", payload_req)
939 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
940 logger.debug("openmano response: %s", mano_response.text )
941 return _print_verbose(mano_response, args.verbose)
943 def datacenter_delete(args):
944 #print "datacenter-delete",args
945 todelete = _get_item_uuid("datacenters", args.name, "any")
947 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
948 if not (len(r)>0 and r[0].lower()=="y"):
950 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
951 mano_response = requests.delete(URLrequest)
952 logger.debug("openmano response: %s", mano_response.text )
953 result = 0 if mano_response.status_code==200 else mano_response.status_code
954 content = mano_response.json()
955 #print json.dumps(content, indent=4)
956 if mano_response.status_code == 200:
957 print content['result']
959 print content['error']['description']
962 def datacenter_list(args):
963 #print "datacenter-list",args
964 tenant='any' if args.all else _get_tenant()
967 toshow = _get_item_uuid("datacenters", args.name, tenant)
968 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
970 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
971 mano_response = requests.get(URLrequest)
972 logger.debug("openmano response: %s", mano_response.text )
973 if args.verbose==None:
977 return _print_verbose(mano_response, args.verbose)
979 def vim_action(args):
980 #print "datacenter-net-action",args
981 tenant = _get_tenant()
982 datacenter = _get_datacenter(args.datacenter, tenant)
983 if args.verbose==None:
985 if args.action=="list":
986 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
989 URLrequest += "/" + args.name
990 mano_response = requests.get(URLrequest)
991 logger.debug("openmano response: %s", mano_response.text )
992 return _print_verbose(mano_response, args.verbose)
993 elif args.action=="delete":
994 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
995 mano_response = requests.delete(URLrequest)
996 logger.debug("openmano response: %s", mano_response.text )
997 result = 0 if mano_response.status_code==200 else mano_response.status_code
998 content = mano_response.json()
999 #print json.dumps(content, indent=4)
1000 if mano_response.status_code == 200:
1001 print content['result']
1003 print content['error']['description']
1005 elif args.action=="create":
1006 headers_req = {'content-type': 'application/yaml'}
1008 create_dict = _load_file_or_yaml(args.file)
1009 if args.item not in create_dict:
1010 create_dict = {args.item: create_dict}
1012 create_dict = {args.item:{}}
1014 create_dict[args.item]['name'] = args.name
1015 #if args.description:
1016 # create_dict[args.item]['description'] = args.description
1017 if args.item=="vim-net":
1019 create_dict[args.item]['bind_net'] = args.bind_net
1021 create_dict[args.item]['bind_type'] = args.bind_type
1023 create_dict[args.item]['shared'] = args.shared
1024 if "name" not in create_dict[args.item]:
1025 print "You must provide a name in the descriptor file or with the --name option"
1027 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1028 logger.debug("openmano request: %s", payload_req)
1029 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1030 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1031 logger.debug("openmano response: %s", mano_response.text )
1032 if args.verbose==None:
1034 return _print_verbose(mano_response, args.verbose)
1037 def datacenter_net_action(args):
1038 if args.action == "net-update":
1039 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1041 args.action = "netmap-delete"
1044 r = datacenter_netmap_action(args)
1047 args.action = "netmap-import"
1048 r = datacenter_netmap_action(args)
1051 if args.action == "net-edit":
1052 args.netmap = args.net
1054 elif args.action == "net-list":
1056 elif args.action == "net-delete":
1057 args.netmap = args.net
1060 args.action = "netmap" + args.action[3:]
1063 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1065 return datacenter_netmap_action(args)
1067 def datacenter_netmap_action(args):
1068 tenant = _get_tenant()
1069 datacenter = _get_datacenter(args.datacenter, tenant)
1070 #print "datacenter_netmap_action",args
1072 if args.verbose==None:
1074 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1075 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1077 if args.action=="netmap-list":
1079 URLrequest += "/" + args.netmap
1081 mano_response = requests.get(URLrequest)
1083 elif args.action=="netmap-delete":
1084 if args.netmap and args.all:
1085 print "you can not use a netmap name and the option --all at the same time"
1088 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1089 URLrequest += "/" + args.netmap
1091 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1093 print "you must specify a netmap name or the option --all"
1096 r = raw_input(force_text)
1097 if len(r)>0 and r[0].lower()=="y":
1101 mano_response = requests.delete(URLrequest, headers=headers_req)
1102 elif args.action=="netmap-import":
1104 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1105 if len(r)>0 and r[0].lower()=="y":
1109 URLrequest += "/upload"
1110 mano_response = requests.post(URLrequest, headers=headers_req)
1111 elif args.action=="netmap-edit" or args.action=="netmap-create":
1113 payload = _load_file_or_yaml(args.file)
1116 if "netmap" not in payload:
1117 payload = {"netmap": payload}
1119 payload["netmap"]["name"] = args.name
1121 payload["netmap"]["vim_id"] = args.vim_id
1122 if args.action=="netmap-create" and args.vim_name:
1123 payload["netmap"]["vim_name"] = args.vim_name
1124 payload_req = json.dumps(payload)
1125 logger.debug("openmano request: %s", payload_req)
1127 if args.action=="netmap-edit" and not args.force:
1128 if len(payload["netmap"]) == 0:
1129 print "You must supply some parameter to edit"
1131 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1132 if len(r)>0 and r[0].lower()=="y":
1136 URLrequest += "/" + args.netmap
1137 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1138 else: #netmap-create
1139 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1140 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1142 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1144 logger.debug("openmano response: %s", mano_response.text )
1145 return _print_verbose(mano_response, args.verbose)
1147 def element_edit(args):
1148 element = _get_item_uuid(args.element, args.name)
1149 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1150 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1151 payload=_load_file_or_yaml(args.file)
1152 if args.element[:-1] not in payload:
1153 payload = {args.element[:-1]: payload }
1154 payload_req = json.dumps(payload)
1157 if not args.force or (args.name==None and args.filer==None):
1158 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1159 if len(r)>0 and r[0].lower()=="y":
1163 logger.debug("openmano request: %s", payload_req)
1164 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1165 logger.debug("openmano response: %s", mano_response.text )
1166 if args.verbose==None:
1170 return _print_verbose(mano_response, args.verbose)
1177 if __name__=="__main__":
1179 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1180 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1181 mano_port = os.getenv('OPENMANO_PORT',"9090")
1182 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1184 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1185 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1187 subparsers = main_parser.add_subparsers(help='commands')
1189 parent_parser = argparse.ArgumentParser(add_help=False)
1190 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1191 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1193 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1194 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1195 config_parser.set_defaults(func=config)
1197 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1198 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1199 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1200 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1201 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1202 vnf_create_parser.set_defaults(func=vnf_create)
1204 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1205 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1206 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1207 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1208 vnf_list_parser.set_defaults(func=vnf_list)
1210 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1211 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1212 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1213 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1214 vnf_delete_parser.set_defaults(func=vnf_delete)
1216 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1217 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1218 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1219 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1220 scenario_create_parser.set_defaults(func=scenario_create)
1222 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1223 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1224 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1225 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1226 scenario_list_parser.set_defaults(func=scenario_list)
1228 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1229 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1230 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1231 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1232 scenario_delete_parser.set_defaults(func=scenario_delete)
1234 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1235 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1236 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1237 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1238 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1239 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1240 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1242 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1243 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1244 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1245 scenario_deploy_parser.set_defaults(func=scenario_verify)
1247 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1248 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1249 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1250 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1251 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1252 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1253 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")
1254 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")
1255 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")
1256 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")
1257 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1258 instance_scenario_create_parser.set_defaults(func=instance_create)
1260 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1261 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1262 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1263 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1265 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)")
1266 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1267 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1268 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1269 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1271 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1272 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1273 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1274 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1275 help="action to send")
1276 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1277 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1278 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1279 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1281 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1282 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1283 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1285 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1286 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1287 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1288 tenant_create_parser.set_defaults(func=tenant_create)
1290 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1291 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1292 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1293 tenant_delete_parser.set_defaults(func=tenant_delete)
1295 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1296 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1297 tenant_list_parser.set_defaults(func=tenant_list)
1299 item_list=('tenant','datacenter') #put tenant before so that help appear in order
1300 for item in item_list:
1301 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1302 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1303 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1304 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1305 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1307 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1308 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1309 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1310 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1311 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1312 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1313 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1314 datacenter_create_parser.set_defaults(func=datacenter_create)
1316 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1317 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1318 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1319 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1321 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1322 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1323 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1324 datacenter_list_parser.set_defaults(func=datacenter_list)
1326 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1327 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1328 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1329 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1330 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1331 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1332 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1334 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1335 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1336 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1337 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1340 action_dict={'net-update': 'retrieves external networks from datacenter',
1341 'net-edit': 'edits an external network',
1342 'net-delete': 'deletes an external network',
1343 'net-list': 'lists external networks from a datacenter'
1345 for item in action_dict:
1346 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1347 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1348 if item=='net-edit' or item=='net-delete':
1349 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1350 if item=='net-edit':
1351 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1352 if item!='net-list':
1353 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1354 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1357 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1358 'netmap-create': 'create a new network senario netmap',
1359 'netmap-edit': 'edit name of a network senario netmap',
1360 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1361 'netmap-list': 'list/show network scenario netmaps'
1363 for item in action_dict:
1364 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1365 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1366 #if item=='net-add':
1367 # datacenter_action_parser.add_argument("net", help="name of the network")
1368 if item=='netmap-delete':
1369 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1370 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1371 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1372 if item=='netmap-edit':
1373 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1374 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1375 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1376 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1377 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1378 if item=='netmap-list':
1379 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1380 if item=='netmap-create':
1381 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1382 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1383 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1384 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1385 if item=='netmap-import':
1386 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1387 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1389 for item in ("network", "tenant"):
1391 commnad_name = 'vim-net'
1393 commnad_name = 'vim-'+item
1394 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1395 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1396 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1397 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1399 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1400 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1401 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1402 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1404 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1405 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1406 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1407 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1409 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1410 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1411 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>'")
1413 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1414 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1416 argcomplete.autocomplete(main_parser)
1419 args = main_parser.parse_args()
1421 level = logging.CRITICAL
1422 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1423 if "debug" in args and args.debug:
1424 level = logging.DEBUG
1425 logging.basicConfig(format=streamformat, level= level)
1426 logger = logging.getLogger('mano')
1427 logger.setLevel(level)
1428 result = args.func(args)
1431 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1432 except (requests.exceptions.ConnectionError):
1433 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1435 except (KeyboardInterrupt):
1436 print 'Exiting openmano'
1438 except (SystemExit, ArgumentParserError):
1440 except OpenmanoCLIError as e: