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 else: # image name in volumes
321 vdu_list[index]["volumes"][0]["image"] = image_name_
322 if "image-checksum" in vdu_list[index]["volumes"][0]:
323 del vdu_list[index]["volumes"][0]["image-checksum"]
325 vdu_list[index]['image name'] = image_name_
326 if "VNFC image" in vdu_list[index]:
327 del vdu_list[index]["VNFC image"]
329 if args.image_checksum:
331 for image_checksum_ in args.image_checksum.split(","):
332 if api_version == "/v3":
333 if vdu_list[index].get("image"):
334 vdu_list[index]['image-checksum'] = image_checksum_
335 else: # image name in volumes
336 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
338 vdu_list[index]['image checksum'] = image_checksum_
340 except (KeyError, TypeError), e:
341 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
342 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
343 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
344 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
345 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
346 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
347 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
348 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
349 else: error_pos="wrong format"
350 print "Wrong VNF descriptor: " + error_pos
352 payload_req = json.dumps(myvnf)
356 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
357 logger.debug("openmano request: %s", payload_req)
358 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
359 logger.debug("openmano response: %s", mano_response.text )
361 return _print_verbose(mano_response, args.verbose)
364 #print "vnf-list",args
368 tenant = _get_tenant()
370 toshow = _get_item_uuid("vnfs", args.name, tenant)
371 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
373 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
374 mano_response = requests.get(URLrequest)
375 logger.debug("openmano response: %s", mano_response.text )
376 content = mano_response.json()
377 # print json.dumps(content, indent=4)
378 if args.verbose==None:
380 result = 0 if mano_response.status_code==200 else mano_response.status_code
381 if mano_response.status_code == 200:
383 if args.verbose >= 3:
384 print yaml.safe_dump(content, indent=4, default_flow_style=False)
386 if len(content['vnfs']) == 0:
387 print "No VNFs were found."
388 return 404 # HTTP_Not_Found
389 for vnf in content['vnfs']:
390 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
391 if vnf.get('osm_id') or args.verbose >= 1:
392 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
393 if args.verbose >= 1:
394 myoutput += " {}".format(vnf['created_at'])
396 if args.verbose >= 2:
397 print (" Description: {}".format(vnf['description']))
398 # print (" VNF descriptor file: {}".format(vnf['path']))
401 print yaml.safe_dump(content, indent=4, default_flow_style=False)
404 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
406 print (" Description: {}".format(vnf['description']))
407 # print " VNF descriptor file: %s" %vnf['path']
409 for vm in vnf['VNFC']:
410 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
411 if len(vnf['nets']) > 0:
412 print (" Internal nets:")
413 for net in vnf['nets']:
414 print (" {:20} {}".format(net['name'], net['description']))
415 if len(vnf['external-connections']) > 0:
416 print (" External interfaces:")
417 for interface in vnf['external-connections']:
418 print (" {:20} {:20} {:20} {:14}".format(
419 interface['external_name'], interface['vm_name'],
420 interface['internal_name'],
421 interface.get('vpci') if interface.get('vpci') else ""))
423 print content['error']['description']
425 print yaml.safe_dump(content, indent=4, default_flow_style=False)
428 def vnf_delete(args):
429 #print "vnf-delete",args
433 tenant = _get_tenant()
434 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
436 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
437 if not (len(r)>0 and r[0].lower()=="y"):
439 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
440 mano_response = requests.delete(URLrequest)
441 logger.debug("openmano response: %s", mano_response.text )
442 result = 0 if mano_response.status_code==200 else mano_response.status_code
443 content = mano_response.json()
444 #print json.dumps(content, indent=4)
445 if mano_response.status_code == 200:
446 print content['result']
448 print content['error']['description']
451 def scenario_create(args):
452 # print "scenario-create",args
453 tenant = _get_tenant()
454 headers_req = {'content-type': 'application/yaml'}
455 myscenario = _load_file_or_yaml(args.file)
456 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
459 nsd_catalog = myscenario.get("nsd:nsd-catalog")
461 nsd_catalog = myscenario.get("nsd-catalog")
462 nsds = nsd_catalog.get("nsd:nsd")
464 nsds = nsd_catalog.get("nsd")
469 if "scenario" in myscenario:
470 nsd = myscenario["scenario"]
473 # TODO modify for API v3
475 nsd['name'] = args.name
477 nsd['description'] = args.description
478 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
479 encoding='utf-8', allow_unicode=True)
482 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
483 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
484 logger.debug("openmano request: %s", payload_req)
485 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
486 logger.debug("openmano response: %s", mano_response.text )
487 return _print_verbose(mano_response, args.verbose)
489 def scenario_list(args):
490 #print "scenario-list",args
494 tenant = _get_tenant()
496 toshow = _get_item_uuid("scenarios", args.name, tenant)
497 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
499 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
500 mano_response = requests.get(URLrequest)
501 logger.debug("openmano response: %s", mano_response.text )
502 content = mano_response.json()
503 #print json.dumps(content, indent=4)
504 if args.verbose==None:
507 result = 0 if mano_response.status_code==200 else mano_response.status_code
508 if mano_response.status_code == 200:
510 if args.verbose >= 3:
511 print yaml.safe_dump(content, indent=4, default_flow_style=False)
513 if len(content['scenarios']) == 0:
514 print "No scenarios were found."
515 return 404 #HTTP_Not_Found
516 for scenario in content['scenarios']:
517 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
518 if scenario.get('osm_id') or args.verbose >= 1:
519 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
520 if args.verbose >= 1:
521 myoutput += " {}".format(scenario['created_at'])
524 print (" Description: {}".format(scenario['description']))
527 print yaml.safe_dump(content, indent=4, default_flow_style=False)
529 scenario = content['scenario']
530 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
531 scenario['created_at']))
532 print (" Description: {}".format(scenario['description']))
534 for vnf in scenario['vnfs']:
535 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
537 if len(scenario['nets']) > 0:
539 for net in scenario['nets']:
540 description = net['description']
541 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
544 if net.get('vim_id'):
545 vim_id = " vim_id=" + net["vim_id"]
548 external = " external"
549 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
551 print (content['error']['description'])
553 print yaml.safe_dump(content, indent=4, default_flow_style=False)
556 def scenario_delete(args):
557 #print "scenario-delete",args
561 tenant = _get_tenant()
562 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
564 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
565 if not (len(r)>0 and r[0].lower()=="y"):
567 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
568 mano_response = requests.delete(URLrequest)
569 logger.debug("openmano response: %s", mano_response.text )
570 result = 0 if mano_response.status_code==200 else mano_response.status_code
571 content = mano_response.json()
572 #print json.dumps(content, indent=4)
573 if mano_response.status_code == 200:
574 print content['result']
576 print content['error']['description']
579 def scenario_deploy(args):
580 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
583 args.netmap_use = None
584 args.netmap_create = None
586 args.keypair_auto = None
587 return instance_create(args)
589 # #print "scenario-deploy",args
590 # headers_req = {'content-type': 'application/json'}
594 # actionCmd="reserve"
595 # action[actionCmd] = {}
596 # action[actionCmd]["instance_name"] = args.name
597 # if args.datacenter != None:
598 # action[actionCmd]["datacenter"] = args.datacenter
599 # elif mano_datacenter != None:
600 # action[actionCmd]["datacenter"] = mano_datacenter
602 # if args.description:
603 # action[actionCmd]["description"] = args.description
604 # payload_req = json.dumps(action, indent=4)
607 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario)
608 # logger.debug("openmano request: %s", payload_req)
609 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
610 # logger.debug("openmano response: %s", mano_response.text )
611 # if args.verbose==None:
614 # result = 0 if mano_response.status_code==200 else mano_response.status_code
615 # content = mano_response.json()
616 # #print json.dumps(content, indent=4)
617 # if args.verbose >= 3:
618 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
621 # if mano_response.status_code == 200:
622 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
623 # if args.verbose >=1:
624 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
625 # if args.verbose >=2:
626 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
629 # print "To check the status, run the following command:"
630 # print "openmano instance-scenario-list <instance_id>"
632 # print content['error']['description']
635 def scenario_verify(args):
636 #print "scenario-verify",args
637 tenant = _get_tenant()
638 headers_req = {'content-type': 'application/json'}
640 action["verify"] = {}
641 action["verify"]["instance_name"] = "scen-verify-return5"
642 payload_req = json.dumps(action, indent=4)
645 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
646 logger.debug("openmano request: %s", payload_req)
647 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
648 logger.debug("openmano response: %s", mano_response.text )
650 result = 0 if mano_response.status_code==200 else mano_response.status_code
651 content = mano_response.json()
652 #print json.dumps(content, indent=4)
653 if mano_response.status_code == 200:
654 print content['result']
656 print content['error']['description']
659 def instance_create(args):
660 tenant = _get_tenant()
661 headers_req = {'content-type': 'application/yaml'}
662 myInstance={"instance": {}, "schema_version": "0.1"}
664 instance_dict = _load_file_or_yaml(args.file)
665 if "instance" not in instance_dict:
666 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
668 myInstance = instance_dict
670 myInstance["instance"]['name'] = args.name
672 myInstance["instance"]['description'] = args.description
674 myInstance["instance"]['action'] = "reserve"
676 datacenter = myInstance["instance"].get("datacenter")
677 if args.datacenter != None:
678 datacenter = args.datacenter
679 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
681 scenario = myInstance["instance"].get("scenario")
682 if args.scenario != None:
683 scenario = args.scenario
685 print "you must provide a scenario in the file descriptor or with --scenario"
687 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
689 if "networks" not in myInstance["instance"]:
690 myInstance["instance"]["networks"] = {}
691 for net in args.netmap_use:
692 net_comma_list = net.split(",")
693 for net_comma in net_comma_list:
694 net_tuple = net_comma.split("=")
695 if len(net_tuple) != 2:
696 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
698 net_scenario = net_tuple[0].strip()
699 net_datacenter = net_tuple[1].strip()
700 if net_scenario not in myInstance["instance"]["networks"]:
701 myInstance["instance"]["networks"][net_scenario] = {}
702 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
703 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
704 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
705 if args.netmap_create:
706 if "networks" not in myInstance["instance"]:
707 myInstance["instance"]["networks"] = {}
708 for net in args.netmap_create:
709 net_comma_list = net.split(",")
710 for net_comma in net_comma_list:
711 net_tuple = net_comma.split("=")
712 if len(net_tuple) == 1:
713 net_scenario = net_tuple[0].strip()
714 net_datacenter = None
715 elif len(net_tuple) == 2:
716 net_scenario = net_tuple[0].strip()
717 net_datacenter = net_tuple[1].strip()
719 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
721 if net_scenario not in myInstance["instance"]["networks"]:
722 myInstance["instance"]["networks"][net_scenario] = {}
723 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
724 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
725 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
727 if "cloud-config" not in myInstance["instance"]:
728 myInstance["instance"]["cloud-config"] = {}
729 cloud_config = myInstance["instance"]["cloud-config"]
730 for key in args.keypair:
731 index = key.find(":")
733 if "key-pairs" not in cloud_config:
734 cloud_config["key-pairs"] = []
735 cloud_config["key-pairs"].append(key)
739 key_list = key_.split(",")
740 if "users" not in cloud_config:
741 cloud_config["users"] = []
742 cloud_config["users"].append({"name": user, "key-pairs": key_list })
743 if args.keypair_auto:
746 home = os.getenv("HOME")
747 user = os.getenv("USER")
748 files = os.listdir(home+'/.ssh')
750 if file[-4:] == ".pub":
751 with open(home+'/.ssh/'+file, 'r') as f:
752 keys.append(f.read())
754 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
756 except Exception as e:
757 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
760 if "cloud-config" not in myInstance["instance"]:
761 myInstance["instance"]["cloud-config"] = {}
762 cloud_config = myInstance["instance"]["cloud-config"]
763 if "key-pairs" not in cloud_config:
764 cloud_config["key-pairs"] = []
766 if "users" not in cloud_config:
767 cloud_config["users"] = []
768 cloud_config["users"].append({"name": user, "key-pairs": keys })
770 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
771 logger.debug("openmano request: %s", payload_req)
772 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
773 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
774 logger.debug("openmano response: %s", mano_response.text )
775 if args.verbose==None:
778 result = 0 if mano_response.status_code==200 else mano_response.status_code
779 content = mano_response.json()
780 #print json.dumps(content, indent=4)
781 if args.verbose >= 3:
782 print yaml.safe_dump(content, indent=4, default_flow_style=False)
785 if mano_response.status_code == 200:
786 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
788 myoutput = "{} {:20}".format(myoutput, content['created_at'])
790 myoutput = "{} {:30}".format(myoutput, content['description'])
793 print content['error']['description']
796 def instance_scenario_list(args):
797 #print "instance-scenario-list",args
801 tenant = _get_tenant()
803 toshow = _get_item_uuid("instances", args.name, tenant)
804 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
806 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
807 mano_response = requests.get(URLrequest)
808 logger.debug("openmano response: %s", mano_response.text )
809 content = mano_response.json()
810 #print json.dumps(content, indent=4)
811 if args.verbose==None:
814 result = 0 if mano_response.status_code==200 else mano_response.status_code
815 if mano_response.status_code == 200:
817 if args.verbose >= 3:
818 print yaml.safe_dump(content, indent=4, default_flow_style=False)
820 if len(content['instances']) == 0:
821 print "No scenario instances were found."
823 for instance in content['instances']:
824 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
826 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
829 print "Description: %s" %instance['description']
832 print yaml.safe_dump(content, indent=4, default_flow_style=False)
835 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
836 print ("Description: %s" %instance['description'])
837 print ("Template scenario id: {}".format(instance['scenario_id']))
838 print ("Template scenario name: {}".format(instance['scenario_name']))
839 print ("---------------------------------------")
840 print ("VNF instances: {}".format(len(instance['vnfs'])))
841 for vnf in instance['vnfs']:
842 #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))
843 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
844 if len(instance['nets'])>0:
845 print "---------------------------------------"
846 print "Internal nets:"
847 for net in instance['nets']:
849 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
850 print "---------------------------------------"
851 print "External nets:"
852 for net in instance['nets']:
853 if not net['created']:
854 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
855 print ("---------------------------------------")
856 print ("VM instances:")
857 for vnf in instance['vnfs']:
858 for vm in vnf['vms']:
859 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
860 vm['status'], vm['vim_vm_id']))
862 print content['error']['description']
864 print yaml.safe_dump(content, indent=4, default_flow_style=False)
867 def instance_scenario_status(args):
868 print "instance-scenario-status"
871 def instance_scenario_delete(args):
875 tenant = _get_tenant()
876 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
877 #print "instance-scenario-delete",args
879 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
880 if not (len(r)>0 and r[0].lower()=="y"):
882 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
883 mano_response = requests.delete(URLrequest)
884 logger.debug("openmano response: %s", mano_response.text )
885 result = 0 if mano_response.status_code==200 else mano_response.status_code
886 content = mano_response.json()
887 #print json.dumps(content, indent=4)
888 if mano_response.status_code == 200:
889 print content['result']
891 print content['error']['description']
894 def get_action(args):
896 tenant = _get_tenant()
899 if not args.instance:
902 instance_id =args.instance
905 action_id = "/" + args.id
906 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
908 mano_response = requests.get(URLrequest)
909 logger.debug("openmano response: %s", mano_response.text )
910 if args.verbose == None:
914 return _print_verbose(mano_response, args.verbose)
916 def instance_scenario_action(args):
917 #print "instance-scenario-action", args
918 tenant = _get_tenant()
919 toact = _get_item_uuid("instances", args.name, tenant=tenant)
921 action[ args.action ] = args.param
923 action["vnfs"] = args.vnf
925 action["vms"] = args.vm
927 headers_req = {'content-type': 'application/json'}
928 payload_req = json.dumps(action, indent=4)
929 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
930 logger.debug("openmano request: %s", payload_req)
931 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
932 logger.debug("openmano response: %s", mano_response.text )
933 result = 0 if mano_response.status_code==200 else mano_response.status_code
934 content = mano_response.json()
935 #print json.dumps(content, indent=4)
936 if mano_response.status_code == 200:
938 print yaml.safe_dump(content, indent=4, default_flow_style=False)
940 for uuid,c in content.iteritems():
941 print ("{:38} {:20} {:20}".format(uuid, c['name'], c['description']))
943 print content['error']['description']
947 def instance_vnf_list(args):
948 print "instance-vnf-list"
951 def instance_vnf_status(args):
952 print "instance-vnf-status"
955 def tenant_create(args):
956 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
957 tenant_dict={"name": args.name}
958 if args.description!=None:
959 tenant_dict["description"] = args.description
960 payload_req = json.dumps( {"tenant": tenant_dict })
964 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
965 logger.debug("openmano request: %s", payload_req)
966 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
967 logger.debug("openmano response: %s", mano_response.text )
968 return _print_verbose(mano_response, args.verbose)
970 def tenant_list(args):
971 #print "tenant-list",args
973 toshow = _get_item_uuid("tenants", args.name)
974 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
976 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
977 mano_response = requests.get(URLrequest)
978 logger.debug("openmano response: %s", mano_response.text )
979 if args.verbose==None:
983 return _print_verbose(mano_response, args.verbose)
985 def tenant_delete(args):
986 #print "tenant-delete",args
987 todelete = _get_item_uuid("tenants", args.name)
989 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
990 if not (len(r)>0 and r[0].lower()=="y"):
992 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
993 mano_response = requests.delete(URLrequest)
994 logger.debug("openmano response: %s", mano_response.text )
995 result = 0 if mano_response.status_code==200 else mano_response.status_code
996 content = mano_response.json()
997 #print json.dumps(content, indent=4)
998 if mano_response.status_code == 200:
999 print content['result']
1001 print content['error']['description']
1004 def datacenter_attach(args):
1005 tenant = _get_tenant()
1006 datacenter = _get_datacenter(args.name)
1007 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1010 if args.vim_tenant_id != None:
1011 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1012 if args.vim_tenant_name != None:
1013 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1014 if args.user != None:
1015 datacenter_dict['vim_username'] = args.user
1016 if args.password != None:
1017 datacenter_dict['vim_password'] = args.password
1018 if args.config!=None:
1019 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1021 payload_req = json.dumps( {"datacenter": datacenter_dict })
1025 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1026 logger.debug("openmano request: %s", payload_req)
1027 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1028 logger.debug("openmano response: %s", mano_response.text )
1029 result = _print_verbose(mano_response, args.verbose)
1030 #provide addional information if error
1031 if mano_response.status_code != 200:
1032 content = mano_response.json()
1033 if "already in use for 'name'" in content['error']['description'] and \
1034 "to database vim_tenants table" in content['error']['description']:
1035 print "Try to specify a different name with --vim-tenant-name"
1039 def datacenter_edit_vim_tenant(args):
1040 tenant = _get_tenant()
1041 datacenter = _get_datacenter(args.name)
1042 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1044 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1045 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1047 datacenter_dict = {}
1048 if args.vim_tenant_id != None:
1049 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1050 if args.vim_tenant_name != None:
1051 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1052 if args.user != None:
1053 datacenter_dict['vim_username'] = args.user
1054 if args.password != None:
1055 datacenter_dict['vim_password'] = args.password
1056 if args.config != None:
1057 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1058 payload_req = json.dumps({"datacenter": datacenter_dict})
1062 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1063 logger.debug("openmano request: %s", payload_req)
1064 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1065 logger.debug("openmano response: %s", mano_response.text)
1066 result = _print_verbose(mano_response, args.verbose)
1070 def datacenter_detach(args):
1074 tenant = _get_tenant()
1075 datacenter = _get_datacenter(args.name, tenant)
1076 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1077 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1078 mano_response = requests.delete(URLrequest, headers=headers_req)
1079 logger.debug("openmano response: %s", mano_response.text )
1080 content = mano_response.json()
1081 #print json.dumps(content, indent=4)
1082 result = 0 if mano_response.status_code==200 else mano_response.status_code
1083 if mano_response.status_code == 200:
1084 print content['result']
1086 print content['error']['description']
1089 def datacenter_create(args):
1090 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1091 datacenter_dict={"name": args.name, "vim_url": args.url}
1092 if args.description!=None:
1093 datacenter_dict["description"] = args.description
1095 datacenter_dict["type"] = args.type
1097 datacenter_dict["vim_url_admin"] = args.url_admin
1098 if args.config!=None:
1099 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1100 if args.sdn_controller!=None:
1101 tenant = _get_tenant()
1102 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1103 if not 'config' in datacenter_dict:
1104 datacenter_dict['config'] = {}
1105 datacenter_dict['config']['sdn-controller'] = sdn_controller
1106 payload_req = json.dumps( {"datacenter": datacenter_dict })
1110 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1111 logger.debug("openmano request: %s", payload_req)
1112 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1113 logger.debug("openmano response: %s", mano_response.text )
1114 return _print_verbose(mano_response, args.verbose)
1116 def datacenter_delete(args):
1117 #print "datacenter-delete",args
1118 todelete = _get_item_uuid("datacenters", args.name, "any")
1120 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1121 if not (len(r)>0 and r[0].lower()=="y"):
1123 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1124 mano_response = requests.delete(URLrequest)
1125 logger.debug("openmano response: %s", mano_response.text )
1126 result = 0 if mano_response.status_code==200 else mano_response.status_code
1127 content = mano_response.json()
1128 #print json.dumps(content, indent=4)
1129 if mano_response.status_code == 200:
1130 print content['result']
1132 print content['error']['description']
1136 def datacenter_list(args):
1137 #print "datacenter-list",args
1138 tenant='any' if args.all else _get_tenant()
1141 toshow = _get_item_uuid("datacenters", args.name, tenant)
1142 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1144 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1145 mano_response = requests.get(URLrequest)
1146 logger.debug("openmano response: %s", mano_response.text )
1147 if args.verbose==None:
1151 return _print_verbose(mano_response, args.verbose)
1154 def datacenter_sdn_port_mapping_set(args):
1155 tenant = _get_tenant()
1156 datacenter = _get_datacenter(args.name, tenant)
1157 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1160 raise OpenmanoCLIError(
1161 "No yaml/json has been provided specifying the SDN port mapping")
1162 sdn_port_mapping = _load_file_or_yaml(args.file)
1163 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1166 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1167 mano_response = requests.get(URLrequest)
1168 logger.debug("openmano response: %s", mano_response.text)
1169 port_mapping = mano_response.json()
1170 if mano_response.status_code != 200:
1171 str(mano_response.json())
1172 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1173 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1175 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1176 if not (len(r) > 0 and r[0].lower() == "y"):
1180 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1181 mano_response = requests.delete(URLrequest)
1182 logger.debug("openmano response: %s", mano_response.text)
1183 if mano_response.status_code != 200:
1184 return _print_verbose(mano_response, args.verbose)
1187 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1188 logger.debug("openmano request: %s", payload_req)
1189 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1190 logger.debug("openmano response: %s", mano_response.text)
1191 return _print_verbose(mano_response, args.verbose)
1194 def datacenter_sdn_port_mapping_list(args):
1195 tenant = _get_tenant()
1196 datacenter = _get_datacenter(args.name, tenant)
1198 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1199 mano_response = requests.get(URLrequest)
1200 logger.debug("openmano response: %s", mano_response.text)
1202 return _print_verbose(mano_response, 4)
1205 def datacenter_sdn_port_mapping_clear(args):
1206 tenant = _get_tenant()
1207 datacenter = _get_datacenter(args.name, tenant)
1210 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1211 if not (len(r) > 0 and r[0].lower() == "y"):
1214 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1215 mano_response = requests.delete(URLrequest)
1216 logger.debug("openmano response: %s", mano_response.text)
1218 return _print_verbose(mano_response, args.verbose)
1221 def sdn_controller_create(args):
1222 tenant = _get_tenant()
1223 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1226 if not args.ip: error_msg.append("'ip'")
1227 if not args.port: error_msg.append("'port'")
1228 if not args.dpid: error_msg.append("'dpid'")
1229 if not args.type: error_msg.append("'type'")
1231 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
1233 controller_dict = {}
1234 controller_dict['name'] = args.name
1235 controller_dict['ip'] = args.ip
1236 controller_dict['port'] = int(args.port)
1237 controller_dict['dpid'] = args.dpid
1238 controller_dict['type'] = args.type
1239 if args.description != None:
1240 controller_dict['description'] = args.description
1241 if args.user != None:
1242 controller_dict['user'] = args.user
1243 if args.password != None:
1244 controller_dict['password'] = args.password
1246 payload_req = json.dumps({"sdn_controller": controller_dict})
1250 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1251 logger.debug("openmano request: %s", payload_req)
1252 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1253 logger.debug("openmano response: %s", mano_response.text)
1254 result = _print_verbose(mano_response, args.verbose)
1258 def sdn_controller_edit(args):
1259 tenant = _get_tenant()
1260 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1261 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1263 controller_dict = {}
1265 controller_dict['name'] = args.new_name
1267 controller_dict['ip'] = args.ip
1269 controller_dict['port'] = int(args.port)
1271 controller_dict['dpid'] = args.dpid
1273 controller_dict['type'] = args.type
1274 if args.description:
1275 controller_dict['description'] = args.description
1277 controller_dict['user'] = args.user
1279 controller_dict['password'] = args.password
1281 if not controller_dict:
1282 raise OpenmanoCLIError("At least one parameter must be edited")
1285 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1286 if not (len(r) > 0 and r[0].lower() == "y"):
1289 payload_req = json.dumps({"sdn_controller": controller_dict})
1292 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1293 logger.debug("openmano request: %s", payload_req)
1294 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1295 logger.debug("openmano response: %s", mano_response.text)
1296 result = _print_verbose(mano_response, args.verbose)
1300 def sdn_controller_list(args):
1301 tenant = _get_tenant()
1302 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1305 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1306 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1308 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1310 mano_response = requests.get(URLrequest)
1311 logger.debug("openmano response: %s", mano_response.text )
1312 if args.verbose==None:
1317 # json.dumps(mano_response.json(), indent=4)
1318 return _print_verbose(mano_response, args.verbose)
1321 def sdn_controller_delete(args):
1322 tenant = _get_tenant()
1323 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1326 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1327 if not (len(r) > 0 and r[0].lower() == "y"):
1330 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1331 mano_response = requests.delete(URLrequest)
1332 logger.debug("openmano response: %s", mano_response.text)
1333 return _print_verbose(mano_response, args.verbose)
1335 def vim_action(args):
1336 #print "datacenter-net-action",args
1337 tenant = _get_tenant()
1338 datacenter = _get_datacenter(args.datacenter, tenant)
1339 if args.verbose==None:
1341 if args.action=="list":
1342 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1345 URLrequest += "/" + args.name
1346 mano_response = requests.get(URLrequest)
1347 logger.debug("openmano response: %s", mano_response.text )
1348 return _print_verbose(mano_response, args.verbose)
1349 elif args.action=="delete":
1350 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1351 mano_response = requests.delete(URLrequest)
1352 logger.debug("openmano response: %s", mano_response.text )
1353 result = 0 if mano_response.status_code==200 else mano_response.status_code
1354 content = mano_response.json()
1355 #print json.dumps(content, indent=4)
1356 if mano_response.status_code == 200:
1357 print content['result']
1359 print content['error']['description']
1361 elif args.action=="create":
1362 headers_req = {'content-type': 'application/yaml'}
1364 create_dict = _load_file_or_yaml(args.file)
1365 if args.item not in create_dict:
1366 create_dict = {args.item: create_dict}
1368 create_dict = {args.item:{}}
1370 create_dict[args.item]['name'] = args.name
1371 #if args.description:
1372 # create_dict[args.item]['description'] = args.description
1373 if args.item=="network":
1375 create_dict[args.item]['bind_net'] = args.bind_net
1377 create_dict[args.item]['type'] = args.type
1379 create_dict[args.item]['shared'] = args.shared
1380 if "name" not in create_dict[args.item]:
1381 print "You must provide a name in the descriptor file or with the --name option"
1383 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1384 logger.debug("openmano request: %s", payload_req)
1385 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1386 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1387 logger.debug("openmano response: %s", mano_response.text )
1388 if args.verbose==None:
1390 return _print_verbose(mano_response, args.verbose)
1393 def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1394 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1396 URLrequest += "/" + tenant
1398 URLrequest += "/vim/" + datacenter
1400 URLrequest += "/" + item +"s"
1402 URLrequest += "/" + item_name_id
1403 mano_response = requests.get(URLrequest)
1404 logger.debug("openmano response: %s", mano_response.text )
1406 return mano_response
1409 def vim_net_sdn_attach(args):
1410 #Verify the network exists in the vim
1411 tenant = _get_tenant()
1412 datacenter = _get_datacenter(args.datacenter, tenant)
1413 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1414 content = yaml.load(result.content)
1415 if 'networks' in content:
1416 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1417 if 'error' in content:
1418 raise OpenmanoCLIError(yaml.safe_dump(content))
1419 network_uuid = content['network']['id']
1421 #Make call to attach the dataplane port to the SND network associated to the vim network
1422 headers_req = {'content-type': 'application/yaml'}
1423 payload_req = {'port': args.port}
1425 payload_req['vlan'] = int(args.vlan)
1427 payload_req['mac'] = args.mac
1429 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1430 logger.debug("openmano request: %s", payload_req)
1431 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1432 logger.debug("openmano response: %s", mano_response.text)
1433 result = _print_verbose(mano_response, args.verbose)
1437 def vim_net_sdn_detach(args):
1438 if not args.all and not args.id:
1439 print "--all or --id must be used"
1442 # Verify the network exists in the vim
1443 tenant = _get_tenant()
1444 datacenter = _get_datacenter(args.datacenter, tenant)
1445 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1446 content = yaml.load(result.content)
1447 if 'networks' in content:
1448 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1449 if 'error' in content:
1450 raise OpenmanoCLIError(yaml.safe_dump(content))
1451 network_uuid = content['network']['id']
1454 r = raw_input("Confirm action' (y/N)? ")
1455 if len(r) == 0 or r[0].lower() != "y":
1459 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1460 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1462 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1463 mano_host, mano_port, tenant, datacenter, network_uuid)
1464 mano_response = requests.delete(URLrequest)
1465 logger.debug("openmano response: %s", mano_response.text)
1466 result = _print_verbose(mano_response, args.verbose)
1470 def datacenter_net_action(args):
1471 if args.action == "net-update":
1472 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1474 args.action = "netmap-delete"
1477 r = datacenter_netmap_action(args)
1480 args.action = "netmap-import"
1481 r = datacenter_netmap_action(args)
1484 if args.action == "net-edit":
1485 args.netmap = args.net
1487 elif args.action == "net-list":
1489 elif args.action == "net-delete":
1490 args.netmap = args.net
1493 args.action = "netmap" + args.action[3:]
1496 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1498 return datacenter_netmap_action(args)
1500 def datacenter_netmap_action(args):
1501 tenant = _get_tenant()
1502 datacenter = _get_datacenter(args.datacenter, tenant)
1503 #print "datacenter_netmap_action",args
1505 if args.verbose==None:
1507 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1508 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1510 if args.action=="netmap-list":
1512 URLrequest += "/" + args.netmap
1514 mano_response = requests.get(URLrequest)
1516 elif args.action=="netmap-delete":
1517 if args.netmap and args.all:
1518 print "you can not use a netmap name and the option --all at the same time"
1521 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1522 URLrequest += "/" + args.netmap
1524 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1526 print "you must specify a netmap name or the option --all"
1529 r = raw_input(force_text)
1530 if len(r)>0 and r[0].lower()=="y":
1534 mano_response = requests.delete(URLrequest, headers=headers_req)
1535 elif args.action=="netmap-import":
1537 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1538 if len(r)>0 and r[0].lower()=="y":
1542 URLrequest += "/upload"
1543 mano_response = requests.post(URLrequest, headers=headers_req)
1544 elif args.action=="netmap-edit" or args.action=="netmap-create":
1546 payload = _load_file_or_yaml(args.file)
1549 if "netmap" not in payload:
1550 payload = {"netmap": payload}
1552 payload["netmap"]["name"] = args.name
1554 payload["netmap"]["vim_id"] = args.vim_id
1555 if args.action=="netmap-create" and args.vim_name:
1556 payload["netmap"]["vim_name"] = args.vim_name
1557 payload_req = json.dumps(payload)
1558 logger.debug("openmano request: %s", payload_req)
1560 if args.action=="netmap-edit" and not args.force:
1561 if len(payload["netmap"]) == 0:
1562 print "You must supply some parameter to edit"
1564 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1565 if len(r)>0 and r[0].lower()=="y":
1569 URLrequest += "/" + args.netmap
1570 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1571 else: #netmap-create
1572 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1573 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1575 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1577 logger.debug("openmano response: %s", mano_response.text )
1578 return _print_verbose(mano_response, args.verbose)
1581 def element_edit(args):
1582 element = _get_item_uuid(args.element, args.name)
1583 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1584 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1585 payload=_load_file_or_yaml(args.file)
1586 if args.element[:-1] not in payload:
1587 payload = {args.element[:-1]: payload }
1588 payload_req = json.dumps(payload)
1591 if not args.force or (args.name==None and args.filer==None):
1592 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1593 if len(r)>0 and r[0].lower()=="y":
1597 logger.debug("openmano request: %s", payload_req)
1598 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1599 logger.debug("openmano response: %s", mano_response.text )
1600 if args.verbose==None:
1604 return _print_verbose(mano_response, args.verbose)
1607 def datacenter_edit(args):
1608 tenant = _get_tenant()
1609 element = _get_item_uuid('datacenters', args.name, tenant)
1610 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1611 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1613 has_arguments = False
1614 if args.file != None:
1615 has_arguments = True
1616 payload = _load_file_or_yaml(args.file)
1620 if args.sdn_controller != None:
1621 has_arguments = True
1622 if not 'config' in payload:
1623 payload['config'] = {}
1624 if not 'sdn-controller' in payload['config']:
1625 payload['config']['sdn-controller'] = {}
1626 if args.sdn_controller == 'null':
1627 payload['config']['sdn-controller'] = None
1629 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1631 if not has_arguments:
1632 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1634 if 'datacenter' not in payload:
1635 payload = {'datacenter': payload}
1636 payload_req = json.dumps(payload)
1639 if not args.force or (args.name == None and args.filer == None):
1640 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1641 if len(r) > 0 and r[0].lower() == "y":
1645 logger.debug("openmano request: %s", payload_req)
1646 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1647 logger.debug("openmano response: %s", mano_response.text)
1648 if args.verbose == None:
1650 if args.name != None:
1652 return _print_verbose(mano_response, args.verbose)
1656 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1657 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1659 mano_response = requests.get(URLrequest, headers=headers_req)
1660 logger.debug("openmano response: %s", mano_response.text)
1661 print mano_response.text
1668 if __name__=="__main__":
1670 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1671 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1672 mano_port = os.getenv('OPENMANO_PORT',"9090")
1673 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1675 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1676 main_parser.add_argument('--version', action='version', help="get version of this client",
1677 version='%(prog)s client version ' + __version__ +
1678 " (Note: use '%(prog)s version' to get server version)")
1680 subparsers = main_parser.add_subparsers(help='commands')
1682 parent_parser = argparse.ArgumentParser(add_help=False)
1683 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1684 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1686 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1687 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1688 config_parser.set_defaults(func=config)
1690 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1691 version_parser.set_defaults(func=version)
1693 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1694 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1695 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1696 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1697 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1698 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1699 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1700 vnf_create_parser.set_defaults(func=vnf_create)
1702 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
1703 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
1704 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
1705 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
1706 vnf_list_parser.set_defaults(func=vnf_list)
1708 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
1709 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
1710 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1711 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1712 vnf_delete_parser.set_defaults(func=vnf_delete)
1714 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
1715 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
1716 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
1717 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
1718 scenario_create_parser.set_defaults(func=scenario_create)
1720 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
1721 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
1722 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
1723 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
1724 scenario_list_parser.set_defaults(func=scenario_list)
1726 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
1727 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
1728 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1729 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1730 scenario_delete_parser.set_defaults(func=scenario_delete)
1732 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
1733 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
1734 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
1735 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1736 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1737 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
1738 scenario_deploy_parser.set_defaults(func=scenario_deploy)
1740 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
1741 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
1742 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1743 scenario_deploy_parser.set_defaults(func=scenario_verify)
1745 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
1746 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
1747 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
1748 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
1749 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
1750 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
1751 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")
1752 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")
1753 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")
1754 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")
1755 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
1756 instance_scenario_create_parser.set_defaults(func=instance_create)
1758 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
1759 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
1760 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
1761 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
1763 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)")
1764 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
1765 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1766 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
1767 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
1769 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
1770 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1771 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
1772 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key"],\
1773 help="action to send")
1774 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console type (novnc, ...), reboot type (TODO)")
1775 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
1776 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
1777 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
1779 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
1780 action_parser.add_argument("id", nargs='?', action="store", help="action id")
1781 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
1782 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
1783 action_parser.set_defaults(func=get_action)
1785 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
1786 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
1787 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
1789 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
1790 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
1791 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
1792 tenant_create_parser.set_defaults(func=tenant_create)
1794 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
1795 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
1796 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1797 tenant_delete_parser.set_defaults(func=tenant_delete)
1799 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
1800 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
1801 tenant_list_parser.set_defaults(func=tenant_list)
1803 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
1804 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
1805 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1806 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1807 element_edit_parser.set_defaults(func=element_edit, element='tenants')
1809 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
1810 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
1811 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
1812 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
1813 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
1814 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1815 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
1816 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
1817 datacenter_create_parser.set_defaults(func=datacenter_create)
1819 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
1820 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
1821 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1822 datacenter_delete_parser.set_defaults(func=datacenter_delete)
1824 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
1825 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
1826 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
1827 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
1828 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
1829 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1830 datacenter_edit_parser.set_defaults(func=datacenter_edit)
1832 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
1833 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
1834 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
1835 datacenter_list_parser.set_defaults(func=datacenter_list)
1837 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
1838 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
1839 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
1840 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1841 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1842 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1843 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
1844 datacenter_attach_parser.set_defaults(func=datacenter_attach)
1846 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
1847 help="Edit the association of a datacenter to the operating tenant")
1848 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
1849 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
1850 help="specify a datacenter tenant to use. A new one is created by default")
1851 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
1852 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
1853 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
1854 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
1855 help="aditional configuration in json/yaml format")
1856 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
1858 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
1859 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
1860 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
1861 datacenter_detach_parser.set_defaults(func=datacenter_detach)
1863 #=======================datacenter_sdn_port_mapping_xxx section=======================
1864 #datacenter_sdn_port_mapping_set
1865 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
1866 parents=[parent_parser],
1867 help="Load a file with the mapping of physical ports "
1868 "and the ports of the dataplaneswitch controlled "
1870 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
1871 datacenter_sdn_port_mapping_set_parser.add_argument("file",
1872 help="json/yaml text or file with the port mapping").completer = FilesCompleter
1873 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
1874 help="forces overwriting without asking")
1875 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
1877 #datacenter_sdn_port_mapping_list
1878 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
1879 parents=[parent_parser],
1880 help="Show the SDN port mapping in a datacenter")
1881 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
1882 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
1884 # datacenter_sdn_port_mapping_clear
1885 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
1886 parents=[parent_parser],
1887 help="Clean the the SDN port mapping in a datacenter")
1888 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
1889 help="specifies the datacenter")
1890 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
1891 help="forces clearing without asking")
1892 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
1893 # =======================
1895 # =======================sdn_controller_xxx section=======================
1896 # sdn_controller_create
1897 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
1898 help="Creates an SDN controller entity within RO")
1899 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
1900 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
1901 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1902 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1903 sdn_controller_create_parser.add_argument("--dpid", action="store",
1904 help="DPID of the dataplane switch controlled by this SDN controller")
1905 sdn_controller_create_parser.add_argument("--type", action="store",
1906 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1907 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1908 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
1909 help="password credentials for the SDN controller")
1910 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
1912 # sdn_controller_edit
1913 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
1914 help="Update one or more options of a SDN controller")
1915 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
1916 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
1918 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
1919 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
1920 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
1921 sdn_controller_edit_parser.add_argument("--dpid", action="store",
1922 help="DPID of the dataplane switch controlled by this SDN controller")
1923 sdn_controller_edit_parser.add_argument("--type", action="store",
1924 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
1925 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
1926 sdn_controller_edit_parser.add_argument("--password", action="store",
1927 help="password credentials for the SDN controller", dest='password')
1928 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
1929 #TODO: include option --file
1930 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
1932 #sdn_controller_list
1933 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
1934 parents=[parent_parser],
1935 help="List the SDN controllers")
1936 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
1937 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
1939 # sdn_controller_delete
1940 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
1941 parents=[parent_parser],
1942 help="Delete the the SDN controller")
1943 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
1944 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
1945 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
1946 # =======================
1948 action_dict={'net-update': 'retrieves external networks from datacenter',
1949 'net-edit': 'edits an external network',
1950 'net-delete': 'deletes an external network',
1951 'net-list': 'lists external networks from a datacenter'
1953 for item in action_dict:
1954 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1955 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
1956 if item=='net-edit' or item=='net-delete':
1957 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
1958 if item=='net-edit':
1959 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
1960 if item!='net-list':
1961 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1962 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
1965 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
1966 'netmap-create': 'create a new network senario netmap',
1967 'netmap-edit': 'edit name of a network senario netmap',
1968 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
1969 'netmap-list': 'list/show network scenario netmaps'
1971 for item in action_dict:
1972 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
1973 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
1974 #if item=='net-add':
1975 # datacenter_action_parser.add_argument("net", help="name of the network")
1976 if item=='netmap-delete':
1977 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
1978 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
1979 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1980 if item=='netmap-edit':
1981 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
1982 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
1983 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
1984 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1985 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1986 if item=='netmap-list':
1987 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
1988 if item=='netmap-create':
1989 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
1990 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
1991 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
1992 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
1993 if item=='netmap-import':
1994 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
1995 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
1997 # =======================vim_net_sdn_xxx section=======================
1998 # vim_net_sdn_attach
1999 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2000 parents=[parent_parser],
2001 help="Specify the port to access to an external network using SDN")
2002 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2003 help="Name/id of the network in the vim that will be used to connect to the external network")
2004 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2005 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2006 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")
2007 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2008 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2010 # vim_net_sdn_detach
2011 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2012 parents=[parent_parser],
2013 help="Remove the port information to access to an external network using SDN")
2015 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2016 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2017 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2018 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2019 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2020 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2021 # =======================
2023 for item in ("network", "tenant", "image"):
2025 command_name = 'vim-net'
2027 command_name = 'vim-'+item
2028 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
2029 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2030 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2031 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2033 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
2034 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2035 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2036 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2038 if item == "network" or item == "tenant":
2039 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
2040 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2041 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2042 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2044 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2045 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2046 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>'")
2048 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2049 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
2051 argcomplete.autocomplete(main_parser)
2054 args = main_parser.parse_args()
2056 level = logging.CRITICAL
2057 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2058 if "debug" in args and args.debug:
2059 level = logging.DEBUG
2060 logging.basicConfig(format=streamformat, level= level)
2061 logger = logging.getLogger('mano')
2062 logger.setLevel(level)
2063 result = args.func(args)
2066 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2067 except (requests.exceptions.ConnectionError):
2068 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2070 except (KeyboardInterrupt):
2071 print 'Exiting openmano'
2073 except (SystemExit, ArgumentParserError):
2075 except OpenmanoCLIError as e: