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 wimconn
import WimConnector
, WimConnectorError
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"
49 class WimAPIActions(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(WimConnector
):
58 __supported_service_types
= ["ELINE (L2)"]
59 __supported_encapsulation_types
= ["dot1q"]
60 __WIM_LOGGER
= 'openmano.wimconn.dynpac'
61 __ENCAPSULATION_TYPE_PARAM
= "service_endpoint_encapsulation_type"
62 __BACKUP_PARAM
= "backup"
63 __BANDWIDTH_PARAM
= "bandwidth"
64 __SERVICE_ENDPOINT_PARAM
= "service_endpoint_id"
65 __WAN_SERVICE_ENDPOINT_PARAM
= "wan_service_endpoint_id"
66 __WAN_MAPPING_INFO_PARAM
= "wan_service_mapping_info"
67 __SW_ID_PARAM
= "wan_switch_dpid"
68 __SW_PORT_PARAM
= "wan_switch_port"
71 # Public functions exposed to the Resource Orchestrator
72 def __init__(self
, wim
, wim_account
, config
):
73 self
.logger
= logging
.getLogger(self
.__WIM
_LOGGER
)
75 self
.__wim
_account
= wim_account
76 self
.__config
= config
77 self
.__wim
_url
= self
.__wim
.get("wim_url")
78 self
.__user
= wim_account
.get("user")
79 self
.__passwd
= wim_account
.get("passwd")
80 self
.logger
.info("Initialized.")
82 def create_connectivity_service(self
,
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
(WimError
.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
(WimError
.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
(WimError
.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
(WimError
.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
)
152 auth
= (self
.__user
, self
.__passwd
)
155 response
= requests
.get(endpoint
, auth
=auth
)
156 http_code
= response
.status_code
157 except requests
.exceptions
.RequestException
as e
:
158 self
.__exception
(e
.message
, http_code
=503)
161 self
.__exception
(WimError
.UNREACHABLE
, http_code
=http_code
)
162 self
.logger
.info("Connectivity checked")
165 def __exception(self
, x
, **kwargs
):
166 http_code
= kwargs
.get("http_code")
167 if hasattr(x
, "value"):
171 self
.logger
.error(error
)
172 raise WimConnectorError(error
, http_code
=http_code
)
174 def __check_service(self
, service_type
, connection_points
, kwargs
):
175 if service_type
not in self
.__supported
_service
_types
:
176 self
.__exception
(WimError
.SERVICE_TYPE_ERROR
, http_code
=400)
178 if len(connection_points
) != 2:
179 self
.__exception
(WimError
.CONNECTION_POINTS_SIZE
, http_code
=400)
181 for connection_point
in connection_points
:
182 enc_type
= connection_point
.get(self
.__ENCAPSULATION
_TYPE
_PARAM
)
183 if enc_type
not in self
.__supported
_encapsulation
_types
:
184 self
.__exception
(WimError
.ENCAPSULATION_TYPE
, http_code
=400)
186 bandwidth
= kwargs
.get(self
.__BANDWIDTH
_PARAM
)
187 if not isinstance(bandwidth
, int):
188 self
.__exception
(WimError
.BANDWIDTH
, http_code
=400)
190 backup
= kwargs
.get(self
.__BACKUP
_PARAM
)
191 if not isinstance(backup
, bool):
192 self
.__exception
(WimError
.BACKUP
, http_code
=400)
194 def __get_body(self
, service_type
, connection_points
, kwargs
):
195 port_mapping
= self
.__config
.get("port_mapping")
197 for connection_point
in connection_points
:
198 endpoint_id
= connection_point
.get(self
.__SERVICE
_ENDPOINT
_PARAM
)
199 port
= filter(lambda x
: x
.get(self
.__WAN
_SERVICE
_ENDPOINT
_PARAM
)
200 == endpoint_id
, port_mapping
)[0]
201 wsmpi_json
= port
.get(self
.__WAN
_MAPPING
_INFO
_PARAM
)
202 port_info
= json
.loads(wsmpi_json
)
203 selected_ports
.append(port_info
)
204 if service_type
== "ELINE (L2)":
207 "connection_points": [{
208 "wan_switch_dpid": selected_ports
[0].get(self
.__SW
_ID
_PARAM
),
209 "wan_switch_port": selected_ports
[0].get(self
.__SW
_PORT
_PARAM
),
210 "wan_vlan": connection_points
[0].get(self
.__VLAN
_PARAM
)
212 "wan_switch_dpid": selected_ports
[1].get(self
.__SW
_ID
_PARAM
),
213 "wan_switch_port": selected_ports
[1].get(self
.__SW
_PORT
_PARAM
),
214 "wan_vlan": connection_points
[1].get(self
.__VLAN
_PARAM
)
216 "bandwidth": kwargs
.get(self
.__BANDWIDTH
_PARAM
),
217 "service_type": service_type
,
218 "backup": kwargs
.get(self
.__BACKUP
_PARAM
)
220 return "body={}".format(json
.dumps(body
))