2 # -*- coding: utf-8 -*-
5 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6 # This file is part of openmano
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact with: nfvlabs@tid.es
26 openmano python client used to interact with openmano-server
28 __author__
="Alfonso Tierno, Pablo Montes"
29 __date__
="$09-Mar-2016 09:09:48$"
30 __version__
="0.0.2-r468"
31 version_date
="Feb 2017"
38 if sys
.version_info
.major
== 3:
39 from urllib
.parse
import quote
40 elif sys
.version_info
.major
== 2:
41 from urllib
import quote
43 class OpenmanoException(Exception):
44 '''Common Exception for all openmano client exceptions'''
46 class OpenmanoBadParamsException(OpenmanoException
):
47 '''Bad or missing input parameters'''
49 class OpenmanoResponseException(OpenmanoException
):
50 '''Unexpected response from openmano server'''
52 class OpenmanoNotFoundException(OpenmanoException
):
53 '''Not found at server'''
56 # def __init__(self, message):
57 # print "Error: %s" %message
62 # print "Type 'openmano -h' for help"
64 class openmanoclient():
65 headers_req
= {'Accept': 'application/yaml', 'content-type': 'application/yaml'}
67 def __init__(self
, **kwargs
):
68 self
.username
= kwargs
.get("username")
69 self
.password
= kwargs
.get("password")
70 self
.endpoint_url
= kwargs
.get("endpoint_url")
71 self
.tenant_id
= kwargs
.get("tenant_id")
72 self
.tenant_name
= kwargs
.get("tenant_name")
74 self
.datacenter_id
= kwargs
.get("datacenter_id")
75 self
.datacenter_name
= kwargs
.get("datacenter_name")
76 self
.datacenter
= None
77 self
.logger
= logging
.getLogger(kwargs
.get('logger','manoclient'))
78 if kwargs
.get("debug"):
79 self
.logger
.setLevel(logging
.DEBUG
)
81 def __getitem__(self
, index
):
82 if index
=='tenant_name':
83 return self
.tenant_name
84 elif index
=='tenant_id':
86 elif index
=='datacenter_name':
87 return self
.datacenter_name
88 elif index
=='datacenter_id':
89 return self
.datacenter_id
90 elif index
=='username':
92 elif index
=='password':
94 elif index
=='endpoint_url':
95 return self
.endpoint_url
97 raise KeyError("Invalid key '%s'" %str
(index
))
99 def __setitem__(self
,index
, value
):
100 if index
=='tenant_name':
101 self
.tenant_name
= value
102 elif index
=='tenant_id':
103 self
.tenant_id
= value
104 elif index
=='datacenter_name':
105 self
.datacenter_name
= value
106 elif index
=='datacenter_id':
107 self
.datacenter_id
= value
108 elif index
=='username':
109 self
.username
= value
110 elif index
=='password':
111 self
.password
= value
112 elif index
=='endpoint_url':
113 self
.endpoint_url
= value
115 raise KeyError("Invalid key '%s'" %str
(index
))
116 self
.tenant
= None # force to reload tenant with different credentials
117 self
.datacenter
= None # force to reload datacenter with different credentials
119 def _parse(self
, descriptor
, descriptor_format
, response
=False):
121 if descriptor_format
and descriptor_format
!= "json" and descriptor_format
!= "yaml":
122 raise OpenmanoBadParamsException("'descriptor_format' must be a 'json' or 'yaml' text")
123 if descriptor_format
!= "json":
125 return yaml
.load(descriptor
)
126 except yaml
.YAMLError
as exc
:
128 if hasattr(exc
, 'problem_mark'):
129 mark
= exc
.problem_mark
130 error_pos
= " at line:{} column:{}s".format(mark
.line
+1, mark
.column
+1)
131 error_text
= "yaml format error" + error_pos
132 elif descriptor_format
!= "yaml":
134 return json
.loads(descriptor
)
135 except Exception as e
:
137 error_text
= "json format error" + str(e
)
140 raise OpenmanoResponseException(error_text
)
141 raise OpenmanoBadParamsException(error_text
)
143 def _parse_yaml(self
, descriptor
, response
=False):
145 return yaml
.load(descriptor
)
146 except yaml
.YAMLError
as exc
:
148 if hasattr(exc
, 'problem_mark'):
149 mark
= exc
.problem_mark
150 error_pos
= " at line:{} column:{}s".format(mark
.line
+1, mark
.column
+1)
151 error_text
= "yaml format error" + error_pos
153 raise OpenmanoResponseException(error_text
)
154 raise OpenmanoBadParamsException(error_text
)
157 def _get_item_uuid(self
, item
, item_id
=None, item_name
=None, all_tenants
=False):
158 if all_tenants
== None:
160 elif all_tenants
== False:
161 tenant_text
= "/" + self
.tenant
164 URLrequest
= "{}{}/{}".format(self
.endpoint_url
, tenant_text
, item
)
165 self
.logger
.debug("GET %s", URLrequest
)
166 mano_response
= requests
.get(URLrequest
, headers
=self
.headers_req
)
167 self
.logger
.debug("openmano response: %s", mano_response
.text
)
168 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
171 if not item_id
and not item_name
:
172 raise OpenmanoResponseException("Missing either {0}_name or {0}_id".format(item
[:-1]))
173 for i
in content
[item
]:
174 if item_id
and i
["uuid"] == item_id
:
176 elif item_name
and i
["name"] == item_name
:
182 raise OpenmanoNotFoundException("No {} found with id '{}'".format(item
[:-1], item_id
))
184 #print(item, item_name)
185 raise OpenmanoNotFoundException("No {} found with name '{}'".format(item
[:-1], item_name
) )
187 raise OpenmanoNotFoundException("{} {} found with name '{}'. uuid must be used".format(found
, item
, item_name
))
190 def _get_item(self
, item
, uuid
=None, name
=None, all_tenants
=False):
193 elif all_tenants
==None:
196 tenant_text
= "/"+self
._get
_tenant
()
199 uuid
= self
._get
_item
_uuid
(item
, uuid
, name
, all_tenants
)
201 URLrequest
= "{}{}/{}/{}".format(self
.endpoint_url
, tenant_text
, item
, uuid
)
202 self
.logger
.debug("GET %s", URLrequest
)
203 mano_response
= requests
.get(URLrequest
, headers
=self
.headers_req
)
204 self
.logger
.debug("openmano response: %s", mano_response
.text
)
206 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
207 if mano_response
.status_code
==200:
210 raise OpenmanoResponseException(str(content
))
212 def _get_tenant(self
):
214 self
.tenant
= self
._get
_item
_uuid
("tenants", self
.tenant_id
, self
.tenant_name
, None)
217 def _get_datacenter(self
):
220 if not self
.datacenter
:
221 self
.datacenter
= self
._get
_item
_uuid
("datacenters", self
.datacenter_id
, self
.datacenter_name
, False)
222 return self
.datacenter
224 def _create_item(self
, item
, descriptor
, all_tenants
=False):
227 elif all_tenants
==None:
230 tenant_text
= "/"+self
._get
_tenant
()
231 payload_req
= yaml
.safe_dump(descriptor
)
235 URLrequest
= "{}{}/{}".format(self
.endpoint_url
, tenant_text
, item
)
236 self
.logger
.debug("openmano POST %s %s", URLrequest
, payload_req
)
237 mano_response
= requests
.post(URLrequest
, headers
= self
.headers_req
, data
=payload_req
)
238 self
.logger
.debug("openmano response: %s", mano_response
.text
)
240 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
241 if mano_response
.status_code
==200:
244 raise OpenmanoResponseException(str(content
))
246 def _del_item(self
, item
, uuid
=None, name
=None, all_tenants
=False):
249 elif all_tenants
==None:
252 tenant_text
= "/"+self
._get
_tenant
()
255 uuid
= self
._get
_item
_uuid
(item
, uuid
, name
, all_tenants
)
257 URLrequest
= "{}{}/{}/{}".format(self
.endpoint_url
, tenant_text
, item
, uuid
)
258 self
.logger
.debug("DELETE %s", URLrequest
)
259 mano_response
= requests
.delete(URLrequest
, headers
= self
.headers_req
)
260 self
.logger
.debug("openmano response: %s", mano_response
.text
)
262 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
263 if mano_response
.status_code
==200:
266 raise OpenmanoResponseException(str(content
))
268 def _list_item(self
, item
, all_tenants
=False, filter_dict
=None):
271 elif all_tenants
==None:
274 tenant_text
= "/"+self
._get
_tenant
()
276 URLrequest
= "{}{}/{}".format(self
.endpoint_url
, tenant_text
, item
)
279 for k
in filter_dict
:
280 URLrequest
+= separator
+ quote(str(k
)) + "=" + quote(str(filter_dict
[k
]))
282 self
.logger
.debug("openmano GET %s", URLrequest
)
283 mano_response
= requests
.get(URLrequest
, headers
=self
.headers_req
)
284 self
.logger
.debug("openmano response: %s", mano_response
.text
)
286 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
287 if mano_response
.status_code
==200:
290 raise OpenmanoResponseException(str(content
))
292 def _edit_item(self
, item
, descriptor
, uuid
=None, name
=None, all_tenants
=False):
295 elif all_tenants
==None:
298 tenant_text
= "/"+self
._get
_tenant
()
302 uuid
= self
._get
_item
_uuid
("tenants", uuid
, name
, all_tenants
)
304 payload_req
= yaml
.safe_dump(descriptor
)
308 URLrequest
= "{}{}/{}/{}".format(self
.endpoint_url
, tenant_text
, item
, uuid
)
309 self
.logger
.debug("openmano PUT %s %s", URLrequest
, payload_req
)
310 mano_response
= requests
.put(URLrequest
, headers
= self
.headers_req
, data
=payload_req
)
311 self
.logger
.debug("openmano response: %s", mano_response
.text
)
313 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
314 if mano_response
.status_code
==200:
317 raise OpenmanoResponseException(str(content
))
320 def list_tenants(self
, **kwargs
):
321 '''Obtain a list of tenants
322 Params: can be filtered by 'uuid','name','description'
323 Return: Raises an exception on error
324 Obtain a dictionary with format {'tenants':[{tenant1_info},{tenant2_info},...]}}
326 return self
._list
_item
("tenants", all_tenants
=None, filter_dict
=kwargs
)
328 def get_tenant(self
, uuid
=None, name
=None):
329 '''Obtain the information of a tenant
330 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
331 Return: Raises an exception on error, not found, found several
332 Obtain a dictionary with format {'tenant':{tenant_info}}
334 return self
._get
_item
("tenants", uuid
, name
, all_tenants
=None)
336 def delete_tenant(self
, uuid
=None, name
=None):
338 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
339 Return: Raises an exception on error, not found, found several
340 Obtain a dictionary with format {'result': text indicating deleted}
342 return self
._del
_item
("tenants", uuid
, name
, all_tenants
=None)
344 def create_tenant(self
, descriptor
=None, descriptor_format
=None, name
=None, description
=None):
346 Params: must supply a descriptor or/and just a name
347 descriptor: with format {'tenant':{new_tenant_info}}
348 newtenant_info must contain 'name', and optionally 'description'
349 must be a dictionary or a json/yaml text.
350 name: the tenant name. Overwrite descriptor name if any
351 description: tenant descriptor.. Overwrite descriptor description if any
352 Return: Raises an exception on error
353 Obtain a dictionary with format {'tenant':{new_tenant_info}}
355 if isinstance(descriptor
, str):
356 descriptor
= self
._parse
(descriptor
, descriptor_format
)
360 descriptor
={"tenant": {"name": name
}}
362 raise OpenmanoBadParamsException("Missing descriptor")
364 if 'tenant' not in descriptor
or len(descriptor
)!=1:
365 raise OpenmanoBadParamsException("Descriptor must contain only one 'tenant' field")
367 descriptor
['tenant']['name'] = name
369 descriptor
['tenant']['description'] = description
371 return self
._create
_item
("tenants", descriptor
, all_tenants
=None)
373 def edit_tenant(self
, uuid
=None, name
=None, descriptor
=None, descriptor_format
=None, new_name
=None, new_description
=None):
374 '''Edit the parameters of a tenant
375 Params: must supply a descriptor or/and a new_name or new_description
376 uuid or/and name. If only name is supplied, there must be only one or an exception is raised
377 descriptor: with format {'tenant':{params to change info}}
378 must be a dictionary or a json/yaml text.
379 name: the tenant name. Overwrite descriptor name if any
380 description: tenant descriptor.. Overwrite descriptor description if any
381 Return: Raises an exception on error, not found or found several
382 Obtain a dictionary with format {'tenant':{newtenant_info}}
385 if isinstance(descriptor
, str):
386 descriptor
= self
.parse(descriptor
, descriptor_format
)
389 elif new_name
or new_description
:
390 descriptor
={"tenant": {}}
392 raise OpenmanoBadParamsException("Missing descriptor")
394 if 'tenant' not in descriptor
or len(descriptor
)!=1:
395 raise OpenmanoBadParamsException("Descriptor must contain only one 'tenant' field")
397 descriptor
['tenant']['name'] = new_name
399 descriptor
['tenant']['description'] = new_description
401 return self
._edit
_item
("tenants", descriptor
, uuid
, name
, all_tenants
=None)
405 def list_datacenters(self
, all_tenants
=False, **kwargs
):
406 '''Obtain a list of datacenters, that are the VIM information at openmano
407 Params: can be filtered by 'uuid','name','vim_url','type'
408 Return: Raises an exception on error
409 Obtain a dictionary with format {'datacenters':[{datacenter1_info},{datacenter2_info},...]}}
411 return self
._list
_item
("datacenters", all_tenants
, filter_dict
=kwargs
)
413 def get_datacenter(self
, uuid
=None, name
=None, all_tenants
=False):
414 '''Obtain the information of a datacenter
415 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
416 Return: Raises an exception on error, not found, found several
417 Obtain a dictionary with format {'datacenter':{datacenter_info}}
419 return self
._get
_item
("datacenters", uuid
, name
, all_tenants
)
421 def delete_datacenter(self
, uuid
=None, name
=None):
422 '''Delete a datacenter
423 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
424 Return: Raises an exception on error, not found, found several, not free
425 Obtain a dictionary with format {'result': text indicating deleted}
429 uuid
= self
._get
_item
_uuid
("datacenters", uuid
, name
, all_tenants
=True)
430 return self
._del
_item
("datacenters", uuid
, name
, all_tenants
=None)
432 def create_datacenter(self
, descriptor
=None, descriptor_format
=None, name
=None, vim_url
=None, **kwargs
):
433 #, type="openvim", public=False, description=None):
434 '''Creates a datacenter
435 Params: must supply a descriptor or/and just a name and vim_url
436 descriptor: with format {'datacenter':{new_datacenter_info}}
437 newdatacenter_info must contain 'name', 'vim_url', and optionally 'description'
438 must be a dictionary or a json/yaml text.
439 name: the datacenter name. Overwrite descriptor name if any
440 vim_url: the datacenter URL. Overwrite descriptor vim_url if any
441 vim_url_admin: the datacenter URL for administrative issues. Overwrite descriptor vim_url if any
442 vim_type: the datacenter type, can be openstack or openvim. Overwrite descriptor type if any
443 public: boolean, by default not public
444 description: datacenter description. Overwrite descriptor description if any
445 config: dictionary with extra configuration for the concrete datacenter
446 Return: Raises an exception on error
447 Obtain a dictionary with format {'datacenter':{new_datacenter_info}}
449 if isinstance(descriptor
, str):
450 descriptor
= self
.parse(descriptor
, descriptor_format
)
453 elif name
and vim_url
:
454 descriptor
={"datacenter": {"name": name
, "vim_url": vim_url
}}
456 raise OpenmanoBadParamsException("Missing descriptor, or name and vim_url")
458 if 'datacenter' not in descriptor
or len(descriptor
)!=1:
459 raise OpenmanoBadParamsException("Descriptor must contain only one 'datacenter' field")
461 descriptor
['datacenter']['name'] = name
463 descriptor
['datacenter']['vim_url'] = vim_url
465 descriptor
['datacenter'][param
] = kwargs
[param
]
467 return self
._create
_item
("datacenters", descriptor
, all_tenants
=None)
469 def edit_datacenter(self
, uuid
=None, name
=None, descriptor
=None, descriptor_format
=None, all_tenants
=False, **kwargs
):
470 '''Edit the parameters of a datacenter
471 Params: must supply a descriptor or/and a parameter to change
472 uuid or/and name. If only name is supplied, there must be only one or an exception is raised
473 descriptor: with format {'datacenter':{params to change info}}
474 must be a dictionary or a json/yaml text.
475 parameters to change can be supplyied by the descriptor or as parameters:
476 new_name: the datacenter name
477 vim_url: the datacenter URL
478 vim_url_admin: the datacenter URL for administrative issues
479 vim_type: the datacenter type, can be openstack or openvim.
480 public: boolean, available to other tenants
481 description: datacenter description
482 Return: Raises an exception on error, not found or found several
483 Obtain a dictionary with format {'datacenter':{new_datacenter_info}}
486 if isinstance(descriptor
, str):
487 descriptor
= self
.parse(descriptor
, descriptor_format
)
491 descriptor
={"datacenter": {}}
493 raise OpenmanoBadParamsException("Missing descriptor")
495 if 'datacenter' not in descriptor
or len(descriptor
)!=1:
496 raise OpenmanoBadParamsException("Descriptor must contain only one 'datacenter' field")
498 if param
=='new_name':
499 descriptor
['datacenter']['name'] = kwargs
[param
]
501 descriptor
['datacenter'][param
] = kwargs
[param
]
502 return self
._edit
_item
("datacenters", descriptor
, uuid
, name
, all_tenants
=None)
504 def attach_datacenter(self
, uuid
=None, name
=None, descriptor
=None, descriptor_format
=None, vim_user
=None, vim_password
=None, vim_tenant_name
=None, vim_tenant_id
=None):
506 uuid
= self
._get
_item
_uuid
("datacenters", uuid
, name
, all_tenants
=True)
507 tenant_text
= "/"+self
._get
_tenant
()
509 if isinstance(descriptor
, str):
510 descriptor
= self
.parse(descriptor
, descriptor_format
)
513 elif vim_user
or vim_password
or vim_tenant_name
or vim_tenant_id
:
514 descriptor
={"datacenter": {}}
516 raise OpenmanoBadParamsException("Missing descriptor or params")
518 if vim_user
or vim_password
or vim_tenant_name
or vim_tenant_id
:
522 descriptor
['datacenter']['vim_user'] = vim_user
524 descriptor
['datacenter']['vim_password'] = vim_password
526 descriptor
['datacenter']['vim_tenant_name'] = vim_tenant_name
528 descriptor
['datacenter']['vim_tenant'] = vim_tenant_id
529 except (KeyError, TypeError) as e
:
530 if str(e
)=='datacenter': error_pos
= "missing field 'datacenter'"
531 else: error_pos
="wrong format"
532 raise OpenmanoBadParamsException("Wrong datacenter descriptor: " + error_pos
)
534 payload_req
= yaml
.safe_dump(descriptor
)
536 URLrequest
= "{}{}/datacenters/{}".format(self
.endpoint_url
, tenant_text
, uuid
)
537 self
.logger
.debug("openmano POST %s %s", URLrequest
, payload_req
)
538 mano_response
= requests
.post(URLrequest
, headers
= self
.headers_req
, data
=payload_req
)
539 self
.logger
.debug("openmano response: %s", mano_response
.text
)
541 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
542 if mano_response
.status_code
==200:
545 raise OpenmanoResponseException(str(content
))
547 def detach_datacenter(self
, uuid
=None, name
=None):
550 uuid
= self
._get
_item
_uuid
("datacenters", uuid
, name
, all_tenants
=False)
551 tenant_text
= "/"+self
._get
_tenant
()
552 URLrequest
= "{}{}/datacenters/{}".format(self
.endpoint_url
, tenant_text
, uuid
)
553 self
.logger
.debug("openmano DELETE %s", URLrequest
)
554 mano_response
= requests
.delete(URLrequest
, headers
= self
.headers_req
)
555 self
.logger
.debug("openmano response: %s", mano_response
.text
)
557 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
558 if mano_response
.status_code
==200:
561 raise OpenmanoResponseException(str(content
))
564 def list_vnfs(self
, all_tenants
=False, **kwargs
):
565 '''Obtain a list of vnfs
566 Params: can be filtered by 'uuid','name','description','public', "tenant_id"
567 Return: Raises an exception on error
568 Obtain a dictionary with format {'vnfs':[{vnf1_info},{vnf2_info},...]}}
570 return self
._list
_item
("vnfs", all_tenants
, kwargs
)
572 def get_vnf(self
, uuid
=None, name
=None, all_tenants
=False):
573 '''Obtain the information of a vnf
574 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
575 Return: Raises an exception on error, not found, found several
576 Obtain a dictionary with format {'vnf':{vnf_info}}
578 return self
._get
_item
("vnfs", uuid
, name
, all_tenants
)
580 def delete_vnf(self
, uuid
=None, name
=None, all_tenants
=False):
582 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
583 Return: Raises an exception on error, not found, found several, not free
584 Obtain a dictionary with format {'result': text indicating deleted}
586 return self
._del
_item
("vnfs", uuid
, name
, all_tenants
)
588 def create_vnf(self
, descriptor
=None, descriptor_format
=None, **kwargs
):
590 Params: must supply a descriptor
591 descriptor: with format {'vnf':{new_vnf_info}}
592 must be a dictionary or a json/yaml text.
593 must be a dictionary or a json/yaml text.
594 Other parameters can be:
595 name: the vnf name. Overwrite descriptor name if any
596 image_path: Can be a string or a string list. Overwrite the image_path at descriptor
597 description: vnf descriptor.. Overwrite descriptor description if any
598 public: boolean, available to other tenants
599 class: user text for vnf classification
600 tenant_id: Propietary tenant
602 Return: Raises an exception on error
603 Obtain a dictionary with format {'vnf':{new_vnf_info}}
605 if isinstance(descriptor
, str):
606 descriptor
= self
.parse(descriptor
, descriptor_format
)
610 raise OpenmanoBadParamsException("Missing descriptor")
612 if 'vnf' not in descriptor
or len(descriptor
)>2:
613 raise OpenmanoBadParamsException("Descriptor must contain only one 'vnf' field, and an optional version")
615 if param
== 'image_path':
618 if isinstance(kwargs
[param
], str):
619 descriptor
['vnf']['VNFC'][0]['VNFC image']=kwargs
[param
]
620 elif isinstance(kwargs
[param
], tuple) or isinstance(kwargs
[param
], list):
622 for image_path_
in kwargs
[param
]:
623 #print "image-path", image_path_
624 descriptor
['vnf']['VNFC'][index
]['VNFC image']=image_path_
627 raise OpenmanoBadParamsException("Wrong image_path type. Expected text or a text list")
628 except (KeyError, TypeError) as e
:
629 if str(e
)=='vnf': error_pos
= "missing field 'vnf'"
630 elif str(e
)=='VNFC': error_pos
= "missing field 'vnf':'VNFC'"
631 elif str(e
)==str(index
): error_pos
= "field 'vnf':'VNFC' must be an array"
632 elif str(e
)=='VNFC image': error_pos
= "missing field 'vnf':'VNFC'['VNFC image']"
633 else: error_pos
="wrong format"
634 raise OpenmanoBadParamsException("Wrong VNF descriptor: " + error_pos
)
636 descriptor
['vnf'][param
] = kwargs
[param
]
637 return self
._create
_item
("vnfs", descriptor
)
639 # def edit_vnf(self, uuid=None, name=None, descriptor=None, descriptor_format=None, all_tenants=False, **kwargs):
640 # '''Edit the parameters of a vnf
641 # Params: must supply a descriptor or/and a parameters to change
642 # uuid or/and name. If only name is supplied, there must be only one or an exception is raised
643 # descriptor: with format {'vnf':{params to change info}}
644 # parameters to change can be supplyied by the descriptor or as parameters:
645 # new_name: the vnf name
646 # vim_url: the vnf URL
647 # vim_url_admin: the vnf URL for administrative issues
648 # vim_type: the vnf type, can be openstack or openvim.
649 # public: boolean, available to other tenants
650 # description: vnf description
651 # Return: Raises an exception on error, not found or found several
652 # Obtain a dictionary with format {'vnf':{new_vnf_info}}
655 # if isinstance(descriptor, str):
656 # descriptor = self.parse(descriptor, descriptor_format)
660 # descriptor={"vnf": {}}
662 # raise OpenmanoBadParamsException("Missing descriptor")
664 # if 'vnf' not in descriptor or len(descriptor)>2:
665 # raise OpenmanoBadParamsException("Descriptor must contain only one 'vnf' field")
666 # for param in kwargs:
667 # if param=='new_name':
668 # descriptor['vnf']['name'] = kwargs[param]
670 # descriptor['vnf'][param] = kwargs[param]
671 # return self._edit_item("vnfs", descriptor, uuid, name, all_tenants=None)
674 def list_scenarios(self
, all_tenants
=False, **kwargs
):
675 '''Obtain a list of scenarios
676 Params: can be filtered by 'uuid','name','description','public', "tenant_id"
677 Return: Raises an exception on error
678 Obtain a dictionary with format {'scenarios':[{scenario1_info},{scenario2_info},...]}}
680 return self
._list
_item
("scenarios", all_tenants
, kwargs
)
682 def get_scenario(self
, uuid
=None, name
=None, all_tenants
=False):
683 '''Obtain the information of a scenario
684 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
685 Return: Raises an exception on error, not found, found several
686 Obtain a dictionary with format {'scenario':{scenario_info}}
688 return self
._get
_item
("scenarios", uuid
, name
, all_tenants
)
690 def delete_scenario(self
, uuid
=None, name
=None, all_tenants
=False):
692 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
693 Return: Raises an exception on error, not found, found several, not free
694 Obtain a dictionary with format {'result': text indicating deleted}
696 return self
._del
_item
("scenarios", uuid
, name
, all_tenants
)
698 def create_scenario(self
, descriptor
=None, descriptor_format
=None, **kwargs
):
699 '''Creates a scenario
700 Params: must supply a descriptor
701 descriptor: with format {'scenario':{new_scenario_info}}
702 must be a dictionary or a json/yaml text.
703 Other parameters can be:
704 name: the scenario name. Overwrite descriptor name if any
705 description: scenario descriptor.. Overwrite descriptor description if any
706 public: boolean, available to other tenants
707 tenant_id. Propietary tenant
708 Return: Raises an exception on error
709 Obtain a dictionary with format {'scenario':{new_scenario_info}}
711 if isinstance(descriptor
, str):
712 descriptor
= self
.parse(descriptor
, descriptor_format
)
716 raise OpenmanoBadParamsException("Missing descriptor")
718 if 'scenario' not in descriptor
or len(descriptor
)>2:
719 raise OpenmanoBadParamsException("Descriptor must contain only one 'scenario' field, and an optional version")
721 descriptor
['scenario'][param
] = kwargs
[param
]
722 return self
._create
_item
("scenarios", descriptor
)
724 def edit_scenario(self
, uuid
=None, name
=None, descriptor
=None, descriptor_format
=None, all_tenants
=False, **kwargs
):
725 '''Edit the parameters of a scenario
726 Params: must supply a descriptor or/and a parameters to change
727 uuid or/and name. If only name is supplied, there must be only one or an exception is raised
728 descriptor: with format {'scenario':{params to change info}}
729 must be a dictionary or a json/yaml text.
730 parameters to change can be supplyied by the descriptor or as parameters:
731 new_name: the scenario name
732 public: boolean, available to other tenants
733 description: scenario description
734 tenant_id. Propietary tenant
735 Return: Raises an exception on error, not found or found several
736 Obtain a dictionary with format {'scenario':{new_scenario_info}}
739 if isinstance(descriptor
, str):
740 descriptor
= self
.parse(descriptor
, descriptor_format
)
744 descriptor
={"scenario": {}}
746 raise OpenmanoBadParamsException("Missing descriptor")
748 if 'scenario' not in descriptor
or len(descriptor
)>2:
749 raise OpenmanoBadParamsException("Descriptor must contain only one 'scenario' field")
751 if param
=='new_name':
752 descriptor
['scenario']['name'] = kwargs
[param
]
754 descriptor
['scenario'][param
] = kwargs
[param
]
755 return self
._edit
_item
("scenarios", descriptor
, uuid
, name
, all_tenants
=None)
759 def list_instances(self
, all_tenants
=False, **kwargs
):
760 '''Obtain a list of instances
761 Params: can be filtered by 'uuid','name','description','scenario_id', "tenant_id"
762 Return: Raises an exception on error
763 Obtain a dictionary with format {'instances':[{instance1_info},{instance2_info},...]}}
765 return self
._list
_item
("instances", all_tenants
, kwargs
)
767 def get_instance(self
, uuid
=None, name
=None, all_tenants
=False):
768 '''Obtain the information of a instance
769 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
770 Return: Raises an exception on error, not found, found several
771 Obtain a dictionary with format {'instance':{instance_info}}
773 return self
._get
_item
("instances", uuid
, name
, all_tenants
)
775 def delete_instance(self
, uuid
=None, name
=None, all_tenants
=False):
777 Params: uuid or/and name. If only name is supplied, there must be only one or an exception is raised
778 Return: Raises an exception on error, not found, found several, not free
779 Obtain a dictionary with format {'result': text indicating deleted}
781 return self
._del
_item
("instances", uuid
, name
, all_tenants
)
783 def create_instance(self
, descriptor
=None, descriptor_format
=None, name
=None, **kwargs
):
784 '''Creates a instance
785 Params: must supply a descriptor or/and a name and scenario
786 descriptor: with format {'instance':{new_instance_info}}
787 must be a dictionary or a json/yaml text.
788 name: the instance name. Overwrite descriptor name if any
789 Other parameters can be:
790 description: instance descriptor.. Overwrite descriptor description if any
791 datacenter_name, datacenter_id: datacenter where to be deployed
792 scenario_name, scenario_id: Scenario this instance is based on
793 Return: Raises an exception on error
794 Obtain a dictionary with format {'instance':{new_instance_info}}
796 if isinstance(descriptor
, str):
797 descriptor
= self
.parse(descriptor
, descriptor_format
)
800 elif name
and ("scenario_name" in kwargs
or "scenario_id" in kwargs
):
801 descriptor
= {"instance":{"name": name
}}
803 raise OpenmanoBadParamsException("Missing descriptor")
805 if 'instance' not in descriptor
or len(descriptor
)>2:
806 raise OpenmanoBadParamsException("Descriptor must contain only one 'instance' field, and an optional version")
808 descriptor
['instance']["name"] = name
809 if "scenario_name" in kwargs
or "scenario_id" in kwargs
:
810 descriptor
['instance']["scenario"] = self
._get
_item
_uuid
("scenarios", kwargs
.get("scenario_id"), kwargs
.get("scenario_name"))
811 if "datacenter_name" in kwargs
or "datacenter_id" in kwargs
:
812 descriptor
['instance']["datacenter"] = self
._get
_item
_uuid
("datacenters", kwargs
.get("datacenter_id"), kwargs
.get("datacenter_name"))
813 if "description" in kwargs
:
814 descriptor
['instance']["description"] = kwargs
.get("description")
815 #for param in kwargs:
816 # descriptor['instance'][param] = kwargs[param]
817 if "datacenter" not in descriptor
['instance']:
818 descriptor
['instance']["datacenter"] = self
._get
_datacenter
()
819 return self
._create
_item
("instances", descriptor
)
822 def vim_action(self
, action
, item
, uuid
=None, all_tenants
=False, **kwargs
):
823 '''Perform an action over a vim
825 action: can be 'list', 'get'/'show', 'delete' or 'create'
826 item: can be 'tenants' or 'networks'
827 uuid: uuid of the tenant/net to show or to delete. Ignore otherwise
829 datacenter_name, datacenter_id: datacenters to act on, if missing uses classes store datacenter
830 descriptor, descriptor_format: descriptor needed on creation, can be a dict or a yaml/json str
831 must be a dictionary or a json/yaml text.
832 name: for created tenant/net Overwrite descriptor name if any
833 description: tenant descriptor. Overwrite descriptor description if any
835 Return: Raises an exception on error
836 Obtain a dictionary with format {'tenant':{new_tenant_info}}
838 if item
not in ("tenants", "networks", "images"):
839 raise OpenmanoBadParamsException("Unknown value for item '{}', must be 'tenants', 'nets' or "
840 "images".format(str(item
)))
842 image_actions
= ['list','get','show','delete']
843 if item
== "images" and action
not in image_actions
:
844 raise OpenmanoBadParamsException("Only available actions for item '{}' are {}\n"
845 "Requested action was '{}'".format(item
, ', '.join(image_actions
), action
))
849 tenant_text
= "/"+self
._get
_tenant
()
851 if "datacenter_id" in kwargs
or "datacenter_name" in kwargs
:
852 datacenter
= self
._get
_item
_uuid
("datacenters", kwargs
.get("datacenter_id"), kwargs
.get("datacenter_name"), all_tenants
=all_tenants
)
854 datacenter
= self
._get
_datacenter
()
857 URLrequest
= "{}{}/vim/{}/{}".format(self
.endpoint_url
, tenant_text
, datacenter
, item
)
858 self
.logger
.debug("GET %s", URLrequest
)
859 mano_response
= requests
.get(URLrequest
, headers
=self
.headers_req
)
860 self
.logger
.debug("openmano response: %s", mano_response
.text
)
861 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
862 if mano_response
.status_code
==200:
865 raise OpenmanoResponseException(str(content
))
866 elif action
=="get" or action
=="show":
867 URLrequest
= "{}{}/vim/{}/{}/{}".format(self
.endpoint_url
, tenant_text
, datacenter
, item
, uuid
)
868 self
.logger
.debug("GET %s", URLrequest
)
869 mano_response
= requests
.get(URLrequest
, headers
=self
.headers_req
)
870 self
.logger
.debug("openmano response: %s", mano_response
.text
)
871 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
872 if mano_response
.status_code
==200:
875 raise OpenmanoResponseException(str(content
))
876 elif action
=="delete":
877 URLrequest
= "{}{}/vim/{}/{}/{}".format(self
.endpoint_url
, tenant_text
, datacenter
, item
, uuid
)
878 self
.logger
.debug("DELETE %s", URLrequest
)
879 mano_response
= requests
.delete(URLrequest
, headers
=self
.headers_req
)
880 self
.logger
.debug("openmano response: %s", mano_response
.text
)
881 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
882 if mano_response
.status_code
==200:
885 raise OpenmanoResponseException(str(content
))
886 elif action
=="create":
887 if "descriptor" in kwargs
:
888 if isinstance(kwargs
["descriptor"], str):
889 descriptor
= self
._parse
(kwargs
["descriptor"], kwargs
.get("descriptor_format") )
891 descriptor
= kwargs
["descriptor"]
892 elif "name" in kwargs
:
893 descriptor
={item
[:-1]: {"name": kwargs
["name"]}}
895 raise OpenmanoResponseException("Missing descriptor")
897 if item
[:-1] not in descriptor
or len(descriptor
)!=1:
898 raise OpenmanoBadParamsException("Descriptor must contain only one 'tenant' field")
900 descriptor
[ item
[:-1] ]['name'] = kwargs
["name"]
901 if "description" in kwargs
:
902 descriptor
[ item
[:-1] ]['description'] = kwargs
["description"]
903 payload_req
= yaml
.safe_dump(descriptor
)
905 URLrequest
= "{}{}/vim/{}/{}".format(self
.endpoint_url
, tenant_text
, datacenter
, item
)
906 self
.logger
.debug("openmano POST %s %s", URLrequest
, payload_req
)
907 mano_response
= requests
.post(URLrequest
, headers
= self
.headers_req
, data
=payload_req
)
908 self
.logger
.debug("openmano response: %s", mano_response
.text
)
909 content
= self
._parse
_yaml
(mano_response
.text
, response
=True)
910 if mano_response
.status_code
==200:
913 raise OpenmanoResponseException(str(content
))
915 raise OpenmanoBadParamsException("Unknown value for action '{}".format(str(action
)))