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.15-r525"
32 version_date = "Jul 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 content.get('sdn_attached_ports'):
145 #myoutput += " " + str(content['sdn_attached_ports']).ljust(20)
146 myoutput += "\nsdn_attached_ports:\n" + yaml.safe_dump(content['sdn_attached_ports'], indent=4, default_flow_style=False)
147 if verbose_level >=2:
149 if content.get('type'):
150 myoutput += new_line + " Type: " + content['type'].ljust(29)
152 if content.get('description'):
153 myoutput += new_line + " Description: " + content['description'].ljust(20)
156 print content['error']['description']
159 def parser_json_yaml(file_name):
161 f = file(file_name, "r")
164 except Exception as e:
165 return (False, str(e))
168 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
170 config = yaml.load(text)
171 except yaml.YAMLError as exc:
173 if hasattr(exc, 'problem_mark'):
174 mark = exc.problem_mark
175 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
176 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
179 config = json.loads(text)
180 except Exception as e:
181 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
185 def _load_file_or_yaml(content):
187 'content' can be or a yaml/json file or a text containing a yaml/json text format
188 This function autodetect, trying to load and parse the file,
189 if fails trying to parse the 'content' text
190 Returns the dictionary once parsed, or print an error and finish the program
192 #Check config file exists
193 if os.path.isfile(content):
194 r,payload = parser_json_yaml(content)
198 elif "{" in content or ":" in content:
200 payload = yaml.load(content)
201 except yaml.YAMLError as exc:
203 if hasattr(exc, 'problem_mark'):
204 mark = exc.problem_mark
205 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
206 print "Error loading yaml/json text"+error_pos
209 print "'%s' is neither a valid file nor a yaml/json content" % content
213 def _get_item_uuid(item, item_name_id, tenant=None):
215 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
217 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
218 mano_response = requests.get(URLrequest)
219 logger.debug("openmano response: %s", mano_response.text )
220 content = mano_response.json()
223 for i in content[item]:
224 if i["uuid"] == item_name_id:
226 if i["name"] == item_name_id:
230 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
232 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
235 # def check_valid_uuid(uuid):
236 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
238 # js_v(uuid, id_schema)
240 # except js_e.ValidationError:
243 def _get_tenant(tenant_name_id = None):
244 if not tenant_name_id:
245 tenant_name_id = mano_tenant
247 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
248 return _get_item_uuid("tenants", tenant_name_id)
250 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
251 if not datacenter_name_id:
252 datacenter_name_id = mano_datacenter
253 if not datacenter_name_id:
254 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
255 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
257 def vnf_create(args):
258 #print "vnf-create",args
259 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
260 tenant = _get_tenant()
261 myvnf = _load_file_or_yaml(args.file)
263 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
267 myvnf['vnf']['name'] = args.name
269 myvnf['vnf']['description'] = args.description
272 for image_path_ in args.image_path.split(","):
273 #print "image-path", image_path_
274 myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_
275 if "image name" in myvnf['vnf']['VNFC'][index]:
276 del myvnf['vnf']['VNFC'][index]["image name"]
277 if "image checksum" in myvnf['vnf']['VNFC'][index]:
278 del myvnf['vnf']['VNFC'][index]["image checksum"]
280 if args.image_name: #image name precedes if both are supplied
282 for image_name_ in args.image_name.split(","):
283 myvnf['vnf']['VNFC'][index]['image name']=image_name_
284 if "VNFC image" in myvnf['vnf']['VNFC'][index]:
285 del myvnf['vnf']['VNFC'][index]["VNFC image"]
287 if args.image_checksum:
289 for image_checksum_ in args.image_checksum.split(","):
290 myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_
292 except (KeyError, TypeError), e:
293 if str(e)=='vnf': error_pos= "missing field 'vnf'"
294 elif str(e)=='name': error_pos= "missing field 'vnf':'name'"
295 elif str(e)=='description': error_pos= "missing field 'vnf':'description'"
296 elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'"
297 elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array"
298 elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
299 elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
300 elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
301 else: error_pos="wrong format"
302 print "Wrong VNF descriptor: " + error_pos
304 payload_req = json.dumps(myvnf)
308 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
309 logger.debug("openmano request: %s", payload_req)
310 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
311 logger.debug("openmano response: %s", mano_response.text )
313 return _print_verbose(mano_response, args.verbose)
316 #print "vnf-list",args
320 tenant = _get_tenant()
322 toshow = _get_item_uuid("vnfs", args.name, tenant)
323 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
325 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
326 mano_response = requests.get(URLrequest)
327 logger.debug("openmano response: %s", mano_response.text )
328 content = mano_response.json()
329 #print json.dumps(content, indent=4)
330 if args.verbose==None:
332 result = 0 if mano_response.status_code==200 else mano_response.status_code
333 if mano_response.status_code == 200:
335 if args.verbose >= 3:
336 print yaml.safe_dump(content, indent=4, default_flow_style=False)
338 if len(content['vnfs']) == 0:
339 print "No VNFs were found."
340 return 404 #HTTP_Not_Found
341 for vnf in content['vnfs']:
342 myoutput = "%s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20))
344 myoutput = "%s %s" %(myoutput, vnf['created_at'].ljust(20))
347 print " Description: %s" %vnf['description']
348 print " VNF descriptor file: %s" %vnf['path']
351 print yaml.safe_dump(content, indent=4, default_flow_style=False)
354 print "%s %s %s" %(vnf['uuid'].ljust(38),vnf['name'].ljust(20), vnf['created_at'].ljust(20))
355 print " Description: %s" %vnf['description']
356 #print " VNF descriptor file: %s" %vnf['path']
358 for vm in vnf['VNFC']:
359 #print " %s %s %s" %(vm['name'].ljust(20), vm['uuid'].ljust(38), vm['description'].ljust(30))
360 print " %s %s" %(vm['name'].ljust(20), vm['description'])
361 if len(vnf['nets'])>0:
362 print " Internal nets:"
363 for net in vnf['nets']:
364 print " %s %s" %(net['name'].ljust(20), net['description'])
365 if len(vnf['external-connections'])>0:
366 print " External interfaces:"
367 for interface in vnf['external-connections']:
368 print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \
369 interface.get('vpci',"").ljust(14))
371 print content['error']['description']
373 print yaml.safe_dump(content, indent=4, default_flow_style=False)
376 def vnf_delete(args):
377 #print "vnf-delete",args
381 tenant = _get_tenant()
382 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
384 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
385 if not (len(r)>0 and r[0].lower()=="y"):
387 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
388 mano_response = requests.delete(URLrequest)
389 logger.debug("openmano response: %s", mano_response.text )
390 result = 0 if mano_response.status_code==200 else mano_response.status_code
391 content = mano_response.json()
392 #print json.dumps(content, indent=4)
393 if mano_response.status_code == 200:
394 print content['result']
396 print content['error']['description']
399 def scenario_create(args):
400 #print "scenario-create",args
401 tenant = _get_tenant()
402 headers_req = {'content-type': 'application/yaml'}
403 myscenario = _load_file_or_yaml(args.file)
406 myscenario['name'] = args.name
408 myscenario['description'] = args.description
409 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
413 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
414 logger.debug("openmano request: %s", payload_req)
415 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
416 logger.debug("openmano response: %s", mano_response.text )
417 return _print_verbose(mano_response, args.verbose)
419 def scenario_list(args):
420 #print "scenario-list",args
424 tenant = _get_tenant()
426 toshow = _get_item_uuid("scenarios", args.name, tenant)
427 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
429 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
430 mano_response = requests.get(URLrequest)
431 logger.debug("openmano response: %s", mano_response.text )
432 content = mano_response.json()
433 #print json.dumps(content, indent=4)
434 if args.verbose==None:
437 result = 0 if mano_response.status_code==200 else mano_response.status_code
438 if mano_response.status_code == 200:
440 if args.verbose >= 3:
441 print yaml.safe_dump(content, indent=4, default_flow_style=False)
443 if len(content['scenarios']) == 0:
444 print "No scenarios were found."
445 return 404 #HTTP_Not_Found
446 for scenario in content['scenarios']:
447 myoutput = "%s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20))
449 myoutput = "%s %s" %(myoutput, scenario['created_at'].ljust(20))
452 print " Description: %s" %scenario['description']
455 print yaml.safe_dump(content, indent=4, default_flow_style=False)
457 scenario = content['scenario']
458 myoutput = "%s %s %s" %(scenario['uuid'].ljust(38),scenario['name'].ljust(20), scenario['created_at'].ljust(20))
460 print " Description: %s" %scenario['description']
462 for vnf in scenario['vnfs']:
463 print " %s %s %s" %(vnf['name'].ljust(20), vnf['vnf_id'].ljust(38), vnf['description'])
464 if len(scenario['nets'])>0:
465 print " Internal nets:"
466 for net in scenario['nets']:
467 if net['description'] is None: #if description does not exist, description is "-". Valid for external and internal nets.
468 net['description'] = '-'
469 if not net['external']:
470 print " %s %s %s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30))
471 print " External nets:"
472 for net in scenario['nets']:
474 print " %s %s %s vim-id:%s" %(net['name'].ljust(20), net['uuid'].ljust(38), net['description'].ljust(30), net['vim_id'])
476 print content['error']['description']
478 print yaml.safe_dump(content, indent=4, default_flow_style=False)
481 def scenario_delete(args):
482 #print "scenario-delete",args
486 tenant = _get_tenant()
487 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
489 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
490 if not (len(r)>0 and r[0].lower()=="y"):
492 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
493 mano_response = requests.delete(URLrequest)
494 logger.debug("openmano response: %s", mano_response.text )
495 result = 0 if mano_response.status_code==200 else mano_response.status_code
496 content = mano_response.json()
497 #print json.dumps(content, indent=4)
498 if mano_response.status_code == 200:
499 print content['result']
501 print content['error']['description']
504 def scenario_deploy(args):
505 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
508 args.netmap_use = None
509 args.netmap_create = None
511 args.keypair_auto = None
512 return instance_create(args)
514 # #print "scenario-deploy",args
515 # headers_req = {'content-type': 'application/json'}
519 # actionCmd="reserve"
520 # action[actionCmd] = {}
521 # action[actionCmd]["instance_name"] = args.name
522 # if args.datacenter != None:
523 # action[actionCmd]["datacenter"] = args.datacenter
524 # elif mano_datacenter != None:
525 # action[actionCmd]["datacenter"] = mano_datacenter
527 # if args.description:
528 # action[actionCmd]["description"] = args.description
529 # payload_req = json.dumps(action, indent=4)
532 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
533 # logger.debug("openmano request: %s", payload_req)
534 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
535 # logger.debug("openmano response: %s", mano_response.text )
536 # if args.verbose==None:
539 # result = 0 if mano_response.status_code==200 else mano_response.status_code
540 # content = mano_response.json()
541 # #print json.dumps(content, indent=4)
542 # if args.verbose >= 3:
543 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
546 # if mano_response.status_code == 200:
547 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
548 # if args.verbose >=1:
549 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
550 # if args.verbose >=2:
551 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
554 # print "To check the status, run the following command:"
555 # print "openmano instance-scenario-list <instance_id>"
557 # print content['error']['description']
560 def scenario_verify(args):
561 #print "scenario-verify",args
562 tenant = _get_tenant()
563 headers_req = {'content-type': 'application/json'}
565 action["verify"] = {}
566 action["verify"]["instance_name"] = "scen-verify-return5"
567 payload_req = json.dumps(action, indent=4)
570 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
571 logger.debug("openmano request: %s", payload_req)
572 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
573 logger.debug("openmano response: %s", mano_response.text )
575 result = 0 if mano_response.status_code==200 else mano_response.status_code
576 content = mano_response.json()
577 #print json.dumps(content, indent=4)
578 if mano_response.status_code == 200:
579 print content['result']
581 print content['error']['description']
584 def instance_create(args):
585 tenant = _get_tenant()
586 headers_req = {'content-type': 'application/yaml'}
587 myInstance={"instance": {}, "schema_version": "0.1"}
589 instance_dict = _load_file_or_yaml(args.file)
590 if "instance" not in instance_dict:
591 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
593 myInstance = instance_dict
595 myInstance["instance"]['name'] = args.name
597 myInstance["instance"]['description'] = args.description
599 myInstance["instance"]['action'] = "reserve"
601 datacenter = myInstance["instance"].get("datacenter")
602 if args.datacenter != None:
603 datacenter = args.datacenter
604 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
606 scenario = myInstance["instance"].get("scenario")
607 if args.scenario != None:
608 scenario = args.scenario
610 print "you must provide a scenario in the file descriptor or with --scenario"
612 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
614 if "networks" not in myInstance["instance"]:
615 myInstance["instance"]["networks"] = {}
616 for net in args.netmap_use:
617 net_comma_list = net.split(",")
618 for net_comma in net_comma_list:
619 net_tuple = net_comma.split("=")
620 if len(net_tuple) != 2:
621 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
623 net_scenario = net_tuple[0].strip()
624 net_datacenter = net_tuple[1].strip()
625 if net_scenario not in myInstance["instance"]["networks"]:
626 myInstance["instance"]["networks"][net_scenario] = {}
627 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
628 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
629 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
630 if args.netmap_create:
631 if "networks" not in myInstance["instance"]:
632 myInstance["instance"]["networks"] = {}
633 for net in args.netmap_create:
634 net_comma_list = net.split(",")
635 for net_comma in net_comma_list:
636 net_tuple = net_comma.split("=")
637 if len(net_tuple) == 1:
638 net_scenario = net_tuple[0].strip()
639 net_datacenter = None
640 elif len(net_tuple) == 2:
641 net_scenario = net_tuple[0].strip()
642 net_datacenter = net_tuple[1].strip()
644 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
646 if net_scenario not in myInstance["instance"]["networks"]:
647 myInstance["instance"]["networks"][net_scenario] = {}
648 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
649 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
650 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
652 if "cloud-config" not in myInstance["instance"]:
653 myInstance["instance"]["cloud-config"] = {}
654 cloud_config = myInstance["instance"]["cloud-config"]
655 for key in args.keypair:
656 index = key.find(":")
658 if "key-pairs" not in cloud_config:
659 cloud_config["key-pairs"] = []
660 cloud_config["key-pairs"].append(key)
664 key_list = key_.split(",")
665 if "users" not in cloud_config:
666 cloud_config["users"] = []
667 cloud_config["users"].append({"name": user, "key-pairs": key_list })
668 if args.keypair_auto:
671 home = os.getenv("HOME")
672 user = os.getenv("USER")
673 files = os.listdir(home+'/.ssh')
675 if file[-4:] == ".pub":
676 with open(home+'/.ssh/'+file, 'r') as f:
677 keys.append(f.read())
679 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
681 except Exception as e:
682 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
685 if "cloud-config" not in myInstance["instance"]:
686 myInstance["instance"]["cloud-config"] = {}
687 cloud_config = myInstance["instance"]["cloud-config"]
688 if "key-pairs" not in cloud_config:
689 cloud_config["key-pairs"] = []
691 if "users" not in cloud_config:
692 cloud_config["users"] = []
693 cloud_config["users"].append({"name": user, "key-pairs": keys })
695 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
696 logger.debug("openmano request: %s", payload_req)
697 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
698 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
699 logger.debug("openmano response: %s", mano_response.text )
700 if args.verbose==None:
703 result = 0 if mano_response.status_code==200 else mano_response.status_code
704 content = mano_response.json()
705 #print json.dumps(content, indent=4)
706 if args.verbose >= 3:
707 print yaml.safe_dump(content, indent=4, default_flow_style=False)
710 if mano_response.status_code == 200:
711 myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
713 myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
715 myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
718 print content['error']['description']
721 def instance_scenario_list(args):
722 #print "instance-scenario-list",args
726 tenant = _get_tenant()
728 toshow = _get_item_uuid("instances", args.name, tenant)
729 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
731 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
732 mano_response = requests.get(URLrequest)
733 logger.debug("openmano response: %s", mano_response.text )
734 content = mano_response.json()
735 #print json.dumps(content, indent=4)
736 if args.verbose==None:
739 result = 0 if mano_response.status_code==200 else mano_response.status_code
740 if mano_response.status_code == 200:
742 if args.verbose >= 3:
743 print yaml.safe_dump(content, indent=4, default_flow_style=False)
745 if len(content['instances']) == 0:
746 print "No scenario instances were found."
748 for instance in content['instances']:
749 myoutput = "%s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20))
751 myoutput = "%s %s" %(myoutput, instance['created_at'].ljust(20))
754 print "Description: %s" %instance['description']
757 print yaml.safe_dump(content, indent=4, default_flow_style=False)
760 print "%s %s %s" %(instance['uuid'].ljust(38),instance['name'].ljust(20),instance['created_at'].ljust(20))
761 print "Description: %s" %instance['description']
762 print "Template scenario id: %s" %instance['scenario_id']
763 print "Template scenario name: %s" %instance['scenario_name']
764 print "---------------------------------------"
765 print "VNF instances: %d" %len(instance['vnfs'])
766 for vnf in instance['vnfs']:
767 #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))
768 print " %s %s Template vnf id: %s" %(vnf['uuid'].ljust(38), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
769 if len(instance['nets'])>0:
770 print "---------------------------------------"
771 print "Internal nets:"
772 for net in instance['nets']:
774 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
775 print "---------------------------------------"
776 print "External nets:"
777 for net in instance['nets']:
778 if not net['created']:
779 print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id'])
780 print "---------------------------------------"
781 print "VM instances:"
782 for vnf in instance['vnfs']:
783 for vm in vnf['vms']:
784 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'])
786 print content['error']['description']
788 print yaml.safe_dump(content, indent=4, default_flow_style=False)
791 def instance_scenario_status(args):
792 print "instance-scenario-status"
795 def instance_scenario_delete(args):
799 tenant = _get_tenant()
800 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
801 #print "instance-scenario-delete",args
803 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
804 if not (len(r)>0 and r[0].lower()=="y"):
806 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
807 mano_response = requests.delete(URLrequest)
808 logger.debug("openmano response: %s", mano_response.text )
809 result = 0 if mano_response.status_code==200 else mano_response.status_code
810 content = mano_response.json()
811 #print json.dumps(content, indent=4)
812 if mano_response.status_code == 200:
813 print content['result']
815 print content['error']['description']
818 def instance_scenario_action(args):
819 #print "instance-scenario-action", args
820 tenant = _get_tenant()
821 toact = _get_item_uuid("instances", args.name, tenant=tenant)
823 action[ args.action ] = args.param
825 action["vnfs"] = args.vnf
827 action["vms"] = args.vm
829 headers_req = {'content-type': 'application/json'}
830 payload_req = json.dumps(action, indent=4)
831 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
832 logger.debug("openmano request: %s", payload_req)
833 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
834 logger.debug("openmano response: %s", mano_response.text )
835 result = 0 if mano_response.status_code==200 else mano_response.status_code
836 content = mano_response.json()
837 #print json.dumps(content, indent=4)
838 if mano_response.status_code == 200:
840 print yaml.safe_dump(content, indent=4, default_flow_style=False)
842 for uuid,c in content.iteritems():
843 print "%s %s %s" %(uuid.ljust(38), c['name'].ljust(20),c['description'].ljust(20))
845 print content['error']['description']
849 def instance_vnf_list(args):
850 print "instance-vnf-list"
853 def instance_vnf_status(args):
854 print "instance-vnf-status"
857 def tenant_create(args):
858 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
859 tenant_dict={"name": args.name}
860 if args.description!=None:
861 tenant_dict["description"] = args.description
862 payload_req = json.dumps( {"tenant": tenant_dict })
866 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
867 logger.debug("openmano request: %s", payload_req)
868 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
869 logger.debug("openmano response: %s", mano_response.text )
870 return _print_verbose(mano_response, args.verbose)
872 def tenant_list(args):
873 #print "tenant-list",args
875 toshow = _get_item_uuid("tenants", args.name)
876 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
878 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
879 mano_response = requests.get(URLrequest)
880 logger.debug("openmano response: %s", mano_response.text )
881 if args.verbose==None:
885 return _print_verbose(mano_response, args.verbose)
887 def tenant_delete(args):
888 #print "tenant-delete",args
889 todelete = _get_item_uuid("tenants", args.name)
891 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
892 if not (len(r)>0 and r[0].lower()=="y"):
894 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
895 mano_response = requests.delete(URLrequest)
896 logger.debug("openmano response: %s", mano_response.text )
897 result = 0 if mano_response.status_code==200 else mano_response.status_code
898 content = mano_response.json()
899 #print json.dumps(content, indent=4)
900 if mano_response.status_code == 200:
901 print content['result']
903 print content['error']['description']
906 def datacenter_attach(args):
907 tenant = _get_tenant()
908 datacenter = _get_datacenter(args.name)
909 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
912 if args.vim_tenant_id != None:
913 datacenter_dict['vim_tenant'] = args.vim_tenant_id
914 if args.vim_tenant_name != None:
915 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
916 if args.user != None:
917 datacenter_dict['vim_username'] = args.user
918 if args.password != None:
919 datacenter_dict['vim_password'] = args.password
920 if args.config!=None:
921 datacenter_dict["config"] = _load_file_or_yaml(args.config)
922 payload_req = json.dumps( {"datacenter": datacenter_dict })
926 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
927 logger.debug("openmano request: %s", payload_req)
928 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
929 logger.debug("openmano response: %s", mano_response.text )
930 result = _print_verbose(mano_response, args.verbose)
931 #provide addional information if error
932 if mano_response.status_code != 200:
933 content = mano_response.json()
934 if "already in use for 'name'" in content['error']['description'] and \
935 "to database vim_tenants table" in content['error']['description']:
936 print "Try to specify a different name with --vim-tenant-name"
940 def datacenter_edit_vim_tenant(args):
941 tenant = _get_tenant()
942 datacenter = _get_datacenter(args.name)
943 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
945 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
946 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
949 if args.vim_tenant_id != None:
950 datacenter_dict['vim_tenant'] = args.vim_tenant_id
951 if args.vim_tenant_name != None:
952 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
953 if args.user != None:
954 datacenter_dict['vim_username'] = args.user
955 if args.password != None:
956 datacenter_dict['vim_password'] = args.password
957 if args.config != None:
958 datacenter_dict["config"] = _load_file_or_yaml(args.config)
959 payload_req = json.dumps({"datacenter": datacenter_dict})
963 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
964 logger.debug("openmano request: %s", payload_req)
965 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
966 logger.debug("openmano response: %s", mano_response.text)
967 result = _print_verbose(mano_response, args.verbose)
971 def datacenter_detach(args):
975 tenant = _get_tenant()
976 datacenter = _get_datacenter(args.name, tenant)
977 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
978 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
979 mano_response = requests.delete(URLrequest, headers=headers_req)
980 logger.debug("openmano response: %s", mano_response.text )
981 content = mano_response.json()
982 #print json.dumps(content, indent=4)
983 result = 0 if mano_response.status_code==200 else mano_response.status_code
984 if mano_response.status_code == 200:
985 print content['result']
987 print content['error']['description']
990 def datacenter_create(args):
991 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
992 datacenter_dict={"name": args.name, "vim_url": args.url}
993 if args.description!=None:
994 datacenter_dict["description"] = args.description
996 datacenter_dict["type"] = args.type
998 datacenter_dict["vim_url_admin"] = args.url_admin
999 if args.config!=None:
1000 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1001 if args.sdn_controller!=None:
1002 tenant = _get_tenant()
1003 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1004 if not 'config' in datacenter_dict:
1005 datacenter_dict['config'] = {}
1006 datacenter_dict['config']['sdn-controller'] = sdn_controller
1007 payload_req = json.dumps( {"datacenter": datacenter_dict })
1011 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1012 logger.debug("openmano request: %s", payload_req)
1013 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1014 logger.debug("openmano response: %s", mano_response.text )
1015 return _print_verbose(mano_response, args.verbose)
1017 def datacenter_delete(args):
1018 #print "datacenter-delete",args
1019 todelete = _get_item_uuid("datacenters", args.name, "any")
1021 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1022 if not (len(r)>0 and r[0].lower()=="y"):
1024 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1025 mano_response = requests.delete(URLrequest)
1026 logger.debug("openmano response: %s", mano_response.text )
1027 result = 0 if mano_response.status_code==200 else mano_response.status_code
1028 content = mano_response.json()
1029 #print json.dumps(content, indent=4)
1030 if mano_response.status_code == 200:
1031 print content['result']
1033 print content['error']['description']
1037 def datacenter_list(args):
1038 #print "datacenter-list",args
1039 tenant='any' if args.all else _get_tenant()
1042 toshow = _get_item_uuid("datacenters", args.name, tenant)
1043 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1045 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1046 mano_response = requests.get(URLrequest)
1047 logger.debug("openmano response: %s", mano_response.text )
1048 if args.verbose==None:
1052 return _print_verbose(mano_response, args.verbose)
1055 def datacenter_sdn_port_mapping_set(args):
1056 tenant = _get_tenant()
1057 datacenter = _get_datacenter(args.name, tenant)
1058 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1061 raise OpenmanoCLIError(
1062 "No yaml/json has been provided specifying the SDN port mapping")
1063 sdn_port_mapping = _load_file_or_yaml(args.file)
1064 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1067 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1068 mano_response = requests.get(URLrequest)
1069 logger.debug("openmano response: %s", mano_response.text)
1070 port_mapping = mano_response.json()
1071 if mano_response.status_code != 200:
1072 str(mano_response.json())
1073 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1074 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1076 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1077 if not (len(r) > 0 and r[0].lower() == "y"):
1081 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1082 mano_response = requests.delete(URLrequest)
1083 logger.debug("openmano response: %s", mano_response.text)
1084 if mano_response.status_code != 200:
1085 return _print_verbose(mano_response, args.verbose)
1088 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1089 logger.debug("openmano request: %s", payload_req)
1090 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1091 logger.debug("openmano response: %s", mano_response.text)
1092 return _print_verbose(mano_response, args.verbose)
1095 def datacenter_sdn_port_mapping_list(args):
1096 tenant = _get_tenant()
1097 datacenter = _get_datacenter(args.name, tenant)
1099 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1100 mano_response = requests.get(URLrequest)
1101 logger.debug("openmano response: %s", mano_response.text)
1103 return _print_verbose(mano_response, 4)
1106 def datacenter_sdn_port_mapping_clear(args):
1107 tenant = _get_tenant()
1108 datacenter = _get_datacenter(args.name, tenant)
1111 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1112 if not (len(r) > 0 and r[0].lower() == "y"):
1115 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1116 mano_response = requests.delete(URLrequest)
1117 logger.debug("openmano response: %s", mano_response.text)
1119 return _print_verbose(mano_response, args.verbose)
1122 def sdn_controller_create(args):
1123 tenant = _get_tenant()
1124 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1126 if not (args.ip and args.port and args.dpid and args.type):
1127 raise OpenmanoCLIError("The following arguments are required: ip, port, dpid, type")
1129 controller_dict = {}
1130 controller_dict['name'] = args.name
1131 controller_dict['ip'] = args.ip
1132 controller_dict['port'] = int(args.port)
1133 controller_dict['dpid'] = args.dpid
1134 controller_dict['type'] = args.type
1135 if args.description != None:
1136 controller_dict['description'] = args.description
1137 if args.user != None:
1138 controller_dict['user'] = args.user
1139 if args.password != None:
1140 controller_dict['password'] = args.password
1142 payload_req = json.dumps({"sdn_controller": controller_dict})
1146 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1147 logger.debug("openmano request: %s", payload_req)
1148 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1149 logger.debug("openmano response: %s", mano_response.text)
1150 result = _print_verbose(mano_response, args.verbose)
1154 def sdn_controller_edit(args):
1155 tenant = _get_tenant()
1156 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1157 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1159 controller_dict = {}
1161 controller_dict['name'] = args.new_name
1163 controller_dict['ip'] = args.ip
1165 controller_dict['port'] = int(args.port)
1167 controller_dict['dpid'] = args.dpid
1169 controller_dict['type'] = args.type
1170 if args.description:
1171 controller_dict['description'] = args.description
1173 controller_dict['user'] = args.user
1175 controller_dict['password'] = args.password
1177 if not controller_dict:
1178 raise OpenmanoCLIError("At least one parameter must be edited")
1181 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1182 if not (len(r) > 0 and r[0].lower() == "y"):
1185 payload_req = json.dumps({"sdn_controller": controller_dict})
1188 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1189 logger.debug("openmano request: %s", payload_req)
1190 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1191 logger.debug("openmano response: %s", mano_response.text)
1192 result = _print_verbose(mano_response, args.verbose)
1196 def sdn_controller_list(args):
1197 tenant = _get_tenant()
1198 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1201 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1202 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1204 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1206 mano_response = requests.get(URLrequest)
1207 logger.debug("openmano response: %s", mano_response.text )
1208 if args.verbose==None:
1213 # json.dumps(mano_response.json(), indent=4)
1214 return _print_verbose(mano_response, args.verbose)
1217 def sdn_controller_delete(args):
1218 tenant = _get_tenant()
1219 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1222 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1223 if not (len(r) > 0 and r[0].lower() == "y"):
1226 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1227 mano_response = requests.delete(URLrequest)
1228 logger.debug("openmano response: %s", mano_response.text)
1229 return _print_verbose(mano_response, args.verbose)
1231 def vim_action(args):
1232 #print "datacenter-net-action",args
1233 tenant = _get_tenant()
1234 datacenter = _get_datacenter(args.datacenter, tenant)
1235 if args.verbose==None:
1237 if args.action=="list":
1238 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1241 URLrequest += "/" + args.name
1242 mano_response = requests.get(URLrequest)
1243 logger.debug("openmano response: %s", mano_response.text )
1244 return _print_verbose(mano_response, args.verbose)
1245 elif args.action=="delete":
1246 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1247 mano_response = requests.delete(URLrequest)
1248 logger.debug("openmano response: %s", mano_response.text )
1249 result = 0 if mano_response.status_code==200 else mano_response.status_code
1250 content = mano_response.json()
1251 #print json.dumps(content, indent=4)
1252 if mano_response.status_code == 200:
1253 print content['result']
1255 print content['error']['description']
1257 elif args.action=="create":
1258 headers_req = {'content-type': 'application/yaml'}
1260 create_dict = _load_file_or_yaml(args.file)
1261 if args.item not in create_dict:
1262 create_dict = {args.item: create_dict}
1264 create_dict = {args.item:{}}
1266 create_dict[args.item]['name'] = args.name
1267 #if args.description:
1268 # create_dict[args.item]['description'] = args.description
1269 if args.item=="network":
1271 create_dict[args.item]['bind_net'] = args.bind_net
1273 create_dict[args.item]['type'] = args.type
1275 create_dict[args.item]['shared'] = args.shared
1276 if "name" not in create_dict[args.item]:
1277 print "You must provide a name in the descriptor file or with the --name option"
1279 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1280 logger.debug("openmano request: %s", payload_req)
1281 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1282 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1283 logger.debug("openmano response: %s", mano_response.text )
1284 if args.verbose==None:
1286 return _print_verbose(mano_response, args.verbose)
1289 def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1290 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1292 URLrequest += "/" + tenant
1294 URLrequest += "/vim/" + datacenter
1296 URLrequest += "/" + item +"s"
1298 URLrequest += "/" + item_name_id
1299 mano_response = requests.get(URLrequest)
1300 logger.debug("openmano response: %s", mano_response.text )
1302 return mano_response
1305 def vim_net_sdn_attach(args):
1306 #Verify the network exists in the vim
1307 tenant = _get_tenant()
1308 datacenter = _get_datacenter(args.datacenter, tenant)
1309 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1310 content = yaml.load(result.content)
1311 if 'networks' in content:
1312 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1313 if 'error' in content:
1314 raise OpenmanoCLIError(yaml.safe_dump(content))
1315 network_uuid = content['network']['id']
1317 #Make call to attach the dataplane port to the SND network associated to the vim network
1318 headers_req = {'content-type': 'application/yaml'}
1319 payload_req = {'port': args.port}
1321 payload_req['vlan'] = int(args.vlan)
1323 payload_req['mac'] = args.mac
1325 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1326 logger.debug("openmano request: %s", payload_req)
1327 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1328 logger.debug("openmano response: %s", mano_response.text)
1329 result = _print_verbose(mano_response, args.verbose)
1333 def vim_net_sdn_detach(args):
1334 if not args.all and not args.id:
1335 print "--all or --id must be used"
1338 # Verify the network exists in the vim
1339 tenant = _get_tenant()
1340 datacenter = _get_datacenter(args.datacenter, tenant)
1341 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1342 content = yaml.load(result.content)
1343 if 'networks' in content:
1344 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1345 if 'error' in content:
1346 raise OpenmanoCLIError(yaml.safe_dump(content))
1347 network_uuid = content['network']['id']
1350 r = raw_input("Confirm action' (y/N)? ")
1351 if len(r) == 0 or r[0].lower() != "y":
1355 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1356 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1358 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1359 mano_host, mano_port, tenant, datacenter, network_uuid)
1360 mano_response = requests.delete(URLrequest)
1361 logger.debug("openmano response: %s", mano_response.text)
1362 result = _print_verbose(mano_response, args.verbose)
1366 def datacenter_net_action(args):
1367 if args.action == "net-update":
1368 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1370 args.action = "netmap-delete"
1373 r = datacenter_netmap_action(args)
1376 args.action = "netmap-import"
1377 r = datacenter_netmap_action(args)
1380 if args.action == "net-edit":
1381 args.netmap = args.net
1383 elif args.action == "net-list":
1385 elif args.action == "net-delete":
1386 args.netmap = args.net
1389 args.action = "netmap" + args.action[3:]
1392 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1394 return datacenter_netmap_action(args)
1396 def datacenter_netmap_action(args):
1397 tenant = _get_tenant()
1398 datacenter = _get_datacenter(args.datacenter, tenant)
1399 #print "datacenter_netmap_action",args
1401 if args.verbose==None:
1403 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1404 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1406 if args.action=="netmap-list":
1408 URLrequest += "/" + args.netmap
1410 mano_response = requests.get(URLrequest)
1412 elif args.action=="netmap-delete":
1413 if args.netmap and args.all:
1414 print "you can not use a netmap name and the option --all at the same time"
1417 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1418 URLrequest += "/" + args.netmap
1420 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1422 print "you must specify a netmap name or the option --all"
1425 r = raw_input(force_text)
1426 if len(r)>0 and r[0].lower()=="y":
1430 mano_response = requests.delete(URLrequest, headers=headers_req)
1431 elif args.action=="netmap-import":
1433 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1434 if len(r)>0 and r[0].lower()=="y":
1438 URLrequest += "/upload"
1439 mano_response = requests.post(URLrequest, headers=headers_req)
1440 elif args.action=="netmap-edit" or args.action=="netmap-create":
1442 payload = _load_file_or_yaml(args.file)
1445 if "netmap" not in payload:
1446 payload = {"netmap": payload}
1448 payload["netmap"]["name"] = args.name
1450 payload["netmap"]["vim_id"] = args.vim_id
1451 if args.action=="netmap-create" and args.vim_name:
1452 payload["netmap"]["vim_name"] = args.vim_name
1453 payload_req = json.dumps(payload)
1454 logger.debug("openmano request: %s", payload_req)
1456 if args.action=="netmap-edit" and not args.force:
1457 if len(payload["netmap"]) == 0:
1458 print "You must supply some parameter to edit"
1460 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1461 if len(r)>0 and r[0].lower()=="y":
1465 URLrequest += "/" + args.netmap
1466 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1467 else: #netmap-create
1468 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1469 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1471 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1473 logger.debug("openmano response: %s", mano_response.text )
1474 return _print_verbose(mano_response, args.verbose)
1477 def element_edit(args):
1478 element = _get_item_uuid(args.element, args.name)
1479 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1480 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1481 payload=_load_file_or_yaml(args.file)
1482 if args.element[:-1] not in payload:
1483 payload = {args.element[:-1]: payload }
1484 payload_req = json.dumps(payload)
1487 if not args.force or (args.name==None and args.filer==None):
1488 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1489 if len(r)>0 and r[0].lower()=="y":
1493 logger.debug("openmano request: %s", payload_req)
1494 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1495 logger.debug("openmano response: %s", mano_response.text )
1496 if args.verbose==None:
1500 return _print_verbose(mano_response, args.verbose)
1503 def datacenter_edit(args):
1504 tenant = _get_tenant()
1505 element = _get_item_uuid('datacenters', args.name, tenant)
1506 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1507 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1509 has_arguments = False
1510 if args.file != None:
1511 has_arguments = True
1512 payload = _load_file_or_yaml(args.file)
1516 if args.sdn_controller != None:
1517 has_arguments = True
1518 if not 'config' in payload:
1519 payload['config'] = {}
1520 if not 'sdn-controller' in payload['config']:
1521 payload['config']['sdn-controller'] = {}
1522 if args.sdn_controller == 'null':
1523 payload['config']['sdn-controller'] = None
1525 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1527 if not has_arguments:
1528 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1530 if 'datacenter' not in payload:
1531 payload = {'datacenter': payload}
1532 payload_req = json.dumps(payload)
1535 if not args.force or (args.name == None and args.filer == None):
1536 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1537 if len(r) > 0 and r[0].lower() == "y":
1541 logger.debug("openmano request: %s", payload_req)
1542 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1543 logger.debug("openmano response: %s", mano_response.text)
1544 if args.verbose == None:
1546 if args.name != None:
1548 return _print_verbose(mano_response, args.verbose)
1552 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1553 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1555 mano_response = requests.get(URLrequest, headers=headers_req)
1556 logger.debug("openmano response: %s", mano_response.text)
1557 print mano_response.text
1564 if __name__=="__main__":
1566 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1567 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1568 mano_port = os.getenv('OPENMANO_PORT',"9090")
1569 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1571 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1572 main_parser.add_argument('--version', action='version', help="get version of this client",
1573 version='%(prog)s client version ' + __version__ +
1574 " (Note: use '%(prog)s version' to get server version)")
1576 subparsers = main_parser.add_subparsers(help='commands')
1578 parent_parser = argparse.ArgumentParser(add_help=False)
1579 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1580 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1582 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1583 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1584 config_parser.set_defaults(func=config)
1586 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1587 version_parser.set_defaults(func=version)
1589 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1590 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1591 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1592 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1593 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1594 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1595 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1596 vnf_create_parser.set_defaults(func=vnf_create)
1598 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1599 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1600 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1601 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1602 vnf_list_parser.set_defaults(func=vnf_list)
1604 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1605 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1606 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1607 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1608 vnf_delete_parser.set_defaults(func=vnf_delete)
1610 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1611 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1612 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1613 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1614 scenario_create_parser.set_defaults(func=scenario_create)
1616 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1617 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1618 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1619 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1620 scenario_list_parser.set_defaults(func=scenario_list)
1622 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1623 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1624 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1625 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1626 scenario_delete_parser.set_defaults(func=scenario_delete)
1628 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1629 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1630 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1631 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1632 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1633 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1634 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1636 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1637 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1638 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1639 scenario_deploy_parser.set_defaults(func=scenario_verify)
1641 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1642 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1643 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1644 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1645 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1646 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1647 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")
1648 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")
1649 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")
1650 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")
1651 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1652 instance_scenario_create_parser.set_defaults(func=instance_create)
1654 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1655 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1656 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1657 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1659 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)")
1660 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1661 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1662 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1663 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1665 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1666 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1667 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1668 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console"],\
1669 help="action to send")
1670 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1671 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1672 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1673 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1675 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1676 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1677 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1679 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1680 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1681 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1682 tenant_create_parser.set_defaults(func=tenant_create)
1684 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1685 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1686 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1687 tenant_delete_parser.set_defaults(func=tenant_delete)
1689 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1690 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1691 tenant_list_parser.set_defaults(func=tenant_list)
1693 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1694 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1695 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1696 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1697 element_edit_parser.set_defaults(func=element_edit, element='tenants')
1699 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1700 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1701 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1702 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1703 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1704 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1705 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1706 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1707 datacenter_create_parser.set_defaults(func=datacenter_create)
1709 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1710 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1711 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1712 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1714 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1715 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1716 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1717 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1718 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1719 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1720 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1722 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1723 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1724 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1725 datacenter_list_parser.set_defaults(func=datacenter_list)
1727 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1728 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1729 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1730 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1731 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1732 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1733 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1734 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1736 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1737 help="Edit the association of a datacenter to the operating tenant")
1738 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1739 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1740 help="specify a datacenter tenant to use. A new one is created by default")
1741 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1742 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1743 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1744 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1745 help="aditional configuration in json/yaml format")
1746 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1748 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1749 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1750 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1751 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1753 #=======================datacenter_sdn_port_mapping_xxx section=======================
1754 #datacenter_sdn_port_mapping_set
1755 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1756 parents=[parent_parser],
1757 help="Load a file with the mapping of physical ports "
1758 "and the ports of the dataplaneswitch controlled "
1760 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1761 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1762 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1763 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1764 help="forces overwriting without asking")
1765 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1767 #datacenter_sdn_port_mapping_list
1768 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1769 parents=[parent_parser],
1770 help="Show the SDN port mapping in a datacenter")
1771 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1772 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1774 # datacenter_sdn_port_mapping_clear
1775 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1776 parents=[parent_parser],
1777 help="Clean the the SDN port mapping in a datacenter")
1778 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1779 help="specifies the datacenter")
1780 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1781 help="forces clearing without asking")
1782 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1783 # =======================
1785 # =======================sdn_controller_xxx section=======================
1786 # sdn_controller_create
1787 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1788 help="Creates an SDN controller entity within RO")
1789 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1790 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1791 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1792 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1793 sdn_controller_create_parser.add_argument("--dpid", action="store",
1794 help="DPID of the dataplane switch controlled by this SDN controller")
1795 sdn_controller_create_parser.add_argument("--type", action="store",
1796 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1797 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1798 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1799 help="password credentials for the SDN controller")
1800 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1802 # sdn_controller_edit
1803 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1804 help="Update one or more options of a SDN controller")
1805 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1806 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1808 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1809 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1810 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1811 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1812 help="DPID of the dataplane switch controlled by this SDN controller")
1813 sdn_controller_edit_parser.add_argument("--type", action="store",
1814 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1815 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1816 sdn_controller_edit_parser.add_argument("--password", action="store",
1817 help="password credentials for the SDN controller", dest='password')
1818 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1819 #TODO: include option --file
1820 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1822 #sdn_controller_list
1823 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1824 parents=[parent_parser],
1825 help="List the SDN controllers")
1826 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1827 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1829 # sdn_controller_delete
1830 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1831 parents=[parent_parser],
1832 help="Delete the the SDN controller")
1833 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1834 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1835 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1836 # =======================
1838 action_dict={'net-update': 'retrieves external networks from datacenter',
1839 'net-edit': 'edits an external network',
1840 'net-delete': 'deletes an external network',
1841 'net-list': 'lists external networks from a datacenter'
1843 for item in action_dict:
1844 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1845 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1846 if item=='net-edit' or item=='net-delete':
1847 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1848 if item=='net-edit':
1849 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1850 if item!='net-list':
1851 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1852 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1855 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1856 'netmap-create': 'create a new network senario netmap',
1857 'netmap-edit': 'edit name of a network senario netmap',
1858 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1859 'netmap-list': 'list/show network scenario netmaps'
1861 for item in action_dict:
1862 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1863 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1864 #if item=='net-add':
1865 # datacenter_action_parser.add_argument("net", help="name of the network")
1866 if item=='netmap-delete':
1867 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1868 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1869 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1870 if item=='netmap-edit':
1871 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1872 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1873 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1874 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1875 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1876 if item=='netmap-list':
1877 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1878 if item=='netmap-create':
1879 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1880 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1881 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1882 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1883 if item=='netmap-import':
1884 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1885 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1887 # =======================vim_net_sdn_xxx section=======================
1888 # vim_net_sdn_attach
1889 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
1890 parents=[parent_parser],
1891 help="Specify the port to access to an external network using SDN")
1892 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
1893 help="Name/id of the network in the vim that will be used to connect to the external network")
1894 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
1895 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
1896 vim_net_sdn_attach_parser.add_argument("--mac", action="store", help="Specifies the MAC (if known) of the physical device that will be reachable by this external port")
1897 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1898 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
1900 # vim_net_sdn_detach
1901 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
1902 parents=[parent_parser],
1903 help="Remove the port information to access to an external network using SDN")
1905 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
1906 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
1907 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
1908 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
1909 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1910 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
1911 # =======================
1913 for item in ("network", "tenant", "image"):
1915 command_name = 'vim-net'
1917 command_name = 'vim-'+item
1918 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
1919 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
1920 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1921 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
1923 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
1924 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
1925 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1926 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
1928 if item == "network" or item == "tenant":
1929 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
1930 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
1931 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
1932 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
1934 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
1935 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
1936 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>'")
1938 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
1939 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
1941 argcomplete.autocomplete(main_parser)
1944 args = main_parser.parse_args()
1946 level = logging.CRITICAL
1947 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
1948 if "debug" in args and args.debug:
1949 level = logging.DEBUG
1950 logging.basicConfig(format=streamformat, level= level)
1951 logger = logging.getLogger('mano')
1952 logger.setLevel(level)
1953 result = args.func(args)
1956 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
1957 except (requests.exceptions.ConnectionError):
1958 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
1960 except (KeyboardInterrupt):
1961 print 'Exiting openmano'
1963 except (SystemExit, ArgumentParserError):
1965 except OpenmanoCLIError as e: