2 # -*- coding: utf-8 -*-
3 # PYTHON_ARGCOMPLETE_OK
6 # Copyright 2015 Telefonica Investigacion 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.24-r534"
32 version_date = "Nov 2018"
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 = "{:38} {:20}".format(uuid, name)
137 if content.get("status"):
138 myoutput += " {:20}".format(content['status'])
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 += " {:20}".format(content['created_at'])
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: {:29}".format(content['type'])
152 if content.get('description'):
153 myoutput += new_line + " Description: {:20}".format(content['description'])
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:
229 if item_name_id.startswith("osm_id=") and i.get("osm_id") == item_name_id[7:]:
233 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
235 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
238 # def check_valid_uuid(uuid):
239 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
241 # js_v(uuid, id_schema)
243 # except js_e.ValidationError:
246 def _get_tenant(tenant_name_id = None):
247 if not tenant_name_id:
248 tenant_name_id = mano_tenant
250 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
251 return _get_item_uuid("tenants", tenant_name_id)
253 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
254 if not datacenter_name_id:
255 datacenter_name_id = mano_datacenter
256 if not datacenter_name_id:
257 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
258 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
260 def vnf_create(args):
261 #print "vnf-create",args
262 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
263 tenant = _get_tenant()
264 myvnf = _load_file_or_yaml(args.file)
266 if "vnfd:vnfd-catalog" in myvnf or "vnfd-catalog" in myvnf:
269 vnfd_catalog = myvnf.get("vnfd:vnfd-catalog")
271 vnfd_catalog = myvnf.get("vnfd-catalog")
272 vnfds = vnfd_catalog.get("vnfd:vnfd")
274 vnfds = vnfd_catalog.get("vnfd")
276 vdu_list = vnfd.get("vdu")
282 vdu_list = vnfd.get("VNFC")
284 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
285 # TODO, change this for API v3
289 vnfd['name'] = args.name
291 vnfd['description'] = args.description
295 for image_path_ in args.image_path.split(","):
296 # print "image-path", image_path_
297 if api_version == "/v3":
298 if vdu_list[index].get("image"):
299 vdu_list[index]['image'] = image_path_
300 if "image-checksum" in vdu_list[index]:
301 del vdu_list[index]["image-checksum"]
302 else: # image name in volumes
303 vdu_list[index]["volumes"][0]["image"] = image_path_
304 if "image-checksum" in vdu_list[index]["volumes"][0]:
305 del vdu_list[index]["volumes"][0]["image-checksum"]
307 vdu_list[index]['VNFC image'] = image_path_
308 if "image name" in vdu_list[index]:
309 del vdu_list[index]["image name"]
310 if "image checksum" in vdu_list[index]:
311 del vdu_list[index]["image checksum"]
313 if args.image_name: # image name precedes if both are supplied
315 for image_name_ in args.image_name.split(","):
316 if api_version == "/v3":
317 if vdu_list[index].get("image"):
318 vdu_list[index]['image'] = image_name_
319 if "image-checksum" in vdu_list[index]:
320 del vdu_list[index]["image-checksum"]
321 if vdu_list[index].get("alternative-images"):
322 for a_image in vdu_list[index]["alternative-images"]:
323 a_image['image'] = image_name_
324 if "image-checksum" in a_image:
325 del a_image["image-checksum"]
326 else: # image name in volumes
327 vdu_list[index]["volumes"][0]["image"] = image_name_
328 if "image-checksum" in vdu_list[index]["volumes"][0]:
329 del vdu_list[index]["volumes"][0]["image-checksum"]
331 vdu_list[index]['image name'] = image_name_
332 if "VNFC image" in vdu_list[index]:
333 del vdu_list[index]["VNFC image"]
335 if args.image_checksum:
337 for image_checksum_ in args.image_checksum.split(","):
338 if api_version == "/v3":
339 if vdu_list[index].get("image"):
340 vdu_list[index]['image-checksum'] = image_checksum_
341 if vdu_list[index].get("alternative-images"):
342 for a_image in vdu_list[index]["alternative-images"]:
343 a_image['image-checksum'] = image_checksum_
344 else: # image name in volumes
345 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
347 vdu_list[index]['image checksum'] = image_checksum_
349 except (KeyError, TypeError), e:
350 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
351 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
352 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
353 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
354 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
355 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
356 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
357 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
358 else: error_pos="wrong format"
359 print "Wrong VNF descriptor: " + error_pos
361 payload_req = json.dumps(myvnf)
365 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
366 logger.debug("openmano request: %s", payload_req)
367 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
368 logger.debug("openmano response: %s", mano_response.text )
370 return _print_verbose(mano_response, args.verbose)
373 #print "vnf-list",args
377 tenant = _get_tenant()
379 toshow = _get_item_uuid("vnfs", args.name, tenant)
380 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
382 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
383 mano_response = requests.get(URLrequest)
384 logger.debug("openmano response: %s", mano_response.text )
385 content = mano_response.json()
386 # print json.dumps(content, indent=4)
387 if args.verbose==None:
389 result = 0 if mano_response.status_code==200 else mano_response.status_code
390 if mano_response.status_code == 200:
392 if args.verbose >= 3:
393 print yaml.safe_dump(content, indent=4, default_flow_style=False)
395 if len(content['vnfs']) == 0:
396 print "No VNFs were found."
397 return 404 # HTTP_Not_Found
398 for vnf in content['vnfs']:
399 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
400 if vnf.get('osm_id') or args.verbose >= 1:
401 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
402 if args.verbose >= 1:
403 myoutput += " {}".format(vnf['created_at'])
405 if args.verbose >= 2:
406 print (" Description: {}".format(vnf['description']))
407 # print (" VNF descriptor file: {}".format(vnf['path']))
410 print yaml.safe_dump(content, indent=4, default_flow_style=False)
413 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
415 print (" Description: {}".format(vnf['description']))
416 # print " VNF descriptor file: %s" %vnf['path']
418 for vm in vnf['VNFC']:
419 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
420 if len(vnf['nets']) > 0:
421 print (" Internal nets:")
422 for net in vnf['nets']:
423 print (" {:20} {}".format(net['name'], net['description']))
424 if len(vnf['external-connections']) > 0:
425 print (" External interfaces:")
426 for interface in vnf['external-connections']:
427 print (" {:20} {:20} {:20} {:14}".format(
428 interface['external_name'], interface['vm_name'],
429 interface['internal_name'],
430 interface.get('vpci') if interface.get('vpci') else ""))
432 print content['error']['description']
434 print yaml.safe_dump(content, indent=4, default_flow_style=False)
437 def vnf_delete(args):
438 #print "vnf-delete",args
442 tenant = _get_tenant()
443 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
445 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
446 if not (len(r)>0 and r[0].lower()=="y"):
448 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
449 mano_response = requests.delete(URLrequest)
450 logger.debug("openmano response: %s", mano_response.text )
451 result = 0 if mano_response.status_code==200 else mano_response.status_code
452 content = mano_response.json()
453 #print json.dumps(content, indent=4)
454 if mano_response.status_code == 200:
455 print content['result']
457 print content['error']['description']
460 def scenario_create(args):
461 # print "scenario-create",args
462 tenant = _get_tenant()
463 headers_req = {'content-type': 'application/yaml'}
464 myscenario = _load_file_or_yaml(args.file)
465 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
468 nsd_catalog = myscenario.get("nsd:nsd-catalog")
470 nsd_catalog = myscenario.get("nsd-catalog")
471 nsds = nsd_catalog.get("nsd:nsd")
473 nsds = nsd_catalog.get("nsd")
478 if "scenario" in myscenario:
479 nsd = myscenario["scenario"]
482 # TODO modify for API v3
484 nsd['name'] = args.name
486 nsd['description'] = args.description
487 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
488 encoding='utf-8', allow_unicode=True)
491 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
492 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
493 logger.debug("openmano request: %s", payload_req)
494 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
495 logger.debug("openmano response: %s", mano_response.text )
496 return _print_verbose(mano_response, args.verbose)
498 def scenario_list(args):
499 #print "scenario-list",args
503 tenant = _get_tenant()
505 toshow = _get_item_uuid("scenarios", args.name, tenant)
506 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
508 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
509 mano_response = requests.get(URLrequest)
510 logger.debug("openmano response: %s", mano_response.text )
511 content = mano_response.json()
512 #print json.dumps(content, indent=4)
513 if args.verbose==None:
516 result = 0 if mano_response.status_code==200 else mano_response.status_code
517 if mano_response.status_code == 200:
519 if args.verbose >= 3:
520 print yaml.safe_dump(content, indent=4, default_flow_style=False)
522 if len(content['scenarios']) == 0:
523 print "No scenarios were found."
524 return 404 #HTTP_Not_Found
525 for scenario in content['scenarios']:
526 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
527 if scenario.get('osm_id') or args.verbose >= 1:
528 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
529 if args.verbose >= 1:
530 myoutput += " {}".format(scenario['created_at'])
533 print (" Description: {}".format(scenario['description']))
536 print yaml.safe_dump(content, indent=4, default_flow_style=False)
538 scenario = content['scenario']
539 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
540 scenario['created_at']))
541 print (" Description: {}".format(scenario['description']))
543 for vnf in scenario['vnfs']:
544 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
546 if len(scenario['nets']) > 0:
548 for net in scenario['nets']:
549 description = net['description']
550 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
553 if net.get('vim_id'):
554 vim_id = " vim_id=" + net["vim_id"]
557 external = " external"
558 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
560 print (content['error']['description'])
562 print yaml.safe_dump(content, indent=4, default_flow_style=False)
565 def scenario_delete(args):
566 #print "scenario-delete",args
570 tenant = _get_tenant()
571 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
573 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
574 if not (len(r)>0 and r[0].lower()=="y"):
576 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
577 mano_response = requests.delete(URLrequest)
578 logger.debug("openmano response: %s", mano_response.text )
579 result = 0 if mano_response.status_code==200 else mano_response.status_code
580 content = mano_response.json()
581 #print json.dumps(content, indent=4)
582 if mano_response.status_code == 200:
583 print content['result']
585 print content['error']['description']
588 def scenario_deploy(args):
589 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
592 args.netmap_use = None
593 args.netmap_create = None
595 args.keypair_auto = None
596 return instance_create(args)
598 # #print "scenario-deploy",args
599 # headers_req = {'content-type': 'application/json'}
603 # actionCmd="reserve"
604 # action[actionCmd] = {}
605 # action[actionCmd]["instance_name"] = args.name
606 # if args.datacenter != None:
607 # action[actionCmd]["datacenter"] = args.datacenter
608 # elif mano_datacenter != None:
609 # action[actionCmd]["datacenter"] = mano_datacenter
611 # if args.description:
612 # action[actionCmd]["description"] = args.description
613 # payload_req = json.dumps(action, indent=4)
616 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
617 # logger.debug("openmano request: %s", payload_req)
618 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
619 # logger.debug("openmano response: %s", mano_response.text )
620 # if args.verbose==None:
623 # result = 0 if mano_response.status_code==200 else mano_response.status_code
624 # content = mano_response.json()
625 # #print json.dumps(content, indent=4)
626 # if args.verbose >= 3:
627 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
630 # if mano_response.status_code == 200:
631 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
632 # if args.verbose >=1:
633 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
634 # if args.verbose >=2:
635 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
638 # print "To check the status, run the following command:"
639 # print "openmano instance-scenario-list <instance_id>"
641 # print content['error']['description']
644 def scenario_verify(args):
645 #print "scenario-verify",args
646 tenant = _get_tenant()
647 headers_req = {'content-type': 'application/json'}
649 action["verify"] = {}
650 action["verify"]["instance_name"] = "scen-verify-return5"
651 payload_req = json.dumps(action, indent=4)
654 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
655 logger.debug("openmano request: %s", payload_req)
656 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
657 logger.debug("openmano response: %s", mano_response.text )
659 result = 0 if mano_response.status_code==200 else mano_response.status_code
660 content = mano_response.json()
661 #print json.dumps(content, indent=4)
662 if mano_response.status_code == 200:
663 print content['result']
665 print content['error']['description']
668 def instance_create(args):
669 tenant = _get_tenant()
670 headers_req = {'content-type': 'application/yaml'}
671 myInstance={"instance": {}, "schema_version": "0.1"}
673 instance_dict = _load_file_or_yaml(args.file)
674 if "instance" not in instance_dict:
675 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
677 myInstance = instance_dict
679 myInstance["instance"]['name'] = args.name
681 myInstance["instance"]['description'] = args.description
683 myInstance["instance"]['action'] = "reserve"
685 datacenter = myInstance["instance"].get("datacenter")
686 if args.datacenter != None:
687 datacenter = args.datacenter
688 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
690 scenario = myInstance["instance"].get("scenario")
691 if args.scenario != None:
692 scenario = args.scenario
694 print "you must provide a scenario in the file descriptor or with --scenario"
696 if isinstance(scenario, str):
697 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
699 if "networks" not in myInstance["instance"]:
700 myInstance["instance"]["networks"] = {}
701 for net in args.netmap_use:
702 net_comma_list = net.split(",")
703 for net_comma in net_comma_list:
704 net_tuple = net_comma.split("=")
705 if len(net_tuple) != 2:
706 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
708 net_scenario = net_tuple[0].strip()
709 net_datacenter = net_tuple[1].strip()
710 if net_scenario not in myInstance["instance"]["networks"]:
711 myInstance["instance"]["networks"][net_scenario] = {}
712 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
713 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
714 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
715 if args.netmap_create:
716 if "networks" not in myInstance["instance"]:
717 myInstance["instance"]["networks"] = {}
718 for net in args.netmap_create:
719 net_comma_list = net.split(",")
720 for net_comma in net_comma_list:
721 net_tuple = net_comma.split("=")
722 if len(net_tuple) == 1:
723 net_scenario = net_tuple[0].strip()
724 net_datacenter = None
725 elif len(net_tuple) == 2:
726 net_scenario = net_tuple[0].strip()
727 net_datacenter = net_tuple[1].strip()
729 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
731 if net_scenario not in myInstance["instance"]["networks"]:
732 myInstance["instance"]["networks"][net_scenario] = {}
733 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
734 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
735 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
737 if "cloud-config" not in myInstance["instance"]:
738 myInstance["instance"]["cloud-config"] = {}
739 cloud_config = myInstance["instance"]["cloud-config"]
740 for key in args.keypair:
741 index = key.find(":")
743 if "key-pairs" not in cloud_config:
744 cloud_config["key-pairs"] = []
745 cloud_config["key-pairs"].append(key)
749 key_list = key_.split(",")
750 if "users" not in cloud_config:
751 cloud_config["users"] = []
752 cloud_config["users"].append({"name": user, "key-pairs": key_list })
753 if args.keypair_auto:
756 home = os.getenv("HOME")
757 user = os.getenv("USER")
758 files = os.listdir(home+'/.ssh')
760 if file[-4:] == ".pub":
761 with open(home+'/.ssh/'+file, 'r') as f:
762 keys.append(f.read())
764 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
766 except Exception as e:
767 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
770 if "cloud-config" not in myInstance["instance"]:
771 myInstance["instance"]["cloud-config"] = {}
772 cloud_config = myInstance["instance"]["cloud-config"]
773 if "key-pairs" not in cloud_config:
774 cloud_config["key-pairs"] = []
776 if "users" not in cloud_config:
777 cloud_config["users"] = []
778 cloud_config["users"].append({"name": user, "key-pairs": keys })
780 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
781 logger.debug("openmano request: %s", payload_req)
782 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
783 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
784 logger.debug("openmano response: %s", mano_response.text )
785 if args.verbose==None:
788 result = 0 if mano_response.status_code==200 else mano_response.status_code
789 content = mano_response.json()
790 #print json.dumps(content, indent=4)
791 if args.verbose >= 3:
792 print yaml.safe_dump(content, indent=4, default_flow_style=False)
795 if mano_response.status_code == 200:
796 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
798 myoutput = "{} {:20}".format(myoutput, content['created_at'])
800 myoutput = "{} {:30}".format(myoutput, content['description'])
803 print content['error']['description']
806 def instance_scenario_list(args):
807 #print "instance-scenario-list",args
811 tenant = _get_tenant()
813 toshow = _get_item_uuid("instances", args.name, tenant)
814 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
816 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
817 mano_response = requests.get(URLrequest)
818 logger.debug("openmano response: %s", mano_response.text )
819 content = mano_response.json()
820 #print json.dumps(content, indent=4)
821 if args.verbose==None:
824 result = 0 if mano_response.status_code==200 else mano_response.status_code
825 if mano_response.status_code == 200:
827 if args.verbose >= 3:
828 print yaml.safe_dump(content, indent=4, default_flow_style=False)
830 if len(content['instances']) == 0:
831 print "No scenario instances were found."
833 for instance in content['instances']:
834 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
836 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
839 print "Description: %s" %instance['description']
842 print yaml.safe_dump(content, indent=4, default_flow_style=False)
845 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
846 print ("Description: %s" %instance['description'])
847 print ("Template scenario id: {}".format(instance['scenario_id']))
848 print ("Template scenario name: {}".format(instance['scenario_name']))
849 print ("---------------------------------------")
850 print ("VNF instances: {}".format(len(instance['vnfs'])))
851 for vnf in instance['vnfs']:
852 #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))
853 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
854 if len(instance['nets'])>0:
855 print "---------------------------------------"
856 print "Internal nets:"
857 for net in instance['nets']:
859 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
860 print "---------------------------------------"
861 print "External nets:"
862 for net in instance['nets']:
863 if not net['created']:
864 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
865 print ("---------------------------------------")
866 print ("VM instances:")
867 for vnf in instance['vnfs']:
868 for vm in vnf['vms']:
869 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
870 vm['status'], vm['vim_vm_id']))
872 print content['error']['description']
874 print yaml.safe_dump(content, indent=4, default_flow_style=False)
877 def instance_scenario_status(args):
878 print "instance-scenario-status"
881 def instance_scenario_delete(args):
885 tenant = _get_tenant()
886 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
887 #print "instance-scenario-delete",args
889 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
890 if not (len(r)>0 and r[0].lower()=="y"):
892 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
893 mano_response = requests.delete(URLrequest)
894 logger.debug("openmano response: %s", mano_response.text )
895 result = 0 if mano_response.status_code==200 else mano_response.status_code
896 content = mano_response.json()
897 #print json.dumps(content, indent=4)
898 if mano_response.status_code == 200:
899 print content['result']
901 print content['error']['description']
904 def get_action(args):
906 tenant = _get_tenant()
909 if not args.instance:
912 instance_id =args.instance
915 action_id = "/" + args.id
916 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
918 mano_response = requests.get(URLrequest)
919 logger.debug("openmano response: %s", mano_response.text )
920 if args.verbose == None:
924 return _print_verbose(mano_response, args.verbose)
926 def instance_scenario_action(args):
927 #print "instance-scenario-action", args
928 tenant = _get_tenant()
929 toact = _get_item_uuid("instances", args.name, tenant=tenant)
931 action[ args.action ] = yaml.safe_load(args.param)
933 action["vnfs"] = args.vnf
935 action["vms"] = args.vm
937 headers_req = {'content-type': 'application/json'}
938 payload_req = json.dumps(action, indent=4)
939 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
940 logger.debug("openmano request: %s", payload_req)
941 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
942 logger.debug("openmano response: %s", mano_response.text )
943 result = 0 if mano_response.status_code==200 else mano_response.status_code
944 content = mano_response.json()
945 # print json.dumps(content, indent=4)
946 if mano_response.status_code == 200:
948 print yaml.safe_dump(content, indent=4, default_flow_style=False)
950 if "instance_action_id" in content:
951 print("instance_action_id={}".format(content["instance_action_id"]))
953 for uuid,c in content.iteritems():
954 print ("{:38} {:20} {:20}".format(uuid, c.get('name'), c.get('description')))
956 print content['error']['description']
960 def instance_vnf_list(args):
961 print "instance-vnf-list"
964 def instance_vnf_status(args):
965 print "instance-vnf-status"
968 def tenant_create(args):
969 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
970 tenant_dict={"name": args.name}
971 if args.description!=None:
972 tenant_dict["description"] = args.description
973 payload_req = json.dumps( {"tenant": tenant_dict })
977 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
978 logger.debug("openmano request: %s", payload_req)
979 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
980 logger.debug("openmano response: %s", mano_response.text )
981 return _print_verbose(mano_response, args.verbose)
983 def tenant_list(args):
984 #print "tenant-list",args
986 toshow = _get_item_uuid("tenants", args.name)
987 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
989 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
990 mano_response = requests.get(URLrequest)
991 logger.debug("openmano response: %s", mano_response.text )
992 if args.verbose==None:
996 return _print_verbose(mano_response, args.verbose)
998 def tenant_delete(args):
999 #print "tenant-delete",args
1000 todelete = _get_item_uuid("tenants", args.name)
1002 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
1003 if not (len(r)>0 and r[0].lower()=="y"):
1005 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
1006 mano_response = requests.delete(URLrequest)
1007 logger.debug("openmano response: %s", mano_response.text )
1008 result = 0 if mano_response.status_code==200 else mano_response.status_code
1009 content = mano_response.json()
1010 #print json.dumps(content, indent=4)
1011 if mano_response.status_code == 200:
1012 print content['result']
1014 print content['error']['description']
1017 def datacenter_attach(args):
1018 tenant = _get_tenant()
1019 datacenter = _get_datacenter(args.name)
1020 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1023 if args.vim_tenant_id != None:
1024 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1025 if args.vim_tenant_name != None:
1026 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1027 if args.user != None:
1028 datacenter_dict['vim_username'] = args.user
1029 if args.password != None:
1030 datacenter_dict['vim_password'] = args.password
1031 if args.config!=None:
1032 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1034 payload_req = json.dumps( {"datacenter": datacenter_dict })
1038 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1039 logger.debug("openmano request: %s", payload_req)
1040 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1041 logger.debug("openmano response: %s", mano_response.text )
1042 result = _print_verbose(mano_response, args.verbose)
1043 #provide addional information if error
1044 if mano_response.status_code != 200:
1045 content = mano_response.json()
1046 if "already in use for 'name'" in content['error']['description'] and \
1047 "to database vim_tenants table" in content['error']['description']:
1048 print "Try to specify a different name with --vim-tenant-name"
1052 def datacenter_edit_vim_tenant(args):
1053 tenant = _get_tenant()
1054 datacenter = _get_datacenter(args.name)
1055 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1057 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1058 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1060 datacenter_dict = {}
1061 if args.vim_tenant_id != None:
1062 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1063 if args.vim_tenant_name != None:
1064 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1065 if args.user != None:
1066 datacenter_dict['vim_username'] = args.user
1067 if args.password != None:
1068 datacenter_dict['vim_password'] = args.password
1069 if args.config != None:
1070 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1071 payload_req = json.dumps({"datacenter": datacenter_dict})
1075 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1076 logger.debug("openmano request: %s", payload_req)
1077 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1078 logger.debug("openmano response: %s", mano_response.text)
1079 result = _print_verbose(mano_response, args.verbose)
1083 def datacenter_detach(args):
1087 tenant = _get_tenant()
1088 datacenter = _get_datacenter(args.name, tenant)
1089 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1090 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1091 mano_response = requests.delete(URLrequest, headers=headers_req)
1092 logger.debug("openmano response: %s", mano_response.text )
1093 content = mano_response.json()
1094 #print json.dumps(content, indent=4)
1095 result = 0 if mano_response.status_code==200 else mano_response.status_code
1096 if mano_response.status_code == 200:
1097 print content['result']
1099 print content['error']['description']
1102 def datacenter_create(args):
1103 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1104 datacenter_dict={"name": args.name, "vim_url": args.url}
1105 if args.description!=None:
1106 datacenter_dict["description"] = args.description
1108 datacenter_dict["type"] = args.type
1110 datacenter_dict["vim_url_admin"] = args.url_admin
1111 if args.config!=None:
1112 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1113 if args.sdn_controller!=None:
1114 tenant = _get_tenant()
1115 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1116 if not 'config' in datacenter_dict:
1117 datacenter_dict['config'] = {}
1118 datacenter_dict['config']['sdn-controller'] = sdn_controller
1119 payload_req = json.dumps( {"datacenter": datacenter_dict })
1123 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1124 logger.debug("openmano request: %s", payload_req)
1125 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1126 logger.debug("openmano response: %s", mano_response.text )
1127 return _print_verbose(mano_response, args.verbose)
1129 def datacenter_delete(args):
1130 #print "datacenter-delete",args
1131 todelete = _get_item_uuid("datacenters", args.name, "any")
1133 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1134 if not (len(r)>0 and r[0].lower()=="y"):
1136 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1137 mano_response = requests.delete(URLrequest)
1138 logger.debug("openmano response: %s", mano_response.text )
1139 result = 0 if mano_response.status_code==200 else mano_response.status_code
1140 content = mano_response.json()
1141 #print json.dumps(content, indent=4)
1142 if mano_response.status_code == 200:
1143 print content['result']
1145 print content['error']['description']
1149 def datacenter_list(args):
1150 #print "datacenter-list",args
1151 tenant='any' if args.all else _get_tenant()
1154 toshow = _get_item_uuid("datacenters", args.name, tenant)
1155 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1157 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1158 mano_response = requests.get(URLrequest)
1159 logger.debug("openmano response: %s", mano_response.text )
1160 if args.verbose==None:
1164 return _print_verbose(mano_response, args.verbose)
1167 def datacenter_sdn_port_mapping_set(args):
1168 tenant = _get_tenant()
1169 datacenter = _get_datacenter(args.name, tenant)
1170 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1173 raise OpenmanoCLIError(
1174 "No yaml/json has been provided specifying the SDN port mapping")
1175 sdn_port_mapping = _load_file_or_yaml(args.file)
1176 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1179 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1180 mano_response = requests.get(URLrequest)
1181 logger.debug("openmano response: %s", mano_response.text)
1182 port_mapping = mano_response.json()
1183 if mano_response.status_code != 200:
1184 str(mano_response.json())
1185 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1186 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1188 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1189 if not (len(r) > 0 and r[0].lower() == "y"):
1193 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1194 mano_response = requests.delete(URLrequest)
1195 logger.debug("openmano response: %s", mano_response.text)
1196 if mano_response.status_code != 200:
1197 return _print_verbose(mano_response, args.verbose)
1200 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1201 logger.debug("openmano request: %s", payload_req)
1202 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1203 logger.debug("openmano response: %s", mano_response.text)
1204 return _print_verbose(mano_response, args.verbose)
1207 def datacenter_sdn_port_mapping_list(args):
1208 tenant = _get_tenant()
1209 datacenter = _get_datacenter(args.name, tenant)
1211 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1212 mano_response = requests.get(URLrequest)
1213 logger.debug("openmano response: %s", mano_response.text)
1215 return _print_verbose(mano_response, 4)
1218 def datacenter_sdn_port_mapping_clear(args):
1219 tenant = _get_tenant()
1220 datacenter = _get_datacenter(args.name, tenant)
1223 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1224 if not (len(r) > 0 and r[0].lower() == "y"):
1227 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1228 mano_response = requests.delete(URLrequest)
1229 logger.debug("openmano response: %s", mano_response.text)
1231 return _print_verbose(mano_response, args.verbose)
1234 def sdn_controller_create(args):
1235 tenant = _get_tenant()
1236 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1239 if not args.ip: error_msg.append("'ip'")
1240 if not args.port: error_msg.append("'port'")
1241 if not args.dpid: error_msg.append("'dpid'")
1242 if not args.type: error_msg.append("'type'")
1244 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
1246 controller_dict = {}
1247 controller_dict['name'] = args.name
1248 controller_dict['ip'] = args.ip
1249 controller_dict['port'] = int(args.port)
1250 controller_dict['dpid'] = args.dpid
1251 controller_dict['type'] = args.type
1252 if args.description != None:
1253 controller_dict['description'] = args.description
1254 if args.user != None:
1255 controller_dict['user'] = args.user
1256 if args.password != None:
1257 controller_dict['password'] = args.password
1259 payload_req = json.dumps({"sdn_controller": controller_dict})
1263 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1264 logger.debug("openmano request: %s", payload_req)
1265 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1266 logger.debug("openmano response: %s", mano_response.text)
1267 result = _print_verbose(mano_response, args.verbose)
1271 def sdn_controller_edit(args):
1272 tenant = _get_tenant()
1273 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1274 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1276 controller_dict = {}
1278 controller_dict['name'] = args.new_name
1280 controller_dict['ip'] = args.ip
1282 controller_dict['port'] = int(args.port)
1284 controller_dict['dpid'] = args.dpid
1286 controller_dict['type'] = args.type
1287 if args.description:
1288 controller_dict['description'] = args.description
1290 controller_dict['user'] = args.user
1292 controller_dict['password'] = args.password
1294 if not controller_dict:
1295 raise OpenmanoCLIError("At least one parameter must be edited")
1298 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1299 if not (len(r) > 0 and r[0].lower() == "y"):
1302 payload_req = json.dumps({"sdn_controller": controller_dict})
1305 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1306 logger.debug("openmano request: %s", payload_req)
1307 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1308 logger.debug("openmano response: %s", mano_response.text)
1309 result = _print_verbose(mano_response, args.verbose)
1313 def sdn_controller_list(args):
1314 tenant = _get_tenant()
1315 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1318 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1319 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1321 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1323 mano_response = requests.get(URLrequest)
1324 logger.debug("openmano response: %s", mano_response.text )
1325 if args.verbose==None:
1330 # json.dumps(mano_response.json(), indent=4)
1331 return _print_verbose(mano_response, args.verbose)
1334 def sdn_controller_delete(args):
1335 tenant = _get_tenant()
1336 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1339 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1340 if not (len(r) > 0 and r[0].lower() == "y"):
1343 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1344 mano_response = requests.delete(URLrequest)
1345 logger.debug("openmano response: %s", mano_response.text)
1346 return _print_verbose(mano_response, args.verbose)
1348 def vim_action(args):
1349 #print "datacenter-net-action",args
1350 tenant = _get_tenant()
1351 datacenter = _get_datacenter(args.datacenter, tenant)
1352 if args.verbose==None:
1354 if args.action=="list":
1355 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1358 URLrequest += "/" + args.name
1359 mano_response = requests.get(URLrequest)
1360 logger.debug("openmano response: %s", mano_response.text )
1361 return _print_verbose(mano_response, args.verbose)
1362 elif args.action=="delete":
1363 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1364 mano_response = requests.delete(URLrequest)
1365 logger.debug("openmano response: %s", mano_response.text )
1366 result = 0 if mano_response.status_code==200 else mano_response.status_code
1367 content = mano_response.json()
1368 #print json.dumps(content, indent=4)
1369 if mano_response.status_code == 200:
1370 print content['result']
1372 print content['error']['description']
1374 elif args.action=="create":
1375 headers_req = {'content-type': 'application/yaml'}
1377 create_dict = _load_file_or_yaml(args.file)
1378 if args.item not in create_dict:
1379 create_dict = {args.item: create_dict}
1381 create_dict = {args.item:{}}
1383 create_dict[args.item]['name'] = args.name
1384 #if args.description:
1385 # create_dict[args.item]['description'] = args.description
1386 if args.item=="network":
1388 create_dict[args.item]['bind_net'] = args.bind_net
1390 create_dict[args.item]['type'] = args.type
1392 create_dict[args.item]['shared'] = args.shared
1393 if "name" not in create_dict[args.item]:
1394 print "You must provide a name in the descriptor file or with the --name option"
1396 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1397 logger.debug("openmano request: %s", payload_req)
1398 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1399 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1400 logger.debug("openmano response: %s", mano_response.text )
1401 if args.verbose==None:
1403 return _print_verbose(mano_response, args.verbose)
1406 def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1407 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1409 URLrequest += "/" + tenant
1411 URLrequest += "/vim/" + datacenter
1413 URLrequest += "/" + item +"s"
1415 URLrequest += "/" + item_name_id
1416 mano_response = requests.get(URLrequest)
1417 logger.debug("openmano response: %s", mano_response.text )
1419 return mano_response
1422 def vim_net_sdn_attach(args):
1423 #Verify the network exists in the vim
1424 tenant = _get_tenant()
1425 datacenter = _get_datacenter(args.datacenter, tenant)
1426 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1427 content = yaml.load(result.content)
1428 if 'networks' in content:
1429 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1430 if 'error' in content:
1431 raise OpenmanoCLIError(yaml.safe_dump(content))
1432 network_uuid = content['network']['id']
1434 #Make call to attach the dataplane port to the SND network associated to the vim network
1435 headers_req = {'content-type': 'application/yaml'}
1436 payload_req = {'port': args.port}
1438 payload_req['vlan'] = int(args.vlan)
1440 payload_req['mac'] = args.mac
1442 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1443 logger.debug("openmano request: %s", payload_req)
1444 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1445 logger.debug("openmano response: %s", mano_response.text)
1446 result = _print_verbose(mano_response, args.verbose)
1450 def vim_net_sdn_detach(args):
1451 if not args.all and not args.id:
1452 print "--all or --id must be used"
1455 # Verify the network exists in the vim
1456 tenant = _get_tenant()
1457 datacenter = _get_datacenter(args.datacenter, tenant)
1458 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1459 content = yaml.load(result.content)
1460 if 'networks' in content:
1461 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1462 if 'error' in content:
1463 raise OpenmanoCLIError(yaml.safe_dump(content))
1464 network_uuid = content['network']['id']
1467 r = raw_input("Confirm action' (y/N)? ")
1468 if len(r) == 0 or r[0].lower() != "y":
1472 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1473 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1475 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1476 mano_host, mano_port, tenant, datacenter, network_uuid)
1477 mano_response = requests.delete(URLrequest)
1478 logger.debug("openmano response: %s", mano_response.text)
1479 result = _print_verbose(mano_response, args.verbose)
1483 def datacenter_net_action(args):
1484 if args.action == "net-update":
1485 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1487 args.action = "netmap-delete"
1490 r = datacenter_netmap_action(args)
1493 args.action = "netmap-import"
1494 r = datacenter_netmap_action(args)
1497 if args.action == "net-edit":
1498 args.netmap = args.net
1500 elif args.action == "net-list":
1502 elif args.action == "net-delete":
1503 args.netmap = args.net
1506 args.action = "netmap" + args.action[3:]
1509 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1511 return datacenter_netmap_action(args)
1513 def datacenter_netmap_action(args):
1514 tenant = _get_tenant()
1515 datacenter = _get_datacenter(args.datacenter, tenant)
1516 #print "datacenter_netmap_action",args
1518 if args.verbose==None:
1520 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1521 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1523 if args.action=="netmap-list":
1525 URLrequest += "/" + args.netmap
1527 mano_response = requests.get(URLrequest)
1529 elif args.action=="netmap-delete":
1530 if args.netmap and args.all:
1531 print "you can not use a netmap name and the option --all at the same time"
1534 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1535 URLrequest += "/" + args.netmap
1537 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1539 print "you must specify a netmap name or the option --all"
1542 r = raw_input(force_text)
1543 if len(r)>0 and r[0].lower()=="y":
1547 mano_response = requests.delete(URLrequest, headers=headers_req)
1548 elif args.action=="netmap-import":
1550 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1551 if len(r)>0 and r[0].lower()=="y":
1555 URLrequest += "/upload"
1556 mano_response = requests.post(URLrequest, headers=headers_req)
1557 elif args.action=="netmap-edit" or args.action=="netmap-create":
1559 payload = _load_file_or_yaml(args.file)
1562 if "netmap" not in payload:
1563 payload = {"netmap": payload}
1565 payload["netmap"]["name"] = args.name
1567 payload["netmap"]["vim_id"] = args.vim_id
1568 if args.action=="netmap-create" and args.vim_name:
1569 payload["netmap"]["vim_name"] = args.vim_name
1570 payload_req = json.dumps(payload)
1571 logger.debug("openmano request: %s", payload_req)
1573 if args.action=="netmap-edit" and not args.force:
1574 if len(payload["netmap"]) == 0:
1575 print "You must supply some parameter to edit"
1577 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1578 if len(r)>0 and r[0].lower()=="y":
1582 URLrequest += "/" + args.netmap
1583 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1584 else: #netmap-create
1585 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1586 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1588 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1590 logger.debug("openmano response: %s", mano_response.text )
1591 return _print_verbose(mano_response, args.verbose)
1594 def element_edit(args):
1595 element = _get_item_uuid(args.element, args.name)
1596 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1597 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1598 payload=_load_file_or_yaml(args.file)
1599 if args.element[:-1] not in payload:
1600 payload = {args.element[:-1]: payload }
1601 payload_req = json.dumps(payload)
1604 if not args.force or (args.name==None and args.filer==None):
1605 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1606 if len(r)>0 and r[0].lower()=="y":
1610 logger.debug("openmano request: %s", payload_req)
1611 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1612 logger.debug("openmano response: %s", mano_response.text )
1613 if args.verbose==None:
1617 return _print_verbose(mano_response, args.verbose)
1620 def datacenter_edit(args):
1621 tenant = _get_tenant()
1622 element = _get_item_uuid('datacenters', args.name, tenant)
1623 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1624 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1626 has_arguments = False
1627 if args.file != None:
1628 has_arguments = True
1629 payload = _load_file_or_yaml(args.file)
1633 if args.sdn_controller != None:
1634 has_arguments = True
1635 if not 'config' in payload:
1636 payload['config'] = {}
1637 if not 'sdn-controller' in payload['config']:
1638 payload['config']['sdn-controller'] = {}
1639 if args.sdn_controller == 'null':
1640 payload['config']['sdn-controller'] = None
1642 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1644 if not has_arguments:
1645 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1647 if 'datacenter' not in payload:
1648 payload = {'datacenter': payload}
1649 payload_req = json.dumps(payload)
1652 if not args.force or (args.name == None and args.filer == None):
1653 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1654 if len(r) > 0 and r[0].lower() == "y":
1658 logger.debug("openmano request: %s", payload_req)
1659 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1660 logger.debug("openmano response: %s", mano_response.text)
1661 if args.verbose == None:
1663 if args.name != None:
1665 return _print_verbose(mano_response, args.verbose)
1669 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1670 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1672 mano_response = requests.get(URLrequest, headers=headers_req)
1673 logger.debug("openmano response: %s", mano_response.text)
1674 print mano_response.text
1681 if __name__=="__main__":
1683 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1684 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1685 mano_port = os.getenv('OPENMANO_PORT',"9090")
1686 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1688 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1689 main_parser.add_argument('--version', action='version', help="get version of this client",
1690 version='%(prog)s client version ' + __version__ +
1691 " (Note: use '%(prog)s version' to get server version)")
1693 subparsers = main_parser.add_subparsers(help='commands')
1695 parent_parser = argparse.ArgumentParser(add_help=False)
1696 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1697 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1699 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1700 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1701 config_parser.set_defaults(func=config)
1703 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1704 version_parser.set_defaults(func=version)
1706 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1707 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1708 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1709 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1710 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1711 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1712 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1713 vnf_create_parser.set_defaults(func=vnf_create)
1715 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1716 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1717 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1718 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1719 vnf_list_parser.set_defaults(func=vnf_list)
1721 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1722 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1723 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1724 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1725 vnf_delete_parser.set_defaults(func=vnf_delete)
1727 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1728 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1729 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1730 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1731 scenario_create_parser.set_defaults(func=scenario_create)
1733 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1734 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1735 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1736 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1737 scenario_list_parser.set_defaults(func=scenario_list)
1739 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1740 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1741 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1742 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1743 scenario_delete_parser.set_defaults(func=scenario_delete)
1745 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1746 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1747 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1748 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1749 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1750 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1751 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1753 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1754 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1755 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1756 scenario_deploy_parser.set_defaults(func=scenario_verify)
1758 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1759 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1760 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1761 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1762 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1763 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1764 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")
1765 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")
1766 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")
1767 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")
1768 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1769 instance_scenario_create_parser.set_defaults(func=instance_create)
1771 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1772 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1773 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1774 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1776 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)")
1777 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1778 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1779 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1780 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1782 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1783 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1784 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1785 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key","vdu-scaling"],\
1786 help="action to send")
1787 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console: novnc; reboot: type; vdu-scaling: '[{vdu-id: xxx, type: create|delete, count: 1}]'")
1788 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1789 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1790 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1792 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1793 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1794 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1795 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1796 action_parser.set_defaults(func=get_action)
1798 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1799 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1800 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1802 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1803 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1804 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1805 tenant_create_parser.set_defaults(func=tenant_create)
1807 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1808 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1809 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1810 tenant_delete_parser.set_defaults(func=tenant_delete)
1812 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1813 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1814 tenant_list_parser.set_defaults(func=tenant_list)
1816 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1817 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1818 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1819 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1820 element_edit_parser.set_defaults(func=element_edit, element='tenants')
1822 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1823 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1824 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1825 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1826 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1827 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1828 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1829 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1830 datacenter_create_parser.set_defaults(func=datacenter_create)
1832 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1833 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1834 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1835 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1837 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1838 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1839 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1840 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1841 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1842 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1843 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1845 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1846 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1847 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1848 datacenter_list_parser.set_defaults(func=datacenter_list)
1850 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1851 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1852 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1853 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1854 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1855 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1856 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1857 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1859 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1860 help="Edit the association of a datacenter to the operating tenant")
1861 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1862 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1863 help="specify a datacenter tenant to use. A new one is created by default")
1864 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1865 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1866 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1867 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1868 help="aditional configuration in json/yaml format")
1869 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1871 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1872 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1873 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1874 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1876 #=======================datacenter_sdn_port_mapping_xxx section=======================
1877 #datacenter_sdn_port_mapping_set
1878 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1879 parents=[parent_parser],
1880 help="Load a file with the mapping of physical ports "
1881 "and the ports of the dataplaneswitch controlled "
1883 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1884 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1885 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1886 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1887 help="forces overwriting without asking")
1888 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1890 #datacenter_sdn_port_mapping_list
1891 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1892 parents=[parent_parser],
1893 help="Show the SDN port mapping in a datacenter")
1894 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1895 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1897 # datacenter_sdn_port_mapping_clear
1898 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1899 parents=[parent_parser],
1900 help="Clean the the SDN port mapping in a datacenter")
1901 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1902 help="specifies the datacenter")
1903 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1904 help="forces clearing without asking")
1905 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1906 # =======================
1908 # =======================sdn_controller_xxx section=======================
1909 # sdn_controller_create
1910 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1911 help="Creates an SDN controller entity within RO")
1912 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1913 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1914 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1915 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1916 sdn_controller_create_parser.add_argument("--dpid", action="store",
1917 help="DPID of the dataplane switch controlled by this SDN controller")
1918 sdn_controller_create_parser.add_argument("--type", action="store",
1919 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1920 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1921 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1922 help="password credentials for the SDN controller")
1923 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1925 # sdn_controller_edit
1926 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1927 help="Update one or more options of a SDN controller")
1928 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1929 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1931 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1932 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1933 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1934 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1935 help="DPID of the dataplane switch controlled by this SDN controller")
1936 sdn_controller_edit_parser.add_argument("--type", action="store",
1937 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1938 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1939 sdn_controller_edit_parser.add_argument("--password", action="store",
1940 help="password credentials for the SDN controller", dest='password')
1941 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1942 #TODO: include option --file
1943 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1945 #sdn_controller_list
1946 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1947 parents=[parent_parser],
1948 help="List the SDN controllers")
1949 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1950 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1952 # sdn_controller_delete
1953 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1954 parents=[parent_parser],
1955 help="Delete the the SDN controller")
1956 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1957 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1958 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1959 # =======================
1961 action_dict={'net-update': 'retrieves external networks from datacenter',
1962 'net-edit': 'edits an external network',
1963 'net-delete': 'deletes an external network',
1964 'net-list': 'lists external networks from a datacenter'
1966 for item in action_dict:
1967 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1968 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1969 if item=='net-edit' or item=='net-delete':
1970 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1971 if item=='net-edit':
1972 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1973 if item!='net-list':
1974 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1975 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1978 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1979 'netmap-create': 'create a new network senario netmap',
1980 'netmap-edit': 'edit name of a network senario netmap',
1981 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1982 'netmap-list': 'list/show network scenario netmaps'
1984 for item in action_dict:
1985 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1986 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1987 #if item=='net-add':
1988 # datacenter_action_parser.add_argument("net", help="name of the network")
1989 if item=='netmap-delete':
1990 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1991 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1992 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1993 if item=='netmap-edit':
1994 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1995 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1996 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1997 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1998 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1999 if item=='netmap-list':
2000 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
2001 if item=='netmap-create':
2002 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
2003 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
2004 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2005 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
2006 if item=='netmap-import':
2007 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2008 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
2010 # =======================vim_net_sdn_xxx section=======================
2011 # vim_net_sdn_attach
2012 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2013 parents=[parent_parser],
2014 help="Specify the port to access to an external network using SDN")
2015 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2016 help="Name/id of the network in the vim that will be used to connect to the external network")
2017 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2018 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2019 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")
2020 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2021 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2023 # vim_net_sdn_detach
2024 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2025 parents=[parent_parser],
2026 help="Remove the port information to access to an external network using SDN")
2028 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2029 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2030 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2031 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2032 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2033 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2034 # =======================
2036 for item in ("network", "tenant", "image"):
2038 command_name = 'vim-net'
2040 command_name = 'vim-'+item
2041 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
2042 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2043 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2044 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2046 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
2047 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2048 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2049 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2051 if item == "network" or item == "tenant":
2052 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
2053 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2054 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2055 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2057 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2058 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2059 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>'")
2061 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2062 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
2064 argcomplete.autocomplete(main_parser)
2067 args = main_parser.parse_args()
2069 level = logging.CRITICAL
2070 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2071 if "debug" in args and args.debug:
2072 level = logging.DEBUG
2073 logging.basicConfig(format=streamformat, level= level)
2074 logger = logging.getLogger('mano')
2075 logger.setLevel(level)
2076 result = args.func(args)
2079 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2080 except (requests.exceptions.ConnectionError):
2081 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2083 except (KeyboardInterrupt):
2084 print 'Exiting openmano'
2086 except (SystemExit, ArgumentParserError):
2088 except OpenmanoCLIError as e: