diff --git a/src/context/service/database/models/enums/DeviceDriver.py b/src/context/service/database/models/enums/DeviceDriver.py index cf900ed6df3b4699a4e56f53873174ddd997cd53..ca00f6e80a0ccf07147fc9794da642ef1dec2dad 100644 --- a/src/context/service/database/models/enums/DeviceDriver.py +++ b/src/context/service/database/models/enums/DeviceDriver.py @@ -35,6 +35,7 @@ class ORM_DeviceDriverEnum(enum.Enum): IETF_ACTN = DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN OC = DeviceDriverEnum.DEVICEDRIVER_OC QKD = DeviceDriverEnum.DEVICEDRIVER_QKD + IETF_L3VPN = DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN grpc_to_enum__device_driver = functools.partial( grpc_to_enum, DeviceDriverEnum, ORM_DeviceDriverEnum) diff --git a/src/device/service/drivers/emulated/Tools.py b/src/device/service/drivers/emulated/Tools.py index cdd84fccf0d3b2c373b99e5f229201e8967de9c2..f452712bbe9e2ea2386766f82f99d1922fdbb1f9 100644 --- a/src/device/service/drivers/emulated/Tools.py +++ b/src/device/service/drivers/emulated/Tools.py @@ -82,6 +82,26 @@ def compose_resource_endpoint(endpoint_data : Dict[str, Any]) -> Optional[Tuple[ if 'location' in endpoint_data: endpoint_resource_value['location'] = endpoint_data['location'] + + if "site_location" in endpoint_data: + endpoint_resource_value["site_location"] = endpoint_data["site_location"] + + if "ce-ip" in endpoint_data: + endpoint_resource_value["ce-ip"] = endpoint_data["ce-ip"] + + if "address_ip" in endpoint_data: + endpoint_resource_value["address_ip"] = endpoint_data["address_ip"] + + if "address_prefix" in endpoint_data: + endpoint_resource_value["address_prefix"] = endpoint_data["address_prefix"] + + if "mtu" in endpoint_data: + endpoint_resource_value["mtu"] = endpoint_data["mtu"] + + if "ipv4_lan_prefixes" in endpoint_data: + endpoint_resource_value["ipv4_lan_prefixes"] = endpoint_data[ + "ipv4_lan_prefixes" + ] return endpoint_resource_key, endpoint_resource_value except: # pylint: disable=bare-except diff --git a/src/device/service/drivers/ietf_l3vpn/TfsApiClient.py b/src/device/service/drivers/ietf_l3vpn/TfsApiClient.py index 661907a7384cc4abb6aafc106f01216ee5b0652c..f635f1a75aba78fb3d54b9fb46275e6f2f2e2c29 100644 --- a/src/device/service/drivers/ietf_l3vpn/TfsApiClient.py +++ b/src/device/service/drivers/ietf_l3vpn/TfsApiClient.py @@ -69,12 +69,13 @@ class TfsApiClient: ) -> None: self._devices_url = GET_DEVICES_URL.format(scheme, address, port) self._links_url = GET_LINKS_URL.format(scheme, address, port) - self._l3vph_url = L3VPN_URL.format(scheme, address, port) - self._auth = ( - HTTPBasicAuth(username, password) - if username is not None and password is not None - else None - ) + self._l3vpn_url = L3VPN_URL.format(scheme, address, port) + self._auth = None + # ( + # HTTPBasicAuth(username, password) + # if username is not None and password is not None + # else None + # ) def get_devices_endpoints( self, import_topology: ImportTopologyEnum = ImportTopologyEnum.DEVICES @@ -84,9 +85,7 @@ class TfsApiClient: "[get_devices_endpoints] import_topology={:s}".format(str(import_topology)) ) - reply = requests.get( - self._devices_url, timeout=TIMEOUT, verify=False, auth=self._auth - ) + reply = requests.get(self._devices_url, timeout=TIMEOUT, auth=self._auth) if reply.status_code not in HTTP_OK_CODES: msg = MSG_ERROR.format( str(self._devices_url), str(reply.status_code), str(reply) @@ -131,9 +130,7 @@ class TfsApiClient: LOGGER.debug("[get_devices_endpoints] devices only; returning") return result - reply = requests.get( - self._links_url, timeout=TIMEOUT, verify=False, auth=self._auth - ) + reply = requests.get(self._links_url, timeout=TIMEOUT, auth=self._auth) if reply.status_code not in HTTP_OK_CODES: msg = MSG_ERROR.format( str(self._links_url), str(reply.status_code), str(reply) @@ -163,12 +160,12 @@ class TfsApiClient: def create_connectivity_service(self, l3vpn_data: dict) -> None: try: - requests.post(self._l3vph_url, json=l3vpn_data, auth=self._auth) + requests.post(self._l3vpn_url, json=l3vpn_data) except requests.exceptions.ConnectionError: raise Exception("faild to send post request to TFS L3VPN NBI") def delete_connectivity_service(self, service_uuid: str) -> None: - url = self._l3vph_url + f"/vpn-service={service_uuid}" + url = self._l3vpn_url + f"/vpn-service={service_uuid}" try: requests.delete(url, auth=self._auth) except requests.exceptions.ConnectionError: diff --git a/src/device/service/drivers/ietf_l3vpn/Tools.py b/src/device/service/drivers/ietf_l3vpn/Tools.py index bf9c40732d00f5a7e37a37ca8c56d565ca8e29e9..eeb0d87f1600979ebc30fd7400f23e3595afb7a4 100644 --- a/src/device/service/drivers/ietf_l3vpn/Tools.py +++ b/src/device/service/drivers/ietf_l3vpn/Tools.py @@ -61,9 +61,9 @@ def get_all_active_connectivity_services(wim_url: str, auth): def get_connectivity_service(wim_url, auth, service_uuid): try: LOGGER.info("Sending get connectivity service") - servicepoint = f"{wim_url}/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-service={service_uuid}" + servicepoint = f"{wim_url}/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={service_uuid}" - response = requests.get(servicepoint, auth=auth) + response = requests.get(servicepoint) if response.status_code != requests.codes.ok: raise Exception( @@ -85,9 +85,9 @@ def create_l3vpn_datamodel(service_uuid, resource_value: dict) -> dict: ) src_site_id: str = resource_value.get("src_site_id", f"site_{src_site_location}") src_management_type: str = resource_value.get( - "src_management_type", "ietf-l3vpn-svc:customer-managed" + "src_management_type", "ietf-l3vpn-svc:provider-managed" ) - if src_management_type != "ietf-l3vpn-svc:customer-managed": + if src_management_type != "ietf-l3vpn-svc:provider-managed": raise Exception("management type %s not supported", src_management_type) src_role: str = "ietf-l3vpn-svc:hub-role" src_ce_address: str = resource_value["src_ce_address"] @@ -96,12 +96,8 @@ def create_l3vpn_datamodel(service_uuid, resource_value: dict) -> dict: src_mtu: int = resource_value["src_mtu"] src_input_bw: int = resource_value.get("src_input_bw", 1000000000) src_output_bw: int = resource_value.get("src_input_bw", 1000000000) - src_qos_profile_id: str = resource_value.get( - "src_qos_profile_id", "src_qos_profile" - ) - src_qos_profile_direction: str = ( - resource_value.get("src_qos_profile_direction", "ietf-l3vpn-svc:both"), - ) + src_qos_profile_id = "qos-realtime" + src_qos_profile_direction = "ietf-l3vpn-svc:both" src_qos_profile_latency: int = resource_value.get("src_qos_profile_latency", 10) src_qos_profile_bw_guarantee: int = resource_value.get( "src_qos_profile_bw_guarantee", 100 @@ -115,9 +111,9 @@ def create_l3vpn_datamodel(service_uuid, resource_value: dict) -> dict: ] dst_site_id: str = resource_value.get("dst_site_id", f"site_{dst_site_location}") dst_management_type: str = resource_value.get( - "dst_management_type", "ietf-l3vpn-svc:customer-managed" + "dst_management_type", "ietf-l3vpn-svc:provider-managed" ) - if dst_management_type != "ietf-l3vpn-svc:customer-managed": + if dst_management_type != "ietf-l3vpn-svc:provider-managed": raise Exception("management type %s not supported", dst_management_type) dst_role: str = "ietf-l3vpn-svc:spoke-role" dst_ce_address: str = resource_value["dst_ce_address"] @@ -126,12 +122,8 @@ def create_l3vpn_datamodel(service_uuid, resource_value: dict) -> dict: dst_mtu: int = resource_value["dst_mtu"] dst_input_bw: int = resource_value.get("dst_input_bw", 1000000000) dst_output_bw: int = resource_value.get("dst_output_bw", 1000000000) - dst_qos_profile_id: str = resource_value.get( - "dst_qos_profile_id", "dst_qos_profile" - ) - dst_qos_profile_direction: str = ( - resource_value.get("dst_qos_profile_direction", "ietf-l3vpn-svc:both"), - ) + dst_qos_profile_id = "qos-realtime" + dst_qos_profile_direction = "ietf-l3vpn-svc:both" dst_qos_profile_latency: int = resource_value.get("dst_qos_profile_latency", 10) dst_qos_profile_bw_guarantee: int = resource_value.get( "dst_qos_profile_bw_guarantee", 100 @@ -333,6 +325,20 @@ def compose_resource_endpoint( # Check endpoint optional string fields process_optional_string_field(endpoint_data, "name", endpoint_resource_value) + process_optional_string_field( + endpoint_data, "site_location", endpoint_resource_value + ) + process_optional_string_field(endpoint_data, "ce-ip", endpoint_resource_value) + process_optional_string_field( + endpoint_data, "address_ip", endpoint_resource_value + ) + process_optional_string_field( + endpoint_data, "address_prefix", endpoint_resource_value + ) + process_optional_string_field(endpoint_data, "mtu", endpoint_resource_value) + process_optional_string_field( + endpoint_data, "ipv4_lan_prefixes", endpoint_resource_value + ) process_optional_string_field(endpoint_data, "type", endpoint_resource_value) process_optional_string_field( endpoint_data, "context_uuid", endpoint_resource_value @@ -382,8 +388,8 @@ def compose_resource_endpoint( if len(sample_types) > 0: endpoint_resource_value["sample_types"] = sample_types - if "location" in endpoint_data: - endpoint_resource_value["location"] = endpoint_data["location"] + if "site_location" in endpoint_data: + endpoint_resource_value["site_location"] = endpoint_data["site_location"] if "ce-ip" in endpoint_data: endpoint_resource_value["ce-ip"] = endpoint_data["ce-ip"] diff --git a/src/device/service/drivers/ietf_l3vpn/driver.py b/src/device/service/drivers/ietf_l3vpn/driver.py index e81736d43875e4344efc804e2709103d867cc6cd..25d8f9319d5cc14b14f843c7d06a75cc59212560 100644 --- a/src/device/service/drivers/ietf_l3vpn/driver.py +++ b/src/device/service/drivers/ietf_l3vpn/driver.py @@ -63,8 +63,8 @@ METRICS_POOL = MetricsPool("Device", "Driver", labels={"driver": DRIVER_NAME}) class IetfL3VpnDriver(_Driver): - def __init__(self, address: str, port: int, **settings) -> None: - super().__init__(DRIVER_NAME, address, port, **settings) + def __init__(self, address: str, port: str, **settings) -> None: + super().__init__(DRIVER_NAME, address, int(port), **settings) self.__lock = threading.Lock() self.__started = threading.Event() self.__terminate = threading.Event() @@ -79,11 +79,12 @@ class IetfL3VpnDriver(_Driver): username=username, password=password, ) - self.__auth = ( - HTTPBasicAuth(username, password) - if username is not None and password is not None - else None - ) + self.__auth = None + # ( + # HTTPBasicAuth(username, password) + # if username is not None and password is not None + # else None + # ) self.__tfs_nbi_root = "{:s}://{:s}:{:d}".format( scheme, self.address, int(self.port) ) @@ -146,18 +147,12 @@ class IetfL3VpnDriver(_Driver): if self.__started.is_set(): return True try: - requests.get( - url, timeout=self.__timeout, verify=False, auth=self.__auth - ) + requests.get(url, timeout=self.__timeout, auth=self.__auth) except requests.exceptions.Timeout: - LOGGER.exception( - "Timeout connecting {:s}".format(str(self.__tapi_root)) - ) + LOGGER.exception("Timeout connecting {:s}".format(url)) return False except Exception: # pylint: disable=broad-except - LOGGER.exception( - "Exception connecting {:s}".format(str(self.__tapi_root)) - ) + LOGGER.exception("Exception connecting {:s}".format(url)) return False else: self.__started.set() diff --git a/src/device/tests/test_unitary_ietf_l3vpn.py b/src/device/tests/test_unitary_ietf_l3vpn.py index 8683c345451a9bf1504fae1799b4160186c47c6a..728ca691332c8abee7b5d6f5ad6c151240e540ed 100644 --- a/src/device/tests/test_unitary_ietf_l3vpn.py +++ b/src/device/tests/test_unitary_ietf_l3vpn.py @@ -165,11 +165,11 @@ def test_SetConfig(monkeypatch): assert result_SetConfig == [("/services/service[vpn_A]", True)] assert len(get_request_data) == 1 assert get_request_data[0][0] == ( - "http://1.2.3.4:0/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-service=vpn_A", + "http://1.2.3.4:0/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service=vpn_A", ) assert len(post_request_data) == 1 assert post_request_data[0][0] == ( - "http://1.2.3.4:0/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services", + "http://1.2.3.4:0/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-services", ) assert post_request_data[0][1]["json"] == { "ietf-l3vpn-svc:l3vpn-svc": { diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py index f7329cb35666f423e85f99510e5f89a82e89b7f8..3a139536556088b273aa90070b27ddeaff65fd26 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py @@ -15,7 +15,7 @@ import logging, netaddr from typing import Dict, List, Optional, Tuple from common.Constants import DEFAULT_CONTEXT_NAME -from common.proto.context_pb2 import Service, ServiceStatusEnum, ServiceTypeEnum +from common.proto.context_pb2 import Service, ServiceStatusEnum, ServiceTypeEnum, Empty from common.tools.context_queries.Service import get_service_by_uuid from common.tools.grpc.ConfigRules import update_config_rule_custom from common.tools.grpc.Constraints import ( @@ -97,8 +97,11 @@ def update_service_endpoint( endpoint_settings_key = ENDPOINT_SETTINGS_KEY.format(device_uuid, endpoint_uuid) field_updates = {} if vlan_tag is not None: field_updates['vlan_tag' ] = (vlan_tag, True) - if ipv4_address is not None: field_updates['ip_address' ] = (ipv4_address, True) - if neighbor_ipv4_address is not None: field_updates['neighbor_address'] = (neighbor_ipv4_address, True) + # if ipv4_address is not None: field_updates['ip_address' ] = (ipv4_address, True) + # if neighbor_ipv4_address is not None: field_updates['neighbor_address'] = (neighbor_ipv4_address, True) + #! neighbor_ipv4_address and ipv4_address' field swapped to manage the PE. Fix it later + if ipv4_address is not None: field_updates['ip_address' ] = (neighbor_ipv4_address, True) + if neighbor_ipv4_address is not None: field_updates['neighbor_address'] = (ipv4_address, True) if ipv4_prefix_length is not None: field_updates['prefix_length' ] = (ipv4_prefix_length, True) update_config_rule_custom(config_rules, endpoint_settings_key, field_updates) @@ -113,6 +116,8 @@ def update_service_endpoint( def process_site_network_access( site_id : str, network_access : Dict, site_static_routing : Dict[Tuple[str, str], str], errors : List[Dict] ) -> None: + # client = ContextClient() + # devices = client.ListDevices(Empty()).devices endpoint_uuid = network_access['site-network-access-id'] if network_access['site-network-access-type'] != 'ietf-l3vpn-svc:multipoint': @@ -120,6 +125,12 @@ def process_site_network_access( raise NotImplementedError(MSG.format(str(network_access['site-network-access-type']))) device_uuid = network_access['device-reference'] + + # location = network_access['location-reference'] + # for device in devices: + # for cr in device.device_config.config_rules: + # if cr.WhichOneof('config_rule') != 'custom': + # continue service_uuid = network_access['vpn-attachment']['vpn-id'] access_role : str = network_access['vpn-attachment']['site-role'] diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py index a313677c12203c1621b920f3fcb7f6ff0c281bfb..245d20861014cf552a81615b952a68a1d7af42d0 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py @@ -26,7 +26,7 @@ from ..tools.HttpStatusCodes import HTTP_GATEWAYTIMEOUT, HTTP_NOCONTENT, HTTP_OK LOGGER = logging.getLogger(__name__) class L3VPN_Service(Resource): - @HTTP_AUTH.login_required + # @HTTP_AUTH.login_required def get(self, vpn_id : str): LOGGER.debug('VPN_Id: {:s}'.format(str(vpn_id))) LOGGER.debug('Request: {:s}'.format(str(request))) @@ -52,7 +52,7 @@ class L3VPN_Service(Resource): response.status_code = HTTP_SERVERERROR return response - @HTTP_AUTH.login_required + # @HTTP_AUTH.login_required def delete(self, vpn_id : str): LOGGER.debug('VPN_Id: {:s}'.format(str(vpn_id))) LOGGER.debug('Request: {:s}'.format(str(request))) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py index 11f2d6dae2f42cb06543979dcdb4d44b4d21e8aa..dc3bb0df259becfc8e20d53c2b5d4bbd9b207051 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py @@ -26,11 +26,11 @@ from .YangValidator import YangValidator LOGGER = logging.getLogger(__name__) class L3VPN_Services(Resource): - @HTTP_AUTH.login_required + # @HTTP_AUTH.login_required def get(self): return {} - @HTTP_AUTH.login_required + # @HTTP_AUTH.login_required def post(self): if not request.is_json: raise UnsupportedMediaType('JSON payload is required') request_data : Dict = request.json diff --git a/src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py b/src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py index 7957fe76d7f3d15e075f47d91b60f7ba5d98f40d..5f18e4657681be0c050733e169a4084048a10525 100644 --- a/src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py +++ b/src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py @@ -65,9 +65,16 @@ class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler): DeviceId(**json_device_id(src_device_uuid)) ) src_endpoint_obj = get_endpoint_matching(src_device_obj, src_endpoint_uuid) - src_endpoint_settings = self.__settings_handler.get_endpoint_settings( - src_device_obj, src_endpoint_obj - ).value + for cr in src_device_obj.device_config.config_rules: + if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == f'/endpoints/endpoint[{src_endpoint_obj.name}]': + src_endpoint_settings = json.loads(cr.custom.resource_value) + break + # src_endpoint_settings = self.__settings_handler.get_endpoint_settings( + # src_device_obj, src_endpoint_obj + # ).value + + src_controller = self.__task_executor.get_device_controller(src_device_obj) + if src_controller is None: src_controller = src_device_obj dst_device_uuid, dst_endpoint_uuid = get_device_endpoint_uuids( endpoints[-1] @@ -76,12 +83,21 @@ class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler): DeviceId(**json_device_id(dst_device_uuid)) ) dst_endpoint_obj = get_endpoint_matching(dst_device_obj, dst_endpoint_uuid) - dst_endpoint_settings = self.__settings_handler.get_endpoint_settings( - dst_device_obj, dst_endpoint_obj - ).value - if dst_device_uuid != src_device_uuid: - raise Exception("Different Src-Dst devices not supported by now") + for cr in dst_device_obj.device_config.config_rules: + if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == f'/endpoints/endpoint[{dst_endpoint_obj.name}]': + dst_endpoint_settings = json.loads(cr.custom.resource_value) + break + # dst_endpoint_settings = self.__settings_handler.get_endpoint_settings( + # dst_device_obj, dst_endpoint_obj + # ).value + dst_controller = self.__task_executor.get_device_controller(dst_device_obj) + if dst_controller is None: dst_controller = dst_device_obj + + if src_controller.device_id.device_uuid.uuid != dst_controller.device_id.device_uuid.uuid: + raise Exception('Different Src-Dst devices not supported by now') + controller = src_controller + json_config_rule = json_config_rule_set( "/services/service[{:s}]".format(service_uuid), @@ -89,7 +105,7 @@ class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler): "uuid": service_uuid, "src_device_name": src_device_obj.name, "src_endpoint_name": src_endpoint_obj.name, - "src_site_location": src_endpoint_settings["location"], + "src_site_location": src_endpoint_settings["site_location"], "src_ipv4_lan_prefixes": src_endpoint_settings["ipv4_lan_prefixes"], "src_ce_address": src_endpoint_settings["ce-ip"], "src_pe_address": src_endpoint_settings["address_ip"], @@ -97,7 +113,7 @@ class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler): "src_mtu": src_endpoint_settings["mtu"], "dst_device_name": dst_device_obj.name, "dst_endpoint_name": dst_endpoint_obj.name, - "dst_site_location": dst_endpoint_settings["location"], + "dst_site_location": dst_endpoint_settings["site_location"], "dst_ipv4_lan_prefixes": dst_endpoint_settings["ipv4_lan_prefixes"], "dst_ce_address": dst_endpoint_settings["ce-ip"], "dst_pe_address": dst_endpoint_settings["address_ip"], @@ -105,11 +121,11 @@ class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler): "dst_mtu": dst_endpoint_settings["mtu"], }, ) - del src_device_obj.device_config.config_rules[:] - src_device_obj.device_config.config_rules.append( + del controller.device_config.config_rules[:] + controller.device_config.config_rules.append( ConfigRule(**json_config_rule) ) - self.__task_executor.configure_device(src_device_obj) + self.__task_executor.configure_device(controller) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception(