2 # -*- coding: utf-8 -*-
5 # Copyright 2020 Telefónica Investigación y Desarrollo, S.A.U.
7 # Licensed under the Apache License, Version 2.0 (the "License"); you may
8 # not use this file except in compliance with the License. You may obtain
9 # a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 # License for the specific language governing permissions and limitations
22 asyncio RO python client to interact with New Generation RO server
30 __author__
= "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com"
31 __date__
= "$09-Jan-2018 09:09:48$"
33 version_date
= "2020-05-08"
36 class NgRoException(Exception):
37 def __init__(self
, message
, http_code
=400):
38 """Common Exception for all RO client exceptions"""
39 self
.http_code
= http_code
40 Exception.__init
__(self
, message
)
44 headers_req
= {"Accept": "application/yaml", "content-type": "application/yaml"}
48 "vim_account": "datacenters",
49 "sdn": "sdn_controllers",
53 "wim_account": "wims",
56 mandatory_for_create
= {
58 "vnfd": ("name", "id"),
59 "nsd": ("name", "id"),
60 "ns": ("name", "scenario", "datacenter"),
61 "vim": ("name", "vim_url"),
62 "wim": ("name", "wim_url"),
65 "sdn": ("name", "type"),
70 def __init__(self
, loop
, uri
, **kwargs
):
72 self
.endpoint_url
= uri
73 if not self
.endpoint_url
.endswith("/"):
74 self
.endpoint_url
+= "/"
75 if not self
.endpoint_url
.startswith("http"):
76 self
.endpoint_url
= "http://" + self
.endpoint_url
78 self
.username
= kwargs
.get("username")
79 self
.password
= kwargs
.get("password")
80 self
.tenant_id_name
= kwargs
.get("tenant")
82 self
.datacenter_id_name
= kwargs
.get("datacenter")
83 self
.datacenter
= None
84 logger_name
= kwargs
.get("logger_name", "lcm.ro")
85 self
.logger
= logging
.getLogger(logger_name
)
86 if kwargs
.get("loglevel"):
87 self
.logger
.setLevel(kwargs
["loglevel"])
89 async def deploy(self
, nsr_id
, target
):
91 Performs an action over an item
92 :param item: can be 'tenant', 'vnfd', 'nsd', 'ns', 'vim', 'vim_account', 'sdn'
93 :param item_id_name: RO id or name of the item. Raise and exception if more than one found
94 :param descriptor: can be a dict, or a yaml/json text. Autodetect unless descriptor_format is provided
95 :param descriptor_format: Can be 'json' or 'yaml'
96 :param kwargs: Overrides descriptor with values as name, description, vim_url, vim_url_admin, vim_type
97 keys can be a dot separated list to specify elements inside dict
98 :return: dictionary with the information or raises NgRoException on Error
101 if isinstance(target
, str):
102 target
= self
._parse
_yaml
(target
)
103 payload_req
= yaml
.safe_dump(target
)
105 url
= "{}/ns/v1/deploy/{nsr_id}".format(self
.endpoint_url
, nsr_id
=nsr_id
)
106 async with aiohttp
.ClientSession(loop
=self
.loop
) as session
:
107 self
.logger
.debug("NG-RO POST %s %s", url
, payload_req
)
108 # timeout = aiohttp.ClientTimeout(total=self.timeout_large)
109 async with session
.post(
110 url
, headers
=self
.headers_req
, data
=payload_req
112 response_text
= await response
.read()
114 "POST {} [{}] {}".format(
115 url
, response
.status
, response_text
[:100]
118 if response
.status
>= 300:
119 raise NgRoException(response_text
, http_code
=response
.status
)
120 return self
._parse
_yaml
(response_text
, response
=True)
121 except (aiohttp
.ClientOSError
, aiohttp
.ClientError
) as e
:
122 raise NgRoException(e
, http_code
=504)
123 except asyncio
.TimeoutError
:
124 raise NgRoException("Timeout", http_code
=504)
126 async def status(self
, nsr_id
, action_id
):
128 url
= "{}/ns/v1/deploy/{nsr_id}/{action_id}".format(
129 self
.endpoint_url
, nsr_id
=nsr_id
, action_id
=action_id
131 async with aiohttp
.ClientSession(loop
=self
.loop
) as session
:
132 self
.logger
.debug("GET %s", url
)
133 # timeout = aiohttp.ClientTimeout(total=self.timeout_short)
134 async with session
.get(url
, headers
=self
.headers_req
) as response
:
135 response_text
= await response
.read()
137 "GET {} [{}] {}".format(
138 url
, response
.status
, response_text
[:100]
141 if response
.status
>= 300:
142 raise NgRoException(response_text
, http_code
=response
.status
)
143 return self
._parse
_yaml
(response_text
, response
=True)
145 except (aiohttp
.ClientOSError
, aiohttp
.ClientError
) as e
:
146 raise NgRoException(e
, http_code
=504)
147 except asyncio
.TimeoutError
:
148 raise NgRoException("Timeout", http_code
=504)
150 async def delete(self
, nsr_id
):
152 url
= "{}/ns/v1/deploy/{nsr_id}".format(self
.endpoint_url
, nsr_id
=nsr_id
)
153 async with aiohttp
.ClientSession(loop
=self
.loop
) as session
:
154 self
.logger
.debug("DELETE %s", url
)
155 # timeout = aiohttp.ClientTimeout(total=self.timeout_short)
156 async with session
.delete(url
, headers
=self
.headers_req
) as response
:
157 self
.logger
.debug("DELETE {} [{}]".format(url
, response
.status
))
158 if response
.status
>= 300:
160 "Delete {}".format(nsr_id
), http_code
=response
.status
164 except (aiohttp
.ClientOSError
, aiohttp
.ClientError
) as e
:
165 raise NgRoException(e
, http_code
=504)
166 except asyncio
.TimeoutError
:
167 raise NgRoException("Timeout", http_code
=504)
169 async def get_version(self
):
171 Obtain RO server version.
172 :return: a list with integers ["major", "minor", "release"]. Raises NgRoException on Error,
176 async with aiohttp
.ClientSession(loop
=self
.loop
) as session
:
177 url
= "{}/version".format(self
.endpoint_url
)
178 self
.logger
.debug("RO GET %s", url
)
179 # timeout = aiohttp.ClientTimeout(total=self.timeout_short)
180 async with session
.get(url
, headers
=self
.headers_req
) as response
:
181 response_text
= await response
.read()
183 "GET {} [{}] {}".format(
184 url
, response
.status
, response_text
[:100]
187 if response
.status
>= 300:
188 raise NgRoException(response_text
, http_code
=response
.status
)
190 for word
in str(response_text
).split(" "):
192 version_text
, _
, _
= word
.partition("-")
195 "Got invalid version text: '{}'".format(response_text
),
198 except (aiohttp
.ClientOSError
, aiohttp
.ClientError
) as e
:
199 raise NgRoException(e
, http_code
=504)
200 except asyncio
.TimeoutError
:
201 raise NgRoException("Timeout", http_code
=504)
202 except Exception as e
:
204 "Got invalid version text: '{}'; causing exception {}".format(
211 def _parse_yaml(descriptor
, response
=False):
213 return yaml
.safe_load(descriptor
)
214 except yaml
.YAMLError
as exc
:
216 if hasattr(exc
, "problem_mark"):
217 mark
= exc
.problem_mark
218 error_pos
= " at line:{} column:{}s".format(
219 mark
.line
+ 1, mark
.column
+ 1
221 error_text
= "yaml format error" + error_pos
223 raise NgRoException("reponse with " + error_text
)
224 raise NgRoException(error_text
)