feature 8029 change RO to python3. Using vim plugins
[osm/RO.git] / RO / osm_ro / wim / wimconn_dynpac.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 ##
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
8 # All Rights Reserved.
9 # Contact information at http://i2t.ehu.eus
10 #
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
14 #
15 # http://www.apache.org/licenses/LICENSE-2.0
16 #
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
20 # implied.
21 # See the License for the specific language governing permissions and
22 # limitations under the License.
23
24 import requests
25 import json
26 import logging
27 from enum import Enum
28
29 from .wimconn import WimConnector, WimConnectorError
30
31
32 class WimError(Enum):
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"
48
49
50 class WimAPIActions(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",
56
57
58 class DynpacConnector(WimConnector):
59 __supported_service_types = ["ELINE (L2)", "ELINE"]
60 __supported_encapsulation_types = ["dot1q"]
61 __WIM_LOGGER = 'openmano.wimconn.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 = "wan_service_endpoint_id"
68 __WAN_MAPPING_INFO_PARAM = "wan_service_mapping_info"
69 __SW_ID_PARAM = "wan_switch_dpid"
70 __SW_PORT_PARAM = "wan_switch_port"
71 __VLAN_PARAM = "vlan"
72
73 # Public functions exposed to the Resource Orchestrator
74 def __init__(self, wim, wim_account, config):
75 self.logger = logging.getLogger(self.__WIM_LOGGER)
76 self.__wim = wim
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("passwd")
82 self.logger.info("Initialized.")
83
84 def create_connectivity_service(self,
85 service_type,
86 connection_points,
87 **kwargs):
88 self.__check_service(service_type, connection_points, kwargs)
89
90 body = self.__get_body(service_type, connection_points, kwargs)
91
92 headers = {'Content-type': 'application/x-www-form-urlencoded'}
93 endpoint = "{}/service/create".format(self.__wim_url)
94
95 try:
96 response = requests.post(endpoint, data=body, headers=headers)
97 except requests.exceptions.RequestException as e:
98 self.__exception(e.message, http_code=503)
99
100 if response.status_code != 200:
101 error = json.loads(response.content)
102 reason = "Reason: {}. ".format(error.get("code"))
103 description = "Description: {}.".format(error.get("description"))
104 exception = reason + description
105 self.__exception(exception, http_code=response.status_code)
106 uuid = response.content
107 self.logger.info("Service with uuid {} created.".format(uuid))
108 return (uuid, None)
109
110 def edit_connectivity_service(self, service_uuid,
111 conn_info, connection_points,
112 **kwargs):
113 self.__exception(WimError.UNSUPPORTED_FEATURE, http_code=501)
114
115 def get_connectivity_service_status(self, service_uuid):
116 endpoint = "{}/service/status/{}".format(self.__wim_url, service_uuid)
117 try:
118 response = requests.get(endpoint)
119 except requests.exceptions.RequestException as e:
120 self.__exception(e.message, http_code=503)
121
122 if response.status_code != 200:
123 self.__exception(WimError.STATUS, http_code=response.status_code)
124 self.logger.info("Status for service with uuid {}: {}"
125 .format(service_uuid, response.content))
126 return response.content
127
128 def delete_connectivity_service(self, service_uuid, conn_info):
129 endpoint = "{}/service/delete/{}".format(self.__wim_url, service_uuid)
130 try:
131 response = requests.delete(endpoint)
132 except requests.exceptions.RequestException as e:
133 self.__exception(e.message, http_code=503)
134 if response.status_code != 200:
135 self.__exception(WimError.DELETE, http_code=response.status_code)
136
137 self.logger.info("Service with uuid: {} deleted".format(service_uuid))
138
139 def clear_all_connectivity_services(self):
140 endpoint = "{}/service/clearAll".format(self.__wim_url)
141 try:
142 response = requests.delete(endpoint)
143 http_code = response.status_code
144 except requests.exceptions.RequestException as e:
145 self.__exception(e.message, http_code=503)
146 if http_code != 200:
147 self.__exception(WimError.CLEAR_ALL, http_code=http_code)
148
149 self.logger.info("{} services deleted".format(response.content))
150 return "{} services deleted".format(response.content)
151
152 def check_connectivity(self):
153 endpoint = "{}/checkConnectivity".format(self.__wim_url)
154
155 try:
156 response = requests.get(endpoint)
157 http_code = response.status_code
158 except requests.exceptions.RequestException as e:
159 self.__exception(e.message, http_code=503)
160
161 if http_code != 200:
162 self.__exception(WimError.UNREACHABLE, http_code=http_code)
163 self.logger.info("Connectivity checked")
164
165 def check_credentials(self):
166 endpoint = "{}/checkCredentials".format(self.__wim_url)
167 auth = (self.__user, self.__passwd)
168
169 try:
170 response = requests.get(endpoint, auth=auth)
171 http_code = response.status_code
172 except requests.exceptions.RequestException as e:
173 self.__exception(e.message, http_code=503)
174
175 if http_code != 200:
176 self.__exception(WimError.UNAUTHORIZED, http_code=http_code)
177 self.logger.info("Credentials checked")
178
179 # Private functions
180 def __exception(self, x, **kwargs):
181 http_code = kwargs.get("http_code")
182 if hasattr(x, "value"):
183 error = x.value
184 else:
185 error = x
186 self.logger.error(error)
187 raise WimConnectorError(error, http_code=http_code)
188
189 def __check_service(self, service_type, connection_points, kwargs):
190 if service_type not in self.__supported_service_types:
191 self.__exception(WimError.SERVICE_TYPE_ERROR, http_code=400)
192
193 if len(connection_points) != 2:
194 self.__exception(WimError.CONNECTION_POINTS_SIZE, http_code=400)
195
196 for connection_point in connection_points:
197 enc_type = connection_point.get(self.__ENCAPSULATION_TYPE_PARAM)
198 if enc_type not in self.__supported_encapsulation_types:
199 self.__exception(WimError.ENCAPSULATION_TYPE, http_code=400)
200
201 # Commented out for as long as parameter isn't implemented
202 # bandwidth = kwargs.get(self.__BANDWIDTH_PARAM)
203 # if not isinstance(bandwidth, int):
204 # self.__exception(WimError.BANDWIDTH, http_code=400)
205
206 # Commented out for as long as parameter isn't implemented
207 # backup = kwargs.get(self.__BACKUP_PARAM)
208 # if not isinstance(backup, bool):
209 # self.__exception(WimError.BACKUP, http_code=400)
210
211 def __get_body(self, service_type, connection_points, kwargs):
212 port_mapping = self.__config.get("service_endpoint_mapping")
213 selected_ports = []
214 for connection_point in connection_points:
215 endpoint_id = connection_point.get(self.__SERVICE_ENDPOINT_PARAM)
216 port = filter(lambda x: x.get(self.__WAN_SERVICE_ENDPOINT_PARAM) == endpoint_id, port_mapping)[0]
217 port_info = port.get(self.__WAN_MAPPING_INFO_PARAM)
218 selected_ports.append(port_info)
219 if service_type == "ELINE (L2)" or service_type == "ELINE":
220 service_type = "L2"
221 body = {
222 "connection_points": [{
223 "wan_switch_dpid": selected_ports[0].get(self.__SW_ID_PARAM),
224 "wan_switch_port": selected_ports[0].get(self.__SW_PORT_PARAM),
225 "wan_vlan": connection_points[0].get(self.__ENCAPSULATION_INFO_PARAM).get(self.__VLAN_PARAM)
226 }, {
227 "wan_switch_dpid": selected_ports[1].get(self.__SW_ID_PARAM),
228 "wan_switch_port": selected_ports[1].get(self.__SW_PORT_PARAM),
229 "wan_vlan": connection_points[1].get(self.__ENCAPSULATION_INFO_PARAM).get(self.__VLAN_PARAM)
230 }],
231 "bandwidth": 100, # Hardcoded for as long as parameter isn't implemented
232 "service_type": service_type,
233 "backup": False # Hardcoded for as long as parameter isn't implemented
234 }
235 return "body={}".format(json.dumps(body))