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.
29 from osm_ro
.wim
.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
= \
36 'Unexpected number of connection points: 2 expected.',
37 ENCAPSULATION_TYPE
= \
38 'Unexpected service_endpoint_encapsulation_type. \
39 Only "dotq1" is accepted.',
40 BANDWIDTH
= 'Unable to get the bandwidth.',
41 STATUS
= 'Unable to get the status for the service.',
42 DELETE
= 'Unable to delete service.',
43 CLEAR_ALL
= 'Unable to clear all the services',
44 UNKNOWN_ACTION
= 'Unknown action invoked.',
45 BACKUP
= 'Unable to get the backup parameter.',
46 UNSUPPORTED_FEATURE
= "Unsupported feature",
47 UNAUTHORIZED
= "Failed while authenticating"
50 class SdnAPIActions(Enum
):
51 CHECK_CONNECTIVITY
= "CHECK_CONNECTIVITY",
52 CREATE_SERVICE
= "CREATE_SERVICE",
53 DELETE_SERVICE
= "DELETE_SERVICE",
54 CLEAR_ALL
= "CLEAR_ALL",
55 SERVICE_STATUS
= "SERVICE_STATUS",
58 class DynpacConnector(SdnConnectorBase
):
59 __supported_service_types
= ["ELINE (L2)", "ELINE"]
60 __supported_encapsulation_types
= ["dot1q"]
61 __WIM_LOGGER
= 'openmano.sdnconn.dynpac'
62 __ENCAPSULATION_TYPE_PARAM
= "service_endpoint_encapsulation_type"
63 __ENCAPSULATION_INFO_PARAM
= "service_endpoint_encapsulation_info"
64 __BACKUP_PARAM
= "backup"
65 __BANDWIDTH_PARAM
= "bandwidth"
66 __SERVICE_ENDPOINT_PARAM
= "service_endpoint_id"
67 __WAN_SERVICE_ENDPOINT_PARAM
= "service_endpoint_id"
68 __WAN_MAPPING_INFO_PARAM
= "service_mapping_info"
69 __SW_ID_PARAM
= "switch_dpid"
70 __SW_PORT_PARAM
= "switch_port"
73 # Public functions exposed to the Resource Orchestrator
74 def __init__(self
, wim
, wim_account
, config
=None, logger
=None):
75 self
.logger
= logger
or logging
.getLogger(self
.__WIM
_LOGGER
)
76 super().__init
__(wim
, wim_account
, config
, self
.logger
)
78 self
.__wim
_account
= wim_account
79 self
.__config
= config
80 self
.__wim
_url
= self
.__wim
.get("wim_url")
81 self
.__user
= wim_account
.get("user")
82 self
.__passwd
= wim_account
.get("password")
83 self
.logger
.info("Initialized.")
85 def create_connectivity_service(self
, service_type
, connection_points
, **kwargs
):
86 self
.__check
_service
(service_type
, connection_points
, kwargs
)
88 body
= self
.__get
_body
(service_type
, connection_points
, kwargs
)
90 headers
= {'Content-type': 'application/x-www-form-urlencoded'}
91 endpoint
= "{}/service/create".format(self
.__wim
_url
)
94 response
= requests
.post(endpoint
, data
=body
, headers
=headers
)
95 except requests
.exceptions
.RequestException
as e
:
96 self
.__exception
(e
.message
, http_code
=503)
98 if response
.status_code
!= 200:
99 error
= json
.loads(response
.content
)
100 reason
= "Reason: {}. ".format(error
.get("code"))
101 description
= "Description: {}.".format(error
.get("description"))
102 exception
= reason
+ description
103 self
.__exception
(exception
, http_code
=response
.status_code
)
104 uuid
= response
.content
105 self
.logger
.info("Service with uuid {} created.".format(uuid
))
108 def edit_connectivity_service(self
, service_uuid
,
109 conn_info
, connection_points
,
111 self
.__exception
(SdnError
.UNSUPPORTED_FEATURE
, http_code
=501)
113 def get_connectivity_service_status(self
, service_uuid
):
114 endpoint
= "{}/service/status/{}".format(self
.__wim
_url
, service_uuid
)
116 response
= requests
.get(endpoint
)
117 except requests
.exceptions
.RequestException
as e
:
118 self
.__exception
(e
.message
, http_code
=503)
120 if response
.status_code
!= 200:
121 self
.__exception
(SdnError
.STATUS
, http_code
=response
.status_code
)
122 self
.logger
.info("Status for service with uuid {}: {}"
123 .format(service_uuid
, response
.content
))
124 return response
.content
126 def delete_connectivity_service(self
, service_uuid
, conn_info
):
127 endpoint
= "{}/service/delete/{}".format(self
.__wim
_url
, service_uuid
)
129 response
= requests
.delete(endpoint
)
130 except requests
.exceptions
.RequestException
as e
:
131 self
.__exception
(e
.message
, http_code
=503)
132 if response
.status_code
!= 200:
133 self
.__exception
(SdnError
.DELETE
, http_code
=response
.status_code
)
135 self
.logger
.info("Service with uuid: {} deleted".format(service_uuid
))
137 def clear_all_connectivity_services(self
):
138 endpoint
= "{}/service/clearAll".format(self
.__wim
_url
)
140 response
= requests
.delete(endpoint
)
141 http_code
= response
.status_code
142 except requests
.exceptions
.RequestException
as e
:
143 self
.__exception
(e
.message
, http_code
=503)
145 self
.__exception
(SdnError
.CLEAR_ALL
, http_code
=http_code
)
147 self
.logger
.info("{} services deleted".format(response
.content
))
148 return "{} services deleted".format(response
.content
)
150 def check_connectivity(self
):
151 endpoint
= "{}/checkConnectivity".format(self
.__wim
_url
)
154 response
= requests
.get(endpoint
)
155 http_code
= response
.status_code
156 except requests
.exceptions
.RequestException
as e
:
157 self
.__exception
(e
.message
, http_code
=503)
160 self
.__exception
(SdnError
.UNREACHABLE
, http_code
=http_code
)
161 self
.logger
.info("Connectivity checked")
163 def check_credentials(self
):
164 endpoint
= "{}/checkCredentials".format(self
.__wim
_url
)
165 auth
= (self
.__user
, self
.__passwd
)
168 response
= requests
.get(endpoint
, auth
=auth
)
169 http_code
= response
.status_code
170 except requests
.exceptions
.RequestException
as e
:
171 self
.__exception
(e
.message
, http_code
=503)
174 self
.__exception
(SdnError
.UNAUTHORIZED
, http_code
=http_code
)
175 self
.logger
.info("Credentials checked")
178 def __exception(self
, x
, **kwargs
):
179 http_code
= kwargs
.get("http_code")
180 if hasattr(x
, "value"):
184 self
.logger
.error(error
)
185 raise SdnConnectorError(error
, http_code
=http_code
)
187 def __check_service(self
, service_type
, connection_points
, kwargs
):
188 if service_type
not in self
.__supported
_service
_types
:
189 self
.__exception
(SdnError
.SERVICE_TYPE_ERROR
, http_code
=400)
191 if len(connection_points
) != 2:
192 self
.__exception
(SdnError
.CONNECTION_POINTS_SIZE
, http_code
=400)
194 for connection_point
in connection_points
:
195 enc_type
= connection_point
.get(self
.__ENCAPSULATION
_TYPE
_PARAM
)
196 if enc_type
not in self
.__supported
_encapsulation
_types
:
197 self
.__exception
(SdnError
.ENCAPSULATION_TYPE
, http_code
=400)
199 # Commented out for as long as parameter isn't implemented
200 # bandwidth = kwargs.get(self.__BANDWIDTH_PARAM)
201 # if not isinstance(bandwidth, int):
202 # self.__exception(SdnError.BANDWIDTH, http_code=400)
204 # Commented out for as long as parameter isn't implemented
205 # backup = kwargs.get(self.__BACKUP_PARAM)
206 # if not isinstance(backup, bool):
207 # self.__exception(SdnError.BACKUP, http_code=400)
209 def __get_body(self
, service_type
, connection_points
, kwargs
):
210 port_mapping
= self
.__config
.get("service_endpoint_mapping")
212 for connection_point
in connection_points
:
213 endpoint_id
= connection_point
.get(self
.__SERVICE
_ENDPOINT
_PARAM
)
214 port
= filter(lambda x
: x
.get(self
.__WAN
_SERVICE
_ENDPOINT
_PARAM
) == endpoint_id
, port_mapping
)[0]
215 port_info
= port
.get(self
.__WAN
_MAPPING
_INFO
_PARAM
)
216 selected_ports
.append(port_info
)
217 if service_type
== "ELINE (L2)" or service_type
== "ELINE":
220 "connection_points": [{
221 "wan_switch_dpid": selected_ports
[0].get(self
.__SW
_ID
_PARAM
),
222 "wan_switch_port": selected_ports
[0].get(self
.__SW
_PORT
_PARAM
),
223 "wan_vlan": connection_points
[0].get(self
.__ENCAPSULATION
_INFO
_PARAM
).get(self
.__VLAN
_PARAM
)
225 "wan_switch_dpid": selected_ports
[1].get(self
.__SW
_ID
_PARAM
),
226 "wan_switch_port": selected_ports
[1].get(self
.__SW
_PORT
_PARAM
),
227 "wan_vlan": connection_points
[1].get(self
.__ENCAPSULATION
_INFO
_PARAM
).get(self
.__VLAN
_PARAM
)
229 "bandwidth": 100, # Hardcoded for as long as parameter isn't implemented
230 "service_type": service_type
,
231 "backup": False # Hardcoded for as long as parameter isn't implemented
233 return "body={}".format(json
.dumps(body
))