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)
1466 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1467 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1469 mano_response = requests.get(URLrequest, headers=headers_req)
1470 logger.debug("openmano response: %s", mano_response.text)
1471 print mano_response.text
1478 if __name__=="__main__":
1480 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1481 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1482 mano_port = os.getenv('OPENMANO_PORT',"9090")
1483 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1485 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1486 main_parser.add_argument('--version', action='version', help="get version of this client",
1487 version='%(prog)s client version ' + __version__ +
1488 " (Note: use '%(prog)s version' to get server version)")
1490 subparsers = main_parser.add_subparsers(help='commands')
1492 parent_parser = argparse.ArgumentParser(add_help=False)
1493 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1494 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1496 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1497 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1498 config_parser.set_defaults(func=config)
1500 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1501 version_parser.set_defaults(func=version)
1503 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1504 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1505 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1506 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1507 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1508 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1509 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1510 vnf_create_parser.set_defaults(func=vnf_create)
1512 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1513 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1514 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1515 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1516 vnf_list_parser.set_defaults(func=vnf_list)
1518 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1519 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1520 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1521 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1522 vnf_delete_parser.set_defaults(func=vnf_delete)
1524 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1525 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1526 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1527 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1528 scenario_create_parser.set_defaults(func=scenario_create)
1530 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1531 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1532 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1533 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1534 scenario_list_parser.set_defaults(func=scenario_list)
1536 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1537 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1538 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1539 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1540 scenario_delete_parser.set_defaults(func=scenario_delete)
1542 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1543 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1544 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1545 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1546 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1547 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1548 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1550 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1551 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1552 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1553 scenario_deploy_parser.set_defaults(func=scenario_verify)
1555 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1556 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1557 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1558 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1559 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1560 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1561 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")
1562 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")
1563 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")
1564 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")
1565 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1566 instance_scenario_create_parser.set_defaults(func=instance_create)
1568 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1569 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1570 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1571 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1573 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)")
1574 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1575 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1576 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1577 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1579 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1580 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1581 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1582 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1583 help="action to send")
1584 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1585 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1586 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1587 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1589 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1590 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1591 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1593 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1594 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1595 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1596 tenant_create_parser.set_defaults(func=tenant_create)
1598 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1599 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1600 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1601 tenant_delete_parser.set_defaults(func=tenant_delete)
1603 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1604 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1605 tenant_list_parser.set_defaults(func=tenant_list)
1607 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1608 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1609 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1610 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1611 element_edit_parser.set_defaults(func=element_edit, element='tenants')
1613 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1614 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1615 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1616 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1617 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1618 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1619 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1620 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1621 datacenter_create_parser.set_defaults(func=datacenter_create)
1623 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1624 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1625 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1626 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1628 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1629 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1630 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1631 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1632 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1633 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1634 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1636 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1637 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1638 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1639 datacenter_list_parser.set_defaults(func=datacenter_list)
1641 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1642 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1643 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1644 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1645 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1646 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1647 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1648 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1650 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1651 help="Edit the association of a datacenter to the operating tenant")
1652 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1653 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1654 help="specify a datacenter tenant to use. A new one is created by default")
1655 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1656 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1657 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1658 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1659 help="aditional configuration in json/yaml format")
1660 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1662 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1663 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1664 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1665 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1667 #=======================datacenter_sdn_port_mapping_xxx section=======================
1668 #datacenter_sdn_port_mapping_set
1669 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1670 parents=[parent_parser],
1671 help="Load a file with the mapping of physical ports "
1672 "and the ports of the dataplaneswitch controlled "
1674 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1675 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1676 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1677 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1678 help="forces overwriting without asking")
1679 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1681 #datacenter_sdn_port_mapping_list
1682 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1683 parents=[parent_parser],
1684 help="Show the SDN port mapping in a datacenter")
1685 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1686 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1688 # datacenter_sdn_port_mapping_clear
1689 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1690 parents=[parent_parser],
1691 help="Clean the the SDN port mapping in a datacenter")
1692 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1693 help="specifies the datacenter")
1694 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1695 help="forces clearing without asking")
1696 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1697 # =======================
1699 # =======================sdn_controller_xxx section=======================
1700 # sdn_controller_create
1701 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1702 help="Creates an SDN controller entity within RO")
1703 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1704 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1705 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1706 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1707 sdn_controller_create_parser.add_argument("--dpid", action="store",
1708 help="DPID of the dataplane switch controlled by this SDN controller")
1709 sdn_controller_create_parser.add_argument("--type", action="store",
1710 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1711 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1712 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1713 help="password credentials for the SDN controller")
1714 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1716 # sdn_controller_edit
1717 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1718 help="Update one or more options of a SDN controller")
1719 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1720 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1722 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1723 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1724 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1725 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1726 help="DPID of the dataplane switch controlled by this SDN controller")
1727 sdn_controller_edit_parser.add_argument("--type", action="store",
1728 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1729 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1730 sdn_controller_edit_parser.add_argument("--password", action="store",
1731 help="password credentials for the SDN controller", dest='password')
1732 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1733 #TODO: include option --file
1734 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1736 #sdn_controller_list
1737 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1738 parents=[parent_parser],
1739 help="List the SDN controllers")
1740 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1741 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1743 # sdn_controller_delete
1744 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1745 parents=[parent_parser],
1746 help="Delete the the SDN controller")
1747 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1748 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1749 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1750 # =======================
1752 action_dict={'net-update': 'retrieves external networks from datacenter',
1753 'net-edit': 'edits an external network',
1754 'net-delete': 'deletes an external network',
1755 'net-list': 'lists external networks from a datacenter'
1757 for item in action_dict:
1758 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1759 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1760 if item=='net-edit' or item=='net-delete':
1761 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1762 if item=='net-edit':
1763 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1764 if item!='net-list':
1765 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1766 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1769 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1770 'netmap-create': 'create a new network senario netmap',
1771 'netmap-edit': 'edit name of a network senario netmap',
1772 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1773 'netmap-list': 'list/show network scenario netmaps'
1775 for item in action_dict:
1776 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1777 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1778 #if item=='net-add':
1779 # datacenter_action_parser.add_argument("net", help="name of the network")
1780 if item=='netmap-delete':
1781 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1782 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1783 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1784 if item=='netmap-edit':
1785 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1786 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1787 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1788 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1789 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1790 if item=='netmap-list':
1791 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1792 if item=='netmap-create':
1793 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1794 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1795 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1796 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1797 if item=='netmap-import':
1798 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1799 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1801 for item in ("network", "tenant", "image"):
1803 commnad_name = 'vim-net'
1805 commnad_name = 'vim-'+item
1806 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1807 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1808 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1809 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1811 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1812 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1813 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1814 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1816 if item == "network" or item == "tenant":
1817 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1818 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1819 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1820 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1822 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1823 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1824 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>'")
1826 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1827 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1829 argcomplete.autocomplete(main_parser)
1832 args = main_parser.parse_args()
1834 level = logging.CRITICAL
1835 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1836 if "debug" in args and args.debug:
1837 level = logging.DEBUG
1838 logging.basicConfig(format=streamformat, level= level)
1839 logger = logging.getLogger('mano')
1840 logger.setLevel(level)
1841 result = args.func(args)
1844 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1845 except (requests.exceptions.ConnectionError):
1846 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1848 except (KeyboardInterrupt):
1849 print 'Exiting openmano'
1851 except (SystemExit, ArgumentParserError):
1853 except OpenmanoCLIError as e: