| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | ## |
| 3 | # Copyright 2018 Telefonica |
| 4 | # All Rights Reserved. |
| 5 | # |
| 6 | # Contributors: Oscar Gonzalez de Dios, Manuel Lopez Bravo, Guillermo Pajares Martin |
| 7 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 8 | # you may not use this file except in compliance with the License. |
| 9 | # You may obtain a copy of the License at |
| 10 | # |
| 11 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | # |
| 13 | # Unless required by applicable law or agreed to in writing, software |
| 14 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| 16 | # implied. |
| 17 | # See the License for the specific language governing permissions and |
| 18 | # limitations under the License. |
| 19 | # |
| 20 | # This work has been performed in the context of the Metro-Haul project - |
| 21 | # funded by the European Commission under Grant number 761727 through the |
| 22 | # Horizon 2020 program. |
| 23 | ## |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 24 | """The SDN/WIM connector is responsible for establishing wide area network |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 25 | connectivity. |
| 26 | |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 27 | This SDN/WIM connector implements the standard IETF RFC 8466 "A YANG Data |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 28 | Model for Layer 2 Virtual Private Network (L2VPN) Service Delivery" |
| 29 | |
| 30 | It receives the endpoints and the necessary details to request |
| 31 | the Layer 2 service. |
| 32 | """ |
| 33 | import requests |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 34 | import uuid |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 35 | import logging |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 36 | from osm_ro.wim.sdnconn import SdnConnectorBase, SdnConnectorError |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 37 | """CHeck layer where we move it""" |
| 38 | |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 39 | |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 40 | class WimconnectorIETFL2VPN(SdnConnectorBase): |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 41 | |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 42 | def __init__(self, wim, wim_account, config=None, logger=None): |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 43 | """IETF L2VPM WIM connector |
| 44 | |
| 45 | Arguments: (To be completed) |
| 46 | wim (dict): WIM record, as stored in the database |
| 47 | wim_account (dict): WIM account record, as stored in the database |
| 48 | """ |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 49 | self.logger = logging.getLogger('openmano.sdnconn.ietfl2vpn') |
| 50 | super().__init__(wim, wim_account, config, logger) |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 51 | self.headers = {'Content-Type': 'application/json'} |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 52 | self.mappings = {m['service_endpoint_id']: m |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 53 | for m in self.service_endpoint_mapping} |
| 54 | self.user = wim_account.get("user") |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 55 | self.passwd = wim_account.get("passwordd") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 56 | if self.user and self.passwd is not None: |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 57 | self.auth = (self.user, self.passwd) |
| 58 | else: |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 59 | self.auth = None |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 60 | self.logger.info("IETFL2VPN Connector Initialized.") |
| 61 | |
| 62 | def check_credentials(self): |
| 63 | endpoint = "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services".format(self.wim["wim_url"]) |
| 64 | try: |
| 65 | response = requests.get(endpoint, auth=self.auth) |
| 66 | http_code = response.status_code |
| 67 | except requests.exceptions.RequestException as e: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 68 | raise SdnConnectorError(e.message, http_code=503) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 69 | |
| 70 | if http_code != 200: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 71 | raise SdnConnectorError("Failed while authenticating", http_code=http_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 72 | self.logger.info("Credentials checked") |
| 73 | |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 74 | def get_connectivity_service_status(self, service_uuid, conn_info=None): |
| 75 | """Monitor the status of the connectivity service stablished |
| 76 | |
| 77 | Arguments: |
| 78 | service_uuid: Connectivity service unique identifier |
| 79 | |
| 80 | Returns: |
| 81 | Examples:: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 82 | {'sdn_status': 'ACTIVE'} |
| 83 | {'sdn_status': 'INACTIVE'} |
| 84 | {'sdn_status': 'DOWN'} |
| 85 | {'sdn_status': 'ERROR'} |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 86 | """ |
| 87 | try: |
| 88 | self.logger.info("Sending get connectivity service stuatus") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 89 | servicepoint = "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services/vpn-service={}/".format( |
| 90 | self.wim["wim_url"], service_uuid) |
| 91 | response = requests.get(servicepoint, auth=self.auth) |
| 92 | if response.status_code != requests.codes.ok: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 93 | raise SdnConnectorError("Unable to obtain connectivity servcice status", http_code=response.status_code) |
| 94 | service_status = {'sdn_status': 'ACTIVE'} |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 95 | return service_status |
| 96 | except requests.exceptions.ConnectionError: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 97 | raise SdnConnectorError("Request Timeout", http_code=408) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 98 | |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 99 | def search_mapp(self, connection_point): |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 100 | id = connection_point['service_endpoint_id'] |
| 101 | if id not in self.mappings: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 102 | raise SdnConnectorError("Endpoint {} not located".format(str(id))) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 103 | else: |
| 104 | return self.mappings[id] |
| 105 | |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 106 | def create_connectivity_service(self, service_type, connection_points, **kwargs): |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 107 | """Stablish WAN connectivity between the endpoints |
| 108 | |
| 109 | Arguments: |
| 110 | service_type (str): ``ELINE`` (L2), ``ELAN`` (L2), ``ETREE`` (L2), |
| 111 | ``L3``. |
| 112 | connection_points (list): each point corresponds to |
| 113 | an entry point from the DC to the transport network. One |
| 114 | connection point serves to identify the specific access and |
| 115 | some other service parameters, such as encapsulation type. |
| 116 | Represented by a dict as follows:: |
| 117 | |
| 118 | { |
| 119 | "service_endpoint_id": ..., (str[uuid]) |
| 120 | "service_endpoint_encapsulation_type": ..., |
| 121 | (enum: none, dot1q, ...) |
| 122 | "service_endpoint_encapsulation_info": { |
| 123 | ... (dict) |
| 124 | "vlan": ..., (int, present if encapsulation is dot1q) |
| 125 | "vni": ... (int, present if encapsulation is vxlan), |
| 126 | "peers": [(ipv4_1), (ipv4_2)] |
| 127 | (present if encapsulation is vxlan) |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | The service endpoint ID should be previously informed to the WIM |
| 132 | engine in the RO when the WIM port mapping is registered. |
| 133 | |
| 134 | Keyword Arguments: |
| 135 | bandwidth (int): value in kilobytes |
| 136 | latency (int): value in milliseconds |
| 137 | |
| 138 | Other QoS might be passed as keyword arguments. |
| 139 | |
| 140 | Returns: |
| 141 | tuple: ``(service_id, conn_info)`` containing: |
| 142 | - *service_uuid* (str): UUID of the established connectivity |
| 143 | service |
| 144 | - *conn_info* (dict or None): Information to be stored at the |
| 145 | database (or ``None``). This information will be provided to |
| 146 | the :meth:`~.edit_connectivity_service` and :obj:`~.delete`. |
| 147 | **MUST** be JSON/YAML-serializable (plain data structures). |
| 148 | |
| 149 | Raises: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 150 | SdnConnectorException: In case of error. |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 151 | """ |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 152 | if service_type == "ELINE": |
| 153 | if len(connection_points) > 2: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 154 | raise SdnConnectorError('Connections between more than 2 endpoints are not supported') |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 155 | if len(connection_points) < 2: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 156 | raise SdnConnectorError('Connections must be of at least 2 endpoints') |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 157 | """ First step, create the vpn service """ |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 158 | uuid_l2vpn = str(uuid.uuid4()) |
| 159 | vpn_service = {} |
| 160 | vpn_service["vpn-id"] = uuid_l2vpn |
| 161 | vpn_service["vpn-scv-type"] = "vpws" |
| 162 | vpn_service["svc-topo"] = "any-to-any" |
| 163 | vpn_service["customer-name"] = "osm" |
| 164 | vpn_service_list = [] |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 165 | vpn_service_list.append(vpn_service) |
| pajaresmarti | 6e9f180 | 2019-08-29 10:55:31 +0200 | [diff] [blame] | 166 | vpn_service_l = {"ietf-l2vpn-svc:vpn-service": vpn_service_list} |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 167 | response_service_creation = None |
| 168 | conn_info = [] |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 169 | self.logger.info("Sending vpn-service :{}".format(vpn_service_l)) |
| 170 | try: |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 171 | endpoint_service_creation = "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services".format( |
| 172 | self.wim["wim_url"]) |
| 173 | response_service_creation = requests.post(endpoint_service_creation, headers=self.headers, |
| 174 | json=vpn_service_l, auth=self.auth) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 175 | except requests.exceptions.ConnectionError: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 176 | raise SdnConnectorError("Request to create service Timeout", http_code=408) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 177 | if response_service_creation.status_code == 409: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 178 | raise SdnConnectorError("Service already exists", http_code=response_service_creation.status_code) |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 179 | elif response_service_creation.status_code != requests.codes.created: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 180 | raise SdnConnectorError("Request to create service not accepted", |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 181 | http_code=response_service_creation.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 182 | """ Second step, create the connections and vpn attachments """ |
| 183 | for connection_point in connection_points: |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 184 | connection_point_wan_info = self.search_mapp(connection_point) |
| 185 | site_network_access = {} |
| 186 | connection = {} |
| 187 | if connection_point["service_endpoint_encapsulation_type"] != "none": |
| 188 | if connection_point["service_endpoint_encapsulation_type"] == "dot1q": |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 189 | """ The connection is a VLAN """ |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 190 | connection["encapsulation-type"] = "dot1q-vlan-tagged" |
| 191 | tagged = {} |
| 192 | tagged_interf = {} |
| 193 | service_endpoint_encapsulation_info = connection_point["service_endpoint_encapsulation_info"] |
| 194 | if service_endpoint_encapsulation_info["vlan"] is None: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 195 | raise SdnConnectorError("VLAN must be provided") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 196 | tagged_interf["cvlan-id"] = service_endpoint_encapsulation_info["vlan"] |
| 197 | tagged["dot1q-vlan-tagged"] = tagged_interf |
| 198 | connection["tagged-interface"] = tagged |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 199 | else: |
| 200 | raise NotImplementedError("Encapsulation type not implemented") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 201 | site_network_access["connection"] = connection |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 202 | self.logger.info("Sending connection:{}".format(connection)) |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 203 | vpn_attach = {} |
| 204 | vpn_attach["vpn-id"] = uuid_l2vpn |
| 205 | vpn_attach["site-role"] = vpn_service["svc-topo"]+"-role" |
| 206 | site_network_access["vpn-attachment"] = vpn_attach |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 207 | self.logger.info("Sending vpn-attachement :{}".format(vpn_attach)) |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 208 | uuid_sna = str(uuid.uuid4()) |
| 209 | site_network_access["network-access-id"] = uuid_sna |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 210 | site_network_access["bearer"] = connection_point_wan_info["service_mapping_info"]["bearer"] |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 211 | site_network_accesses = {} |
| 212 | site_network_access_list = [] |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 213 | site_network_access_list.append(site_network_access) |
| pajaresmarti | 6e9f180 | 2019-08-29 10:55:31 +0200 | [diff] [blame] | 214 | site_network_accesses["ietf-l2vpn-svc:site-network-access"] = site_network_access_list |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 215 | conn_info_d = {} |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 216 | conn_info_d["site"] = connection_point_wan_info["service_mapping_info"]["site-id"] |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 217 | conn_info_d["site-network-access-id"] = site_network_access["network-access-id"] |
| 218 | conn_info_d["mapping"] = None |
| 219 | conn_info.append(conn_info_d) |
| 220 | try: |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 221 | endpoint_site_network_access_creation = \ |
| 222 | "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/sites/site={}/site-network-accesses/".format( |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 223 | self.wim["wim_url"], connection_point_wan_info["service_mapping_info"]["site-id"]) |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 224 | response_endpoint_site_network_access_creation = requests.post( |
| 225 | endpoint_site_network_access_creation, |
| 226 | headers=self.headers, |
| 227 | json=site_network_accesses, |
| 228 | auth=self.auth) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 229 | |
| 230 | if response_endpoint_site_network_access_creation.status_code == 409: |
| 231 | self.delete_connectivity_service(vpn_service["vpn-id"]) |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 232 | raise SdnConnectorError("Site_Network_Access with ID '{}' already exists".format( |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 233 | site_network_access["network-access-id"]), |
| 234 | http_code=response_endpoint_site_network_access_creation.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 235 | |
| 236 | elif response_endpoint_site_network_access_creation.status_code == 400: |
| 237 | self.delete_connectivity_service(vpn_service["vpn-id"]) |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 238 | raise SdnConnectorError("Site {} does not exist".format( |
| 239 | connection_point_wan_info["service_mapping_info"]["site-id"]), |
| pajaresmarti | 66d080e | 2019-06-20 12:45:21 +0200 | [diff] [blame] | 240 | http_code=response_endpoint_site_network_access_creation.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 241 | |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 242 | elif response_endpoint_site_network_access_creation.status_code != requests.codes.created and \ |
| 243 | response_endpoint_site_network_access_creation.status_code != requests.codes.no_content: |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 244 | self.delete_connectivity_service(vpn_service["vpn-id"]) |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 245 | raise SdnConnectorError("Request no accepted", |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 246 | http_code=response_endpoint_site_network_access_creation.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 247 | |
| 248 | except requests.exceptions.ConnectionError: |
| 249 | self.delete_connectivity_service(vpn_service["vpn-id"]) |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 250 | raise SdnConnectorError("Request Timeout", http_code=408) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 251 | return uuid_l2vpn, conn_info |
| 252 | |
| 253 | else: |
| 254 | raise NotImplementedError |
| 255 | |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 256 | def delete_connectivity_service(self, service_uuid, conn_info=None): |
| 257 | """Disconnect multi-site endpoints previously connected |
| 258 | |
| 259 | This method should receive as the first argument the UUID generated by |
| 260 | the ``create_connectivity_service`` |
| 261 | """ |
| 262 | try: |
| 263 | self.logger.info("Sending delete") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 264 | servicepoint = "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services/vpn-service={}/".format( |
| 265 | self.wim["wim_url"], service_uuid) |
| 266 | response = requests.delete(servicepoint, auth=self.auth) |
| 267 | if response.status_code != requests.codes.no_content: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 268 | raise SdnConnectorError("Error in the request", http_code=response.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 269 | except requests.exceptions.ConnectionError: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 270 | raise SdnConnectorError("Request Timeout", http_code=408) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 271 | |
| 272 | def edit_connectivity_service(self, service_uuid, conn_info=None, |
| 273 | connection_points=None, **kwargs): |
| 274 | """Change an existing connectivity service, see |
| 275 | ``create_connectivity_service``""" |
| 276 | |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 277 | # sites = {"sites": {}} |
| 278 | # site_list = [] |
| 279 | vpn_service = {} |
| 280 | vpn_service["svc-topo"] = "any-to-any" |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 281 | counter = 0 |
| 282 | for connection_point in connection_points: |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 283 | site_network_access = {} |
| 284 | connection_point_wan_info = self.search_mapp(connection_point) |
| 285 | params_site = {} |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 286 | params_site["site-id"] = connection_point_wan_info["service_mapping_info"]["site-id"] |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 287 | params_site["site-vpn-flavor"] = "site-vpn-flavor-single" |
| 288 | device_site = {} |
| 289 | device_site["device-id"] = connection_point_wan_info["device-id"] |
| 290 | params_site["devices"] = device_site |
| 291 | # network_access = {} |
| 292 | connection = {} |
| 293 | if connection_point["service_endpoint_encapsulation_type"] != "none": |
| 294 | if connection_point["service_endpoint_encapsulation_type"] == "dot1q": |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 295 | """ The connection is a VLAN """ |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 296 | connection["encapsulation-type"] = "dot1q-vlan-tagged" |
| 297 | tagged = {} |
| 298 | tagged_interf = {} |
| 299 | service_endpoint_encapsulation_info = connection_point["service_endpoint_encapsulation_info"] |
| 300 | if service_endpoint_encapsulation_info["vlan"] is None: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 301 | raise SdnConnectorError("VLAN must be provided") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 302 | tagged_interf["cvlan-id"] = service_endpoint_encapsulation_info["vlan"] |
| 303 | tagged["dot1q-vlan-tagged"] = tagged_interf |
| 304 | connection["tagged-interface"] = tagged |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 305 | else: |
| 306 | raise NotImplementedError("Encapsulation type not implemented") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 307 | site_network_access["connection"] = connection |
| 308 | vpn_attach = {} |
| 309 | vpn_attach["vpn-id"] = service_uuid |
| 310 | vpn_attach["site-role"] = vpn_service["svc-topo"]+"-role" |
| 311 | site_network_access["vpn-attachment"] = vpn_attach |
| 312 | uuid_sna = conn_info[counter]["site-network-access-id"] |
| 313 | site_network_access["network-access-id"] = uuid_sna |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 314 | site_network_access["bearer"] = connection_point_wan_info["service_mapping_info"]["bearer"] |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 315 | site_network_accesses = {} |
| 316 | site_network_access_list = [] |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 317 | site_network_access_list.append(site_network_access) |
| pajaresmarti | 6e9f180 | 2019-08-29 10:55:31 +0200 | [diff] [blame] | 318 | site_network_accesses["ietf-l2vpn-svc:site-network-access"] = site_network_access_list |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 319 | try: |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 320 | endpoint_site_network_access_edit = \ |
| 321 | "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/sites/site={}/site-network-accesses/".format( |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 322 | self.wim["wim_url"], connection_point_wan_info["service_mapping_info"]["site-id"]) |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 323 | response_endpoint_site_network_access_creation = requests.put(endpoint_site_network_access_edit, |
| 324 | headers=self.headers, |
| 325 | json=site_network_accesses, |
| 326 | auth=self.auth) |
| 327 | if response_endpoint_site_network_access_creation.status_code == 400: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 328 | raise SdnConnectorError("Service does not exist", |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 329 | http_code=response_endpoint_site_network_access_creation.status_code) |
| 330 | elif response_endpoint_site_network_access_creation.status_code != 201 and \ |
| 331 | response_endpoint_site_network_access_creation.status_code != 204: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 332 | raise SdnConnectorError("Request no accepted", |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 333 | http_code=response_endpoint_site_network_access_creation.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 334 | except requests.exceptions.ConnectionError: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 335 | raise SdnConnectorError("Request Timeout", http_code=408) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 336 | counter += 1 |
| 337 | return None |
| 338 | |
| 339 | def clear_all_connectivity_services(self): |
| 340 | """Delete all WAN Links corresponding to a WIM""" |
| 341 | try: |
| 342 | self.logger.info("Sending clear all connectivity services") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 343 | servicepoint = "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services".format(self.wim["wim_url"]) |
| 344 | response = requests.delete(servicepoint, auth=self.auth) |
| 345 | if response.status_code != requests.codes.no_content: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 346 | raise SdnConnectorError("Unable to clear all connectivity services", http_code=response.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 347 | except requests.exceptions.ConnectionError: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 348 | raise SdnConnectorError("Request Timeout", http_code=408) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 349 | |
| 350 | def get_all_active_connectivity_services(self): |
| 351 | """Provide information about all active connections provisioned by a |
| 352 | WIM |
| 353 | """ |
| 354 | try: |
| 355 | self.logger.info("Sending get all connectivity services") |
| tierno | 8a2d207 | 2019-04-29 14:42:32 +0000 | [diff] [blame] | 356 | servicepoint = "{}/restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services".format(self.wim["wim_url"]) |
| 357 | response = requests.get(servicepoint, auth=self.auth) |
| 358 | if response.status_code != requests.codes.ok: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 359 | raise SdnConnectorError("Unable to get all connectivity services", http_code=response.status_code) |
| gonzalezdedi | 00f9c19 | 2019-01-18 14:52:43 +0100 | [diff] [blame] | 360 | return response |
| 361 | except requests.exceptions.ConnectionError: |
| tierno | ed3e4d4 | 2019-10-21 15:31:27 +0000 | [diff] [blame] | 362 | raise SdnConnectorError("Request Timeout", http_code=408) |