Disable the check of the release notes
[osm/RO.git] / RO-SDN-tapi / osm_rosdn_tapi / tapi_client.py
1 # -*- coding: utf-8 -*-
2
3 #######################################################################################
4 # This file is part of OSM RO module
5 #
6 # Copyright ETSI Contributors and Others.
7 #
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
18 # under the License.
19 #######################################################################################
20 # This work has been performed in the context of the TeraFlow Project -
21 # funded by the European Commission under Grant number 101015857 through the
22 # Horizon 2020 program.
23 # Contributors:
24 # - Lluis Gifre <lluis.gifre@cttc.es>
25 # - Ricard Vilalta <ricard.vilalta@cttc.es>
26 #######################################################################################
27
28 """This file contains the TransportApiClient class used by the Transport API
29 (TAPI) WIM connector to interact with the underlying WIM."""
30
31 import requests
32
33 from .exceptions import (
34 WimTapiConnectivityServiceCreateFailed,
35 WimTapiConnectivityServiceDeleteFailed,
36 WimTapiConnectivityServiceGetStatusFailed,
37 WimTapiServerNotAvailable,
38 WimTapiServerRequestFailed,
39 )
40 from .log_messages import (
41 LOG_MSG_CREATE_REPLY,
42 LOG_MSG_CREATE_REQUEST,
43 LOG_MSG_DELETE_REPLY,
44 LOG_MSG_DELETE_REQUEST,
45 LOG_MSG_GET_STATUS_REPLY,
46 LOG_MSG_GET_STATUS_REQUEST,
47 )
48 from .message_composers import (
49 compose_create_request,
50 compose_delete_request,
51 )
52
53 DEFAULT_TIMEOUT = 30
54
55 SUCCESS_HTTP_CODES = {
56 requests.codes.ok, # pylint: disable=no-member
57 requests.codes.created, # pylint: disable=no-member
58 requests.codes.accepted, # pylint: disable=no-member
59 requests.codes.no_content, # pylint: disable=no-member
60 }
61
62 RESTCONF_DATA_URL = "{:s}/restconf/data"
63 RESTCONF_OPER_URL = "{:s}/restconf/operations"
64
65 CONTEXT_URL = RESTCONF_DATA_URL + "/tapi-common:context"
66 CTX_SIPS_URL = CONTEXT_URL + "/service-interface-point"
67 CONN_CTX_URL = CONTEXT_URL + "/tapi-connectivity:connectivity-context"
68 CONN_SVC_URL = CONN_CTX_URL + "/connectivity-service"
69 DELETE_URL = RESTCONF_OPER_URL + "/tapi-connectivity:delete-connectivity-service"
70
71
72 class TransportApiClient:
73 def __init__(self, logger, wim, wim_account, config) -> None:
74 self.logger = logger
75 self.wim_url = wim["wim_url"]
76
77 user = wim_account.get("user")
78 password = wim_account.get("password")
79 self.auth = (
80 None
81 if user is None or user == "" or password is None or password == ""
82 else (user, password)
83 )
84
85 self.headers = {"Content-Type": "application/json"}
86 self.timeout = int(config.get("timeout", DEFAULT_TIMEOUT))
87
88 def get_root_context(self):
89 context_url = CONTEXT_URL.format(self.wim_url)
90
91 try:
92 response = requests.get(
93 context_url, auth=self.auth, headers=self.headers, timeout=self.timeout
94 )
95 http_code = response.status_code
96 except requests.exceptions.RequestException as e:
97 raise WimTapiServerNotAvailable(str(e))
98
99 if http_code != 200:
100 raise WimTapiServerRequestFailed(
101 "Unexpected status code", http_code=http_code
102 )
103
104 return response.json()
105
106 def get_service_interface_points(self):
107 get_sips_url = CTX_SIPS_URL.format(self.wim_url)
108
109 try:
110 response = requests.get(
111 get_sips_url, auth=self.auth, headers=self.headers, timeout=self.timeout
112 )
113 http_code = response.status_code
114 except requests.exceptions.RequestException as e:
115 raise WimTapiServerNotAvailable(str(e))
116
117 if http_code != 200:
118 raise WimTapiServerRequestFailed(
119 "Unexpected status code", http_code=http_code
120 )
121
122 response = response.json()
123 response = response.get("tapi-common:service-interface-point", [])
124 return {sip["uuid"]: sip for sip in response}
125
126 def get_service_status(self, name, service_uuid):
127 self.logger.debug(LOG_MSG_GET_STATUS_REQUEST.format(name, service_uuid))
128
129 try:
130 services_url = CONN_SVC_URL.format(self.wim_url)
131 response = requests.get(
132 services_url, auth=self.auth, headers=self.headers, timeout=self.timeout
133 )
134 self.logger.debug(
135 LOG_MSG_GET_STATUS_REPLY.format(
136 name, service_uuid, response.status_code, response.text
137 )
138 )
139 except requests.exceptions.ConnectionError as e:
140 status_code = e.response.status_code if e.response is not None else 500
141 content = e.response.text if e.response is not None else ""
142 raise WimTapiConnectivityServiceGetStatusFailed(
143 name, service_uuid, status_code, content
144 )
145
146 if response.status_code not in SUCCESS_HTTP_CODES:
147 raise WimTapiConnectivityServiceGetStatusFailed(
148 name, service_uuid, response.status_code, response.text
149 )
150
151 json_response = response.json()
152 connectivity_services = json_response.get(
153 "tapi-connectivity:connectivity-service", []
154 )
155 connectivity_service = next(
156 iter(
157 [
158 connectivity_service
159 for connectivity_service in connectivity_services
160 if connectivity_service.get("uuid") == service_uuid
161 ]
162 ),
163 None,
164 )
165
166 if connectivity_service is None:
167 service_status = {"sdn_status": "ERROR"}
168 else:
169 service_status = {"sdn_status": "ACTIVE"}
170 return service_status
171
172 def create_service(
173 self,
174 name,
175 service_uuid,
176 service_endpoints,
177 bidirectional=False,
178 requested_capacity=None,
179 vlan_constraint=None,
180 ):
181 request_create = compose_create_request(
182 service_uuid,
183 service_endpoints,
184 bidirectional=bidirectional,
185 requested_capacity=requested_capacity,
186 vlan_constraint=vlan_constraint,
187 )
188 self.logger.debug(
189 LOG_MSG_CREATE_REQUEST.format(name, service_uuid, str(request_create))
190 )
191
192 try:
193 create_url = CONN_CTX_URL.format(self.wim_url)
194 response = requests.post(
195 create_url, headers=self.headers, json=request_create, auth=self.auth
196 )
197 self.logger.debug(
198 LOG_MSG_CREATE_REPLY.format(
199 name, service_uuid, response.status_code, response.text
200 )
201 )
202 except requests.exceptions.ConnectionError as e:
203 status_code = e.response.status_code if e.response is not None else 500
204 content = e.response.text if e.response is not None else ""
205 raise WimTapiConnectivityServiceCreateFailed(
206 name, service_uuid, status_code, content
207 )
208
209 if response.status_code not in SUCCESS_HTTP_CODES:
210 raise WimTapiConnectivityServiceCreateFailed(
211 name, service_uuid, response.status_code, response.text
212 )
213
214 def delete_service(self, name, service_uuid):
215 request_delete = compose_delete_request(service_uuid)
216 self.logger.debug(
217 LOG_MSG_DELETE_REQUEST.format(name, service_uuid, str(request_delete))
218 )
219
220 try:
221 delete_url = DELETE_URL.format(self.wim_url)
222 response = requests.post(
223 delete_url, headers=self.headers, json=request_delete, auth=self.auth
224 )
225 self.logger.debug(
226 LOG_MSG_DELETE_REPLY.format(
227 name, service_uuid, response.status_code, response.text
228 )
229 )
230 except requests.exceptions.ConnectionError as e:
231 status_code = e.response.status_code if e.response is not None else 500
232 content = e.response.text if e.response is not None else ""
233 raise WimTapiConnectivityServiceDeleteFailed(
234 name, service_uuid, status_code, content
235 )
236
237 if response.status_code not in SUCCESS_HTTP_CODES:
238 raise WimTapiConnectivityServiceDeleteFailed(
239 name, service_uuid, response.status_code, response.text
240 )