From 7e2ca0af3dffcc1d2fdccbee39d8b77d7b8f78e2 Mon Sep 17 00:00:00 2001 From: gifrerenom <lluis.gifre@cttc.es> Date: Mon, 20 Feb 2023 17:26:45 +0000 Subject: [PATCH] Device component - IETF L2VPN Driver: - added pseudocode - backup WORK IN PROGRESS --- .../drivers/ietf_l2vpn/IetfL2VpnDriver.py | 96 ++++++++++++------- .../service/drivers/ietf_l2vpn/MockOSM.py | 62 ------------ .../ietf_l2vpn/WimconnectorIETFL2VPN.py | 4 +- .../service/drivers/ietf_l2vpn/__init__.py | 14 --- 4 files changed, 63 insertions(+), 113 deletions(-) delete mode 100644 src/device/service/drivers/ietf_l2vpn/MockOSM.py diff --git a/src/device/service/drivers/ietf_l2vpn/IetfL2VpnDriver.py b/src/device/service/drivers/ietf_l2vpn/IetfL2VpnDriver.py index 3823f569b..609221963 100644 --- a/src/device/service/drivers/ietf_l2vpn/IetfL2VpnDriver.py +++ b/src/device/service/drivers/ietf_l2vpn/IetfL2VpnDriver.py @@ -12,17 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -import logging, requests, threading -from requests.auth import HTTPBasicAuth +import logging, threading from typing import Any, Iterator, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method from common.type_checkers.Checkers import chk_string, chk_type -from device.service.driver_api._Driver import _Driver -from . import ALL_RESOURCE_KEYS -from .Tools import create_connectivity_service, find_key, config_getter, delete_connectivity_service +from device.service.driver_api._Driver import _Driver, RESOURCE_ENDPOINTS, RESOURCE_SERVICES +from .Tools import find_key +from .WimconnectorIETFL2VPN import WimconnectorIETFL2VPN LOGGER = logging.getLogger(__name__) +ALL_RESOURCE_KEYS = [ + RESOURCE_ENDPOINTS, + RESOURCE_SERVICES, +] + METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': 'ietf_l2vpn'}) class IetfL2VpnDriver(_Driver): @@ -32,20 +36,17 @@ class IetfL2VpnDriver(_Driver): self.__terminate = threading.Event() username = settings.get('username') password = settings.get('password') - self.__auth = HTTPBasicAuth(username, password) if username is not None and password is not None else None scheme = settings.get('scheme', 'http') - self.__tapi_root = '{:s}://{:s}:{:d}'.format(scheme, address, int(port)) - self.__timeout = int(settings.get('timeout', 120)) + wim = {'wim_url': '{:s}://{:s}:{:d}'.format(scheme, address, int(port))} + wim_account = {'user': username, 'password': password} + config = {'mapping_not_needed': False, 'service_endpoint_mapping': mapping} + self.wim = WimconnectorIETFL2VPN(wim, wim_account, config=config) + self.conn_info = {} # internal database emulating OSM storage provided to WIM Connectors def Connect(self) -> bool: - url = self.__tapi_root + '/restconf/data/tapi-common:context' with self.__lock: - if self.__started.is_set(): return True try: - requests.get(url, timeout=self.__timeout, verify=False, auth=self.__auth) - except requests.exceptions.Timeout: - LOGGER.exception('Timeout connecting {:s}'.format(str(self.__tapi_root))) - return False + self.wim.check_credentials() except Exception: # pylint: disable=broad-except LOGGER.exception('Exception connecting {:s}'.format(str(self.__tapi_root))) return False @@ -68,36 +69,53 @@ class IetfL2VpnDriver(_Driver): chk_type('resources', resource_keys, list) results = [] with self.__lock: + self.wim.check_credentials() if len(resource_keys) == 0: resource_keys = ALL_RESOURCE_KEYS for i, resource_key in enumerate(resource_keys): str_resource_name = 'resource_key[#{:d}]'.format(i) chk_string(str_resource_name, resource_key, allow_empty=False) - results.extend(config_getter( - self.__tapi_root, resource_key, timeout=self.__timeout, auth=self.__auth)) + + if resource_key == RESOURCE_ENDPOINTS: + # return endpoints through debug-api and list-devices method + endpoints = self.debug_api.get_endpoints() + for endpoint in endpoints: results.append(process_endpoint(endpoint)) + elif resource_key == RESOURCE_SERVICES: + # return all services through + services = self.wim.get_all_active_connectivity_services() + for service in services: results.append(process_service(service)) + else: + # assume single-service retrieval + service = self.wim.get_connectivity_service() + results.append(process_service(service)) return results @metered_subclass_method(METRICS_POOL) def SetConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: results = [] - if len(resources) == 0: - return results + if len(resources) == 0: return results with self.__lock: + self.wim.check_credentials() for resource in resources: LOGGER.info('resource = {:s}'.format(str(resource))) - input_sip = find_key(resource, 'input_sip') - output_sip = find_key(resource, 'output_sip') uuid = find_key(resource, 'uuid') - capacity_value = find_key(resource, 'capacity_value') - capacity_unit = find_key(resource, 'capacity_unit') - layer_protocol_name = find_key(resource, 'layer_protocol_name') - layer_protocol_qualifier = find_key(resource, 'layer_protocol_qualifier') - direction = find_key(resource, 'direction') - - data = create_connectivity_service( - self.__tapi_root, uuid, input_sip, output_sip, direction, capacity_value, capacity_unit, - layer_protocol_name, layer_protocol_qualifier, timeout=self.__timeout, auth=self.__auth) - results.extend(data) + #input_sip = find_key(resource, 'input_sip') + #output_sip = find_key(resource, 'output_sip') + #capacity_value = find_key(resource, 'capacity_value') + #capacity_unit = find_key(resource, 'capacity_unit') + #layer_protocol_name = find_key(resource, 'layer_protocol_name') + #layer_protocol_qualifier = find_key(resource, 'layer_protocol_qualifier') + #direction = find_key(resource, 'direction') + + result = self.wim.get_connectivity_service_status( + service_uuid, conn_info=conn_info) + if service_exists(result): + result = self.wim.create_connectivity_service( + service_type, connection_points) + else: + result = self.wim.edit_connectivity_service( + service_uuid, conn_info=conn_info, connection_points=connection_points) + results.extend(process_result(result)) return results @metered_subclass_method(METRICS_POOL) @@ -105,25 +123,33 @@ class IetfL2VpnDriver(_Driver): results = [] if len(resources) == 0: return results with self.__lock: + self.wim.check_credentials() for resource in resources: LOGGER.info('resource = {:s}'.format(str(resource))) uuid = find_key(resource, 'uuid') - results.extend(delete_connectivity_service( - self.__tapi_root, uuid, timeout=self.__timeout, auth=self.__auth)) + + result = self.wim.get_connectivity_service_status( + service_uuid, conn_info=conn_info) + if service_exists(result): + result = self.wim.delete_connectivity_service( + service_uuid, conn_info=conn_info) + else: + result = False + results.append(process_result(result)) return results @metered_subclass_method(METRICS_POOL) def SubscribeState(self, subscriptions : List[Tuple[str, float, float]]) -> List[Union[bool, Exception]]: - # TODO: TAPI does not support monitoring by now + # TODO: IETF L2VPN does not support monitoring by now return [False for _ in subscriptions] @metered_subclass_method(METRICS_POOL) def UnsubscribeState(self, subscriptions : List[Tuple[str, float, float]]) -> List[Union[bool, Exception]]: - # TODO: TAPI does not support monitoring by now + # TODO: IETF L2VPN does not support monitoring by now return [False for _ in subscriptions] def GetState( self, blocking=False, terminate : Optional[threading.Event] = None ) -> Iterator[Tuple[float, str, Any]]: - # TODO: TAPI does not support monitoring by now + # TODO: IETF L2VPN does not support monitoring by now return [] diff --git a/src/device/service/drivers/ietf_l2vpn/MockOSM.py b/src/device/service/drivers/ietf_l2vpn/MockOSM.py deleted file mode 100644 index 338db0e19..000000000 --- a/src/device/service/drivers/ietf_l2vpn/MockOSM.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -from .WimconnectorIETFL2VPN import WimconnectorIETFL2VPN - -LOGGER = logging.getLogger(__name__) - -class MockOSM: - def __init__(self, url, mapping, username, password): - wim = {'wim_url': url} - wim_account = {'user': username, 'password': password} - config = {'mapping_not_needed': False, 'service_endpoint_mapping': mapping} - self.wim = WimconnectorIETFL2VPN(wim, wim_account, config=config) - self.conn_info = {} # internal database emulating OSM storage provided to WIM Connectors - - def create_connectivity_service(self, service_type, connection_points): - LOGGER.info('[create_connectivity_service] service_type={:s}'.format(str(service_type))) - LOGGER.info('[create_connectivity_service] connection_points={:s}'.format(str(connection_points))) - self.wim.check_credentials() - result = self.wim.create_connectivity_service(service_type, connection_points) - LOGGER.info('[create_connectivity_service] result={:s}'.format(str(result))) - service_uuid, conn_info = result - self.conn_info[service_uuid] = conn_info - return service_uuid - - def get_connectivity_service_status(self, service_uuid): - LOGGER.info('[get_connectivity_service] service_uuid={:s}'.format(str(service_uuid))) - conn_info = self.conn_info.get(service_uuid) - if conn_info is None: raise Exception('ServiceId({:s}) not found'.format(str(service_uuid))) - LOGGER.info('[get_connectivity_service] conn_info={:s}'.format(str(conn_info))) - self.wim.check_credentials() - result = self.wim.get_connectivity_service_status(service_uuid, conn_info=conn_info) - LOGGER.info('[get_connectivity_service] result={:s}'.format(str(result))) - return result - - def edit_connectivity_service(self, service_uuid, connection_points): - LOGGER.info('[edit_connectivity_service] service_uuid={:s}'.format(str(service_uuid))) - LOGGER.info('[edit_connectivity_service] connection_points={:s}'.format(str(connection_points))) - conn_info = self.conn_info.get(service_uuid) - if conn_info is None: raise Exception('ServiceId({:s}) not found'.format(str(service_uuid))) - LOGGER.info('[edit_connectivity_service] conn_info={:s}'.format(str(conn_info))) - self.wim.edit_connectivity_service(service_uuid, conn_info=conn_info, connection_points=connection_points) - - def delete_connectivity_service(self, service_uuid): - LOGGER.info('[delete_connectivity_service] service_uuid={:s}'.format(str(service_uuid))) - conn_info = self.conn_info.get(service_uuid) - if conn_info is None: raise Exception('ServiceId({:s}) not found'.format(str(service_uuid))) - LOGGER.info('[delete_connectivity_service] conn_info={:s}'.format(str(conn_info))) - self.wim.check_credentials() - self.wim.delete_connectivity_service(service_uuid, conn_info=conn_info) diff --git a/src/device/service/drivers/ietf_l2vpn/WimconnectorIETFL2VPN.py b/src/device/service/drivers/ietf_l2vpn/WimconnectorIETFL2VPN.py index aa4ca045f..b3721b2d5 100644 --- a/src/device/service/drivers/ietf_l2vpn/WimconnectorIETFL2VPN.py +++ b/src/device/service/drivers/ietf_l2vpn/WimconnectorIETFL2VPN.py @@ -55,9 +55,9 @@ class WimconnectorIETFL2VPN(SdnConnectorBase): m["service_endpoint_id"]: m for m in self.service_endpoint_mapping } self.user = wim_account.get("user") - self.passwd = wim_account.get("password") # replace "passwordd" -> "password" + self.passwd = wim_account.get("password") - if self.user and self.passwd is not None: + if self.user is not None and self.passwd is not None: self.auth = (self.user, self.passwd) else: self.auth = None diff --git a/src/device/service/drivers/ietf_l2vpn/__init__.py b/src/device/service/drivers/ietf_l2vpn/__init__.py index 2d3f6df32..38d04994f 100644 --- a/src/device/service/drivers/ietf_l2vpn/__init__.py +++ b/src/device/service/drivers/ietf_l2vpn/__init__.py @@ -11,17 +11,3 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - -from device.service.driver_api._Driver import RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES - -ALL_RESOURCE_KEYS = [ - RESOURCE_ENDPOINTS, - RESOURCE_INTERFACES, - RESOURCE_NETWORK_INSTANCES, -] - -RESOURCE_KEY_MAPPINGS = { - RESOURCE_ENDPOINTS : 'component', - RESOURCE_INTERFACES : 'interface', - RESOURCE_NETWORK_INSTANCES: 'network_instance', -} -- GitLab