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.23-r533"
32 version_date = "May 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["vdu"]
282 vdu_list = vnfd["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
294 for image_path_ in args.image_path.split(","):
295 # print "image-path", image_path_
296 if api_version == "/v3":
297 if vdu_list[index].get("image"):
298 vdu_list[index]['image'] = image_path_
299 if "image-checksum" in vdu_list[index]:
300 del vdu_list[index]["image-checksum"]
301 else: # image name in volumes
302 vdu_list[index]["volumes"][0]["image"] = image_path_
303 if "image-checksum" in vdu_list[index]["volumes"][0]:
304 del vdu_list[index]["volumes"][0]["image-checksum"]
306 vdu_list[index]['VNFC image'] = image_path_
307 if "image name" in vdu_list[index]:
308 del vdu_list[index]["image name"]
309 if "image checksum" in vdu_list[index]:
310 del vdu_list[index]["image checksum"]
312 if args.image_name: # image name precedes if both are supplied
314 for image_name_ in args.image_name.split(","):
315 if api_version == "/v3":
316 if vdu_list[index].get("image"):
317 vdu_list[index]['image'] = image_name_
318 if "image-checksum" in vdu_list[index]:
319 del vdu_list[index]["image-checksum"]
320 if vdu_list[index].get("alternative-images"):
321 for a_image in vdu_list[index]["alternative-images"]:
322 a_image['image'] = image_name_
323 if "image-checksum" in a_image:
324 del a_image["image-checksum"]
325 else: # image name in volumes
326 vdu_list[index]["volumes"][0]["image"] = image_name_
327 if "image-checksum" in vdu_list[index]["volumes"][0]:
328 del vdu_list[index]["volumes"][0]["image-checksum"]
330 vdu_list[index]['image name'] = image_name_
331 if "VNFC image" in vdu_list[index]:
332 del vdu_list[index]["VNFC image"]
334 if args.image_checksum:
336 for image_checksum_ in args.image_checksum.split(","):
337 if api_version == "/v3":
338 if vdu_list[index].get("image"):
339 vdu_list[index]['image-checksum'] = image_checksum_
340 if vdu_list[index].get("alternative-images"):
341 for a_image in vdu_list[index]["alternative-images"]:
342 a_image['image-checksum'] = image_checksum_
343 else: # image name in volumes
344 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
346 vdu_list[index]['image checksum'] = image_checksum_
348 except (KeyError, TypeError), e:
349 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
350 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
351 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
352 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
353 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
354 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
355 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
356 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
357 else: error_pos="wrong format"
358 print "Wrong VNF descriptor: " + error_pos
360 payload_req = json.dumps(myvnf)
364 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
365 logger.debug("openmano request: %s", payload_req)
366 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
367 logger.debug("openmano response: %s", mano_response.text )
369 return _print_verbose(mano_response, args.verbose)
372 #print "vnf-list",args
376 tenant = _get_tenant()
378 toshow = _get_item_uuid("vnfs", args.name, tenant)
379 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
381 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
382 mano_response = requests.get(URLrequest)
383 logger.debug("openmano response: %s", mano_response.text )
384 content = mano_response.json()
385 # print json.dumps(content, indent=4)
386 if args.verbose==None:
388 result = 0 if mano_response.status_code==200 else mano_response.status_code
389 if mano_response.status_code == 200:
391 if args.verbose >= 3:
392 print yaml.safe_dump(content, indent=4, default_flow_style=False)
394 if len(content['vnfs']) == 0:
395 print "No VNFs were found."
396 return 404 # HTTP_Not_Found
397 for vnf in content['vnfs']:
398 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
399 if vnf.get('osm_id') or args.verbose >= 1:
400 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
401 if args.verbose >= 1:
402 myoutput += " {}".format(vnf['created_at'])
404 if args.verbose >= 2:
405 print (" Description: {}".format(vnf['description']))
406 # print (" VNF descriptor file: {}".format(vnf['path']))
409 print yaml.safe_dump(content, indent=4, default_flow_style=False)
412 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
414 print (" Description: {}".format(vnf['description']))
415 # print " VNF descriptor file: %s" %vnf['path']
417 for vm in vnf['VNFC']:
418 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
419 if len(vnf['nets']) > 0:
420 print (" Internal nets:")
421 for net in vnf['nets']:
422 print (" {:20} {}".format(net['name'], net['description']))
423 if len(vnf['external-connections']) > 0:
424 print (" External interfaces:")
425 for interface in vnf['external-connections']:
426 print (" {:20} {:20} {:20} {:14}".format(
427 interface['external_name'], interface['vm_name'],
428 interface['internal_name'],
429 interface.get('vpci') if interface.get('vpci') else ""))
431 print content['error']['description']
433 print yaml.safe_dump(content, indent=4, default_flow_style=False)
436 def vnf_delete(args):
437 #print "vnf-delete",args
441 tenant = _get_tenant()
442 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
444 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
445 if not (len(r)>0 and r[0].lower()=="y"):
447 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
448 mano_response = requests.delete(URLrequest)
449 logger.debug("openmano response: %s", mano_response.text )
450 result = 0 if mano_response.status_code==200 else mano_response.status_code
451 content = mano_response.json()
452 #print json.dumps(content, indent=4)
453 if mano_response.status_code == 200:
454 print content['result']
456 print content['error']['description']
459 def scenario_create(args):
460 # print "scenario-create",args
461 tenant = _get_tenant()
462 headers_req = {'content-type': 'application/yaml'}
463 myscenario = _load_file_or_yaml(args.file)
464 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
467 nsd_catalog = myscenario.get("nsd:nsd-catalog")
469 nsd_catalog = myscenario.get("nsd-catalog")
470 nsds = nsd_catalog.get("nsd:nsd")
472 nsds = nsd_catalog.get("nsd")
477 if "scenario" in myscenario:
478 nsd = myscenario["scenario"]
481 # TODO modify for API v3
483 nsd['name'] = args.name
485 nsd['description'] = args.description
486 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
487 encoding='utf-8', allow_unicode=True)
490 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
491 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
492 logger.debug("openmano request: %s", payload_req)
493 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
494 logger.debug("openmano response: %s", mano_response.text )
495 return _print_verbose(mano_response, args.verbose)
497 def scenario_list(args):
498 #print "scenario-list",args
502 tenant = _get_tenant()
504 toshow = _get_item_uuid("scenarios", args.name, tenant)
505 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
507 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
508 mano_response = requests.get(URLrequest)
509 logger.debug("openmano response: %s", mano_response.text )
510 content = mano_response.json()
511 #print json.dumps(content, indent=4)
512 if args.verbose==None:
515 result = 0 if mano_response.status_code==200 else mano_response.status_code
516 if mano_response.status_code == 200:
518 if args.verbose >= 3:
519 print yaml.safe_dump(content, indent=4, default_flow_style=False)
521 if len(content['scenarios']) == 0:
522 print "No scenarios were found."
523 return 404 #HTTP_Not_Found
524 for scenario in content['scenarios']:
525 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
526 if scenario.get('osm_id') or args.verbose >= 1:
527 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
528 if args.verbose >= 1:
529 myoutput += " {}".format(scenario['created_at'])
532 print (" Description: {}".format(scenario['description']))
535 print yaml.safe_dump(content, indent=4, default_flow_style=False)
537 scenario = content['scenario']
538 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
539 scenario['created_at']))
540 print (" Description: {}".format(scenario['description']))
542 for vnf in scenario['vnfs']:
543 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
545 if len(scenario['nets']) > 0:
547 for net in scenario['nets']:
548 description = net['description']
549 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
552 if net.get('vim_id'):
553 vim_id = " vim_id=" + net["vim_id"]
556 external = " external"
557 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
559 print (content['error']['description'])
561 print yaml.safe_dump(content, indent=4, default_flow_style=False)
564 def scenario_delete(args):
565 #print "scenario-delete",args
569 tenant = _get_tenant()
570 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
572 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
573 if not (len(r)>0 and r[0].lower()=="y"):
575 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
576 mano_response = requests.delete(URLrequest)
577 logger.debug("openmano response: %s", mano_response.text )
578 result = 0 if mano_response.status_code==200 else mano_response.status_code
579 content = mano_response.json()
580 #print json.dumps(content, indent=4)
581 if mano_response.status_code == 200:
582 print content['result']
584 print content['error']['description']
587 def scenario_deploy(args):
588 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
591 args.netmap_use = None
592 args.netmap_create = None
594 args.keypair_auto = None
595 return instance_create(args)
597 # #print "scenario-deploy",args
598 # headers_req = {'content-type': 'application/json'}
602 # actionCmd="reserve"
603 # action[actionCmd] = {}
604 # action[actionCmd]["instance_name"] = args.name
605 # if args.datacenter != None:
606 # action[actionCmd]["datacenter"] = args.datacenter
607 # elif mano_datacenter != None:
608 # action[actionCmd]["datacenter"] = mano_datacenter
610 # if args.description:
611 # action[actionCmd]["description"] = args.description
612 # payload_req = json.dumps(action, indent=4)
615 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
616 # logger.debug("openmano request: %s", payload_req)
617 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
618 # logger.debug("openmano response: %s", mano_response.text )
619 # if args.verbose==None:
622 # result = 0 if mano_response.status_code==200 else mano_response.status_code
623 # content = mano_response.json()
624 # #print json.dumps(content, indent=4)
625 # if args.verbose >= 3:
626 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
629 # if mano_response.status_code == 200:
630 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
631 # if args.verbose >=1:
632 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
633 # if args.verbose >=2:
634 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
637 # print "To check the status, run the following command:"
638 # print "openmano instance-scenario-list <instance_id>"
640 # print content['error']['description']
643 def scenario_verify(args):
644 #print "scenario-verify",args
645 tenant = _get_tenant()
646 headers_req = {'content-type': 'application/json'}
648 action["verify"] = {}
649 action["verify"]["instance_name"] = "scen-verify-return5"
650 payload_req = json.dumps(action, indent=4)
653 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
654 logger.debug("openmano request: %s", payload_req)
655 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
656 logger.debug("openmano response: %s", mano_response.text )
658 result = 0 if mano_response.status_code==200 else mano_response.status_code
659 content = mano_response.json()
660 #print json.dumps(content, indent=4)
661 if mano_response.status_code == 200:
662 print content['result']
664 print content['error']['description']
667 def instance_create(args):
668 tenant = _get_tenant()
669 headers_req = {'content-type': 'application/yaml'}
670 myInstance={"instance": {}, "schema_version": "0.1"}
672 instance_dict = _load_file_or_yaml(args.file)
673 if "instance" not in instance_dict:
674 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
676 myInstance = instance_dict
678 myInstance["instance"]['name'] = args.name
680 myInstance["instance"]['description'] = args.description
682 myInstance["instance"]['action'] = "reserve"
684 datacenter = myInstance["instance"].get("datacenter")
685 if args.datacenter != None:
686 datacenter = args.datacenter
687 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
689 scenario = myInstance["instance"].get("scenario")
690 if args.scenario != None:
691 scenario = args.scenario
693 print "you must provide a scenario in the file descriptor or with --scenario"
695 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
697 if "networks" not in myInstance["instance"]:
698 myInstance["instance"]["networks"] = {}
699 for net in args.netmap_use:
700 net_comma_list = net.split(",")
701 for net_comma in net_comma_list:
702 net_tuple = net_comma.split("=")
703 if len(net_tuple) != 2:
704 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
706 net_scenario = net_tuple[0].strip()
707 net_datacenter = net_tuple[1].strip()
708 if net_scenario not in myInstance["instance"]["networks"]:
709 myInstance["instance"]["networks"][net_scenario] = {}
710 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
711 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
712 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
713 if args.netmap_create:
714 if "networks" not in myInstance["instance"]:
715 myInstance["instance"]["networks"] = {}
716 for net in args.netmap_create:
717 net_comma_list = net.split(",")
718 for net_comma in net_comma_list:
719 net_tuple = net_comma.split("=")
720 if len(net_tuple) == 1:
721 net_scenario = net_tuple[0].strip()
722 net_datacenter = None
723 elif len(net_tuple) == 2:
724 net_scenario = net_tuple[0].strip()
725 net_datacenter = net_tuple[1].strip()
727 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
729 if net_scenario not in myInstance["instance"]["networks"]:
730 myInstance["instance"]["networks"][net_scenario] = {}
731 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
732 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
733 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
735 if "cloud-config" not in myInstance["instance"]:
736 myInstance["instance"]["cloud-config"] = {}
737 cloud_config = myInstance["instance"]["cloud-config"]
738 for key in args.keypair:
739 index = key.find(":")
741 if "key-pairs" not in cloud_config:
742 cloud_config["key-pairs"] = []
743 cloud_config["key-pairs"].append(key)
747 key_list = key_.split(",")
748 if "users" not in cloud_config:
749 cloud_config["users"] = []
750 cloud_config["users"].append({"name": user, "key-pairs": key_list })
751 if args.keypair_auto:
754 home = os.getenv("HOME")
755 user = os.getenv("USER")
756 files = os.listdir(home+'/.ssh')
758 if file[-4:] == ".pub":
759 with open(home+'/.ssh/'+file, 'r') as f:
760 keys.append(f.read())
762 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
764 except Exception as e:
765 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
768 if "cloud-config" not in myInstance["instance"]:
769 myInstance["instance"]["cloud-config"] = {}
770 cloud_config = myInstance["instance"]["cloud-config"]
771 if "key-pairs" not in cloud_config:
772 cloud_config["key-pairs"] = []
774 if "users" not in cloud_config:
775 cloud_config["users"] = []
776 cloud_config["users"].append({"name": user, "key-pairs": keys })
778 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
779 logger.debug("openmano request: %s", payload_req)
780 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
781 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
782 logger.debug("openmano response: %s", mano_response.text )
783 if args.verbose==None:
786 result = 0 if mano_response.status_code==200 else mano_response.status_code
787 content = mano_response.json()
788 #print json.dumps(content, indent=4)
789 if args.verbose >= 3:
790 print yaml.safe_dump(content, indent=4, default_flow_style=False)
793 if mano_response.status_code == 200:
794 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
796 myoutput = "{} {:20}".format(myoutput, content['created_at'])
798 myoutput = "{} {:30}".format(myoutput, content['description'])
801 print content['error']['description']
804 def instance_scenario_list(args):
805 #print "instance-scenario-list",args
809 tenant = _get_tenant()
811 toshow = _get_item_uuid("instances", args.name, tenant)
812 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
814 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
815 mano_response = requests.get(URLrequest)
816 logger.debug("openmano response: %s", mano_response.text )
817 content = mano_response.json()
818 #print json.dumps(content, indent=4)
819 if args.verbose==None:
822 result = 0 if mano_response.status_code==200 else mano_response.status_code
823 if mano_response.status_code == 200:
825 if args.verbose >= 3:
826 print yaml.safe_dump(content, indent=4, default_flow_style=False)
828 if len(content['instances']) == 0:
829 print "No scenario instances were found."
831 for instance in content['instances']:
832 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
834 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
837 print "Description: %s" %instance['description']
840 print yaml.safe_dump(content, indent=4, default_flow_style=False)
843 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
844 print ("Description: %s" %instance['description'])
845 print ("Template scenario id: {}".format(instance['scenario_id']))
846 print ("Template scenario name: {}".format(instance['scenario_name']))
847 print ("---------------------------------------")
848 print ("VNF instances: {}".format(len(instance['vnfs'])))
849 for vnf in instance['vnfs']:
850 #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))
851 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
852 if len(instance['nets'])>0:
853 print "---------------------------------------"
854 print "Internal nets:"
855 for net in instance['nets']:
857 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
858 print "---------------------------------------"
859 print "External nets:"
860 for net in instance['nets']:
861 if not net['created']:
862 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
863 print ("---------------------------------------")
864 print ("VM instances:")
865 for vnf in instance['vnfs']:
866 for vm in vnf['vms']:
867 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
868 vm['status'], vm['vim_vm_id']))
870 print content['error']['description']
872 print yaml.safe_dump(content, indent=4, default_flow_style=False)
875 def instance_scenario_status(args):
876 print "instance-scenario-status"
879 def instance_scenario_delete(args):
883 tenant = _get_tenant()
884 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
885 #print "instance-scenario-delete",args
887 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
888 if not (len(r)>0 and r[0].lower()=="y"):
890 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
891 mano_response = requests.delete(URLrequest)
892 logger.debug("openmano response: %s", mano_response.text )
893 result = 0 if mano_response.status_code==200 else mano_response.status_code
894 content = mano_response.json()
895 #print json.dumps(content, indent=4)
896 if mano_response.status_code == 200:
897 print content['result']
899 print content['error']['description']
902 def get_action(args):
904 tenant = _get_tenant()
907 if not args.instance:
910 instance_id =args.instance
913 action_id = "/" + args.id
914 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
916 mano_response = requests.get(URLrequest)
917 logger.debug("openmano response: %s", mano_response.text )
918 if args.verbose == None:
922 return _print_verbose(mano_response, args.verbose)
924 def instance_scenario_action(args):
925 #print "instance-scenario-action", args
926 tenant = _get_tenant()
927 toact = _get_item_uuid("instances", args.name, tenant=tenant)
929 action[ args.action ] = yaml.safe_load(args.param)
931 action["vnfs"] = args.vnf
933 action["vms"] = args.vm
935 headers_req = {'content-type': 'application/json'}
936 payload_req = json.dumps(action, indent=4)
937 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
938 logger.debug("openmano request: %s", payload_req)
939 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
940 logger.debug("openmano response: %s", mano_response.text )
941 result = 0 if mano_response.status_code==200 else mano_response.status_code
942 content = mano_response.json()
943 # print json.dumps(content, indent=4)
944 if mano_response.status_code == 200:
946 print yaml.safe_dump(content, indent=4, default_flow_style=False)
948 if "instance_action_id" in content:
949 print("instance_action_id={}".format(content["instance_action_id"]))
951 for uuid,c in content.iteritems():
952 print ("{:38} {:20} {:20}".format(uuid, c.get('name'), c.get('description')))
954 print content['error']['description']
958 def instance_vnf_list(args):
959 print "instance-vnf-list"
962 def instance_vnf_status(args):
963 print "instance-vnf-status"
966 def tenant_create(args):
967 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
968 tenant_dict={"name": args.name}
969 if args.description!=None:
970 tenant_dict["description"] = args.description
971 payload_req = json.dumps( {"tenant": tenant_dict })
975 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
976 logger.debug("openmano request: %s", payload_req)
977 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
978 logger.debug("openmano response: %s", mano_response.text )
979 return _print_verbose(mano_response, args.verbose)
981 def tenant_list(args):
982 #print "tenant-list",args
984 toshow = _get_item_uuid("tenants", args.name)
985 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
987 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
988 mano_response = requests.get(URLrequest)
989 logger.debug("openmano response: %s", mano_response.text )
990 if args.verbose==None:
994 return _print_verbose(mano_response, args.verbose)
996 def tenant_delete(args):
997 #print "tenant-delete",args
998 todelete = _get_item_uuid("tenants", args.name)
1000 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
1001 if not (len(r)>0 and r[0].lower()=="y"):
1003 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
1004 mano_response = requests.delete(URLrequest)
1005 logger.debug("openmano response: %s", mano_response.text )
1006 result = 0 if mano_response.status_code==200 else mano_response.status_code
1007 content = mano_response.json()
1008 #print json.dumps(content, indent=4)
1009 if mano_response.status_code == 200:
1010 print content['result']
1012 print content['error']['description']
1015 def datacenter_attach(args):
1016 tenant = _get_tenant()
1017 datacenter = _get_datacenter(args.name)
1018 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1021 if args.vim_tenant_id != None:
1022 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1023 if args.vim_tenant_name != None:
1024 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1025 if args.user != None:
1026 datacenter_dict['vim_username'] = args.user
1027 if args.password != None:
1028 datacenter_dict['vim_password'] = args.password
1029 if args.config!=None:
1030 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1032 payload_req = json.dumps( {"datacenter": datacenter_dict })
1036 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1037 logger.debug("openmano request: %s", payload_req)
1038 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1039 logger.debug("openmano response: %s", mano_response.text )
1040 result = _print_verbose(mano_response, args.verbose)
1041 #provide addional information if error
1042 if mano_response.status_code != 200:
1043 content = mano_response.json()
1044 if "already in use for 'name'" in content['error']['description'] and \
1045 "to database vim_tenants table" in content['error']['description']:
1046 print "Try to specify a different name with --vim-tenant-name"
1050 def datacenter_edit_vim_tenant(args):
1051 tenant = _get_tenant()
1052 datacenter = _get_datacenter(args.name)
1053 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1055 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1056 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1058 datacenter_dict = {}
1059 if args.vim_tenant_id != None:
1060 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1061 if args.vim_tenant_name != None:
1062 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1063 if args.user != None:
1064 datacenter_dict['vim_username'] = args.user
1065 if args.password != None:
1066 datacenter_dict['vim_password'] = args.password
1067 if args.config != None:
1068 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1069 payload_req = json.dumps({"datacenter": datacenter_dict})
1073 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1074 logger.debug("openmano request: %s", payload_req)
1075 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1076 logger.debug("openmano response: %s", mano_response.text)
1077 result = _print_verbose(mano_response, args.verbose)
1081 def datacenter_detach(args):
1085 tenant = _get_tenant()
1086 datacenter = _get_datacenter(args.name, tenant)
1087 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1088 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1089 mano_response = requests.delete(URLrequest, headers=headers_req)
1090 logger.debug("openmano response: %s", mano_response.text )
1091 content = mano_response.json()
1092 #print json.dumps(content, indent=4)
1093 result = 0 if mano_response.status_code==200 else mano_response.status_code
1094 if mano_response.status_code == 200:
1095 print content['result']
1097 print content['error']['description']
1100 def datacenter_create(args):
1101 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1102 datacenter_dict={"name": args.name, "vim_url": args.url}
1103 if args.description!=None:
1104 datacenter_dict["description"] = args.description
1106 datacenter_dict["type"] = args.type
1108 datacenter_dict["vim_url_admin"] = args.url_admin
1109 if args.config!=None:
1110 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1111 if args.sdn_controller!=None:
1112 tenant = _get_tenant()
1113 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1114 if not 'config' in datacenter_dict:
1115 datacenter_dict['config'] = {}
1116 datacenter_dict['config']['sdn-controller'] = sdn_controller
1117 payload_req = json.dumps( {"datacenter": datacenter_dict })
1121 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1122 logger.debug("openmano request: %s", payload_req)
1123 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1124 logger.debug("openmano response: %s", mano_response.text )
1125 return _print_verbose(mano_response, args.verbose)
1127 def datacenter_delete(args):
1128 #print "datacenter-delete",args
1129 todelete = _get_item_uuid("datacenters", args.name, "any")
1131 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1132 if not (len(r)>0 and r[0].lower()=="y"):
1134 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1135 mano_response = requests.delete(URLrequest)
1136 logger.debug("openmano response: %s", mano_response.text )
1137 result = 0 if mano_response.status_code==200 else mano_response.status_code
1138 content = mano_response.json()
1139 #print json.dumps(content, indent=4)
1140 if mano_response.status_code == 200:
1141 print content['result']
1143 print content['error']['description']
1147 def datacenter_list(args):
1148 #print "datacenter-list",args
1149 tenant='any' if args.all else _get_tenant()
1152 toshow = _get_item_uuid("datacenters", args.name, tenant)
1153 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1155 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1156 mano_response = requests.get(URLrequest)
1157 logger.debug("openmano response: %s", mano_response.text )
1158 if args.verbose==None:
1162 return _print_verbose(mano_response, args.verbose)
1165 def datacenter_sdn_port_mapping_set(args):
1166 tenant = _get_tenant()
1167 datacenter = _get_datacenter(args.name, tenant)
1168 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1171 raise OpenmanoCLIError(
1172 "No yaml/json has been provided specifying the SDN port mapping")
1173 sdn_port_mapping = _load_file_or_yaml(args.file)
1174 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1177 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1178 mano_response = requests.get(URLrequest)
1179 logger.debug("openmano response: %s", mano_response.text)
1180 port_mapping = mano_response.json()
1181 if mano_response.status_code != 200:
1182 str(mano_response.json())
1183 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1184 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1186 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1187 if not (len(r) > 0 and r[0].lower() == "y"):
1191 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1192 mano_response = requests.delete(URLrequest)
1193 logger.debug("openmano response: %s", mano_response.text)
1194 if mano_response.status_code != 200:
1195 return _print_verbose(mano_response, args.verbose)
1198 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1199 logger.debug("openmano request: %s", payload_req)
1200 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1201 logger.debug("openmano response: %s", mano_response.text)
1202 return _print_verbose(mano_response, args.verbose)
1205 def datacenter_sdn_port_mapping_list(args):
1206 tenant = _get_tenant()
1207 datacenter = _get_datacenter(args.name, tenant)
1209 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1210 mano_response = requests.get(URLrequest)
1211 logger.debug("openmano response: %s", mano_response.text)
1213 return _print_verbose(mano_response, 4)
1216 def datacenter_sdn_port_mapping_clear(args):
1217 tenant = _get_tenant()
1218 datacenter = _get_datacenter(args.name, tenant)
1221 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1222 if not (len(r) > 0 and r[0].lower() == "y"):
1225 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1226 mano_response = requests.delete(URLrequest)
1227 logger.debug("openmano response: %s", mano_response.text)
1229 return _print_verbose(mano_response, args.verbose)
1232 def sdn_controller_create(args):
1233 tenant = _get_tenant()
1234 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1237 if not args.ip: error_msg.append("'ip'")
1238 if not args.port: error_msg.append("'port'")
1239 if not args.dpid: error_msg.append("'dpid'")
1240 if not args.type: error_msg.append("'type'")
1242 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
1244 controller_dict = {}
1245 controller_dict['name'] = args.name
1246 controller_dict['ip'] = args.ip
1247 controller_dict['port'] = int(args.port)
1248 controller_dict['dpid'] = args.dpid
1249 controller_dict['type'] = args.type
1250 if args.description != None:
1251 controller_dict['description'] = args.description
1252 if args.user != None:
1253 controller_dict['user'] = args.user
1254 if args.password != None:
1255 controller_dict['password'] = args.password
1257 payload_req = json.dumps({"sdn_controller": controller_dict})
1261 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1262 logger.debug("openmano request: %s", payload_req)
1263 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1264 logger.debug("openmano response: %s", mano_response.text)
1265 result = _print_verbose(mano_response, args.verbose)
1269 def sdn_controller_edit(args):
1270 tenant = _get_tenant()
1271 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1272 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1274 controller_dict = {}
1276 controller_dict['name'] = args.new_name
1278 controller_dict['ip'] = args.ip
1280 controller_dict['port'] = int(args.port)
1282 controller_dict['dpid'] = args.dpid
1284 controller_dict['type'] = args.type
1285 if args.description:
1286 controller_dict['description'] = args.description
1288 controller_dict['user'] = args.user
1290 controller_dict['password'] = args.password
1292 if not controller_dict:
1293 raise OpenmanoCLIError("At least one parameter must be edited")
1296 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1297 if not (len(r) > 0 and r[0].lower() == "y"):
1300 payload_req = json.dumps({"sdn_controller": controller_dict})
1303 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1304 logger.debug("openmano request: %s", payload_req)
1305 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1306 logger.debug("openmano response: %s", mano_response.text)
1307 result = _print_verbose(mano_response, args.verbose)
1311 def sdn_controller_list(args):
1312 tenant = _get_tenant()
1313 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1316 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1317 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1319 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1321 mano_response = requests.get(URLrequest)
1322 logger.debug("openmano response: %s", mano_response.text )
1323 if args.verbose==None:
1328 # json.dumps(mano_response.json(), indent=4)
1329 return _print_verbose(mano_response, args.verbose)
1332 def sdn_controller_delete(args):
1333 tenant = _get_tenant()
1334 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1337 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1338 if not (len(r) > 0 and r[0].lower() == "y"):
1341 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1342 mano_response = requests.delete(URLrequest)
1343 logger.debug("openmano response: %s", mano_response.text)
1344 return _print_verbose(mano_response, args.verbose)
1346 def vim_action(args):
1347 #print "datacenter-net-action",args
1348 tenant = _get_tenant()
1349 datacenter = _get_datacenter(args.datacenter, tenant)
1350 if args.verbose==None:
1352 if args.action=="list":
1353 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1356 URLrequest += "/" + args.name
1357 mano_response = requests.get(URLrequest)
1358 logger.debug("openmano response: %s", mano_response.text )
1359 return _print_verbose(mano_response, args.verbose)
1360 elif args.action=="delete":
1361 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1362 mano_response = requests.delete(URLrequest)
1363 logger.debug("openmano response: %s", mano_response.text )
1364 result = 0 if mano_response.status_code==200 else mano_response.status_code
1365 content = mano_response.json()
1366 #print json.dumps(content, indent=4)
1367 if mano_response.status_code == 200:
1368 print content['result']
1370 print content['error']['description']
1372 elif args.action=="create":
1373 headers_req = {'content-type': 'application/yaml'}
1375 create_dict = _load_file_or_yaml(args.file)
1376 if args.item not in create_dict:
1377 create_dict = {args.item: create_dict}
1379 create_dict = {args.item:{}}
1381 create_dict[args.item]['name'] = args.name
1382 #if args.description:
1383 # create_dict[args.item]['description'] = args.description
1384 if args.item=="network":
1386 create_dict[args.item]['bind_net'] = args.bind_net
1388 create_dict[args.item]['type'] = args.type
1390 create_dict[args.item]['shared'] = args.shared
1391 if "name" not in create_dict[args.item]:
1392 print "You must provide a name in the descriptor file or with the --name option"
1394 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1395 logger.debug("openmano request: %s", payload_req)
1396 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1397 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1398 logger.debug("openmano response: %s", mano_response.text )
1399 if args.verbose==None:
1401 return _print_verbose(mano_response, args.verbose)
1404 def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1405 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1407 URLrequest += "/" + tenant
1409 URLrequest += "/vim/" + datacenter
1411 URLrequest += "/" + item +"s"
1413 URLrequest += "/" + item_name_id
1414 mano_response = requests.get(URLrequest)
1415 logger.debug("openmano response: %s", mano_response.text )
1417 return mano_response
1420 def vim_net_sdn_attach(args):
1421 #Verify the network exists in the vim
1422 tenant = _get_tenant()
1423 datacenter = _get_datacenter(args.datacenter, tenant)
1424 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1425 content = yaml.load(result.content)
1426 if 'networks' in content:
1427 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1428 if 'error' in content:
1429 raise OpenmanoCLIError(yaml.safe_dump(content))
1430 network_uuid = content['network']['id']
1432 #Make call to attach the dataplane port to the SND network associated to the vim network
1433 headers_req = {'content-type': 'application/yaml'}
1434 payload_req = {'port': args.port}
1436 payload_req['vlan'] = int(args.vlan)
1438 payload_req['mac'] = args.mac
1440 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1441 logger.debug("openmano request: %s", payload_req)
1442 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1443 logger.debug("openmano response: %s", mano_response.text)
1444 result = _print_verbose(mano_response, args.verbose)
1448 def vim_net_sdn_detach(args):
1449 if not args.all and not args.id:
1450 print "--all or --id must be used"
1453 # Verify the network exists in the vim
1454 tenant = _get_tenant()
1455 datacenter = _get_datacenter(args.datacenter, tenant)
1456 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1457 content = yaml.load(result.content)
1458 if 'networks' in content:
1459 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1460 if 'error' in content:
1461 raise OpenmanoCLIError(yaml.safe_dump(content))
1462 network_uuid = content['network']['id']
1465 r = raw_input("Confirm action' (y/N)? ")
1466 if len(r) == 0 or r[0].lower() != "y":
1470 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1471 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1473 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1474 mano_host, mano_port, tenant, datacenter, network_uuid)
1475 mano_response = requests.delete(URLrequest)
1476 logger.debug("openmano response: %s", mano_response.text)
1477 result = _print_verbose(mano_response, args.verbose)
1481 def datacenter_net_action(args):
1482 if args.action == "net-update":
1483 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1485 args.action = "netmap-delete"
1488 r = datacenter_netmap_action(args)
1491 args.action = "netmap-import"
1492 r = datacenter_netmap_action(args)
1495 if args.action == "net-edit":
1496 args.netmap = args.net
1498 elif args.action == "net-list":
1500 elif args.action == "net-delete":
1501 args.netmap = args.net
1504 args.action = "netmap" + args.action[3:]
1507 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1509 return datacenter_netmap_action(args)
1511 def datacenter_netmap_action(args):
1512 tenant = _get_tenant()
1513 datacenter = _get_datacenter(args.datacenter, tenant)
1514 #print "datacenter_netmap_action",args
1516 if args.verbose==None:
1518 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1519 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1521 if args.action=="netmap-list":
1523 URLrequest += "/" + args.netmap
1525 mano_response = requests.get(URLrequest)
1527 elif args.action=="netmap-delete":
1528 if args.netmap and args.all:
1529 print "you can not use a netmap name and the option --all at the same time"
1532 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1533 URLrequest += "/" + args.netmap
1535 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1537 print "you must specify a netmap name or the option --all"
1540 r = raw_input(force_text)
1541 if len(r)>0 and r[0].lower()=="y":
1545 mano_response = requests.delete(URLrequest, headers=headers_req)
1546 elif args.action=="netmap-import":
1548 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1549 if len(r)>0 and r[0].lower()=="y":
1553 URLrequest += "/upload"
1554 mano_response = requests.post(URLrequest, headers=headers_req)
1555 elif args.action=="netmap-edit" or args.action=="netmap-create":
1557 payload = _load_file_or_yaml(args.file)
1560 if "netmap" not in payload:
1561 payload = {"netmap": payload}
1563 payload["netmap"]["name"] = args.name
1565 payload["netmap"]["vim_id"] = args.vim_id
1566 if args.action=="netmap-create" and args.vim_name:
1567 payload["netmap"]["vim_name"] = args.vim_name
1568 payload_req = json.dumps(payload)
1569 logger.debug("openmano request: %s", payload_req)
1571 if args.action=="netmap-edit" and not args.force:
1572 if len(payload["netmap"]) == 0:
1573 print "You must supply some parameter to edit"
1575 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1576 if len(r)>0 and r[0].lower()=="y":
1580 URLrequest += "/" + args.netmap
1581 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1582 else: #netmap-create
1583 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1584 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1586 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1588 logger.debug("openmano response: %s", mano_response.text )
1589 return _print_verbose(mano_response, args.verbose)
1592 def element_edit(args):
1593 element = _get_item_uuid(args.element, args.name)
1594 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1595 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1596 payload=_load_file_or_yaml(args.file)
1597 if args.element[:-1] not in payload:
1598 payload = {args.element[:-1]: payload }
1599 payload_req = json.dumps(payload)
1602 if not args.force or (args.name==None and args.filer==None):
1603 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1604 if len(r)>0 and r[0].lower()=="y":
1608 logger.debug("openmano request: %s", payload_req)
1609 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1610 logger.debug("openmano response: %s", mano_response.text )
1611 if args.verbose==None:
1615 return _print_verbose(mano_response, args.verbose)
1618 def datacenter_edit(args):
1619 tenant = _get_tenant()
1620 element = _get_item_uuid('datacenters', args.name, tenant)
1621 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1622 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1624 has_arguments = False
1625 if args.file != None:
1626 has_arguments = True
1627 payload = _load_file_or_yaml(args.file)
1631 if args.sdn_controller != None:
1632 has_arguments = True
1633 if not 'config' in payload:
1634 payload['config'] = {}
1635 if not 'sdn-controller' in payload['config']:
1636 payload['config']['sdn-controller'] = {}
1637 if args.sdn_controller == 'null':
1638 payload['config']['sdn-controller'] = None
1640 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1642 if not has_arguments:
1643 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1645 if 'datacenter' not in payload:
1646 payload = {'datacenter': payload}
1647 payload_req = json.dumps(payload)
1650 if not args.force or (args.name == None and args.filer == None):
1651 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1652 if len(r) > 0 and r[0].lower() == "y":
1656 logger.debug("openmano request: %s", payload_req)
1657 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1658 logger.debug("openmano response: %s", mano_response.text)
1659 if args.verbose == None:
1661 if args.name != None:
1663 return _print_verbose(mano_response, args.verbose)
1667 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1668 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1670 mano_response = requests.get(URLrequest, headers=headers_req)
1671 logger.debug("openmano response: %s", mano_response.text)
1672 print mano_response.text
1679 if __name__=="__main__":
1681 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1682 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1683 mano_port = os.getenv('OPENMANO_PORT',"9090")
1684 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1686 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1687 main_parser.add_argument('--version', action='version', help="get version of this client",
1688 version='%(prog)s client version ' + __version__ +
1689 " (Note: use '%(prog)s version' to get server version)")
1691 subparsers = main_parser.add_subparsers(help='commands')
1693 parent_parser = argparse.ArgumentParser(add_help=False)
1694 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1695 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1697 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1698 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1699 config_parser.set_defaults(func=config)
1701 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1702 version_parser.set_defaults(func=version)
1704 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1705 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1706 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1707 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1708 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1709 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1710 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1711 vnf_create_parser.set_defaults(func=vnf_create)
1713 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1714 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1715 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1716 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1717 vnf_list_parser.set_defaults(func=vnf_list)
1719 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1720 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1721 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1722 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1723 vnf_delete_parser.set_defaults(func=vnf_delete)
1725 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1726 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1727 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1728 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1729 scenario_create_parser.set_defaults(func=scenario_create)
1731 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1732 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1733 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1734 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1735 scenario_list_parser.set_defaults(func=scenario_list)
1737 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1738 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1739 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1740 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1741 scenario_delete_parser.set_defaults(func=scenario_delete)
1743 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1744 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1745 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1746 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1747 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1748 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1749 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1751 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1752 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1753 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1754 scenario_deploy_parser.set_defaults(func=scenario_verify)
1756 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1757 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1758 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1759 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1760 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1761 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1762 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")
1763 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")
1764 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")
1765 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")
1766 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1767 instance_scenario_create_parser.set_defaults(func=instance_create)
1769 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1770 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1771 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1772 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1774 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)")
1775 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1776 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1777 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1778 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1780 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1781 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1782 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1783 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key","vdu-scaling"],\
1784 help="action to send")
1785 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}]'")
1786 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1787 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1788 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1790 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1791 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1792 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1793 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1794 action_parser.set_defaults(func=get_action)
1796 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1797 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1798 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1800 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1801 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1802 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1803 tenant_create_parser.set_defaults(func=tenant_create)
1805 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1806 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1807 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1808 tenant_delete_parser.set_defaults(func=tenant_delete)
1810 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1811 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1812 tenant_list_parser.set_defaults(func=tenant_list)
1814 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1815 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1816 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1817 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1818 element_edit_parser.set_defaults(func=element_edit, element='tenants')
1820 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1821 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1822 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1823 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1824 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1825 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1826 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1827 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1828 datacenter_create_parser.set_defaults(func=datacenter_create)
1830 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1831 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1832 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1833 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1835 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1836 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1837 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1838 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1839 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1840 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1841 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1843 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1844 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1845 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1846 datacenter_list_parser.set_defaults(func=datacenter_list)
1848 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1849 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1850 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1851 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1852 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1853 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1854 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1855 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1857 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1858 help="Edit the association of a datacenter to the operating tenant")
1859 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1860 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1861 help="specify a datacenter tenant to use. A new one is created by default")
1862 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1863 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1864 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1865 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1866 help="aditional configuration in json/yaml format")
1867 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1869 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1870 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1871 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1872 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1874 #=======================datacenter_sdn_port_mapping_xxx section=======================
1875 #datacenter_sdn_port_mapping_set
1876 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1877 parents=[parent_parser],
1878 help="Load a file with the mapping of physical ports "
1879 "and the ports of the dataplaneswitch controlled "
1881 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1882 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1883 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1884 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1885 help="forces overwriting without asking")
1886 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1888 #datacenter_sdn_port_mapping_list
1889 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1890 parents=[parent_parser],
1891 help="Show the SDN port mapping in a datacenter")
1892 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1893 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1895 # datacenter_sdn_port_mapping_clear
1896 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1897 parents=[parent_parser],
1898 help="Clean the the SDN port mapping in a datacenter")
1899 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1900 help="specifies the datacenter")
1901 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1902 help="forces clearing without asking")
1903 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1904 # =======================
1906 # =======================sdn_controller_xxx section=======================
1907 # sdn_controller_create
1908 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1909 help="Creates an SDN controller entity within RO")
1910 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1911 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1912 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1913 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1914 sdn_controller_create_parser.add_argument("--dpid", action="store",
1915 help="DPID of the dataplane switch controlled by this SDN controller")
1916 sdn_controller_create_parser.add_argument("--type", action="store",
1917 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1918 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1919 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1920 help="password credentials for the SDN controller")
1921 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1923 # sdn_controller_edit
1924 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1925 help="Update one or more options of a SDN controller")
1926 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1927 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1929 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1930 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1931 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1932 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1933 help="DPID of the dataplane switch controlled by this SDN controller")
1934 sdn_controller_edit_parser.add_argument("--type", action="store",
1935 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1936 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1937 sdn_controller_edit_parser.add_argument("--password", action="store",
1938 help="password credentials for the SDN controller", dest='password')
1939 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1940 #TODO: include option --file
1941 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1943 #sdn_controller_list
1944 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1945 parents=[parent_parser],
1946 help="List the SDN controllers")
1947 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1948 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1950 # sdn_controller_delete
1951 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1952 parents=[parent_parser],
1953 help="Delete the the SDN controller")
1954 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1955 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1956 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1957 # =======================
1959 action_dict={'net-update': 'retrieves external networks from datacenter',
1960 'net-edit': 'edits an external network',
1961 'net-delete': 'deletes an external network',
1962 'net-list': 'lists external networks from a datacenter'
1964 for item in action_dict:
1965 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1966 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1967 if item=='net-edit' or item=='net-delete':
1968 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1969 if item=='net-edit':
1970 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1971 if item!='net-list':
1972 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1973 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1976 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1977 'netmap-create': 'create a new network senario netmap',
1978 'netmap-edit': 'edit name of a network senario netmap',
1979 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1980 'netmap-list': 'list/show network scenario netmaps'
1982 for item in action_dict:
1983 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1984 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1985 #if item=='net-add':
1986 # datacenter_action_parser.add_argument("net", help="name of the network")
1987 if item=='netmap-delete':
1988 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1989 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1990 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1991 if item=='netmap-edit':
1992 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1993 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1994 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1995 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1996 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1997 if item=='netmap-list':
1998 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1999 if item=='netmap-create':
2000 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
2001 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
2002 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2003 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
2004 if item=='netmap-import':
2005 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2006 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
2008 # =======================vim_net_sdn_xxx section=======================
2009 # vim_net_sdn_attach
2010 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2011 parents=[parent_parser],
2012 help="Specify the port to access to an external network using SDN")
2013 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2014 help="Name/id of the network in the vim that will be used to connect to the external network")
2015 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2016 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2017 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")
2018 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2019 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2021 # vim_net_sdn_detach
2022 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2023 parents=[parent_parser],
2024 help="Remove the port information to access to an external network using SDN")
2026 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2027 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2028 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2029 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2030 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2031 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2032 # =======================
2034 for item in ("network", "tenant", "image"):
2036 command_name = 'vim-net'
2038 command_name = 'vim-'+item
2039 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
2040 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2041 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2042 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2044 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
2045 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2046 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2047 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2049 if item == "network" or item == "tenant":
2050 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
2051 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2052 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2053 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2055 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2056 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2057 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>'")
2059 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2060 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
2062 argcomplete.autocomplete(main_parser)
2065 args = main_parser.parse_args()
2067 level = logging.CRITICAL
2068 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2069 if "debug" in args and args.debug:
2070 level = logging.DEBUG
2071 logging.basicConfig(format=streamformat, level= level)
2072 logger = logging.getLogger('mano')
2073 logger.setLevel(level)
2074 result = args.func(args)
2077 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2078 except (requests.exceptions.ConnectionError):
2079 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2081 except (KeyboardInterrupt):
2082 print 'Exiting openmano'
2084 except (SystemExit, ArgumentParserError):
2086 except OpenmanoCLIError as e: