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, Pablo Montes"
30 __date__ ="$09-oct-2014 09:09:48$"
31 __version__="0.4.13-r519"
32 version_date="Mar 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:
124 for content in content_list:
125 if "uuid" in content:
126 uuid = content['uuid']
127 elif "id" in content:
129 elif "vim_id" in content:
130 uuid = content['vim_id']
131 name = content.get('name');
136 myoutput = "%s %s" %(uuid.ljust(38),name.ljust(20))
137 if content.get("status"):
138 myoutput += " " + content['status'].ljust(20)
139 elif "enabled" in content and not content["enabled"]:
140 myoutput += " enabled=False".ljust(20)
141 if verbose_level >=1:
142 if content.get('created_at'):
143 myoutput += " " + content['created_at'].ljust(20)
144 if verbose_level >=2:
146 if content.get('type'):
147 myoutput += new_line + " Type: " + content['type'].ljust(29)
149 if content.get('description'):
150 myoutput += new_line + " Description: " + content['description'].ljust(20)
153 print content['error']['description']
156 def parser_json_yaml(file_name):
158 f = file(file_name, "r")
161 except Exception as e:
162 return (False, str(e))
165 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
167 config = yaml.load(text)
168 except yaml.YAMLError as exc:
170 if hasattr(exc, 'problem_mark'):
171 mark = exc.problem_mark
172 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
173 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
176 config = json.loads(text)
177 except Exception as e:
178 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
182 def _load_file_or_yaml(content):
184 'content' can be or a yaml/json file or a text containing a yaml/json text format
185 This function autodetect, trying to load and parse the file,
186 if fails trying to parse the 'content' text
187 Returns the dictionary once parsed, or print an error and finish the program
189 #Check config file exists
190 if os.path.isfile(content):
191 r,payload = parser_json_yaml(content)
195 elif "{" in content or ":" in content:
197 payload = yaml.load(content)
198 except yaml.YAMLError as exc:
200 if hasattr(exc, 'problem_mark'):
201 mark = exc.problem_mark
202 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
203 print "Error loading yaml/json text"+error_pos
206 print "'%s' is neither a valid file nor a yaml/json content" % content
210 def _get_item_uuid(item, item_name_id, tenant=None):
212 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
214 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
215 mano_response = requests.get(URLrequest)
216 logger.debug("openmano response: %s", mano_response.text )
217 content = mano_response.json()
220 for i in content[item]:
221 if i["uuid"] == item_name_id:
223 if i["name"] == item_name_id:
227 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
229 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
232 # def check_valid_uuid(uuid):
233 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
235 # js_v(uuid, id_schema)
237 # except js_e.ValidationError:
240 def _get_tenant(tenant_name_id = None):
241 if not tenant_name_id:
242 tenant_name_id = mano_tenant
244 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
245 return _get_item_uuid("tenants", tenant_name_id)
247 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
248 if not datacenter_name_id:
249 datacenter_name_id = mano_datacenter
250 if not datacenter_name_id:
251 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
252 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
254 def vnf_create(args):
255 #print "vnf-create",args
256 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
257 tenant = _get_tenant()
258 myvnf = _load_file_or_yaml(args.file)
260 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
264 myvnf['vnf']['name'] = args.name
266 myvnf['vnf']['description'] = args.description
269 for image_path_ in args.image_path.split(","):
270 #print "image-path", image_path_
271 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
272 if "image name" in myvnf['vnf']['VNFC'][index]:
273 del myvnf['vnf']['VNFC'][index]["image name"]
274 if "image checksum" in myvnf['vnf']['VNFC'][index]:
275 del myvnf['vnf']['VNFC'][index]["image checksum"]
277 if args.image_name: #image name precedes if both are supplied
279 for image_name_ in args.image_name.split(","):
280 myvnf['vnf']['VNFC'][index]['image name']=image_name_
281 if "VNFC image" in myvnf['vnf']['VNFC'][index]:
282 del myvnf['vnf']['VNFC'][index]["VNFC image"]
284 if args.image_checksum:
286 for image_checksum_ in args.image_checksum.split(","):
287 myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
289 except (KeyError, TypeError), e:
290 if str(e)=='vnf': error_pos= "missing field 'vnf'"
291 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
292 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
293 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
294 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
295 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
296 elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
297 elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
298 else: error_pos="wrong format"
299 print "Wrong VNF descriptor: " + error_pos
301 payload_req = json.dumps(myvnf)
305 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
306 logger.debug("openmano request: %s", payload_req)
307 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
308 logger.debug("openmano response: %s", mano_response.text )
310 return _print_verbose(mano_response, args.verbose)
313 #print "vnf-list",args
317 tenant = _get_tenant()
319 toshow = _get_item_uuid("vnfs", args.name, tenant)
320 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
322 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
323 mano_response = requests.get(URLrequest)
324 logger.debug("openmano response: %s", mano_response.text )
325 content = mano_response.json()
326 #print json.dumps(content, indent=4)
327 if args.verbose==None:
329 result = 0 if mano_response.status_code==200 else mano_response.status_code
330 if mano_response.status_code == 200:
332 if args.verbose >= 3:
333 print yaml.safe_dump(content, indent=4, default_flow_style=False)
335 if len(content['vnfs']) == 0:
336 print "No VNFs were found."
337 return 404 #HTTP_Not_Found
338 for vnf in content['vnfs']:
339 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
341 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
344 print " Description: %s" %vnf['description']
345 print " VNF descriptor file: %s" %vnf['path']
348 print yaml.safe_dump(content, indent=4, default_flow_style=False)
351 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
352 print " Description: %s" %vnf['description']
353 #print " VNF descriptor file: %s" %vnf['path']
355 for vm in vnf['VNFC']:
356 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
357 print " %s %s" %(vm['name'].ljust(20), vm['description'])
358 if len(vnf['nets'])>0:
359 print " Internal nets:"
360 for net in vnf['nets']:
361 print " %s %s" %(net['name'].ljust(20), net['description'])
362 if len(vnf['external-connections'])>0:
363 print " External interfaces:"
364 for interface in vnf['external-connections']:
365 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
366 interface.get('vpci',"").ljust(14))
368 print content['error']['description']
370 print yaml.safe_dump(content, indent=4, default_flow_style=False)
373 def vnf_delete(args):
374 #print "vnf-delete",args
378 tenant = _get_tenant()
379 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
381 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
382 if not (len(r)>0 and r[0].lower()=="y"):
384 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
385 mano_response = requests.delete(URLrequest)
386 logger.debug("openmano response: %s", mano_response.text )
387 result = 0 if mano_response.status_code==200 else mano_response.status_code
388 content = mano_response.json()
389 #print json.dumps(content, indent=4)
390 if mano_response.status_code == 200:
391 print content['result']
393 print content['error']['description']
396 def scenario_create(args):
397 #print "scenario-create",args
398 tenant = _get_tenant()
399 headers_req = {'content-type': 'application/yaml'}
400 myscenario = _load_file_or_yaml(args.file)
403 myscenario['name'] = args.name
405 myscenario['description'] = args.description
406 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
410 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
411 logger.debug("openmano request: %s", payload_req)
412 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
413 logger.debug("openmano response: %s", mano_response.text )
414 return _print_verbose(mano_response, args.verbose)
416 def scenario_list(args):
417 #print "scenario-list",args
421 tenant = _get_tenant()
423 toshow = _get_item_uuid("scenarios", args.name, tenant)
424 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
426 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
427 mano_response = requests.get(URLrequest)
428 logger.debug("openmano response: %s", mano_response.text )
429 content = mano_response.json()
430 #print json.dumps(content, indent=4)
431 if args.verbose==None:
434 result = 0 if mano_response.status_code==200 else mano_response.status_code
435 if mano_response.status_code == 200:
437 if args.verbose >= 3:
438 print yaml.safe_dump(content, indent=4, default_flow_style=False)
440 if len(content['scenarios']) == 0:
441 print "No scenarios were found."
442 return 404 #HTTP_Not_Found
443 for scenario in content['scenarios']:
444 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
446 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
449 print " Description: %s" %scenario['description']
452 print yaml.safe_dump(content, indent=4, default_flow_style=False)
454 scenario = content['scenario']
455 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
457 print " Description: %s" %scenario['description']
459 for vnf in scenario['vnfs']:
460 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
461 if len(scenario['nets'])>0:
462 print " Internal nets:"
463 for net in scenario['nets']:
464 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
465 net['description'] = '-'
466 if not net['external']:
467 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
468 print " External nets:"
469 for net in scenario['nets']:
471 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
473 print content['error']['description']
475 print yaml.safe_dump(content, indent=4, default_flow_style=False)
478 def scenario_delete(args):
479 #print "scenario-delete",args
483 tenant = _get_tenant()
484 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
486 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
487 if not (len(r)>0 and r[0].lower()=="y"):
489 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
490 mano_response = requests.delete(URLrequest)
491 logger.debug("openmano response: %s", mano_response.text )
492 result = 0 if mano_response.status_code==200 else mano_response.status_code
493 content = mano_response.json()
494 #print json.dumps(content, indent=4)
495 if mano_response.status_code == 200:
496 print content['result']
498 print content['error']['description']
501 def scenario_deploy(args):
502 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
505 args.netmap_use = None
506 args.netmap_create = None
508 args.keypair_auto = None
509 return instance_create(args)
511 # #print "scenario-deploy",args
512 # headers_req = {'content-type': 'application/json'}
516 # actionCmd="reserve"
517 # action[actionCmd] = {}
518 # action[actionCmd]["instance_name"] = args.name
519 # if args.datacenter != None:
520 # action[actionCmd]["datacenter"] = args.datacenter
521 # elif mano_datacenter != None:
522 # action[actionCmd]["datacenter"] = mano_datacenter
524 # if args.description:
525 # action[actionCmd]["description"] = args.description
526 # payload_req = json.dumps(action, indent=4)
529 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
530 # logger.debug("openmano request: %s", payload_req)
531 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
532 # logger.debug("openmano response: %s", mano_response.text )
533 # if args.verbose==None:
536 # result = 0 if mano_response.status_code==200 else mano_response.status_code
537 # content = mano_response.json()
538 # #print json.dumps(content, indent=4)
539 # if args.verbose >= 3:
540 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
543 # if mano_response.status_code == 200:
544 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
545 # if args.verbose >=1:
546 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
547 # if args.verbose >=2:
548 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
551 # print "To check the status, run the following command:"
552 # print "openmano instance-scenario-list <instance_id>"
554 # print content['error']['description']
557 def scenario_verify(args):
558 #print "scenario-verify",args
559 headers_req = {'content-type': 'application/json'}
561 action["verify"] = {}
562 action["verify"]["instance_name"] = "scen-verify-return5"
563 payload_req = json.dumps(action, indent=4)
566 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
567 logger.debug("openmano request: %s", payload_req)
568 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
569 logger.debug("openmano response: %s", mano_response.text )
571 result = 0 if mano_response.status_code==200 else mano_response.status_code
572 content = mano_response.json()
573 #print json.dumps(content, indent=4)
574 if mano_response.status_code == 200:
575 print content['result']
577 print content['error']['description']
580 def instance_create(args):
581 tenant = _get_tenant()
582 headers_req = {'content-type': 'application/yaml'}
583 myInstance={"instance": {}, "schema_version": "0.1"}
585 instance_dict = _load_file_or_yaml(args.file)
586 if "instance" not in instance_dict:
587 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
589 myInstance = instance_dict
591 myInstance["instance"]['name'] = args.name
593 myInstance["instance"]['description'] = args.description
595 myInstance["instance"]['action'] = "reserve"
597 datacenter = myInstance["instance"].get("datacenter")
598 if args.datacenter != None:
599 datacenter = args.datacenter
600 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
602 scenario = myInstance["instance"].get("scenario")
603 if args.scenario != None:
604 scenario = args.scenario
606 print "you must provide a scenario in the file descriptor or with --scenario"
608 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
610 if "networks" not in myInstance["instance"]:
611 myInstance["instance"]["networks"] = {}
612 for net in args.netmap_use:
613 net_comma_list = net.split(",")
614 for net_comma in net_comma_list:
615 net_tuple = net_comma.split("=")
616 if len(net_tuple) != 2:
617 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
619 net_scenario = net_tuple[0].strip()
620 net_datacenter = net_tuple[1].strip()
621 if net_scenario not in myInstance["instance"]["networks"]:
622 myInstance["instance"]["networks"][net_scenario] = {}
623 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
624 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
625 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
626 if args.netmap_create:
627 if "networks" not in myInstance["instance"]:
628 myInstance["instance"]["networks"] = {}
629 for net in args.netmap_create:
630 net_comma_list = net.split(",")
631 for net_comma in net_comma_list:
632 net_tuple = net_comma.split("=")
633 if len(net_tuple) == 1:
634 net_scenario = net_tuple[0].strip()
635 net_datacenter = None
636 elif len(net_tuple) == 2:
637 net_scenario = net_tuple[0].strip()
638 net_datacenter = net_tuple[1].strip()
640 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
642 if net_scenario not in myInstance["instance"]["networks"]:
643 myInstance["instance"]["networks"][net_scenario] = {}
644 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
645 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
646 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
648 if "cloud-config" not in myInstance["instance"]:
649 myInstance["instance"]["cloud-config"] = {}
650 cloud_config = myInstance["instance"]["cloud-config"]
651 for key in args.keypair:
652 index = key.find(":")
654 if "key-pairs" not in cloud_config:
655 cloud_config["key-pairs"] = []
656 cloud_config["key-pairs"].append(key)
660 key_list = key_.split(",")
661 if "users" not in cloud_config:
662 cloud_config["users"] = []
663 cloud_config["users"].append({"name": user, "key-pairs": key_list })
664 if args.keypair_auto:
667 home = os.getenv("HOME")
668 user = os.getenv("USER")
669 files = os.listdir(home+'/.ssh')
671 if file[-4:] == ".pub":
672 with open(home+'/.ssh/'+file, 'r') as f:
673 keys.append(f.read())
675 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
677 except Exception as e:
678 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
681 if "cloud-config" not in myInstance["instance"]:
682 myInstance["instance"]["cloud-config"] = {}
683 cloud_config = myInstance["instance"]["cloud-config"]
684 if "key-pairs" not in cloud_config:
685 cloud_config["key-pairs"] = []
687 if "users" not in cloud_config:
688 cloud_config["users"] = []
689 cloud_config["users"].append({"name": user, "key-pairs": keys })
691 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
692 logger.debug("openmano request: %s", payload_req)
693 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
694 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
695 logger.debug("openmano response: %s", mano_response.text )
696 if args.verbose==None:
699 result = 0 if mano_response.status_code==200 else mano_response.status_code
700 content = mano_response.json()
701 #print json.dumps(content, indent=4)
702 if args.verbose >= 3:
703 print yaml.safe_dump(content, indent=4, default_flow_style=False)
706 if mano_response.status_code == 200:
707 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
709 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
711 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
714 print content['error']['description']
717 def instance_scenario_list(args):
718 #print "instance-scenario-list",args
722 tenant = _get_tenant()
724 toshow = _get_item_uuid("instances", args.name, tenant)
725 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
727 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
728 mano_response = requests.get(URLrequest)
729 logger.debug("openmano response: %s", mano_response.text )
730 content = mano_response.json()
731 #print json.dumps(content, indent=4)
732 if args.verbose==None:
735 result = 0 if mano_response.status_code==200 else mano_response.status_code
736 if mano_response.status_code == 200:
738 if args.verbose >= 3:
739 print yaml.safe_dump(content, indent=4, default_flow_style=False)
741 if len(content['instances']) == 0:
742 print "No scenario instances were found."
744 for instance in content['instances']:
745 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
747 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
750 print "Description: %s" %instance['description']
753 print yaml.safe_dump(content, indent=4, default_flow_style=False)
756 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
757 print "Description: %s" %instance['description']
758 print "Template scenario id: %s" %instance['scenario_id']
759 print "Template scenario name: %s" %instance['scenario_name']
760 print "---------------------------------------"
761 print "VNF instances: %d" %len(instance['vnfs'])
762 for vnf in instance['vnfs']:
763 #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))
764 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
765 if len(instance['nets'])>0:
766 print "---------------------------------------"
767 print "Internal nets:"
768 for net in instance['nets']:
770 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
771 print "---------------------------------------"
772 print "External nets:"
773 for net in instance['nets']:
774 if not net['created']:
775 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
776 print "---------------------------------------"
777 print "VM instances:"
778 for vnf in instance['vnfs']:
779 for vm in vnf['vms']:
780 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'])
782 print content['error']['description']
784 print yaml.safe_dump(content, indent=4, default_flow_style=False)
787 def instance_scenario_status(args):
788 print "instance-scenario-status"
791 def instance_scenario_delete(args):
795 tenant = _get_tenant()
796 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
797 #print "instance-scenario-delete",args
799 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
800 if not (len(r)>0 and r[0].lower()=="y"):
802 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
803 mano_response = requests.delete(URLrequest)
804 logger.debug("openmano response: %s", mano_response.text )
805 result = 0 if mano_response.status_code==200 else mano_response.status_code
806 content = mano_response.json()
807 #print json.dumps(content, indent=4)
808 if mano_response.status_code == 200:
809 print content['result']
811 print content['error']['description']
814 def instance_scenario_action(args):
815 #print "instance-scenario-action", args
816 tenant = _get_tenant()
817 toact = _get_item_uuid("instances", args.name, tenant=tenant)
819 action[ args.action ] = args.param
821 action["vnfs"] = args.vnf
823 action["vms"] = args.vm
825 headers_req = {'content-type': 'application/json'}
826 payload_req = json.dumps(action, indent=4)
827 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
828 logger.debug("openmano request: %s", payload_req)
829 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
830 logger.debug("openmano response: %s", mano_response.text )
831 result = 0 if mano_response.status_code==200 else mano_response.status_code
832 content = mano_response.json()
833 #print json.dumps(content, indent=4)
834 if mano_response.status_code == 200:
836 print yaml.safe_dump(content, indent=4, default_flow_style=False)
838 for uuid,c in content.iteritems():
839 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
841 print content['error']['description']
845 def instance_vnf_list(args):
846 print "instance-vnf-list"
849 def instance_vnf_status(args):
850 print "instance-vnf-status"
853 def tenant_create(args):
854 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
855 tenant_dict={"name": args.name}
856 if args.description!=None:
857 tenant_dict["description"] = args.description
858 payload_req = json.dumps( {"tenant": tenant_dict })
862 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
863 logger.debug("openmano request: %s", payload_req)
864 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
865 logger.debug("openmano response: %s", mano_response.text )
866 return _print_verbose(mano_response, args.verbose)
868 def tenant_list(args):
869 #print "tenant-list",args
871 toshow = _get_item_uuid("tenants", args.name)
872 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
874 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
875 mano_response = requests.get(URLrequest)
876 logger.debug("openmano response: %s", mano_response.text )
877 if args.verbose==None:
881 return _print_verbose(mano_response, args.verbose)
883 def tenant_delete(args):
884 #print "tenant-delete",args
885 todelete = _get_item_uuid("tenants", args.name)
887 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
888 if not (len(r)>0 and r[0].lower()=="y"):
890 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
891 mano_response = requests.delete(URLrequest)
892 logger.debug("openmano response: %s", mano_response.text )
893 result = 0 if mano_response.status_code==200 else mano_response.status_code
894 content = mano_response.json()
895 #print json.dumps(content, indent=4)
896 if mano_response.status_code == 200:
897 print content['result']
899 print content['error']['description']
902 def datacenter_attach(args):
903 tenant = _get_tenant()
904 datacenter = _get_datacenter(args.name)
905 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
908 if args.vim_tenant_id != None:
909 datacenter_dict['vim_tenant'] = args.vim_tenant_id
910 if args.vim_tenant_name != None:
911 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
912 if args.user != None:
913 datacenter_dict['vim_username'] = args.user
914 if args.password != None:
915 datacenter_dict['vim_password'] = args.password
916 if args.config!=None:
917 datacenter_dict["config"] = _load_file_or_yaml(args.config)
918 payload_req = json.dumps( {"datacenter": datacenter_dict })
922 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
923 logger.debug("openmano request: %s", payload_req)
924 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
925 logger.debug("openmano response: %s", mano_response.text )
926 result = _print_verbose(mano_response, args.verbose)
927 #provide addional information if error
928 if mano_response.status_code != 200:
929 content = mano_response.json()
930 if "already in use for 'name'" in content['error']['description'] and \
931 "to database vim_tenants table" in content['error']['description']:
932 print "Try to specify a different name with --vim-tenant-name"
936 def datacenter_edit_vim_tenant(args):
937 tenant = _get_tenant()
938 datacenter = _get_datacenter(args.name)
939 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
941 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
942 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
945 if args.vim_tenant_id != None:
946 datacenter_dict['vim_tenant'] = args.vim_tenant_id
947 if args.vim_tenant_name != None:
948 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
949 if args.user != None:
950 datacenter_dict['vim_username'] = args.user
951 if args.password != None:
952 datacenter_dict['vim_password'] = args.password
953 if args.config != None:
954 datacenter_dict["config"] = _load_file_or_yaml(args.config)
955 payload_req = json.dumps({"datacenter": datacenter_dict})
959 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
960 logger.debug("openmano request: %s", payload_req)
961 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
962 logger.debug("openmano response: %s", mano_response.text)
963 result = _print_verbose(mano_response, args.verbose)
967 def datacenter_detach(args):
971 tenant = _get_tenant()
972 datacenter = _get_datacenter(args.name, tenant)
973 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
974 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
975 mano_response = requests.delete(URLrequest, headers=headers_req)
976 logger.debug("openmano response: %s", mano_response.text )
977 content = mano_response.json()
978 #print json.dumps(content, indent=4)
979 result = 0 if mano_response.status_code==200 else mano_response.status_code
980 if mano_response.status_code == 200:
981 print content['result']
983 print content['error']['description']
986 def datacenter_create(args):
987 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
988 datacenter_dict={"name": args.name, "vim_url": args.url}
989 if args.description!=None:
990 datacenter_dict["description"] = args.description
992 datacenter_dict["type"] = args.type
994 datacenter_dict["vim_url_admin"] = args.url_admin
995 if args.config!=None:
996 datacenter_dict["config"] = _load_file_or_yaml(args.config)
997 if args.sdn_controller!=None:
998 tenant = _get_tenant()
999 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1000 if not 'config' in datacenter_dict:
1001 datacenter_dict['config'] = {}
1002 datacenter_dict['config']['sdn-controller'] = sdn_controller
1003 payload_req = json.dumps( {"datacenter": datacenter_dict })
1007 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1008 logger.debug("openmano request: %s", payload_req)
1009 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1010 logger.debug("openmano response: %s", mano_response.text )
1011 return _print_verbose(mano_response, args.verbose)
1013 def datacenter_delete(args):
1014 #print "datacenter-delete",args
1015 todelete = _get_item_uuid("datacenters", args.name, "any")
1017 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1018 if not (len(r)>0 and r[0].lower()=="y"):
1020 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
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']
1032 def datacenter_list(args):
1033 #print "datacenter-list",args
1034 tenant='any' if args.all else _get_tenant()
1037 toshow = _get_item_uuid("datacenters", args.name, tenant)
1038 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1040 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1041 mano_response = requests.get(URLrequest)
1042 logger.debug("openmano response: %s", mano_response.text )
1043 if args.verbose==None:
1047 return _print_verbose(mano_response, args.verbose)
1049 def datacenter_sdn_port_mapping_set(args):
1050 tenant = _get_tenant()
1051 datacenter = _get_datacenter(args.name, tenant)
1052 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1055 raise OpenmanoCLIError(
1056 "No yaml/json has been provided specifying the SDN port mapping")
1058 port_mapping = yaml.load(datacenter_sdn_port_mapping_list(args))
1059 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1061 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1062 if not (len(r) > 0 and r[0].lower() == "y"):
1065 print datacenter_sdn_port_mapping_clear(args)
1067 sdn_port_mapping = _load_file_or_yaml(args.file)
1068 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1070 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1071 logger.debug("openmano request: %s", payload_req)
1072 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1073 logger.debug("openmano response: %s", mano_response.text)
1075 if mano_response.status_code == 200:
1076 return yaml.safe_dump(mano_response.json())
1078 return mano_response.content
1080 def datacenter_sdn_port_mapping_list(args):
1081 tenant = _get_tenant()
1082 datacenter = _get_datacenter(args.name, tenant)
1084 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1085 mano_response = requests.get(URLrequest)
1086 logger.debug("openmano response: %s", mano_response.text)
1088 if mano_response.status_code != 200:
1089 return mano_response.content
1091 return yaml.safe_dump(mano_response.json())
1093 def datacenter_sdn_port_mapping_clear(args):
1094 tenant = _get_tenant()
1095 datacenter = _get_datacenter(args.name, tenant)
1098 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1099 if not (len(r)>0 and r[0].lower()=="y"):
1102 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1103 mano_response = requests.delete(URLrequest)
1104 logger.debug("openmano response: %s", mano_response.text)
1106 if mano_response.status_code != 200:
1107 if "No port mapping for datacenter" in mano_response.content:
1108 return "No port mapping for datacenter " + datacenter + " has been found"
1109 return mano_response.content
1111 return yaml.safe_dump(mano_response.json())
1113 def sdn_controller_create(args):
1114 tenant = _get_tenant()
1115 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1117 if not (args.ip and args.port and args.dpid and args.type):
1118 raise OpenmanoCLIError("The following arguments are required: ip, port, dpid, type")
1120 controller_dict = {}
1121 controller_dict['name'] = args.name
1122 controller_dict['ip'] = args.ip
1123 controller_dict['port'] = int(args.port)
1124 controller_dict['dpid'] = args.dpid
1125 controller_dict['type'] = args.type
1126 if args.description != None:
1127 controller_dict['description'] = args.description
1128 if args.user != None:
1129 controller_dict['user'] = args.user
1130 if args.password != None:
1131 controller_dict['password'] = args.password
1133 payload_req = json.dumps({"sdn_controller": controller_dict})
1137 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1138 logger.debug("openmano request: %s", payload_req)
1139 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1140 logger.debug("openmano response: %s", mano_response.text)
1141 result = _print_verbose(mano_response, args.verbose)
1145 def sdn_controller_edit(args):
1146 tenant = _get_tenant()
1147 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1148 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1150 if not (args.new_name or args.ip or args.port or args.dpid or args.type):
1151 raise OpenmanoCLIError("At least one parameter must be editd")
1154 r = raw_input("Update SDN controller %s (y/N)? " %(args.name))
1155 if not (len(r)>0 and r[0].lower()=="y"):
1158 controller_dict = {}
1159 if args.new_name != None:
1160 controller_dict['name'] = args.new_name
1162 controller_dict['ip'] = args.ip
1163 if args.port != None:
1164 controller_dict['port'] = int(args.port)
1165 if args.dpid != None:
1166 controller_dict['dpid'] = args.dpid
1167 if args.type != None:
1168 controller_dict['type'] = args.type
1169 if args.description != None:
1170 controller_dict['description'] = args.description
1171 if args.user != None:
1172 controller_dict['user'] = args.user
1173 if args.password != None:
1174 controller_dict['password'] = args.password
1176 payload_req = json.dumps({"sdn_controller": controller_dict})
1180 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1181 logger.debug("openmano request: %s", payload_req)
1182 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1183 logger.debug("openmano response: %s", mano_response.text)
1184 result = _print_verbose(mano_response, args.verbose)
1188 def sdn_controller_list(args):
1189 tenant = _get_tenant()
1190 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1193 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1194 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1196 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1198 mano_response = requests.get(URLrequest)
1199 logger.debug("openmano response: %s", mano_response.text )
1200 if args.verbose==None:
1205 result = json.dumps(mano_response.json(), indent=4)
1208 def sdn_controller_delete(args):
1209 tenant = _get_tenant()
1210 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1213 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1214 if not (len(r) > 0 and r[0].lower() == "y"):
1217 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1218 mano_response = requests.delete(URLrequest)
1219 logger.debug("openmano response: %s", mano_response.text)
1220 result = _print_verbose(mano_response, args.verbose)
1224 def vim_action(args):
1225 #print "datacenter-net-action",args
1226 tenant = _get_tenant()
1227 datacenter = _get_datacenter(args.datacenter, tenant)
1228 if args.verbose==None:
1230 if args.action=="list":
1231 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1234 URLrequest += "/" + args.name
1235 mano_response = requests.get(URLrequest)
1236 logger.debug("openmano response: %s", mano_response.text )
1237 return _print_verbose(mano_response, args.verbose)
1238 elif args.action=="delete":
1239 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1240 mano_response = requests.delete(URLrequest)
1241 logger.debug("openmano response: %s", mano_response.text )
1242 result = 0 if mano_response.status_code==200 else mano_response.status_code
1243 content = mano_response.json()
1244 #print json.dumps(content, indent=4)
1245 if mano_response.status_code == 200:
1246 print content['result']
1248 print content['error']['description']
1250 elif args.action=="create":
1251 headers_req = {'content-type': 'application/yaml'}
1253 create_dict = _load_file_or_yaml(args.file)
1254 if args.item not in create_dict:
1255 create_dict = {args.item: create_dict}
1257 create_dict = {args.item:{}}
1259 create_dict[args.item]['name'] = args.name
1260 #if args.description:
1261 # create_dict[args.item]['description'] = args.description
1262 if args.item=="network":
1264 create_dict[args.item]['bind_net'] = args.bind_net
1266 create_dict[args.item]['type'] = args.type
1268 create_dict[args.item]['shared'] = args.shared
1269 if "name" not in create_dict[args.item]:
1270 print "You must provide a name in the descriptor file or with the --name option"
1272 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1273 logger.debug("openmano request: %s", payload_req)
1274 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item)
1275 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1276 logger.debug("openmano response: %s", mano_response.text )
1277 if args.verbose==None:
1279 return _print_verbose(mano_response, args.verbose)
1282 def datacenter_net_action(args):
1283 if args.action == "net-update":
1284 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1286 args.action = "netmap-delete"
1289 r = datacenter_netmap_action(args)
1292 args.action = "netmap-import"
1293 r = datacenter_netmap_action(args)
1296 if args.action == "net-edit":
1297 args.netmap = args.net
1299 elif args.action == "net-list":
1301 elif args.action == "net-delete":
1302 args.netmap = args.net
1305 args.action = "netmap" + args.action[3:]
1308 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1310 return datacenter_netmap_action(args)
1312 def datacenter_netmap_action(args):
1313 tenant = _get_tenant()
1314 datacenter = _get_datacenter(args.datacenter, tenant)
1315 #print "datacenter_netmap_action",args
1317 if args.verbose==None:
1319 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1320 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1322 if args.action=="netmap-list":
1324 URLrequest += "/" + args.netmap
1326 mano_response = requests.get(URLrequest)
1328 elif args.action=="netmap-delete":
1329 if args.netmap and args.all:
1330 print "you can not use a netmap name and the option --all at the same time"
1333 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1334 URLrequest += "/" + args.netmap
1336 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1338 print "you must specify a netmap name or the option --all"
1341 r = raw_input(force_text)
1342 if len(r)>0 and r[0].lower()=="y":
1346 mano_response = requests.delete(URLrequest, headers=headers_req)
1347 elif args.action=="netmap-import":
1349 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1350 if len(r)>0 and r[0].lower()=="y":
1354 URLrequest += "/upload"
1355 mano_response = requests.post(URLrequest, headers=headers_req)
1356 elif args.action=="netmap-edit" or args.action=="netmap-create":
1358 payload = _load_file_or_yaml(args.file)
1361 if "netmap" not in payload:
1362 payload = {"netmap": payload}
1364 payload["netmap"]["name"] = args.name
1366 payload["netmap"]["vim_id"] = args.vim_id
1367 if args.action=="netmap-create" and args.vim_name:
1368 payload["netmap"]["vim_name"] = args.vim_name
1369 payload_req = json.dumps(payload)
1370 logger.debug("openmano request: %s", payload_req)
1372 if args.action=="netmap-edit" and not args.force:
1373 if len(payload["netmap"]) == 0:
1374 print "You must supply some parameter to edit"
1376 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1377 if len(r)>0 and r[0].lower()=="y":
1381 URLrequest += "/" + args.netmap
1382 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1383 else: #netmap-create
1384 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1385 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1387 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1389 logger.debug("openmano response: %s", mano_response.text )
1390 return _print_verbose(mano_response, args.verbose)
1392 def element_edit(args):
1393 element = _get_item_uuid(args.element, args.name)
1394 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1395 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1396 payload=_load_file_or_yaml(args.file)
1397 if args.element[:-1] not in payload:
1398 payload = {args.element[:-1]: payload }
1399 payload_req = json.dumps(payload)
1402 if not args.force or (args.name==None and args.filer==None):
1403 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1404 if len(r)>0 and r[0].lower()=="y":
1408 logger.debug("openmano request: %s", payload_req)
1409 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1410 logger.debug("openmano response: %s", mano_response.text )
1411 if args.verbose==None:
1415 return _print_verbose(mano_response, args.verbose)
1418 def datacenter_edit(args):
1419 tenant = _get_tenant()
1420 element = _get_item_uuid('datacenters', args.name, tenant)
1421 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1422 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1424 has_arguments = False
1425 if args.file != None:
1426 has_arguments = True
1427 payload = _load_file_or_yaml(args.file)
1431 if args.sdn_controller != None:
1432 has_arguments = True
1433 if not 'config' in payload:
1434 payload['config'] = {}
1435 if not 'sdn-controller' in payload['config']:
1436 payload['config']['sdn-controller'] = {}
1437 if args.sdn_controller == 'null':
1438 payload['config']['sdn-controller'] = None
1440 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1442 if not has_arguments:
1443 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1445 if 'datacenter' not in payload:
1446 payload = {'datacenter': payload}
1447 payload_req = json.dumps(payload)
1450 if not args.force or (args.name == None and args.filer == None):
1451 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1452 if len(r) > 0 and r[0].lower() == "y":
1456 logger.debug("openmano request: %s", payload_req)
1457 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1458 logger.debug("openmano response: %s", mano_response.text)
1459 if args.verbose == None:
1461 if args.name != None:
1463 return _print_verbose(mano_response, args.verbose)
1469 if __name__=="__main__":
1471 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1472 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1473 mano_port = os.getenv('OPENMANO_PORT',"9090")
1474 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1476 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1477 main_parser.add_argument('--version', action='version', version='%(prog)s ' + __version__ )
1479 subparsers = main_parser.add_subparsers(help='commands')
1481 parent_parser = argparse.ArgumentParser(add_help=False)
1482 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1483 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1485 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1486 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1487 config_parser.set_defaults(func=config)
1489 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1490 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1491 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1492 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1493 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1494 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1495 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1496 vnf_create_parser.set_defaults(func=vnf_create)
1498 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1499 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1500 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1501 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1502 vnf_list_parser.set_defaults(func=vnf_list)
1504 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1505 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1506 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1507 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1508 vnf_delete_parser.set_defaults(func=vnf_delete)
1510 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1511 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1512 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1513 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1514 scenario_create_parser.set_defaults(func=scenario_create)
1516 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1517 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1518 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1519 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1520 scenario_list_parser.set_defaults(func=scenario_list)
1522 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1523 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1524 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1525 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1526 scenario_delete_parser.set_defaults(func=scenario_delete)
1528 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1529 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1530 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1531 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1532 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1533 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1534 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1536 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1537 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1538 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1539 scenario_deploy_parser.set_defaults(func=scenario_verify)
1541 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1542 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1543 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1544 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1545 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1546 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1547 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")
1548 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")
1549 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")
1550 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")
1551 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1552 instance_scenario_create_parser.set_defaults(func=instance_create)
1554 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1555 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1556 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1557 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1559 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)")
1560 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1561 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1562 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1563 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1565 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1566 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1567 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1568 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1569 help="action to send")
1570 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1571 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1572 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1573 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1575 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1576 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1577 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1579 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1580 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1581 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1582 tenant_create_parser.set_defaults(func=tenant_create)
1584 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1585 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1586 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1587 tenant_delete_parser.set_defaults(func=tenant_delete)
1589 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1590 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1591 tenant_list_parser.set_defaults(func=tenant_list)
1593 item_list=('tenant') #put tenant before so that help appear in order
1594 for item in item_list:
1595 element_edit_parser = subparsers.add_parser(item+'-edit', parents=[parent_parser], help="edits one "+item)
1596 element_edit_parser.add_argument("name", help="name or uuid of the "+item)
1597 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1598 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1599 element_edit_parser.set_defaults(func=element_edit, element=item + 's')
1601 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1602 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1603 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1604 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1605 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1606 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1607 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1608 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1609 datacenter_create_parser.set_defaults(func=datacenter_create)
1611 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1612 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1613 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1614 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1616 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1617 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1618 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1619 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1620 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1621 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1622 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1624 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1625 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1626 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1627 datacenter_list_parser.set_defaults(func=datacenter_list)
1629 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1630 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1631 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1632 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1633 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1634 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1635 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1636 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1638 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1639 help="Edit the association of a datacenter to the operating tenant")
1640 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1641 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1642 help="specify a datacenter tenant to use. A new one is created by default")
1643 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1644 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1645 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1646 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1647 help="aditional configuration in json/yaml format")
1648 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1650 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1651 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1652 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1653 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1655 #=======================datacenter_sdn_port_mapping_xxx section=======================
1656 #datacenter_sdn_port_mapping_set
1657 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1658 parents=[parent_parser],
1659 help="Load a file with the mapping of physical ports "
1660 "and the ports of the dataplaneswitch controlled "
1662 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1663 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1664 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1665 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1666 help="forces overwriting without asking")
1667 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1669 #datacenter_sdn_port_mapping_list
1670 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1671 parents=[parent_parser],
1672 help="Show the SDN port mapping in a datacenter")
1673 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1674 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1676 # datacenter_sdn_port_mapping_clear
1677 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1678 parents=[parent_parser],
1679 help="Clean the the SDN port mapping in a datacenter")
1680 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1681 help="specifies the datacenter")
1682 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1683 help="forces clearing without asking")
1684 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1685 # =======================
1687 # =======================sdn_controller_xxx section=======================
1688 # sdn_controller_create
1689 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1690 help="Creates an SDN controller entity within RO")
1691 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1692 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1693 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1694 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1695 sdn_controller_create_parser.add_argument("--dpid", action="store",
1696 help="DPID of the dataplane switch controlled by this SDN controller")
1697 sdn_controller_create_parser.add_argument("--type", action="store",
1698 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1699 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1700 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1701 help="password credentials for the SDN controller")
1702 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1704 # sdn_controller_edit
1705 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1706 help="Update one or more options of a SDN controller")
1707 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1708 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1710 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1711 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1712 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1713 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1714 help="DPID of the dataplane switch controlled by this SDN controller")
1715 sdn_controller_edit_parser.add_argument("--type", action="store",
1716 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1717 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1718 sdn_controller_edit_parser.add_argument("--password", action="store",
1719 help="password credentials for the SDN controller", dest='password')
1720 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1721 #TODO: include option --file
1722 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1724 #sdn_controller_list
1725 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1726 parents=[parent_parser],
1727 help="List the SDN controllers")
1728 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1729 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1731 # sdn_controller_delete
1732 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1733 parents=[parent_parser],
1734 help="Delete the the SDN controller")
1735 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1736 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1737 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1738 # =======================
1740 action_dict={'net-update': 'retrieves external networks from datacenter',
1741 'net-edit': 'edits an external network',
1742 'net-delete': 'deletes an external network',
1743 'net-list': 'lists external networks from a datacenter'
1745 for item in action_dict:
1746 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1747 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1748 if item=='net-edit' or item=='net-delete':
1749 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1750 if item=='net-edit':
1751 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1752 if item!='net-list':
1753 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1754 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1757 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1758 'netmap-create': 'create a new network senario netmap',
1759 'netmap-edit': 'edit name of a network senario netmap',
1760 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1761 'netmap-list': 'list/show network scenario netmaps'
1763 for item in action_dict:
1764 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1765 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1766 #if item=='net-add':
1767 # datacenter_action_parser.add_argument("net", help="name of the network")
1768 if item=='netmap-delete':
1769 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1770 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1771 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1772 if item=='netmap-edit':
1773 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1774 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1775 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1776 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1777 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1778 if item=='netmap-list':
1779 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1780 if item=='netmap-create':
1781 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1782 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1783 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1784 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1785 if item=='netmap-import':
1786 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1787 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1789 for item in ("network", "tenant", "image"):
1791 commnad_name = 'vim-net'
1793 commnad_name = 'vim-'+item
1794 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1795 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1796 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1797 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1799 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1800 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1801 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1802 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1804 if item == "network" or item == "tenant":
1805 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1806 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1807 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1808 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1810 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1811 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1812 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>'")
1814 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1815 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1817 argcomplete.autocomplete(main_parser)
1820 args = main_parser.parse_args()
1822 level = logging.CRITICAL
1823 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1824 if "debug" in args and args.debug:
1825 level = logging.DEBUG
1826 logging.basicConfig(format=streamformat, level= level)
1827 logger = logging.getLogger('mano')
1828 logger.setLevel(level)
1829 result = args.func(args)
1832 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1833 except (requests.exceptions.ConnectionError):
1834 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1836 except (KeyboardInterrupt):
1837 print 'Exiting openmano'
1839 except (SystemExit, ArgumentParserError):
1841 except OpenmanoCLIError as e: