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.22-r532"
32 version_date = "Oct 2017"
34 from argcomplete.completers import FilesCompleter
42 #from jsonschema import validate as js_v, exceptions as js_e
44 class ArgumentParserError(Exception): pass
46 class OpenmanoCLIError(Exception): pass
48 class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
69 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
70 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
71 mano_response = requests.get(URLrequest)
72 logger.debug("openmano response: %s", mano_response.text )
73 content = mano_response.json()
74 mano_tenant_name = content["tenant"]["name"]
75 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
76 mano_response = requests.get(URLrequest)
77 logger.debug("openmano response: %s", mano_response.text )
78 content = mano_response.json()
79 if "error" not in content:
80 mano_datacenter_id = content["datacenter"]["uuid"]
81 mano_datacenter_name = content["datacenter"]["name"]
82 except OpenmanoCLIError:
84 print "OPENMANO_TENANT: %s" %mano_tenant
85 print " Id: %s" %mano_tenant_id
86 print " Name: %s" %mano_tenant_name
87 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
88 print " Id: %s" %mano_datacenter_id
89 print " Name: %s" %mano_datacenter_name
91 print "OPENMANO_TENANT: %s" %mano_tenant
92 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
94 def _print_verbose(mano_response, verbose_level=0):
95 content = mano_response.json()
96 result = 0 if mano_response.status_code==200 else mano_response.status_code
97 if type(content)!=dict or len(content)!=1:
98 #print "Non expected format output"
102 val=content.values()[0]
106 elif type(val) == list:
108 elif type(val)==dict:
111 #print "Non expected dict/list format output"
116 if verbose_level==None:
118 if verbose_level >= 3:
119 print yaml.safe_dump(content, indent=4, default_flow_style=False)
122 if mano_response.status_code == 200:
124 for content in content_list:
125 if "uuid" in content:
126 uuid = content['uuid']
127 elif "id" in content:
129 elif "vim_id" in content:
130 uuid = content['vim_id']
131 name = content.get('name');
136 myoutput = "{: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 ] = 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 for uuid,c in content.iteritems():
949 print ("{:38} {:20} {:20}".format(uuid, c['name'], c['description']))
951 print content['error']['description']
955 def instance_vnf_list(args):
956 print "instance-vnf-list"
959 def instance_vnf_status(args):
960 print "instance-vnf-status"
963 def tenant_create(args):
964 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
965 tenant_dict={"name": args.name}
966 if args.description!=None:
967 tenant_dict["description"] = args.description
968 payload_req = json.dumps( {"tenant": tenant_dict })
972 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
973 logger.debug("openmano request: %s", payload_req)
974 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
975 logger.debug("openmano response: %s", mano_response.text )
976 return _print_verbose(mano_response, args.verbose)
978 def tenant_list(args):
979 #print "tenant-list",args
981 toshow = _get_item_uuid("tenants", args.name)
982 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
984 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
985 mano_response = requests.get(URLrequest)
986 logger.debug("openmano response: %s", mano_response.text )
987 if args.verbose==None:
991 return _print_verbose(mano_response, args.verbose)
993 def tenant_delete(args):
994 #print "tenant-delete",args
995 todelete = _get_item_uuid("tenants", args.name)
997 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
998 if not (len(r)>0 and r[0].lower()=="y"):
1000 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
1001 mano_response = requests.delete(URLrequest)
1002 logger.debug("openmano response: %s", mano_response.text )
1003 result = 0 if mano_response.status_code==200 else mano_response.status_code
1004 content = mano_response.json()
1005 #print json.dumps(content, indent=4)
1006 if mano_response.status_code == 200:
1007 print content['result']
1009 print content['error']['description']
1012 def datacenter_attach(args):
1013 tenant = _get_tenant()
1014 datacenter = _get_datacenter(args.name)
1015 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1018 if args.vim_tenant_id != None:
1019 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1020 if args.vim_tenant_name != None:
1021 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1022 if args.user != None:
1023 datacenter_dict['vim_username'] = args.user
1024 if args.password != None:
1025 datacenter_dict['vim_password'] = args.password
1026 if args.config!=None:
1027 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1029 payload_req = json.dumps( {"datacenter": datacenter_dict })
1033 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1034 logger.debug("openmano request: %s", payload_req)
1035 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1036 logger.debug("openmano response: %s", mano_response.text )
1037 result = _print_verbose(mano_response, args.verbose)
1038 #provide addional information if error
1039 if mano_response.status_code != 200:
1040 content = mano_response.json()
1041 if "already in use for 'name'" in content['error']['description'] and \
1042 "to database vim_tenants table" in content['error']['description']:
1043 print "Try to specify a different name with --vim-tenant-name"
1047 def datacenter_edit_vim_tenant(args):
1048 tenant = _get_tenant()
1049 datacenter = _get_datacenter(args.name)
1050 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1052 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1053 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1055 datacenter_dict = {}
1056 if args.vim_tenant_id != None:
1057 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1058 if args.vim_tenant_name != None:
1059 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1060 if args.user != None:
1061 datacenter_dict['vim_username'] = args.user
1062 if args.password != None:
1063 datacenter_dict['vim_password'] = args.password
1064 if args.config != None:
1065 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1066 payload_req = json.dumps({"datacenter": datacenter_dict})
1070 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1071 logger.debug("openmano request: %s", payload_req)
1072 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1073 logger.debug("openmano response: %s", mano_response.text)
1074 result = _print_verbose(mano_response, args.verbose)
1078 def datacenter_detach(args):
1082 tenant = _get_tenant()
1083 datacenter = _get_datacenter(args.name, tenant)
1084 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1085 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1086 mano_response = requests.delete(URLrequest, headers=headers_req)
1087 logger.debug("openmano response: %s", mano_response.text )
1088 content = mano_response.json()
1089 #print json.dumps(content, indent=4)
1090 result = 0 if mano_response.status_code==200 else mano_response.status_code
1091 if mano_response.status_code == 200:
1092 print content['result']
1094 print content['error']['description']
1097 def datacenter_create(args):
1098 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1099 datacenter_dict={"name": args.name, "vim_url": args.url}
1100 if args.description!=None:
1101 datacenter_dict["description"] = args.description
1103 datacenter_dict["type"] = args.type
1105 datacenter_dict["vim_url_admin"] = args.url_admin
1106 if args.config!=None:
1107 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1108 if args.sdn_controller!=None:
1109 tenant = _get_tenant()
1110 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1111 if not 'config' in datacenter_dict:
1112 datacenter_dict['config'] = {}
1113 datacenter_dict['config']['sdn-controller'] = sdn_controller
1114 payload_req = json.dumps( {"datacenter": datacenter_dict })
1118 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1119 logger.debug("openmano request: %s", payload_req)
1120 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1121 logger.debug("openmano response: %s", mano_response.text )
1122 return _print_verbose(mano_response, args.verbose)
1124 def datacenter_delete(args):
1125 #print "datacenter-delete",args
1126 todelete = _get_item_uuid("datacenters", args.name, "any")
1128 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1129 if not (len(r)>0 and r[0].lower()=="y"):
1131 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1132 mano_response = requests.delete(URLrequest)
1133 logger.debug("openmano response: %s", mano_response.text )
1134 result = 0 if mano_response.status_code==200 else mano_response.status_code
1135 content = mano_response.json()
1136 #print json.dumps(content, indent=4)
1137 if mano_response.status_code == 200:
1138 print content['result']
1140 print content['error']['description']
1144 def datacenter_list(args):
1145 #print "datacenter-list",args
1146 tenant='any' if args.all else _get_tenant()
1149 toshow = _get_item_uuid("datacenters", args.name, tenant)
1150 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1152 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1153 mano_response = requests.get(URLrequest)
1154 logger.debug("openmano response: %s", mano_response.text )
1155 if args.verbose==None:
1159 return _print_verbose(mano_response, args.verbose)
1162 def datacenter_sdn_port_mapping_set(args):
1163 tenant = _get_tenant()
1164 datacenter = _get_datacenter(args.name, tenant)
1165 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1168 raise OpenmanoCLIError(
1169 "No yaml/json has been provided specifying the SDN port mapping")
1170 sdn_port_mapping = _load_file_or_yaml(args.file)
1171 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1174 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1175 mano_response = requests.get(URLrequest)
1176 logger.debug("openmano response: %s", mano_response.text)
1177 port_mapping = mano_response.json()
1178 if mano_response.status_code != 200:
1179 str(mano_response.json())
1180 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1181 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1183 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1184 if not (len(r) > 0 and r[0].lower() == "y"):
1188 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1189 mano_response = requests.delete(URLrequest)
1190 logger.debug("openmano response: %s", mano_response.text)
1191 if mano_response.status_code != 200:
1192 return _print_verbose(mano_response, args.verbose)
1195 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1196 logger.debug("openmano request: %s", payload_req)
1197 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1198 logger.debug("openmano response: %s", mano_response.text)
1199 return _print_verbose(mano_response, args.verbose)
1202 def datacenter_sdn_port_mapping_list(args):
1203 tenant = _get_tenant()
1204 datacenter = _get_datacenter(args.name, tenant)
1206 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1207 mano_response = requests.get(URLrequest)
1208 logger.debug("openmano response: %s", mano_response.text)
1210 return _print_verbose(mano_response, 4)
1213 def datacenter_sdn_port_mapping_clear(args):
1214 tenant = _get_tenant()
1215 datacenter = _get_datacenter(args.name, tenant)
1218 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1219 if not (len(r) > 0 and r[0].lower() == "y"):
1222 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1223 mano_response = requests.delete(URLrequest)
1224 logger.debug("openmano response: %s", mano_response.text)
1226 return _print_verbose(mano_response, args.verbose)
1229 def sdn_controller_create(args):
1230 tenant = _get_tenant()
1231 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1234 if not args.ip: error_msg.append("'ip'")
1235 if not args.port: error_msg.append("'port'")
1236 if not args.dpid: error_msg.append("'dpid'")
1237 if not args.type: error_msg.append("'type'")
1239 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
1241 controller_dict = {}
1242 controller_dict['name'] = args.name
1243 controller_dict['ip'] = args.ip
1244 controller_dict['port'] = int(args.port)
1245 controller_dict['dpid'] = args.dpid
1246 controller_dict['type'] = args.type
1247 if args.description != None:
1248 controller_dict['description'] = args.description
1249 if args.user != None:
1250 controller_dict['user'] = args.user
1251 if args.password != None:
1252 controller_dict['password'] = args.password
1254 payload_req = json.dumps({"sdn_controller": controller_dict})
1258 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1259 logger.debug("openmano request: %s", payload_req)
1260 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1261 logger.debug("openmano response: %s", mano_response.text)
1262 result = _print_verbose(mano_response, args.verbose)
1266 def sdn_controller_edit(args):
1267 tenant = _get_tenant()
1268 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1269 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1271 controller_dict = {}
1273 controller_dict['name'] = args.new_name
1275 controller_dict['ip'] = args.ip
1277 controller_dict['port'] = int(args.port)
1279 controller_dict['dpid'] = args.dpid
1281 controller_dict['type'] = args.type
1282 if args.description:
1283 controller_dict['description'] = args.description
1285 controller_dict['user'] = args.user
1287 controller_dict['password'] = args.password
1289 if not controller_dict:
1290 raise OpenmanoCLIError("At least one parameter must be edited")
1293 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1294 if not (len(r) > 0 and r[0].lower() == "y"):
1297 payload_req = json.dumps({"sdn_controller": controller_dict})
1300 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1301 logger.debug("openmano request: %s", payload_req)
1302 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1303 logger.debug("openmano response: %s", mano_response.text)
1304 result = _print_verbose(mano_response, args.verbose)
1308 def sdn_controller_list(args):
1309 tenant = _get_tenant()
1310 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1313 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1314 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1316 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1318 mano_response = requests.get(URLrequest)
1319 logger.debug("openmano response: %s", mano_response.text )
1320 if args.verbose==None:
1325 # json.dumps(mano_response.json(), indent=4)
1326 return _print_verbose(mano_response, args.verbose)
1329 def sdn_controller_delete(args):
1330 tenant = _get_tenant()
1331 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1334 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1335 if not (len(r) > 0 and r[0].lower() == "y"):
1338 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1339 mano_response = requests.delete(URLrequest)
1340 logger.debug("openmano response: %s", mano_response.text)
1341 return _print_verbose(mano_response, args.verbose)
1343 def vim_action(args):
1344 #print "datacenter-net-action",args
1345 tenant = _get_tenant()
1346 datacenter = _get_datacenter(args.datacenter, tenant)
1347 if args.verbose==None:
1349 if args.action=="list":
1350 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1353 URLrequest += "/" + args.name
1354 mano_response = requests.get(URLrequest)
1355 logger.debug("openmano response: %s", mano_response.text )
1356 return _print_verbose(mano_response, args.verbose)
1357 elif args.action=="delete":
1358 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1359 mano_response = requests.delete(URLrequest)
1360 logger.debug("openmano response: %s", mano_response.text )
1361 result = 0 if mano_response.status_code==200 else mano_response.status_code
1362 content = mano_response.json()
1363 #print json.dumps(content, indent=4)
1364 if mano_response.status_code == 200:
1365 print content['result']
1367 print content['error']['description']
1369 elif args.action=="create":
1370 headers_req = {'content-type': 'application/yaml'}
1372 create_dict = _load_file_or_yaml(args.file)
1373 if args.item not in create_dict:
1374 create_dict = {args.item: create_dict}
1376 create_dict = {args.item:{}}
1378 create_dict[args.item]['name'] = args.name
1379 #if args.description:
1380 # create_dict[args.item]['description'] = args.description
1381 if args.item=="network":
1383 create_dict[args.item]['bind_net'] = args.bind_net
1385 create_dict[args.item]['type'] = args.type
1387 create_dict[args.item]['shared'] = args.shared
1388 if "name" not in create_dict[args.item]:
1389 print "You must provide a name in the descriptor file or with the --name option"
1391 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1392 logger.debug("openmano request: %s", payload_req)
1393 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1394 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1395 logger.debug("openmano response: %s", mano_response.text )
1396 if args.verbose==None:
1398 return _print_verbose(mano_response, args.verbose)
1401 def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1402 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1404 URLrequest += "/" + tenant
1406 URLrequest += "/vim/" + datacenter
1408 URLrequest += "/" + item +"s"
1410 URLrequest += "/" + item_name_id
1411 mano_response = requests.get(URLrequest)
1412 logger.debug("openmano response: %s", mano_response.text )
1414 return mano_response
1417 def vim_net_sdn_attach(args):
1418 #Verify the network exists in the vim
1419 tenant = _get_tenant()
1420 datacenter = _get_datacenter(args.datacenter, tenant)
1421 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1422 content = yaml.load(result.content)
1423 if 'networks' in content:
1424 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1425 if 'error' in content:
1426 raise OpenmanoCLIError(yaml.safe_dump(content))
1427 network_uuid = content['network']['id']
1429 #Make call to attach the dataplane port to the SND network associated to the vim network
1430 headers_req = {'content-type': 'application/yaml'}
1431 payload_req = {'port': args.port}
1433 payload_req['vlan'] = int(args.vlan)
1435 payload_req['mac'] = args.mac
1437 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1438 logger.debug("openmano request: %s", payload_req)
1439 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1440 logger.debug("openmano response: %s", mano_response.text)
1441 result = _print_verbose(mano_response, args.verbose)
1445 def vim_net_sdn_detach(args):
1446 if not args.all and not args.id:
1447 print "--all or --id must be used"
1450 # Verify the network exists in the vim
1451 tenant = _get_tenant()
1452 datacenter = _get_datacenter(args.datacenter, tenant)
1453 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1454 content = yaml.load(result.content)
1455 if 'networks' in content:
1456 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1457 if 'error' in content:
1458 raise OpenmanoCLIError(yaml.safe_dump(content))
1459 network_uuid = content['network']['id']
1462 r = raw_input("Confirm action' (y/N)? ")
1463 if len(r) == 0 or r[0].lower() != "y":
1467 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1468 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1470 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1471 mano_host, mano_port, tenant, datacenter, network_uuid)
1472 mano_response = requests.delete(URLrequest)
1473 logger.debug("openmano response: %s", mano_response.text)
1474 result = _print_verbose(mano_response, args.verbose)
1478 def datacenter_net_action(args):
1479 if args.action == "net-update":
1480 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1482 args.action = "netmap-delete"
1485 r = datacenter_netmap_action(args)
1488 args.action = "netmap-import"
1489 r = datacenter_netmap_action(args)
1492 if args.action == "net-edit":
1493 args.netmap = args.net
1495 elif args.action == "net-list":
1497 elif args.action == "net-delete":
1498 args.netmap = args.net
1501 args.action = "netmap" + args.action[3:]
1504 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1506 return datacenter_netmap_action(args)
1508 def datacenter_netmap_action(args):
1509 tenant = _get_tenant()
1510 datacenter = _get_datacenter(args.datacenter, tenant)
1511 #print "datacenter_netmap_action",args
1513 if args.verbose==None:
1515 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1516 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1518 if args.action=="netmap-list":
1520 URLrequest += "/" + args.netmap
1522 mano_response = requests.get(URLrequest)
1524 elif args.action=="netmap-delete":
1525 if args.netmap and args.all:
1526 print "you can not use a netmap name and the option --all at the same time"
1529 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1530 URLrequest += "/" + args.netmap
1532 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1534 print "you must specify a netmap name or the option --all"
1537 r = raw_input(force_text)
1538 if len(r)>0 and r[0].lower()=="y":
1542 mano_response = requests.delete(URLrequest, headers=headers_req)
1543 elif args.action=="netmap-import":
1545 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1546 if len(r)>0 and r[0].lower()=="y":
1550 URLrequest += "/upload"
1551 mano_response = requests.post(URLrequest, headers=headers_req)
1552 elif args.action=="netmap-edit" or args.action=="netmap-create":
1554 payload = _load_file_or_yaml(args.file)
1557 if "netmap" not in payload:
1558 payload = {"netmap": payload}
1560 payload["netmap"]["name"] = args.name
1562 payload["netmap"]["vim_id"] = args.vim_id
1563 if args.action=="netmap-create" and args.vim_name:
1564 payload["netmap"]["vim_name"] = args.vim_name
1565 payload_req = json.dumps(payload)
1566 logger.debug("openmano request: %s", payload_req)
1568 if args.action=="netmap-edit" and not args.force:
1569 if len(payload["netmap"]) == 0:
1570 print "You must supply some parameter to edit"
1572 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1573 if len(r)>0 and r[0].lower()=="y":
1577 URLrequest += "/" + args.netmap
1578 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1579 else: #netmap-create
1580 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1581 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1583 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1585 logger.debug("openmano response: %s", mano_response.text )
1586 return _print_verbose(mano_response, args.verbose)
1589 def element_edit(args):
1590 element = _get_item_uuid(args.element, args.name)
1591 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1592 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1593 payload=_load_file_or_yaml(args.file)
1594 if args.element[:-1] not in payload:
1595 payload = {args.element[:-1]: payload }
1596 payload_req = json.dumps(payload)
1599 if not args.force or (args.name==None and args.filer==None):
1600 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1601 if len(r)>0 and r[0].lower()=="y":
1605 logger.debug("openmano request: %s", payload_req)
1606 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1607 logger.debug("openmano response: %s", mano_response.text )
1608 if args.verbose==None:
1612 return _print_verbose(mano_response, args.verbose)
1615 def datacenter_edit(args):
1616 tenant = _get_tenant()
1617 element = _get_item_uuid('datacenters', args.name, tenant)
1618 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1619 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1621 has_arguments = False
1622 if args.file != None:
1623 has_arguments = True
1624 payload = _load_file_or_yaml(args.file)
1628 if args.sdn_controller != None:
1629 has_arguments = True
1630 if not 'config' in payload:
1631 payload['config'] = {}
1632 if not 'sdn-controller' in payload['config']:
1633 payload['config']['sdn-controller'] = {}
1634 if args.sdn_controller == 'null':
1635 payload['config']['sdn-controller'] = None
1637 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1639 if not has_arguments:
1640 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1642 if 'datacenter' not in payload:
1643 payload = {'datacenter': payload}
1644 payload_req = json.dumps(payload)
1647 if not args.force or (args.name == None and args.filer == None):
1648 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1649 if len(r) > 0 and r[0].lower() == "y":
1653 logger.debug("openmano request: %s", payload_req)
1654 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1655 logger.debug("openmano response: %s", mano_response.text)
1656 if args.verbose == None:
1658 if args.name != None:
1660 return _print_verbose(mano_response, args.verbose)
1664 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1665 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1667 mano_response = requests.get(URLrequest, headers=headers_req)
1668 logger.debug("openmano response: %s", mano_response.text)
1669 print mano_response.text
1676 if __name__=="__main__":
1678 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1679 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1680 mano_port = os.getenv('OPENMANO_PORT',"9090")
1681 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1683 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1684 main_parser.add_argument('--version', action='version', help="get version of this client",
1685 version='%(prog)s client version ' + __version__ +
1686 " (Note: use '%(prog)s version' to get server version)")
1688 subparsers = main_parser.add_subparsers(help='commands')
1690 parent_parser = argparse.ArgumentParser(add_help=False)
1691 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1692 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1694 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1695 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1696 config_parser.set_defaults(func=config)
1698 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1699 version_parser.set_defaults(func=version)
1701 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1702 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1703 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1704 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1705 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1706 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1707 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1708 vnf_create_parser.set_defaults(func=vnf_create)
1710 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1711 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1712 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1713 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1714 vnf_list_parser.set_defaults(func=vnf_list)
1716 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1717 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1718 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1719 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1720 vnf_delete_parser.set_defaults(func=vnf_delete)
1722 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1723 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1724 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1725 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1726 scenario_create_parser.set_defaults(func=scenario_create)
1728 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1729 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1730 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1731 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1732 scenario_list_parser.set_defaults(func=scenario_list)
1734 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1735 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1736 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1737 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1738 scenario_delete_parser.set_defaults(func=scenario_delete)
1740 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1741 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1742 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1743 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1744 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1745 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1746 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1748 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1749 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1750 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1751 scenario_deploy_parser.set_defaults(func=scenario_verify)
1753 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1754 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1755 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1756 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1757 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1758 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1759 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")
1760 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")
1761 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")
1762 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")
1763 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1764 instance_scenario_create_parser.set_defaults(func=instance_create)
1766 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1767 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1768 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1769 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1771 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)")
1772 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1773 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1774 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1775 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1777 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1778 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1779 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1780 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key"],\
1781 help="action to send")
1782 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1783 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1784 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1785 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1787 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1788 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1789 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1790 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1791 action_parser.set_defaults(func=get_action)
1793 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1794 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1795 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1797 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1798 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1799 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1800 tenant_create_parser.set_defaults(func=tenant_create)
1802 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1803 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1804 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1805 tenant_delete_parser.set_defaults(func=tenant_delete)
1807 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1808 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1809 tenant_list_parser.set_defaults(func=tenant_list)
1811 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1812 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1813 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1814 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1815 element_edit_parser.set_defaults(func=element_edit, element='tenants')
1817 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1818 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1819 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1820 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1821 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1822 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1823 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1824 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1825 datacenter_create_parser.set_defaults(func=datacenter_create)
1827 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1828 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1829 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1830 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1832 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1833 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1834 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1835 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1836 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1837 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1838 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1840 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1841 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1842 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1843 datacenter_list_parser.set_defaults(func=datacenter_list)
1845 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1846 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1847 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1848 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1849 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1850 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1851 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1852 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1854 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1855 help="Edit the association of a datacenter to the operating tenant")
1856 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1857 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1858 help="specify a datacenter tenant to use. A new one is created by default")
1859 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1860 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1861 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1862 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1863 help="aditional configuration in json/yaml format")
1864 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1866 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1867 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1868 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1869 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1871 #=======================datacenter_sdn_port_mapping_xxx section=======================
1872 #datacenter_sdn_port_mapping_set
1873 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1874 parents=[parent_parser],
1875 help="Load a file with the mapping of physical ports "
1876 "and the ports of the dataplaneswitch controlled "
1878 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1879 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1880 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1881 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1882 help="forces overwriting without asking")
1883 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1885 #datacenter_sdn_port_mapping_list
1886 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1887 parents=[parent_parser],
1888 help="Show the SDN port mapping in a datacenter")
1889 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1890 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1892 # datacenter_sdn_port_mapping_clear
1893 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1894 parents=[parent_parser],
1895 help="Clean the the SDN port mapping in a datacenter")
1896 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1897 help="specifies the datacenter")
1898 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1899 help="forces clearing without asking")
1900 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1901 # =======================
1903 # =======================sdn_controller_xxx section=======================
1904 # sdn_controller_create
1905 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1906 help="Creates an SDN controller entity within RO")
1907 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1908 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1909 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1910 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1911 sdn_controller_create_parser.add_argument("--dpid", action="store",
1912 help="DPID of the dataplane switch controlled by this SDN controller")
1913 sdn_controller_create_parser.add_argument("--type", action="store",
1914 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1915 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1916 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1917 help="password credentials for the SDN controller")
1918 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1920 # sdn_controller_edit
1921 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1922 help="Update one or more options of a SDN controller")
1923 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1924 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1926 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1927 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1928 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1929 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1930 help="DPID of the dataplane switch controlled by this SDN controller")
1931 sdn_controller_edit_parser.add_argument("--type", action="store",
1932 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1933 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1934 sdn_controller_edit_parser.add_argument("--password", action="store",
1935 help="password credentials for the SDN controller", dest='password')
1936 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1937 #TODO: include option --file
1938 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1940 #sdn_controller_list
1941 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1942 parents=[parent_parser],
1943 help="List the SDN controllers")
1944 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1945 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1947 # sdn_controller_delete
1948 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1949 parents=[parent_parser],
1950 help="Delete the the SDN controller")
1951 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1952 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1953 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1954 # =======================
1956 action_dict={'net-update': 'retrieves external networks from datacenter',
1957 'net-edit': 'edits an external network',
1958 'net-delete': 'deletes an external network',
1959 'net-list': 'lists external networks from a datacenter'
1961 for item in action_dict:
1962 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1963 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1964 if item=='net-edit' or item=='net-delete':
1965 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1966 if item=='net-edit':
1967 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1968 if item!='net-list':
1969 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1970 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1973 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1974 'netmap-create': 'create a new network senario netmap',
1975 'netmap-edit': 'edit name of a network senario netmap',
1976 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1977 'netmap-list': 'list/show network scenario netmaps'
1979 for item in action_dict:
1980 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1981 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1982 #if item=='net-add':
1983 # datacenter_action_parser.add_argument("net", help="name of the network")
1984 if item=='netmap-delete':
1985 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1986 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1987 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1988 if item=='netmap-edit':
1989 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1990 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1991 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1992 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1993 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1994 if item=='netmap-list':
1995 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1996 if item=='netmap-create':
1997 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1998 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1999 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2000 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
2001 if item=='netmap-import':
2002 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2003 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
2005 # =======================vim_net_sdn_xxx section=======================
2006 # vim_net_sdn_attach
2007 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2008 parents=[parent_parser],
2009 help="Specify the port to access to an external network using SDN")
2010 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2011 help="Name/id of the network in the vim that will be used to connect to the external network")
2012 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2013 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2014 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")
2015 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2016 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2018 # vim_net_sdn_detach
2019 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2020 parents=[parent_parser],
2021 help="Remove the port information to access to an external network using SDN")
2023 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2024 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2025 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2026 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2027 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2028 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2029 # =======================
2031 for item in ("network", "tenant", "image"):
2033 command_name = 'vim-net'
2035 command_name = 'vim-'+item
2036 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
2037 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2038 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2039 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2041 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
2042 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2043 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2044 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2046 if item == "network" or item == "tenant":
2047 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
2048 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2049 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2050 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2052 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2053 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2054 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>'")
2056 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2057 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
2059 argcomplete.autocomplete(main_parser)
2062 args = main_parser.parse_args()
2064 level = logging.CRITICAL
2065 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2066 if "debug" in args and args.debug:
2067 level = logging.DEBUG
2068 logging.basicConfig(format=streamformat, level= level)
2069 logger = logging.getLogger('mano')
2070 logger.setLevel(level)
2071 result = args.func(args)
2074 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2075 except (requests.exceptions.ConnectionError):
2076 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2078 except (KeyboardInterrupt):
2079 print 'Exiting openmano'
2081 except (SystemExit, ArgumentParserError):
2083 except OpenmanoCLIError as e: