diff --git a/manifests/pathcompservice.yaml b/manifests/pathcompservice.yaml index 679552e2fbaf14ceb7e1a190f11adb6877efa386..d5939cb154443139be88d8e0ac23c281a3b18c4d 100644 --- a/manifests/pathcompservice.yaml +++ b/manifests/pathcompservice.yaml @@ -51,18 +51,18 @@ spec: - name: backend image: registry.gitlab.com/teraflow-h2020/controller/pathcomp-backend:latest imagePullPolicy: Always - readinessProbe: - httpGet: - path: /health - port: 8081 - initialDelaySeconds: 5 - timeoutSeconds: 5 - livenessProbe: - httpGet: - path: /health - port: 8081 - initialDelaySeconds: 5 - timeoutSeconds: 5 + #readinessProbe: + # httpGet: + # path: /health + # port: 8081 + # initialDelaySeconds: 5 + # timeoutSeconds: 5 + #livenessProbe: + # httpGet: + # path: /health + # port: 8081 + # initialDelaySeconds: 5 + # timeoutSeconds: 5 resources: requests: cpu: 250m diff --git a/scripts/show_logs_pathcomp_backend.sh b/scripts/show_logs_pathcomp_backend.sh new file mode 100755 index 0000000000000000000000000000000000000000..cee99ee4bd19de9b7cd4e45eb651e809397ccaeb --- /dev/null +++ b/scripts/show_logs_pathcomp_backend.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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. + +######################################################################################################################## +# Define your deployment settings here +######################################################################################################################## + +# If not already set, set the name of the Kubernetes namespace to deploy to. +export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"} + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + +kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c backend diff --git a/scripts/show_logs_pathcomp_frontend.sh b/scripts/show_logs_pathcomp_frontend.sh new file mode 100755 index 0000000000000000000000000000000000000000..32f92b59d53b5804e9f1a0b145576667cfa21131 --- /dev/null +++ b/scripts/show_logs_pathcomp_frontend.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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. + +######################################################################################################################## +# Define your deployment settings here +######################################################################################################################## + +# If not already set, set the name of the Kubernetes namespace to deploy to. +export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"} + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + +kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend diff --git a/src/common/DeviceTypes.py b/src/common/DeviceTypes.py index 8554ea3cf97f33cc71f60e37310798cc335234a0..4d67ff6615227f0d9e7d82e2f69b39d72011a75c 100644 --- a/src/common/DeviceTypes.py +++ b/src/common/DeviceTypes.py @@ -15,14 +15,14 @@ from enum import Enum class DeviceTypeEnum(Enum): - EMULATED_DATACENTER = 'emu-datacenter' - EMULATED_OPTICAL_LINE_SYSTEM = 'emu-optical-line-system' - EMULATED_PACKET_ROUTER = 'emu-packet-router' - DATACENTER = 'datacenter' - MICROVAWE_RADIO_SYSTEM = 'microwave-radio-system' - OPTICAL_ROADM = 'optical-roadm' - OPTICAL_TRANDPONDER = 'optical-trandponder' - OPTICAL_LINE_SYSTEM = 'optical-line-system' - PACKET_ROUTER = 'packet-router' - PACKET_SWITCH = 'packet-switch' - P4_SWITCH = 'p4-switch' + EMULATED_DATACENTER = 'emu-datacenter' + EMULATED_OPEN_LINE_SYSTEM = 'emu-open-line-system' + EMULATED_PACKET_ROUTER = 'emu-packet-router' + DATACENTER = 'datacenter' + MICROVAWE_RADIO_SYSTEM = 'microwave-radio-system' + OPTICAL_ROADM = 'optical-roadm' + OPTICAL_TRANDPONDER = 'optical-trandponder' + OPEN_LINE_SYSTEM = 'open-line-system' + PACKET_ROUTER = 'packet-router' + PACKET_SWITCH = 'packet-switch' + P4_SWITCH = 'p4-switch' diff --git a/src/common/tools/object_factory/Constraint.py b/src/common/tools/object_factory/Constraint.py index df290d4285330f1965608d710d9d48ca49131521..757531daf65b60c5f5b6c90ee67ef00488f91590 100644 --- a/src/common/tools/object_factory/Constraint.py +++ b/src/common/tools/object_factory/Constraint.py @@ -15,6 +15,19 @@ import json from typing import Any, Dict, Union -def json_constraint(constraint_type : str, constraint_value : Union[str, Dict[str, Any]]): +def json_constraint_custom(constraint_type : str, constraint_value : Union[str, Dict[str, Any]]) -> Dict: if not isinstance(constraint_value, str): constraint_value = json.dumps(constraint_value, sort_keys=True) return {'custom': {'constraint_type': constraint_type, 'constraint_value': constraint_value}} + +def json_constraint_endpoint_location_region(endpoint_id : Dict, region : str) -> Dict: + return {'endpoint_location': {'endpoint_id': endpoint_id, 'location': {'region': region}}} + +def json_constraint_endpoint_location_gps(endpoint_id : Dict, latitude : float, longitude : float) -> Dict: + gps_position = {'latitude': latitude, 'longitude': longitude} + return {'endpoint_location': {'endpoint_id': endpoint_id, 'location': {'gps_position': gps_position}}} + +def json_constraint_endpoint_priority(endpoint_id : Dict, priority : int) -> Dict: + return {'endpoint_priority': {'endpoint_id': endpoint_id, 'priority': priority}} + +def json_constraint_sla_availability(num_disjoint_paths : int, all_active : bool) -> Dict: + return {'sla_availability': {'num_disjoint_paths': num_disjoint_paths, 'all_active': all_active}} diff --git a/src/common/tools/object_factory/Device.py b/src/common/tools/object_factory/Device.py index d69272346be6b2c1823c33f291a06410c3c9ec33..4a590134dd7b455c92b62fc5e4aa9fece0f874b4 100644 --- a/src/common/tools/object_factory/Device.py +++ b/src/common/tools/object_factory/Device.py @@ -21,7 +21,7 @@ from common.tools.object_factory.ConfigRule import json_config_rule_set DEVICE_DISABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED DEVICE_EMUDC_TYPE = DeviceTypeEnum.EMULATED_DATACENTER.value -DEVICE_EMUOLS_TYPE = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value +DEVICE_EMUOLS_TYPE = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value DEVICE_EMUPR_TYPE = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value DEVICE_EMU_DRIVERS = [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED] DEVICE_EMU_ADDRESS = '127.0.0.1' @@ -30,7 +30,7 @@ DEVICE_EMU_PORT = '0' DEVICE_PR_TYPE = DeviceTypeEnum.PACKET_ROUTER.value DEVICE_PR_DRIVERS = [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG] -DEVICE_TAPI_TYPE = DeviceTypeEnum.OPTICAL_LINE_SYSTEM.value +DEVICE_TAPI_TYPE = DeviceTypeEnum.OPEN_LINE_SYSTEM.value DEVICE_TAPI_DRIVERS = [DeviceDriverEnum.DEVICEDRIVER_TRANSPORT_API] # check which enum type and value assign to microwave device diff --git a/src/context/service/database/ConstraintModel.py b/src/context/service/database/ConstraintModel.py index a35ec250d8a62a8a2534e9f27ddecac801db6eff..17a9b52e980bf0eec44ea58edfb35eac5471d016 100644 --- a/src/context/service/database/ConstraintModel.py +++ b/src/context/service/database/ConstraintModel.py @@ -54,24 +54,13 @@ class ConstraintCustomModel(Model): # pylint: disable=abstract-method def dump(self) -> Dict: # pylint: disable=arguments-differ return {'custom': {'constraint_type': self.constraint_type, 'constraint_value': self.constraint_value}} -Union_ConstraintEndpoint = Union[ - 'ConstraintEndpointLocationGpsPositionModel', 'ConstraintEndpointLocationRegionModel', - 'ConstraintEndpointPriorityModel' -] -def dump_endpoint_id(endpoint_constraint : Union_ConstraintEndpoint): - db_endpoints_pks = list(endpoint_constraint.references(EndPointModel)) - num_endpoints = len(db_endpoints_pks) - if num_endpoints != 1: - raise Exception('Wrong number({:d}) of associated Endpoints with constraint'.format(num_endpoints)) - db_endpoint = EndPointModel(endpoint_constraint.database, db_endpoints_pks[0]) - return db_endpoint.dump_id() - class ConstraintEndpointLocationRegionModel(Model): # pylint: disable=abstract-method endpoint_fk = ForeignKeyField(EndPointModel) region = StringField(required=True, allow_empty=False) def dump(self) -> Dict: # pylint: disable=arguments-differ - return {'endpoint_location': {'endpoint_id': dump_endpoint_id(self), 'region': self.region}} + json_endpoint_id = EndPointModel(self.database, self.endpoint_fk).dump_id() + return {'endpoint_location': {'endpoint_id': json_endpoint_id, 'location': {'region': self.region}}} class ConstraintEndpointLocationGpsPositionModel(Model): # pylint: disable=abstract-method endpoint_fk = ForeignKeyField(EndPointModel) @@ -80,14 +69,16 @@ class ConstraintEndpointLocationGpsPositionModel(Model): # pylint: disable=abstr def dump(self) -> Dict: # pylint: disable=arguments-differ gps_position = {'latitude': self.latitude, 'longitude': self.longitude} - return {'endpoint_location': {'endpoint_id': dump_endpoint_id(self), 'gps_position': gps_position}} + json_endpoint_id = EndPointModel(self.database, self.endpoint_fk).dump_id() + return {'endpoint_location': {'endpoint_id': json_endpoint_id, 'location': {'gps_position': gps_position}}} class ConstraintEndpointPriorityModel(Model): # pylint: disable=abstract-method endpoint_fk = ForeignKeyField(EndPointModel) - priority = FloatField(required=True) + priority = IntegerField(required=True, min_value=0) def dump(self) -> Dict: # pylint: disable=arguments-differ - return {'endpoint_priority': {'endpoint_id': dump_endpoint_id(self), 'priority': self.priority}} + json_endpoint_id = EndPointModel(self.database, self.endpoint_fk).dump_id() + return {'endpoint_priority': {'endpoint_id': json_endpoint_id, 'priority': self.priority}} class ConstraintSlaAvailabilityModel(Model): # pylint: disable=abstract-method num_disjoint_paths = IntegerField(required=True, min_value=1) diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py index 4c8f957ecb70765cbd36032fca7bfacc27f9b5ae..d21868d3d5faaa945c9a4d8c5a8f5b336cdafae7 100644 --- a/src/context/service/grpc_server/ContextServiceServicerImpl.py +++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py @@ -319,7 +319,7 @@ class ContextServiceServicerImpl(ContextServiceServicer): result : Tuple[EndPointModel, bool] = update_or_create_object( self.database, EndPointModel, str_endpoint_key, endpoint_attributes) - db_endpoint, endpoint_updated = result + db_endpoint, endpoint_updated = result # pylint: disable=unused-variable set_kpi_sample_types(self.database, db_endpoint, endpoint.kpi_sample_types) diff --git a/src/context/tests/Objects.py b/src/context/tests/Objects.py index 519a0093ac2733125487ed9daf0c61e0821910d5..140cbff686eaf5b430f23ee987a9335ecb04c0f5 100644 --- a/src/context/tests/Objects.py +++ b/src/context/tests/Objects.py @@ -16,7 +16,7 @@ from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID from common.proto.kpi_sample_types_pb2 import KpiSampleType from common.tools.object_factory.ConfigRule import json_config_rule_set from common.tools.object_factory.Connection import json_connection, json_connection_id -from common.tools.object_factory.Constraint import json_constraint +from common.tools.object_factory.Constraint import json_constraint_custom from common.tools.object_factory.Context import json_context, json_context_id from common.tools.object_factory.Device import json_device_id, json_device_packetrouter_disabled from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id @@ -129,8 +129,8 @@ SERVICE_R1_R2_EPIDS = [ json_endpoint_id(DEVICE_R2_ID, 'EP100', topology_id=TOPOLOGY_ID), ] SERVICE_R1_R2_CONST = [ - json_constraint('latency_ms', '15.2'), - json_constraint('jitter_us', '1.2'), + json_constraint_custom('latency[ms]', '15.2'), + json_constraint_custom('jitter[us]', '1.2'), ] SERVICE_R1_R2_RULES = [ json_config_rule_set('svc/rsrc1/value', 'value7'), @@ -149,8 +149,8 @@ SERVICE_R1_R3_EPIDS = [ json_endpoint_id(DEVICE_R3_ID, 'EP100', topology_id=TOPOLOGY_ID), ] SERVICE_R1_R3_CONST = [ - json_constraint('latency_ms', '5.8'), - json_constraint('jitter_us', '0.1'), + json_constraint_custom('latency[ms]', '5.8'), + json_constraint_custom('jitter[us]', '0.1'), ] SERVICE_R1_R3_RULES = [ json_config_rule_set('svc/rsrc1/value', 'value7'), @@ -169,8 +169,8 @@ SERVICE_R2_R3_EPIDS = [ json_endpoint_id(DEVICE_R3_ID, 'EP100', topology_id=TOPOLOGY_ID), ] SERVICE_R2_R3_CONST = [ - json_constraint('latency_ms', '23.1'), - json_constraint('jitter_us', '3.4'), + json_constraint_custom('latency[ms]', '23.1'), + json_constraint_custom('jitter[us]', '3.4'), ] SERVICE_R2_R3_RULES = [ json_config_rule_set('svc/rsrc1/value', 'value7'), diff --git a/src/device/service/database/ContextModel.py b/src/device/service/database/ContextModel.py index 0ca13269c52d02ea663e10be986ab28d12d8f144..a609e1ba9189f5359064e6628cba6c08d353770e 100644 --- a/src/device/service/database/ContextModel.py +++ b/src/device/service/database/ContextModel.py @@ -24,15 +24,15 @@ class ContextModel(Model): pk = PrimaryKeyField() context_uuid = StringField(required=True, allow_empty=False) -# def dump_id(self) -> Dict: -# return {'context_uuid': {'uuid': self.context_uuid}} + def dump_id(self) -> Dict: + return {'context_uuid': {'uuid': self.context_uuid}} -# def dump_topology_ids(self) -> List[Dict]: -# from .TopologyModel import TopologyModel # pylint: disable=import-outside-toplevel -# db_topology_pks = self.references(TopologyModel) -# return [TopologyModel(self.database, pk).dump_id() for pk,_ in db_topology_pks] + def dump_topology_ids(self) -> List[Dict]: + from .TopologyModel import TopologyModel # pylint: disable=import-outside-toplevel + db_topology_pks = self.references(TopologyModel) + return [TopologyModel(self.database, pk).dump_id() for pk,_ in db_topology_pks] -# def dump(self, include_topologies=True) -> Dict: # pylint: disable=arguments-differ -# result = {'context_id': self.dump_id()} -# if include_topologies: result['topology_ids'] = self.dump_topology_ids() -# return result + def dump(self, include_topologies=False) -> Dict: # pylint: disable=arguments-differ + result = {'context_id': self.dump_id()} + if include_topologies: result['topology_ids'] = self.dump_topology_ids() + return result diff --git a/src/device/service/database/TopologyModel.py b/src/device/service/database/TopologyModel.py index a099c8adfd8bb64d94c8326c90094f39d7fe9b6b..f9e9c0b1a26fdf8faca7e1cbe0a64b582bdd4d5d 100644 --- a/src/device/service/database/TopologyModel.py +++ b/src/device/service/database/TopologyModel.py @@ -27,13 +27,13 @@ class TopologyModel(Model): context_fk = ForeignKeyField(ContextModel) topology_uuid = StringField(required=True, allow_empty=False) -# def dump_id(self) -> Dict: -# context_id = ContextModel(self.database, self.context_fk).dump_id() -# return { -# 'context_id': context_id, -# 'topology_uuid': {'uuid': self.topology_uuid}, -# } + def dump_id(self) -> Dict: + context_id = ContextModel(self.database, self.context_fk).dump_id() + return { + 'context_id': context_id, + 'topology_uuid': {'uuid': self.topology_uuid}, + } -# def dump(self) -> Dict: -# result = {'topology_id': self.dump_id()} -# return result + def dump(self) -> Dict: + result = {'topology_id': self.dump_id()} + return result diff --git a/src/device/service/drivers/__init__.py b/src/device/service/drivers/__init__.py index 40912f50b98f1d5fc9555d87a4855a12ab8e0c07..6188a385da391af74272eee3be1e467c15f97702 100644 --- a/src/device/service/drivers/__init__.py +++ b/src/device/service/drivers/__init__.py @@ -29,7 +29,7 @@ DRIVERS = [ { # Emulated OLS/Packet Router, specifying Undefined/OpenConfig/TAPI Driver => use EmulatedDriver FilterFieldEnum.DEVICE_TYPE: [ - DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM, + DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM, DeviceTypeEnum.EMULATED_PACKET_ROUTER, ], FilterFieldEnum.DRIVER : [ @@ -49,7 +49,7 @@ DRIVERS = [ (TransportApiDriver, [ { # Real OLS, specifying TAPI Driver => use TransportApiDriver - FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.OPTICAL_LINE_SYSTEM, + FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.OPEN_LINE_SYSTEM, FilterFieldEnum.DRIVER : ORM_DeviceDriverEnum.TRANSPORT_API, } ]), diff --git a/src/pathcomp/backend/Dockerfile b/src/pathcomp/backend/Dockerfile index 128085f902df61acad7493ae6c085031a7aac568..b351d4715d99ee8a9b518a0cfc827c17cf2bba49 100644 --- a/src/pathcomp/backend/Dockerfile +++ b/src/pathcomp/backend/Dockerfile @@ -45,11 +45,11 @@ EXPOSE 8081 # builder defines coverage version of pathcomp by default # coverage entrypoint: -ENTRYPOINT [ "./pathComp-cvr", "config/pathcomp.conf", "pathcomp.log" ] +ENTRYPOINT [ "./pathComp-cvr", "config/pathcomp.conf", "screen_only" ] # debug entrypoint: -#ENTRYPOINT [ "./pathComp-dbg", "config/pathcomp.conf", "pathcomp.log" ] +#ENTRYPOINT [ "./pathComp-dbg", "config/pathcomp.conf", "screen_only" ] # debug entrypoint with memory tracking: -#ENTRYPOINT [ "valgrind", "--leak-check=full", "--show-leak-kinds=all", "--track-origins=yes", "--show-error-list=yes", "./pathComp-dbg", "config/pathcomp.conf", "pathcomp.log" ] +#ENTRYPOINT [ "valgrind", "--leak-check=full", "--show-leak-kinds=all", "--track-origins=yes", "--show-error-list=yes", "./pathComp-dbg", "config/pathcomp.conf", "screen_only" ] # Stage 2 diff --git a/src/pathcomp/frontend/Config.py b/src/pathcomp/frontend/Config.py index 75f910e36f92ca008b318cfc61718ae81f94214c..f59ca45035ab0efecdf4297467626df18b74fa4d 100644 --- a/src/pathcomp/frontend/Config.py +++ b/src/pathcomp/frontend/Config.py @@ -16,13 +16,23 @@ import os DEFAULT_PATHCOMP_BACKEND_SCHEME = 'http' DEFAULT_PATHCOMP_BACKEND_HOST = '127.0.0.1' -DEFAULT_PATHCOMP_BACKEND_PORT = 8081 +DEFAULT_PATHCOMP_BACKEND_PORT = '8081' DEFAULT_PATHCOMP_BACKEND_BASEURL = '/pathComp/api/v1/compRoute' PATHCOMP_BACKEND_SCHEME = str(os.environ.get('PATHCOMP_BACKEND_SCHEME', DEFAULT_PATHCOMP_BACKEND_SCHEME )) -PATHCOMP_BACKEND_HOST = str(os.environ.get('PATHCOMP_BACKEND_HOST', DEFAULT_PATHCOMP_BACKEND_HOST )) -PATHCOMP_BACKEND_PORT = int(os.environ.get('PATHCOMP_BACKEND_PORT', DEFAULT_PATHCOMP_BACKEND_PORT )) PATHCOMP_BACKEND_BASEURL = str(os.environ.get('PATHCOMP_BACKEND_BASEURL', DEFAULT_PATHCOMP_BACKEND_BASEURL)) +# Find IP:port of backend container as follows: +# - first check env vars PATHCOMP_BACKEND_HOST & PATHCOMP_BACKEND_PORT +# - if not set, check env vars PATHCOMPSERVICE_SERVICE_HOST & PATHCOMPSERVICE_SERVICE_PORT_HTTP +# - if not set, use DEFAULT_PATHCOMP_BACKEND_HOST & DEFAULT_PATHCOMP_BACKEND_PORT +backend_host = DEFAULT_PATHCOMP_BACKEND_HOST +backend_host = os.environ.get('PATHCOMPSERVICE_SERVICE_HOST', backend_host) +PATHCOMP_BACKEND_HOST = str(os.environ.get('PATHCOMP_BACKEND_HOST', backend_host)) + +backend_port = DEFAULT_PATHCOMP_BACKEND_PORT +backend_port = os.environ.get('PATHCOMPSERVICE_SERVICE_PORT_HTTP', backend_port) +PATHCOMP_BACKEND_PORT = int(os.environ.get('PATHCOMP_BACKEND_PORT', backend_port)) + BACKEND_URL = '{:s}://{:s}:{:d}{:s}'.format( PATHCOMP_BACKEND_SCHEME, PATHCOMP_BACKEND_HOST, PATHCOMP_BACKEND_PORT, PATHCOMP_BACKEND_BASEURL) diff --git a/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py b/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py index 1e676b0aec93d083217bd53ca8e078b00ddf8376..48e951b1dbe01790e1ec44d2759c6079d52d0aab 100644 --- a/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py +++ b/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py @@ -12,17 +12,73 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy +import operator from typing import Dict, List, Optional, Set, Tuple from common.proto.context_pb2 import Link -from common.proto.pathcomp_pb2 import Algorithm_KDisjointPath, Algorithm_KShortestPath, PathCompReply +from common.proto.pathcomp_pb2 import Algorithm_KDisjointPath, Algorithm_KShortestPath, PathCompReply, PathCompRequest +from common.tools.grpc.Tools import grpc_message_to_json_string from ._Algorithm import _Algorithm from .KShortestPathAlgorithm import KShortestPathAlgorithm +Service_Id = Tuple[str, str] # (context_uuid, service_uuid) +Service_Constraints = Dict[str, str] # {constraint_type => constraint_value} +Endpoint_Id = Tuple[str, str] # (device_uuid, endpoint_uuid) +Endpoint_Details = Tuple[str, int] # (site_id, priority) +Service_Endpoints = Dict[Endpoint_Id, Endpoint_Details] +Service_Details = Tuple[int, Service_Constraints, Service_Endpoints] +Services_Details = Dict[Service_Id, Service_Details] + +CUSTOM_CONSTRAINTS = {'bandwidth[gbps]', 'latency[ms]', 'jitter[us]'} + +DUMP_EXECUTION_STEPS = False + class KDisjointPathAlgorithm(_Algorithm): def __init__(self, algorithm : Algorithm_KDisjointPath, class_name=__name__) -> None: super().__init__('KDP', False, class_name=class_name) self.num_disjoint = algorithm.num_disjoint + self.services_details : Services_Details = dict() + + def add_service_requests(self, request: PathCompRequest) -> None: + super().add_service_requests(request) + for service in request.services: + service_id = service.service_id + context_uuid = service_id.context_id.context_uuid.uuid + service_uuid = service_id.service_uuid.uuid + service_key = (context_uuid, service_uuid) + + constraints = dict() + endpoints = dict() + service_details = (int(service.service_type), constraints, endpoints) + self.services_details.setdefault(service_key, service_details) + + for constraint in service.service_constraints: + if constraint.WhichOneof('constraint') == 'custom': + constraint_type = constraint.custom.constraint_type + if constraint_type not in CUSTOM_CONSTRAINTS: continue + constraint_value = constraint.custom.constraint_value + constraints[constraint_type] = constraint_value + + if constraint.WhichOneof('constraint') == 'endpoint_location': + endpoint_id = constraint.endpoint_location.endpoint_id + device_uuid = endpoint_id.device_id.device_uuid.uuid + endpoint_uuid = endpoint_id.endpoint_uuid.uuid + location_kind = constraint.endpoint_location.location.WhichOneof('location') + if location_kind != 'region': + MSG = 'Unsupported LocationType({:s}) in Constraint({:s})' + raise Exception(MSG.format(location_kind, grpc_message_to_json_string(constraint))) + site_id = constraint.endpoint_location.location.region + endpoints.setdefault((device_uuid, endpoint_uuid), dict())['site_id'] = site_id + + if constraint.WhichOneof('constraint') == 'endpoint_priority': + endpoint_id = constraint.endpoint_priority.endpoint_id + device_uuid = endpoint_id.device_id.device_uuid.uuid + endpoint_uuid = endpoint_id.endpoint_uuid.uuid + priority = constraint.endpoint_priority.priority + endpoints.setdefault((device_uuid, endpoint_uuid), dict())['priority'] = priority + + # TODO: ensure these constraints are provided in the request + if 'bandwidth[gbps]' not in constraints: constraints['bandwidth[gbps]'] = '20.0' + if 'latency[ms]' not in constraints: constraints['latency[ms]'] = '20.0' def get_link_from_endpoint(self, endpoint : Dict) -> Tuple[Dict, Link]: device_uuid = endpoint['device_id'] @@ -50,8 +106,8 @@ class KDisjointPathAlgorithm(_Algorithm): def remove_traversed_links(self, link_list : List[Dict], path_endpoints : List[Dict]): _, path_link_ids = self.path_to_links(path_endpoints) new_link_list = list(filter(lambda l: l['link_Id'] not in path_link_ids, link_list)) - self.logger.info('cur_link_list = {:s}'.format(str(link_list))) - self.logger.info('new_link_list = {:s}'.format(str(new_link_list))) + #self.logger.info('cur_link_list = {:s}'.format(str(link_list))) + #self.logger.info('new_link_list = {:s}'.format(str(new_link_list))) return new_link_list def execute(self, dump_request_filename: Optional[str] = None, dump_reply_filename: Optional[str] = None) -> None: @@ -63,18 +119,52 @@ class KDisjointPathAlgorithm(_Algorithm): algorithm.link_list = self.link_list algorithm.link_dict = self.link_dict algorithm.endpoint_to_link_dict = self.endpoint_to_link_dict - algorithm.service_list = self.service_list - algorithm.service_dict = self.service_dict Path = List[Dict] Path_NoPath = Optional[Path] # None = no path, list = path self.json_reply : Dict[Tuple[str, str], List[Path_NoPath]] = dict() for num_path in range(self.num_disjoint): - #dump_request_filename = 'ksp-{:d}-request.json'.format(num_path) - #dump_reply_filename = 'ksp-{:d}-reply.txt'.format(num_path) - #algorithm.execute(dump_request_filename, dump_reply_filename) - algorithm.execute() + algorithm.service_list = list() + algorithm.service_dict = dict() + + #self.logger.warning('services_details = {:s}'.format(str(self.services_details))) + + _request = PathCompRequest() + for service_key, service_details in self.services_details.items(): + service_type, constraints, endpoints = service_details + _service = _request.services.add() + _service.service_id.context_id.context_uuid.uuid = service_key[0] + _service.service_id.service_uuid.uuid = service_key[1] + _service.service_type = service_type + for constraint_type, constraint_value in constraints.items(): + constraint = _service.service_constraints.add() + constraint.custom.constraint_type = constraint_type + constraint.custom.constraint_value = constraint_value + + site_to_endpoints : Dict[str, List[Tuple[Endpoint_Id, int]]] = {} + for endpoint_key,endpoint_details in endpoints.items(): + site_id = endpoint_details.get('site_id') + if site_id is None: continue + priority = endpoint_details.get('priority', 999) + site_to_endpoints.setdefault(site_id, list()).append((endpoint_key, priority)) + + for site_id,site_endpoints in site_to_endpoints.items(): + pending_endpoints = sorted(site_endpoints, key=operator.itemgetter(1)) + if len(pending_endpoints) == 0: continue + endpoint_key, _ = pending_endpoints[0] + device_uuid, endpoint_uuid = endpoint_key + endpoint_id = _service.service_endpoint_ids.add() + endpoint_id.device_id.device_uuid.uuid = device_uuid + endpoint_id.endpoint_uuid.uuid = endpoint_uuid + endpoints.pop(endpoint_key) + + algorithm.add_service_requests(_request) + + dump_request_filename = 'ksp-{:d}-request.json'.format(num_path) if DUMP_EXECUTION_STEPS else None + dump_reply_filename = 'ksp-{:d}-reply.txt'.format(num_path) if DUMP_EXECUTION_STEPS else None + algorithm.execute(dump_request_filename, dump_reply_filename) + response_list = algorithm.json_reply.get('response-list', []) for response in response_list: service_id = response['serviceId'] @@ -90,7 +180,7 @@ class KDisjointPathAlgorithm(_Algorithm): json_reply_service.append(path_endpoints) algorithm.link_list = self.remove_traversed_links(algorithm.link_list, path_endpoints) - self.logger.info('self.json_reply = {:s}'.format(str(self.json_reply))) + self.logger.debug('self.json_reply = {:s}'.format(str(self.json_reply))) def get_reply(self) -> PathCompReply: reply = PathCompReply() diff --git a/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py b/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py index 944a2d168e47f5329b4afd6103540ba76a0c5d01..d5f937fd207807ba650669ea9fb2395b2e21b164 100644 --- a/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py +++ b/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py @@ -18,11 +18,9 @@ from ._Algorithm import _Algorithm class ShortestPathAlgorithm(_Algorithm): def __init__(self, algorithm : Algorithm_ShortestPath, class_name=__name__) -> None: super().__init__('SP', False, class_name=class_name) - self.k_paths = 1 def add_service_requests(self, requested_services) -> None: super().add_service_requests(requested_services) for service_request in self.service_list: service_request['algId' ] = self.algorithm_id service_request['syncPaths'] = self.sync_paths - service_request['kPaths' ] = self.k_paths diff --git a/src/pathcomp/frontend/service/algorithms/_Algorithm.py b/src/pathcomp/frontend/service/algorithms/_Algorithm.py index d4973f168dd7bce9fb830600c2d010fc238f3b48..f90c1f18bae5e5d63cba5d8dd0785d8ba5f12d71 100644 --- a/src/pathcomp/frontend/service/algorithms/_Algorithm.py +++ b/src/pathcomp/frontend/service/algorithms/_Algorithm.py @@ -85,20 +85,21 @@ class _Algorithm: def execute(self, dump_request_filename : Optional[str] = None, dump_reply_filename : Optional[str] = None) -> None: request = {'serviceList': self.service_list, 'deviceList': self.device_list, 'linkList': self.link_list} + self.logger.debug('[execute] request={:s}'.format(str(request))) if dump_request_filename is not None: with open(dump_request_filename, 'w', encoding='UTF-8') as f: f.write(json.dumps(request, sort_keys=True, indent=4)) + self.logger.debug('[execute] BACKEND_URL: {:s}'.format(str(BACKEND_URL))) reply = requests.post(BACKEND_URL, json=request) self.status_code = reply.status_code self.raw_reply = reply.content.decode('UTF-8') + self.logger.debug('[execute] status_code={:s} reply={:s}'.format(str(reply.status_code), str(self.raw_reply))) if dump_reply_filename is not None: with open(dump_reply_filename, 'w', encoding='UTF-8') as f: f.write('status_code={:s} reply={:s}'.format(str(self.status_code), str(self.raw_reply))) - self.logger.info('status_code={:s} reply={:s}'.format(str(reply.status_code), str(self.raw_reply))) - if reply.status_code not in {requests.codes.ok}: raise Exception('Backend error({:s}) for request({:s})'.format( str(self.raw_reply), json.dumps(request, sort_keys=True))) @@ -125,8 +126,9 @@ class _Algorithm: _, grpc_service = tuple_service # TODO: implement support for multi-point services - service_endpoint_ids = grpc_service.service_endpoint_ids - if len(service_endpoint_ids) != 2: raise NotImplementedError('Service must have 2 endpoints') + # Control deactivated to enable disjoint paths with multiple redundant endpoints on each side + #service_endpoint_ids = grpc_service.service_endpoint_ids + #if len(service_endpoint_ids) != 2: raise NotImplementedError('Service must have 2 endpoints') service = reply.services.add() service.CopyFrom(grpc_service) diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py index 706906b36d02d3ac5d8bcf05f4ae8d2e1243a561..d24597c6beac4d4a27c7cb141c3349b862076f20 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py @@ -12,18 +12,29 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging from typing import Dict +from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID from common.proto.context_pb2 import Constraint, Device, EndPointId, Link, Service, ServiceId, TopologyId from common.tools.grpc.Tools import grpc_message_to_json_string from .Constants import CapacityUnit, LinkForwardingDirection, LinkPortDirection, TerminationDirection, TerminationState +LOGGER = logging.getLogger(__name__) + def compose_topology_id(topology_id : TopologyId) -> Dict: context_uuid = topology_id.context_id.context_uuid.uuid topology_uuid = topology_id.topology_uuid.uuid + + if len(context_uuid) == 0: context_uuid = DEFAULT_CONTEXT_UUID + if len(topology_uuid) == 0: topology_uuid = DEFAULT_TOPOLOGY_UUID + return {'contextId': context_uuid, 'topology_uuid': topology_uuid} def compose_service_id(service_id : ServiceId) -> Dict: context_uuid = service_id.context_id.context_uuid.uuid + + if len(context_uuid) == 0: context_uuid = DEFAULT_CONTEXT_UUID + service_uuid = service_id.service_uuid.uuid return {'contextId': context_uuid, 'service_uuid': service_uuid} @@ -54,9 +65,9 @@ def compose_latency_characteristics(fixed_latency_characteristic : str) -> Dict: def compose_constraint(constraint : Constraint) -> Dict: if constraint.WhichOneof('constraint') != 'custom': - MSG = 'Constraint({:s}) not supported' str_constraint = grpc_message_to_json_string(constraint) - raise NotImplementedError(MSG.format(str_constraint)) + LOGGER.warning('Ignoring unsupported Constraint({:s})'.format(str_constraint)) + return None constraint_type = constraint.custom.constraint_type constraint_value = constraint.custom.constraint_value return {'constraint_type': constraint_type, 'constraint_value': constraint_value} @@ -110,10 +121,10 @@ def compose_service(grpc_service : Service) -> Dict: for service_endpoint_id in grpc_service.service_endpoint_ids ] - constraints = [ + constraints = list(filter(lambda constraint: constraint is not None, [ compose_constraint(service_constraint) for service_constraint in grpc_service.service_constraints - ] + ])) return { 'serviceId': service_id, diff --git a/src/pathcomp/frontend/tests/Objects_A_B_C.py b/src/pathcomp/frontend/tests/Objects_A_B_C.py index 586911180bcb7379382b644cac1eb338a31bd522..510ebb6746ccb8d050d5eb6ea91ec6354f224459 100644 --- a/src/pathcomp/frontend/tests/Objects_A_B_C.py +++ b/src/pathcomp/frontend/tests/Objects_A_B_C.py @@ -13,7 +13,7 @@ # limitations under the License. from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID -from common.tools.object_factory.Constraint import json_constraint +from common.tools.object_factory.Constraint import json_constraint_custom from common.tools.object_factory.Context import json_context, json_context_id from common.tools.object_factory.Device import json_device_emulated_packet_router_disabled, json_device_id from common.tools.object_factory.EndPoint import json_endpoints @@ -97,8 +97,8 @@ LINK_C2_C3_ID, LINK_C2_C3 = compose_link(DEVICE_C2_ENDPOINTS[1], DEVICE_C3_ENDPO # ----- Service -------------------------------------------------------------------------------------------------------- SERVICE_A1_B1 = compose_service(DEVICE_A1_ENDPOINTS[2], DEVICE_B1_ENDPOINTS[2], constraints=[ - json_constraint('bandwidth[gbps]', 10.0), - json_constraint('latency[ms]', 12.0), + json_constraint_custom('bandwidth[gbps]', 10.0), + json_constraint_custom('latency[ms]', 12.0), ]) # ----- Containers ----------------------------------------------------------------------------------------------------- diff --git a/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py index edb468455ba4edf5ea63a545f2b1c78d0c2cad94..d40d76454078177fd5b61455d0445859512463f4 100644 --- a/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py +++ b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py @@ -13,19 +13,36 @@ # limitations under the License. from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID -from common.tools.object_factory.Constraint import json_constraint +from common.tools.object_factory.Constraint import json_constraint_custom from common.tools.object_factory.Context import json_context, json_context_id -from common.tools.object_factory.Device import json_device_emulated_packet_router_disabled, json_device_id +from common.tools.object_factory.Device import ( + json_device_emulated_connect_rules, json_device_emulated_datacenter_disabled, + json_device_emulated_packet_router_disabled, json_device_id) from common.tools.object_factory.EndPoint import json_endpoints from common.tools.object_factory.Link import get_link_uuid, json_link, json_link_id from common.tools.object_factory.Service import get_service_uuid, json_service_l3nm_planned from common.tools.object_factory.Topology import json_topology, json_topology_id -def compose_device(device_uuid, endpoint_uuids, topology_id=None): +# if true, Device component is present and will infeer the endpoints from connect-rules +# if false, Device component is not present and device objects must contain preconfigured endpoints +ADD_CONNECT_RULES_TO_DEVICES = False + +def compose_router(device_uuid, endpoint_uuids, topology_id=None): + device_id = json_device_id(device_uuid) + r_endpoints = [(endpoint_uuid, 'copper', []) for endpoint_uuid in endpoint_uuids] + config_rules = json_device_emulated_connect_rules(r_endpoints) if ADD_CONNECT_RULES_TO_DEVICES else [] + endpoints = json_endpoints(device_id, r_endpoints, topology_id=topology_id) + j_endpoints = [] if ADD_CONNECT_RULES_TO_DEVICES else endpoints + device = json_device_emulated_packet_router_disabled(device_uuid, config_rules=config_rules, endpoints=j_endpoints) + return device_id, endpoints, device + +def compose_datacenter(device_uuid, endpoint_uuids, topology_id=None): device_id = json_device_id(device_uuid) - endpoints = [(endpoint_uuid, 'copper', []) for endpoint_uuid in endpoint_uuids] - endpoints = json_endpoints(device_id, endpoints, topology_id=topology_id) - device = json_device_emulated_packet_router_disabled(device_uuid, endpoints=endpoints) + r_endpoints = [(endpoint_uuid, 'copper', []) for endpoint_uuid in endpoint_uuids] + config_rules = json_device_emulated_connect_rules(r_endpoints) if ADD_CONNECT_RULES_TO_DEVICES else [] + endpoints = json_endpoints(device_id, r_endpoints, topology_id=topology_id) + j_endpoints = [] if ADD_CONNECT_RULES_TO_DEVICES else endpoints + device = json_device_emulated_datacenter_disabled(device_uuid, config_rules=config_rules, endpoints=j_endpoints) return device_id, endpoints, device def compose_link(endpoint_a, endpoint_z): @@ -78,20 +95,20 @@ TOPO_TN = json_topology(TOPO_TN_UUID, context_id=CONTEXT_ID) # ----- Devices -------------------------------------------------------------------------------------------------------- # DataCenters -DEV_DC1GW_ID, DEV_DC1GW_EPS, DEV_DC1GW = compose_device('DC1-GW', ['eth1', 'eth2', 'int'], topology_id=TOPO_DC1_ID) -DEV_DC2GW_ID, DEV_DC2GW_EPS, DEV_DC2GW = compose_device('DC2-GW', ['eth1', 'eth2', 'int'], topology_id=TOPO_DC2_ID) +DEV_DC1GW_ID, DEV_DC1GW_EPS, DEV_DC1GW = compose_datacenter('DC1-GW', ['eth1', 'eth2', 'int']) +DEV_DC2GW_ID, DEV_DC2GW_EPS, DEV_DC2GW = compose_datacenter('DC2-GW', ['eth1', 'eth2', 'int']) # CellSites -DEV_CS1GW1_ID, DEV_CS1GW1_EPS, DEV_CS1GW1 = compose_device('CS1-GW1', ['1000', '100', '200'], topology_id=TOPO_CS1_ID) -DEV_CS1GW2_ID, DEV_CS1GW2_EPS, DEV_CS1GW2 = compose_device('CS1-GW2', ['1000', '100', '200'], topology_id=TOPO_CS1_ID) -DEV_CS2GW1_ID, DEV_CS2GW1_EPS, DEV_CS2GW1 = compose_device('CS2-GW1', ['1000', '100', '200'], topology_id=TOPO_CS2_ID) -DEV_CS2GW2_ID, DEV_CS2GW2_EPS, DEV_CS2GW2 = compose_device('CS2-GW2', ['1000', '100', '200'], topology_id=TOPO_CS2_ID) +DEV_CS1GW1_ID, DEV_CS1GW1_EPS, DEV_CS1GW1 = compose_router('CS1-GW1', ['10/1', '1/1', '1/2']) +DEV_CS1GW2_ID, DEV_CS1GW2_EPS, DEV_CS1GW2 = compose_router('CS1-GW2', ['10/1', '1/1', '1/2']) +DEV_CS2GW1_ID, DEV_CS2GW1_EPS, DEV_CS2GW1 = compose_router('CS2-GW1', ['10/1', '1/1', '1/2']) +DEV_CS2GW2_ID, DEV_CS2GW2_EPS, DEV_CS2GW2 = compose_router('CS2-GW2', ['10/1', '1/1', '1/2']) # Transport Network -DEV_TNR1_ID, DEV_TNR1_EPS, DEV_TNR1 = compose_device('TN-R1', ['100', '200', '1', '2', '3'], topology_id=TOPO_TN_ID) -DEV_TNR2_ID, DEV_TNR2_EPS, DEV_TNR2 = compose_device('TN-R2', ['100', '200', '1', '2', '3'], topology_id=TOPO_TN_ID) -DEV_TNR3_ID, DEV_TNR3_EPS, DEV_TNR3 = compose_device('TN-R3', ['100', '200', '1', '2', '3'], topology_id=TOPO_TN_ID) -DEV_TNR4_ID, DEV_TNR4_EPS, DEV_TNR4 = compose_device('TN-R4', ['100', '200', '1', '2', '3'], topology_id=TOPO_TN_ID) +DEV_TNR1_ID, DEV_TNR1_EPS, DEV_TNR1 = compose_router('TN-R1', ['1/1', '1/2', '2/1', '2/2', '2/3']) +DEV_TNR2_ID, DEV_TNR2_EPS, DEV_TNR2 = compose_router('TN-R2', ['1/1', '1/2', '2/1', '2/2', '2/3']) +DEV_TNR3_ID, DEV_TNR3_EPS, DEV_TNR3 = compose_router('TN-R3', ['1/1', '1/2', '2/1', '2/2', '2/3']) +DEV_TNR4_ID, DEV_TNR4_EPS, DEV_TNR4 = compose_router('TN-R4', ['1/1', '1/2', '2/1', '2/2', '2/3']) # ----- Links ---------------------------------------------------------------------------------------------------------- @@ -122,32 +139,36 @@ LINK_TNR2_TNR4_ID, LINK_TNR2_TNR4 = compose_link(DEV_TNR2_EPS[4], DEV_TNR4_EPS[4 # ----- Service -------------------------------------------------------------------------------------------------------- SERVICE_DC1GW_DC2GW = compose_service(DEV_DC1GW_EPS[2], DEV_DC2GW_EPS[2], constraints=[ - json_constraint('bandwidth[gbps]', 10.0), - json_constraint('latency[ms]', 12.0), + json_constraint_custom('bandwidth[gbps]', 10.0), + json_constraint_custom('latency[ms]', 12.0), ]) # ----- Containers ----------------------------------------------------------------------------------------------------- -CONTEXTS = [ CONTEXT] -TOPOLOGIES = [ TOPO_ADMIN, TOPO_DC1, TOPO_DC2, TOPO_CS1, TOPO_CS2, TOPO_TN] +CONTEXTS = [ CONTEXT ] +TOPOLOGIES = [ TOPO_ADMIN, TOPO_DC1, TOPO_DC2, TOPO_CS1, TOPO_CS2, TOPO_TN ] DEVICES = [ DEV_DC1GW, DEV_DC2GW, DEV_CS1GW1, DEV_CS1GW2, DEV_CS2GW1, DEV_CS2GW2, - DEV_TNR1, DEV_TNR2, DEV_TNR3, DEV_TNR4 ] + DEV_TNR1, DEV_TNR2, DEV_TNR3, DEV_TNR4, + ] LINKS = [ LINK_DC1GW_CS1GW1, LINK_DC1GW_CS1GW2, LINK_DC2GW_CS2GW1, LINK_DC2GW_CS2GW2, LINK_CS1GW1_TNR1, LINK_CS1GW2_TNR2, LINK_CS1GW1_TNR2, LINK_CS1GW2_TNR1, LINK_CS2GW1_TNR3, LINK_CS2GW2_TNR4, LINK_CS2GW1_TNR4, LINK_CS2GW2_TNR3, - LINK_TNR1_TNR2, LINK_TNR2_TNR3, LINK_TNR3_TNR4, LINK_TNR4_TNR1, LINK_TNR1_TNR3, LINK_TNR2_TNR4 ] + LINK_TNR1_TNR2, LINK_TNR2_TNR3, LINK_TNR3_TNR4, LINK_TNR4_TNR1, LINK_TNR1_TNR3, LINK_TNR2_TNR4, + ] SERVICES = [ SERVICE_DC1GW_DC2GW ] OBJECTS_PER_TOPOLOGY = [ (TOPO_ADMIN_ID, [ DEV_DC1GW_ID, DEV_DC2GW_ID, DEV_CS1GW1_ID, DEV_CS1GW2_ID, DEV_CS2GW1_ID, DEV_CS2GW2_ID, - DEV_TNR1_ID, DEV_TNR2_ID, DEV_TNR3_ID, DEV_TNR4_ID ], + DEV_TNR1_ID, DEV_TNR2_ID, DEV_TNR3_ID, DEV_TNR4_ID, + ], [ LINK_DC1GW_CS1GW1_ID, LINK_DC1GW_CS1GW2_ID, LINK_DC2GW_CS2GW1_ID, LINK_DC2GW_CS2GW2_ID, LINK_CS1GW1_TNR1_ID, LINK_CS1GW2_TNR2_ID, LINK_CS1GW1_TNR2_ID, LINK_CS1GW2_TNR1_ID, LINK_CS2GW1_TNR3_ID, LINK_CS2GW2_TNR4_ID, LINK_CS2GW1_TNR4_ID, LINK_CS2GW2_TNR3_ID, LINK_TNR1_TNR2_ID, LINK_TNR2_TNR3_ID, LINK_TNR3_TNR4_ID, LINK_TNR4_TNR1_ID, LINK_TNR1_TNR3_ID, - LINK_TNR2_TNR4_ID ], + LINK_TNR2_TNR4_ID, + ], ), (TOPO_DC1_ID, [DEV_DC1GW_ID], @@ -162,7 +183,9 @@ OBJECTS_PER_TOPOLOGY = [ [DEV_CS2GW1_ID, DEV_CS2GW2_ID], []), (TOPO_TN_ID, - [DEV_TNR1_ID, DEV_TNR2_ID, DEV_TNR3_ID, DEV_TNR4_ID], - [LINK_TNR1_TNR2_ID, LINK_TNR2_TNR3_ID, LINK_TNR3_TNR4_ID, LINK_TNR4_TNR1_ID, LINK_TNR1_TNR3_ID, - LINK_TNR2_TNR4_ID]), + [ DEV_TNR1_ID, DEV_TNR2_ID, DEV_TNR3_ID, DEV_TNR4_ID, + ], + [ LINK_TNR1_TNR2_ID, LINK_TNR2_TNR3_ID, LINK_TNR3_TNR4_ID, LINK_TNR4_TNR1_ID, LINK_TNR1_TNR3_ID, + LINK_TNR2_TNR4_ID, + ]), ] diff --git a/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN_OLS.py b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN_OLS.py new file mode 100644 index 0000000000000000000000000000000000000000..a9b4a1512599ce4436b3498beb0b5ae4ebae92fb --- /dev/null +++ b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN_OLS.py @@ -0,0 +1,202 @@ +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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 uuid +from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID +from common.tools.object_factory.Constraint import json_constraint_custom +from common.tools.object_factory.Context import json_context, json_context_id +from common.tools.object_factory.Device import ( + json_device_emulated_connect_rules, json_device_emulated_datacenter_disabled, + json_device_emulated_packet_router_disabled, json_device_emulated_tapi_disabled, json_device_id) +from common.tools.object_factory.EndPoint import json_endpoints +from common.tools.object_factory.Link import get_link_uuid, json_link, json_link_id +from common.tools.object_factory.Service import get_service_uuid, json_service_l3nm_planned +from common.tools.object_factory.Topology import json_topology, json_topology_id + +# if true, Device component is present and will infeer the endpoints from connect-rules +# if false, Device component is not present and device objects must contain preconfigured endpoints +ADD_CONNECT_RULES_TO_DEVICES = False + +def compose_router(device_uuid, endpoint_uuids, topology_id=None): + device_id = json_device_id(device_uuid) + r_endpoints = [(endpoint_uuid, 'copper', []) for endpoint_uuid in endpoint_uuids] + config_rules = json_device_emulated_connect_rules(r_endpoints) if ADD_CONNECT_RULES_TO_DEVICES else [] + endpoints = json_endpoints(device_id, r_endpoints, topology_id=topology_id) + j_endpoints = [] if ADD_CONNECT_RULES_TO_DEVICES else endpoints + device = json_device_emulated_packet_router_disabled(device_uuid, config_rules=config_rules, endpoints=j_endpoints) + return device_id, endpoints, device + +def compose_ols(device_uuid, endpoint_uuids, topology_id=None): + device_id = json_device_id(device_uuid) + r_endpoints = [(endpoint_uuid, 'optical', []) for endpoint_uuid in endpoint_uuids] + config_rules = json_device_emulated_connect_rules(r_endpoints) if ADD_CONNECT_RULES_TO_DEVICES else [] + endpoints = json_endpoints(device_id, r_endpoints, topology_id=topology_id) + j_endpoints = [] if ADD_CONNECT_RULES_TO_DEVICES else endpoints + device = json_device_emulated_tapi_disabled(device_uuid, config_rules=config_rules, endpoints=j_endpoints) + return device_id, endpoints, device + +def compose_datacenter(device_uuid, endpoint_uuids, topology_id=None): + device_id = json_device_id(device_uuid) + r_endpoints = [(endpoint_uuid, 'copper', []) for endpoint_uuid in endpoint_uuids] + config_rules = json_device_emulated_connect_rules(r_endpoints) if ADD_CONNECT_RULES_TO_DEVICES else [] + endpoints = json_endpoints(device_id, r_endpoints, topology_id=topology_id) + j_endpoints = [] if ADD_CONNECT_RULES_TO_DEVICES else endpoints + device = json_device_emulated_datacenter_disabled(device_uuid, config_rules=config_rules, endpoints=j_endpoints) + return device_id, endpoints, device + +def compose_link(endpoint_a, endpoint_z): + link_uuid = get_link_uuid(endpoint_a['endpoint_id'], endpoint_z['endpoint_id']) + link_id = json_link_id(link_uuid) + link = json_link(link_uuid, [endpoint_a['endpoint_id'], endpoint_z['endpoint_id']]) + return link_id, link + +def compose_service(endpoint_a, endpoint_z, constraints=[]): + service_uuid = get_service_uuid(endpoint_a['endpoint_id'], endpoint_z['endpoint_id']) + endpoint_ids = [endpoint_a['endpoint_id'], endpoint_z['endpoint_id']] + service = json_service_l3nm_planned(service_uuid, endpoint_ids=endpoint_ids, constraints=constraints) + return service + +# ----- Context -------------------------------------------------------------------------------------------------------- +CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID) +CONTEXT = json_context(DEFAULT_CONTEXT_UUID) + +# ----- Domains -------------------------------------------------------------------------------------------------------- +# Overall network topology +TOPO_ADMIN_UUID = DEFAULT_TOPOLOGY_UUID +TOPO_ADMIN_ID = json_topology_id(TOPO_ADMIN_UUID, context_id=CONTEXT_ID) +TOPO_ADMIN = json_topology(TOPO_ADMIN_UUID, context_id=CONTEXT_ID) + +# DataCenter #1 Network +TOPO_DC1_UUID = 'DC1' +TOPO_DC1_ID = json_topology_id(TOPO_DC1_UUID, context_id=CONTEXT_ID) +TOPO_DC1 = json_topology(TOPO_DC1_UUID, context_id=CONTEXT_ID) + +# DataCenter #2 Network +TOPO_DC2_UUID = 'DC2' +TOPO_DC2_ID = json_topology_id(TOPO_DC2_UUID, context_id=CONTEXT_ID) +TOPO_DC2 = json_topology(TOPO_DC2_UUID, context_id=CONTEXT_ID) + +# CellSite #1 Network +TOPO_CS1_UUID = 'CS1' +TOPO_CS1_ID = json_topology_id(TOPO_CS1_UUID, context_id=CONTEXT_ID) +TOPO_CS1 = json_topology(TOPO_CS1_UUID, context_id=CONTEXT_ID) + +# CellSite #2 Network +TOPO_CS2_UUID = 'CS2' +TOPO_CS2_ID = json_topology_id(TOPO_CS2_UUID, context_id=CONTEXT_ID) +TOPO_CS2 = json_topology(TOPO_CS2_UUID, context_id=CONTEXT_ID) + +# Transport Network Network +TOPO_TN_UUID = 'TN' +TOPO_TN_ID = json_topology_id(TOPO_TN_UUID, context_id=CONTEXT_ID) +TOPO_TN = json_topology(TOPO_TN_UUID, context_id=CONTEXT_ID) + + +# ----- Devices -------------------------------------------------------------------------------------------------------- +# DataCenters +DEV_DC1GW_ID, DEV_DC1GW_EPS, DEV_DC1GW = compose_datacenter('DC1-GW', ['eth1', 'eth2', 'int']) +DEV_DC2GW_ID, DEV_DC2GW_EPS, DEV_DC2GW = compose_datacenter('DC2-GW', ['eth1', 'eth2', 'int']) + +# CellSites +DEV_CS1GW1_ID, DEV_CS1GW1_EPS, DEV_CS1GW1 = compose_router('CS1-GW1', ['10/1', '1/1', '1/2']) +DEV_CS1GW2_ID, DEV_CS1GW2_EPS, DEV_CS1GW2 = compose_router('CS1-GW2', ['10/1', '1/1', '1/2']) +DEV_CS2GW1_ID, DEV_CS2GW1_EPS, DEV_CS2GW1 = compose_router('CS2-GW1', ['10/1', '1/1', '1/2']) +DEV_CS2GW2_ID, DEV_CS2GW2_EPS, DEV_CS2GW2 = compose_router('CS2-GW2', ['10/1', '1/1', '1/2']) + +# Transport Network +DEV_TNR1_ID, DEV_TNR1_EPS, DEV_TNR1 = compose_router('TN-R1', ['1/1', '1/2', '2/1']) +DEV_TNR2_ID, DEV_TNR2_EPS, DEV_TNR2 = compose_router('TN-R2', ['1/1', '1/2', '2/1']) +DEV_TNR3_ID, DEV_TNR3_EPS, DEV_TNR3 = compose_router('TN-R3', ['1/1', '1/2', '2/1']) +DEV_TNR4_ID, DEV_TNR4_EPS, DEV_TNR4 = compose_router('TN-R4', ['1/1', '1/2', '2/1']) +tols_ep_uuids = [str(uuid.uuid4()).split('-')[-1] for _ in range(4)] +DEV_TOLS_ID, DEV_TOLS_EPS, DEV_TOLS = compose_ols('TN-OLS', tols_ep_uuids) + + +# ----- Links ---------------------------------------------------------------------------------------------------------- +# InterDomain DC-CSGW +LINK_DC1GW_CS1GW1_ID, LINK_DC1GW_CS1GW1 = compose_link(DEV_DC1GW_EPS[0], DEV_CS1GW1_EPS[0]) +LINK_DC1GW_CS1GW2_ID, LINK_DC1GW_CS1GW2 = compose_link(DEV_DC1GW_EPS[1], DEV_CS1GW2_EPS[0]) +LINK_DC2GW_CS2GW1_ID, LINK_DC2GW_CS2GW1 = compose_link(DEV_DC2GW_EPS[0], DEV_CS2GW1_EPS[0]) +LINK_DC2GW_CS2GW2_ID, LINK_DC2GW_CS2GW2 = compose_link(DEV_DC2GW_EPS[1], DEV_CS2GW2_EPS[0]) + +# InterDomain CSGW-TN +LINK_CS1GW1_TNR1_ID, LINK_CS1GW1_TNR1 = compose_link(DEV_CS1GW1_EPS[1], DEV_TNR1_EPS[0]) +LINK_CS1GW2_TNR2_ID, LINK_CS1GW2_TNR2 = compose_link(DEV_CS1GW2_EPS[1], DEV_TNR2_EPS[0]) +LINK_CS1GW1_TNR2_ID, LINK_CS1GW1_TNR2 = compose_link(DEV_CS1GW1_EPS[2], DEV_TNR2_EPS[1]) +LINK_CS1GW2_TNR1_ID, LINK_CS1GW2_TNR1 = compose_link(DEV_CS1GW2_EPS[2], DEV_TNR1_EPS[1]) +LINK_CS2GW1_TNR3_ID, LINK_CS2GW1_TNR3 = compose_link(DEV_CS2GW1_EPS[1], DEV_TNR3_EPS[0]) +LINK_CS2GW2_TNR4_ID, LINK_CS2GW2_TNR4 = compose_link(DEV_CS2GW2_EPS[1], DEV_TNR4_EPS[0]) +LINK_CS2GW1_TNR4_ID, LINK_CS2GW1_TNR4 = compose_link(DEV_CS2GW1_EPS[2], DEV_TNR4_EPS[1]) +LINK_CS2GW2_TNR3_ID, LINK_CS2GW2_TNR3 = compose_link(DEV_CS2GW2_EPS[2], DEV_TNR3_EPS[1]) + +# IntraDomain TN +LINK_TNR1_TOLS_ID, LINK_TNR1_TOLS = compose_link(DEV_TNR1_EPS[2], DEV_TOLS_EPS[0]) +LINK_TNR2_TOLS_ID, LINK_TNR2_TOLS = compose_link(DEV_TNR2_EPS[2], DEV_TOLS_EPS[1]) +LINK_TNR3_TOLS_ID, LINK_TNR3_TOLS = compose_link(DEV_TNR3_EPS[2], DEV_TOLS_EPS[2]) +LINK_TNR4_TOLS_ID, LINK_TNR4_TOLS = compose_link(DEV_TNR4_EPS[2], DEV_TOLS_EPS[3]) + + +# ----- Service -------------------------------------------------------------------------------------------------------- +SERVICE_DC1GW_DC2GW = compose_service(DEV_DC1GW_EPS[2], DEV_DC2GW_EPS[2], constraints=[ + json_constraint_custom('bandwidth[gbps]', 10.0), + json_constraint_custom('latency[ms]', 12.0), +]) + +# ----- Containers ----------------------------------------------------------------------------------------------------- +CONTEXTS = [ CONTEXT ] +TOPOLOGIES = [ TOPO_ADMIN, TOPO_DC1, TOPO_DC2, TOPO_CS1, TOPO_CS2, TOPO_TN ] +DEVICES = [ DEV_DC1GW, DEV_DC2GW, + DEV_CS1GW1, DEV_CS1GW2, DEV_CS2GW1, DEV_CS2GW2, + DEV_TNR1, DEV_TNR2, DEV_TNR3, DEV_TNR4, + DEV_TOLS, + ] +LINKS = [ LINK_DC1GW_CS1GW1, LINK_DC1GW_CS1GW2, LINK_DC2GW_CS2GW1, LINK_DC2GW_CS2GW2, + LINK_CS1GW1_TNR1, LINK_CS1GW2_TNR2, LINK_CS1GW1_TNR2, LINK_CS1GW2_TNR1, + LINK_CS2GW1_TNR3, LINK_CS2GW2_TNR4, LINK_CS2GW1_TNR4, LINK_CS2GW2_TNR3, + LINK_TNR1_TOLS, LINK_TNR2_TOLS, LINK_TNR3_TOLS, LINK_TNR4_TOLS, + ] +SERVICES = [ SERVICE_DC1GW_DC2GW ] + +OBJECTS_PER_TOPOLOGY = [ + (TOPO_ADMIN_ID, + [ DEV_DC1GW_ID, DEV_DC2GW_ID, + DEV_CS1GW1_ID, DEV_CS1GW2_ID, DEV_CS2GW1_ID, DEV_CS2GW2_ID, + DEV_TNR1_ID, DEV_TNR2_ID, DEV_TNR3_ID, DEV_TNR4_ID, + DEV_TOLS_ID, + ], + [ LINK_DC1GW_CS1GW1_ID, LINK_DC1GW_CS1GW2_ID, LINK_DC2GW_CS2GW1_ID, LINK_DC2GW_CS2GW2_ID, + LINK_CS1GW1_TNR1_ID, LINK_CS1GW2_TNR2_ID, LINK_CS1GW1_TNR2_ID, LINK_CS1GW2_TNR1_ID, + LINK_CS2GW1_TNR3_ID, LINK_CS2GW2_TNR4_ID, LINK_CS2GW1_TNR4_ID, LINK_CS2GW2_TNR3_ID, + LINK_TNR1_TOLS_ID, LINK_TNR2_TOLS_ID, LINK_TNR3_TOLS_ID, LINK_TNR4_TOLS_ID, + ], + ), + (TOPO_DC1_ID, + [DEV_DC1GW_ID], + []), + (TOPO_DC2_ID, + [DEV_DC2GW_ID], + []), + (TOPO_CS1_ID, + [DEV_CS1GW1_ID, DEV_CS1GW2_ID], + []), + (TOPO_CS2_ID, + [DEV_CS2GW1_ID, DEV_CS2GW2_ID], + []), + (TOPO_TN_ID, + [ DEV_TNR1_ID, DEV_TNR2_ID, DEV_TNR3_ID, DEV_TNR4_ID, + DEV_TOLS_ID, + ], + [ LINK_TNR1_TOLS_ID, LINK_TNR2_TOLS_ID, LINK_TNR3_TOLS_ID, LINK_TNR4_TOLS_ID, + ]), +] diff --git a/src/pathcomp/frontend/tests/test_unitary.py b/src/pathcomp/frontend/tests/test_unitary.py index 2368a6c0ade2bd0125a0a8df66560496fe782a1d..c09d4c7100629449e250dc87019f69f8ce6c3429 100644 --- a/src/pathcomp/frontend/tests/test_unitary.py +++ b/src/pathcomp/frontend/tests/test_unitary.py @@ -16,7 +16,12 @@ import copy, logging, os from common.proto.context_pb2 import Context, ContextId, DeviceId, Link, LinkId, Topology, Device, TopologyId from common.proto.pathcomp_pb2 import PathCompRequest from common.tools.grpc.Tools import grpc_message_to_json -from common.tools.object_factory.Constraint import json_constraint +from common.tools.object_factory.Constraint import ( + json_constraint_custom, json_constraint_endpoint_location_region, json_constraint_endpoint_priority, + json_constraint_sla_availability) +from common.tools.object_factory.Device import json_device_id +from common.tools.object_factory.EndPoint import json_endpoint_id +from common.tools.object_factory.Service import json_service_l3nm_planned from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from pathcomp.frontend.client.PathCompClient import PathCompClient @@ -24,6 +29,7 @@ from pathcomp.frontend.client.PathCompClient import PathCompClient # Scenarios: #from .Objects_A_B_C import CONTEXTS, DEVICES, LINKS, OBJECTS_PER_TOPOLOGY, SERVICES, TOPOLOGIES from .Objects_DC_CSGW_TN import CONTEXTS, DEVICES, LINKS, OBJECTS_PER_TOPOLOGY, SERVICES, TOPOLOGIES +#from .Objects_DC_CSGW_TN_OLS import CONTEXTS, DEVICES, LINKS, OBJECTS_PER_TOPOLOGY, SERVICES, TOPOLOGIES # configure backend environment variables before overwriting them with fixtures to use real backend pathcomp DEFAULT_PATHCOMP_BACKEND_SCHEME = 'http' @@ -85,8 +91,8 @@ def test_request_service_shortestpath( request_services = copy.deepcopy(SERVICES) #request_services[0]['service_constraints'] = [ - # json_constraint('bandwidth[gbps]', 1000.0), - # json_constraint('latency[ms]', 1200.0), + # json_constraint_custom('bandwidth[gbps]', 1000.0), + # json_constraint_custom('latency[ms]', 1200.0), #] pathcomp_request = PathCompRequest(services=request_services) pathcomp_request.shortest_path.Clear() # hack to select the shortest path algorithm that has no attributes @@ -188,7 +194,33 @@ def test_request_service_kshortestpath( def test_request_service_kdisjointpath( pathcomp_client : PathCompClient): # pylint: disable=redefined-outer-name - request_services = SERVICES + service_uuid = 'DC1-DC2' + raw_endpoints = [ + ('CS1-GW1', '10/1', 'DC1', 10), + ('CS1-GW2', '10/1', 'DC1', 20), + ('CS2-GW1', '10/1', 'DC2', 10), + ('CS2-GW2', '10/1', 'DC2', 20), + ] + + endpoint_ids, constraints = [], [ + json_constraint_custom('bandwidth[gbps]', 10.0), + json_constraint_custom('latency[ms]', 12.0), + json_constraint_sla_availability(2, True), + json_constraint_custom('diversity', {'end-to-end-diverse': 'all-other-accesses'}), + ] + + for device_uuid, endpoint_uuid, region, priority in raw_endpoints: + device_id = json_device_id(device_uuid) + endpoint_id = json_endpoint_id(device_id, endpoint_uuid) + endpoint_ids.append(endpoint_id) + constraints.extend([ + json_constraint_endpoint_location_region(endpoint_id, region), + json_constraint_endpoint_priority(endpoint_id, priority), + ]) + + service = json_service_l3nm_planned(service_uuid, endpoint_ids=endpoint_ids, constraints=constraints) + request_services = [service] + pathcomp_request = PathCompRequest(services=request_services) pathcomp_request.k_disjoint_path.num_disjoint = 2 #pylint: disable=no-member diff --git a/src/service/service/path_computation_element/PathComputationElement.py b/src/service/service/path_computation_element/PathComputationElement.py index 41a4c5d57722cb59ab3d3e505f9f79e68952ad5d..80316ac8965ebdbed99264127465488a946f6782 100644 --- a/src/service/service/path_computation_element/PathComputationElement.py +++ b/src/service/service/path_computation_element/PathComputationElement.py @@ -31,10 +31,10 @@ LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.INFO) SUB_SERVICE_TYPES = { - DeviceTypeEnum.EMULATED_PACKET_ROUTER.value : ServiceTypeEnum.SERVICETYPE_L3NM, - DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value: ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, - DeviceTypeEnum.PACKET_ROUTER.value : ServiceTypeEnum.SERVICETYPE_L3NM, - DeviceTypeEnum.OPTICAL_LINE_SYSTEM.value : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, + DeviceTypeEnum.EMULATED_PACKET_ROUTER.value : ServiceTypeEnum.SERVICETYPE_L3NM, + DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value: ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, + DeviceTypeEnum.PACKET_ROUTER.value : ServiceTypeEnum.SERVICETYPE_L3NM, + DeviceTypeEnum.OPEN_LINE_SYSTEM.value : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, } DEFAULT_SUB_SERVICE_TYPE = ServiceTypeEnum.SERVICETYPE_UNKNOWN diff --git a/src/service/tests/ServiceHandler_L3NM_EMU.py b/src/service/tests/ServiceHandler_L3NM_EMU.py index 0ac5fbf24cf1937104646374f60ab9487ee1c84d..45df80e4265018e802be587285fce318fc6b0736 100644 --- a/src/service/tests/ServiceHandler_L3NM_EMU.py +++ b/src/service/tests/ServiceHandler_L3NM_EMU.py @@ -14,7 +14,7 @@ from typing import Dict, List, Tuple from common.tools.object_factory.ConfigRule import json_config_rule_set -from common.tools.object_factory.Constraint import json_constraint +from common.tools.object_factory.Constraint import json_constraint_custom from common.tools.object_factory.Device import ( json_device_emulated_packet_router_disabled, json_device_emulated_tapi_disabled, json_device_id) from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id @@ -101,8 +101,8 @@ SERVICE_R1_R3_UUID = 'SVC:{:s}/{:s}-{:s}/{:s}'.format( DEVICE_R3_UUID, ENDPOINT_ID_R3_EP100['endpoint_uuid']['uuid']) SERVICE_R1_R3_ENDPOINT_IDS = [ENDPOINT_ID_R1_EP100, ENDPOINT_ID_R3_EP100] SERVICE_R1_R3_CONSTRAINTS = [ - json_constraint('latency_ms', 15.2), - json_constraint('jitter_us', 1.2), + json_constraint_custom('latency_ms', 15.2), + json_constraint_custom('jitter_us', 1.2), ] SERVICE_R1_R3_CONFIG_RULES = [ json_config_rule_set( diff --git a/src/service/tests/ServiceHandler_L3NM_OC.py b/src/service/tests/ServiceHandler_L3NM_OC.py index 0797a4af5505e78e2af49cefc29970f9c8ff11e7..717536f6d1ee60564752f3107cd366796e3a36e2 100644 --- a/src/service/tests/ServiceHandler_L3NM_OC.py +++ b/src/service/tests/ServiceHandler_L3NM_OC.py @@ -15,7 +15,7 @@ import uuid from typing import Dict, List, Tuple from common.tools.object_factory.ConfigRule import json_config_rule_set -from common.tools.object_factory.Constraint import json_constraint +from common.tools.object_factory.Constraint import json_constraint_custom from common.tools.object_factory.Device import ( json_device_connect_rules, json_device_emulated_packet_router_disabled, json_device_emulated_tapi_disabled, json_device_id) @@ -115,8 +115,8 @@ SERVICE_R1_R2_UUID = 'SVC:{:s}/{:s}-{:s}/{:s}'.format( DEVICE_R2_UUID, ENDPOINT_ID_R2_EP100['endpoint_uuid']['uuid']) SERVICE_R1_R2_ENDPOINT_IDS = [ENDPOINT_ID_R1_EP100, ENDPOINT_ID_R2_EP100] SERVICE_R1_R2_CONSTRAINTS = [ - json_constraint('latency_ms', 15.2), - json_constraint('jitter_us', 1.2), + json_constraint_custom('latency_ms', 15.2), + json_constraint_custom('jitter_us', 1.2), ] SERVICE_R1_R2_CONFIG_RULES = [ json_config_rule_set( diff --git a/src/tests/oeccpsc22/tests/test_functional_create_interdomain_slice.py b/src/tests/oeccpsc22/tests/test_functional_create_interdomain_slice.py index e6f6ccbc96152eb7e3a33317293261e28c89d713..b31e868741a7996494d1f7763a3f7e237ca216a1 100644 --- a/src/tests/oeccpsc22/tests/test_functional_create_interdomain_slice.py +++ b/src/tests/oeccpsc22/tests/test_functional_create_interdomain_slice.py @@ -27,7 +27,7 @@ LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) DEVTYPE_EMU_PR = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value -DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value +DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value @pytest.fixture(scope='session') diff --git a/src/tests/oeccpsc22/tests/test_functional_delete_interdomain_slice.py b/src/tests/oeccpsc22/tests/test_functional_delete_interdomain_slice.py index 40a954868620564aef7d60c5ec0023ea0a32337b..45296d107bcdb14472f05c677ba0c75113fd94cc 100644 --- a/src/tests/oeccpsc22/tests/test_functional_delete_interdomain_slice.py +++ b/src/tests/oeccpsc22/tests/test_functional_delete_interdomain_slice.py @@ -27,7 +27,7 @@ LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) DEVTYPE_EMU_PR = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value -DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value +DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value @pytest.fixture(scope='session') diff --git a/src/tests/ofc22/descriptors_emulated.json b/src/tests/ofc22/descriptors_emulated.json index eb22506238e03a161f0e2b8aaeadf5fd31cf547b..6beb1427ebb22f22bcb24b73c173d33d4352cdb4 100644 --- a/src/tests/ofc22/descriptors_emulated.json +++ b/src/tests/ofc22/descriptors_emulated.json @@ -64,7 +64,7 @@ }, { "device_id": {"device_uuid": {"uuid": "O1-OLS"}}, - "device_type": "emu-optical-line-system", + "device_type": "emu-open-line-system", "device_config": {"config_rules": [ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, diff --git a/src/tests/ofc22/tests/test_functional_create_service.py b/src/tests/ofc22/tests/test_functional_create_service.py index f3389fdbfce4e9262ffddbad876bb86f9b300551..31572e7ba0854a394607fb705aa52b9caeb08085 100644 --- a/src/tests/ofc22/tests/test_functional_create_service.py +++ b/src/tests/ofc22/tests/test_functional_create_service.py @@ -32,7 +32,7 @@ LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) DEVTYPE_EMU_PR = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value -DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value +DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value @pytest.fixture(scope='session') diff --git a/src/tests/ofc22/tests/test_functional_delete_service.py b/src/tests/ofc22/tests/test_functional_delete_service.py index 51e91a5967e1696fa2fdfe7dd06d2efb46642248..b4bc621d294245a6286e77483e3074f95533fd4e 100644 --- a/src/tests/ofc22/tests/test_functional_delete_service.py +++ b/src/tests/ofc22/tests/test_functional_delete_service.py @@ -33,7 +33,7 @@ LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) DEVTYPE_EMU_PR = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value -DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value +DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value @pytest.fixture(scope='session') diff --git a/src/webui/service/static/topology_icons/Acknowledgements.txt b/src/webui/service/static/topology_icons/Acknowledgements.txt index 6329f8233098788e92cecc34d1b38380b0bcce6a..5daab200f87c29f18706e9e07023a45047739df7 100644 --- a/src/webui/service/static/topology_icons/Acknowledgements.txt +++ b/src/webui/service/static/topology_icons/Acknowledgements.txt @@ -8,8 +8,8 @@ https://symbols.getvecta.com/stencil_241/45_atm-switch.6a7362c1df.png => emu-pac https://symbols.getvecta.com/stencil_240/204_router.7b208c1133.png => packet-router.png https://symbols.getvecta.com/stencil_241/224_router.be30fb87e7.png => emu-packet-router.png -https://symbols.getvecta.com/stencil_240/269_virtual-layer-switch.ed10fdede6.png => optical-line-system.png -https://symbols.getvecta.com/stencil_241/281_virtual-layer-switch.29420aff2f.png => emu-optical-line-system.png +https://symbols.getvecta.com/stencil_240/269_virtual-layer-switch.ed10fdede6.png => open-line-system.png +https://symbols.getvecta.com/stencil_241/281_virtual-layer-switch.29420aff2f.png => emu-open-line-system.png https://symbols.getvecta.com/stencil_240/102_ibm-tower.2cc133f3d0.png => datacenter.png https://symbols.getvecta.com/stencil_241/133_ibm-tower.995c44696c.png => emu-datacenter.png diff --git a/src/webui/service/static/topology_icons/emu-optical-line-system.png b/src/webui/service/static/topology_icons/emu-open-line-system.png similarity index 100% rename from src/webui/service/static/topology_icons/emu-optical-line-system.png rename to src/webui/service/static/topology_icons/emu-open-line-system.png diff --git a/src/webui/service/static/topology_icons/optical-line-system.png b/src/webui/service/static/topology_icons/open-line-system.png similarity index 100% rename from src/webui/service/static/topology_icons/optical-line-system.png rename to src/webui/service/static/topology_icons/open-line-system.png