2 # -*- coding: utf-8 -*-
3 # PYTHON_ARGCOMPLETE_OK
6 # Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
7 # This file is part of openmano
10 # Licensed under the Apache License, Version 2.0 (the "License"); you may
11 # not use this file except in compliance with the License. You may obtain
12 # a copy of the License at
14 # http://www.apache.org/licenses/LICENSE-2.0
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19 # License for the specific language governing permissions and limitations
22 # For those usages not covered by the Apache License, Version 2.0 please
23 # contact with: nfvlabs@tid.es
27 openmano client used to interact with openmano-server (openmanod)
29 __author__
= "Alfonso Tierno, Gerardo Garcia, Pablo Montes"
30 __date__
= "$09-oct-2014 09:09:48$"
32 version_date
= "2019-010-04"
34 from argcomplete
.completers
import FilesCompleter
42 #from jsonschema import validate as js_v, exceptions as js_e
45 class ArgumentParserError(Exception):
49 class OpenmanoCLIError(Exception):
53 class ThrowingArgumentParser(argparse
.ArgumentParser
):
54 def error(self
, message
):
55 print("Error: {}".format(message
))
60 print("Type 'openmano -h' for help")
61 raise ArgumentParserError
65 print("OPENMANO_HOST: {}".format(mano_host
))
66 print("OPENMANO_PORT: {}".format(mano_port
))
68 logger
.debug("resolving tenant and datacenter names")
69 mano_tenant_id
= "None"
70 mano_tenant_name
= "None"
71 mano_datacenter_id
= "None"
72 mano_datacenter_name
= "None"
74 logger
.debug("resolving WIM names")
76 mano_wim_name
= "None"
78 mano_tenant_id
= _get_item_uuid("tenants", mano_tenant
)
79 URLrequest
= "http://{}:{}/openmano/tenants/{}".format(mano_host
, mano_port
, mano_tenant_id
)
80 mano_response
= requests
.get(URLrequest
)
81 logger
.debug("openmano response: %s", mano_response
.text
)
82 content
= mano_response
.json()
83 mano_tenant_name
= content
["tenant"]["name"]
84 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}".format(mano_host
, mano_port
, mano_tenant_id
,
86 mano_response
= requests
.get(URLrequest
)
87 logger
.debug("openmano response: %s", mano_response
.text
)
88 content
= mano_response
.json()
89 if "error" not in content
:
90 mano_datacenter_id
= content
["datacenter"]["uuid"]
91 mano_datacenter_name
= content
["datacenter"]["name"]
94 URLrequest
= "http://{}:{}/openmano/{}/wims/{}".format(
95 mano_host
, mano_port
, mano_tenant_id
, mano_wim
)
96 mano_response
= requests
.get(URLrequest
)
97 logger
.debug("openmano response: %s", mano_response
.text
)
98 content
= mano_response
.json()
99 if "error" not in content
:
100 mano_wim_id
= content
["wim"]["uuid"]
101 mano_wim_name
= content
["wim"]["name"]
103 except OpenmanoCLIError
:
105 print( "OPENMANO_TENANT: {}".format(mano_tenant
))
106 print( " Id: {}".format(mano_tenant_id
))
107 print( " Name: {}".format(mano_tenant_name
))
108 print( "OPENMANO_DATACENTER: {}".format(mano_datacenter
))
109 print( " Id: {}".format(mano_datacenter_id
))
110 print( " Name: {}".format(mano_datacenter_name
))
112 print( "OPENMANO_WIM: {}".format( (mano_wim
)))
113 print( " Id: {}".format(mano_wim_id
))
114 print( " Name: {}".format(mano_wim_name
))
117 print("OPENMANO_TENANT: {}".format(mano_tenant
))
118 print("OPENMANO_DATACENTER: {}".format(mano_datacenter
))
120 print("OPENMANO_WIM: {}".format(mano_wim
))
122 def _print_verbose(mano_response
, verbose_level
=0):
123 content
= mano_response
.json()
124 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
125 if type(content
)!=dict or len(content
)!=1:
126 # print("Non expected format output")
130 val
= next(iter(content
.values()))
134 elif type(val
) == list:
136 elif type(val
)==dict:
139 # print("Non expected dict/list format output"
144 if verbose_level
==None:
146 if verbose_level
>= 3:
147 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
150 if mano_response
.status_code
== 200:
152 for content
in content_list
:
153 if "uuid" in content
:
154 uuid
= content
['uuid']
155 elif "id" in content
:
157 elif "vim_id" in content
:
158 uuid
= content
['vim_id']
159 name
= content
.get('name');
164 myoutput
= "{:38} {:20}".format(uuid
, name
)
165 if content
.get("status"):
166 myoutput
+= " {:20}".format(content
['status'])
167 elif "enabled" in content
and not content
["enabled"]:
168 myoutput
+= " enabled=False".ljust(20)
169 if verbose_level
>=1:
170 if content
.get('created_at'):
171 myoutput
+= " {:20}".format(content
['created_at'])
172 if content
.get('sdn_attached_ports'):
173 #myoutput += " " + str(content['sdn_attached_ports']).ljust(20)
174 myoutput
+= "\nsdn_attached_ports:\n" + yaml
.safe_dump(content
['sdn_attached_ports'], indent
=4, default_flow_style
=False)
175 if verbose_level
>=2:
177 if content
.get('type'):
178 myoutput
+= new_line
+ " Type: {:29}".format(content
['type'])
180 if content
.get('description'):
181 myoutput
+= new_line
+ " Description: {:20}".format(content
['description'])
184 print(content
['error']['description'])
187 def parser_json_yaml(file_name
):
189 with
open(file_name
, "r") as f
:
191 except Exception as e
:
192 return (False, str(e
))
195 if file_name
[-5:]=='.yaml' or file_name
[-4:]=='.yml' or (file_name
[-5:]!='.json' and '\t' not in text
):
197 config
= yaml
.load(text
, Loader
=yaml
.SafeLoader
)
198 except yaml
.YAMLError
as exc
:
200 if hasattr(exc
, 'problem_mark'):
201 mark
= exc
.problem_mark
202 error_pos
= " at line:{} column:{}".format(mark
.line
+1, mark
.column
+1)
203 return (False, "Error loading file '"+file_name
+"' yaml format error" + error_pos
)
206 config
= json
.loads(text
)
207 except Exception as e
:
208 return (False, "Error loading file '"+file_name
+"' json format error " + str(e
) )
211 def _load_file_or_yaml(content
):
213 'content' can be or a yaml/json file or a text containing a yaml/json text format
214 This function autodetect, trying to load and parse the file,
215 if fails trying to parse the 'content' text
216 Returns the dictionary once parsed, or print an error and finish the program
218 #Check config file exists
219 if os
.path
.isfile(content
):
220 r
,payload
= parser_json_yaml(content
)
224 elif "{" in content
or ":" in content
:
226 payload
= yaml
.load(content
)
227 except yaml
.YAMLError
as exc
:
229 if hasattr(exc
, 'problem_mark'):
230 mark
= exc
.problem_mark
231 error_pos
= " at position: ({}:{})".format(mark
.line
+1, mark
.column
+1)
232 print("Error loading yaml/json text"+error_pos
)
235 print("'{}' is neither a valid file nor a yaml/json content".format(content
))
239 def _get_item_uuid(item
, item_name_id
, tenant
=None):
241 URLrequest
= "http://{}:{}/openmano/{}/{}".format(mano_host
, mano_port
, tenant
, item
)
243 URLrequest
= "http://{}:{}/openmano/{}".format(mano_host
, mano_port
, item
)
244 mano_response
= requests
.get(URLrequest
)
245 logger
.debug("openmano response: %s", mano_response
.text
)
246 content
= mano_response
.json()
249 for i
in content
[item
]:
250 if i
["uuid"] == item_name_id
:
252 if i
["name"] == item_name_id
:
255 if item_name_id
.startswith("osm_id=") and i
.get("osm_id") == item_name_id
[7:]:
259 raise OpenmanoCLIError("No {} found with name/uuid '{}'".format(item
[:-1], item_name_id
))
261 raise OpenmanoCLIError("{} {} found with name '{}'. uuid must be used".format(found
, item
, item_name_id
))
264 # def check_valid_uuid(uuid):
265 # id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
267 # js_v(uuid, id_schema)
269 # except js_e.ValidationError:
272 def _get_tenant(tenant_name_id
= None):
273 if not tenant_name_id
:
274 tenant_name_id
= mano_tenant
276 raise OpenmanoCLIError("'OPENMANO_TENANT' environment variable is not set")
277 return _get_item_uuid("tenants", tenant_name_id
)
279 def _get_datacenter(datacenter_name_id
= None, tenant
= "any"):
280 if not datacenter_name_id
:
281 datacenter_name_id
= mano_datacenter
282 if not datacenter_name_id
:
283 raise OpenmanoCLIError("neither 'OPENMANO_DATACENTER' environment variable is set nor --datacenter option is used")
284 return _get_item_uuid("datacenters", datacenter_name_id
, tenant
)
287 def _get_wim(wim_name_id
= None, tenant
= "any"):
289 wim_name_id
= mano_wim
291 raise OpenmanoCLIError("neither 'OPENMANO_WIM' environment variable is set nor --wim option is used")
292 return _get_item_uuid("wims", wim_name_id
, tenant
)
294 def vnf_create(args
):
295 # print("vnf-create", args)
296 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
297 tenant
= _get_tenant()
298 myvnf
= _load_file_or_yaml(args
.file)
301 if "vnfd:vnfd-catalog" in myvnf
or "vnfd-catalog" in myvnf
:
304 vnfd_catalog
= myvnf
.get("vnfd:vnfd-catalog")
306 vnfd_catalog
= myvnf
.get("vnfd-catalog")
307 vnfds
= vnfd_catalog
.get("vnfd:vnfd")
309 vnfds
= vnfd_catalog
.get("vnfd")
311 vdu_list
= vnfd
.get("vdu")
317 vdu_list
= vnfd
.get("VNFC")
319 if args
.name
or args
.description
or args
.image_path
or args
.image_name
or args
.image_checksum
:
320 # TODO, change this for API v3
324 vnfd
['name'] = args
.name
326 vnfd
['description'] = args
.description
330 for image_path_
in args
.image_path
.split(","):
331 # print("image-path", image_path_)
332 if api_version
== "/v3":
333 if vdu_list
[index
].get("image"):
334 vdu_list
[index
]['image'] = image_path_
335 if "image-checksum" in vdu_list
[index
]:
336 del vdu_list
[index
]["image-checksum"]
337 else: # image name in volumes
338 vdu_list
[index
]["volumes"][0]["image"] = image_path_
339 if "image-checksum" in vdu_list
[index
]["volumes"][0]:
340 del vdu_list
[index
]["volumes"][0]["image-checksum"]
342 vdu_list
[index
]['VNFC image'] = image_path_
343 if "image name" in vdu_list
[index
]:
344 del vdu_list
[index
]["image name"]
345 if "image checksum" in vdu_list
[index
]:
346 del vdu_list
[index
]["image checksum"]
348 if args
.image_name
: # image name precedes if both are supplied
350 for image_name_
in args
.image_name
.split(","):
351 if api_version
== "/v3":
352 if vdu_list
[index
].get("image"):
353 vdu_list
[index
]['image'] = image_name_
354 if "image-checksum" in vdu_list
[index
]:
355 del vdu_list
[index
]["image-checksum"]
356 if vdu_list
[index
].get("alternative-images"):
357 for a_image
in vdu_list
[index
]["alternative-images"]:
358 a_image
['image'] = image_name_
359 if "image-checksum" in a_image
:
360 del a_image
["image-checksum"]
361 else: # image name in volumes
362 vdu_list
[index
]["volumes"][0]["image"] = image_name_
363 if "image-checksum" in vdu_list
[index
]["volumes"][0]:
364 del vdu_list
[index
]["volumes"][0]["image-checksum"]
366 vdu_list
[index
]['image name'] = image_name_
367 if "VNFC image" in vdu_list
[index
]:
368 del vdu_list
[index
]["VNFC image"]
370 if args
.image_checksum
:
372 for image_checksum_
in args
.image_checksum
.split(","):
373 if api_version
== "/v3":
374 if vdu_list
[index
].get("image"):
375 vdu_list
[index
]['image-checksum'] = image_checksum_
376 if vdu_list
[index
].get("alternative-images"):
377 for a_image
in vdu_list
[index
]["alternative-images"]:
378 a_image
['image-checksum'] = image_checksum_
379 else: # image name in volumes
380 vdu_list
[index
]["volumes"][0]["image-checksum"] = image_checksum_
382 vdu_list
[index
]['image checksum'] = image_checksum_
384 except (KeyError, TypeError) as e
:
385 if str(e
) == 'vnf': error_pos
= "missing field 'vnf'"
386 elif str(e
) == 'name': error_pos
= "missing field 'vnf':'name'"
387 elif str(e
) == 'description': error_pos
= "missing field 'vnf':'description'"
388 elif str(e
) == 'VNFC': error_pos
= "missing field 'vnf':'VNFC'"
389 elif str(e
) == str(index
): error_pos
= "field 'vnf':'VNFC' must be an array"
390 elif str(e
) == 'VNFC image': error_pos
= "missing field 'vnf':'VNFC'['VNFC image']"
391 elif str(e
) == 'image name': error_pos
= "missing field 'vnf':'VNFC'['image name']"
392 elif str(e
) == 'image checksum': error_pos
= "missing field 'vnf':'VNFC'['image checksum']"
393 else: error_pos
="wrong format"
394 print("Wrong VNF descriptor: " + error_pos
)
396 payload_req
= json
.dumps(myvnf
)
400 URLrequest
= "http://{}:{}/openmano{}/{}/{token}".format(mano_host
, mano_port
, api_version
, tenant
, token
=token
)
401 logger
.debug("openmano request: %s", payload_req
)
402 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
403 logger
.debug("openmano response: %s", mano_response
.text
)
405 return _print_verbose(mano_response
, args
.verbose
)
408 # print("vnf-list",args
412 tenant
= _get_tenant()
414 toshow
= _get_item_uuid("vnfs", args
.name
, tenant
)
415 URLrequest
= "http://{}:{}/openmano/{}/vnfs/{}".format(mano_host
, mano_port
, tenant
, toshow
)
417 URLrequest
= "http://{}:{}/openmano/{}/vnfs".format(mano_host
, mano_port
, tenant
)
418 mano_response
= requests
.get(URLrequest
)
419 logger
.debug("openmano response: %s", mano_response
.text
)
420 content
= mano_response
.json()
421 # print(json.dumps(content, indent=4)
422 if args
.verbose
==None:
424 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
425 if mano_response
.status_code
== 200:
427 if args
.verbose
>= 3:
428 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
430 if len(content
['vnfs']) == 0:
431 print("No VNFs were found.")
432 return 404 # HTTP_Not_Found
433 for vnf
in content
['vnfs']:
434 myoutput
= "{:38} {:20}".format(vnf
['uuid'], vnf
['name'])
435 if vnf
.get('osm_id') or args
.verbose
>= 1:
436 myoutput
+= " osm_id={:20}".format(vnf
.get('osm_id'))
437 if args
.verbose
>= 1:
438 myoutput
+= " {}".format(vnf
['created_at'])
440 if args
.verbose
>= 2:
441 print(" Description: {}".format(vnf
['description']))
442 # print(" VNF descriptor file: {}".format(vnf['path']))
445 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
448 print("{:38} {:20} osm_id={:20} {:20}".format(vnf
['uuid'], vnf
['name'], vnf
.get('osm_id'),
449 vnf
['created_at']), end
=" ")
450 print(" Description: {}".format(vnf
['description']))
451 # print(" VNF descriptor file: {}".format(vnf['path']))
453 for vm
in vnf
['VNFC']:
454 print(" {:20} osm_id={:20} {}".format(vm
['name'], vm
.get('osm_id'), vm
['description']))
455 if len(vnf
['nets']) > 0:
456 print(" Internal nets:")
457 for net
in vnf
['nets']:
458 print(" {:20} {}".format(net
['name'], net
['description']))
459 if len(vnf
['external-connections']) > 0:
460 print(" External interfaces:")
461 for interface
in vnf
['external-connections']:
462 print(" {:20} {:20} {:20} {:14}".format(
463 interface
['external_name'], interface
['vm_name'],
464 interface
['internal_name'],
465 interface
.get('vpci') if interface
.get('vpci') else ""))
467 print(content
['error']['description'])
469 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
472 def vnf_delete(args
):
473 # print("vnf-delete",args
477 tenant
= _get_tenant()
478 todelete
= _get_item_uuid("vnfs", args
.name
, tenant
=tenant
)
480 r
= input("Delete VNF {} (y/N)? ".format(todelete
))
481 if not (len(r
)>0 and r
[0].lower()=="y"):
483 URLrequest
= "http://{}:{}/openmano/{}/vnfs/{}".format(mano_host
, mano_port
, tenant
, todelete
)
484 mano_response
= requests
.delete(URLrequest
)
485 logger
.debug("openmano response: %s", mano_response
.text
)
486 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
487 content
= mano_response
.json()
488 # print(json.dumps(content, indent=4))
489 if mano_response
.status_code
== 200:
490 print(content
['result'])
492 print(content
['error']['description'])
495 def scenario_create(args
):
496 # print("scenario-create",args
497 tenant
= _get_tenant()
498 headers_req
= {'content-type': 'application/yaml'}
499 myscenario
= _load_file_or_yaml(args
.file)
500 if "nsd:nsd-catalog" in myscenario
or "nsd-catalog" in myscenario
:
503 nsd_catalog
= myscenario
.get("nsd:nsd-catalog")
505 nsd_catalog
= myscenario
.get("nsd-catalog")
506 nsds
= nsd_catalog
.get("nsd:nsd")
508 nsds
= nsd_catalog
.get("nsd")
513 if "scenario" in myscenario
:
514 nsd
= myscenario
["scenario"]
517 # TODO modify for API v3
519 nsd
['name'] = args
.name
521 nsd
['description'] = args
.description
522 payload_req
= yaml
.safe_dump(myscenario
, explicit_start
=True, indent
=4, default_flow_style
=False, tags
=False,
526 URLrequest
= "http://{host}:{port}/openmano{api}/{tenant}/{token}".format(
527 host
=mano_host
, port
=mano_port
, api
=api_version
, tenant
=tenant
, token
=token
)
528 logger
.debug("openmano request: %s", payload_req
)
529 mano_response
= requests
.post(URLrequest
, headers
= headers_req
, data
=payload_req
)
530 logger
.debug("openmano response: %s", mano_response
.text
)
531 return _print_verbose(mano_response
, args
.verbose
)
533 def scenario_list(args
):
534 # print("scenario-list",args
538 tenant
= _get_tenant()
540 toshow
= _get_item_uuid("scenarios", args
.name
, tenant
)
541 URLrequest
= "http://{}:{}/openmano/{}/scenarios/{}".format(mano_host
, mano_port
, tenant
, toshow
)
543 URLrequest
= "http://{}:{}/openmano/{}/scenarios".format(mano_host
, mano_port
, tenant
)
544 mano_response
= requests
.get(URLrequest
)
545 logger
.debug("openmano response: %s", mano_response
.text
)
546 content
= mano_response
.json()
547 # print(json.dumps(content, indent=4)
548 if args
.verbose
==None:
551 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
552 if mano_response
.status_code
== 200:
554 if args
.verbose
>= 3:
555 print( yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
557 if len(content
['scenarios']) == 0:
558 print( "No scenarios were found.")
559 return 404 #HTTP_Not_Found
560 for scenario
in content
['scenarios']:
561 myoutput
= "{:38} {:20}".format(scenario
['uuid'], scenario
['name'])
562 if scenario
.get('osm_id') or args
.verbose
>= 1:
563 myoutput
+= " osm_id={:20}".format(scenario
.get('osm_id'))
564 if args
.verbose
>= 1:
565 myoutput
+= " {}".format(scenario
['created_at'])
568 print(" Description: {}".format(scenario
['description']))
571 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
573 scenario
= content
['scenario']
574 print("{:38} {:20} osm_id={:20} {:20}".format(scenario
['uuid'], scenario
['name'], scenario
.get('osm_id'),
575 scenario
['created_at']), end
=" ")
576 print(" Description: {}".format(scenario
['description']))
578 for vnf
in scenario
['vnfs']:
579 print(" {:38} {:20} vnf_index={} {}".format(vnf
['vnf_id'], vnf
['name'], vnf
.get("member_vnf_index"),
581 if len(scenario
['nets']) > 0:
583 for net
in scenario
['nets']:
584 description
= net
['description']
585 if not description
: # if description does not exist, description is "-". Valid for external and internal nets.
588 if net
.get('vim_id'):
589 vim_id
= " vim_id=" + net
["vim_id"]
592 external
= " external"
593 print(" {:20} {:38} {:30}{}{}".format(net
['name'], net
['uuid'], description
, vim_id
, external
))
595 print(content
['error']['description'])
597 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
600 def scenario_delete(args
):
601 # print("scenario-delete",args
605 tenant
= _get_tenant()
606 todelete
= _get_item_uuid("scenarios", args
.name
, tenant
=tenant
)
608 r
= input("Delete scenario {} (y/N)? ".format(args
.name
))
609 if not (len(r
)>0 and r
[0].lower()=="y"):
611 URLrequest
= "http://{}:{}/openmano/{}/scenarios/{}".format(mano_host
, mano_port
, tenant
, todelete
)
612 mano_response
= requests
.delete(URLrequest
)
613 logger
.debug("openmano response: %s", mano_response
.text
)
614 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
615 content
= mano_response
.json()
616 # print(json.dumps(content, indent=4)
617 if mano_response
.status_code
== 200:
618 print( content
['result'])
620 print( content
['error']['description'])
623 def scenario_deploy(args
):
624 print("This command is deprecated, use 'openmano instance-scenario-create --scenario {} --name {}' instead!!!".format(args
.scenario
, args
.name
))
627 args
.netmap_use
= None
628 args
.netmap_create
= None
630 args
.keypair_auto
= None
631 return instance_create(args
)
633 # # print("scenario-deploy",args
634 # headers_req = {'content-type': 'application/json'}
638 # actionCmd="reserve"
639 # action[actionCmd] = {}
640 # action[actionCmd]["instance_name"] = args.name
641 # if args.datacenter != None:
642 # action[actionCmd]["datacenter"] = args.datacenter
643 # elif mano_datacenter != None:
644 # action[actionCmd]["datacenter"] = mano_datacenter
646 # if args.description:
647 # action[actionCmd]["description"] = args.description
648 # payload_req = json.dumps(action, indent=4)
649 # # print(payload_req
651 # URLrequest = "http://{}:{}/openmano/{}/scenarios/{}/action".format(mano_host, mano_port, mano_tenant, args.scenario)
652 # logger.debug("openmano request: %s", payload_req)
653 # mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req)
654 # logger.debug("openmano response: %s", mano_response.text )
655 # if args.verbose==None:
658 # result = 0 if mano_response.status_code==200 else mano_response.status_code
659 # content = mano_response.json()
660 # # print(json.dumps(content, indent=4))
661 # if args.verbose >= 3:
662 # print(yaml.safe_dump(content, indent=4, default_flow_style=False))
665 # if mano_response.status_code == 200:
666 # myoutput = "{} {}".format(content['uuid'].ljust(38),content['name'].ljust(20))
667 # if args.verbose >=1:
668 # myoutput = "{} {}".format(myoutput, content['created_at'].ljust(20))
669 # if args.verbose >=2:
670 # myoutput = "{} {} {}".format(myoutput, content['description'].ljust(30))
673 # print("To check the status, run the following command:")
674 # print("openmano instance-scenario-list <instance_id>"
676 # print(content['error']['description'])
679 def scenario_verify(args
):
680 # print("scenario-verify",args)
681 tenant
= _get_tenant()
682 headers_req
= {'content-type': 'application/json'}
684 action
["verify"] = {}
685 action
["verify"]["instance_name"] = "scen-verify-return5"
686 payload_req
= json
.dumps(action
, indent
=4)
689 URLrequest
= "http://{}:{}/openmano/{}/scenarios/{}/action".format(mano_host
, mano_port
, tenant
, args
.scenario
)
690 logger
.debug("openmano request: %s", payload_req
)
691 mano_response
= requests
.post(URLrequest
, headers
= headers_req
, data
=payload_req
)
692 logger
.debug("openmano response: %s", mano_response
.text
)
694 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
695 content
= mano_response
.json()
696 # print(json.dumps(content, indent=4))
697 if mano_response
.status_code
== 200:
698 print(content
['result'])
700 print(content
['error']['description'])
703 def instance_create(args
):
704 tenant
= _get_tenant()
705 headers_req
= {'content-type': 'application/yaml'}
706 myInstance
={"instance": {}, "schema_version": "0.1"}
708 instance_dict
= _load_file_or_yaml(args
.file)
709 if "instance" not in instance_dict
:
710 myInstance
= {"instance": instance_dict
, "schema_version": "0.1"}
712 myInstance
= instance_dict
714 myInstance
["instance"]['name'] = args
.name
716 myInstance
["instance"]['description'] = args
.description
718 myInstance
["instance"]['action'] = "reserve"
720 datacenter
= myInstance
["instance"].get("datacenter")
721 if args
.datacenter
!= None:
722 datacenter
= args
.datacenter
723 myInstance
["instance"]["datacenter"] = _get_datacenter(datacenter
, tenant
)
725 scenario
= myInstance
["instance"].get("scenario")
726 if args
.scenario
!= None:
727 scenario
= args
.scenario
729 print("you must provide a scenario in the file descriptor or with --scenario")
731 if isinstance(scenario
, str):
732 myInstance
["instance"]["scenario"] = _get_item_uuid("scenarios", scenario
, tenant
)
734 if "networks" not in myInstance
["instance"]:
735 myInstance
["instance"]["networks"] = {}
736 for net
in args
.netmap_use
:
737 net_comma_list
= net
.split(",")
738 for net_comma
in net_comma_list
:
739 net_tuple
= net_comma
.split("=")
740 if len(net_tuple
) != 2:
741 print("error at netmap-use. Expected net-scenario=net-datacenter. ({})?".format(net_comma
))
743 net_scenario
= net_tuple
[0].strip()
744 net_datacenter
= net_tuple
[1].strip()
745 if net_scenario
not in myInstance
["instance"]["networks"]:
746 myInstance
["instance"]["networks"][net_scenario
] = {}
747 if "sites" not in myInstance
["instance"]["networks"][net_scenario
]:
748 myInstance
["instance"]["networks"][net_scenario
]["sites"] = [ {} ]
749 myInstance
["instance"]["networks"][net_scenario
]["sites"][0]["netmap-use"] = net_datacenter
750 if args
.netmap_create
:
751 if "networks" not in myInstance
["instance"]:
752 myInstance
["instance"]["networks"] = {}
753 for net
in args
.netmap_create
:
754 net_comma_list
= net
.split(",")
755 for net_comma
in net_comma_list
:
756 net_tuple
= net_comma
.split("=")
757 if len(net_tuple
) == 1:
758 net_scenario
= net_tuple
[0].strip()
759 net_datacenter
= None
760 elif len(net_tuple
) == 2:
761 net_scenario
= net_tuple
[0].strip()
762 net_datacenter
= net_tuple
[1].strip()
764 print("error at netmap-create. Expected net-scenario=net-datacenter or net-scenario. ({})?".format(
767 if net_scenario
not in myInstance
["instance"]["networks"]:
768 myInstance
["instance"]["networks"][net_scenario
] = {}
769 if "sites" not in myInstance
["instance"]["networks"][net_scenario
]:
770 myInstance
["instance"]["networks"][net_scenario
]["sites"] = [ {} ]
771 myInstance
["instance"]["networks"][net_scenario
]["sites"][0]["netmap-create"] = net_datacenter
773 if "cloud-config" not in myInstance
["instance"]:
774 myInstance
["instance"]["cloud-config"] = {}
775 cloud_config
= myInstance
["instance"]["cloud-config"]
776 for key
in args
.keypair
:
777 index
= key
.find(":")
779 if "key-pairs" not in cloud_config
:
780 cloud_config
["key-pairs"] = []
781 cloud_config
["key-pairs"].append(key
)
785 key_list
= key_
.split(",")
786 if "users" not in cloud_config
:
787 cloud_config
["users"] = []
788 cloud_config
["users"].append({"name": user
, "key-pairs": key_list
})
789 if args
.keypair_auto
:
792 home
= os
.getenv("HOME")
793 user
= os
.getenv("USER")
794 files
= os
.listdir(home
+'/.ssh')
796 if file[-4:] == ".pub":
797 with
open(home
+'/.ssh/'+file, 'r') as f
:
798 keys
.append(f
.read())
800 print("Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home
+'/.ssh'))
802 except Exception as e
:
803 print("Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e
)))
806 if "cloud-config" not in myInstance
["instance"]:
807 myInstance
["instance"]["cloud-config"] = {}
808 cloud_config
= myInstance
["instance"]["cloud-config"]
809 if "key-pairs" not in cloud_config
:
810 cloud_config
["key-pairs"] = []
812 if "users" not in cloud_config
:
813 cloud_config
["users"] = []
814 cloud_config
["users"].append({"name": user
, "key-pairs": keys
})
816 payload_req
= yaml
.safe_dump(myInstance
, explicit_start
=True, indent
=4, default_flow_style
=False, tags
=False,
818 logger
.debug("openmano request: %s", payload_req
)
819 URLrequest
= "http://{}:{}/openmano/{}/instances".format(mano_host
, mano_port
, tenant
)
820 mano_response
= requests
.post(URLrequest
, headers
= headers_req
, data
=payload_req
)
821 logger
.debug("openmano response: %s", mano_response
.text
)
822 if args
.verbose
==None:
825 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
826 content
= mano_response
.json()
827 # print(json.dumps(content, indent=4))
828 if args
.verbose
>= 3:
829 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
832 if mano_response
.status_code
== 200:
833 myoutput
= "{:38} {:20}".format(content
['uuid'], content
['name'])
835 myoutput
= "{} {:20}".format(myoutput
, content
['created_at'])
837 myoutput
= "{} {:30}".format(myoutput
, content
['description'])
840 print(content
['error']['description'])
843 def instance_scenario_list(args
):
844 # print("instance-scenario-list",args)
848 tenant
= _get_tenant()
850 toshow
= _get_item_uuid("instances", args
.name
, tenant
)
851 URLrequest
= "http://{}:{}/openmano/{}/instances/{}".format(mano_host
, mano_port
, tenant
, toshow
)
853 URLrequest
= "http://{}:{}/openmano/{}/instances".format(mano_host
, mano_port
, tenant
)
854 mano_response
= requests
.get(URLrequest
)
855 logger
.debug("openmano response: %s", mano_response
.text
)
856 content
= mano_response
.json()
857 # print(json.dumps(content, indent=4)
858 if args
.verbose
==None:
861 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
862 if mano_response
.status_code
== 200:
864 if args
.verbose
>= 3:
865 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
867 if len(content
['instances']) == 0:
868 print("No scenario instances were found.")
870 for instance
in content
['instances']:
871 myoutput
= "{:38} {:20}".format(instance
['uuid'], instance
['name'])
873 myoutput
= "{} {:20}".format(myoutput
, instance
['created_at'])
876 print("Description: {}".format(instance
['description']))
879 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
882 print("{:38} {:20} {:20}".format(instance
['uuid'],instance
['name'],instance
['created_at']))
883 print("Description: {}".format(instance
['description']))
884 print("Template scenario id: {}".format(instance
['scenario_id']))
885 print("Template scenario name: {}".format(instance
['scenario_name']))
886 print("---------------------------------------")
887 print("VNF instances: {}".format(len(instance
['vnfs'])))
888 for vnf
in instance
['vnfs']:
889 # print(" {} {} Template vnf name: {} Template vnf id: {}".format(vnf['uuid'].ljust(38), vnf['name'].ljust(20), vnf['vnf_name'].ljust(20), vnf['vnf_id'].ljust(38))
890 print(" {:38} {:20} Template vnf id: {:38}".format(vnf
['uuid'], vnf
['vnf_name'], vnf
['vnf_id']))
891 if len(instance
['nets'])>0:
892 print("---------------------------------------")
893 print("Internal nets:")
894 for net
in instance
['nets']:
896 print(" {:38} {:12} VIM ID: {}".format(net
['uuid'], net
['status'], net
['vim_net_id']))
897 print("---------------------------------------")
898 print("External nets:")
899 for net
in instance
['nets']:
900 if not net
['created']:
901 print(" {:38} {:12} VIM ID: {}".format(net
['uuid'], net
['status'], net
['vim_net_id']))
902 print("---------------------------------------")
903 print("VM instances:")
904 for vnf
in instance
['vnfs']:
905 for vm
in vnf
['vms']:
906 print(" {:38} {:20} {:20} {:12} VIM ID: {}".format(vm
['uuid'], vnf
['vnf_name'], vm
['name'],
907 vm
['status'], vm
['vim_vm_id']))
909 print(content
['error']['description'])
911 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
914 def instance_scenario_status(args
):
915 print("instance-scenario-status")
918 def instance_scenario_delete(args
):
922 tenant
= _get_tenant()
923 todelete
= _get_item_uuid("instances", args
.name
, tenant
=tenant
)
924 # print("instance-scenario-delete",args)
926 r
= input("Delete scenario instance {} (y/N)? ".format(args
.name
))
927 if not (len(r
)>0 and r
[0].lower()=="y"):
929 URLrequest
= "http://{}:{}/openmano/{}/instances/{}".format(mano_host
, mano_port
, tenant
, todelete
)
930 mano_response
= requests
.delete(URLrequest
)
931 logger
.debug("openmano response: %s", mano_response
.text
)
932 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
933 content
= mano_response
.json()
934 # print(json.dumps(content, indent=4))
935 if mano_response
.status_code
== 200:
936 print(content
['result'])
938 print(content
['error']['description'])
941 def get_action(args
):
943 tenant
= _get_tenant()
946 if not args
.instance
:
949 instance_id
=args
.instance
952 action_id
= "/" + args
.id
953 URLrequest
= "http://{}:{}/openmano/{}/instances/{}/action{}".format(mano_host
, mano_port
, tenant
, instance_id
,
955 mano_response
= requests
.get(URLrequest
)
956 logger
.debug("openmano response: %s", mano_response
.text
)
957 if args
.verbose
== None:
961 return _print_verbose(mano_response
, args
.verbose
)
963 def instance_scenario_action(args
):
964 # print("instance-scenario-action", args)
965 tenant
= _get_tenant()
966 toact
= _get_item_uuid("instances", args
.name
, tenant
=tenant
)
968 action
[ args
.action
] = yaml
.safe_load(args
.param
)
970 action
["vnfs"] = args
.vnf
972 action
["vms"] = args
.vm
974 headers_req
= {'content-type': 'application/json'}
975 payload_req
= json
.dumps(action
, indent
=4)
976 URLrequest
= "http://{}:{}/openmano/{}/instances/{}/action".format(mano_host
, mano_port
, tenant
, toact
)
977 logger
.debug("openmano request: %s", payload_req
)
978 mano_response
= requests
.post(URLrequest
, headers
= headers_req
, data
=payload_req
)
979 logger
.debug("openmano response: %s", mano_response
.text
)
980 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
981 content
= mano_response
.json()
982 # print(json.dumps(content, indent=4))
983 if mano_response
.status_code
== 200:
985 print(yaml
.safe_dump(content
, indent
=4, default_flow_style
=False))
987 if "instance_action_id" in content
:
988 print("instance_action_id={}".format(content
["instance_action_id"]))
990 for uuid
,c
in content
.items():
991 print("{:38} {:20} {:20}".format(uuid
, c
.get('name'), c
.get('description')))
993 print(content
['error']['description'])
997 def instance_vnf_list(args
):
998 print("instance-vnf-list")
1001 def instance_vnf_status(args
):
1002 print("instance-vnf-status")
1005 def tenant_create(args
):
1006 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1007 tenant_dict
={"name": args
.name
}
1008 if args
.description
!=None:
1009 tenant_dict
["description"] = args
.description
1010 payload_req
= json
.dumps( {"tenant": tenant_dict
})
1012 # print(payload_req)
1014 URLrequest
= "http://{}:{}/openmano/tenants".format(mano_host
, mano_port
)
1015 logger
.debug("openmano request: %s", payload_req
)
1016 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1017 logger
.debug("openmano response: %s", mano_response
.text
)
1018 return _print_verbose(mano_response
, args
.verbose
)
1020 def tenant_list(args
):
1021 # print("tenant-list",args)
1023 toshow
= _get_item_uuid("tenants", args
.name
)
1024 URLrequest
= "http://{}:{}/openmano/tenants/{}".format(mano_host
, mano_port
, toshow
)
1026 URLrequest
= "http://{}:{}/openmano/tenants".format(mano_host
, mano_port
)
1027 mano_response
= requests
.get(URLrequest
)
1028 logger
.debug("openmano response: %s", mano_response
.text
)
1029 if args
.verbose
==None:
1033 return _print_verbose(mano_response
, args
.verbose
)
1035 def tenant_delete(args
):
1036 # print("tenant-delete",args)
1037 todelete
= _get_item_uuid("tenants", args
.name
)
1039 r
= input("Delete tenant {} (y/N)? ".format(args
.name
))
1040 if not (len(r
)>0 and r
[0].lower()=="y"):
1042 URLrequest
= "http://{}:{}/openmano/tenants/{}".format(mano_host
, mano_port
, todelete
)
1043 mano_response
= requests
.delete(URLrequest
)
1044 logger
.debug("openmano response: %s", mano_response
.text
)
1045 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
1046 content
= mano_response
.json()
1047 # print(json.dumps(content, indent=4))
1048 if mano_response
.status_code
== 200:
1049 print(content
['result'])
1051 print(content
['error']['description'])
1054 def datacenter_attach(args
):
1055 tenant
= _get_tenant()
1056 datacenter
= _get_datacenter(args
.name
)
1057 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1060 if args
.vim_tenant_id
!= None:
1061 datacenter_dict
['vim_tenant'] = args
.vim_tenant_id
1062 if args
.vim_tenant_name
!= None:
1063 datacenter_dict
['vim_tenant_name'] = args
.vim_tenant_name
1064 if args
.user
!= None:
1065 datacenter_dict
['vim_username'] = args
.user
1066 if args
.password
!= None:
1067 datacenter_dict
['vim_password'] = args
.password
1068 if args
.config
!=None:
1069 datacenter_dict
["config"] = _load_file_or_yaml(args
.config
)
1071 payload_req
= json
.dumps( {"datacenter": datacenter_dict
})
1073 # print(payload_req)
1075 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}".format(mano_host
, mano_port
, tenant
, datacenter
)
1076 logger
.debug("openmano request: %s", payload_req
)
1077 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1078 logger
.debug("openmano response: %s", mano_response
.text
)
1079 result
= _print_verbose(mano_response
, args
.verbose
)
1080 #provide addional information if error
1081 if mano_response
.status_code
!= 200:
1082 content
= mano_response
.json()
1083 if "already in use for 'name'" in content
['error']['description'] and \
1084 "to database vim_tenants table" in content
['error']['description']:
1085 print("Try to specify a different name with --vim-tenant-name")
1089 def datacenter_edit_vim_tenant(args
):
1090 tenant
= _get_tenant()
1091 datacenter
= _get_datacenter(args
.name
)
1092 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1094 if not (args
.vim_tenant_id
or args
.vim_tenant_name
or args
.user
or args
.password
or args
.config
):
1095 raise OpenmanoCLIError("Error. At least one parameter must be updated.")
1097 datacenter_dict
= {}
1098 if args
.vim_tenant_id
!= None:
1099 datacenter_dict
['vim_tenant'] = args
.vim_tenant_id
1100 if args
.vim_tenant_name
!= None:
1101 datacenter_dict
['vim_tenant_name'] = args
.vim_tenant_name
1102 if args
.user
!= None:
1103 datacenter_dict
['vim_username'] = args
.user
1104 if args
.password
!= None:
1105 datacenter_dict
['vim_password'] = args
.password
1106 if args
.config
!= None:
1107 datacenter_dict
["config"] = _load_file_or_yaml(args
.config
)
1108 payload_req
= json
.dumps({"datacenter": datacenter_dict
})
1110 # print(payload_req)
1112 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}".format(mano_host
, mano_port
, tenant
, datacenter
)
1113 logger
.debug("openmano request: %s", payload_req
)
1114 mano_response
= requests
.put(URLrequest
, headers
=headers_req
, data
=payload_req
)
1115 logger
.debug("openmano response: %s", mano_response
.text
)
1116 result
= _print_verbose(mano_response
, args
.verbose
)
1120 def datacenter_detach(args
):
1124 tenant
= _get_tenant()
1125 datacenter
= _get_datacenter(args
.name
, tenant
)
1126 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1127 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}".format(mano_host
, mano_port
, tenant
, datacenter
)
1128 mano_response
= requests
.delete(URLrequest
, headers
=headers_req
)
1129 logger
.debug("openmano response: %s", mano_response
.text
)
1130 content
= mano_response
.json()
1131 # print(json.dumps(content, indent=4))
1132 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
1133 if mano_response
.status_code
== 200:
1134 print(content
['result'])
1136 print(content
['error']['description'])
1139 def datacenter_create(args
):
1140 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1141 datacenter_dict
={"name": args
.name
, "vim_url": args
.url
}
1142 if args
.description
!=None:
1143 datacenter_dict
["description"] = args
.description
1145 datacenter_dict
["type"] = args
.type
1147 datacenter_dict
["vim_url_admin"] = args
.url_admin
1148 if args
.config
!=None:
1149 datacenter_dict
["config"] = _load_file_or_yaml(args
.config
)
1150 if args
.sdn_controller
!=None:
1151 tenant
= _get_tenant()
1152 sdn_controller
= _get_item_uuid("sdn_controllers", args
.sdn_controller
, tenant
)
1153 if not 'config' in datacenter_dict
:
1154 datacenter_dict
['config'] = {}
1155 datacenter_dict
['config']['sdn-controller'] = sdn_controller
1156 payload_req
= json
.dumps( {"datacenter": datacenter_dict
})
1158 # print(payload_req)
1160 URLrequest
= "http://{}:{}/openmano/datacenters".format(mano_host
, mano_port
)
1161 logger
.debug("openmano request: %s", payload_req
)
1162 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1163 logger
.debug("openmano response: %s", mano_response
.text
)
1164 return _print_verbose(mano_response
, args
.verbose
)
1166 def datacenter_delete(args
):
1167 # print("datacenter-delete",args)
1168 todelete
= _get_item_uuid("datacenters", args
.name
, "any")
1170 r
= input("Delete datacenter {} (y/N)? ".format(args
.name
))
1171 if not (len(r
)>0 and r
[0].lower()=="y"):
1173 URLrequest
= "http://{}:{}/openmano/datacenters/{}".format(mano_host
, mano_port
, todelete
)
1174 mano_response
= requests
.delete(URLrequest
)
1175 logger
.debug("openmano response: %s", mano_response
.text
)
1176 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
1177 content
= mano_response
.json()
1178 # print(json.dumps(content, indent=4))
1179 if mano_response
.status_code
== 200:
1180 print(content
['result'])
1182 print(content
['error']['description'])
1186 def datacenter_list(args
):
1187 # print("datacenter-list",args)
1188 tenant
='any' if args
.all
else _get_tenant()
1191 toshow
= _get_item_uuid("datacenters", args
.name
, tenant
)
1192 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}".format(mano_host
, mano_port
, tenant
, toshow
)
1194 URLrequest
= "http://{}:{}/openmano/{}/datacenters".format(mano_host
, mano_port
, tenant
)
1195 mano_response
= requests
.get(URLrequest
)
1196 logger
.debug("openmano response: %s", mano_response
.text
)
1197 if args
.verbose
==None:
1201 return _print_verbose(mano_response
, args
.verbose
)
1204 def datacenter_sdn_port_mapping_set(args
):
1205 tenant
= _get_tenant()
1206 datacenter
= _get_datacenter(args
.name
, tenant
)
1207 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1210 raise OpenmanoCLIError(
1211 "No yaml/json has been provided specifying the SDN port mapping")
1212 sdn_port_mapping
= _load_file_or_yaml(args
.file)
1213 payload_req
= json
.dumps({"sdn_port_mapping": sdn_port_mapping
})
1216 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}/sdn_mapping".format(mano_host
, mano_port
, tenant
, datacenter
)
1217 mano_response
= requests
.get(URLrequest
)
1218 logger
.debug("openmano response: %s", mano_response
.text
)
1219 port_mapping
= mano_response
.json()
1220 if mano_response
.status_code
!= 200:
1221 str(mano_response
.json())
1222 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping
['error']['description']))
1223 if len(port_mapping
["sdn_port_mapping"]["ports_mapping"]) > 0:
1225 r
= input("Datacenter {} already contains a port mapping. Overwrite? (y/N)? ".format(datacenter
))
1226 if not (len(r
) > 0 and r
[0].lower() == "y"):
1230 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}/sdn_mapping".format(mano_host
, mano_port
, tenant
, datacenter
)
1231 mano_response
= requests
.delete(URLrequest
)
1232 logger
.debug("openmano response: %s", mano_response
.text
)
1233 if mano_response
.status_code
!= 200:
1234 return _print_verbose(mano_response
, args
.verbose
)
1237 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}/sdn_mapping".format(mano_host
, mano_port
, tenant
, datacenter
)
1238 logger
.debug("openmano request: %s", payload_req
)
1239 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1240 logger
.debug("openmano response: %s", mano_response
.text
)
1241 return _print_verbose(mano_response
, args
.verbose
)
1244 def datacenter_sdn_port_mapping_list(args
):
1245 tenant
= _get_tenant()
1246 datacenter
= _get_datacenter(args
.name
, tenant
)
1248 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}/sdn_mapping".format(mano_host
, mano_port
, tenant
, datacenter
)
1249 mano_response
= requests
.get(URLrequest
)
1250 logger
.debug("openmano response: %s", mano_response
.text
)
1252 return _print_verbose(mano_response
, 4)
1255 def datacenter_sdn_port_mapping_clear(args
):
1256 tenant
= _get_tenant()
1257 datacenter
= _get_datacenter(args
.name
, tenant
)
1260 r
= input("Clean SDN port mapping for datacenter {} (y/N)? ".format(datacenter
))
1261 if not (len(r
) > 0 and r
[0].lower() == "y"):
1264 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}/sdn_mapping".format(mano_host
, mano_port
, tenant
, datacenter
)
1265 mano_response
= requests
.delete(URLrequest
)
1266 logger
.debug("openmano response: %s", mano_response
.text
)
1268 return _print_verbose(mano_response
, args
.verbose
)
1271 def sdn_controller_create(args
):
1272 tenant
= _get_tenant()
1273 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1276 if not args
.ip
: error_msg
.append("'ip'")
1277 if not args
.port
: error_msg
.append("'port'")
1278 if not args
.dpid
: error_msg
.append("'dpid'")
1279 if not args
.type: error_msg
.append("'type'")
1281 raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg
))
1283 controller_dict
= {}
1284 controller_dict
['name'] = args
.name
1285 controller_dict
['ip'] = args
.ip
1286 controller_dict
['port'] = int(args
.port
)
1287 controller_dict
['dpid'] = args
.dpid
1288 controller_dict
['type'] = args
.type
1289 if args
.description
!= None:
1290 controller_dict
['description'] = args
.description
1291 if args
.user
!= None:
1292 controller_dict
['user'] = args
.user
1293 if args
.password
!= None:
1294 controller_dict
['password'] = args
.password
1296 payload_req
= json
.dumps({"sdn_controller": controller_dict
})
1298 # print(payload_req)
1300 URLrequest
= "http://{}:{}/openmano/{}/sdn_controllers".format(mano_host
, mano_port
, tenant
)
1301 logger
.debug("openmano request: %s", payload_req
)
1302 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1303 logger
.debug("openmano response: %s", mano_response
.text
)
1304 result
= _print_verbose(mano_response
, args
.verbose
)
1308 def sdn_controller_edit(args
):
1309 tenant
= _get_tenant()
1310 controller_uuid
= _get_item_uuid("sdn_controllers", args
.name
, tenant
)
1311 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1313 controller_dict
= {}
1315 controller_dict
['name'] = args
.new_name
1317 controller_dict
['ip'] = args
.ip
1319 controller_dict
['port'] = int(args
.port
)
1321 controller_dict
['dpid'] = args
.dpid
1323 controller_dict
['type'] = args
.type
1324 if args
.description
:
1325 controller_dict
['description'] = args
.description
1327 controller_dict
['user'] = args
.user
1329 controller_dict
['password'] = args
.password
1331 if not controller_dict
:
1332 raise OpenmanoCLIError("At least one parameter must be edited")
1335 r
= input("Update SDN controller {} (y/N)? ".format(args
.name
))
1336 if not (len(r
) > 0 and r
[0].lower() == "y"):
1339 payload_req
= json
.dumps({"sdn_controller": controller_dict
})
1340 # print(payload_req)
1342 URLrequest
= "http://{}:{}/openmano/{}/sdn_controllers/{}".format(mano_host
, mano_port
, tenant
, controller_uuid
)
1343 logger
.debug("openmano request: %s", payload_req
)
1344 mano_response
= requests
.put(URLrequest
, headers
=headers_req
, data
=payload_req
)
1345 logger
.debug("openmano response: %s", mano_response
.text
)
1346 result
= _print_verbose(mano_response
, args
.verbose
)
1350 def sdn_controller_list(args
):
1351 tenant
= _get_tenant()
1352 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1355 toshow
= _get_item_uuid("sdn_controllers", args
.name
, tenant
)
1356 URLrequest
= "http://{}:{}/openmano/{}/sdn_controllers/{}".format(mano_host
, mano_port
, tenant
, toshow
)
1358 URLrequest
= "http://{}:{}/openmano/{}/sdn_controllers".format(mano_host
, mano_port
, tenant
)
1360 mano_response
= requests
.get(URLrequest
)
1361 logger
.debug("openmano response: %s", mano_response
.text
)
1362 if args
.verbose
==None:
1367 # json.dumps(mano_response.json(), indent=4)
1368 return _print_verbose(mano_response
, args
.verbose
)
1371 def sdn_controller_delete(args
):
1372 tenant
= _get_tenant()
1373 controller_uuid
= _get_item_uuid("sdn_controllers", args
.name
, tenant
)
1376 r
= input("Delete SDN controller {} (y/N)? ".format(args
.name
))
1377 if not (len(r
) > 0 and r
[0].lower() == "y"):
1380 URLrequest
= "http://{}:{}/openmano/{}/sdn_controllers/{}".format(mano_host
, mano_port
, tenant
, controller_uuid
)
1381 mano_response
= requests
.delete(URLrequest
)
1382 logger
.debug("openmano response: %s", mano_response
.text
)
1383 return _print_verbose(mano_response
, args
.verbose
)
1385 def vim_action(args
):
1386 # print("datacenter-net-action",args)
1387 tenant
= _get_tenant()
1388 datacenter
= _get_datacenter(args
.datacenter
, tenant
)
1389 if args
.verbose
==None:
1391 if args
.action
=="list":
1392 URLrequest
= "http://{}:{}/openmano/{}/vim/{}/{}s".format(mano_host
, mano_port
, tenant
, datacenter
, args
.item
)
1395 URLrequest
+= "/" + args
.name
1396 mano_response
= requests
.get(URLrequest
)
1397 logger
.debug("openmano response: %s", mano_response
.text
)
1398 return _print_verbose(mano_response
, args
.verbose
)
1399 elif args
.action
=="delete":
1400 URLrequest
= "http://{}:{}/openmano/{}/vim/{}/{}s/{}".format(mano_host
, mano_port
, tenant
, datacenter
, args
.item
, args
.name
)
1401 mano_response
= requests
.delete(URLrequest
)
1402 logger
.debug("openmano response: %s", mano_response
.text
)
1403 result
= 0 if mano_response
.status_code
==200 else mano_response
.status_code
1404 content
= mano_response
.json()
1405 # print(json.dumps(content, indent=4))
1406 if mano_response
.status_code
== 200:
1407 print(content
['result'])
1409 print(content
['error']['description'])
1411 elif args
.action
=="create":
1412 headers_req
= {'content-type': 'application/yaml'}
1414 create_dict
= _load_file_or_yaml(args
.file)
1415 if args
.item
not in create_dict
:
1416 create_dict
= {args
.item
: create_dict
}
1418 create_dict
= {args
.item
:{}}
1420 create_dict
[args
.item
]['name'] = args
.name
1421 #if args.description:
1422 # create_dict[args.item]['description'] = args.description
1423 if args
.item
=="network":
1425 create_dict
[args
.item
]['bind_net'] = args
.bind_net
1427 create_dict
[args
.item
]['type'] = args
.type
1429 create_dict
[args
.item
]['shared'] = args
.shared
1430 if "name" not in create_dict
[args
.item
]:
1431 print("You must provide a name in the descriptor file or with the --name option")
1433 payload_req
= yaml
.safe_dump(create_dict
, explicit_start
=True, indent
=4, default_flow_style
=False, tags
=False,
1435 logger
.debug("openmano request: %s", payload_req
)
1436 URLrequest
= "http://{}:{}/openmano/{}/vim/{}/{}s".format(mano_host
, mano_port
, tenant
, datacenter
, args
.item
)
1437 mano_response
= requests
.post(URLrequest
, headers
= headers_req
, data
=payload_req
)
1438 logger
.debug("openmano response: %s", mano_response
.text
)
1439 if args
.verbose
==None:
1441 return _print_verbose(mano_response
, args
.verbose
)
1444 def _get_items(item
, item_name_id
=None, datacenter
=None, tenant
=None):
1445 URLrequest
= "http://{}:{}/openmano".format(mano_host
, mano_port
)
1447 URLrequest
+= "/" + tenant
1449 URLrequest
+= "/vim/" + datacenter
1451 URLrequest
+= "/" + item
+"s"
1453 URLrequest
+= "/" + item_name_id
1454 mano_response
= requests
.get(URLrequest
)
1455 logger
.debug("openmano response: %s", mano_response
.text
)
1457 return mano_response
1460 def vim_net_sdn_attach(args
):
1461 #Verify the network exists in the vim
1462 tenant
= _get_tenant()
1463 datacenter
= _get_datacenter(args
.datacenter
, tenant
)
1464 result
= _get_items('network', item_name_id
=args
.vim_net
, datacenter
=datacenter
, tenant
=tenant
)
1465 content
= yaml
.load(result
.content
)
1466 if 'networks' in content
:
1467 raise OpenmanoCLIError('More than one network in the vim named ' + args
.vim_net
+ '. Use uuid instead')
1468 if 'error' in content
:
1469 raise OpenmanoCLIError(yaml
.safe_dump(content
))
1470 network_uuid
= content
['network']['id']
1472 #Make call to attach the dataplane port to the SND network associated to the vim network
1473 headers_req
= {'content-type': 'application/yaml'}
1474 payload_req
= {'port': args
.port
}
1476 payload_req
['vlan'] = int(args
.vlan
)
1478 payload_req
['mac'] = args
.mac
1480 URLrequest
= "http://{}:{}/openmano/{}/vim/{}/network/{}/attach".format(mano_host
, mano_port
, tenant
, datacenter
, network_uuid
)
1481 logger
.debug("openmano request: %s", payload_req
)
1482 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=json
.dumps(payload_req
))
1483 logger
.debug("openmano response: %s", mano_response
.text
)
1484 result
= _print_verbose(mano_response
, args
.verbose
)
1488 def vim_net_sdn_detach(args
):
1489 if not args
.all
and not args
.id:
1490 print("--all or --id must be used")
1493 # Verify the network exists in the vim
1494 tenant
= _get_tenant()
1495 datacenter
= _get_datacenter(args
.datacenter
, tenant
)
1496 result
= _get_items('network', item_name_id
=args
.vim_net
, datacenter
=datacenter
, tenant
=tenant
)
1497 content
= yaml
.load(result
.content
)
1498 if 'networks' in content
:
1499 raise OpenmanoCLIError('More than one network in the vim named ' + args
.vim_net
+ '. Use uuid instead')
1500 if 'error' in content
:
1501 raise OpenmanoCLIError(yaml
.safe_dump(content
))
1502 network_uuid
= content
['network']['id']
1505 r
= input("Confirm action' (y/N)? ")
1506 if len(r
) == 0 or r
[0].lower() != "y":
1510 URLrequest
= "http://{}:{}/openmano/{}/vim/{}/network/{}/detach/{}".format(
1511 mano_host
, mano_port
, tenant
, datacenter
, network_uuid
, args
.id)
1513 URLrequest
= "http://{}:{}/openmano/{}/vim/{}/network/{}/detach".format(
1514 mano_host
, mano_port
, tenant
, datacenter
, network_uuid
)
1515 mano_response
= requests
.delete(URLrequest
)
1516 logger
.debug("openmano response: %s", mano_response
.text
)
1517 result
= _print_verbose(mano_response
, args
.verbose
)
1521 def datacenter_net_action(args
):
1522 if args
.action
== "net-update":
1523 print("This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano"
1524 " datacenter-netmap-import' instead!!!")
1526 args
.action
= "netmap-delete"
1529 r
= datacenter_netmap_action(args
)
1532 args
.action
= "netmap-import"
1533 r
= datacenter_netmap_action(args
)
1536 if args
.action
== "net-edit":
1537 args
.netmap
= args
.net
1539 elif args
.action
== "net-list":
1541 elif args
.action
== "net-delete":
1542 args
.netmap
= args
.net
1545 args
.action
= "netmap" + args
.action
[3:]
1548 print("This command is deprecated, use 'openmano datacenter-{}' instead!!!".format(args
.action
))
1550 return datacenter_netmap_action(args
)
1552 def datacenter_netmap_action(args
):
1553 tenant
= _get_tenant()
1554 datacenter
= _get_datacenter(args
.datacenter
, tenant
)
1555 # print("datacenter_netmap_action",args)
1557 if args
.verbose
==None:
1559 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1560 URLrequest
= "http://{}:{}/openmano/{}/datacenters/{}/netmaps".format(mano_host
, mano_port
, tenant
, datacenter
)
1562 if args
.action
=="netmap-list":
1564 URLrequest
+= "/" + args
.netmap
1566 mano_response
= requests
.get(URLrequest
)
1568 elif args
.action
=="netmap-delete":
1569 if args
.netmap
and args
.all
:
1570 print("you can not use a netmap name and the option --all at the same time")
1573 force_text
= "Delete default netmap '{}' from datacenter '{}' (y/N)? ".format(args
.netmap
, datacenter
)
1574 URLrequest
+= "/" + args
.netmap
1576 force_text
="Delete all default netmaps from datacenter '{}' (y/N)? ".format(datacenter
)
1578 print("you must specify a netmap name or the option --all")
1581 r
= input(force_text
)
1582 if len(r
)>0 and r
[0].lower()=="y":
1586 mano_response
= requests
.delete(URLrequest
, headers
=headers_req
)
1587 elif args
.action
=="netmap-import":
1589 r
= input("Create all the available networks from datacenter '{}' as default netmaps (y/N)? ".format(datacenter
))
1590 if len(r
)>0 and r
[0].lower()=="y":
1594 URLrequest
+= "/upload"
1595 mano_response
= requests
.post(URLrequest
, headers
=headers_req
)
1596 elif args
.action
=="netmap-edit" or args
.action
=="netmap-create":
1598 payload
= _load_file_or_yaml(args
.file)
1601 if "netmap" not in payload
:
1602 payload
= {"netmap": payload
}
1604 payload
["netmap"]["name"] = args
.name
1606 payload
["netmap"]["vim_id"] = args
.vim_id
1607 if args
.action
=="netmap-create" and args
.vim_name
:
1608 payload
["netmap"]["vim_name"] = args
.vim_name
1609 payload_req
= json
.dumps(payload
)
1610 logger
.debug("openmano request: %s", payload_req
)
1612 if args
.action
=="netmap-edit" and not args
.force
:
1613 if len(payload
["netmap"]) == 0:
1614 print("You must supply some parameter to edit")
1616 r
= input("Edit default netmap '{}' from datacenter '{}' (y/N)? ".format(args
.netmap
, datacenter
))
1617 if len(r
)>0 and r
[0].lower()=="y":
1621 URLrequest
+= "/" + args
.netmap
1622 mano_response
= requests
.put(URLrequest
, headers
=headers_req
, data
=payload_req
)
1623 else: #netmap-create
1624 if "vim_name" not in payload
["netmap"] and "vim_id" not in payload
["netmap"]:
1625 print("You must supply either --vim-id or --vim-name option; or include one of them in the file"
1628 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1630 logger
.debug("openmano response: %s", mano_response
.text
)
1631 return _print_verbose(mano_response
, args
.verbose
)
1634 def element_edit(args
):
1635 element
= _get_item_uuid(args
.element
, args
.name
)
1636 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1637 URLrequest
= "http://{}:{}/openmano/{}/{}".format(mano_host
, mano_port
, args
.element
, element
)
1638 payload
=_load_file_or_yaml(args
.file)
1639 if args
.element
[:-1] not in payload
:
1640 payload
= {args
.element
[:-1]: payload
}
1641 payload_req
= json
.dumps(payload
)
1643 # print(payload_req)
1644 if not args
.force
or (args
.name
==None and args
.filer
==None):
1645 r
= input(" Edit " + args
.element
[:-1] + " " + args
.name
+ " (y/N)? ")
1646 if len(r
)>0 and r
[0].lower()=="y":
1650 logger
.debug("openmano request: %s", payload_req
)
1651 mano_response
= requests
.put(URLrequest
, headers
=headers_req
, data
=payload_req
)
1652 logger
.debug("openmano response: %s", mano_response
.text
)
1653 if args
.verbose
==None:
1657 return _print_verbose(mano_response
, args
.verbose
)
1660 def datacenter_edit(args
):
1661 tenant
= _get_tenant()
1662 element
= _get_item_uuid('datacenters', args
.name
, tenant
)
1663 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1664 URLrequest
= "http://{}:{}/openmano/datacenters/{}".format(mano_host
, mano_port
, element
)
1666 has_arguments
= False
1667 if args
.file != None:
1668 has_arguments
= True
1669 payload
= _load_file_or_yaml(args
.file)
1673 if args
.sdn_controller
!= None:
1674 has_arguments
= True
1675 if not 'config' in payload
:
1676 payload
['config'] = {}
1677 if not 'sdn-controller' in payload
['config']:
1678 payload
['config']['sdn-controller'] = {}
1679 if args
.sdn_controller
== 'null':
1680 payload
['config']['sdn-controller'] = None
1682 payload
['config']['sdn-controller'] = _get_item_uuid("sdn_controllers", args
.sdn_controller
, tenant
)
1684 if not has_arguments
:
1685 raise OpenmanoCLIError("At least one argument must be provided to modify the datacenter")
1687 if 'datacenter' not in payload
:
1688 payload
= {'datacenter': payload
}
1689 payload_req
= json
.dumps(payload
)
1691 # print(payload_req)
1692 if not args
.force
or (args
.name
== None and args
.filer
== None):
1693 r
= input(" Edit datacenter " + args
.name
+ " (y/N)? ")
1694 if len(r
) > 0 and r
[0].lower() == "y":
1698 logger
.debug("openmano request: %s", payload_req
)
1699 mano_response
= requests
.put(URLrequest
, headers
=headers_req
, data
=payload_req
)
1700 logger
.debug("openmano response: %s", mano_response
.text
)
1701 if args
.verbose
== None:
1703 if args
.name
!= None:
1705 return _print_verbose(mano_response
, args
.verbose
)
1709 def wim_account_create(args
):
1710 tenant
= _get_tenant()
1711 wim
= _get_wim(args
.name
)
1712 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1715 if args
.account_name
is not None:
1716 wim_dict
['name'] = args
.account_name
1717 if args
.user
is not None:
1718 wim_dict
['user'] = args
.user
1719 if args
.password
is not None:
1720 wim_dict
['password'] = args
.password
1721 if args
.config
is not None:
1722 wim_dict
["config"] = _load_file_or_yaml(args
.config
)
1724 payload_req
= json
.dumps({"wim_account": wim_dict
})
1726 URLrequest
= "http://{}:{}/openmano/{}/wims/{}".format(mano_host
, mano_port
, tenant
, wim
)
1727 logger
.debug("openmano request: %s", payload_req
)
1728 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1729 logger
.debug("openmano response: %s", mano_response
.text
)
1730 result
= _print_verbose(mano_response
, args
.verbose
)
1731 # provide addional information if error
1732 if mano_response
.status_code
!= 200:
1733 content
= mano_response
.json()
1734 if "already in use for 'name'" in content
['error']['description'] and \
1735 "to database wim_tenants table" in content
['error']['description']:
1736 print("Try to specify a different name with --wim-tenant-name")
1740 def wim_account_delete(args
):
1744 tenant
= _get_tenant()
1745 wim
= _get_wim(args
.name
, tenant
)
1746 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1747 URLrequest
= "http://{}:{}/openmano/{}/wims/{}".format(mano_host
, mano_port
, tenant
, wim
)
1748 mano_response
= requests
.delete(URLrequest
, headers
=headers_req
)
1749 logger
.debug("openmano response: %s", mano_response
.text
)
1750 content
= mano_response
.json()
1751 # print(json.dumps(content, indent=4))
1752 result
= 0 if mano_response
.status_code
== 200 else mano_response
.status_code
1753 if mano_response
.status_code
== 200:
1754 print(content
['result'])
1756 print(content
['error']['description'])
1760 def wim_account_edit(args
):
1761 tenant
= _get_tenant()
1762 wim
= _get_wim(args
.name
)
1763 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1766 if not args
.account_name
:
1767 wim_dict
['name'] = args
.vim_tenant_name
1769 wim_dict
['user'] = args
.user
1770 if not args
.password
:
1771 wim_dict
['password'] = args
.password
1773 wim_dict
["config"] = _load_file_or_yaml(args
.config
)
1775 payload_req
= json
.dumps({"wim_account": wim_dict
})
1777 # print(payload_req)
1779 URLrequest
= "http://{}:{}/openmano/{}/wims/{}".format(mano_host
, mano_port
, tenant
, wim
)
1780 logger
.debug("openmano request: %s", payload_req
)
1781 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1782 logger
.debug("openmano response: %s", mano_response
.text
)
1783 result
= _print_verbose(mano_response
, args
.verbose
)
1784 # provide addional information if error
1785 if mano_response
.status_code
!= 200:
1786 content
= mano_response
.json()
1787 if "already in use for 'name'" in content
['error']['description'] and \
1788 "to database wim_tenants table" in content
['error']['description']:
1789 print("Try to specify a different name with --wim-tenant-name")
1792 def wim_create(args
):
1793 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1794 wim_dict
= {"name": args
.name
, "wim_url": args
.url
}
1795 if args
.description
!= None:
1796 wim_dict
["description"] = args
.description
1797 if args
.type != None:
1798 wim_dict
["type"] = args
.type
1799 if args
.config
!= None:
1800 wim_dict
["config"] = _load_file_or_yaml(args
.config
)
1802 payload_req
= json
.dumps({"wim": wim_dict
})
1804 URLrequest
= "http://{}:{}/openmano/wims".format(mano_host
, mano_port
)
1805 logger
.debug("openmano request: %s", payload_req
)
1806 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1807 logger
.debug("openmano response: %s", mano_response
.text
)
1808 return _print_verbose(mano_response
, args
.verbose
)
1812 tenant
= _get_tenant()
1813 element
= _get_item_uuid('wims', args
.name
, tenant
)
1814 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1815 URLrequest
= "http://{}:{}/openmano/wims/{}".format(mano_host
, mano_port
, element
)
1817 has_arguments
= False
1818 if args
.file != None:
1819 has_arguments
= True
1820 payload
= _load_file_or_yaml(args
.file)
1824 if not has_arguments
:
1825 raise OpenmanoCLIError("At least one argument must be provided to modify the wim")
1827 if 'wim' not in payload
:
1828 payload
= {'wim': payload
}
1829 payload_req
= json
.dumps(payload
)
1831 # print(payload_req)
1832 if not args
.force
or (args
.name
== None and args
.filer
== None):
1833 r
= input(" Edit wim " + args
.name
+ " (y/N)? ")
1834 if len(r
) > 0 and r
[0].lower() == "y":
1838 logger
.debug("openmano request: %s", payload_req
)
1839 mano_response
= requests
.put(URLrequest
, headers
=headers_req
, data
=payload_req
)
1840 logger
.debug("openmano response: %s", mano_response
.text
)
1841 if args
.verbose
== None:
1843 if args
.name
!= None:
1845 return _print_verbose(mano_response
, args
.verbose
)
1848 def wim_delete(args
):
1849 # print("wim-delete",args)
1850 todelete
= _get_item_uuid("wims", args
.name
, "any")
1852 r
= input("Delete wim {} (y/N)? ".format(args
.name
))
1853 if not (len(r
) > 0 and r
[0].lower() == "y"):
1855 URLrequest
= "http://{}:{}/openmano/wims/{}".format(mano_host
, mano_port
, todelete
)
1856 mano_response
= requests
.delete(URLrequest
)
1857 logger
.debug("openmano response: %s", mano_response
.text
)
1858 result
= 0 if mano_response
.status_code
== 200 else mano_response
.status_code
1859 content
= mano_response
.json()
1860 # print(json.dumps(content, indent=4)
1861 if mano_response
.status_code
== 200:
1862 print(content
['result'])
1864 print(content
['error']['description'])
1869 # print("wim-list",args)
1870 tenant
= 'any' if args
.all
else _get_tenant()
1873 toshow
= _get_item_uuid("wims", args
.name
, tenant
)
1874 URLrequest
= "http://{}:{}/openmano/{}/wims/{}".format(mano_host
, mano_port
, tenant
, toshow
)
1876 URLrequest
= "http://{}:{}/openmano/{}/wims".format(mano_host
, mano_port
, tenant
)
1877 mano_response
= requests
.get(URLrequest
)
1878 logger
.debug("openmano response: %s", mano_response
.text
)
1879 if args
.verbose
== None:
1881 if args
.name
!= None:
1883 return _print_verbose(mano_response
, args
.verbose
)
1886 def wim_port_mapping_set(args
):
1887 tenant
= _get_tenant()
1888 wim
= _get_wim(args
.name
, tenant
)
1889 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1892 raise OpenmanoCLIError(
1893 "No yaml/json has been provided specifying the WIM port mapping")
1894 wim_port_mapping
= _load_file_or_yaml(args
.file)
1896 payload_req
= json
.dumps({"wim_port_mapping": wim_port_mapping
})
1899 URLrequest
= "http://{}:{}/openmano/{}/wims/{}/port_mapping".format(mano_host
, mano_port
, tenant
, wim
)
1900 mano_response
= requests
.get(URLrequest
)
1901 logger
.debug("openmano response: %s", mano_response
.text
)
1902 port_mapping
= mano_response
.json()
1904 if mano_response
.status_code
!= 200:
1905 str(mano_response
.json())
1906 raise OpenmanoCLIError("openmano client error: {}".format(port_mapping
['error']['description']))
1907 # TODO: check this if statement
1908 if len(port_mapping
["wim_port_mapping"]) > 0:
1910 r
= input("WIM {} already contains a port mapping. Overwrite? (y/N)? ".format(wim
))
1911 if not (len(r
) > 0 and r
[0].lower() == "y"):
1915 URLrequest
= "http://{}:{}/openmano/{}/wims/{}/port_mapping".format(mano_host
, mano_port
, tenant
, wim
)
1916 mano_response
= requests
.delete(URLrequest
)
1917 logger
.debug("openmano response: %s", mano_response
.text
)
1918 if mano_response
.status_code
!= 200:
1919 return _print_verbose(mano_response
, args
.verbose
)
1922 URLrequest
= "http://{}:{}/openmano/{}/wims/{}/port_mapping".format(mano_host
, mano_port
, tenant
, wim
)
1923 logger
.debug("openmano request: %s", payload_req
)
1924 mano_response
= requests
.post(URLrequest
, headers
=headers_req
, data
=payload_req
)
1925 logger
.debug("openmano response: %s", mano_response
.text
)
1926 return _print_verbose(mano_response
, 4)
1929 def wim_port_mapping_list(args
):
1930 tenant
= _get_tenant()
1931 wim
= _get_wim(args
.name
, tenant
)
1933 URLrequest
= "http://{}:{}/openmano/{}/wims/{}/port_mapping".format(mano_host
, mano_port
, tenant
, wim
)
1934 mano_response
= requests
.get(URLrequest
)
1935 logger
.debug("openmano response: %s", mano_response
.text
)
1937 return _print_verbose(mano_response
, 4)
1940 def wim_port_mapping_clear(args
):
1941 tenant
= _get_tenant()
1942 wim
= _get_wim(args
.name
, tenant
)
1945 r
= input("Clear WIM port mapping for wim {} (y/N)? ".format(wim
))
1946 if not (len(r
) > 0 and r
[0].lower() == "y"):
1949 URLrequest
= "http://{}:{}/openmano/{}/wims/{}/port_mapping".format(mano_host
, mano_port
, tenant
, wim
)
1950 mano_response
= requests
.delete(URLrequest
)
1951 logger
.debug("openmano response: %s", mano_response
.text
)
1952 content
= mano_response
.json()
1953 # print(json.dumps(content, indent=4))
1954 result
= 0 if mano_response
.status_code
== 200 else mano_response
.status_code
1955 if mano_response
.status_code
== 200:
1956 print(content
['result'])
1958 print(content
['error']['description'])
1963 headers_req
= {'Accept': 'application/json', 'content-type': 'application/json'}
1964 URLrequest
= "http://{}:{}/openmano/version".format(mano_host
, mano_port
)
1966 mano_response
= requests
.get(URLrequest
, headers
=headers_req
)
1967 logger
.debug("openmano response: %s", mano_response
.text
)
1968 print(mano_response
.text
)
1976 mano_tenant
= os
.getenv('OPENMANO_TENANT', None)
1977 mano_host
= os
.getenv('OPENMANO_HOST',"localhost")
1978 mano_port
= os
.getenv('OPENMANO_PORT',"9090")
1979 mano_datacenter
= os
.getenv('OPENMANO_DATACENTER',None)
1980 # WIM env variable for default WIM
1981 mano_wim
= os
.getenv('OPENMANO_WIM', None)
1983 main_parser
= ThrowingArgumentParser(description
='User program to interact with OPENMANO-SERVER (openmanod)')
1984 main_parser
.add_argument('--version', action
='version', help="get version of this client",
1985 version
='%(prog)s client version ' + __version__
+
1986 " (Note: use '%(prog)s version' to get server version)")
1988 subparsers
= main_parser
.add_subparsers(help='commands')
1990 parent_parser
= argparse
.ArgumentParser(add_help
=False)
1991 parent_parser
.add_argument('--verbose', '-v', action
='count', help="increase verbosity level. Use several times")
1992 parent_parser
.add_argument('--debug', '-d', action
='store_true', help="show debug information")
1994 config_parser
= subparsers
.add_parser('config', parents
=[parent_parser
], help="prints configuration values")
1995 config_parser
.add_argument("-n", action
="store_true", help="resolves tenant and datacenter names")
1996 config_parser
.set_defaults(func
=config
)
1998 version_parser
= subparsers
.add_parser('version', parents
=[parent_parser
], help="get server version")
1999 version_parser
.set_defaults(func
=version
)
2001 vnf_create_parser
= subparsers
.add_parser('vnf-create', parents
=[parent_parser
], help="adds a vnf into the catalogue")
2002 vnf_create_parser
.add_argument("file", action
="store", help="location of the JSON file describing the VNF").completer
= FilesCompleter
2003 vnf_create_parser
.add_argument("--name", action
="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)")
2004 vnf_create_parser
.add_argument("--description", action
="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)")
2005 vnf_create_parser
.add_argument("--image-path", action
="store", help="change image path locations (overwritten)")
2006 vnf_create_parser
.add_argument("--image-name", action
="store", help="change image name (overwritten)")
2007 vnf_create_parser
.add_argument("--image-checksum", action
="store", help="change image checksum (overwritten)")
2008 vnf_create_parser
.set_defaults(func
=vnf_create
)
2010 vnf_list_parser
= subparsers
.add_parser('vnf-list', parents
=[parent_parser
], help="lists information about a vnf")
2011 vnf_list_parser
.add_argument("name", nargs
='?', help="name of the VNF")
2012 vnf_list_parser
.add_argument("-a", "--all", action
="store_true", help="shows all vnfs, not only the owned or public ones")
2013 #vnf_list_parser.add_argument('--descriptor', help="prints the VNF descriptor", action="store_true")
2014 vnf_list_parser
.set_defaults(func
=vnf_list
)
2016 vnf_delete_parser
= subparsers
.add_parser('vnf-delete', parents
=[parent_parser
], help="deletes a vnf from the catalogue")
2017 vnf_delete_parser
.add_argument("name", action
="store", help="name or uuid of the VNF to be deleted")
2018 vnf_delete_parser
.add_argument("-f", "--force", action
="store_true", help="forces deletion without asking")
2019 vnf_delete_parser
.add_argument("-a", "--all", action
="store_true", help="allow delete not owned or privated one")
2020 vnf_delete_parser
.set_defaults(func
=vnf_delete
)
2022 scenario_create_parser
= subparsers
.add_parser('scenario-create', parents
=[parent_parser
], help="adds a scenario into the OPENMANO DB")
2023 scenario_create_parser
.add_argument("file", action
="store", help="location of the YAML file describing the scenario").completer
= FilesCompleter
2024 scenario_create_parser
.add_argument("--name", action
="store", help="name of the scenario (if it exists in the YAML scenario, it is overwritten)")
2025 scenario_create_parser
.add_argument("--description", action
="store", help="description of the scenario (if it exists in the YAML scenario, it is overwritten)")
2026 scenario_create_parser
.set_defaults(func
=scenario_create
)
2028 scenario_list_parser
= subparsers
.add_parser('scenario-list', parents
=[parent_parser
], help="lists information about a scenario")
2029 scenario_list_parser
.add_argument("name", nargs
='?', help="name of the scenario")
2030 #scenario_list_parser.add_argument('--descriptor', help="prints the scenario descriptor", action="store_true")
2031 scenario_list_parser
.add_argument("-a", "--all", action
="store_true", help="shows all scenarios, not only the owned or public ones")
2032 scenario_list_parser
.set_defaults(func
=scenario_list
)
2034 scenario_delete_parser
= subparsers
.add_parser('scenario-delete', parents
=[parent_parser
], help="deletes a scenario from the OPENMANO DB")
2035 scenario_delete_parser
.add_argument("name", action
="store", help="name or uuid of the scenario to be deleted")
2036 scenario_delete_parser
.add_argument("-f", "--force", action
="store_true", help="forces deletion without asking")
2037 scenario_delete_parser
.add_argument("-a", "--all", action
="store_true", help="allow delete not owned or privated one")
2038 scenario_delete_parser
.set_defaults(func
=scenario_delete
)
2040 scenario_deploy_parser
= subparsers
.add_parser('scenario-deploy', parents
=[parent_parser
], help="deploys a scenario")
2041 scenario_deploy_parser
.add_argument("scenario", action
="store", help="name or uuid of the scenario to be deployed")
2042 scenario_deploy_parser
.add_argument("name", action
="store", help="name of the instance")
2043 scenario_deploy_parser
.add_argument("--nostart", action
="store_true", help="does not start the vms, just reserve resources")
2044 scenario_deploy_parser
.add_argument("--datacenter", action
="store", help="specifies the datacenter. Needed if several datacenters are available")
2045 scenario_deploy_parser
.add_argument("--description", action
="store", help="description of the instance")
2046 scenario_deploy_parser
.set_defaults(func
=scenario_deploy
)
2048 scenario_deploy_parser
= subparsers
.add_parser('scenario-verify', help="verifies if a scenario can be deployed (deploys it and deletes it)")
2049 scenario_deploy_parser
.add_argument("scenario", action
="store", help="name or uuid of the scenario to be verified")
2050 scenario_deploy_parser
.add_argument('--debug', '-d', action
='store_true', help="show debug information")
2051 scenario_deploy_parser
.set_defaults(func
=scenario_verify
)
2053 instance_scenario_create_parser
= subparsers
.add_parser('instance-scenario-create', parents
=[parent_parser
], help="deploys a scenario")
2054 instance_scenario_create_parser
.add_argument("file", nargs
='?', help="descriptor of the instance. Must be a file or yaml/json text")
2055 instance_scenario_create_parser
.add_argument("--scenario", action
="store", help="name or uuid of the scenario to be deployed")
2056 instance_scenario_create_parser
.add_argument("--name", action
="store", help="name of the instance")
2057 instance_scenario_create_parser
.add_argument("--nostart", action
="store_true", help="does not start the vms, just reserve resources")
2058 instance_scenario_create_parser
.add_argument("--datacenter", action
="store", help="specifies the datacenter. Needed if several datacenters are available")
2059 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")
2060 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")
2061 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")
2062 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")
2063 instance_scenario_create_parser
.add_argument("--description", action
="store", help="description of the instance")
2064 instance_scenario_create_parser
.set_defaults(func
=instance_create
)
2066 instance_scenario_list_parser
= subparsers
.add_parser('instance-scenario-list', parents
=[parent_parser
], help="lists information about a scenario instance")
2067 instance_scenario_list_parser
.add_argument("name", nargs
='?', help="name of the scenario instance")
2068 instance_scenario_list_parser
.add_argument("-a", "--all", action
="store_true", help="shows all instance-scenarios, not only the owned")
2069 instance_scenario_list_parser
.set_defaults(func
=instance_scenario_list
)
2071 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)")
2072 instance_scenario_delete_parser
.add_argument("name", action
="store", help="name or uuid of the scenario instance to be deleted")
2073 instance_scenario_delete_parser
.add_argument("-f", "--force", action
="store_true", help="forces deletion without asking")
2074 instance_scenario_delete_parser
.add_argument("-a", "--all", action
="store_true", help="allow delete not owned or privated one")
2075 instance_scenario_delete_parser
.set_defaults(func
=instance_scenario_delete
)
2077 instance_scenario_action_parser
= subparsers
.add_parser('instance-scenario-action', parents
=[parent_parser
], help="invoke an action over part or the whole scenario instance")
2078 instance_scenario_action_parser
.add_argument("name", action
="store", help="name or uuid of the scenario instance")
2079 instance_scenario_action_parser
.add_argument("action", action
="store", type=str, \
2080 choices
=["start","pause","resume","shutoff","shutdown","forceOff","rebuild","reboot", "console", "add_public_key","vdu-scaling"],\
2081 help="action to send")
2082 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}]'")
2083 instance_scenario_action_parser
.add_argument("--vnf", action
="append", help="VNF to act on (can use several entries)")
2084 instance_scenario_action_parser
.add_argument("--vm", action
="append", help="VM to act on (can use several entries)")
2085 instance_scenario_action_parser
.set_defaults(func
=instance_scenario_action
)
2087 action_parser
= subparsers
.add_parser('action-list', parents
=[parent_parser
], help="get action over an instance status")
2088 action_parser
.add_argument("id", nargs
='?', action
="store", help="action id")
2089 action_parser
.add_argument("--instance", action
="store", help="fitler by this instance_id")
2090 action_parser
.add_argument("--all", action
="store", help="Not filter by tenant")
2091 action_parser
.set_defaults(func
=get_action
)
2093 #instance_scenario_status_parser = subparsers.add_parser('instance-scenario-status', help="show the status of a scenario instance")
2094 #instance_scenario_status_parser.add_argument("name", action="store", help="name or uuid of the scenario instance")
2095 #instance_scenario_status_parser.set_defaults(func=instance_scenario_status)
2097 tenant_create_parser
= subparsers
.add_parser('tenant-create', parents
=[parent_parser
], help="creates a new tenant")
2098 tenant_create_parser
.add_argument("name", action
="store", help="name for the tenant")
2099 tenant_create_parser
.add_argument("--description", action
="store", help="description of the tenant")
2100 tenant_create_parser
.set_defaults(func
=tenant_create
)
2102 tenant_delete_parser
= subparsers
.add_parser('tenant-delete', parents
=[parent_parser
], help="deletes a tenant from the catalogue")
2103 tenant_delete_parser
.add_argument("name", action
="store", help="name or uuid of the tenant to be deleted")
2104 tenant_delete_parser
.add_argument("-f", "--force", action
="store_true", help="forces deletion without asking")
2105 tenant_delete_parser
.set_defaults(func
=tenant_delete
)
2107 tenant_list_parser
= subparsers
.add_parser('tenant-list', parents
=[parent_parser
], help="lists information about a tenant")
2108 tenant_list_parser
.add_argument("name", nargs
='?', help="name or uuid of the tenant")
2109 tenant_list_parser
.set_defaults(func
=tenant_list
)
2111 element_edit_parser
= subparsers
.add_parser('tenant-edit', parents
=[parent_parser
], help="edits one tenant")
2112 element_edit_parser
.add_argument("name", help="name or uuid of the tenant")
2113 element_edit_parser
.add_argument("file", help="json/yaml text or file with the changes").completer
= FilesCompleter
2114 element_edit_parser
.add_argument("-f","--force", action
="store_true", help="do not prompt for confirmation")
2115 element_edit_parser
.set_defaults(func
=element_edit
, element
='tenants')
2117 datacenter_create_parser
= subparsers
.add_parser('datacenter-create', parents
=[parent_parser
], help="creates a new datacenter")
2118 datacenter_create_parser
.add_argument("name", action
="store", help="name for the datacenter")
2119 datacenter_create_parser
.add_argument("url", action
="store", help="url for the datacenter")
2120 datacenter_create_parser
.add_argument("--url_admin", action
="store", help="url for administration for the datacenter")
2121 datacenter_create_parser
.add_argument("--type", action
="store", help="datacenter type: openstack or openvim (default)")
2122 datacenter_create_parser
.add_argument("--config", action
="store", help="aditional configuration in json/yaml format")
2123 datacenter_create_parser
.add_argument("--description", action
="store", help="description of the datacenter")
2124 datacenter_create_parser
.add_argument("--sdn-controller", action
="store", help="Name or uuid of the SDN controller to be used", dest
='sdn_controller')
2125 datacenter_create_parser
.set_defaults(func
=datacenter_create
)
2127 datacenter_delete_parser
= subparsers
.add_parser('datacenter-delete', parents
=[parent_parser
], help="deletes a datacenter from the catalogue")
2128 datacenter_delete_parser
.add_argument("name", action
="store", help="name or uuid of the datacenter to be deleted")
2129 datacenter_delete_parser
.add_argument("-f", "--force", action
="store_true", help="forces deletion without asking")
2130 datacenter_delete_parser
.set_defaults(func
=datacenter_delete
)
2132 datacenter_edit_parser
= subparsers
.add_parser('datacenter-edit', parents
=[parent_parser
], help="Edit datacenter")
2133 datacenter_edit_parser
.add_argument("name", help="name or uuid of the datacenter")
2134 datacenter_edit_parser
.add_argument("--file", help="json/yaml text or file with the changes").completer
= FilesCompleter
2135 datacenter_edit_parser
.add_argument("--sdn-controller", action
="store",
2136 help="Name or uuid of the SDN controller to be used. Specify 'null' to clear entry", dest
='sdn_controller')
2137 datacenter_edit_parser
.add_argument("-f", "--force", action
="store_true", help="do not prompt for confirmation")
2138 datacenter_edit_parser
.set_defaults(func
=datacenter_edit
)
2140 datacenter_list_parser
= subparsers
.add_parser('datacenter-list', parents
=[parent_parser
], help="lists information about a datacenter")
2141 datacenter_list_parser
.add_argument("name", nargs
='?', help="name or uuid of the datacenter")
2142 datacenter_list_parser
.add_argument("-a", "--all", action
="store_true", help="shows all datacenters, not only datacenters attached to tenant")
2143 datacenter_list_parser
.set_defaults(func
=datacenter_list
)
2145 datacenter_attach_parser
= subparsers
.add_parser('datacenter-attach', parents
=[parent_parser
], help="associates a datacenter to the operating tenant")
2146 datacenter_attach_parser
.add_argument("name", help="name or uuid of the datacenter")
2147 datacenter_attach_parser
.add_argument('--vim-tenant-id', action
='store', help="specify a datacenter tenant to use. A new one is created by default")
2148 datacenter_attach_parser
.add_argument('--vim-tenant-name', action
='store', help="specify a datacenter tenant name.")
2149 datacenter_attach_parser
.add_argument("--user", action
="store", help="user credentials for the datacenter")
2150 datacenter_attach_parser
.add_argument("--password", action
="store", help="password credentials for the datacenter")
2151 datacenter_attach_parser
.add_argument("--config", action
="store", help="aditional configuration in json/yaml format")
2152 datacenter_attach_parser
.set_defaults(func
=datacenter_attach
)
2154 datacenter_edit_vim_tenant_parser
= subparsers
.add_parser('datacenter-edit-vim-tenant', parents
=[parent_parser
],
2155 help="Edit the association of a datacenter to the operating tenant")
2156 datacenter_edit_vim_tenant_parser
.add_argument("name", help="name or uuid of the datacenter")
2157 datacenter_edit_vim_tenant_parser
.add_argument('--vim-tenant-id', action
='store',
2158 help="specify a datacenter tenant to use. A new one is created by default")
2159 datacenter_edit_vim_tenant_parser
.add_argument('--vim-tenant-name', action
='store', help="specify a datacenter tenant name.")
2160 datacenter_edit_vim_tenant_parser
.add_argument("--user", action
="store", help="user credentials for the datacenter")
2161 datacenter_edit_vim_tenant_parser
.add_argument("--password", action
="store", help="password credentials for the datacenter")
2162 datacenter_edit_vim_tenant_parser
.add_argument("--config", action
="store",
2163 help="aditional configuration in json/yaml format")
2164 datacenter_edit_vim_tenant_parser
.set_defaults(func
=datacenter_edit_vim_tenant
)
2166 datacenter_detach_parser
= subparsers
.add_parser('datacenter-detach', parents
=[parent_parser
], help="removes the association between a datacenter and the operating tenant")
2167 datacenter_detach_parser
.add_argument("name", help="name or uuid of the datacenter")
2168 datacenter_detach_parser
.add_argument("-a", "--all", action
="store_true", help="removes all associations from this datacenter")
2169 datacenter_detach_parser
.set_defaults(func
=datacenter_detach
)
2171 #=======================datacenter_sdn_port_mapping_xxx section=======================
2172 #datacenter_sdn_port_mapping_set
2173 datacenter_sdn_port_mapping_set_parser
= subparsers
.add_parser('datacenter-sdn-port-mapping-set',
2174 parents
=[parent_parser
],
2175 help="Load a file with the mapping of physical ports "
2176 "and the ports of the dataplaneswitch controlled "
2178 datacenter_sdn_port_mapping_set_parser
.add_argument("name", action
="store", help="specifies the datacenter")
2179 datacenter_sdn_port_mapping_set_parser
.add_argument("file",
2180 help="json/yaml text or file with the port mapping").completer
= FilesCompleter
2181 datacenter_sdn_port_mapping_set_parser
.add_argument("-f", "--force", action
="store_true",
2182 help="forces overwriting without asking")
2183 datacenter_sdn_port_mapping_set_parser
.set_defaults(func
=datacenter_sdn_port_mapping_set
)
2185 #datacenter_sdn_port_mapping_list
2186 datacenter_sdn_port_mapping_list_parser
= subparsers
.add_parser('datacenter-sdn-port-mapping-list',
2187 parents
=[parent_parser
],
2188 help="Show the SDN port mapping in a datacenter")
2189 datacenter_sdn_port_mapping_list_parser
.add_argument("name", action
="store", help="specifies the datacenter")
2190 datacenter_sdn_port_mapping_list_parser
.set_defaults(func
=datacenter_sdn_port_mapping_list
)
2192 # datacenter_sdn_port_mapping_clear
2193 datacenter_sdn_port_mapping_clear_parser
= subparsers
.add_parser('datacenter-sdn-port-mapping-clear',
2194 parents
=[parent_parser
],
2195 help="Clean the the SDN port mapping in a datacenter")
2196 datacenter_sdn_port_mapping_clear_parser
.add_argument("name", action
="store",
2197 help="specifies the datacenter")
2198 datacenter_sdn_port_mapping_clear_parser
.add_argument("-f", "--force", action
="store_true",
2199 help="forces clearing without asking")
2200 datacenter_sdn_port_mapping_clear_parser
.set_defaults(func
=datacenter_sdn_port_mapping_clear
)
2201 # =======================
2203 # =======================sdn_controller_xxx section=======================
2204 # sdn_controller_create
2205 sdn_controller_create_parser
= subparsers
.add_parser('sdn-controller-create', parents
=[parent_parser
],
2206 help="Creates an SDN controller entity within RO")
2207 sdn_controller_create_parser
.add_argument("name", help="name of the SDN controller")
2208 sdn_controller_create_parser
.add_argument("--description", action
="store", help="description of the SDN controller")
2209 sdn_controller_create_parser
.add_argument("--ip", action
="store", help="IP of the SDN controller")
2210 sdn_controller_create_parser
.add_argument("--port", action
="store", help="Port of the SDN controller")
2211 sdn_controller_create_parser
.add_argument("--dpid", action
="store",
2212 help="DPID of the dataplane switch controlled by this SDN controller")
2213 sdn_controller_create_parser
.add_argument("--type", action
="store",
2214 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
2215 sdn_controller_create_parser
.add_argument("--user", action
="store", help="user credentials for the SDN controller")
2216 sdn_controller_create_parser
.add_argument("--passwd", action
="store", dest
='password',
2217 help="password credentials for the SDN controller")
2218 sdn_controller_create_parser
.set_defaults(func
=sdn_controller_create
)
2220 # sdn_controller_edit
2221 sdn_controller_edit_parser
= subparsers
.add_parser('sdn-controller-edit', parents
=[parent_parser
],
2222 help="Update one or more options of a SDN controller")
2223 sdn_controller_edit_parser
.add_argument("name", help="name or uuid of the SDN controller", )
2224 sdn_controller_edit_parser
.add_argument("--name", action
="store", help="Update the name of the SDN controller",
2226 sdn_controller_edit_parser
.add_argument("--description", action
="store", help="description of the SDN controller")
2227 sdn_controller_edit_parser
.add_argument("--ip", action
="store", help="IP of the SDN controller")
2228 sdn_controller_edit_parser
.add_argument("--port", action
="store", help="Port of the SDN controller")
2229 sdn_controller_edit_parser
.add_argument("--dpid", action
="store",
2230 help="DPID of the dataplane switch controlled by this SDN controller")
2231 sdn_controller_edit_parser
.add_argument("--type", action
="store",
2232 help="Specify the SDN controller type. Valid types are 'opendaylight' and 'floodlight'")
2233 sdn_controller_edit_parser
.add_argument("--user", action
="store", help="user credentials for the SDN controller")
2234 sdn_controller_edit_parser
.add_argument("--password", action
="store",
2235 help="password credentials for the SDN controller", dest
='password')
2236 sdn_controller_edit_parser
.add_argument("-f", "--force", action
="store_true", help="do not prompt for confirmation")
2237 #TODO: include option --file
2238 sdn_controller_edit_parser
.set_defaults(func
=sdn_controller_edit
)
2240 #sdn_controller_list
2241 sdn_controller_list_parser
= subparsers
.add_parser('sdn-controller-list',
2242 parents
=[parent_parser
],
2243 help="List the SDN controllers")
2244 sdn_controller_list_parser
.add_argument("name", nargs
='?', help="name or uuid of the SDN controller")
2245 sdn_controller_list_parser
.set_defaults(func
=sdn_controller_list
)
2247 # sdn_controller_delete
2248 sdn_controller_delete_parser
= subparsers
.add_parser('sdn-controller-delete',
2249 parents
=[parent_parser
],
2250 help="Delete the the SDN controller")
2251 sdn_controller_delete_parser
.add_argument("name", help="name or uuid of the SDN controller")
2252 sdn_controller_delete_parser
.add_argument("-f", "--force", action
="store_true", help="forces deletion without asking")
2253 sdn_controller_delete_parser
.set_defaults(func
=sdn_controller_delete
)
2254 # =======================
2256 # WIM ======================= WIM section==================
2259 wim_create_parser
= subparsers
.add_parser('wim-create',
2260 parents
=[parent_parser
], help="creates a new wim")
2261 wim_create_parser
.add_argument("name", action
="store",
2262 help="name for the wim")
2263 wim_create_parser
.add_argument("url", action
="store",
2264 help="url for the wim")
2265 wim_create_parser
.add_argument("--type", action
="store",
2266 help="wim type: ietfl2vpn, dynpac, ...")
2267 wim_create_parser
.add_argument("--config", action
="store",
2268 help="additional configuration in json/yaml format")
2269 wim_create_parser
.add_argument("--description", action
="store",
2270 help="description of the wim")
2271 wim_create_parser
.set_defaults(func
=wim_create
)
2274 wim_delete_parser
= subparsers
.add_parser('wim-delete',
2275 parents
=[parent_parser
], help="deletes a wim from the catalogue")
2276 wim_delete_parser
.add_argument("name", action
="store",
2277 help="name or uuid of the wim to be deleted")
2278 wim_delete_parser
.add_argument("-f", "--force", action
="store_true",
2279 help="forces deletion without asking")
2280 wim_delete_parser
.set_defaults(func
=wim_delete
)
2283 wim_edit_parser
= subparsers
.add_parser('wim-edit',
2284 parents
=[parent_parser
], help="edits a wim")
2285 wim_edit_parser
.add_argument("name", help="name or uuid of the wim")
2286 wim_edit_parser
.add_argument("--file",
2287 help="json/yaml text or file with the changes")\
2288 .completer
= FilesCompleter
2289 wim_edit_parser
.add_argument("-f", "--force", action
="store_true",
2290 help="do not prompt for confirmation")
2291 wim_edit_parser
.set_defaults(func
=wim_edit
)
2294 wim_list_parser
= subparsers
.add_parser('wim-list',
2295 parents
=[parent_parser
],
2296 help="lists information about registered wims")
2297 wim_list_parser
.add_argument("name", nargs
='?',
2298 help="name or uuid of the wim")
2299 wim_list_parser
.add_argument("-a", "--all", action
="store_true",
2300 help="shows all wims, not only wims attached to tenant")
2301 wim_list_parser
.set_defaults(func
=wim_list
)
2303 # WIM account create
2304 wim_attach_parser
= subparsers
.add_parser('wim-account-create', parents
=
2305 [parent_parser
], help="associates a wim account to the operating tenant")
2306 wim_attach_parser
.add_argument("name", help="name or uuid of the wim")
2307 wim_attach_parser
.add_argument('--account-name', action
='store',
2308 help="specify a name for the wim account.")
2309 wim_attach_parser
.add_argument("--user", action
="store",
2310 help="user credentials for the wim account")
2311 wim_attach_parser
.add_argument("--password", action
="store",
2312 help="password credentials for the wim account")
2313 wim_attach_parser
.add_argument("--config", action
="store",
2314 help="additional configuration in json/yaml format")
2315 wim_attach_parser
.set_defaults(func
=wim_account_create
)
2317 # WIM account delete
2318 wim_detach_parser
= subparsers
.add_parser('wim-account-delete',
2319 parents
=[parent_parser
],
2320 help="removes the association "
2321 "between a wim account and the operating tenant")
2322 wim_detach_parser
.add_argument("name", help="name or uuid of the wim")
2323 wim_detach_parser
.add_argument("-a", "--all", action
="store_true",
2324 help="removes all associations from this wim")
2325 wim_detach_parser
.add_argument("-f", "--force", action
="store_true",
2326 help="forces delete without asking")
2327 wim_detach_parser
.set_defaults(func
=wim_account_delete
)
2330 wim_attach_edit_parser
= subparsers
.add_parser('wim-account-edit', parents
=
2331 [parent_parser
], help="modifies the association of a wim account to the operating tenant")
2332 wim_attach_edit_parser
.add_argument("name", help="name or uuid of the wim")
2333 wim_attach_edit_parser
.add_argument('--account-name', action
='store',
2334 help="specify a name for the wim account.")
2335 wim_attach_edit_parser
.add_argument("--user", action
="store",
2336 help="user credentials for the wim account")
2337 wim_attach_edit_parser
.add_argument("--password", action
="store",
2338 help="password credentials for the wim account")
2339 wim_attach_edit_parser
.add_argument("--config", action
="store",
2340 help="additional configuration in json/yaml format")
2341 wim_attach_edit_parser
.set_defaults(func
=wim_account_edit
)
2343 # WIM port mapping set
2344 wim_port_mapping_set_parser
= subparsers
.add_parser('wim-port-mapping-set',
2345 parents
=[parent_parser
],
2346 help="Load a file with the mappings "
2347 "of ports of a WAN switch that is "
2348 "connected to a PoP and the ports "
2349 "of the switch controlled by the PoP")
2350 wim_port_mapping_set_parser
.add_argument("name", action
="store",
2351 help="specifies the wim")
2352 wim_port_mapping_set_parser
.add_argument("file",
2353 help="json/yaml text or file with the wim port mapping")\
2354 .completer
= FilesCompleter
2355 wim_port_mapping_set_parser
.add_argument("-f", "--force",
2356 action
="store_true", help="forces overwriting without asking")
2357 wim_port_mapping_set_parser
.set_defaults(func
=wim_port_mapping_set
)
2359 # WIM port mapping list
2360 wim_port_mapping_list_parser
= subparsers
.add_parser('wim-port-mapping-list',
2361 parents
=[parent_parser
], help="Show the port mappings for a wim")
2362 wim_port_mapping_list_parser
.add_argument("name", action
="store",
2363 help="specifies the wim")
2364 wim_port_mapping_list_parser
.set_defaults(func
=wim_port_mapping_list
)
2366 # WIM port mapping clear
2367 wim_port_mapping_clear_parser
= subparsers
.add_parser('wim-port-mapping-clear',
2368 parents
=[parent_parser
], help="Clean the port mapping in a wim")
2369 wim_port_mapping_clear_parser
.add_argument("name", action
="store",
2370 help="specifies the wim")
2371 wim_port_mapping_clear_parser
.add_argument("-f", "--force",
2372 action
="store_true",
2373 help="forces clearing without asking")
2374 wim_port_mapping_clear_parser
.set_defaults(func
=wim_port_mapping_clear
)
2376 # =======================================================
2378 action_dict
={'net-update': 'retrieves external networks from datacenter',
2379 'net-edit': 'edits an external network',
2380 'net-delete': 'deletes an external network',
2381 'net-list': 'lists external networks from a datacenter'
2383 for item
in action_dict
:
2384 datacenter_action_parser
= subparsers
.add_parser('datacenter-'+item
, parents
=[parent_parser
], help=action_dict
[item
])
2385 datacenter_action_parser
.add_argument("datacenter", help="name or uuid of the datacenter")
2386 if item
=='net-edit' or item
=='net-delete':
2387 datacenter_action_parser
.add_argument("net", help="name or uuid of the datacenter net")
2388 if item
=='net-edit':
2389 datacenter_action_parser
.add_argument("file", help="json/yaml text or file with the changes").completer
= FilesCompleter
2390 if item
!='net-list':
2391 datacenter_action_parser
.add_argument("-f","--force", action
="store_true", help="do not prompt for confirmation")
2392 datacenter_action_parser
.set_defaults(func
=datacenter_net_action
, action
=item
)
2395 action_dict
={'netmap-import': 'create network senario netmap base on the datacenter networks',
2396 'netmap-create': 'create a new network senario netmap',
2397 'netmap-edit': 'edit name of a network senario netmap',
2398 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)',
2399 'netmap-list': 'list/show network scenario netmaps'
2401 for item
in action_dict
:
2402 datacenter_action_parser
= subparsers
.add_parser('datacenter-'+item
, parents
=[parent_parser
], help=action_dict
[item
])
2403 datacenter_action_parser
.add_argument("--datacenter", help="name or uuid of the datacenter")
2404 #if item=='net-add':
2405 # datacenter_action_parser.add_argument("net", help="name of the network")
2406 if item
=='netmap-delete':
2407 datacenter_action_parser
.add_argument("netmap", nargs
='?',help="name or uuid of the datacenter netmap to delete")
2408 datacenter_action_parser
.add_argument("--all", action
="store_true", help="delete all netmap of this datacenter")
2409 datacenter_action_parser
.add_argument("-f","--force", action
="store_true", help="do not prompt for confirmation")
2410 if item
=='netmap-edit':
2411 datacenter_action_parser
.add_argument("netmap", help="name or uuid of the datacenter netmap do edit")
2412 datacenter_action_parser
.add_argument("file", nargs
='?', help="json/yaml text or file with the changes").completer
= FilesCompleter
2413 datacenter_action_parser
.add_argument("--name", action
='store', help="name to assign to the datacenter netmap")
2414 datacenter_action_parser
.add_argument('--vim-id', action
='store', help="specify vim network uuid")
2415 datacenter_action_parser
.add_argument("-f","--force", action
="store_true", help="do not prompt for confirmation")
2416 if item
=='netmap-list':
2417 datacenter_action_parser
.add_argument("netmap", nargs
='?',help="name or uuid of the datacenter netmap to show")
2418 if item
=='netmap-create':
2419 datacenter_action_parser
.add_argument("file", nargs
='?', help="json/yaml text or file descriptor with the changes").completer
= FilesCompleter
2420 datacenter_action_parser
.add_argument("--name", action
='store', help="name to assign to the datacenter netmap, by default same as vim-name")
2421 datacenter_action_parser
.add_argument('--vim-id', action
='store', help="specify vim network uuid")
2422 datacenter_action_parser
.add_argument('--vim-name', action
='store', help="specify vim network name")
2423 if item
=='netmap-import':
2424 datacenter_action_parser
.add_argument("-f","--force", action
="store_true", help="do not prompt for confirmation")
2425 datacenter_action_parser
.set_defaults(func
=datacenter_netmap_action
, action
=item
)
2427 # =======================vim_net_sdn_xxx section=======================
2428 # vim_net_sdn_attach
2429 vim_net_sdn_attach_parser
= subparsers
.add_parser('vim-net-sdn-attach',
2430 parents
=[parent_parser
],
2431 help="Specify the port to access to an external network using SDN")
2432 vim_net_sdn_attach_parser
.add_argument("vim_net", action
="store",
2433 help="Name/id of the network in the vim that will be used to connect to the external network")
2434 vim_net_sdn_attach_parser
.add_argument("port", action
="store", help="Specifies the port in the dataplane switch to access to the external network")
2435 vim_net_sdn_attach_parser
.add_argument("--vlan", action
="store", help="Specifies the vlan (if any) to use in the defined port")
2436 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")
2437 vim_net_sdn_attach_parser
.add_argument("--datacenter", action
="store", help="specifies the datacenter")
2438 vim_net_sdn_attach_parser
.set_defaults(func
=vim_net_sdn_attach
)
2440 # vim_net_sdn_detach
2441 vim_net_sdn_detach_parser
= subparsers
.add_parser('vim-net-sdn-detach',
2442 parents
=[parent_parser
],
2443 help="Remove the port information to access to an external network using SDN")
2445 vim_net_sdn_detach_parser
.add_argument("vim_net", action
="store", help="Name/id of the vim network")
2446 vim_net_sdn_detach_parser
.add_argument("--id", action
="store",help="Specify the uuid of the external ports from this network to be detached")
2447 vim_net_sdn_detach_parser
.add_argument("--all", action
="store_true", help="Detach all external ports from this network")
2448 vim_net_sdn_detach_parser
.add_argument("-f", "--force", action
="store_true", help="forces clearing without asking")
2449 vim_net_sdn_detach_parser
.add_argument("--datacenter", action
="store", help="specifies the datacenter")
2450 vim_net_sdn_detach_parser
.set_defaults(func
=vim_net_sdn_detach
)
2451 # =======================
2453 for item
in ("network", "tenant", "image"):
2455 command_name
= 'vim-net'
2457 command_name
= 'vim-'+item
2458 vim_item_list_parser
= subparsers
.add_parser(command_name
+ '-list', parents
=[parent_parser
], help="list the vim " + item
+ "s")
2459 vim_item_list_parser
.add_argument("name", nargs
='?', help="name or uuid of the " + item
+ "s")
2460 vim_item_list_parser
.add_argument("--datacenter", action
="store", help="specifies the datacenter")
2461 vim_item_list_parser
.set_defaults(func
=vim_action
, item
=item
, action
="list")
2463 vim_item_del_parser
= subparsers
.add_parser(command_name
+ '-delete', parents
=[parent_parser
], help="list the vim " + item
+ "s")
2464 vim_item_del_parser
.add_argument("name", help="name or uuid of the " + item
+ "s")
2465 vim_item_del_parser
.add_argument("--datacenter", action
="store", help="specifies the datacenter")
2466 vim_item_del_parser
.set_defaults(func
=vim_action
, item
=item
, action
="delete")
2468 if item
== "network" or item
== "tenant":
2469 vim_item_create_parser
= subparsers
.add_parser(command_name
+ '-create', parents
=[parent_parser
], help="create a "+item
+" at vim")
2470 vim_item_create_parser
.add_argument("file", nargs
='?', help="descriptor of the {}. Must be a file or yaml/json text".format(item
)).completer
= FilesCompleter
2471 vim_item_create_parser
.add_argument("--name", action
="store", help="name of the {}".format(item
))
2472 vim_item_create_parser
.add_argument("--datacenter", action
="store", help="specifies the datacenter")
2474 vim_item_create_parser
.add_argument("--type", action
="store", help="type of network, data, ptp, bridge")
2475 vim_item_create_parser
.add_argument("--shared", action
="store_true", help="Private or shared")
2476 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>'")
2478 vim_item_create_parser
.add_argument("--description", action
="store", help="description of the {}".format(item
))
2479 vim_item_create_parser
.set_defaults(func
=vim_action
, item
=item
, action
="create")
2481 argcomplete
.autocomplete(main_parser
)
2484 args
= main_parser
.parse_args()
2486 level
= logging
.CRITICAL
2487 streamformat
= "%(asctime)s %(name)s %(levelname)s: %(message)s"
2488 if "debug" in args
and args
.debug
:
2489 level
= logging
.DEBUG
2490 logging
.basicConfig(format
=streamformat
, level
= level
)
2491 logger
= logging
.getLogger('mano')
2492 logger
.setLevel(level
)
2493 # print("#TODO py3", args)
2494 result
= args
.func(args
)
2497 #for some reason it fails if call exit inside try instance. Need to call exit at the end !?
2498 except (requests
.exceptions
.ConnectionError
):
2499 print("Connection error: not possible to contact OPENMANO-SERVER (openmanod)")
2501 except (KeyboardInterrupt):
2502 print('Exiting openmano')
2504 except (SystemExit, ArgumentParserError
):
2506 except (AttributeError):
2507 print("Type '--help' for more information")
2509 except OpenmanoCLIError
as e
:
2510 # print("#TODO py3", e)
2518 if __name__
== '__main__':