2 # -*- coding: utf-8 -*-
5 # Copyright 2018 David GarcĂa, University of the Basque Country
6 # Copyright 2018 University of the Basque Country
7 # This file is part of openmano
9 # Contact information at http://i2t.ehu.eus
11 # # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
15 # http://www.apache.org/licenses/LICENSE-2.0
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
21 # See the License for the specific language governing permissions and
22 # limitations under the License.
28 from osm_ro_plugin
.sdnconn
import SdnConnectorBase
, SdnConnectorError
33 UNREACHABLE
= "Unable to reach the WIM."
34 SERVICE_TYPE_ERROR
= 'Unexpected service_type. Only "L2" is accepted.'
35 CONNECTION_POINTS_SIZE
= "Unexpected number of connection points: 2 expected."
36 ENCAPSULATION_TYPE
= (
37 'Unexpected service_endpoint_encapsulation_type. Only "dotq1" is accepted.'
39 BANDWIDTH
= "Unable to get the bandwidth."
40 STATUS
= "Unable to get the status for the service."
41 DELETE
= "Unable to delete service."
42 CLEAR_ALL
= "Unable to clear all the services"
43 UNKNOWN_ACTION
= "Unknown action invoked."
44 BACKUP
= "Unable to get the backup parameter."
45 UNSUPPORTED_FEATURE
= "Unsupported feature"
46 UNAUTHORIZED
= "Failed while authenticating"
49 class SdnAPIActions(Enum
):
50 CHECK_CONNECTIVITY
= "CHECK_CONNECTIVITY"
51 CREATE_SERVICE
= "CREATE_SERVICE"
52 DELETE_SERVICE
= "DELETE_SERVICE"
53 CLEAR_ALL
= "CLEAR_ALL"
54 SERVICE_STATUS
= "SERVICE_STATUS"
57 class DynpacConnector(SdnConnectorBase
):
58 __supported_service_types
= ["ELINE (L2)", "ELINE"]
59 __supported_encapsulation_types
= ["dot1q"]
60 __WIM_LOGGER
= "ro.sdn.dynpac"
61 __ENCAPSULATION_TYPE_PARAM
= "service_endpoint_encapsulation_type"
62 __ENCAPSULATION_INFO_PARAM
= "service_endpoint_encapsulation_info"
63 __BACKUP_PARAM
= "backup"
64 __BANDWIDTH_PARAM
= "bandwidth"
65 __SERVICE_ENDPOINT_PARAM
= "service_endpoint_id"
66 __WAN_SERVICE_ENDPOINT_PARAM
= "service_endpoint_id"
67 __WAN_MAPPING_INFO_PARAM
= "service_mapping_info"
68 __SW_ID_PARAM
= "switch_dpid"
69 __SW_PORT_PARAM
= "switch_port"
72 # Public functions exposed to the Resource Orchestrator
73 def __init__(self
, wim
, wim_account
, config
=None, logger
=None):
74 self
.logger
= logger
or logging
.getLogger(self
.__WIM
_LOGGER
)
75 super().__init
__(wim
, wim_account
, config
, self
.logger
)
77 self
.__wim
_account
= wim_account
78 self
.__config
= config
79 self
.__wim
_url
= self
.__wim
.get("wim_url")
80 self
.__user
= wim_account
.get("user")
81 self
.__passwd
= wim_account
.get("password")
82 self
.logger
.info("Initialized.")
84 def create_connectivity_service(self
, service_type
, connection_points
, **kwargs
):
85 self
.__check
_service
(service_type
, connection_points
, kwargs
)
87 body
= self
.__get
_body
(service_type
, connection_points
, kwargs
)
89 headers
= {"Content-type": "application/x-www-form-urlencoded"}
90 endpoint
= "{}/service/create".format(self
.__wim
_url
)
93 response
= requests
.post(endpoint
, data
=body
, headers
=headers
)
94 except requests
.exceptions
.RequestException
as e
:
95 self
.__exception
(e
.message
, http_code
=503)
97 if response
.status_code
!= 200:
98 error
= json
.loads(response
.content
)
99 reason
= "Reason: {}. ".format(error
.get("code"))
100 description
= "Description: {}.".format(error
.get("description"))
101 exception
= reason
+ description
102 self
.__exception
(exception
, http_code
=response
.status_code
)
104 uuid
= response
.content
105 self
.logger
.info("Service with uuid {} created.".format(uuid
))
109 def edit_connectivity_service(
110 self
, service_uuid
, conn_info
, connection_points
, **kwargs
112 self
.__exception
(SdnError
.UNSUPPORTED_FEATURE
, http_code
=501)
114 def get_connectivity_service_status(self
, service_uuid
):
115 endpoint
= "{}/service/status/{}".format(self
.__wim
_url
, service_uuid
)
118 response
= requests
.get(endpoint
)
119 except requests
.exceptions
.RequestException
as e
:
120 self
.__exception
(e
.message
, http_code
=503)
122 if response
.status_code
!= 200:
123 self
.__exception
(SdnError
.STATUS
, http_code
=response
.status_code
)
126 "Status for service with uuid {}: {}".format(service_uuid
, response
.content
)
129 return response
.content
131 def delete_connectivity_service(self
, service_uuid
, conn_info
):
132 endpoint
= "{}/service/delete/{}".format(self
.__wim
_url
, service_uuid
)
135 response
= requests
.delete(endpoint
)
136 except requests
.exceptions
.RequestException
as e
:
137 self
.__exception
(e
.message
, http_code
=503)
139 if response
.status_code
!= 200:
140 self
.__exception
(SdnError
.DELETE
, http_code
=response
.status_code
)
142 self
.logger
.info("Service with uuid: {} deleted".format(service_uuid
))
144 def clear_all_connectivity_services(self
):
145 endpoint
= "{}/service/clearAll".format(self
.__wim
_url
)
148 response
= requests
.delete(endpoint
)
149 http_code
= response
.status_code
150 except requests
.exceptions
.RequestException
as e
:
151 self
.__exception
(e
.message
, http_code
=503)
154 self
.__exception
(SdnError
.CLEAR_ALL
, http_code
=http_code
)
156 self
.logger
.info("{} services deleted".format(response
.content
))
158 return "{} services deleted".format(response
.content
)
160 def check_connectivity(self
):
161 endpoint
= "{}/checkConnectivity".format(self
.__wim
_url
)
164 response
= requests
.get(endpoint
)
165 http_code
= response
.status_code
166 except requests
.exceptions
.RequestException
as e
:
167 self
.__exception
(e
.message
, http_code
=503)
170 self
.__exception
(SdnError
.UNREACHABLE
, http_code
=http_code
)
172 self
.logger
.info("Connectivity checked")
174 def check_credentials(self
):
175 endpoint
= "{}/checkCredentials".format(self
.__wim
_url
)
176 auth
= (self
.__user
, self
.__passwd
)
179 response
= requests
.get(endpoint
, auth
=auth
)
180 http_code
= response
.status_code
181 except requests
.exceptions
.RequestException
as e
:
182 self
.__exception
(e
.message
, http_code
=503)
185 self
.__exception
(SdnError
.UNAUTHORIZED
, http_code
=http_code
)
187 self
.logger
.info("Credentials checked")
190 def __exception(self
, x
, **kwargs
):
191 http_code
= kwargs
.get("http_code")
193 if hasattr(x
, "value"):
198 self
.logger
.error(error
)
200 raise SdnConnectorError(error
, http_code
=http_code
)
202 def __check_service(self
, service_type
, connection_points
, kwargs
):
203 if service_type
not in self
.__supported
_service
_types
:
204 self
.__exception
(SdnError
.SERVICE_TYPE_ERROR
, http_code
=400)
206 if len(connection_points
) != 2:
207 self
.__exception
(SdnError
.CONNECTION_POINTS_SIZE
, http_code
=400)
209 for connection_point
in connection_points
:
210 enc_type
= connection_point
.get(self
.__ENCAPSULATION
_TYPE
_PARAM
)
212 if enc_type
not in self
.__supported
_encapsulation
_types
:
213 self
.__exception
(SdnError
.ENCAPSULATION_TYPE
, http_code
=400)
215 # Commented out for as long as parameter isn't implemented
216 # bandwidth = kwargs.get(self.__BANDWIDTH_PARAM)
217 # if not isinstance(bandwidth, int):
218 # self.__exception(SdnError.BANDWIDTH, http_code=400)
220 # Commented out for as long as parameter isn't implemented
221 # backup = kwargs.get(self.__BACKUP_PARAM)
222 # if not isinstance(backup, bool):
223 # self.__exception(SdnError.BACKUP, http_code=400)
225 def __get_body(self
, service_type
, connection_points
, kwargs
):
226 port_mapping
= self
.__config
.get("service_endpoint_mapping")
229 for connection_point
in connection_points
:
230 endpoint_id
= connection_point
.get(self
.__SERVICE
_ENDPOINT
_PARAM
)
232 lambda x
: x
.get(self
.__WAN
_SERVICE
_ENDPOINT
_PARAM
) == endpoint_id
,
235 port_info
= port
.get(self
.__WAN
_MAPPING
_INFO
_PARAM
)
236 selected_ports
.append(port_info
)
238 if service_type
== "ELINE (L2)" or service_type
== "ELINE":
242 "connection_points": [
244 "wan_switch_dpid": selected_ports
[0].get(self
.__SW
_ID
_PARAM
),
245 "wan_switch_port": selected_ports
[0].get(self
.__SW
_PORT
_PARAM
),
246 "wan_vlan": connection_points
[0]
247 .get(self
.__ENCAPSULATION
_INFO
_PARAM
)
248 .get(self
.__VLAN
_PARAM
),
251 "wan_switch_dpid": selected_ports
[1].get(self
.__SW
_ID
_PARAM
),
252 "wan_switch_port": selected_ports
[1].get(self
.__SW
_PORT
_PARAM
),
253 "wan_vlan": connection_points
[1]
254 .get(self
.__ENCAPSULATION
_INFO
_PARAM
)
255 .get(self
.__VLAN
_PARAM
),
258 "bandwidth": 100, # Hardcoded for as long as parameter isn't implemented
259 "service_type": service_type
,
260 "backup": False, # Hardcoded for as long as parameter isn't implemented
263 return "body={}".format(json
.dumps(body
))