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.14-r521"
32 version_date = "May 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 tenant = _get_tenant()
560 headers_req = {'content-type': 'application/json'}
562 action["verify"] = {}
563 action["verify"]["instance_name"] = "scen-verify-return5"
564 payload_req = json.dumps(action, indent=4)
567 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
568 logger.debug("openmano request: %s", payload_req)
569 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
570 logger.debug("openmano response: %s", mano_response.text )
572 result = 0 if mano_response.status_code==200 else mano_response.status_code
573 content = mano_response.json()
574 #print json.dumps(content, indent=4)
575 if mano_response.status_code == 200:
576 print content['result']
578 print content['error']['description']
581 def instance_create(args):
582 tenant = _get_tenant()
583 headers_req = {'content-type': 'application/yaml'}
584 myInstance={"instance": {}, "schema_version": "0.1"}
586 instance_dict = _load_file_or_yaml(args.file)
587 if "instance" not in instance_dict:
588 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
590 myInstance = instance_dict
592 myInstance["instance"]['name'] = args.name
594 myInstance["instance"]['description'] = args.description
596 myInstance["instance"]['action'] = "reserve"
598 datacenter = myInstance["instance"].get("datacenter")
599 if args.datacenter != None:
600 datacenter = args.datacenter
601 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
603 scenario = myInstance["instance"].get("scenario")
604 if args.scenario != None:
605 scenario = args.scenario
607 print "you must provide a scenario in the file descriptor or with --scenario"
609 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
611 if "networks" not in myInstance["instance"]:
612 myInstance["instance"]["networks"] = {}
613 for net in args.netmap_use:
614 net_comma_list = net.split(",")
615 for net_comma in net_comma_list:
616 net_tuple = net_comma.split("=")
617 if len(net_tuple) != 2:
618 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
620 net_scenario = net_tuple[0].strip()
621 net_datacenter = net_tuple[1].strip()
622 if net_scenario not in myInstance["instance"]["networks"]:
623 myInstance["instance"]["networks"][net_scenario] = {}
624 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
625 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
626 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
627 if args.netmap_create:
628 if "networks" not in myInstance["instance"]:
629 myInstance["instance"]["networks"] = {}
630 for net in args.netmap_create:
631 net_comma_list = net.split(",")
632 for net_comma in net_comma_list:
633 net_tuple = net_comma.split("=")
634 if len(net_tuple) == 1:
635 net_scenario = net_tuple[0].strip()
636 net_datacenter = None
637 elif len(net_tuple) == 2:
638 net_scenario = net_tuple[0].strip()
639 net_datacenter = net_tuple[1].strip()
641 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
643 if net_scenario not in myInstance["instance"]["networks"]:
644 myInstance["instance"]["networks"][net_scenario] = {}
645 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
646 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
647 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
649 if "cloud-config" not in myInstance["instance"]:
650 myInstance["instance"]["cloud-config"] = {}
651 cloud_config = myInstance["instance"]["cloud-config"]
652 for key in args.keypair:
653 index = key.find(":")
655 if "key-pairs" not in cloud_config:
656 cloud_config["key-pairs"] = []
657 cloud_config["key-pairs"].append(key)
661 key_list = key_.split(",")
662 if "users" not in cloud_config:
663 cloud_config["users"] = []
664 cloud_config["users"].append({"name": user, "key-pairs": key_list })
665 if args.keypair_auto:
668 home = os.getenv("HOME")
669 user = os.getenv("USER")
670 files = os.listdir(home+'/.ssh')
672 if file[-4:] == ".pub":
673 with open(home+'/.ssh/'+file, 'r') as f:
674 keys.append(f.read())
676 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
678 except Exception as e:
679 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
682 if "cloud-config" not in myInstance["instance"]:
683 myInstance["instance"]["cloud-config"] = {}
684 cloud_config = myInstance["instance"]["cloud-config"]
685 if "key-pairs" not in cloud_config:
686 cloud_config["key-pairs"] = []
688 if "users" not in cloud_config:
689 cloud_config["users"] = []
690 cloud_config["users"].append({"name": user, "key-pairs": keys })
692 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
693 logger.debug("openmano request: %s", payload_req)
694 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
695 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
696 logger.debug("openmano response: %s", mano_response.text )
697 if args.verbose==None:
700 result = 0 if mano_response.status_code==200 else mano_response.status_code
701 content = mano_response.json()
702 #print json.dumps(content, indent=4)
703 if args.verbose >= 3:
704 print yaml.safe_dump(content, indent=4, default_flow_style=False)
707 if mano_response.status_code == 200:
708 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
710 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
712 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
715 print content['error']['description']
718 def instance_scenario_list(args):
719 #print "instance-scenario-list",args
723 tenant = _get_tenant()
725 toshow = _get_item_uuid("instances", args.name, tenant)
726 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
728 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
729 mano_response = requests.get(URLrequest)
730 logger.debug("openmano response: %s", mano_response.text )
731 content = mano_response.json()
732 #print json.dumps(content, indent=4)
733 if args.verbose==None:
736 result = 0 if mano_response.status_code==200 else mano_response.status_code
737 if mano_response.status_code == 200:
739 if args.verbose >= 3:
740 print yaml.safe_dump(content, indent=4, default_flow_style=False)
742 if len(content['instances']) == 0:
743 print "No scenario instances were found."
745 for instance in content['instances']:
746 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
748 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
751 print "Description: %s" %instance['description']
754 print yaml.safe_dump(content, indent=4, default_flow_style=False)
757 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
758 print "Description: %s" %instance['description']
759 print "Template scenario id: %s" %instance['scenario_id']
760 print "Template scenario name: %s" %instance['scenario_name']
761 print "---------------------------------------"
762 print "VNF instances: %d" %len(instance['vnfs'])
763 for vnf in instance['vnfs']:
764 #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))
765 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
766 if len(instance['nets'])>0:
767 print "---------------------------------------"
768 print "Internal nets:"
769 for net in instance['nets']:
771 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
772 print "---------------------------------------"
773 print "External nets:"
774 for net in instance['nets']:
775 if not net['created']:
776 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
777 print "---------------------------------------"
778 print "VM instances:"
779 for vnf in instance['vnfs']:
780 for vm in vnf['vms']:
781 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'])
783 print content['error']['description']
785 print yaml.safe_dump(content, indent=4, default_flow_style=False)
788 def instance_scenario_status(args):
789 print "instance-scenario-status"
792 def instance_scenario_delete(args):
796 tenant = _get_tenant()
797 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
798 #print "instance-scenario-delete",args
800 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
801 if not (len(r)>0 and r[0].lower()=="y"):
803 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
804 mano_response = requests.delete(URLrequest)
805 logger.debug("openmano response: %s", mano_response.text )
806 result = 0 if mano_response.status_code==200 else mano_response.status_code
807 content = mano_response.json()
808 #print json.dumps(content, indent=4)
809 if mano_response.status_code == 200:
810 print content['result']
812 print content['error']['description']
815 def instance_scenario_action(args):
816 #print "instance-scenario-action", args
817 tenant = _get_tenant()
818 toact = _get_item_uuid("instances", args.name, tenant=tenant)
820 action[ args.action ] = args.param
822 action["vnfs"] = args.vnf
824 action["vms"] = args.vm
826 headers_req = {'content-type': 'application/json'}
827 payload_req = json.dumps(action, indent=4)
828 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
829 logger.debug("openmano request: %s", payload_req)
830 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
831 logger.debug("openmano response: %s", mano_response.text )
832 result = 0 if mano_response.status_code==200 else mano_response.status_code
833 content = mano_response.json()
834 #print json.dumps(content, indent=4)
835 if mano_response.status_code == 200:
837 print yaml.safe_dump(content, indent=4, default_flow_style=False)
839 for uuid,c in content.iteritems():
840 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
842 print content['error']['description']
846 def instance_vnf_list(args):
847 print "instance-vnf-list"
850 def instance_vnf_status(args):
851 print "instance-vnf-status"
854 def tenant_create(args):
855 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
856 tenant_dict={"name": args.name}
857 if args.description!=None:
858 tenant_dict["description"] = args.description
859 payload_req = json.dumps( {"tenant": tenant_dict })
863 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
864 logger.debug("openmano request: %s", payload_req)
865 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
866 logger.debug("openmano response: %s", mano_response.text )
867 return _print_verbose(mano_response, args.verbose)
869 def tenant_list(args):
870 #print "tenant-list",args
872 toshow = _get_item_uuid("tenants", args.name)
873 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
875 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
876 mano_response = requests.get(URLrequest)
877 logger.debug("openmano response: %s", mano_response.text )
878 if args.verbose==None:
882 return _print_verbose(mano_response, args.verbose)
884 def tenant_delete(args):
885 #print "tenant-delete",args
886 todelete = _get_item_uuid("tenants", args.name)
888 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
889 if not (len(r)>0 and r[0].lower()=="y"):
891 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
892 mano_response = requests.delete(URLrequest)
893 logger.debug("openmano response: %s", mano_response.text )
894 result = 0 if mano_response.status_code==200 else mano_response.status_code
895 content = mano_response.json()
896 #print json.dumps(content, indent=4)
897 if mano_response.status_code == 200:
898 print content['result']
900 print content['error']['description']
903 def datacenter_attach(args):
904 tenant = _get_tenant()
905 datacenter = _get_datacenter(args.name)
906 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
909 if args.vim_tenant_id != None:
910 datacenter_dict['vim_tenant'] = args.vim_tenant_id
911 if args.vim_tenant_name != None:
912 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
913 if args.user != None:
914 datacenter_dict['vim_username'] = args.user
915 if args.password != None:
916 datacenter_dict['vim_password'] = args.password
917 if args.config!=None:
918 datacenter_dict["config"] = _load_file_or_yaml(args.config)
919 payload_req = json.dumps( {"datacenter": datacenter_dict })
923 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
924 logger.debug("openmano request: %s", payload_req)
925 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
926 logger.debug("openmano response: %s", mano_response.text )
927 result = _print_verbose(mano_response, args.verbose)
928 #provide addional information if error
929 if mano_response.status_code != 200:
930 content = mano_response.json()
931 if "already in use for 'name'" in content['error']['description'] and \
932 "to database vim_tenants table" in content['error']['description']:
933 print "Try to specify a different name with --vim-tenant-name"
937 def datacenter_edit_vim_tenant(args):
938 tenant = _get_tenant()
939 datacenter = _get_datacenter(args.name)
940 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
942 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
943 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
946 if args.vim_tenant_id != None:
947 datacenter_dict['vim_tenant'] = args.vim_tenant_id
948 if args.vim_tenant_name != None:
949 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
950 if args.user != None:
951 datacenter_dict['vim_username'] = args.user
952 if args.password != None:
953 datacenter_dict['vim_password'] = args.password
954 if args.config != None:
955 datacenter_dict["config"] = _load_file_or_yaml(args.config)
956 payload_req = json.dumps({"datacenter": datacenter_dict})
960 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
961 logger.debug("openmano request: %s", payload_req)
962 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
963 logger.debug("openmano response: %s", mano_response.text)
964 result = _print_verbose(mano_response, args.verbose)
968 def datacenter_detach(args):
972 tenant = _get_tenant()
973 datacenter = _get_datacenter(args.name, tenant)
974 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
975 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
976 mano_response = requests.delete(URLrequest, headers=headers_req)
977 logger.debug("openmano response: %s", mano_response.text )
978 content = mano_response.json()
979 #print json.dumps(content, indent=4)
980 result = 0 if mano_response.status_code==200 else mano_response.status_code
981 if mano_response.status_code == 200:
982 print content['result']
984 print content['error']['description']
987 def datacenter_create(args):
988 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
989 datacenter_dict={"name": args.name, "vim_url": args.url}
990 if args.description!=None:
991 datacenter_dict["description"] = args.description
993 datacenter_dict["type"] = args.type
995 datacenter_dict["vim_url_admin"] = args.url_admin
996 if args.config!=None:
997 datacenter_dict["config"] = _load_file_or_yaml(args.config)
998 if args.sdn_controller!=None:
999 tenant = _get_tenant()
1000 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1001 if not 'config' in datacenter_dict:
1002 datacenter_dict['config'] = {}
1003 datacenter_dict['config']['sdn-controller'] = sdn_controller
1004 payload_req = json.dumps( {"datacenter": datacenter_dict })
1008 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1009 logger.debug("openmano request: %s", payload_req)
1010 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1011 logger.debug("openmano response: %s", mano_response.text )
1012 return _print_verbose(mano_response, args.verbose)
1014 def datacenter_delete(args):
1015 #print "datacenter-delete",args
1016 todelete = _get_item_uuid("datacenters", args.name, "any")
1018 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1019 if not (len(r)>0 and r[0].lower()=="y"):
1021 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1022 mano_response = requests.delete(URLrequest)
1023 logger.debug("openmano response: %s", mano_response.text )
1024 result = 0 if mano_response.status_code==200 else mano_response.status_code
1025 content = mano_response.json()
1026 #print json.dumps(content, indent=4)
1027 if mano_response.status_code == 200:
1028 print content['result']
1030 print content['error']['description']
1033 def datacenter_list(args):
1034 #print "datacenter-list",args
1035 tenant='any' if args.all else _get_tenant()
1038 toshow = _get_item_uuid("datacenters", args.name, tenant)
1039 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1041 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1042 mano_response = requests.get(URLrequest)
1043 logger.debug("openmano response: %s", mano_response.text )
1044 if args.verbose==None:
1048 return _print_verbose(mano_response, args.verbose)
1050 def datacenter_sdn_port_mapping_set(args):
1051 tenant = _get_tenant()
1052 datacenter = _get_datacenter(args.name, tenant)
1053 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1056 raise OpenmanoCLIError(
1057 "No yaml/json has been provided specifying the SDN port mapping")
1059 port_mapping = yaml.load(datacenter_sdn_port_mapping_list(args))
1060 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1062 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1063 if not (len(r) > 0 and r[0].lower() == "y"):
1066 print datacenter_sdn_port_mapping_clear(args)
1068 sdn_port_mapping = _load_file_or_yaml(args.file)
1069 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1071 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1072 logger.debug("openmano request: %s", payload_req)
1073 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1074 logger.debug("openmano response: %s", mano_response.text)
1076 if mano_response.status_code == 200:
1077 return yaml.safe_dump(mano_response.json())
1079 return mano_response.content
1081 def datacenter_sdn_port_mapping_list(args):
1082 tenant = _get_tenant()
1083 datacenter = _get_datacenter(args.name, tenant)
1085 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1086 mano_response = requests.get(URLrequest)
1087 logger.debug("openmano response: %s", mano_response.text)
1089 if mano_response.status_code != 200:
1090 return mano_response.content
1092 return yaml.safe_dump(mano_response.json())
1094 def datacenter_sdn_port_mapping_clear(args):
1095 tenant = _get_tenant()
1096 datacenter = _get_datacenter(args.name, tenant)
1099 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1100 if not (len(r)>0 and r[0].lower()=="y"):
1103 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1104 mano_response = requests.delete(URLrequest)
1105 logger.debug("openmano response: %s", mano_response.text)
1107 if mano_response.status_code != 200:
1108 if "No port mapping for datacenter" in mano_response.content:
1109 return "No port mapping for datacenter " + datacenter + " has been found"
1110 return mano_response.content
1112 return yaml.safe_dump(mano_response.json())
1114 def sdn_controller_create(args):
1115 tenant = _get_tenant()
1116 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1118 if not (args.ip and args.port and args.dpid and args.type):
1119 raise OpenmanoCLIError("The following arguments are required: ip, port, dpid, type")
1121 controller_dict = {}
1122 controller_dict['name'] = args.name
1123 controller_dict['ip'] = args.ip
1124 controller_dict['port'] = int(args.port)
1125 controller_dict['dpid'] = args.dpid
1126 controller_dict['type'] = args.type
1127 if args.description != None:
1128 controller_dict['description'] = args.description
1129 if args.user != None:
1130 controller_dict['user'] = args.user
1131 if args.password != None:
1132 controller_dict['password'] = args.password
1134 payload_req = json.dumps({"sdn_controller": controller_dict})
1138 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1139 logger.debug("openmano request: %s", payload_req)
1140 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1141 logger.debug("openmano response: %s", mano_response.text)
1142 result = _print_verbose(mano_response, args.verbose)
1146 def sdn_controller_edit(args):
1147 tenant = _get_tenant()
1148 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1149 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1151 if not (args.new_name or args.ip or args.port or args.dpid or args.type):
1152 raise OpenmanoCLIError("At least one parameter must be editd")
1155 r = raw_input("Update SDN controller %s (y/N)? " %(args.name))
1156 if not (len(r)>0 and r[0].lower()=="y"):
1159 controller_dict = {}
1160 if args.new_name != None:
1161 controller_dict['name'] = args.new_name
1163 controller_dict['ip'] = args.ip
1164 if args.port != None:
1165 controller_dict['port'] = int(args.port)
1166 if args.dpid != None:
1167 controller_dict['dpid'] = args.dpid
1168 if args.type != None:
1169 controller_dict['type'] = args.type
1170 if args.description != None:
1171 controller_dict['description'] = args.description
1172 if args.user != None:
1173 controller_dict['user'] = args.user
1174 if args.password != None:
1175 controller_dict['password'] = args.password
1177 payload_req = json.dumps({"sdn_controller": controller_dict})
1181 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1182 logger.debug("openmano request: %s", payload_req)
1183 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1184 logger.debug("openmano response: %s", mano_response.text)
1185 result = _print_verbose(mano_response, args.verbose)
1189 def sdn_controller_list(args):
1190 tenant = _get_tenant()
1191 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1194 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1195 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1197 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1199 mano_response = requests.get(URLrequest)
1200 logger.debug("openmano response: %s", mano_response.text )
1201 if args.verbose==None:
1206 result = json.dumps(mano_response.json(), indent=4)
1209 def sdn_controller_delete(args):
1210 tenant = _get_tenant()
1211 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1214 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1215 if not (len(r) > 0 and r[0].lower() == "y"):
1218 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1219 mano_response = requests.delete(URLrequest)
1220 logger.debug("openmano response: %s", mano_response.text)
1221 result = _print_verbose(mano_response, args.verbose)
1225 def vim_action(args):
1226 #print "datacenter-net-action",args
1227 tenant = _get_tenant()
1228 datacenter = _get_datacenter(args.datacenter, tenant)
1229 if args.verbose==None:
1231 if args.action=="list":
1232 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1235 URLrequest += "/" + args.name
1236 mano_response = requests.get(URLrequest)
1237 logger.debug("openmano response: %s", mano_response.text )
1238 return _print_verbose(mano_response, args.verbose)
1239 elif args.action=="delete":
1240 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1241 mano_response = requests.delete(URLrequest)
1242 logger.debug("openmano response: %s", mano_response.text )
1243 result = 0 if mano_response.status_code==200 else mano_response.status_code
1244 content = mano_response.json()
1245 #print json.dumps(content, indent=4)
1246 if mano_response.status_code == 200:
1247 print content['result']
1249 print content['error']['description']
1251 elif args.action=="create":
1252 headers_req = {'content-type': 'application/yaml'}
1254 create_dict = _load_file_or_yaml(args.file)
1255 if args.item not in create_dict:
1256 create_dict = {args.item: create_dict}
1258 create_dict = {args.item:{}}
1260 create_dict[args.item]['name'] = args.name
1261 #if args.description:
1262 # create_dict[args.item]['description'] = args.description
1263 if args.item=="network":
1265 create_dict[args.item]['bind_net'] = args.bind_net
1267 create_dict[args.item]['type'] = args.type
1269 create_dict[args.item]['shared'] = args.shared
1270 if "name" not in create_dict[args.item]:
1271 print "You must provide a name in the descriptor file or with the --name option"
1273 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1274 logger.debug("openmano request: %s", payload_req)
1275 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1276 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1277 logger.debug("openmano response: %s", mano_response.text )
1278 if args.verbose==None:
1280 return _print_verbose(mano_response, args.verbose)
1283 def datacenter_net_action(args):
1284 if args.action == "net-update":
1285 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1287 args.action = "netmap-delete"
1290 r = datacenter_netmap_action(args)
1293 args.action = "netmap-import"
1294 r = datacenter_netmap_action(args)
1297 if args.action == "net-edit":
1298 args.netmap = args.net
1300 elif args.action == "net-list":
1302 elif args.action == "net-delete":
1303 args.netmap = args.net
1306 args.action = "netmap" + args.action[3:]
1309 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1311 return datacenter_netmap_action(args)
1313 def datacenter_netmap_action(args):
1314 tenant = _get_tenant()
1315 datacenter = _get_datacenter(args.datacenter, tenant)
1316 #print "datacenter_netmap_action",args
1318 if args.verbose==None:
1320 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1321 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1323 if args.action=="netmap-list":
1325 URLrequest += "/" + args.netmap
1327 mano_response = requests.get(URLrequest)
1329 elif args.action=="netmap-delete":
1330 if args.netmap and args.all:
1331 print "you can not use a netmap name and the option --all at the same time"
1334 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1335 URLrequest += "/" + args.netmap
1337 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1339 print "you must specify a netmap name or the option --all"
1342 r = raw_input(force_text)
1343 if len(r)>0 and r[0].lower()=="y":
1347 mano_response = requests.delete(URLrequest, headers=headers_req)
1348 elif args.action=="netmap-import":
1350 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1351 if len(r)>0 and r[0].lower()=="y":
1355 URLrequest += "/upload"
1356 mano_response = requests.post(URLrequest, headers=headers_req)
1357 elif args.action=="netmap-edit" or args.action=="netmap-create":
1359 payload = _load_file_or_yaml(args.file)
1362 if "netmap" not in payload:
1363 payload = {"netmap": payload}
1365 payload["netmap"]["name"] = args.name
1367 payload["netmap"]["vim_id"] = args.vim_id
1368 if args.action=="netmap-create" and args.vim_name:
1369 payload["netmap"]["vim_name"] = args.vim_name
1370 payload_req = json.dumps(payload)
1371 logger.debug("openmano request: %s", payload_req)
1373 if args.action=="netmap-edit" and not args.force:
1374 if len(payload["netmap"]) == 0:
1375 print "You must supply some parameter to edit"
1377 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1378 if len(r)>0 and r[0].lower()=="y":
1382 URLrequest += "/" + args.netmap
1383 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1384 else: #netmap-create
1385 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1386 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1388 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1390 logger.debug("openmano response: %s", mano_response.text )
1391 return _print_verbose(mano_response, args.verbose)
1393 def element_edit(args):
1394 element = _get_item_uuid(args.element, args.name)
1395 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1396 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1397 payload=_load_file_or_yaml(args.file)
1398 if args.element[:-1] not in payload:
1399 payload = {args.element[:-1]: payload }
1400 payload_req = json.dumps(payload)
1403 if not args.force or (args.name==None and args.filer==None):
1404 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1405 if len(r)>0 and r[0].lower()=="y":
1409 logger.debug("openmano request: %s", payload_req)
1410 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1411 logger.debug("openmano response: %s", mano_response.text )
1412 if args.verbose==None:
1416 return _print_verbose(mano_response, args.verbose)
1419 def datacenter_edit(args):
1420 tenant = _get_tenant()
1421 element = _get_item_uuid('datacenters', args.name, tenant)
1422 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1423 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1425 has_arguments = False
1426 if args.file != None:
1427 has_arguments = True
1428 payload = _load_file_or_yaml(args.file)
1432 if args.sdn_controller != None:
1433 has_arguments = True
1434 if not 'config' in payload:
1435 payload['config'] = {}
1436 if not 'sdn-controller' in payload['config']:
1437 payload['config']['sdn-controller'] = {}
1438 if args.sdn_controller == 'null':
1439 payload['config']['sdn-controller'] = None
1441 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1443 if not has_arguments:
1444 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1446 if 'datacenter' not in payload:
1447 payload = {'datacenter': payload}
1448 payload_req = json.dumps(payload)
1451 if not args.force or (args.name == None and args.filer == None):
1452 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1453 if len(r) > 0 and r[0].lower() == "y":
1457 logger.debug("openmano request: %s", payload_req)
1458 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1459 logger.debug("openmano response: %s", mano_response.text)
1460 if args.verbose == None:
1462 if args.name != None:
1464 return _print_verbose(mano_response, args.verbose)
1467 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1468 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1470 mano_response = requests.get(URLrequest, headers=headers_req)
1471 logger.debug("openmano response: %s", mano_response.text)
1472 print mano_response.text
1479 if __name__=="__main__":
1481 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1482 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1483 mano_port = os.getenv('OPENMANO_PORT',"9090")
1484 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1486 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1487 main_parser.add_argument('--version', action='version', help="get version of this client",
1488 version='%(prog)s client version ' + __version__ +
1489 " (Note: use '%(prog)s version' to get server version)")
1491 subparsers = main_parser.add_subparsers(help='commands')
1493 parent_parser = argparse.ArgumentParser(add_help=False)
1494 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1495 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1497 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1498 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1499 config_parser.set_defaults(func=config)
1501 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1502 version_parser.set_defaults(func=version)
1504 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1505 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1506 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1507 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1508 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1509 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1510 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1511 vnf_create_parser.set_defaults(func=vnf_create)
1513 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1514 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1515 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1516 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1517 vnf_list_parser.set_defaults(func=vnf_list)
1519 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1520 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1521 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1522 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1523 vnf_delete_parser.set_defaults(func=vnf_delete)
1525 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1526 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1527 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1528 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1529 scenario_create_parser.set_defaults(func=scenario_create)
1531 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1532 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1533 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1534 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1535 scenario_list_parser.set_defaults(func=scenario_list)
1537 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1538 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1539 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1540 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1541 scenario_delete_parser.set_defaults(func=scenario_delete)
1543 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1544 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1545 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1546 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1547 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1548 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1549 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1551 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1552 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1553 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1554 scenario_deploy_parser.set_defaults(func=scenario_verify)
1556 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1557 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1558 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1559 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1560 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1561 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1562 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")
1563 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")
1564 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")
1565 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")
1566 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1567 instance_scenario_create_parser.set_defaults(func=instance_create)
1569 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1570 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1571 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1572 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1574 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)")
1575 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1576 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1577 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1578 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1580 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1581 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1582 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1583 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1584 help="action to send")
1585 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1586 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1587 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1588 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1590 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1591 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1592 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1594 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1595 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1596 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1597 tenant_create_parser.set_defaults(func=tenant_create)
1599 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1600 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1601 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1602 tenant_delete_parser.set_defaults(func=tenant_delete)
1604 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1605 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1606 tenant_list_parser.set_defaults(func=tenant_list)
1608 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1609 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1610 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1611 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1612 element_edit_parser.set_defaults(func=element_edit, element='tenants')
1614 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1615 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1616 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1617 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1618 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1619 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1620 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1621 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1622 datacenter_create_parser.set_defaults(func=datacenter_create)
1624 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1625 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1626 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1627 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1629 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1630 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1631 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1632 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1633 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1634 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1635 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1637 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1638 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1639 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1640 datacenter_list_parser.set_defaults(func=datacenter_list)
1642 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1643 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1644 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1645 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1646 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1647 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1648 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1649 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1651 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1652 help="Edit the association of a datacenter to the operating tenant")
1653 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1654 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1655 help="specify a datacenter tenant to use. A new one is created by default")
1656 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1657 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1658 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1659 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1660 help="aditional configuration in json/yaml format")
1661 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1663 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1664 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1665 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1666 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1668 #=======================datacenter_sdn_port_mapping_xxx section=======================
1669 #datacenter_sdn_port_mapping_set
1670 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1671 parents=[parent_parser],
1672 help="Load a file with the mapping of physical ports "
1673 "and the ports of the dataplaneswitch controlled "
1675 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1676 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1677 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1678 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1679 help="forces overwriting without asking")
1680 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1682 #datacenter_sdn_port_mapping_list
1683 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1684 parents=[parent_parser],
1685 help="Show the SDN port mapping in a datacenter")
1686 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1687 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1689 # datacenter_sdn_port_mapping_clear
1690 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1691 parents=[parent_parser],
1692 help="Clean the the SDN port mapping in a datacenter")
1693 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1694 help="specifies the datacenter")
1695 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1696 help="forces clearing without asking")
1697 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1698 # =======================
1700 # =======================sdn_controller_xxx section=======================
1701 # sdn_controller_create
1702 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1703 help="Creates an SDN controller entity within RO")
1704 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1705 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1706 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1707 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1708 sdn_controller_create_parser.add_argument("--dpid", action="store",
1709 help="DPID of the dataplane switch controlled by this SDN controller")
1710 sdn_controller_create_parser.add_argument("--type", action="store",
1711 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1712 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1713 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1714 help="password credentials for the SDN controller")
1715 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1717 # sdn_controller_edit
1718 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1719 help="Update one or more options of a SDN controller")
1720 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1721 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1723 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1724 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1725 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1726 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1727 help="DPID of the dataplane switch controlled by this SDN controller")
1728 sdn_controller_edit_parser.add_argument("--type", action="store",
1729 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1730 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1731 sdn_controller_edit_parser.add_argument("--password", action="store",
1732 help="password credentials for the SDN controller", dest='password')
1733 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1734 #TODO: include option --file
1735 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1737 #sdn_controller_list
1738 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1739 parents=[parent_parser],
1740 help="List the SDN controllers")
1741 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1742 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1744 # sdn_controller_delete
1745 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1746 parents=[parent_parser],
1747 help="Delete the the SDN controller")
1748 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1749 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1750 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1751 # =======================
1753 action_dict={'net-update': 'retrieves external networks from datacenter',
1754 'net-edit': 'edits an external network',
1755 'net-delete': 'deletes an external network',
1756 'net-list': 'lists external networks from a datacenter'
1758 for item in action_dict:
1759 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1760 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1761 if item=='net-edit' or item=='net-delete':
1762 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1763 if item=='net-edit':
1764 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1765 if item!='net-list':
1766 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1767 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1770 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1771 'netmap-create': 'create a new network senario netmap',
1772 'netmap-edit': 'edit name of a network senario netmap',
1773 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1774 'netmap-list': 'list/show network scenario netmaps'
1776 for item in action_dict:
1777 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1778 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1779 #if item=='net-add':
1780 # datacenter_action_parser.add_argument("net", help="name of the network")
1781 if item=='netmap-delete':
1782 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1783 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1784 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1785 if item=='netmap-edit':
1786 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1787 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1788 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1789 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1790 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1791 if item=='netmap-list':
1792 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1793 if item=='netmap-create':
1794 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1795 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1796 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1797 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1798 if item=='netmap-import':
1799 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1800 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1802 for item in ("network", "tenant", "image"):
1804 commnad_name = 'vim-net'
1806 commnad_name = 'vim-'+item
1807 vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1808 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1809 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1810 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1812 vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1813 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1814 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1815 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1817 if item == "network" or item == "tenant":
1818 vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1819 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1820 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1821 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1823 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1824 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1825 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>'")
1827 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1828 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1830 argcomplete.autocomplete(main_parser)
1833 args = main_parser.parse_args()
1835 level = logging.CRITICAL
1836 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1837 if "debug" in args and args.debug:
1838 level = logging.DEBUG
1839 logging.basicConfig(format=streamformat, level= level)
1840 logger = logging.getLogger('mano')
1841 logger.setLevel(level)
1842 result = args.func(args)
1845 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1846 except (requests.exceptions.ConnectionError):
1847 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1849 except (KeyboardInterrupt):
1850 print 'Exiting openmano'
1852 except (SystemExit, ArgumentParserError):
1854 except OpenmanoCLIError as e: