2 # -*- coding: utf-8 -*-
3 # PYTHON_ARGCOMPLETE_OK
6 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
7 # This file is part of openmano
10 # Licensed under the Apache License, Version 2.0 (the "License"); you may
11 # not use this file except in compliance with the License. You may obtain
12 # a copy of the License at
14 # http://www.apache.org/licenses/LICENSE-2.0
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19 # License for the specific language governing permissions and limitations
22 # For those usages not covered by the Apache License, Version 2.0 please
23 # contact with: nfvlabs@tid.es
27 openmano client used to interact with openmano-server (openmanod)
29 __author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
30 __date__ = "$09-oct-2014 09:09:48$"
31 __version__ = "0.4.23-r533"
32 version_date = "May 2018"
34 from argcomplete.completers import FilesCompleter
42 #from jsonschema import validate as js_v, exceptions as js_e
44 class ArgumentParserError(Exception): pass
46 class OpenmanoCLIError(Exception): pass
48 class ThrowingArgumentParser(argparse.ArgumentParser):
49 def error(self, message):
50 print "Error: %s" %message
55 print "Type 'openmano -h' for help"
56 raise ArgumentParserError
60 print "OPENMANO_HOST: %s" %mano_host
61 print "OPENMANO_PORT: %s" %mano_port
63 logger.debug("resolving tenant and datacenter names")
64 mano_tenant_id = "None"
65 mano_tenant_name = "None"
66 mano_datacenter_id = "None"
67 mano_datacenter_name = "None"
69 logger.debug("resolving WIM names")
71 mano_wim_name = "None"
73 mano_tenant_id = _get_item_uuid("tenants", mano_tenant)
74 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id)
75 mano_response = requests.get(URLrequest)
76 logger.debug("openmano response: %s", mano_response.text )
77 content = mano_response.json()
78 mano_tenant_name = content["tenant"]["name"]
79 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter)
80 mano_response = requests.get(URLrequest)
81 logger.debug("openmano response: %s", mano_response.text )
82 content = mano_response.json()
83 if "error" not in content:
84 mano_datacenter_id = content["datacenter"]["uuid"]
85 mano_datacenter_name = content["datacenter"]["name"]
88 URLrequest = "http://%s:%s/openmano/%s/wims/%s" % (
89 mano_host, mano_port, mano_tenant_id, mano_wim)
90 mano_response = requests.get(URLrequest)
91 logger.debug("openmano response: %s", mano_response.text)
92 content = mano_response.json()
93 if "error" not in content:
94 mano_wim_id = content["wim"]["uuid"]
95 mano_wim_name = content["wim"]["name"]
97 except OpenmanoCLIError:
99 print "OPENMANO_TENANT: %s" %mano_tenant
100 print " Id: %s" %mano_tenant_id
101 print " Name: %s" %mano_tenant_name
102 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
103 print " Id: %s" %mano_datacenter_id
104 print " Name: %s" %mano_datacenter_name
106 print "OPENMANO_WIM: %s" %str (mano_wim)
107 print " Id: %s" %mano_wim_id
108 print " Name: %s" %mano_wim_name
111 print "OPENMANO_TENANT: %s" %mano_tenant
112 print "OPENMANO_DATACENTER: %s" %str (mano_datacenter)
114 print "OPENMANO_WIM: %s" %str (mano_wim)
116 def _print_verbose(mano_response, verbose_level=0):
117 content = mano_response.json()
118 result = 0 if mano_response.status_code==200 else mano_response.status_code
119 if type(content)!=dict or len(content)!=1:
120 #print "Non expected format output"
124 val=content.values()[0]
128 elif type(val) == list:
130 elif type(val)==dict:
133 #print "Non expected dict/list format output"
138 if verbose_level==None:
140 if verbose_level >= 3:
141 print yaml.safe_dump(content, indent=4, default_flow_style=False)
144 if mano_response.status_code == 200:
146 for content in content_list:
147 if "uuid" in content:
148 uuid = content['uuid']
149 elif "id" in content:
151 elif "vim_id" in content:
152 uuid = content['vim_id']
153 name = content.get('name');
158 myoutput = "{:38} {:20}".format(uuid, name)
159 if content.get("status"):
160 myoutput += " {:20}".format(content['status'])
161 elif "enabled" in content and not content["enabled"]:
162 myoutput += " enabled=False".ljust(20)
163 if verbose_level >=1:
164 if content.get('created_at'):
165 myoutput += " {:20}".format(content['created_at'])
166 if content.get('sdn_attached_ports'):
167 #myoutput += " " + str(content['sdn_attached_ports']).ljust(20)
168 myoutput += "\nsdn_attached_ports:\n" + yaml.safe_dump(content['sdn_attached_ports'], indent=4, default_flow_style=False)
169 if verbose_level >=2:
171 if content.get('type'):
172 myoutput += new_line + " Type: {:29}".format(content['type'])
174 if content.get('description'):
175 myoutput += new_line + " Description: {:20}".format(content['description'])
178 print content['error']['description']
181 def parser_json_yaml(file_name):
183 f = file(file_name, "r")
186 except Exception as e:
187 return (False, str(e))
190 if file_name[-5:]=='.yaml' or file_name[-4:]=='.yml' or (file_name[-5:]!='.json' and '\t' not in text):
192 config = yaml.load(text)
193 except yaml.YAMLError as exc:
195 if hasattr(exc, 'problem_mark'):
196 mark = exc.problem_mark
197 error_pos = " at line:%s column:%s" % (mark.line+1, mark.column+1)
198 return (False, "Error loading file '"+file_name+"' yaml format error" + error_pos)
201 config = json.loads(text)
202 except Exception as e:
203 return (False, "Error loading file '"+file_name+"' json format error " + str(e) )
207 def _load_file_or_yaml(content):
209 'content' can be or a yaml/json file or a text containing a yaml/json text format
210 This function autodetect, trying to load and parse the file,
211 if fails trying to parse the 'content' text
212 Returns the dictionary once parsed, or print an error and finish the program
214 #Check config file exists
215 if os.path.isfile(content):
216 r,payload = parser_json_yaml(content)
220 elif "{" in content or ":" in content:
222 payload = yaml.load(content)
223 except yaml.YAMLError as exc:
225 if hasattr(exc, 'problem_mark'):
226 mark = exc.problem_mark
227 error_pos = " at position: (%s:%s)" % (mark.line+1, mark.column+1)
228 print "Error loading yaml/json text"+error_pos
231 print "'%s' is neither a valid file nor a yaml/json content" % content
235 def _get_item_uuid(item, item_name_id, tenant=None):
237 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, tenant, item)
239 URLrequest = "http://%s:%s/openmano/%s" %(mano_host, mano_port, item)
240 mano_response = requests.get(URLrequest)
241 logger.debug("openmano response: %s", mano_response.text )
242 content = mano_response.json()
245 for i in content[item]:
246 if i["uuid"] == item_name_id:
248 if i["name"] == item_name_id:
251 if item_name_id.startswith("osm_id=") and i.get("osm_id") == item_name_id[7:]:
255 raise OpenmanoCLIError("No %s found with name/uuid '%s'" %(item[:-1], item_name_id))
257 raise OpenmanoCLIError("%d %s found with name '%s'. uuid must be used" %(found, item, item_name_id))
260 # def check_valid_uuid(uuid):
261 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
263 # js_v(uuid, id_schema)
265 # except js_e.ValidationError:
268 def _get_tenant(tenant_name_id = None):
269 if not tenant_name_id:
270 tenant_name_id = mano_tenant
272 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
273 return _get_item_uuid("tenants", tenant_name_id)
275 def _get_datacenter(datacenter_name_id = None, tenant = "any"):
276 if not datacenter_name_id:
277 datacenter_name_id = mano_datacenter
278 if not datacenter_name_id:
279 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
280 return _get_item_uuid("datacenters", datacenter_name_id, tenant)
283 def _get_wim(wim_name_id = None, tenant = "any"):
285 wim_name_id = mano_wim
287 raise OpenmanoCLIError("neither 'OPENMANO_WIM' environment variable is set nor --wim option is used")
288 return _get_item_uuid("wims", wim_name_id, tenant)
290 def vnf_create(args):
291 #print "vnf-create",args
292 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
293 tenant = _get_tenant()
294 myvnf = _load_file_or_yaml(args.file)
296 if "vnfd:vnfd-catalog" in myvnf or "vnfd-catalog" in myvnf:
299 vnfd_catalog = myvnf.get("vnfd:vnfd-catalog")
301 vnfd_catalog = myvnf.get("vnfd-catalog")
302 vnfds = vnfd_catalog.get("vnfd:vnfd")
304 vnfds = vnfd_catalog.get("vnfd")
306 vdu_list = vnfd["vdu"]
312 vdu_list = vnfd["VNFC"]
314 if args.name or args.description or args.image_path or args.image_name or args.image_checksum:
315 # TODO, change this for API v3
319 vnfd['name'] = args.name
321 vnfd['description'] = args.description
324 for image_path_ in args.image_path.split(","):
325 # print "image-path", image_path_
326 if api_version == "/v3":
327 if vdu_list[index].get("image"):
328 vdu_list[index]['image'] = image_path_
329 if "image-checksum" in vdu_list[index]:
330 del vdu_list[index]["image-checksum"]
331 else: # image name in volumes
332 vdu_list[index]["volumes"][0]["image"] = image_path_
333 if "image-checksum" in vdu_list[index]["volumes"][0]:
334 del vdu_list[index]["volumes"][0]["image-checksum"]
336 vdu_list[index]['VNFC image'] = image_path_
337 if "image name" in vdu_list[index]:
338 del vdu_list[index]["image name"]
339 if "image checksum" in vdu_list[index]:
340 del vdu_list[index]["image checksum"]
342 if args.image_name: # image name precedes if both are supplied
344 for image_name_ in args.image_name.split(","):
345 if api_version == "/v3":
346 if vdu_list[index].get("image"):
347 vdu_list[index]['image'] = image_name_
348 if "image-checksum" in vdu_list[index]:
349 del vdu_list[index]["image-checksum"]
350 if vdu_list[index].get("alternative-images"):
351 for a_image in vdu_list[index]["alternative-images"]:
352 a_image['image'] = image_name_
353 if "image-checksum" in a_image:
354 del a_image["image-checksum"]
355 else: # image name in volumes
356 vdu_list[index]["volumes"][0]["image"] = image_name_
357 if "image-checksum" in vdu_list[index]["volumes"][0]:
358 del vdu_list[index]["volumes"][0]["image-checksum"]
360 vdu_list[index]['image name'] = image_name_
361 if "VNFC image" in vdu_list[index]:
362 del vdu_list[index]["VNFC image"]
364 if args.image_checksum:
366 for image_checksum_ in args.image_checksum.split(","):
367 if api_version == "/v3":
368 if vdu_list[index].get("image"):
369 vdu_list[index]['image-checksum'] = image_checksum_
370 if vdu_list[index].get("alternative-images"):
371 for a_image in vdu_list[index]["alternative-images"]:
372 a_image['image-checksum'] = image_checksum_
373 else: # image name in volumes
374 vdu_list[index]["volumes"][0]["image-checksum"] = image_checksum_
376 vdu_list[index]['image checksum'] = image_checksum_
378 except (KeyError, TypeError), e:
379 if str(e) == 'vnf': error_pos= "missing field 'vnf'"
380 elif str(e) == 'name': error_pos= "missing field 'vnf':'name'"
381 elif str(e) == 'description': error_pos= "missing field 'vnf':'description'"
382 elif str(e) == 'VNFC': error_pos= "missing field 'vnf':'VNFC'"
383 elif str(e) == str(index): error_pos= "field 'vnf':'VNFC' must be an array"
384 elif str(e) == 'VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']"
385 elif str(e) == 'image name': error_pos= "missing field 'vnf':'VNFC'['image name']"
386 elif str(e) == 'image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']"
387 else: error_pos="wrong format"
388 print "Wrong VNF descriptor: " + error_pos
390 payload_req = json.dumps(myvnf)
394 URLrequest = "http://{}:{}/openmano{}/{}/{token}".format(mano_host, mano_port, api_version, tenant, token=token)
395 logger.debug("openmano request: %s", payload_req)
396 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
397 logger.debug("openmano response: %s", mano_response.text )
399 return _print_verbose(mano_response, args.verbose)
402 #print "vnf-list",args
406 tenant = _get_tenant()
408 toshow = _get_item_uuid("vnfs", args.name, tenant)
409 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, toshow)
411 URLrequest = "http://%s:%s/openmano/%s/vnfs" %(mano_host, mano_port, tenant)
412 mano_response = requests.get(URLrequest)
413 logger.debug("openmano response: %s", mano_response.text )
414 content = mano_response.json()
415 # print json.dumps(content, indent=4)
416 if args.verbose==None:
418 result = 0 if mano_response.status_code==200 else mano_response.status_code
419 if mano_response.status_code == 200:
421 if args.verbose >= 3:
422 print yaml.safe_dump(content, indent=4, default_flow_style=False)
424 if len(content['vnfs']) == 0:
425 print "No VNFs were found."
426 return 404 # HTTP_Not_Found
427 for vnf in content['vnfs']:
428 myoutput = "{:38} {:20}".format(vnf['uuid'], vnf['name'])
429 if vnf.get('osm_id') or args.verbose >= 1:
430 myoutput += " osm_id={:20}".format(vnf.get('osm_id'))
431 if args.verbose >= 1:
432 myoutput += " {}".format(vnf['created_at'])
434 if args.verbose >= 2:
435 print (" Description: {}".format(vnf['description']))
436 # print (" VNF descriptor file: {}".format(vnf['path']))
439 print yaml.safe_dump(content, indent=4, default_flow_style=False)
442 print ("{:38} {:20} osm_id={:20} {:20}".format(vnf['uuid'], vnf['name'], vnf.get('osm_id'),
444 print (" Description: {}".format(vnf['description']))
445 # print " VNF descriptor file: %s" %vnf['path']
447 for vm in vnf['VNFC']:
448 print (" {:20} osm_id={:20} {}".format(vm['name'], vm.get('osm_id'), vm['description']))
449 if len(vnf['nets']) > 0:
450 print (" Internal nets:")
451 for net in vnf['nets']:
452 print (" {:20} {}".format(net['name'], net['description']))
453 if len(vnf['external-connections']) > 0:
454 print (" External interfaces:")
455 for interface in vnf['external-connections']:
456 print (" {:20} {:20} {:20} {:14}".format(
457 interface['external_name'], interface['vm_name'],
458 interface['internal_name'],
459 interface.get('vpci') if interface.get('vpci') else ""))
461 print content['error']['description']
463 print yaml.safe_dump(content, indent=4, default_flow_style=False)
466 def vnf_delete(args):
467 #print "vnf-delete",args
471 tenant = _get_tenant()
472 todelete = _get_item_uuid("vnfs", args.name, tenant=tenant)
474 r = raw_input("Delete VNF %s (y/N)? " %(todelete))
475 if not (len(r)>0 and r[0].lower()=="y"):
477 URLrequest = "http://%s:%s/openmano/%s/vnfs/%s" %(mano_host, mano_port, tenant, todelete)
478 mano_response = requests.delete(URLrequest)
479 logger.debug("openmano response: %s", mano_response.text )
480 result = 0 if mano_response.status_code==200 else mano_response.status_code
481 content = mano_response.json()
482 #print json.dumps(content, indent=4)
483 if mano_response.status_code == 200:
484 print content['result']
486 print content['error']['description']
489 def scenario_create(args):
490 # print "scenario-create",args
491 tenant = _get_tenant()
492 headers_req = {'content-type': 'application/yaml'}
493 myscenario = _load_file_or_yaml(args.file)
494 if "nsd:nsd-catalog" in myscenario or "nsd-catalog" in myscenario:
497 nsd_catalog = myscenario.get("nsd:nsd-catalog")
499 nsd_catalog = myscenario.get("nsd-catalog")
500 nsds = nsd_catalog.get("nsd:nsd")
502 nsds = nsd_catalog.get("nsd")
507 if "scenario" in myscenario:
508 nsd = myscenario["scenario"]
511 # TODO modify for API v3
513 nsd['name'] = args.name
515 nsd['description'] = args.description
516 payload_req = yaml.safe_dump(myscenario, explicit_start=True, indent=4, default_flow_style=False, tags=False,
517 encoding='utf-8', allow_unicode=True)
520 URLrequest = "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
521 host=mano_host, port=mano_port, api=api_version, tenant=tenant, token=token)
522 logger.debug("openmano request: %s", payload_req)
523 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
524 logger.debug("openmano response: %s", mano_response.text )
525 return _print_verbose(mano_response, args.verbose)
527 def scenario_list(args):
528 #print "scenario-list",args
532 tenant = _get_tenant()
534 toshow = _get_item_uuid("scenarios", args.name, tenant)
535 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, toshow)
537 URLrequest = "http://%s:%s/openmano/%s/scenarios" %(mano_host, mano_port, tenant)
538 mano_response = requests.get(URLrequest)
539 logger.debug("openmano response: %s", mano_response.text )
540 content = mano_response.json()
541 #print json.dumps(content, indent=4)
542 if args.verbose==None:
545 result = 0 if mano_response.status_code==200 else mano_response.status_code
546 if mano_response.status_code == 200:
548 if args.verbose >= 3:
549 print yaml.safe_dump(content, indent=4, default_flow_style=False)
551 if len(content['scenarios']) == 0:
552 print "No scenarios were found."
553 return 404 #HTTP_Not_Found
554 for scenario in content['scenarios']:
555 myoutput = "{:38} {:20}".format(scenario['uuid'], scenario['name'])
556 if scenario.get('osm_id') or args.verbose >= 1:
557 myoutput += " osm_id={:20}".format(scenario.get('osm_id'))
558 if args.verbose >= 1:
559 myoutput += " {}".format(scenario['created_at'])
562 print (" Description: {}".format(scenario['description']))
565 print yaml.safe_dump(content, indent=4, default_flow_style=False)
567 scenario = content['scenario']
568 print ("{:38} {:20} osm_id={:20} {:20}".format(scenario['uuid'], scenario['name'], scenario.get('osm_id'),
569 scenario['created_at']))
570 print (" Description: {}".format(scenario['description']))
572 for vnf in scenario['vnfs']:
573 print (" {:38} {:20} vnf_index={} {}".format(vnf['vnf_id'], vnf['name'], vnf.get("member_vnf_index"),
575 if len(scenario['nets']) > 0:
577 for net in scenario['nets']:
578 description = net['description']
579 if not description: # if description does not exist, description is "-". Valid for external and internal nets.
582 if net.get('vim_id'):
583 vim_id = " vim_id=" + net["vim_id"]
586 external = " external"
587 print (" {:20} {:38} {:30}{}{}".format(net['name'], net['uuid'], description, vim_id, external))
589 print (content['error']['description'])
591 print yaml.safe_dump(content, indent=4, default_flow_style=False)
594 def scenario_delete(args):
595 #print "scenario-delete",args
599 tenant = _get_tenant()
600 todelete = _get_item_uuid("scenarios", args.name, tenant=tenant)
602 r = raw_input("Delete scenario %s (y/N)? " %(args.name))
603 if not (len(r)>0 and r[0].lower()=="y"):
605 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s" %(mano_host, mano_port, tenant, todelete)
606 mano_response = requests.delete(URLrequest)
607 logger.debug("openmano response: %s", mano_response.text )
608 result = 0 if mano_response.status_code==200 else mano_response.status_code
609 content = mano_response.json()
610 #print json.dumps(content, indent=4)
611 if mano_response.status_code == 200:
612 print content['result']
614 print content['error']['description']
617 def scenario_deploy(args):
618 print "This command is deprecated, use 'openmano instance-scenario-create --scenario %s --name %s' instead!!!" % (args.scenario, args.name)
621 args.netmap_use = None
622 args.netmap_create = None
624 args.keypair_auto = None
625 return instance_create(args)
627 # #print "scenario-deploy",args
628 # headers_req = {'content-type': 'application/json'}
632 # actionCmd="reserve"
633 # action[actionCmd] = {}
634 # action[actionCmd]["instance_name"] = args.name
635 # if args.datacenter != None:
636 # action[actionCmd]["datacenter"] = args.datacenter
637 # elif mano_datacenter != None:
638 # action[actionCmd]["datacenter"] = mano_datacenter
640 # if args.description:
641 # action[actionCmd]["description"] = args.description
642 # payload_req = json.dumps(action, indent=4)
645 # URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_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 )
649 # if args.verbose==None:
652 # result = 0 if mano_response.status_code==200 else mano_response.status_code
653 # content = mano_response.json()
654 # #print json.dumps(content, indent=4)
655 # if args.verbose >= 3:
656 # print yaml.safe_dump(content, indent=4, default_flow_style=False)
659 # if mano_response.status_code == 200:
660 # myoutput = "%s %s" %(content['uuid'].ljust(38),content['name'].ljust(20))
661 # if args.verbose >=1:
662 # myoutput = "%s %s" %(myoutput, content['created_at'].ljust(20))
663 # if args.verbose >=2:
664 # myoutput = "%s %s %s" %(myoutput, content['description'].ljust(30))
667 # print "To check the status, run the following command:"
668 # print "openmano instance-scenario-list <instance_id>"
670 # print content['error']['description']
673 def scenario_verify(args):
674 #print "scenario-verify",args
675 tenant = _get_tenant()
676 headers_req = {'content-type': 'application/json'}
678 action["verify"] = {}
679 action["verify"]["instance_name"] = "scen-verify-return5"
680 payload_req = json.dumps(action, indent=4)
683 URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario)
684 logger.debug("openmano request: %s", payload_req)
685 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
686 logger.debug("openmano response: %s", mano_response.text )
688 result = 0 if mano_response.status_code==200 else mano_response.status_code
689 content = mano_response.json()
690 #print json.dumps(content, indent=4)
691 if mano_response.status_code == 200:
692 print content['result']
694 print content['error']['description']
697 def instance_create(args):
698 tenant = _get_tenant()
699 headers_req = {'content-type': 'application/yaml'}
700 myInstance={"instance": {}, "schema_version": "0.1"}
702 instance_dict = _load_file_or_yaml(args.file)
703 if "instance" not in instance_dict:
704 myInstance = {"instance": instance_dict, "schema_version": "0.1"}
706 myInstance = instance_dict
708 myInstance["instance"]['name'] = args.name
710 myInstance["instance"]['description'] = args.description
712 myInstance["instance"]['action'] = "reserve"
714 datacenter = myInstance["instance"].get("datacenter")
715 if args.datacenter != None:
716 datacenter = args.datacenter
717 myInstance["instance"]["datacenter"] = _get_datacenter(datacenter, tenant)
719 scenario = myInstance["instance"].get("scenario")
720 if args.scenario != None:
721 scenario = args.scenario
723 print "you must provide a scenario in the file descriptor or with --scenario"
725 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant)
727 if "networks" not in myInstance["instance"]:
728 myInstance["instance"]["networks"] = {}
729 for net in args.netmap_use:
730 net_comma_list = net.split(",")
731 for net_comma in net_comma_list:
732 net_tuple = net_comma.split("=")
733 if len(net_tuple) != 2:
734 print "error at netmap-use. Expected net-scenario=net-datacenter. (%s)?" % net_comma
736 net_scenario = net_tuple[0].strip()
737 net_datacenter = net_tuple[1].strip()
738 if net_scenario not in myInstance["instance"]["networks"]:
739 myInstance["instance"]["networks"][net_scenario] = {}
740 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
741 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
742 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter
743 if args.netmap_create:
744 if "networks" not in myInstance["instance"]:
745 myInstance["instance"]["networks"] = {}
746 for net in args.netmap_create:
747 net_comma_list = net.split(",")
748 for net_comma in net_comma_list:
749 net_tuple = net_comma.split("=")
750 if len(net_tuple) == 1:
751 net_scenario = net_tuple[0].strip()
752 net_datacenter = None
753 elif len(net_tuple) == 2:
754 net_scenario = net_tuple[0].strip()
755 net_datacenter = net_tuple[1].strip()
757 print "error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. (%s)?" % net_comma
759 if net_scenario not in myInstance["instance"]["networks"]:
760 myInstance["instance"]["networks"][net_scenario] = {}
761 if "sites" not in myInstance["instance"]["networks"][net_scenario]:
762 myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ]
763 myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter
765 if "cloud-config" not in myInstance["instance"]:
766 myInstance["instance"]["cloud-config"] = {}
767 cloud_config = myInstance["instance"]["cloud-config"]
768 for key in args.keypair:
769 index = key.find(":")
771 if "key-pairs" not in cloud_config:
772 cloud_config["key-pairs"] = []
773 cloud_config["key-pairs"].append(key)
777 key_list = key_.split(",")
778 if "users" not in cloud_config:
779 cloud_config["users"] = []
780 cloud_config["users"].append({"name": user, "key-pairs": key_list })
781 if args.keypair_auto:
784 home = os.getenv("HOME")
785 user = os.getenv("USER")
786 files = os.listdir(home+'/.ssh')
788 if file[-4:] == ".pub":
789 with open(home+'/.ssh/'+file, 'r') as f:
790 keys.append(f.read())
792 print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh')
794 except Exception as e:
795 print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e))
798 if "cloud-config" not in myInstance["instance"]:
799 myInstance["instance"]["cloud-config"] = {}
800 cloud_config = myInstance["instance"]["cloud-config"]
801 if "key-pairs" not in cloud_config:
802 cloud_config["key-pairs"] = []
804 if "users" not in cloud_config:
805 cloud_config["users"] = []
806 cloud_config["users"].append({"name": user, "key-pairs": keys })
808 payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
809 logger.debug("openmano request: %s", payload_req)
810 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
811 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
812 logger.debug("openmano response: %s", mano_response.text )
813 if args.verbose==None:
816 result = 0 if mano_response.status_code==200 else mano_response.status_code
817 content = mano_response.json()
818 #print json.dumps(content, indent=4)
819 if args.verbose >= 3:
820 print yaml.safe_dump(content, indent=4, default_flow_style=False)
823 if mano_response.status_code == 200:
824 myoutput = "{:38} {:20}".format(content['uuid'], content['name'])
826 myoutput = "{} {:20}".format(myoutput, content['created_at'])
828 myoutput = "{} {:30}".format(myoutput, content['description'])
831 print content['error']['description']
834 def instance_scenario_list(args):
835 #print "instance-scenario-list",args
839 tenant = _get_tenant()
841 toshow = _get_item_uuid("instances", args.name, tenant)
842 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, toshow)
844 URLrequest = "http://%s:%s/openmano/%s/instances" %(mano_host, mano_port, tenant)
845 mano_response = requests.get(URLrequest)
846 logger.debug("openmano response: %s", mano_response.text )
847 content = mano_response.json()
848 #print json.dumps(content, indent=4)
849 if args.verbose==None:
852 result = 0 if mano_response.status_code==200 else mano_response.status_code
853 if mano_response.status_code == 200:
855 if args.verbose >= 3:
856 print yaml.safe_dump(content, indent=4, default_flow_style=False)
858 if len(content['instances']) == 0:
859 print "No scenario instances were found."
861 for instance in content['instances']:
862 myoutput = "{:38} {:20}".format(instance['uuid'], instance['name'])
864 myoutput = "{} {:20}".format(myoutput, instance['created_at'])
867 print "Description: %s" %instance['description']
870 print yaml.safe_dump(content, indent=4, default_flow_style=False)
873 print ("{:38} {:20} {:20}".format(instance['uuid'],instance['name'],instance['created_at']))
874 print ("Description: %s" %instance['description'])
875 print ("Template scenario id: {}".format(instance['scenario_id']))
876 print ("Template scenario name: {}".format(instance['scenario_name']))
877 print ("---------------------------------------")
878 print ("VNF instances: {}".format(len(instance['vnfs'])))
879 for vnf in instance['vnfs']:
880 #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))
881 print (" {:38} {:20} Template vnf id: {:38}".format(vnf['uuid'], vnf['vnf_name'], vnf['vnf_id']))
882 if len(instance['nets'])>0:
883 print "---------------------------------------"
884 print "Internal nets:"
885 for net in instance['nets']:
887 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
888 print "---------------------------------------"
889 print "External nets:"
890 for net in instance['nets']:
891 if not net['created']:
892 print (" {:38} {:12} VIM ID: {}".format(net['uuid'], net['status'], net['vim_net_id']))
893 print ("---------------------------------------")
894 print ("VM instances:")
895 for vnf in instance['vnfs']:
896 for vm in vnf['vms']:
897 print (" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm['uuid'], vnf['vnf_name'], vm['name'],
898 vm['status'], vm['vim_vm_id']))
900 print content['error']['description']
902 print yaml.safe_dump(content, indent=4, default_flow_style=False)
905 def instance_scenario_status(args):
906 print "instance-scenario-status"
909 def instance_scenario_delete(args):
913 tenant = _get_tenant()
914 todelete = _get_item_uuid("instances", args.name, tenant=tenant)
915 #print "instance-scenario-delete",args
917 r = raw_input("Delete scenario instance %s (y/N)? " %(args.name))
918 if not (len(r)>0 and r[0].lower()=="y"):
920 URLrequest = "http://%s:%s/openmano/%s/instances/%s" %(mano_host, mano_port, tenant, todelete)
921 mano_response = requests.delete(URLrequest)
922 logger.debug("openmano response: %s", mano_response.text )
923 result = 0 if mano_response.status_code==200 else mano_response.status_code
924 content = mano_response.json()
925 #print json.dumps(content, indent=4)
926 if mano_response.status_code == 200:
927 print content['result']
929 print content['error']['description']
932 def get_action(args):
934 tenant = _get_tenant()
937 if not args.instance:
940 instance_id =args.instance
943 action_id = "/" + args.id
944 URLrequest = "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host, mano_port, tenant, instance_id,
946 mano_response = requests.get(URLrequest)
947 logger.debug("openmano response: %s", mano_response.text )
948 if args.verbose == None:
952 return _print_verbose(mano_response, args.verbose)
954 def instance_scenario_action(args):
955 #print "instance-scenario-action", args
956 tenant = _get_tenant()
957 toact = _get_item_uuid("instances", args.name, tenant=tenant)
959 action[ args.action ] = yaml.safe_load(args.param)
961 action["vnfs"] = args.vnf
963 action["vms"] = args.vm
965 headers_req = {'content-type': 'application/json'}
966 payload_req = json.dumps(action, indent=4)
967 URLrequest = "http://%s:%s/openmano/%s/instances/%s/action" %(mano_host, mano_port, tenant, toact)
968 logger.debug("openmano request: %s", payload_req)
969 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
970 logger.debug("openmano response: %s", mano_response.text )
971 result = 0 if mano_response.status_code==200 else mano_response.status_code
972 content = mano_response.json()
973 # print json.dumps(content, indent=4)
974 if mano_response.status_code == 200:
976 print yaml.safe_dump(content, indent=4, default_flow_style=False)
978 if "instance_action_id" in content:
979 print("instance_action_id={}".format(content["instance_action_id"]))
981 for uuid,c in content.iteritems():
982 print ("{:38} {:20} {:20}".format(uuid, c.get('name'), c.get('description')))
984 print content['error']['description']
988 def instance_vnf_list(args):
989 print "instance-vnf-list"
992 def instance_vnf_status(args):
993 print "instance-vnf-status"
996 def tenant_create(args):
997 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
998 tenant_dict={"name": args.name}
999 if args.description!=None:
1000 tenant_dict["description"] = args.description
1001 payload_req = json.dumps( {"tenant": tenant_dict })
1005 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
1006 logger.debug("openmano request: %s", payload_req)
1007 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1008 logger.debug("openmano response: %s", mano_response.text )
1009 return _print_verbose(mano_response, args.verbose)
1011 def tenant_list(args):
1012 #print "tenant-list",args
1014 toshow = _get_item_uuid("tenants", args.name)
1015 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, toshow)
1017 URLrequest = "http://%s:%s/openmano/tenants" %(mano_host, mano_port)
1018 mano_response = requests.get(URLrequest)
1019 logger.debug("openmano response: %s", mano_response.text )
1020 if args.verbose==None:
1024 return _print_verbose(mano_response, args.verbose)
1026 def tenant_delete(args):
1027 #print "tenant-delete",args
1028 todelete = _get_item_uuid("tenants", args.name)
1030 r = raw_input("Delete tenant %s (y/N)? " %(args.name))
1031 if not (len(r)>0 and r[0].lower()=="y"):
1033 URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, todelete)
1034 mano_response = requests.delete(URLrequest)
1035 logger.debug("openmano response: %s", mano_response.text )
1036 result = 0 if mano_response.status_code==200 else mano_response.status_code
1037 content = mano_response.json()
1038 #print json.dumps(content, indent=4)
1039 if mano_response.status_code == 200:
1040 print content['result']
1042 print content['error']['description']
1045 def datacenter_attach(args):
1046 tenant = _get_tenant()
1047 datacenter = _get_datacenter(args.name)
1048 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1051 if args.vim_tenant_id != None:
1052 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1053 if args.vim_tenant_name != None:
1054 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1055 if args.user != None:
1056 datacenter_dict['vim_username'] = args.user
1057 if args.password != None:
1058 datacenter_dict['vim_password'] = args.password
1059 if args.config!=None:
1060 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1062 payload_req = json.dumps( {"datacenter": datacenter_dict })
1066 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1067 logger.debug("openmano request: %s", payload_req)
1068 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1069 logger.debug("openmano response: %s", mano_response.text )
1070 result = _print_verbose(mano_response, args.verbose)
1071 #provide addional information if error
1072 if mano_response.status_code != 200:
1073 content = mano_response.json()
1074 if "already in use for 'name'" in content['error']['description'] and \
1075 "to database vim_tenants table" in content['error']['description']:
1076 print "Try to specify a different name with --vim-tenant-name"
1080 def datacenter_edit_vim_tenant(args):
1081 tenant = _get_tenant()
1082 datacenter = _get_datacenter(args.name)
1083 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1085 if not (args.vim_tenant_id or args.vim_tenant_name or args.user or args.password or args.config):
1086 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1088 datacenter_dict = {}
1089 if args.vim_tenant_id != None:
1090 datacenter_dict['vim_tenant'] = args.vim_tenant_id
1091 if args.vim_tenant_name != None:
1092 datacenter_dict['vim_tenant_name'] = args.vim_tenant_name
1093 if args.user != None:
1094 datacenter_dict['vim_username'] = args.user
1095 if args.password != None:
1096 datacenter_dict['vim_password'] = args.password
1097 if args.config != None:
1098 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1099 payload_req = json.dumps({"datacenter": datacenter_dict})
1103 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" % (mano_host, mano_port, tenant, datacenter)
1104 logger.debug("openmano request: %s", payload_req)
1105 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1106 logger.debug("openmano response: %s", mano_response.text)
1107 result = _print_verbose(mano_response, args.verbose)
1111 def datacenter_detach(args):
1115 tenant = _get_tenant()
1116 datacenter = _get_datacenter(args.name, tenant)
1117 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1118 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, datacenter)
1119 mano_response = requests.delete(URLrequest, headers=headers_req)
1120 logger.debug("openmano response: %s", mano_response.text )
1121 content = mano_response.json()
1122 #print json.dumps(content, indent=4)
1123 result = 0 if mano_response.status_code==200 else mano_response.status_code
1124 if mano_response.status_code == 200:
1125 print content['result']
1127 print content['error']['description']
1130 def datacenter_create(args):
1131 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1132 datacenter_dict={"name": args.name, "vim_url": args.url}
1133 if args.description!=None:
1134 datacenter_dict["description"] = args.description
1136 datacenter_dict["type"] = args.type
1138 datacenter_dict["vim_url_admin"] = args.url_admin
1139 if args.config!=None:
1140 datacenter_dict["config"] = _load_file_or_yaml(args.config)
1141 if args.sdn_controller!=None:
1142 tenant = _get_tenant()
1143 sdn_controller = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1144 if not 'config' in datacenter_dict:
1145 datacenter_dict['config'] = {}
1146 datacenter_dict['config']['sdn-controller'] = sdn_controller
1147 payload_req = json.dumps( {"datacenter": datacenter_dict })
1151 URLrequest = "http://%s:%s/openmano/datacenters" %(mano_host, mano_port)
1152 logger.debug("openmano request: %s", payload_req)
1153 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1154 logger.debug("openmano response: %s", mano_response.text )
1155 return _print_verbose(mano_response, args.verbose)
1157 def datacenter_delete(args):
1158 #print "datacenter-delete",args
1159 todelete = _get_item_uuid("datacenters", args.name, "any")
1161 r = raw_input("Delete datacenter %s (y/N)? " %(args.name))
1162 if not (len(r)>0 and r[0].lower()=="y"):
1164 URLrequest = "http://%s:%s/openmano/datacenters/%s" %(mano_host, mano_port, todelete)
1165 mano_response = requests.delete(URLrequest)
1166 logger.debug("openmano response: %s", mano_response.text )
1167 result = 0 if mano_response.status_code==200 else mano_response.status_code
1168 content = mano_response.json()
1169 #print json.dumps(content, indent=4)
1170 if mano_response.status_code == 200:
1171 print content['result']
1173 print content['error']['description']
1177 def datacenter_list(args):
1178 #print "datacenter-list",args
1179 tenant='any' if args.all else _get_tenant()
1182 toshow = _get_item_uuid("datacenters", args.name, tenant)
1183 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, tenant, toshow)
1185 URLrequest = "http://%s:%s/openmano/%s/datacenters" %(mano_host, mano_port, tenant)
1186 mano_response = requests.get(URLrequest)
1187 logger.debug("openmano response: %s", mano_response.text )
1188 if args.verbose==None:
1192 return _print_verbose(mano_response, args.verbose)
1195 def datacenter_sdn_port_mapping_set(args):
1196 tenant = _get_tenant()
1197 datacenter = _get_datacenter(args.name, tenant)
1198 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1201 raise OpenmanoCLIError(
1202 "No yaml/json has been provided specifying the SDN port mapping")
1203 sdn_port_mapping = _load_file_or_yaml(args.file)
1204 payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping})
1207 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1208 mano_response = requests.get(URLrequest)
1209 logger.debug("openmano response: %s", mano_response.text)
1210 port_mapping = mano_response.json()
1211 if mano_response.status_code != 200:
1212 str(mano_response.json())
1213 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1214 if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0:
1216 r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter))
1217 if not (len(r) > 0 and r[0].lower() == "y"):
1221 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1222 mano_response = requests.delete(URLrequest)
1223 logger.debug("openmano response: %s", mano_response.text)
1224 if mano_response.status_code != 200:
1225 return _print_verbose(mano_response, args.verbose)
1228 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1229 logger.debug("openmano request: %s", payload_req)
1230 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1231 logger.debug("openmano response: %s", mano_response.text)
1232 return _print_verbose(mano_response, args.verbose)
1235 def datacenter_sdn_port_mapping_list(args):
1236 tenant = _get_tenant()
1237 datacenter = _get_datacenter(args.name, tenant)
1239 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1240 mano_response = requests.get(URLrequest)
1241 logger.debug("openmano response: %s", mano_response.text)
1243 return _print_verbose(mano_response, 4)
1246 def datacenter_sdn_port_mapping_clear(args):
1247 tenant = _get_tenant()
1248 datacenter = _get_datacenter(args.name, tenant)
1251 r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter))
1252 if not (len(r) > 0 and r[0].lower() == "y"):
1255 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter)
1256 mano_response = requests.delete(URLrequest)
1257 logger.debug("openmano response: %s", mano_response.text)
1259 return _print_verbose(mano_response, args.verbose)
1262 def sdn_controller_create(args):
1263 tenant = _get_tenant()
1264 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1267 if not args.ip: error_msg.append("'ip'")
1268 if not args.port: error_msg.append("'port'")
1269 if not args.dpid: error_msg.append("'dpid'")
1270 if not args.type: error_msg.append("'type'")
1272 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg))
1274 controller_dict = {}
1275 controller_dict['name'] = args.name
1276 controller_dict['ip'] = args.ip
1277 controller_dict['port'] = int(args.port)
1278 controller_dict['dpid'] = args.dpid
1279 controller_dict['type'] = args.type
1280 if args.description != None:
1281 controller_dict['description'] = args.description
1282 if args.user != None:
1283 controller_dict['user'] = args.user
1284 if args.password != None:
1285 controller_dict['password'] = args.password
1287 payload_req = json.dumps({"sdn_controller": controller_dict})
1291 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" % (mano_host, mano_port, tenant)
1292 logger.debug("openmano request: %s", payload_req)
1293 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1294 logger.debug("openmano response: %s", mano_response.text)
1295 result = _print_verbose(mano_response, args.verbose)
1299 def sdn_controller_edit(args):
1300 tenant = _get_tenant()
1301 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1302 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1304 controller_dict = {}
1306 controller_dict['name'] = args.new_name
1308 controller_dict['ip'] = args.ip
1310 controller_dict['port'] = int(args.port)
1312 controller_dict['dpid'] = args.dpid
1314 controller_dict['type'] = args.type
1315 if args.description:
1316 controller_dict['description'] = args.description
1318 controller_dict['user'] = args.user
1320 controller_dict['password'] = args.password
1322 if not controller_dict:
1323 raise OpenmanoCLIError("At least one parameter must be edited")
1326 r = raw_input("Update SDN controller {} (y/N)? ".format(args.name))
1327 if not (len(r) > 0 and r[0].lower() == "y"):
1330 payload_req = json.dumps({"sdn_controller": controller_dict})
1333 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1334 logger.debug("openmano request: %s", payload_req)
1335 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1336 logger.debug("openmano response: %s", mano_response.text)
1337 result = _print_verbose(mano_response, args.verbose)
1341 def sdn_controller_list(args):
1342 tenant = _get_tenant()
1343 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1346 toshow = _get_item_uuid("sdn_controllers", args.name, tenant)
1347 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" %(mano_host, mano_port, tenant, toshow)
1349 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers" %(mano_host, mano_port, tenant)
1351 mano_response = requests.get(URLrequest)
1352 logger.debug("openmano response: %s", mano_response.text )
1353 if args.verbose==None:
1358 # json.dumps(mano_response.json(), indent=4)
1359 return _print_verbose(mano_response, args.verbose)
1362 def sdn_controller_delete(args):
1363 tenant = _get_tenant()
1364 controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant)
1367 r = raw_input("Delete SDN controller %s (y/N)? " % (args.name))
1368 if not (len(r) > 0 and r[0].lower() == "y"):
1371 URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid)
1372 mano_response = requests.delete(URLrequest)
1373 logger.debug("openmano response: %s", mano_response.text)
1374 return _print_verbose(mano_response, args.verbose)
1376 def vim_action(args):
1377 #print "datacenter-net-action",args
1378 tenant = _get_tenant()
1379 datacenter = _get_datacenter(args.datacenter, tenant)
1380 if args.verbose==None:
1382 if args.action=="list":
1383 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1386 URLrequest += "/" + args.name
1387 mano_response = requests.get(URLrequest)
1388 logger.debug("openmano response: %s", mano_response.text )
1389 return _print_verbose(mano_response, args.verbose)
1390 elif args.action=="delete":
1391 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss/%s" %(mano_host, mano_port, tenant, datacenter, args.item, args.name)
1392 mano_response = requests.delete(URLrequest)
1393 logger.debug("openmano response: %s", mano_response.text )
1394 result = 0 if mano_response.status_code==200 else mano_response.status_code
1395 content = mano_response.json()
1396 #print json.dumps(content, indent=4)
1397 if mano_response.status_code == 200:
1398 print content['result']
1400 print content['error']['description']
1402 elif args.action=="create":
1403 headers_req = {'content-type': 'application/yaml'}
1405 create_dict = _load_file_or_yaml(args.file)
1406 if args.item not in create_dict:
1407 create_dict = {args.item: create_dict}
1409 create_dict = {args.item:{}}
1411 create_dict[args.item]['name'] = args.name
1412 #if args.description:
1413 # create_dict[args.item]['description'] = args.description
1414 if args.item=="network":
1416 create_dict[args.item]['bind_net'] = args.bind_net
1418 create_dict[args.item]['type'] = args.type
1420 create_dict[args.item]['shared'] = args.shared
1421 if "name" not in create_dict[args.item]:
1422 print "You must provide a name in the descriptor file or with the --name option"
1424 payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True)
1425 logger.debug("openmano request: %s", payload_req)
1426 URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item)
1427 mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
1428 logger.debug("openmano response: %s", mano_response.text )
1429 if args.verbose==None:
1431 return _print_verbose(mano_response, args.verbose)
1434 def _get_items(item, item_name_id=None, datacenter=None, tenant=None):
1435 URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port)
1437 URLrequest += "/" + tenant
1439 URLrequest += "/vim/" + datacenter
1441 URLrequest += "/" + item +"s"
1443 URLrequest += "/" + item_name_id
1444 mano_response = requests.get(URLrequest)
1445 logger.debug("openmano response: %s", mano_response.text )
1447 return mano_response
1450 def vim_net_sdn_attach(args):
1451 #Verify the network exists in the vim
1452 tenant = _get_tenant()
1453 datacenter = _get_datacenter(args.datacenter, tenant)
1454 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1455 content = yaml.load(result.content)
1456 if 'networks' in content:
1457 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1458 if 'error' in content:
1459 raise OpenmanoCLIError(yaml.safe_dump(content))
1460 network_uuid = content['network']['id']
1462 #Make call to attach the dataplane port to the SND network associated to the vim network
1463 headers_req = {'content-type': 'application/yaml'}
1464 payload_req = {'port': args.port}
1466 payload_req['vlan'] = int(args.vlan)
1468 payload_req['mac'] = args.mac
1470 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid)
1471 logger.debug("openmano request: %s", payload_req)
1472 mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req))
1473 logger.debug("openmano response: %s", mano_response.text)
1474 result = _print_verbose(mano_response, args.verbose)
1478 def vim_net_sdn_detach(args):
1479 if not args.all and not args.id:
1480 print "--all or --id must be used"
1483 # Verify the network exists in the vim
1484 tenant = _get_tenant()
1485 datacenter = _get_datacenter(args.datacenter, tenant)
1486 result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant)
1487 content = yaml.load(result.content)
1488 if 'networks' in content:
1489 raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead')
1490 if 'error' in content:
1491 raise OpenmanoCLIError(yaml.safe_dump(content))
1492 network_uuid = content['network']['id']
1495 r = raw_input("Confirm action' (y/N)? ")
1496 if len(r) == 0 or r[0].lower() != "y":
1500 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % (
1501 mano_host, mano_port, tenant, datacenter, network_uuid, args.id)
1503 URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % (
1504 mano_host, mano_port, tenant, datacenter, network_uuid)
1505 mano_response = requests.delete(URLrequest)
1506 logger.debug("openmano response: %s", mano_response.text)
1507 result = _print_verbose(mano_response, args.verbose)
1511 def datacenter_net_action(args):
1512 if args.action == "net-update":
1513 print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!"
1515 args.action = "netmap-delete"
1518 r = datacenter_netmap_action(args)
1521 args.action = "netmap-import"
1522 r = datacenter_netmap_action(args)
1525 if args.action == "net-edit":
1526 args.netmap = args.net
1528 elif args.action == "net-list":
1530 elif args.action == "net-delete":
1531 args.netmap = args.net
1534 args.action = "netmap" + args.action[3:]
1537 print "This command is deprecated, use 'openmano datacenter-%s' instead!!!" % args.action
1539 return datacenter_netmap_action(args)
1541 def datacenter_netmap_action(args):
1542 tenant = _get_tenant()
1543 datacenter = _get_datacenter(args.datacenter, tenant)
1544 #print "datacenter_netmap_action",args
1546 if args.verbose==None:
1548 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1549 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/netmaps" %(mano_host, mano_port, tenant, datacenter)
1551 if args.action=="netmap-list":
1553 URLrequest += "/" + args.netmap
1555 mano_response = requests.get(URLrequest)
1557 elif args.action=="netmap-delete":
1558 if args.netmap and args.all:
1559 print "you can not use a netmap name and the option --all at the same time"
1562 force_text= "Delete default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter)
1563 URLrequest += "/" + args.netmap
1565 force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter)
1567 print "you must specify a netmap name or the option --all"
1570 r = raw_input(force_text)
1571 if len(r)>0 and r[0].lower()=="y":
1575 mano_response = requests.delete(URLrequest, headers=headers_req)
1576 elif args.action=="netmap-import":
1578 r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter))
1579 if len(r)>0 and r[0].lower()=="y":
1583 URLrequest += "/upload"
1584 mano_response = requests.post(URLrequest, headers=headers_req)
1585 elif args.action=="netmap-edit" or args.action=="netmap-create":
1587 payload = _load_file_or_yaml(args.file)
1590 if "netmap" not in payload:
1591 payload = {"netmap": payload}
1593 payload["netmap"]["name"] = args.name
1595 payload["netmap"]["vim_id"] = args.vim_id
1596 if args.action=="netmap-create" and args.vim_name:
1597 payload["netmap"]["vim_name"] = args.vim_name
1598 payload_req = json.dumps(payload)
1599 logger.debug("openmano request: %s", payload_req)
1601 if args.action=="netmap-edit" and not args.force:
1602 if len(payload["netmap"]) == 0:
1603 print "You must supply some parameter to edit"
1605 r = raw_input("Edit default netmap '%s' from datacenter '%s' (y/N)? " % (args.netmap, datacenter))
1606 if len(r)>0 and r[0].lower()=="y":
1610 URLrequest += "/" + args.netmap
1611 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1612 else: #netmap-create
1613 if "vim_name" not in payload["netmap"] and "vim_id" not in payload["netmap"]:
1614 print "You must supply either --vim-id or --vim-name option; or include one of them in the file descriptor"
1616 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1618 logger.debug("openmano response: %s", mano_response.text )
1619 return _print_verbose(mano_response, args.verbose)
1622 def element_edit(args):
1623 element = _get_item_uuid(args.element, args.name)
1624 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1625 URLrequest = "http://%s:%s/openmano/%s/%s" %(mano_host, mano_port, args.element, element)
1626 payload=_load_file_or_yaml(args.file)
1627 if args.element[:-1] not in payload:
1628 payload = {args.element[:-1]: payload }
1629 payload_req = json.dumps(payload)
1632 if not args.force or (args.name==None and args.filer==None):
1633 r = raw_input(" Edit " + args.element[:-1] + " " + args.name + " (y/N)? ")
1634 if len(r)>0 and r[0].lower()=="y":
1638 logger.debug("openmano request: %s", payload_req)
1639 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1640 logger.debug("openmano response: %s", mano_response.text )
1641 if args.verbose==None:
1645 return _print_verbose(mano_response, args.verbose)
1648 def datacenter_edit(args):
1649 tenant = _get_tenant()
1650 element = _get_item_uuid('datacenters', args.name, tenant)
1651 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1652 URLrequest = "http://%s:%s/openmano/datacenters/%s" % (mano_host, mano_port, element)
1654 has_arguments = False
1655 if args.file != None:
1656 has_arguments = True
1657 payload = _load_file_or_yaml(args.file)
1661 if args.sdn_controller != None:
1662 has_arguments = True
1663 if not 'config' in payload:
1664 payload['config'] = {}
1665 if not 'sdn-controller' in payload['config']:
1666 payload['config']['sdn-controller'] = {}
1667 if args.sdn_controller == 'null':
1668 payload['config']['sdn-controller'] = None
1670 payload['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args.sdn_controller, tenant)
1672 if not has_arguments:
1673 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1675 if 'datacenter' not in payload:
1676 payload = {'datacenter': payload}
1677 payload_req = json.dumps(payload)
1680 if not args.force or (args.name == None and args.filer == None):
1681 r = raw_input(" Edit datacenter " + args.name + " (y/N)? ")
1682 if len(r) > 0 and r[0].lower() == "y":
1686 logger.debug("openmano request: %s", payload_req)
1687 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1688 logger.debug("openmano response: %s", mano_response.text)
1689 if args.verbose == None:
1691 if args.name != None:
1693 return _print_verbose(mano_response, args.verbose)
1697 def wim_account_create(args):
1698 tenant = _get_tenant()
1699 wim = _get_wim(args.name)
1700 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1703 if args.account_name is not None:
1704 wim_dict['name'] = args.account_name
1705 if args.user is not None:
1706 wim_dict['user'] = args.user
1707 if args.password is not None:
1708 wim_dict['password'] = args.password
1709 if args.config is not None:
1710 wim_dict["config"] = _load_file_or_yaml(args.config)
1712 payload_req = json.dumps({"wim_account": wim_dict})
1714 URLrequest = "http://%s:%s/openmano/%s/wims/%s" % (mano_host, mano_port, tenant, wim)
1715 logger.debug("openmano request: %s", payload_req)
1716 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1717 logger.debug("openmano response: %s", mano_response.text)
1718 result = _print_verbose(mano_response, args.verbose)
1719 # provide addional information if error
1720 if mano_response.status_code != 200:
1721 content = mano_response.json()
1722 if "already in use for 'name'" in content['error']['description'] and \
1723 "to database wim_tenants table" in content['error']['description']:
1724 print "Try to specify a different name with --wim-tenant-name"
1728 def wim_account_delete(args):
1732 tenant = _get_tenant()
1733 wim = _get_wim(args.name, tenant)
1734 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1735 URLrequest = "http://%s:%s/openmano/%s/wims/%s" % (mano_host, mano_port, tenant, wim)
1736 mano_response = requests.delete(URLrequest, headers=headers_req)
1737 logger.debug("openmano response: %s", mano_response.text)
1738 content = mano_response.json()
1739 # print json.dumps(content, indent=4)
1740 result = 0 if mano_response.status_code == 200 else mano_response.status_code
1741 if mano_response.status_code == 200:
1742 print content['result']
1744 print content['error']['description']
1748 def wim_account_edit(args):
1749 tenant = _get_tenant()
1750 wim = _get_wim(args.name)
1751 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1754 if not args.account_name:
1755 wim_dict['name'] = args.vim_tenant_name
1757 wim_dict['user'] = args.user
1758 if not args.password:
1759 wim_dict['password'] = args.password
1761 wim_dict["config"] = _load_file_or_yaml(args.config)
1763 payload_req = json.dumps({"wim_account": wim_dict})
1767 URLrequest = "http://%s:%s/openmano/%s/wims/%s" % (mano_host, mano_port, tenant, wim)
1768 logger.debug("openmano request: %s", payload_req)
1769 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1770 logger.debug("openmano response: %s", mano_response.text)
1771 result = _print_verbose(mano_response, args.verbose)
1772 # provide addional information if error
1773 if mano_response.status_code != 200:
1774 content = mano_response.json()
1775 if "already in use for 'name'" in content['error']['description'] and \
1776 "to database wim_tenants table" in content['error']['description']:
1777 print "Try to specify a different name with --wim-tenant-name"
1780 def wim_create(args):
1781 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1782 wim_dict = {"name": args.name, "wim_url": args.url}
1783 if args.description != None:
1784 wim_dict["description"] = args.description
1785 if args.type != None:
1786 wim_dict["type"] = args.type
1787 if args.config != None:
1788 wim_dict["config"] = _load_file_or_yaml(args.config)
1790 payload_req = json.dumps({"wim": wim_dict})
1792 URLrequest = "http://%s:%s/openmano/wims" % (mano_host, mano_port)
1793 logger.debug("openmano request: %s", payload_req)
1794 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1795 logger.debug("openmano response: %s", mano_response.text)
1796 return _print_verbose(mano_response, args.verbose)
1800 tenant = _get_tenant()
1801 element = _get_item_uuid('wims', args.name, tenant)
1802 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1803 URLrequest = "http://%s:%s/openmano/wims/%s" % (mano_host, mano_port, element)
1805 has_arguments = False
1806 if args.file != None:
1807 has_arguments = True
1808 payload = _load_file_or_yaml(args.file)
1812 if not has_arguments:
1813 raise OpenmanoCLIError("At least one argument must be provided to modify the wim")
1815 if 'wim' not in payload:
1816 payload = {'wim': payload}
1817 payload_req = json.dumps(payload)
1820 if not args.force or (args.name == None and args.filer == None):
1821 r = raw_input(" Edit wim " + args.name + " (y/N)? ")
1822 if len(r) > 0 and r[0].lower() == "y":
1826 logger.debug("openmano request: %s", payload_req)
1827 mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req)
1828 logger.debug("openmano response: %s", mano_response.text)
1829 if args.verbose == None:
1831 if args.name != None:
1833 return _print_verbose(mano_response, args.verbose)
1836 def wim_delete(args):
1837 # print "wim-delete",args
1838 todelete = _get_item_uuid("wims", args.name, "any")
1840 r = raw_input("Delete wim %s (y/N)? " % (args.name))
1841 if not (len(r) > 0 and r[0].lower() == "y"):
1843 URLrequest = "http://%s:%s/openmano/wims/%s" % (mano_host, mano_port, todelete)
1844 mano_response = requests.delete(URLrequest)
1845 logger.debug("openmano response: %s", mano_response.text)
1846 result = 0 if mano_response.status_code == 200 else mano_response.status_code
1847 content = mano_response.json()
1848 # print json.dumps(content, indent=4)
1849 if mano_response.status_code == 200:
1850 print content['result']
1852 print content['error']['description']
1857 # print "wim-list",args
1858 tenant = 'any' if args.all else _get_tenant()
1861 toshow = _get_item_uuid("wims", args.name, tenant)
1862 URLrequest = "http://%s:%s/openmano/%s/wims/%s" % (mano_host, mano_port, tenant, toshow)
1864 URLrequest = "http://%s:%s/openmano/%s/wims" % (mano_host, mano_port, tenant)
1865 mano_response = requests.get(URLrequest)
1866 logger.debug("openmano response: %s", mano_response.text)
1867 if args.verbose == None:
1869 if args.name != None:
1871 return _print_verbose(mano_response, args.verbose)
1874 def wim_port_mapping_set(args):
1875 tenant = _get_tenant()
1876 wim = _get_wim(args.name, tenant)
1877 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1880 raise OpenmanoCLIError(
1881 "No yaml/json has been provided specifying the WIM port mapping")
1882 wim_port_mapping = _load_file_or_yaml(args.file)
1884 payload_req = json.dumps({"wim_port_mapping": wim_port_mapping})
1887 URLrequest = "http://%s:%s/openmano/%s/wims/%s/port_mapping" % (mano_host, mano_port, tenant, wim)
1888 mano_response = requests.get(URLrequest)
1889 logger.debug("openmano response: %s", mano_response.text)
1890 port_mapping = mano_response.json()
1892 if mano_response.status_code != 200:
1893 str(mano_response.json())
1894 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description']))
1895 # TODO: check this if statement
1896 if len(port_mapping["wim_port_mapping"]) > 0:
1898 r = raw_input("WIM %s already contains a port mapping. Overwrite? (y/N)? " % (wim))
1899 if not (len(r) > 0 and r[0].lower() == "y"):
1903 URLrequest = "http://%s:%s/openmano/%s/wims/%s/port_mapping" % (mano_host, mano_port, tenant, wim)
1904 mano_response = requests.delete(URLrequest)
1905 logger.debug("openmano response: %s", mano_response.text)
1906 if mano_response.status_code != 200:
1907 return _print_verbose(mano_response, args.verbose)
1910 URLrequest = "http://%s:%s/openmano/%s/wims/%s/port_mapping" % (mano_host, mano_port, tenant, wim)
1911 logger.debug("openmano request: %s", payload_req)
1912 mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req)
1913 logger.debug("openmano response: %s", mano_response.text)
1914 return _print_verbose(mano_response, 4)
1917 def wim_port_mapping_list(args):
1918 tenant = _get_tenant()
1919 wim = _get_wim(args.name, tenant)
1921 URLrequest = "http://%s:%s/openmano/%s/wims/%s/port_mapping" % (mano_host, mano_port, tenant, wim)
1922 mano_response = requests.get(URLrequest)
1923 logger.debug("openmano response: %s", mano_response.text)
1925 return _print_verbose(mano_response, 4)
1928 def wim_port_mapping_clear(args):
1929 tenant = _get_tenant()
1930 wim = _get_wim(args.name, tenant)
1933 r = raw_input("Clear WIM port mapping for wim %s (y/N)? " % (wim))
1934 if not (len(r) > 0 and r[0].lower() == "y"):
1937 URLrequest = "http://%s:%s/openmano/%s/wims/%s/port_mapping" % (mano_host, mano_port, tenant, wim)
1938 mano_response = requests.delete(URLrequest)
1939 logger.debug("openmano response: %s", mano_response.text)
1940 content = mano_response.json()
1941 # print json.dumps(content, indent=4)
1942 result = 0 if mano_response.status_code == 200 else mano_response.status_code
1943 if mano_response.status_code == 200:
1944 print content['result']
1946 print content['error']['description']
1951 headers_req = {'Accept': 'application/json', 'content-type': 'application/json'}
1952 URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port)
1954 mano_response = requests.get(URLrequest, headers=headers_req)
1955 logger.debug("openmano response: %s", mano_response.text)
1956 print mano_response.text
1963 if __name__=="__main__":
1965 mano_tenant = os.getenv('OPENMANO_TENANT', None)
1966 mano_host = os.getenv('OPENMANO_HOST',"localhost")
1967 mano_port = os.getenv('OPENMANO_PORT',"9090")
1968 mano_datacenter = os.getenv('OPENMANO_DATACENTER',None)
1969 # WIM env variable for default WIM
1970 mano_wim = os.getenv('OPENMANO_WIM', None)
1972 main_parser = ThrowingArgumentParser(description='User program to interact with OPENMANO-SERVER (openmanod)')
1973 main_parser.add_argument('--version', action='version', help="get version of this client",
1974 version='%(prog)s client version ' + __version__ +
1975 " (Note: use '%(prog)s version' to get server version)")
1977 subparsers = main_parser.add_subparsers(help='commands')
1979 parent_parser = argparse.ArgumentParser(add_help=False)
1980 parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times")
1981 parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
1983 config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values")
1984 config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names")
1985 config_parser.set_defaults(func=config)
1987 version_parser = subparsers.add_parser('version', parents=[parent_parser], help="get server version")
1988 version_parser.set_defaults(func=version)
1990 vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue")
1991 vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter
1992 vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1993 vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
1994 vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)")
1995 vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)")
1996 vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)")
1997 vnf_create_parser.set_defaults(func=vnf_create)
1999 vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf")
2000 vnf_list_parser.add_argument("name", nargs='?', help="name of the VNF")
2001 vnf_list_parser.add_argument("-a", "--all", action="store_true", help="shows all vnfs, not only the owned or public ones")
2002 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
2003 vnf_list_parser.set_defaults(func=vnf_list)
2005 vnf_delete_parser = subparsers.add_parser('vnf-delete', parents=[parent_parser], help="deletes a vnf from the catalogue")
2006 vnf_delete_parser.add_argument("name", action="store", help="name or uuid of the VNF to be deleted")
2007 vnf_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
2008 vnf_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
2009 vnf_delete_parser.set_defaults(func=vnf_delete)
2011 scenario_create_parser = subparsers.add_parser('scenario-create', parents=[parent_parser], help="adds a scenario into the OPENMANO DB")
2012 scenario_create_parser.add_argument("file", action="store", help="location of the YAML file describing the scenario").completer = FilesCompleter
2013 scenario_create_parser.add_argument("--name", action="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
2014 scenario_create_parser.add_argument("--description", action="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
2015 scenario_create_parser.set_defaults(func=scenario_create)
2017 scenario_list_parser = subparsers.add_parser('scenario-list', parents=[parent_parser], help="lists information about a scenario")
2018 scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario")
2019 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
2020 scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all scenarios, not only the owned or public ones")
2021 scenario_list_parser.set_defaults(func=scenario_list)
2023 scenario_delete_parser = subparsers.add_parser('scenario-delete', parents=[parent_parser], help="deletes a scenario from the OPENMANO DB")
2024 scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario to be deleted")
2025 scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
2026 scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
2027 scenario_delete_parser.set_defaults(func=scenario_delete)
2029 scenario_deploy_parser = subparsers.add_parser('scenario-deploy', parents=[parent_parser], help="deploys a scenario")
2030 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be deployed")
2031 scenario_deploy_parser.add_argument("name", action="store", help="name of the instance")
2032 scenario_deploy_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
2033 scenario_deploy_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
2034 scenario_deploy_parser.add_argument("--description", action="store", help="description of the instance")
2035 scenario_deploy_parser.set_defaults(func=scenario_deploy)
2037 scenario_deploy_parser = subparsers.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
2038 scenario_deploy_parser.add_argument("scenario", action="store", help="name or uuid of the scenario to be verified")
2039 scenario_deploy_parser.add_argument('--debug', '-d', action='store_true', help="show debug information")
2040 scenario_deploy_parser.set_defaults(func=scenario_verify)
2042 instance_scenario_create_parser = subparsers.add_parser('instance-scenario-create', parents=[parent_parser], help="deploys a scenario")
2043 instance_scenario_create_parser.add_argument("file", nargs='?', help="descriptor of the instance. Must be a file or yaml/json text")
2044 instance_scenario_create_parser.add_argument("--scenario", action="store", help="name or uuid of the scenario to be deployed")
2045 instance_scenario_create_parser.add_argument("--name", action="store", help="name of the instance")
2046 instance_scenario_create_parser.add_argument("--nostart", action="store_true", help="does not start the vms, just reserve resources")
2047 instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available")
2048 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")
2049 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")
2050 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")
2051 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")
2052 instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance")
2053 instance_scenario_create_parser.set_defaults(func=instance_create)
2055 instance_scenario_list_parser = subparsers.add_parser('instance-scenario-list', parents=[parent_parser], help="lists information about a scenario instance")
2056 instance_scenario_list_parser.add_argument("name", nargs='?', help="name of the scenario instance")
2057 instance_scenario_list_parser.add_argument("-a", "--all", action="store_true", help="shows all instance-scenarios, not only the owned")
2058 instance_scenario_list_parser.set_defaults(func=instance_scenario_list)
2060 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)")
2061 instance_scenario_delete_parser.add_argument("name", action="store", help="name or uuid of the scenario instance to be deleted")
2062 instance_scenario_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
2063 instance_scenario_delete_parser.add_argument("-a", "--all", action="store_true", help="allow delete not owned or privated one")
2064 instance_scenario_delete_parser.set_defaults(func=instance_scenario_delete)
2066 instance_scenario_action_parser = subparsers.add_parser('instance-scenario-action', parents=[parent_parser], help="invoke an action over part or the whole scenario instance")
2067 instance_scenario_action_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
2068 instance_scenario_action_parser.add_argument("action", action="store", type=str, \
2069 choices=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key","vdu-scaling"],\
2070 help="action to send")
2071 instance_scenario_action_parser.add_argument("param", nargs='?', help="addional param of the action. e.g. console: novnc; reboot: type; vdu-scaling: '[{vdu-id: xxx, type: create|delete, count: 1}]'")
2072 instance_scenario_action_parser.add_argument("--vnf", action="append", help="VNF to act on (can use several entries)")
2073 instance_scenario_action_parser.add_argument("--vm", action="append", help="VM to act on (can use several entries)")
2074 instance_scenario_action_parser.set_defaults(func=instance_scenario_action)
2076 action_parser = subparsers.add_parser('action-list', parents=[parent_parser], help="get action over an instance status")
2077 action_parser.add_argument("id", nargs='?', action="store", help="action id")
2078 action_parser.add_argument("--instance", action="store", help="fitler by this instance_id")
2079 action_parser.add_argument("--all", action="store", help="Not filter by tenant")
2080 action_parser.set_defaults(func=get_action)
2082 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
2083 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
2084 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
2086 tenant_create_parser = subparsers.add_parser('tenant-create', parents=[parent_parser], help="creates a new tenant")
2087 tenant_create_parser.add_argument("name", action="store", help="name for the tenant")
2088 tenant_create_parser.add_argument("--description", action="store", help="description of the tenant")
2089 tenant_create_parser.set_defaults(func=tenant_create)
2091 tenant_delete_parser = subparsers.add_parser('tenant-delete', parents=[parent_parser], help="deletes a tenant from the catalogue")
2092 tenant_delete_parser.add_argument("name", action="store", help="name or uuid of the tenant to be deleted")
2093 tenant_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
2094 tenant_delete_parser.set_defaults(func=tenant_delete)
2096 tenant_list_parser = subparsers.add_parser('tenant-list', parents=[parent_parser], help="lists information about a tenant")
2097 tenant_list_parser.add_argument("name", nargs='?', help="name or uuid of the tenant")
2098 tenant_list_parser.set_defaults(func=tenant_list)
2100 element_edit_parser = subparsers.add_parser('tenant-edit', parents=[parent_parser], help="edits one tenant")
2101 element_edit_parser.add_argument("name", help="name or uuid of the tenant")
2102 element_edit_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
2103 element_edit_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2104 element_edit_parser.set_defaults(func=element_edit, element='tenants')
2106 datacenter_create_parser = subparsers.add_parser('datacenter-create', parents=[parent_parser], help="creates a new datacenter")
2107 datacenter_create_parser.add_argument("name", action="store", help="name for the datacenter")
2108 datacenter_create_parser.add_argument("url", action="store", help="url for the datacenter")
2109 datacenter_create_parser.add_argument("--url_admin", action="store", help="url for administration for the datacenter")
2110 datacenter_create_parser.add_argument("--type", action="store", help="datacenter type: openstack or openvim (default)")
2111 datacenter_create_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
2112 datacenter_create_parser.add_argument("--description", action="store", help="description of the datacenter")
2113 datacenter_create_parser.add_argument("--sdn-controller", action="store", help="Name or uuid of the SDN controller to be used", dest='sdn_controller')
2114 datacenter_create_parser.set_defaults(func=datacenter_create)
2116 datacenter_delete_parser = subparsers.add_parser('datacenter-delete', parents=[parent_parser], help="deletes a datacenter from the catalogue")
2117 datacenter_delete_parser.add_argument("name", action="store", help="name or uuid of the datacenter to be deleted")
2118 datacenter_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
2119 datacenter_delete_parser.set_defaults(func=datacenter_delete)
2121 datacenter_edit_parser = subparsers.add_parser('datacenter-edit', parents=[parent_parser], help="Edit datacenter")
2122 datacenter_edit_parser.add_argument("name", help="name or uuid of the datacenter")
2123 datacenter_edit_parser.add_argument("--file", help="json/yaml text or file with the changes").completer = FilesCompleter
2124 datacenter_edit_parser.add_argument("--sdn-controller", action="store",
2125 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest='sdn_controller')
2126 datacenter_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
2127 datacenter_edit_parser.set_defaults(func=datacenter_edit)
2129 datacenter_list_parser = subparsers.add_parser('datacenter-list', parents=[parent_parser], help="lists information about a datacenter")
2130 datacenter_list_parser.add_argument("name", nargs='?', help="name or uuid of the datacenter")
2131 datacenter_list_parser.add_argument("-a", "--all", action="store_true", help="shows all datacenters, not only datacenters attached to tenant")
2132 datacenter_list_parser.set_defaults(func=datacenter_list)
2134 datacenter_attach_parser = subparsers.add_parser('datacenter-attach', parents=[parent_parser], help="associates a datacenter to the operating tenant")
2135 datacenter_attach_parser.add_argument("name", help="name or uuid of the datacenter")
2136 datacenter_attach_parser.add_argument('--vim-tenant-id', action='store', help="specify a datacenter tenant to use. A new one is created by default")
2137 datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
2138 datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
2139 datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
2140 datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format")
2141 datacenter_attach_parser.set_defaults(func=datacenter_attach)
2143 datacenter_edit_vim_tenant_parser = subparsers.add_parser('datacenter-edit-vim-tenant', parents=[parent_parser],
2144 help="Edit the association of a datacenter to the operating tenant")
2145 datacenter_edit_vim_tenant_parser.add_argument("name", help="name or uuid of the datacenter")
2146 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-id', action='store',
2147 help="specify a datacenter tenant to use. A new one is created by default")
2148 datacenter_edit_vim_tenant_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.")
2149 datacenter_edit_vim_tenant_parser.add_argument("--user", action="store", help="user credentials for the datacenter")
2150 datacenter_edit_vim_tenant_parser.add_argument("--password", action="store", help="password credentials for the datacenter")
2151 datacenter_edit_vim_tenant_parser.add_argument("--config", action="store",
2152 help="aditional configuration in json/yaml format")
2153 datacenter_edit_vim_tenant_parser.set_defaults(func=datacenter_edit_vim_tenant)
2155 datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant")
2156 datacenter_detach_parser.add_argument("name", help="name or uuid of the datacenter")
2157 datacenter_detach_parser.add_argument("-a", "--all", action="store_true", help="removes all associations from this datacenter")
2158 datacenter_detach_parser.set_defaults(func=datacenter_detach)
2160 #=======================datacenter_sdn_port_mapping_xxx section=======================
2161 #datacenter_sdn_port_mapping_set
2162 datacenter_sdn_port_mapping_set_parser = subparsers.add_parser('datacenter-sdn-port-mapping-set',
2163 parents=[parent_parser],
2164 help="Load a file with the mapping of physical ports "
2165 "and the ports of the dataplaneswitch controlled "
2167 datacenter_sdn_port_mapping_set_parser.add_argument("name", action="store", help="specifies the datacenter")
2168 datacenter_sdn_port_mapping_set_parser.add_argument("file",
2169 help="json/yaml text or file with the port mapping").completer = FilesCompleter
2170 datacenter_sdn_port_mapping_set_parser.add_argument("-f", "--force", action="store_true",
2171 help="forces overwriting without asking")
2172 datacenter_sdn_port_mapping_set_parser.set_defaults(func=datacenter_sdn_port_mapping_set)
2174 #datacenter_sdn_port_mapping_list
2175 datacenter_sdn_port_mapping_list_parser = subparsers.add_parser('datacenter-sdn-port-mapping-list',
2176 parents=[parent_parser],
2177 help="Show the SDN port mapping in a datacenter")
2178 datacenter_sdn_port_mapping_list_parser.add_argument("name", action="store", help="specifies the datacenter")
2179 datacenter_sdn_port_mapping_list_parser.set_defaults(func=datacenter_sdn_port_mapping_list)
2181 # datacenter_sdn_port_mapping_clear
2182 datacenter_sdn_port_mapping_clear_parser = subparsers.add_parser('datacenter-sdn-port-mapping-clear',
2183 parents=[parent_parser],
2184 help="Clean the the SDN port mapping in a datacenter")
2185 datacenter_sdn_port_mapping_clear_parser.add_argument("name", action="store",
2186 help="specifies the datacenter")
2187 datacenter_sdn_port_mapping_clear_parser.add_argument("-f", "--force", action="store_true",
2188 help="forces clearing without asking")
2189 datacenter_sdn_port_mapping_clear_parser.set_defaults(func=datacenter_sdn_port_mapping_clear)
2190 # =======================
2192 # =======================sdn_controller_xxx section=======================
2193 # sdn_controller_create
2194 sdn_controller_create_parser = subparsers.add_parser('sdn-controller-create', parents=[parent_parser],
2195 help="Creates an SDN controller entity within RO")
2196 sdn_controller_create_parser.add_argument("name", help="name of the SDN controller")
2197 sdn_controller_create_parser.add_argument("--description", action="store", help="description of the SDN controller")
2198 sdn_controller_create_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
2199 sdn_controller_create_parser.add_argument("--port", action="store", help="Port of the SDN controller")
2200 sdn_controller_create_parser.add_argument("--dpid", action="store",
2201 help="DPID of the dataplane switch controlled by this SDN controller")
2202 sdn_controller_create_parser.add_argument("--type", action="store",
2203 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
2204 sdn_controller_create_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
2205 sdn_controller_create_parser.add_argument("--passwd", action="store", dest='password',
2206 help="password credentials for the SDN controller")
2207 sdn_controller_create_parser.set_defaults(func=sdn_controller_create)
2209 # sdn_controller_edit
2210 sdn_controller_edit_parser = subparsers.add_parser('sdn-controller-edit', parents=[parent_parser],
2211 help="Update one or more options of a SDN controller")
2212 sdn_controller_edit_parser.add_argument("name", help="name or uuid of the SDN controller", )
2213 sdn_controller_edit_parser.add_argument("--name", action="store", help="Update the name of the SDN controller",
2215 sdn_controller_edit_parser.add_argument("--description", action="store", help="description of the SDN controller")
2216 sdn_controller_edit_parser.add_argument("--ip", action="store", help="IP of the SDN controller")
2217 sdn_controller_edit_parser.add_argument("--port", action="store", help="Port of the SDN controller")
2218 sdn_controller_edit_parser.add_argument("--dpid", action="store",
2219 help="DPID of the dataplane switch controlled by this SDN controller")
2220 sdn_controller_edit_parser.add_argument("--type", action="store",
2221 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
2222 sdn_controller_edit_parser.add_argument("--user", action="store", help="user credentials for the SDN controller")
2223 sdn_controller_edit_parser.add_argument("--password", action="store",
2224 help="password credentials for the SDN controller", dest='password')
2225 sdn_controller_edit_parser.add_argument("-f", "--force", action="store_true", help="do not prompt for confirmation")
2226 #TODO: include option --file
2227 sdn_controller_edit_parser.set_defaults(func=sdn_controller_edit)
2229 #sdn_controller_list
2230 sdn_controller_list_parser = subparsers.add_parser('sdn-controller-list',
2231 parents=[parent_parser],
2232 help="List the SDN controllers")
2233 sdn_controller_list_parser.add_argument("name", nargs='?', help="name or uuid of the SDN controller")
2234 sdn_controller_list_parser.set_defaults(func=sdn_controller_list)
2236 # sdn_controller_delete
2237 sdn_controller_delete_parser = subparsers.add_parser('sdn-controller-delete',
2238 parents=[parent_parser],
2239 help="Delete the the SDN controller")
2240 sdn_controller_delete_parser.add_argument("name", help="name or uuid of the SDN controller")
2241 sdn_controller_delete_parser.add_argument("-f", "--force", action="store_true", help="forces deletion without asking")
2242 sdn_controller_delete_parser.set_defaults(func=sdn_controller_delete)
2243 # =======================
2245 # WIM ======================= WIM section==================
2248 wim_create_parser = subparsers.add_parser('wim-create',
2249 parents=[parent_parser], help="creates a new wim")
2250 wim_create_parser.add_argument("name", action="store",
2251 help="name for the wim")
2252 wim_create_parser.add_argument("url", action="store",
2253 help="url for the wim")
2254 wim_create_parser.add_argument("--type", action="store",
2255 help="wim type: tapi, onos or odl (default)")
2256 wim_create_parser.add_argument("--config", action="store",
2257 help="additional configuration in json/yaml format")
2258 wim_create_parser.add_argument("--description", action="store",
2259 help="description of the wim")
2260 wim_create_parser.set_defaults(func=wim_create)
2263 wim_delete_parser = subparsers.add_parser('wim-delete',
2264 parents=[parent_parser], help="deletes a wim from the catalogue")
2265 wim_delete_parser.add_argument("name", action="store",
2266 help="name or uuid of the wim to be deleted")
2267 wim_delete_parser.add_argument("-f", "--force", action="store_true",
2268 help="forces deletion without asking")
2269 wim_delete_parser.set_defaults(func=wim_delete)
2272 wim_edit_parser = subparsers.add_parser('wim-edit',
2273 parents=[parent_parser], help="edits a wim")
2274 wim_edit_parser.add_argument("name", help="name or uuid of the wim")
2275 wim_edit_parser.add_argument("--file",
2276 help="json/yaml text or file with the changes")\
2277 .completer = FilesCompleter
2278 wim_edit_parser.add_argument("-f", "--force", action="store_true",
2279 help="do not prompt for confirmation")
2280 wim_edit_parser.set_defaults(func=wim_edit)
2283 wim_list_parser = subparsers.add_parser('wim-list',
2284 parents=[parent_parser],
2285 help="lists information about registered wims")
2286 wim_list_parser.add_argument("name", nargs='?',
2287 help="name or uuid of the wim")
2288 wim_list_parser.add_argument("-a", "--all", action="store_true",
2289 help="shows all wims, not only wims attached to tenant")
2290 wim_list_parser.set_defaults(func=wim_list)
2292 # WIM account create
2293 wim_attach_parser = subparsers.add_parser('wim-account-create', parents=
2294 [parent_parser], help="associates a wim account to the operating tenant")
2295 wim_attach_parser.add_argument("name", help="name or uuid of the wim")
2296 wim_attach_parser.add_argument('--account-name', action='store',
2297 help="specify a name for the wim account.")
2298 wim_attach_parser.add_argument("--user", action="store",
2299 help="user credentials for the wim account")
2300 wim_attach_parser.add_argument("--password", action="store",
2301 help="password credentials for the wim account")
2302 wim_attach_parser.add_argument("--config", action="store",
2303 help="additional configuration in json/yaml format")
2304 wim_attach_parser.set_defaults(func=wim_account_create)
2306 # WIM account delete
2307 wim_detach_parser = subparsers.add_parser('wim-account-delete',
2308 parents=[parent_parser],
2309 help="removes the association "
2310 "between a wim account and the operating tenant")
2311 wim_detach_parser.add_argument("name", help="name or uuid of the wim")
2312 wim_detach_parser.add_argument("-a", "--all", action="store_true",
2313 help="removes all associations from this wim")
2314 wim_detach_parser.add_argument("-f", "--force", action="store_true",
2315 help="forces delete without asking")
2316 wim_detach_parser.set_defaults(func=wim_account_delete)
2319 wim_attach_edit_parser = subparsers.add_parser('wim-account-edit', parents=
2320 [parent_parser], help="modifies the association of a wim account to the operating tenant")
2321 wim_attach_edit_parser.add_argument("name", help="name or uuid of the wim")
2322 wim_attach_edit_parser.add_argument('--account-name', action='store',
2323 help="specify a name for the wim account.")
2324 wim_attach_edit_parser.add_argument("--user", action="store",
2325 help="user credentials for the wim account")
2326 wim_attach_edit_parser.add_argument("--password", action="store",
2327 help="password credentials for the wim account")
2328 wim_attach_edit_parser.add_argument("--config", action="store",
2329 help="additional configuration in json/yaml format")
2330 wim_attach_edit_parser.set_defaults(func=wim_account_edit)
2332 # WIM port mapping set
2333 wim_port_mapping_set_parser = subparsers.add_parser('wim-port-mapping-set',
2334 parents=[parent_parser],
2335 help="Load a file with the mappings "
2336 "of ports of a WAN switch that is "
2337 "connected to a PoP and the ports "
2338 "of the switch controlled by the PoP")
2339 wim_port_mapping_set_parser.add_argument("name", action="store",
2340 help="specifies the wim")
2341 wim_port_mapping_set_parser.add_argument("file",
2342 help="json/yaml text or file with the wim port mapping")\
2343 .completer = FilesCompleter
2344 wim_port_mapping_set_parser.add_argument("-f", "--force",
2345 action="store_true", help="forces overwriting without asking")
2346 wim_port_mapping_set_parser.set_defaults(func=wim_port_mapping_set)
2348 # WIM port mapping list
2349 wim_port_mapping_list_parser = subparsers.add_parser('wim-port-mapping-list',
2350 parents=[parent_parser], help="Show the port mappings for a wim")
2351 wim_port_mapping_list_parser.add_argument("name", action="store",
2352 help="specifies the wim")
2353 wim_port_mapping_list_parser.set_defaults(func=wim_port_mapping_list)
2355 # WIM port mapping clear
2356 wim_port_mapping_clear_parser = subparsers.add_parser('wim-port-mapping-clear',
2357 parents=[parent_parser], help="Clean the port mapping in a wim")
2358 wim_port_mapping_clear_parser.add_argument("name", action="store",
2359 help="specifies the wim")
2360 wim_port_mapping_clear_parser.add_argument("-f", "--force",
2361 action="store_true",
2362 help="forces clearing without asking")
2363 wim_port_mapping_clear_parser.set_defaults(func=wim_port_mapping_clear)
2365 # =======================================================
2367 action_dict={'net-update': 'retrieves external networks from datacenter',
2368 'net-edit': 'edits an external network',
2369 'net-delete': 'deletes an external network',
2370 'net-list': 'lists external networks from a datacenter'
2372 for item in action_dict:
2373 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
2374 datacenter_action_parser.add_argument("datacenter", help="name or uuid of the datacenter")
2375 if item=='net-edit' or item=='net-delete':
2376 datacenter_action_parser.add_argument("net", help="name or uuid of the datacenter net")
2377 if item=='net-edit':
2378 datacenter_action_parser.add_argument("file", help="json/yaml text or file with the changes").completer = FilesCompleter
2379 if item!='net-list':
2380 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2381 datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item)
2384 action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks',
2385 'netmap-create': 'create a new network senario netmap',
2386 'netmap-edit': 'edit name of a network senario netmap',
2387 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
2388 'netmap-list': 'list/show network scenario netmaps'
2390 for item in action_dict:
2391 datacenter_action_parser = subparsers.add_parser('datacenter-'+item, parents=[parent_parser], help=action_dict[item])
2392 datacenter_action_parser.add_argument("--datacenter", help="name or uuid of the datacenter")
2393 #if item=='net-add':
2394 # datacenter_action_parser.add_argument("net", help="name of the network")
2395 if item=='netmap-delete':
2396 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to delete")
2397 datacenter_action_parser.add_argument("--all", action="store_true", help="delete all netmap of this datacenter")
2398 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2399 if item=='netmap-edit':
2400 datacenter_action_parser.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
2401 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file with the changes").completer = FilesCompleter
2402 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap")
2403 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2404 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2405 if item=='netmap-list':
2406 datacenter_action_parser.add_argument("netmap", nargs='?',help="name or uuid of the datacenter netmap to show")
2407 if item=='netmap-create':
2408 datacenter_action_parser.add_argument("file", nargs='?', help="json/yaml text or file descriptor with the changes").completer = FilesCompleter
2409 datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name")
2410 datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid")
2411 datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name")
2412 if item=='netmap-import':
2413 datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation")
2414 datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item)
2416 # =======================vim_net_sdn_xxx section=======================
2417 # vim_net_sdn_attach
2418 vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach',
2419 parents=[parent_parser],
2420 help="Specify the port to access to an external network using SDN")
2421 vim_net_sdn_attach_parser.add_argument("vim_net", action="store",
2422 help="Name/id of the network in the vim that will be used to connect to the external network")
2423 vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network")
2424 vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port")
2425 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")
2426 vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2427 vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach)
2429 # vim_net_sdn_detach
2430 vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach',
2431 parents=[parent_parser],
2432 help="Remove the port information to access to an external network using SDN")
2434 vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network")
2435 vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached")
2436 vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network")
2437 vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking")
2438 vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2439 vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach)
2440 # =======================
2442 for item in ("network", "tenant", "image"):
2444 command_name = 'vim-net'
2446 command_name = 'vim-'+item
2447 vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s")
2448 vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s")
2449 vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2450 vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list")
2452 vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s")
2453 vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s")
2454 vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2455 vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete")
2457 if item == "network" or item == "tenant":
2458 vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim")
2459 vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter
2460 vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item )
2461 vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")
2463 vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge")
2464 vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared")
2465 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>'")
2467 vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item)
2468 vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create")
2470 argcomplete.autocomplete(main_parser)
2473 args = main_parser.parse_args()
2475 level = logging.CRITICAL
2476 streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s"
2477 if "debug" in args and args.debug:
2478 level = logging.DEBUG
2479 logging.basicConfig(format=streamformat, level= level)
2480 logger = logging.getLogger('mano')
2481 logger.setLevel(level)
2482 result = args.func(args)
2485 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2486 except (requests.exceptions.ConnectionError):
2487 print "Connection error: not possible to contact OPENMANO-SERVER (openmanod)"
2489 except (KeyboardInterrupt):
2490 print 'Exiting openmano'
2492 except (SystemExit, ArgumentParserError):
2494 except OpenmanoCLIError as e: