diff --git a/.gitignore b/.gitignore index a0ac78095a9f275ae35060a584c5df2151aa7d0e..db47387c8c8ff9900a59107642221960134aa1f1 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ MANIFEST # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest +.manifest/ *.spec # Installer logs diff --git a/proto/context.proto b/proto/context.proto index d3888e77b0256f63fb4b4eb10b987137057a0aa7..bb769a5a2cc37c7137be1da5f4e47edf41628f5e 100644 --- a/proto/context.proto +++ b/proto/context.proto @@ -77,13 +77,19 @@ service ContextService { // ------------------------------ Experimental ----------------------------- - rpc GetOpticalConfig (Empty ) returns (OpticalConfigList ) {} - rpc SetOpticalConfig (OpticalConfig ) returns (OpticalConfigId ) {} - rpc SelectOpticalConfig(OpticalConfigId) returns (OpticalConfig ) {} + rpc GetOpticalConfig (Empty ) returns (OpticalConfigList) {} + rpc SetOpticalConfig (OpticalConfig ) returns (OpticalConfigId ) {} + rpc UpdateOpticalConfig (OpticalConfig ) returns (OpticalConfigId ) {} + rpc SelectOpticalConfig (OpticalConfigId ) returns (OpticalConfig ) {} + rpc DeleteOpticalConfig (OpticalConfigId ) returns (Empty ) {} + rpc DeleteOpticalChannel (OpticalConfig ) returns (Empty ) {} - rpc SetOpticalLink (OpticalLink ) returns (Empty ) {} - rpc GetOpticalLink (OpticalLinkId ) returns (OpticalLink ) {} - rpc GetFiber (FiberId ) returns (Fiber ) {} + rpc SetOpticalLink (OpticalLink ) returns (Empty ) {} + rpc GetOpticalLink (LinkId ) returns (OpticalLink ) {} + rpc DeleteOpticalLink (LinkId ) returns (Empty ) {} + rpc GetOpticalLinkList (Empty ) returns (OpticalLinkList ) {} + + rpc DeleteServiceConfigRule(ServiceConfigRule) returns (Empty ) {} } // ----- Generic ------------------------------------------------------------------------------------------------------- @@ -148,6 +154,7 @@ message Topology { string name = 2; repeated DeviceId device_ids = 3; repeated LinkId link_ids = 4; + repeated LinkId optical_link_ids = 5; } message TopologyDetails { @@ -155,6 +162,7 @@ message TopologyDetails { string name = 2; repeated Device devices = 3; repeated Link links = 4; + repeated OpticalLink optical_links = 5; } message TopologyIdList { @@ -653,45 +661,57 @@ message OpticalConfigId { message OpticalConfig { OpticalConfigId opticalconfig_id = 1; string config = 2; + DeviceId device_id = 3; } message OpticalConfigList { repeated OpticalConfig opticalconfigs = 1; } +message OpticalConfigEvent { + Event event = 1; + OpticalConfigId opticalconfig_id = 2; +} + + // ---- Optical Link ---- -message OpticalLinkId { - Uuid optical_link_uuid = 1; +message OpticalEndPointId { + DeviceId device_id = 2; + Uuid endpoint_uuid = 3; } -message FiberId { - Uuid fiber_uuid = 1; -} -message Fiber { - string ID = 10; - string src_port = 1; - string dst_port = 2; - string local_peer_port = 3; - string remote_peer_port = 4; - repeated int32 c_slots = 5; - repeated int32 l_slots = 6; - repeated int32 s_slots = 7; - float length = 8; - bool used = 9; - FiberId fiber_uuid = 11; - +message OpticalLinkList { + repeated OpticalLink optical_links = 1; } + + + message OpticalLinkDetails { float length = 1; - string source = 2; - string target = 3; - repeated Fiber fibers = 4; + string src_port = 2; + string dst_port = 3; + string local_peer_port = 4; + string remote_peer_port = 5 ; + bool used = 6 ; + map<string, int32> c_slots = 7; + map<string, int32> l_slots = 8; + map<string, int32> s_slots = 9; } message OpticalLink { string name = 1; - OpticalLinkDetails details = 2; - OpticalLinkId optical_link_uuid = 3; + OpticalLinkDetails optical_details = 2; + LinkId link_id = 3; + repeated EndPointId link_endpoint_ids=4; +} + + + +////////////////// Config Rule Delete //////////// + +message ServiceConfigRule { + ServiceId service_id =1; + ConfigRule_Custom configrule_custom =2; } diff --git a/proto/openconfig_device.proto b/proto/optical_device.proto similarity index 64% rename from proto/openconfig_device.proto rename to proto/optical_device.proto index 8ed3a900b6b157e096308c9f476e3c0ab1f575c1..39eb92e4420bf28979b5da9d93ec9264a07dacb3 100644 --- a/proto/openconfig_device.proto +++ b/proto/optical_device.proto @@ -13,11 +13,13 @@ // limitations under the License. syntax = "proto3"; -package openconfig_device; +package optical_device; import "context.proto"; service OpenConfigService { - rpc AddOpenConfigDevice (context.OpticalConfig) returns (context.OpticalConfigId) {} - rpc ConfigureOpticalDevice(context.OpticalConfig) returns (context.Empty ) {} + rpc AddOpenConfigDevice (context.OpticalConfig ) returns (context.OpticalConfigId) {} + rpc ConfigureOpticalDevice(context.OpticalConfig ) returns (context.Empty ) {} + rpc DisableOpticalDevice (context.OpticalConfig ) returns (context.Empty ) {} + rpc GetDeviceConfiguration(context.OpticalConfigList) returns (context.Empty ) {} } diff --git a/src/automation/client/PolicyClient.py b/src/automation/client/PolicyClient.py index f2b25f2429d790c9cb25b5d70e1e737594586133..f7b6412a62670d0be2caa1460f7fab5ffec6fccd 100644 --- a/src/automation/client/PolicyClient.py +++ b/src/automation/client/PolicyClient.py @@ -19,7 +19,7 @@ from common.proto.policy_pb2 import PolicyRuleService, PolicyRuleState from common.proto.policy_pb2_grpc import PolicyServiceStub from common.tools.client.RetryDecorator import retry, delay_exponential from common.tools.grpc.Tools import grpc_message_to_json_string -from common.proto.openconfig_device_pb2_grpc import OpenConfigServiceStub + LOGGER = logging.getLogger(__name__) MAX_RETRIES = 15 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) @@ -40,7 +40,6 @@ class PolicyClient: def connect(self): self.channel = grpc.insecure_channel(self.endpoint) self.stub = PolicyServiceStub(self.channel) - self.openconfig_stub=OpenConfigServiceStub(self.channel) def close(self): if self.channel is not None: self.channel.close() diff --git a/src/common/tools/context_queries/OpticalConfig.py b/src/common/tools/context_queries/OpticalConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..bd697599cdd674ad2dca9ac8d38100333e315ea3 --- /dev/null +++ b/src/common/tools/context_queries/OpticalConfig.py @@ -0,0 +1,66 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +from common.method_wrappers.ServiceExceptions import InvalidArgumentsException +from typing import Optional, Union +from uuid import UUID, uuid4, uuid5 + +# Generate a UUIDv5-like from the SHA-1 of "TFS" and no namespace to be used as the NAMESPACE for all +# the context UUIDs generated. For efficiency purposes, the UUID is hardcoded; however, it is produced +# using the following code: +# from hashlib import sha1 +# from uuid import UUID +# hash = sha1(bytes('TFS', 'utf-8')).digest() +# NAMESPACE_TFS = UUID(bytes=hash[:16], version=5) +NAMESPACE_TFS = UUID('200e3a1f-2223-534f-a100-758e29c37f40') + +def get_uuid_from_string(str_uuid_or_name : Union[str, UUID], prefix_for_name : Optional[str] = None) -> str: + # if UUID given, assume it is already a valid UUID + if isinstance(str_uuid_or_name, UUID): return str_uuid_or_name + if not isinstance(str_uuid_or_name, str): + MSG = 'Parameter({:s}) cannot be used to produce a UUID' + raise Exception(MSG.format(str(repr(str_uuid_or_name)))) + try: + # try to parse as UUID + return str(UUID(str_uuid_or_name)) + except: # pylint: disable=bare-except + # produce a UUID within TFS namespace from parameter + if prefix_for_name is not None: + str_uuid_or_name = '{:s}/{:s}'.format(prefix_for_name, str_uuid_or_name) + return str(uuid5(NAMESPACE_TFS, str_uuid_or_name)) + +def get_uuid_random() -> str: + # Generate random UUID. No need to use namespace since "namespace + random = random". + return str(uuid4()) + +def device_get_uuid (device_name) : + if (len(device_name)> 0): + return get_uuid_from_string(device_name) + raise InvalidArgumentsException([ + ('name', device_name), + ], extra_details=['Device Name is required to produce Device UUID']) + + +def opticalconfig_get_uuid( + device_name : str = '', allow_random : bool = False +) -> str: + if len(device_name) > 0: + device_uuid= device_get_uuid(device_name=device_name) + return get_uuid_from_string(f"{device_uuid}_opticalconfig") + if allow_random: return get_uuid_random() + + raise InvalidArgumentsException([ + ('name', device_name), + ], extra_details=['At least one is required to produce a OpticalConfig UUID']) diff --git a/src/common/tools/descriptor/Loader.py b/src/common/tools/descriptor/Loader.py index 2fcc5b63a66ae3c3e96ab774d34958a110f0454a..958536f26c3c63468f1af4a6d14130b6e12fd08f 100644 --- a/src/common/tools/descriptor/Loader.py +++ b/src/common/tools/descriptor/Loader.py @@ -38,7 +38,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from common.proto.context_pb2 import ( Connection, Context, ContextId, Device, DeviceId, Empty, Link, LinkId, Service, ServiceId, Slice, SliceId, - Topology, TopologyId + Topology, TopologyId , OpticalLink ) from common.tools.object_factory.Context import json_context_id from context.client.ContextClient import ContextClient @@ -128,15 +128,16 @@ class DescriptorLoader: self.__num_workers = num_workers - self.__dummy_mode = self.__descriptors.get('dummy_mode' , False) - self.__contexts = self.__descriptors.get('contexts' , []) - self.__topologies = self.__descriptors.get('topologies' , []) - self.__devices = self.__descriptors.get('devices' , []) - self.__links = self.__descriptors.get('links' , []) - self.__services = self.__descriptors.get('services' , []) - self.__slices = self.__descriptors.get('slices' , []) - self.__ietf_slices = self.__descriptors.get('ietf-network-slice-service:network-slice-services', {}) - self.__connections = self.__descriptors.get('connections', []) + self.__dummy_mode = self.__descriptors.get('dummy_mode' , False) + self.__contexts = self.__descriptors.get('contexts' , []) + self.__topologies = self.__descriptors.get('topologies' , []) + self.__devices = self.__descriptors.get('devices' , []) + self.__links = self.__descriptors.get('links' , []) + self.__services = self.__descriptors.get('services' , []) + self.__slices = self.__descriptors.get('slices' , []) + self.__ietf_slices = self.__descriptors.get('ietf-network-slice-service:network-slice-services', {}) + self.__connections = self.__descriptors.get('connections', []) + self.__optical_links = self.__descriptors.get('optical_links',[]) if len(self.__ietf_slices) > 0: for slice_service in self.__ietf_slices["slice-service"]: @@ -285,6 +286,9 @@ class DescriptorLoader: @property def num_connections(self) -> int: return len(self.__connections) + + @property + def optical_links(self) -> List[Dict]: return self.__optical_links def process(self) -> TypeResults: # Format CustomConfigRules in Devices, Services and Slices provided in JSON format @@ -348,16 +352,17 @@ class DescriptorLoader: self.__svc_cli.connect() self.__slc_cli.connect() - self._process_descr('context', 'add', self.__ctx_cli.SetContext, Context, self.__contexts_add ) - self._process_descr('topology', 'add', self.__ctx_cli.SetTopology, Topology, self.__topologies_add) - self._process_descr('controller', 'add', self.__dev_cli.AddDevice, Device, controllers_add ) - self._process_descr('device', 'add', self.__dev_cli.AddDevice, Device, network_devices_add ) - self._process_descr('device', 'config', self.__dev_cli.ConfigureDevice, Device, self.__devices_config) - self._process_descr('link', 'add', self.__ctx_cli.SetLink, Link, self.__links ) - self._process_descr('service', 'add', self.__svc_cli.CreateService, Service, self.__services_add ) - self._process_descr('service', 'update', self.__svc_cli.UpdateService, Service, self.__services ) - self._process_descr('slice', 'add', self.__slc_cli.CreateSlice, Slice, self.__slices_add ) - self._process_descr('slice', 'update', self.__slc_cli.UpdateSlice, Slice, self.__slices ) + self._process_descr('context', 'add', self.__ctx_cli.SetContext, Context, self.__contexts_add ) + self._process_descr('topology', 'add', self.__ctx_cli.SetTopology, Topology, self.__topologies_add) + self._process_descr('controller', 'add', self.__dev_cli.AddDevice, Device, controllers_add ) + self._process_descr('device', 'add', self.__dev_cli.AddDevice, Device, network_devices_add ) + self._process_descr('device', 'config', self.__dev_cli.ConfigureDevice, Device, self.__devices_config) + self._process_descr('link', 'add', self.__ctx_cli.SetLink, Link, self.__links ) + self._process_descr('service', 'add', self.__svc_cli.CreateService, Service, self.__services_add ) + self._process_descr('service', 'update', self.__svc_cli.UpdateService, Service, self.__services ) + self._process_descr('slice', 'add', self.__slc_cli.CreateSlice, Slice, self.__slices_add ) + self._process_descr('slice', 'update', self.__slc_cli.UpdateSlice, Slice, self.__slices ) + self._process_descr('link', 'add', self.__ctx_cli.SetOpticalLink, OpticalLink, self.__optical_links ) # By default the Context component automatically assigns devices and links to topologies based on their # endpoints, and assigns topologies, services, and slices to contexts based on their identifiers. diff --git a/src/common/tools/object_factory/OpticalLink.py b/src/common/tools/object_factory/OpticalLink.py new file mode 100644 index 0000000000000000000000000000000000000000..765cfac22d2aa6a168e01e41df393cc2b693a32f --- /dev/null +++ b/src/common/tools/object_factory/OpticalLink.py @@ -0,0 +1,40 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 copy + +def convert_to_dict(single_val:int)->dict: + slot= dict() + bin_num = bin(single_val) + sliced_num=bin_num[2:] + for i in range(len(sliced_num)): + slot[str(i+1)]=int(sliced_num[i]) + return slot + +def correct_slot(dic: dict) -> dict: + _dict = copy.deepcopy(dic) + keys_list = list(_dict.keys()) + if len(keys_list) < 20: + num_keys = [int(i) for i in keys_list] + if num_keys[-1] != 20: + missed_keys = [] + diff = 20 - len(num_keys) + #print(f"diff {diff}") + for i in range(diff+1): + missed_keys.append(num_keys[-1]+i) + #print(f"missed_keys {missed_keys}") + for key in missed_keys : + _dict[key]=1 + #print(f"result {_dict}") + return _dict diff --git a/src/common/type_checkers/Assertions.py b/src/common/type_checkers/Assertions.py index 3934c9d89568be90129bb766c61b55a532d2f0b3..498a85349c4c9d68bc8c64c5d174595cb98c1cef 100644 --- a/src/common/type_checkers/Assertions.py +++ b/src/common/type_checkers/Assertions.py @@ -451,7 +451,7 @@ def validate_slice(message): def validate_topology(message, num_devices=None, num_links=None): assert isinstance(message, dict) - assert len(message.keys()) == 4 + assert len(message.keys()) == 5 assert 'topology_id' in message validate_topology_id(message['topology_id']) assert 'name' in message @@ -464,6 +464,10 @@ def validate_topology(message, num_devices=None, num_links=None): assert isinstance(message['link_ids'], list) if num_links is not None: assert len(message['link_ids']) == num_links for link_id in message['link_ids']: validate_link_id(link_id) + assert 'optical_link_ids' in message + assert isinstance(message['optical_link_ids'], list) + #if num_links is not None: assert len(message['optical_link_ids']) == num_links + for link_id in message['optical_link_ids']: validate_link_id(link_id) def validate_endpoint(message): assert isinstance(message, dict) diff --git a/src/context/client/ContextClient.py b/src/context/client/ContextClient.py index 2776a0d294e9a9ee7b00e46bfd3fbb068133741f..35f9121b33f60034340cbe2492e1bd26a622f6e7 100644 --- a/src/context/client/ContextClient.py +++ b/src/context/client/ContextClient.py @@ -24,10 +24,10 @@ from common.proto.context_pb2 import ( Device, DeviceEvent, DeviceFilter, DeviceId, DeviceIdList, DeviceList, Empty, EndPointIdList, EndPointNameList, Link, LinkEvent, LinkId, LinkIdList, LinkList, - Service, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList, + OpticalConfig, OpticalConfigId, OpticalConfigList , OpticalLink, OpticalLinkList, + Service, ServiceConfigRule, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList, Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList, - OpticalConfig, OpticalConfigId, OpticalConfigList ) from common.proto.context_pb2_grpc import ContextServiceStub from common.proto.context_policy_pb2_grpc import ContextPolicyServiceStub @@ -447,6 +447,14 @@ class ContextClient: response = self.stub.SetOpticalConfig(request) LOGGER.debug('SetOpticalConfig result: {:s}'.format(grpc_message_to_json_string(response))) return response + + @RETRY_DECORATOR + def UpdateOpticalConfig(self, request : OpticalConfig) -> OpticalConfigId: + LOGGER.debug('SetOpticalConfig request: {:s}'.format(grpc_message_to_json_string(request))) + response_future = self.stub.UpdateOpticalConfig.future(request) + response = response_future.result() + LOGGER.debug('SetOpticalConfig result: {:s}'.format(grpc_message_to_json_string(response))) + return response @RETRY_DECORATOR def GetOpticalConfig(self, request : Empty) -> OpticalConfigList: @@ -461,3 +469,55 @@ class ContextClient: response = self.stub.SelectOpticalConfig(request) LOGGER.debug('SelectOpticalConfig result: {:s}'.format(grpc_message_to_json_string(response))) return response + + @RETRY_DECORATOR + def DeleteOpticalConfig(self,request : OpticalConfigId) -> Empty: + LOGGER.debug('DeleteOpticalConfig request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.DeleteOpticalConfig(request) + LOGGER.debug('DeleteOpticalConfig result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def DeleteOpticalChannel(self,request : OpticalConfig) -> Empty: + LOGGER.debug('DeleteOpticalChannel request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.DeleteOpticalChannel(request) + LOGGER.debug('DeleteOpticalChannel result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + #--------------------------- Optical Link ------------------------ + def GetOpticalLinkList(self, request: Empty) -> OpticalLinkList: + LOGGER.debug('ListOpticalLinks request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetOpticalLinkList(request) + LOGGER.debug('ListOpticalLinks result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def GetOpticalLink(self, request: LinkId) -> OpticalLink: + LOGGER.debug('GetOpticalLink request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetOpticalLink(request) + LOGGER.debug('GetOpticalLink result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def SetOpticalLink(self, request: OpticalLink) -> LinkId: + LOGGER.debug('SetOpticalLink request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.SetOpticalLink(request) + LOGGER.debug('SetOpticalLink result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def DeleteOpticalLink(self, request: LinkId) -> Empty: + LOGGER.debug('RemoveOpticalLink request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.DeleteOpticalLink(request) + LOGGER.debug('RemoveOpticalLink result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + + # --------------------------------- Service ConfigRule Deletion ------------------ + + @RETRY_DECORATOR + def DeleteServiceConfigRule(self, request: ServiceConfigRule) -> Empty: + LOGGER.debug('ServiceConfigRule Delete request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.DeleteServiceConfigRule(request) + LOGGER.debug('ServiceConfigRule Delete result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/context/service/ContextServiceServicerImpl.py b/src/context/service/ContextServiceServicerImpl.py index be32372108e059625801d14c660d18cbe0df677f..09d16b0f8a80f956a32f7e074e3bbe5582b3b26c 100644 --- a/src/context/service/ContextServiceServicerImpl.py +++ b/src/context/service/ContextServiceServicerImpl.py @@ -24,29 +24,51 @@ from common.proto.context_pb2 import ( Service, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList, Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList, - OpticalConfigList, OpticalConfigId, OpticalConfig + OpticalConfigList, OpticalConfigId, OpticalConfig, OpticalLink, OpticalLinkList, + ServiceConfigRule ) from common.proto.policy_pb2 import PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule from common.proto.context_pb2_grpc import ContextServiceServicer from common.proto.context_policy_pb2_grpc import ContextPolicyServiceServicer from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method from .database.Connection import ( - connection_delete, connection_get, connection_list_ids, connection_list_objs, connection_set) -from .database.Context import context_delete, context_get, context_list_ids, context_list_objs, context_set -from .database.Device import device_delete, device_get, device_list_ids, device_list_objs, device_select, device_set + connection_delete, connection_get, connection_list_ids, connection_list_objs, connection_set +) +from .database.Context import ( + context_delete, context_get, context_list_ids, context_list_objs, context_set +) +from .database.Device import ( + device_delete, device_get, device_list_ids, device_list_objs, device_select, device_set +) from .database.EndPoint import endpoint_list_names from .database.Events import EventTopicEnum, consume_events -from .database.Link import link_delete, link_get, link_list_ids, link_list_objs, link_set +from .database.Link import ( + link_delete, link_get, link_list_ids, link_list_objs, link_set +) from .database.PolicyRule import ( - policyrule_delete, policyrule_get, policyrule_list_ids, policyrule_list_objs, policyrule_set) + policyrule_delete, policyrule_get, policyrule_list_ids, policyrule_list_objs, + policyrule_set +) from .database.Service import ( - service_delete, service_get, service_list_ids, service_list_objs, service_select, service_set, service_unset) + service_delete, service_get, service_list_ids, service_list_objs, service_select, + service_set, service_unset +) from .database.Slice import ( - slice_delete, slice_get, slice_list_ids, slice_list_objs, slice_select, slice_set, slice_unset) + slice_delete, slice_get, slice_list_ids, slice_list_objs, slice_select, + slice_set, slice_unset +) from .database.Topology import ( - topology_delete, topology_get, topology_get_details, topology_list_ids, topology_list_objs, topology_set) -from .database.OpticalConfig import set_opticalconfig, select_opticalconfig, get_opticalconfig - + topology_delete, topology_get, topology_get_details, topology_list_ids, + topology_list_objs, topology_set +) +from .database.OpticalConfig import ( + set_opticalconfig, select_opticalconfig, get_opticalconfig, delete_opticalconfig, + update_opticalconfig, delete_opticalchannel +) +from .database.OpticalLink import ( + optical_link_delete, optical_link_get, optical_link_list_objs, optical_link_set +) +from .database.ConfigRule import delete_config_rule LOGGER = logging.getLogger(__name__) METRICS_POOL = MetricsPool('Context', 'RPC') @@ -312,7 +334,48 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer result = set_opticalconfig(self.db_engine, request) return OpticalConfigId(**result) + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def UpdateOpticalConfig(self, request : OpticalConfig, context : grpc.ServicerContext) -> OpticalConfigId: + result = update_opticalconfig(self.db_engine, request) + return OpticalConfigId(**result) + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def SelectOpticalConfig(self, request : OpticalConfigId, context : grpc.ServicerContext) -> OpticalConfig: result = select_opticalconfig(self.db_engine, request) - return OpticalConfig(config=result.config, opticalconfig_id=result.opticalconfig_id) + optical_config_id = OpticalConfigId() + device_id = DeviceId() + optical_config_id.CopyFrom(result.opticalconfig_id) + device_id.CopyFrom(result.device_id) + return OpticalConfig(config=result.config, opticalconfig_id=optical_config_id , device_id=device_id) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def DeleteOpticalConfig(self, request : OpticalConfigId, context : grpc.ServicerContext) -> Empty: + delete_opticalconfig(self.db_engine, self.messagebroker, request) + return Empty() + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def DeleteOpticalChannel(self, request : OpticalConfig, context : grpc.ServicerContext) -> Empty: + delete_opticalchannel(self.db_engine, self.messagebroker, request) + return Empty() + + #--------------------- Experimental Optical Link ------------------- + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetOpticalLinkList(self, request : Empty, context : grpc.ServicerContext) -> OpticalLinkList: + return optical_link_list_objs(self.db_engine) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetOpticalLink(self, request : LinkId, context : grpc.ServicerContext) -> OpticalLink: + return optical_link_get(self.db_engine, request) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def SetOpticalLink(self, request : Link, context : grpc.ServicerContext) -> LinkId: + return optical_link_set(self.db_engine, self.messagebroker, request) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def DeleteOpticalLink(self, request : LinkId, context : grpc.ServicerContext) -> Empty: + return optical_link_delete(self.db_engine, self.messagebroker, request) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def DeleteServiceConfigRule(self, request : ServiceConfigRule, context : grpc.ServicerContext) -> Empty: + return delete_config_rule(self.db_engine, request) diff --git a/src/context/service/database/ConfigRule.py b/src/context/service/database/ConfigRule.py index 7d816b3e87803f71678511f4fadc6bbe7eba548e..0201d2672e0cd47f208e7569f9d34eae6e4601a8 100644 --- a/src/context/service/database/ConfigRule.py +++ b/src/context/service/database/ConfigRule.py @@ -16,15 +16,18 @@ import datetime, json, logging from sqlalchemy import delete #from sqlalchemy.dialects import postgresql from sqlalchemy.dialects.postgresql import insert +from sqlalchemy.engine import Engine from sqlalchemy.orm import Session from typing import Dict, List, Optional, Set -from common.proto.context_pb2 import ConfigRule +from common.proto.context_pb2 import ConfigRule, ServiceConfigRule, Empty from common.tools.grpc.Tools import grpc_message_to_json_string from .models.enums.ConfigAction import ORM_ConfigActionEnum, grpc_to_enum__config_action from .models.ConfigRuleModel import ( ConfigRuleKindEnum, DeviceConfigRuleModel, ServiceConfigRuleModel, SliceConfigRuleModel) from .uuids._Builder import get_uuid_from_string from .uuids.EndPoint import endpoint_get_uuid +from sqlalchemy_cockroachdb import run_transaction +from sqlalchemy.orm import Session, sessionmaker LOGGER = logging.getLogger(__name__) @@ -149,3 +152,16 @@ def upsert_config_rules( upsert_affected = any([(updated_at > created_at) for created_at,updated_at in configrule_updates]) return delete_affected or upsert_affected + + +def delete_config_rule(db_engine : Engine, request : ServiceConfigRule): + config_rule = request.configrule_custom + service_id = request.service_id + parent_uuid = service_id.service_uuid.uuid + configrule_name = 'service:custom:{:s}'.format( config_rule.resource_key) + configrule_uuid = get_uuid_from_string(configrule_name, prefix_for_name=parent_uuid) + def callback(session : Session) -> bool: + num_deleted = session.query(ServiceConfigRuleModel).filter_by(configrule_uuid=configrule_uuid).delete() + return num_deleted > 0 + deleted = run_transaction(sessionmaker(bind=db_engine), callback) + return Empty() diff --git a/src/context/service/database/Device.py b/src/context/service/database/Device.py index beeae59c5967723f2cccfa365fca67dd3acd0096..4713b8e0744df39e6d9227e02f909571bd159a37 100644 --- a/src/context/service/database/Device.py +++ b/src/context/service/database/Device.py @@ -106,6 +106,7 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi topology_uuids.add(topology_uuid) is_oc_driver = DeviceDriverEnum.DEVICEDRIVER_OC in set(request.device_drivers) + #optical_endpoints_data : List[Dict] = list() endpoints_data : List[Dict] = list() for i, endpoint in enumerate(request.device_endpoints): @@ -136,6 +137,18 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi 'created_at' : now, 'updated_at' : now, }) + # # ------------------- Experimental ----------------------- + + # if is_oc_driver: + + # optical_endpoints_data.append({ + # 'endpoint_uuid' : endpoint_uuid, + # 'device_uuid' : endpoint_device_uuid, + # 'name' : endpoint_name, + # 'endpoint_type' : endpoint.endpoint_type, + # 'created_at' : now, + # 'updated_at' : now, + # }) if endpoint_topology_uuid not in topology_uuids: related_topologies.append({ @@ -191,6 +204,23 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi stmt = stmt.returning(EndPointModel.created_at, EndPointModel.updated_at) endpoint_updates = session.execute(stmt).fetchall() updated_endpoints = any([(updated_at > created_at) for created_at,updated_at in endpoint_updates]) + + #---------------------- Experimental --------------------------------- + + # if len(optical_endpoints_data) > 0: + # LOGGER.info(f"Optical endpoint data_ device_model {optical_endpoints_data}") + # stmt = insert(OpticalEndPointModel).values(optical_endpoints_data) + # stmt = stmt.on_conflict_do_update( + # index_elements=[OpticalEndPointModel.endpoint_uuid], + # set_=dict( + # name = stmt.excluded.name, + # endpoint_type = stmt.excluded.endpoint_type, + # updated_at = stmt.excluded.updated_at, + # ) + # ) + # stmt = stmt.returning(OpticalEndPointModel.created_at, OpticalEndPointModel.updated_at) + # optical_endpoint_updates = session.execute(stmt).fetchall() + # updated_optical_endpoints = any([(updated_at > created_at) for created_at,updated_at in endpoint_updates]) device_topology_ids = [] if not updated or len(related_topologies) > 1: diff --git a/src/context/service/database/Events.py b/src/context/service/database/Events.py index a88a4656a8cf078d2b90fe3a0c0ea22a4ec15a75..46688775eaabd5ab428ff9f0e77de52d25c9af41 100644 --- a/src/context/service/database/Events.py +++ b/src/context/service/database/Events.py @@ -17,27 +17,32 @@ from typing import Dict, Iterator, Set from common.message_broker.Message import Message from common.message_broker.MessageBroker import MessageBroker from common.proto.context_pb2 import ( - ConnectionEvent, ContextEvent, DeviceEvent, EventTypeEnum, LinkEvent, ServiceEvent, SliceEvent, TopologyEvent) + ConnectionEvent, ContextEvent, DeviceEvent, EventTypeEnum, LinkEvent, + ServiceEvent, SliceEvent, TopologyEvent, OpticalConfigEvent +) class EventTopicEnum(enum.Enum): - CONNECTION = 'connection' - CONTEXT = 'context' - DEVICE = 'device' - LINK = 'link' - POLICY_RULE = 'policy-rule' - SERVICE = 'service' - SLICE = 'slice' - TOPOLOGY = 'topology' + CONNECTION = 'connection' + CONTEXT = 'context' + DEVICE = 'device' + LINK = 'link' + POLICY_RULE = 'policy-rule' + SERVICE = 'service' + SLICE = 'slice' + TOPOLOGY = 'topology' + OPTICALCONFIG = 'optical-config' + TOPIC_TO_EVENTCLASS = { - EventTopicEnum.CONNECTION.value : ConnectionEvent, - EventTopicEnum.CONTEXT.value : ContextEvent, - EventTopicEnum.DEVICE.value : DeviceEvent, - EventTopicEnum.LINK.value : LinkEvent, - #EventTopicEnum.POLICY_RULE.value : PolicyRuleEvent, # Not defined in proto files - EventTopicEnum.SERVICE.value : ServiceEvent, - EventTopicEnum.SLICE.value : SliceEvent, - EventTopicEnum.TOPOLOGY.value : TopologyEvent, + EventTopicEnum.CONNECTION.value : ConnectionEvent, + EventTopicEnum.CONTEXT.value : ContextEvent, + EventTopicEnum.DEVICE.value : DeviceEvent, + EventTopicEnum.LINK.value : LinkEvent, + #EventTopicEnum.POLICY_RULE.value : PolicyRuleEvent, # Not defined in proto files + EventTopicEnum.SERVICE.value : ServiceEvent, + EventTopicEnum.SLICE.value : SliceEvent, + EventTopicEnum.TOPOLOGY.value : TopologyEvent, + EventTopicEnum.OPTICALCONFIG.value : OpticalConfigEvent, } CONSUME_TIMEOUT = 0.5 # seconds @@ -61,6 +66,9 @@ def notify_event_topology(messagebroker : MessageBroker, event_type : EventTypeE def notify_event_device(messagebroker : MessageBroker, event_type : EventTypeEnum, device_id : Dict) -> None: notify_event(messagebroker, EventTopicEnum.DEVICE, event_type, {'device_id': device_id}) +def notify_event_opticalconfig(messagebroker : MessageBroker, event_type : EventTypeEnum, opticalconfig_id : Dict) -> None: + notify_event(messagebroker, EventTopicEnum.DEVICE, event_type, {'opticalconfig_id': opticalconfig_id}) + def notify_event_link(messagebroker : MessageBroker, event_type : EventTypeEnum, link_id : Dict) -> None: notify_event(messagebroker, EventTopicEnum.LINK, event_type, {'link_id': link_id}) diff --git a/src/context/service/database/OpticalConfig.py b/src/context/service/database/OpticalConfig.py index 663c3bd0b16ac8af20cb1acf9176764d719b3046..ad38751eef9c73b734c13feeeabbc3329d58df0d 100644 --- a/src/context/service/database/OpticalConfig.py +++ b/src/context/service/database/OpticalConfig.py @@ -14,11 +14,19 @@ import json, logging from sqlalchemy.dialects.postgresql import insert +from common.message_broker.MessageBroker import MessageBroker +from common.DeviceTypes import DeviceTypeEnum from sqlalchemy.engine import Engine from sqlalchemy.orm import Session, sessionmaker from sqlalchemy_cockroachdb import run_transaction -from common.proto.context_pb2 import OpticalConfig, OpticalConfigId -from .models.OpticalConfigModel import OpticalConfigModel +from common.proto.context_pb2 import OpticalConfig, OpticalConfigId, Empty, EventTypeEnum +from .models.OpticalConfig.OpticalConfigModel import OpticalConfigModel +from .models.OpticalConfig.TransponderModel import TransponderTypeModel, OpticalChannelModel +from .models.OpticalConfig.RoadmModel import RoadmTypeModel, ChannelModel +from .uuids.OpticalConfig import ( + channel_get_uuid, opticalconfig_get_uuid, transponder_get_uuid, roadm_get_uuid +) +from .Events import notify_event_opticalconfig LOGGER = logging.getLogger(__name__) @@ -28,8 +36,10 @@ def get_opticalconfig(db_engine : Engine): results = session.query(OpticalConfigModel).all() for obj in results: optical_config = OpticalConfig() - optical_config.config = json.dump(obj.config) - optical_config.opticalconfig_id.opticalconfig_uuid = obj.opticalconfig_uuid + optical_config.config = json.dumps(obj.dump()) + ids_obj = obj.dump_id() + optical_config.opticalconfig_id.opticalconfig_uuid = ids_obj["opticalconfig_uuid"] + optical_config.device_id.device_uuid.uuid=ids_obj["device_uuid"] optical_configs.append(optical_config) return optical_configs obj = run_transaction(sessionmaker(bind=db_engine), callback) @@ -37,33 +47,323 @@ def get_opticalconfig(db_engine : Engine): def set_opticalconfig(db_engine : Engine, request : OpticalConfig): opticalconfig_id = OpticalConfigId() - opticalconfig_id.opticalconfig_uuid = request.opticalconfig_id.opticalconfig_uuid - my_config_data = [] + device_id = request.device_id + device_uuid = request.device_id.device_uuid.uuid + channels = [] + transponder = [] + roadms = [] + channel_namespace = None + OpticalConfig_data = [] + config_type=None + #is_transpondre=False + opticalconfig_uuid = opticalconfig_get_uuid(device_id) + if request.config: - channels = [] - transceivers = [] config = json.loads(request.config) - if 'channels' in config and len(config['channels']) > 0: - channels = [channel['name']['index'] for channel in config['channels']] - if 'transceivers' in config and len(config['transceivers']['transceiver']) > 0: - transceivers = [transceiver for transceiver in config['transceivers']['transceiver']] - - my_config_data = [ - { - "opticalconfig_uuid": request.opticalconfig_id.opticalconfig_uuid, - "channels" : channels, - "transcievers" : transceivers, - "interfaces" : json.dumps(config["interfaces"]["interface"]), - "channel_namespace" : config["channel_namespace"], - "endpoints" : [json.dumps(endpoint) for endpoint in config["endpoints"]], - "frequency" : config["frequency"] if "frequency" in config else 0, - "operational_mode" : config["operational_mode"] if "operational_mode" in config else 0, - "output_power" : config["output_power"] if "output_power" in config else '', - } - ] + if 'channel_namespace' in config: + channel_namespace=config['channel_namespace'] + if "type" in config: + config_type= config["type"] + if config_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + is_transpondre = True + transceivers = [] + if channel_namespace is None and 'channel_namespace' in config: + channel_namespace=config['channel_namespace'] + if 'transceivers' in config and len(config['transceivers']['transceiver']) > 0: + transceivers = [transceiver for transceiver in config ['transceivers']['transceiver']] + if 'channels' in config and len(config['channels']) > 0: + #channels = [channel['name']['index'] for channel in config['channels']] + for channel_params in config['channels']: + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "transponder_uuid" : transponder_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(channel_params['name']['index'],device_uuid), + "channel_name" : channel_params['name']['index'], + "frequency" : int(channel_params["frequency"]) if "frequency" in channel_params else 0, + "operational_mode" : int(channel_params["operational-mode"]) if "operational-mode" in channel_params else 0, + "target_output_power": channel_params["target-output-power"] if "target-output-power" in channel_params else '', + "status" : channel_params["status"] if "status" in channel_params else "" + }) + + transponder.append({ + "transponder_uuid" : transponder_get_uuid(device_id), + "transcievers" : transceivers, + "interfaces" : None, + "opticalconfig_uuid": opticalconfig_uuid, + }) + + if config_type == DeviceTypeEnum.OPTICAL_ROADM._value_: + if channel_namespace is None and 'channel_namespace' in config: + channel_namespace=config['channel_namespace'] + if 'media_channels' in config and len(config['media_channels']) > 0: + #channels = [channel['name']['index'] for channel in config['channels']] + channel_num = 0 + for channel_params in config['media_channels']: + channel_index = channel_params['channel_index'] if channel_params['channel_index'] is not None else None + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "roadm_uuid" : roadm_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(f'media_channel_{channel_index}',device_uuid), + "band_name" : channel_params['band_name'], + "lower_frequency" : int(channel_params["lower_frequency"]) if "lower_frequency" in channel_params else 0, + "upper_frequency" : int(channel_params["upper_frequency"]) if "upper_frequency" in channel_params else 0, + "dest_port" : channel_params["dest_port"] if "dest_port" in channel_params else '', + "src_port" : channel_params["src_port"] if "src_port" in channel_params else '', + "status" : channel_params["status"] if "status" in channel_params else "", + "type" : 'media_channel', + "optical_band_parent" : str(channel_params['optical_band_parent']) if 'optical_band_parent' in channel_params else None, + "channel_index" : channel_index if channel_index is not None else None, + }) + if 'optical_bands' in config and len(config['optical_bands']) > 0: + #channels = [channel['name']['index'] for channel in config['channels']] + channel_num = 0 + for channel_params in config['optical_bands']: + channel_num += 1 + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "roadm_uuid" : roadm_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(f'optical_bands_{channel_num}',device_uuid), + "band_name" : channel_params['band_name'], + "lower_frequency" : int(channel_params["lower_frequency"]) if "lower_frequency" in channel_params else 0, + "upper_frequency" : int(channel_params["upper_frequency"]) if "upper_frequency" in channel_params else 0, + "dest_port" : channel_params["dest_port"] if "dest_port" in channel_params else '', + "src_port" : channel_params["src_port"] if "src_port" in channel_params else '', + "status" : channel_params["status"] if "status" in channel_params else "", + "type" : 'optical_band', + "channel_index" : channel_params['channel_index'] if 'channel_index' in channel_params else None, + "optical_band_parent": None + }) + + roadms.append({ + "roadm_uuid" : roadm_get_uuid(device_id), + "opticalconfig_uuid" : opticalconfig_uuid, + }) + + OpticalConfig_data.append({ + "opticalconfig_uuid" : opticalconfig_uuid, + # "transcievers" : transceivers, + # "interfaces" :"", + "channel_namespace" : channel_namespace , + "endpoints" : [json.dumps(endpoint) for endpoint in config.get("endpoints",[])], + "device_uuid": device_uuid, + "type":config_type + }) + + def callback(session:Session)->bool: + stmt = insert(OpticalConfigModel).values(OpticalConfig_data) + stmt = stmt.on_conflict_do_update( + index_elements=[OpticalConfigModel.opticalconfig_uuid], + set_=dict( + channel_namespace=stmt.excluded.channel_namespace + ) + ) + stmt = stmt.returning(OpticalConfigModel.opticalconfig_uuid) + opticalconfig_id = session.execute(stmt).fetchone() + if config_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + if (len(transponder)>0): + stmt = insert(TransponderTypeModel).values(transponder) + stmt = stmt.on_conflict_do_update( + index_elements=[TransponderTypeModel.transponder_uuid], + set_=dict( + transcievers= stmt.excluded.transcievers , + ) + + ) + stmt = stmt.returning(TransponderTypeModel.transponder_uuid) + transponder_id = session.execute(stmt).fetchone() + + if (len(channels) > 0): + stmt = insert(OpticalChannelModel).values(channels) + stmt = stmt.on_conflict_do_update( + index_elements=[OpticalChannelModel.channel_uuid], + set_=dict( + channel_name= stmt.excluded.channel_name , + frequency = stmt.excluded.frequency, + operational_mode=stmt.excluded.operational_mode, + target_output_power=stmt.excluded.target_output_power, + ) + ) + stmt = stmt.returning(OpticalChannelModel.channel_uuid) + opticalChannel_id = session.execute(stmt).fetchone() + + if config_type == DeviceTypeEnum.OPTICAL_ROADM._value_: + if len(roadms) > 0: + stmt = insert(RoadmTypeModel).values(roadms) + stmt = stmt.on_conflict_do_update( + index_elements=[RoadmTypeModel.roadm_uuid], + set_=dict( + circuits=stmt.excluded.circuits + ) + ) + stmt = stmt.returning(RoadmTypeModel.roadm_uuid) + roadm_id = session.execute(stmt).fetchone() + + if (channels is not None and len(channels) > 0): + stmt = insert(ChannelModel).values(channels) + stmt = stmt.on_conflict_do_update( + index_elements=[ChannelModel.channel_uuid ], + set_=dict( + band_name = stmt.excluded.band_name , + lower_frequency = stmt.excluded.lower_frequency, + upper_frequency = stmt.excluded.upper_frequency, + type = stmt.excluded.type, + status = stmt.excluded.status, + dest_port = stmt.excluded.dest_port, + src_port = stmt.excluded.src_port, + channel_index = stmt.excluded.channel_index, + optical_band_parent = stmt.excluded.optical_band_parent + ) + ) + stmt = stmt.returning(ChannelModel.channel_uuid) + opticalChannel_id = session.execute(stmt).fetchone() + + opticalconfig_id = run_transaction(sessionmaker(bind=db_engine), callback) + return {'opticalconfig_uuid': opticalconfig_id} + +def update_opticalconfig(db_engine : Engine, request : OpticalConfig): + opticalconfig_id = OpticalConfigId() + device_id = request.device_id + device_uuid = request.device_id.device_uuid.uuid + channels = [] + transponder=[] + roadms=[] + channel_namespace= None + OpticalConfig_data = [] + config_type=None + #is_transpondre=False + opticalconfig_uuid =opticalconfig_get_uuid(device_id) + + if request.config : + config = json.loads(request.config) + + if 'new_config' in config: + if 'type' in config: + config_type = config['type'] + if "type" in config['new_config'] and config_type is None: + config_type = config['new_config']["type"] + if 'channel_namespace' in config['new_config']: + channel_namespace = config['new_config'] ['channel_namespace'] + + if config_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + is_transpondre = True + transceivers = [] + if channel_namespace is None and 'channel_namespace' in config: + channel_namespace=config['channel_namespace'] + + if 'transceivers' in config['new_config'] and len(config['new_config']['transceivers']['transceiver']) > 0: + transceivers = [transceiver for transceiver in config['new_config'] ['transceivers']['transceiver']] + + if 'channels' in config['new_config'] and len(config['new_config']['channels']) > 0: + #channels = [channel['name']['index'] for channel in config['channels']] + + for channel_params in config['new_config']['channels']: + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "transponder_uuid" : transponder_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(channel_params['name']['index'],device_uuid), + "channel_name" : channel_params['name']['index'], + "frequency" : int(channel_params["frequency"]) if "frequency" in channel_params else 0, + "operational_mode" : int(channel_params["operational-mode"]) if "operational-mode" in channel_params else 0, + "target_output_power" : channel_params["target-output-power"] if "target-output-power" in channel_params else '', + "status" : channel_params["status"] if "status" in channel_params else "" + }) + elif 'flow_handled' in config and 'new_config' in config : + target_config = config['new_config'] + dest_pair = None + src = None + dst = None + src_pair = config['flow_handled'][0] + + src, dst = src_pair + if src_pair is None and len(config['flow_handled'])>1 : + dest_pair = config['flow_handled'][1] + src, dst = dest_pair + channel_index = src if src is not None and src !='0' else dst + channel_name = f"channel-{channel_index}" + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "transponder_uuid" : transponder_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(channel_name,device_uuid), + "channel_name" : channel_name, + "frequency" : int(target_config["frequency"]) if "frequency" in target_config else 0, + "operational_mode" : int(target_config["operational-mode"]) if "operational-mode" in target_config else 0, + "target_output_power" : target_config["target-output-power"] if "target-output-power" in target_config else '', + "status" : target_config["status"] if "status" in target_config else "" + }) + + transponder.append({ + "transponder_uuid" : transponder_get_uuid(device_id), + "transcievers" : transceivers, + "interfaces" : None, + "opticalconfig_uuid": opticalconfig_uuid, + }) + + if config_type == DeviceTypeEnum.OPTICAL_ROADM._value_: + if channel_namespace is None and 'channel_namespace' in config['new_config']: + channel_namespace=config['new_config']['channel_namespace'] + if 'is_opticalband' in config and not config['is_opticalband']: + #channels = [channel['name']['index'] for channel in config['channels']] + if 'flow_handled' in config and len(config['flow_handled'])>0 : + num = 0 + flow_id = config["new_config"]["flow_id"] if 'flow_id' in config['new_config'] else None + for flow in config['flow_handled']: + src_port, dest_port = flow + channel_index = flow_id + num + num += 1 + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "roadm_uuid" : roadm_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(f'media_channel_{channel_index}',device_uuid), + "band_name" : config['new_config']['band_type'], + "lower_frequency" : int(int(config['new_config']['frequency']) - (int(config['new_config']['band'])/2)) if "frequency" in config['new_config'] else 0, + "upper_frequency" : int(int(config['new_config']['frequency']) + (int(config['new_config']['band'])/2)) if "frequency" in config['new_config'] else 0, + "dest_port" : dest_port, + "src_port" : src_port, + "status" : config['new_config']["status"] if "status" in config['new_config'] else "", + "type" : 'media_channel', + "optical_band_parent" : str( config['new_config']['ob_id']) if 'ob_id' in config['new_config'] else None, + "channel_index" : str(channel_index) if channel_index is not None else None + }) + if 'is_opticalband' in config and config['is_opticalband']: + #channels = [channel['name']['index'] for channel in config['channels']] + if 'flow_handled' in config and len(config['flow_handled']) > 0: + ob_id = config['new_config']['ob_id'] if 'ob_id' in config['new_config'] else None + num = 0 + for flow in config['flow_handled']: + src_port, dest_port = flow + channel_index = ob_id + num + num += 1 + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "roadm_uuid" : roadm_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(f'optical_bands_{channel_index}',device_uuid), + "band_name" : config['new_config']['band_type'], + "lower_frequency" : int(config['new_config']["low-freq"]) if "low-freq" in config['new_config'] else 0, + "upper_frequency" : int(config['new_config']["up-freq"]) if "up-freq" in config['new_config'] else 0, + "dest_port" : dest_port, + "src_port" : src_port, + "status" : config['new_config']["status"] if "status" in config['new_config'] else "", + "type" : 'optical_band', + "channel_index" : str( channel_index) if channel_index is not None else None + }) + + roadms.append({ + "roadm_uuid" : roadm_get_uuid(device_id), + "opticalconfig_uuid": opticalconfig_uuid, + }) + + OpticalConfig_data.append({ + "opticalconfig_uuid": opticalconfig_uuid, + # "transcievers" : transceivers, + # "interfaces" :"", + "channel_namespace" : channel_namespace , + "endpoints" : [json.dumps(endpoint) for endpoint in config['new_config'].get("endpoints",[])], + "device_uuid" : device_uuid, + "type" : config_type + }) def callback(session:Session)->bool: - stmt = insert(OpticalConfigModel).values(my_config_data) + stmt = insert(OpticalConfigModel).values(OpticalConfig_data) stmt = stmt.on_conflict_do_update( index_elements=[OpticalConfigModel.opticalconfig_uuid], set_=dict( @@ -71,11 +371,66 @@ def set_opticalconfig(db_engine : Engine, request : OpticalConfig): ) ) stmt = stmt.returning(OpticalConfigModel.opticalconfig_uuid) - id = session.execute(stmt).fetchone() + opticalconfig_id = session.execute(stmt).fetchone() + if config_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + if (len(transponder)>0): + stmt = insert(TransponderTypeModel).values(transponder) + stmt = stmt.on_conflict_do_update( + index_elements=[TransponderTypeModel.transponder_uuid], + set_=dict( + transcievers= stmt.excluded.transcievers, + ) + ) + stmt = stmt.returning(TransponderTypeModel.transponder_uuid) + transponder_id = session.execute(stmt).fetchone() + + if len(channels) > 0: + stmt = insert(OpticalChannelModel).values(channels) + stmt = stmt.on_conflict_do_update( + index_elements=[OpticalChannelModel.channel_uuid ], + set_=dict( + channel_name= stmt.excluded.channel_name , + frequency = stmt.excluded.frequency, + operational_mode=stmt.excluded.operational_mode, + target_output_power=stmt.excluded.target_output_power, + status = stmt.excluded.status, + ) + ) + stmt = stmt.returning(OpticalChannelModel.channel_uuid) + opticalChannel_id = session.execute(stmt).fetchone() + if config_type == DeviceTypeEnum.OPTICAL_ROADM._value_: + if len(roadms) > 0: + stmt = insert(RoadmTypeModel).values(roadms) + stmt = stmt.on_conflict_do_update( + index_elements=[RoadmTypeModel.roadm_uuid], + set_=dict( + circuits=stmt.excluded.circuits + ) + ) + stmt = stmt.returning(RoadmTypeModel.roadm_uuid) + roadm_id = session.execute(stmt).fetchone() + + if (channels is not None and len(channels) > 0): + stmt = insert(ChannelModel).values(channels) + stmt = stmt.on_conflict_do_update( + index_elements=[ChannelModel.channel_uuid ], + set_=dict( + band_name= stmt.excluded.band_name , + lower_frequency = stmt.excluded.lower_frequency, + upper_frequency = stmt.excluded.upper_frequency, + type=stmt.excluded.type, + status=stmt.excluded.status, + dest_port=stmt.excluded.dest_port, + src_port=stmt.excluded.src_port, + ) + ) + stmt = stmt.returning(ChannelModel.channel_uuid) + opticalChannel_id = session.execute(stmt).fetchone() + opticalconfig_id = run_transaction(sessionmaker(bind=db_engine), callback) return {'opticalconfig_uuid': opticalconfig_id} -def select_opticalconfig(db_engine:Engine,request:OpticalConfigId): +def select_opticalconfig(db_engine : Engine, request : OpticalConfigId): def callback(session : Session) -> OpticalConfig: result = OpticalConfig() stmt = session.query(OpticalConfigModel) @@ -83,6 +438,102 @@ def select_opticalconfig(db_engine:Engine,request:OpticalConfigId): obj = stmt.first() if obj is not None: result.config = json.dumps(obj.dump()) - result.opticalconfig_id.opticalconfig_uuid = obj.opticalconfig_uuid + ids_obj = obj.dump_id() + result.opticalconfig_id.opticalconfig_uuid = ids_obj["opticalconfig_uuid"] + result.device_id.device_uuid.uuid=ids_obj["device_uuid"] return result return run_transaction(sessionmaker(bind=db_engine, expire_on_commit=False), callback) + +def delete_opticalconfig(db_engine : Engine, messagebroker : MessageBroker, request : OpticalConfigId): + opticalconfig_uuid = request.opticalconfig_uuid + def callback(session : Session): + #query = session.query(OpticalConfigModel) + num_deleted = session.query(OpticalConfigModel).filter_by(opticalconfig_uuid=opticalconfig_uuid).delete() + return num_deleted > 0 + deleted = run_transaction(sessionmaker(bind=db_engine), callback) + if deleted: + notify_event_opticalconfig(messagebroker, EventTypeEnum.EVENTTYPE_REMOVE, opticalconfig_uuid) + return Empty() + +def delete_opticalchannel(db_engine : Engine, messagebroker : MessageBroker, request : OpticalConfig): + config = json.loads(request.config) + device_id = request.device_id + device_uuid = request.device_id.device_uuid.uuid + opticalconfig_uuid = request.opticalconfig_id.opticalconfig_uuid + channels = [] + config_type = None + + if "type" in config : + config_type= config["type"] + if 'new_config' in config: + if config_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + for flow in config['flow']: + src,dest = flow + channel_index= src if src is not None and src!='0' else dest + channel_name= f"channel-{channel_index}" + channels.append({ + # "opticalconfig_uuid":opticalconfig_uuid, + "transponder_uuid" : transponder_get_uuid(device_id), + "channel_uuid" : channel_get_uuid(channel_name ,device_uuid), + "channel_name" : channel_name , + "frequency" : 0, + "operational_mode" : None, + "target_output_power": None, + "status" : "DISABLED" + }) + elif config_type == DeviceTypeEnum.OPTICAL_ROADM._value_: + channel_num = 0 + if 'flow' in config : + if 'is_opticalband' in config: + if config['is_opticalband']: + ob_id = config['new_config']['ob_id'] if 'ob_id' in config['new_config'] else None + if len(config['flow']) == 0: + channel_index = ob_id + channel_num + channel_name = f'optical_bands_{channel_index}' + channels.append(channel_get_uuid(channel_name, device_uuid)) + else: + for flow in config['flow']: + channel_index = ob_id+channel_num + channel_num +=1 + channel_name = f'optical_bands_{channel_index}' + channels.append(channel_get_uuid(channel_name, device_uuid)) + else: + if config['flow'] == 0: + channel_num = 1 + channel_name = f'media_channel_{channel_num}' + channels.append(channel_get_uuid(channel_name, device_uuid)) + else: + for flow in config['flow']: + channel_num += 1 + channel_name = f'media_channel_{channel_num}' + channels.append(channel_get_uuid(channel_name, device_uuid)) + + def callback(session : Session): + all_suceed = [] + if config_type == DeviceTypeEnum.OPTICAL_ROADM._value_: + for channel_uuid in channels: + num_deleted = session.query(ChannelModel).filter_by(channel_uuid=channel_uuid).delete() + all_suceed.append(num_deleted > 0) + elif config_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + if len(channels) > 0: + stmt = insert(OpticalChannelModel).values(channels) + stmt = stmt.on_conflict_do_update( + index_elements=[OpticalChannelModel.channel_uuid ], + set_=dict( + channel_name= stmt.excluded.channel_name , + frequency = stmt.excluded.frequency, + operational_mode=stmt.excluded.operational_mode, + target_output_power=stmt.excluded.target_output_power, + status=stmt.excluded.status + ) + ) + stmt = stmt.returning(OpticalChannelModel.channel_uuid) + opticalChannel_id = session.execute(stmt).fetchone() + all_suceed.append(True) + return all_suceed + + all_deleted = run_transaction(sessionmaker(bind=db_engine), callback) + for stat in all_deleted: + if not stat: return + notify_event_opticalconfig(messagebroker, EventTypeEnum.EVENTTYPE_REMOVE, opticalconfig_uuid) + return Empty() diff --git a/src/context/service/database/OpticalLink.py b/src/context/service/database/OpticalLink.py new file mode 100644 index 0000000000000000000000000000000000000000..93f43ef34497cb353f50a9b001da8ec4a6f5f92f --- /dev/null +++ b/src/context/service/database/OpticalLink.py @@ -0,0 +1,183 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 datetime, logging +from sqlalchemy.dialects.postgresql import insert +from sqlalchemy.engine import Engine +from sqlalchemy.orm import Session, selectinload, sessionmaker +from sqlalchemy_cockroachdb import run_transaction +from typing import Dict, List, Optional, Set, Tuple +from common.proto.context_pb2 import ( + Empty, EventTypeEnum, OpticalLink, LinkId, OpticalLinkList, TopologyId +) +from common.message_broker.MessageBroker import MessageBroker +from common.method_wrappers.ServiceExceptions import NotFoundException +from common.tools.object_factory.Link import json_link_id +from .models.OpticalLinkModel import OpticalLinkModel,OpticalLinkEndPointModel +from .models.TopologyModel import TopologyOpticalLinkModel, TopologyModel +from .uuids.EndPoint import endpoint_get_uuid +from .uuids.Link import link_get_uuid +from .uuids.Topology import topology_get_uuid +from .Events import notify_event_link + +LOGGER = logging.getLogger(__name__) + + +def optical_link_list_objs(db_engine : Engine) -> OpticalLinkList: + def callback(session : Session) -> List[Dict]: + obj_list : List[OpticalLinkModel] = session.query(OpticalLinkModel)\ + .options(selectinload(OpticalLinkModel.opticallink_endpoints))\ + .all() + return [obj.dump() for obj in obj_list] + links = run_transaction(sessionmaker(bind=db_engine), callback) + return OpticalLinkList(optical_links=links) + +def optical_link_get(db_engine : Engine, request : LinkId) -> OpticalLink: + link_uuid = link_get_uuid(request, allow_random=False) + def callback(session : Session) -> Optional[Dict]: + obj : Optional[OpticalLinkModel] = session.query(OpticalLinkModel)\ + .options(selectinload(OpticalLinkModel.opticallink_endpoints))\ + .filter_by(opticallink_uuid=link_uuid).one_or_none() + return None if obj is None else obj.dump() + obj = run_transaction(sessionmaker(bind=db_engine), callback) + if obj is None: + raw_link_uuid = request.link_uuid.uuid + raise NotFoundException('Optical Link', raw_link_uuid, extra_details=[ + 'link_uuid generated was: {:s}'.format(link_uuid) + ]) + return OpticalLink(**obj) + +def optical_link_set(db_engine : Engine, messagebroker : MessageBroker, request : OpticalLink) -> LinkId: + raw_link_uuid = request.link_id.link_uuid.uuid + raw_link_name = request.name + link_name = raw_link_uuid if len(raw_link_name) == 0 else raw_link_name + link_uuid = link_get_uuid(request.link_id, link_name=link_name, allow_random=True) + + now = datetime.datetime.utcnow() + + # By default, always add link to default Context/Topology + topology_uuids : Set[str] = set() + related_topologies : List[Dict] = list() + _,topology_uuid = topology_get_uuid(TopologyId(), allow_random=False, allow_default=True) + related_topologies.append({ + 'topology_uuid': topology_uuid, + 'optical_link_uuid' : link_uuid, + }) + topology_uuids.add(topology_uuid) + + link_endpoints_data : List[Dict] = list() + + for i,endpoint_id in enumerate(request.link_endpoint_ids): + endpoint_topology_uuid, endpoint_device_uuid, endpoint_uuid = endpoint_get_uuid( + endpoint_id, endpoint_name="", allow_random=True) + + link_endpoints_data.append({ + 'link_uuid' : link_uuid, + 'endpoint_uuid': endpoint_uuid, + + }) + + if endpoint_topology_uuid not in topology_uuids: + related_topologies.append({ + 'topology_uuid': endpoint_topology_uuid, + 'optical_link_uuid' : link_uuid, + }) + topology_uuids.add(endpoint_topology_uuid) + + optical_link_data = [{ + 'opticallink_uuid' : link_uuid, + 'name' : link_name, + 'created_at' : now, + 'updated_at' : now, + 'length' : request.optical_details.length, + "src_port" : request.optical_details.src_port, + "dst_port" : request.optical_details.dst_port, + "local_peer_port" : request.optical_details.local_peer_port, + "remote_peer_port" : request.optical_details.remote_peer_port, + "used" : request.optical_details.used, + "c_slots" : request.optical_details.c_slots , + "l_slots" : request.optical_details.l_slots, + "s_slots" : request.optical_details.s_slots, + }] + + def callback(session : Session) -> Tuple[bool, List[Dict]]: + stmt = insert(OpticalLinkModel).values(optical_link_data) + stmt = stmt.on_conflict_do_update( + index_elements=[OpticalLinkModel.opticallink_uuid], + set_=dict( + updated_at = stmt.excluded.updated_at, + src_port = stmt.excluded.src_port, + dst_port = stmt.excluded.dst_port, + local_peer_port = stmt.excluded.local_peer_port, + remote_peer_port = stmt.excluded.remote_peer_port, + used = stmt.excluded.used , + c_slots = stmt.excluded.c_slots, + l_slots = stmt.excluded.l_slots, + s_slots = stmt.excluded.s_slots + ) + ) + stmt = stmt.returning(OpticalLinkModel.created_at, OpticalLinkModel.updated_at) + created_at,updated_at = session.execute(stmt).fetchone() + updated = updated_at > created_at + + updated_endpoints = False + if len(link_endpoints_data) > 0: + stmt = insert(OpticalLinkEndPointModel).values(link_endpoints_data) + stmt = stmt.on_conflict_do_nothing( + index_elements=[OpticalLinkEndPointModel.link_uuid, OpticalLinkEndPointModel.endpoint_uuid] + ) + link_endpoint_inserts = session.execute(stmt) + updated_endpoints = int(link_endpoint_inserts.rowcount) > 0 + + if not updated or len(related_topologies) > 1: + # Only update topology-link relations when link is created (not updated) or when endpoint_ids are + # modified (len(related_topologies) > 1). + stmt = insert(TopologyOpticalLinkModel).values(related_topologies) + stmt = stmt.on_conflict_do_nothing( + index_elements=[TopologyOpticalLinkModel.topology_uuid, TopologyOpticalLinkModel.optical_link_uuid] + ) + stmt = stmt.returning(TopologyOpticalLinkModel.topology_uuid) + topology_uuids = session.execute(stmt).fetchall() + + #LOGGER.warning('RAW topology_uuids={:s}'.format(str(topology_uuids))) + if len(topology_uuids) > 0: + topology_uuids = [topology_uuid[0] for topology_uuid in topology_uuids] + #LOGGER.warning('NEW topology_uuids={:s}'.format(str(topology_uuids))) + query = session.query(TopologyModel) + query = query.filter(TopologyModel.topology_uuid.in_(topology_uuids)) + link_topologies : List[TopologyModel] = query.all() + link_topology_ids = [obj.dump_id() for obj in link_topologies] + #LOGGER.warning('link_topology_ids={:s}'.format(str(link_topology_ids))) + return updated or updated_endpoints + + updated = run_transaction(sessionmaker(bind=db_engine), callback ) + link_id = json_link_id(link_uuid) + event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE + notify_event_link(messagebroker, event_type, link_id) + + return LinkId(**link_id) + +def optical_link_delete(db_engine : Engine, messagebroker : MessageBroker, request : LinkId) -> Empty: + link_uuid = link_get_uuid(request, allow_random=False) + + def callback(session : Session) -> bool: + num_deleted = session.query(OpticalLinkModel).filter_by(opticallink_uuid=link_uuid).delete() + return num_deleted > 0 + deleted = run_transaction(sessionmaker(bind=db_engine), callback) + + link_id = json_link_id(link_uuid) + if deleted: + notify_event_link(messagebroker, EventTypeEnum.EVENTTYPE_REMOVE, link_id) + + return Empty() diff --git a/src/context/service/database/Topology.py b/src/context/service/database/Topology.py index e1c59ea118915e2ad0d69d4b8cacf59c354b8297..7dc1b60f977fb4447fa86a47a48d0335270c8f1a 100644 --- a/src/context/service/database/Topology.py +++ b/src/context/service/database/Topology.py @@ -27,7 +27,8 @@ from common.tools.object_factory.Topology import json_topology_id from context.Config import ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY, ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY from .models.DeviceModel import DeviceModel from .models.LinkModel import LinkModel -from .models.TopologyModel import TopologyDeviceModel, TopologyLinkModel, TopologyModel +from .models.OpticalLinkModel import OpticalLinkModel +from .models.TopologyModel import TopologyDeviceModel, TopologyLinkModel, TopologyModel, TopologyOpticalLinkModel from .uuids.Context import context_get_uuid from .uuids.Device import device_get_uuid from .uuids.Link import link_get_uuid @@ -79,6 +80,7 @@ def topology_get_details(db_engine : Engine, request : TopologyId) -> TopologyDe obj : Optional[TopologyModel] = session.query(TopologyModel)\ .options(selectinload(TopologyModel.topology_devices, TopologyDeviceModel.device, DeviceModel.endpoints))\ .options(selectinload(TopologyModel.topology_links, TopologyLinkModel.link, LinkModel.link_endpoints))\ + .options(selectinload(TopologyModel.topology_optical_links, TopologyOpticalLinkModel.optical_link, OpticalLinkModel.opticallink_endpoints))\ .filter_by(topology_uuid=topology_uuid).one_or_none() #.options(selectinload(DeviceModel.components))\ return None if obj is None else obj.dump_details() diff --git a/src/context/service/database/models/DeviceModel.py b/src/context/service/database/models/DeviceModel.py index 2aeb90dfdeaa57ba96ff9c9ed095f363c5f8f0fb..0613caba6a433d4440908f4f796c26349f8d9af7 100644 --- a/src/context/service/database/models/DeviceModel.py +++ b/src/context/service/database/models/DeviceModel.py @@ -34,10 +34,11 @@ class DeviceModel(_Base): updated_at = Column(DateTime, nullable=False) #topology_devices = relationship('TopologyDeviceModel', back_populates='device') - config_rules = relationship('DeviceConfigRuleModel', passive_deletes=True) # lazy='joined', back_populates='device' - endpoints = relationship('EndPointModel', passive_deletes=True) # lazy='joined', back_populates='device' - components = relationship('ComponentModel', passive_deletes=True) # lazy='joined', back_populates='device' - controller = relationship('DeviceModel', remote_side=[device_uuid], passive_deletes=True) # lazy='joined', back_populates='device' + config_rules = relationship('DeviceConfigRuleModel', passive_deletes=True) # lazy='joined', back_populates='device' + endpoints = relationship('EndPointModel', passive_deletes=True) # lazy='joined', back_populates='device' + components = relationship('ComponentModel', passive_deletes=True) # lazy='joined', back_populates='device' + controller = relationship('DeviceModel', remote_side=[device_uuid], passive_deletes=True) # lazy='joined', back_populates='device' + optical_config = relationship('OpticalConfigModel', passive_deletes=True) def dump_id(self) -> Dict: return {'device_uuid': {'uuid': self.device_uuid}} diff --git a/src/context/service/database/models/EndPointModel.py b/src/context/service/database/models/EndPointModel.py index 6355f14af453b3695bb688285aa19c8641aac4c0..37a03393bd6a571d8587be7f9c345097971d5111 100644 --- a/src/context/service/database/models/EndPointModel.py +++ b/src/context/service/database/models/EndPointModel.py @@ -33,8 +33,9 @@ class EndPointModel(_Base): updated_at = Column(DateTime, nullable=False) endpoint_location = Column(String, nullable=True) - device = relationship('DeviceModel', back_populates='endpoints') # lazy='selectin' - topology = relationship('TopologyModel', lazy='selectin') + device = relationship('DeviceModel', back_populates='endpoints') # lazy='selectin' + topology = relationship('TopologyModel', lazy='selectin') + optical_link_endpoints = relationship('OpticalLinkEndPointModel', back_populates='endpoint' ) #link_endpoints = relationship('LinkEndPointModel', back_populates='endpoint' ) #service_endpoints = relationship('ServiceEndPointModel', back_populates='endpoint' ) diff --git a/src/context/service/database/models/OpticalConfig/OpticalConfigModel.py b/src/context/service/database/models/OpticalConfig/OpticalConfigModel.py new file mode 100644 index 0000000000000000000000000000000000000000..fa77898337055c88edc120aa53e517ffcd6ed2b1 --- /dev/null +++ b/src/context/service/database/models/OpticalConfig/OpticalConfigModel.py @@ -0,0 +1,64 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 json +from sqlalchemy import Column, String, ForeignKey +from sqlalchemy.dialects.postgresql import ARRAY +from sqlalchemy.orm import relationship +from context.service.database.models._Base import _Base + +class OpticalConfigModel(_Base): + __tablename__ = 'optical_config' + opticalconfig_uuid = Column(String, primary_key=True) + channel_namespace = Column(String, nullable=True) + endpoints = Column(ARRAY(String), nullable=True) + type = Column(String,nullable=False) + + # transcievers = Column(ARRAY(String), nullable=True) + # interfaces = Column(String, nullable=True) + # channels = relationship("OpticalChannelModel") + transponders = relationship("TransponderTypeModel") + roadms = relationship("RoadmTypeModel") + + device_uuid = Column(ForeignKey("device.device_uuid",ondelete="CASCADE"),index=True ,nullable=False) + device = relationship("DeviceModel", back_populates='optical_config') + + def dump_id (self ): + return { + "opticalconfig_uuid":self.opticalconfig_uuid, + "device_uuid" :self.device_uuid + } + + def dump(self): + obj={ + # "channels" : [channel.dump() for channel in self.channels], + # "transceivers" : {"transceiver": [transciever for transciever in self.transcievers]}, + # "interfaces" : {"interface":json.loads(self.interfaces) if self.interfaces else ''}, + "channel_namespace" : self.channel_namespace, + "endpoints" : [json.loads(endpoint) for endpoint in self.endpoints if endpoint], + "device_name" : self.device.device_name, + "type" : self.type + } + if self.type =="optical-transponder" : + channels= [transponer.dump() for transponer in self.transponders ][0] + obj['channels']=channels['channels'] if 'channels' in channels else None + obj['transceivers']=channels['transceivers'] if 'transceivers' in channels else None + obj['interfaces']=channels['interfaces'] if 'interfaces' in channels else None + obj['trasponder_uuid']=channels['trasponder_uuid'] if 'trasponder_uuid' in channels else None + + if self.type =="optical-roadm" : + channels=[roadms.dump() for roadms in self.roadms ][0] + obj['channels']=channels['channels'] if 'channels' in channels else None + obj['roadm_uuid']=channels['roadm_uuid'] if 'roadm_uuid' in channels else None + return obj diff --git a/src/context/service/database/models/OpticalConfig/RoadmModel.py b/src/context/service/database/models/OpticalConfig/RoadmModel.py new file mode 100644 index 0000000000000000000000000000000000000000..31ebf4cfabb2b91252b3c80884d47b93d07db033 --- /dev/null +++ b/src/context/service/database/models/OpticalConfig/RoadmModel.py @@ -0,0 +1,74 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from sqlalchemy import Column, String, Integer , ForeignKey +from sqlalchemy.orm import relationship +from context.service.database.models._Base import _Base + +class RoadmTypeModel (_Base): + __tablename__ = 'roadm_type' + roadm_uuid = Column(String, primary_key=True) + circuits = Column(String, nullable=True) + opticalconfig_uuid = Column(ForeignKey('optical_config.opticalconfig_uuid', ondelete='CASCADE'), index=True, nullable=False) + channels = relationship("ChannelModel") + opticalconfig = relationship('OpticalConfigModel', back_populates='roadms') + + def dump_id (self): + return { + "roadm_uuid" : self.roadm_uuid + } + + def dump (self): + return { + "channels" : [channel.dump() for channel in self.channels], + "roadm_uuid" : self.dump_id(), + } + +class ChannelModel(_Base): + __tablename__ = 'channel' + + channel_uuid = Column(String, primary_key=True) + band_name = Column(String, nullable=True) + lower_frequency = Column(Integer, nullable=True) + upper_frequency = Column(Integer, nullable=True) + channel_index = Column(String, nullable=True) + status = Column(String, nullable=True) + src_port = Column(String, nullable=True) + dest_port = Column(String, nullable=True) + type = Column(String, nullable=False) + optical_band_parent = Column(String, nullable=True) + roadm_uuid = Column(ForeignKey('roadm_type.roadm_uuid', ondelete='CASCADE'), nullable=False) + + roadm = relationship('RoadmTypeModel',back_populates='channels') + + # opticalconfig_uuid = Column(ForeignKey('optical_config.opticalconfig_uuid', ondelete='CASCADE'), primary_key=True) + # opticalconfig = relationship('OpticalConfigModel', back_populates='channels') + + def dump_id (self ): + return { + "channel_uuid": self.channel_uuid + } + + def dump(self): + return { + "band_name" : self.band_name, + "lower_frequency" : self.lower_frequency, + "upper_frequency" : self.upper_frequency, + "type" : self.type, + "src_port" : self.src_port, + "dest_port" : self.dest_port, + "status" : self.status, + "optical_band_parent" : self.optical_band_parent, + "channel_index" : self.channel_index, + } diff --git a/src/context/service/database/models/OpticalConfig/TransponderModel.py b/src/context/service/database/models/OpticalConfig/TransponderModel.py new file mode 100644 index 0000000000000000000000000000000000000000..33e509d354b257d380d61c9795e86fdce7a68348 --- /dev/null +++ b/src/context/service/database/models/OpticalConfig/TransponderModel.py @@ -0,0 +1,72 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 json +from sqlalchemy import Column, String, Integer , ForeignKey +from sqlalchemy.dialects.postgresql import ARRAY +from sqlalchemy.orm import relationship +from context.service.database.models._Base import _Base + +class TransponderTypeModel (_Base): + __tablename__ = 'transponder_type' + + transponder_uuid = Column(String, primary_key=True) + transcievers = Column(ARRAY(String), nullable=True) + interfaces = Column(String, nullable=True) + opticalconfig_uuid = Column(ForeignKey('optical_config.opticalconfig_uuid', ondelete='CASCADE'), index=True, nullable=False) + + channels = relationship("OpticalChannelModel") + opticalconfig = relationship('OpticalConfigModel', back_populates='transponders') + + def dump_id (self): + return { + "transponder_uuid": self.transponder_uuid + } + + def dump (self): + return { + "channels" : [channel.dump() for channel in self.channels], + "transceivers" : {"transceiver": [transciever for transciever in self.transcievers]}, + "interfaces" : {"interface":json.loads(self.interfaces) if self.interfaces else ''}, + "trasponder_uuid" : self.dump_id() + } + +class OpticalChannelModel(_Base): + __tablename__ = 'optical_channel' + + channel_uuid = Column(String, primary_key=True) + channel_name = Column(String, nullable=True) + frequency = Column(Integer, nullable=True) + operational_mode = Column(Integer, nullable=True) + status = Column(String, nullable=True) + target_output_power = Column(String, nullable=True) + transponder_uuid = Column(ForeignKey('transponder_type.transponder_uuid', ondelete='CASCADE'), nullable=False) + transponder = relationship('TransponderTypeModel', back_populates='channels') + + # opticalconfig_uuid = Column(ForeignKey('optical_config.opticalconfig_uuid', ondelete='CASCADE'), primary_key=True) + # opticalconfig = relationship('OpticalConfigModel', back_populates='channels') + + def dump_id (self ): + return { + "channel_uuid": self.channel_uuid + } + + def dump(self): + return { + "name" : {'index':self.channel_name}, + "frequency" : self.frequency, + "target-output-power" : self.target_output_power, + "operational-mode" : self.operational_mode, + "status" : self.status, + } diff --git a/src/context/service/database/models/OpticalConfig/__init__.py b/src/context/service/database/models/OpticalConfig/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..bbfc943b68af13a11e562abbc8680ade71db8f02 --- /dev/null +++ b/src/context/service/database/models/OpticalConfig/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. diff --git a/src/context/service/database/models/OpticalConfigModel.py b/src/context/service/database/models/OpticalConfigModel.py deleted file mode 100644 index d7274da17070e0f21774d8173abcfad12e1dcae7..0000000000000000000000000000000000000000 --- a/src/context/service/database/models/OpticalConfigModel.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 json -from sqlalchemy import Column, String, Integer -from sqlalchemy.dialects.postgresql import ARRAY -from ._Base import _Base - -class OpticalConfigModel(_Base): - __tablename__ = 'optical_config' - opticalconfig_uuid = Column(String, primary_key=True) - channels = Column(ARRAY(String), nullable=True) - transcievers = Column(ARRAY(String), nullable=True) - interfaces = Column(String, nullable=True) - channel_namespace = Column(String, nullable=True) - endpoints = Column(ARRAY(String), nullable=True) - frequency = Column(Integer, nullable=True) - operational_mode = Column(Integer, nullable=True) - output_power = Column(String, nullable=True) - - def dump(self): - return { - "channels" : [{'name': {'index': channel}} for channel in self.channels], - "transceivers" : {"transceiver": [transciever for transciever in self.transcievers]}, - "interfaces" : {"interface": json.loads(self.interfaces)}, - "channel_namespace" : self.channel_namespace, - "endpoints" : [json.loads(endpoint) for endpoint in self.endpoints], - "frequency" : self.frequency, - "output_power" : self.output_power, - "operational_mode" : self.operational_mode, - } diff --git a/src/context/service/database/models/OpticalLinkModel.py b/src/context/service/database/models/OpticalLinkModel.py new file mode 100644 index 0000000000000000000000000000000000000000..6db1b316160aeb3f01d6d70b74338ba67d9b528a --- /dev/null +++ b/src/context/service/database/models/OpticalLinkModel.py @@ -0,0 +1,74 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +from sqlalchemy import Column, DateTime, ForeignKey, Integer, String ,Boolean +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship +from typing import Dict +from ._Base import _Base +from .Slot import C_Slot ,S_Slot , L_Slot + +class OpticalLinkModel(_Base): + __tablename__ = 'opticallink' + + opticallink_uuid = Column(UUID(as_uuid=False), primary_key=True) + name = Column(String, nullable=False) + created_at = Column(DateTime, nullable=False) + updated_at = Column(DateTime, nullable=False) + length = Column(Integer, nullable=True) + src_port = Column(String, nullable=True) + dst_port = Column(String, nullable=True) + local_peer_port = Column(String, nullable=True) + remote_peer_port = Column(String, nullable=True) + used = Column(Boolean ,nullable=True) + c_slots = Column (C_Slot,nullable=True) + l_slots = Column (L_Slot,nullable=True) + s_slots = Column (S_Slot,nullable=True) + opticallink_endpoints = relationship('OpticalLinkEndPointModel') + topology_optical_links = relationship('TopologyOpticalLinkModel', back_populates='optical_link') + + def dump_id(self) -> Dict: + return {'link_uuid': {'uuid': self.opticallink_uuid}} + + def dump(self) -> Dict: + result = { + 'link_id' : self.dump_id(), + 'name' : self.name, + 'optical_details' : { + 'length' : self.length, + 'src_port' : self.src_port, + 'dst_port' : self.dst_port, + 'local_peer_port' : self.local_peer_port, + 'remote_peer_port' : self.remote_peer_port, + 'used' : self.used, + 'c_slots' : self.c_slots if self.c_slots is not None else {}, + 'l_slots' : self.l_slots if self.l_slots is not None else {}, + 's_slots' : self.s_slots if self.s_slots is not None else {}, + }, + 'link_endpoint_ids' : [ + optical_endpoint.endpoint.dump_id() + for optical_endpoint in self.opticallink_endpoints + ], + } + return result + +class OpticalLinkEndPointModel(_Base): + __tablename__ = 'opticallink_endpoint' + + link_uuid = Column(ForeignKey('opticallink.opticallink_uuid', ondelete='CASCADE' ), primary_key=True) + endpoint_uuid = Column(ForeignKey('endpoint.endpoint_uuid', ondelete='RESTRICT'), primary_key=True, index=True) + + optical_link = relationship('OpticalLinkModel', back_populates='opticallink_endpoints') + endpoint = relationship('EndPointModel', lazy='selectin') diff --git a/src/context/service/database/models/Slot.py b/src/context/service/database/models/Slot.py new file mode 100644 index 0000000000000000000000000000000000000000..3d8602bd40464eafa8a6234881b100c73134bed7 --- /dev/null +++ b/src/context/service/database/models/Slot.py @@ -0,0 +1,80 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from sqlalchemy.types import TypeDecorator, Integer + +class SlotType(TypeDecorator): + impl = Integer + + def process_bind_param(self, value, dialect): + if value is not None: + bin_num = "0b" + for i,(key,val) in enumerate(value.items()): + bin_num =bin_num + f"{val}" + int_num = int(bin_num,2) + return int_num + + def process_result_value(self, value, dialect): + if value is not None: + slot = dict() + bin_num = bin(value) + sliced_num = bin_num[2:] + for i in range(len(sliced_num)): + slot[str(i+1)]=int(sliced_num[i]) + return slot + +class C_Slot(SlotType): + start_point = 0 + + def process_result_value(self, value, dialect): + if value is not None: + slot = dict() + bin_num = bin(value) + sliced_num = bin_num[2:] + if (len(sliced_num) != 20) : + for i in range(0,20 - len(sliced_num)): + sliced_num = '0' + sliced_num + for i in range(len(sliced_num)): + slot[str(self.start_point+i+1)]=int(sliced_num[i]) + return slot + +class L_Slot (SlotType): + start_point = 100 + + def process_result_value(self, value, dialect): + if value is not None: + slot = dict() + bin_num = bin(value) + sliced_num = bin_num[2:] + if (len(sliced_num) != 20) : + for i in range(0,20 - len(sliced_num)): + sliced_num='0'+sliced_num + for i in range(len(sliced_num)): + slot[str(self.start_point+i+1)]=int(sliced_num[i]) + return slot + +class S_Slot (SlotType): + start_point = 500 + + def process_result_value(self, value, dialect): + if value is not None: + slot= dict() + bin_num = bin(value) + sliced_num=bin_num[2:] + if (len(sliced_num) != 20) : + for i in range(0,20 - len(sliced_num)): + sliced_num='0'+sliced_num + for i in range(len(sliced_num)): + slot[str(self.start_point+i+1)]=int(sliced_num[i]) + return slot diff --git a/src/context/service/database/models/TopologyModel.py b/src/context/service/database/models/TopologyModel.py index 995abab3a40bfacb446360c55c784b0a5f4207ec..cd731ed60efd6be266dea4bf3c9847bbceb0370e 100644 --- a/src/context/service/database/models/TopologyModel.py +++ b/src/context/service/database/models/TopologyModel.py @@ -27,9 +27,10 @@ class TopologyModel(_Base): created_at = Column(DateTime, nullable=False) updated_at = Column(DateTime, nullable=False) - context = relationship('ContextModel', back_populates='topologies', lazy='selectin') - topology_devices = relationship('TopologyDeviceModel') # back_populates='topology' - topology_links = relationship('TopologyLinkModel' ) # back_populates='topology' + context = relationship('ContextModel', back_populates='topologies', lazy='selectin') + topology_devices = relationship('TopologyDeviceModel') # back_populates='topology' + topology_links = relationship('TopologyLinkModel' ) # back_populates='topology' + topology_optical_links = relationship("TopologyOpticalLinkModel") def dump_id(self) -> Dict: return { @@ -39,10 +40,11 @@ class TopologyModel(_Base): def dump(self) -> Dict: return { - 'topology_id': self.dump_id(), - 'name' : self.topology_name, - 'device_ids' : [{'device_uuid': {'uuid': td.device_uuid}} for td in self.topology_devices], - 'link_ids' : [{'link_uuid' : {'uuid': tl.link_uuid }} for tl in self.topology_links ], + 'topology_id' : self.dump_id(), + 'name' : self.topology_name, + 'device_ids' : [{'device_uuid': {'uuid': td.device_uuid }} for td in self.topology_devices ], + 'link_ids' : [{'link_uuid' : {'uuid': tl.link_uuid }} for tl in self.topology_links ], + 'optical_link_ids': [{'link_uuid' : {'uuid': to.optical_link_uuid}} for to in self.topology_optical_links], } def dump_details(self) -> Dict: @@ -54,11 +56,16 @@ class TopologyModel(_Base): tl.link.dump() for tl in self.topology_links ] + optical_links=[ + ol.optical_link.dump() + for ol in self.topology_optical_links + ] return { - 'topology_id': self.dump_id(), - 'name' : self.topology_name, - 'devices' : devices, - 'links' : links, + 'topology_id' : self.dump_id(), + 'name' : self.topology_name, + 'devices' : devices, + 'links' : links, + 'optical_links': optical_links, } class TopologyDeviceModel(_Base): @@ -78,3 +85,14 @@ class TopologyLinkModel(_Base): topology = relationship('TopologyModel', lazy='selectin', viewonly=True) # back_populates='topology_links' link = relationship('LinkModel', lazy='selectin') # back_populates='topology_links' + +#---------------------------------------- Experimental --------------------------------------- + +class TopologyOpticalLinkModel(_Base): + __tablename__ = 'topology_optical_link' + + topology_uuid = Column(ForeignKey('topology.topology_uuid', ondelete='RESTRICT'), primary_key=True, index=True) + optical_link_uuid = Column(ForeignKey('opticallink.opticallink_uuid', ondelete='CASCADE' ), primary_key=True, index=True) + + topology = relationship('TopologyModel', lazy='selectin', viewonly=True) # back_populates='topology_optical_links' + optical_link = relationship('OpticalLinkModel', lazy='selectin') # back_populates='topology_optical_links' diff --git a/src/context/service/database/uuids/OpticalConfig.py b/src/context/service/database/uuids/OpticalConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..f2cd443a983d5b37009ddc1c2dc821dce960ddb8 --- /dev/null +++ b/src/context/service/database/uuids/OpticalConfig.py @@ -0,0 +1,64 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from common.method_wrappers.ServiceExceptions import InvalidArgumentsException +from common.proto.context_pb2 import DeviceId +from ._Builder import get_uuid_from_string, get_uuid_random + +def channel_get_uuid( + channel_name : str , device_id : str, allow_random : bool = False +) -> str: + if len(channel_name) > 0: + return get_uuid_from_string(channel_name) + device_id + if allow_random: return get_uuid_random() + + raise InvalidArgumentsException([ + ('channel uuid', channel_name), + ], extra_details=['Channel name is required to produce a channel UUID']) + +def transponder_get_uuid( + opticalconfig_id : str, allow_random : bool = False +) -> str: + if opticalconfig_id is not None: + return get_uuid_from_string(f"{opticalconfig_id}-transponder") + if allow_random: return get_uuid_random() + + raise InvalidArgumentsException([ + ('transponder uuid', opticalconfig_id), + + ], extra_details=['opticalconfig id is required to produce a transponder UUID']) + +def roadm_get_uuid( + opticalconfig_id : str, allow_random : bool = False +) -> str: + if opticalconfig_id is not None: + return get_uuid_from_string(f"{opticalconfig_id}-roadm") + if allow_random: return get_uuid_random() + + raise InvalidArgumentsException([ + ('roadm uuid', opticalconfig_id), + + ], extra_details=['opticalconfig id is required to produce a roadm UUID']) + +def opticalconfig_get_uuid( + device_id : DeviceId, allow_random : bool = False +) -> str: + device_uuid = device_id.device_uuid.uuid + if (len(device_uuid)>0): + return get_uuid_from_string(f"{device_uuid}_opticalconfig") + if allow_random: return get_uuid_random() + + raise InvalidArgumentsException([ + ('DeviceId ', device_id), + ], extra_details=['device_id is required to produce a OpticalConfig UUID']) diff --git a/src/context/service/database/uuids/OpticalEndPoint.py b/src/context/service/database/uuids/OpticalEndPoint.py new file mode 100644 index 0000000000000000000000000000000000000000..fedafd6f470af174a6c4701e330f93fea00a5a3f --- /dev/null +++ b/src/context/service/database/uuids/OpticalEndPoint.py @@ -0,0 +1,38 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from typing import Tuple +from common.proto.context_pb2 import EndPointId +from common.method_wrappers.ServiceExceptions import InvalidArgumentsException +from ._Builder import get_uuid_from_string, get_uuid_random +from .Device import device_get_uuid + +def optical_endpoint_get_uuid( + endpoint_id : EndPointId, endpoint_name : str = '', allow_random : bool = False +) -> Tuple[str, str, str]: + device_uuid = device_get_uuid(endpoint_id.device_id, allow_random=False) + raw_endpoint_uuid = endpoint_id.endpoint_uuid.uuid + if len(raw_endpoint_uuid) > 0: + prefix_for_name = '{:s}'.format( device_uuid) + return device_uuid, get_uuid_from_string(raw_endpoint_uuid, prefix_for_name=prefix_for_name) + if len(endpoint_name) > 0: + prefix_for_name = '{:s}'.format( device_uuid) + return device_uuid, get_uuid_from_string(endpoint_name, prefix_for_name=prefix_for_name) + if allow_random: + return device_uuid, get_uuid_random() + + raise InvalidArgumentsException([ + ('optical_endpoint_id.endpoint_uuid.uuid', raw_endpoint_uuid), + ('name', endpoint_name), + ], extra_details=['At least one is required to produce a OpticalEndPoint UUID']) diff --git a/src/context/service/database/uuids/OpticalLink.py b/src/context/service/database/uuids/OpticalLink.py new file mode 100644 index 0000000000000000000000000000000000000000..152686423aa808194f0582075557e6133e405071 --- /dev/null +++ b/src/context/service/database/uuids/OpticalLink.py @@ -0,0 +1,32 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from common.method_wrappers.ServiceExceptions import InvalidArgumentsException +from common.proto.context_pb2 import LinkId +from ._Builder import get_uuid_from_string, get_uuid_random + +optical_detail_sp = "Optical_link_detail" + +def opticaldetail_get_uuid( + link_id : LinkId,allow_random=False +) -> str: + link_uuid = link_id.link_uuid.uuid + if len(link_uuid) > 0: + str_uuid=f"{link_uuid}{optical_detail_sp}" + return get_uuid_from_string(str_uuid) + + if allow_random: return get_uuid_random() + raise InvalidArgumentsException([ + ('link_id.link_uuid.uuid', link_uuid), + ], extra_details=['At least one is required to produce a Optical Link Detail UUID']) diff --git a/src/device/client/DeviceClient.py b/src/device/client/DeviceClient.py index d479b21cd1223e06abb48213cecc23db4fd651dc..8397b89b8c43917a5a22dee2ed3ad5ec0d105aae 100644 --- a/src/device/client/DeviceClient.py +++ b/src/device/client/DeviceClient.py @@ -15,12 +15,16 @@ import grpc, logging from common.Constants import ServiceNameEnum from common.Settings import get_service_host, get_service_port_grpc -from common.proto.context_pb2 import Device, DeviceConfig, DeviceId, Empty,OpticalConfig,OpticalConfigId +from common.proto.context_pb2 import ( + Device, DeviceConfig, DeviceId, Empty, + OpticalConfig, OpticalConfigId, OpticalConfigList +) from common.proto.device_pb2 import MonitoringSettings from common.proto.device_pb2_grpc import DeviceServiceStub +from common.proto.optical_device_pb2_grpc import OpenConfigServiceStub from common.tools.client.RetryDecorator import retry, delay_exponential from common.tools.grpc.Tools import grpc_message_to_json_string -from common.proto.openconfig_device_pb2_grpc import OpenConfigServiceStub + LOGGER = logging.getLogger(__name__) MAX_RETRIES = 15 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) @@ -41,12 +45,13 @@ class DeviceClient: def connect(self): self.channel = grpc.insecure_channel(self.endpoint) self.stub = DeviceServiceStub(self.channel) - self.openconfig_stub=OpenConfigServiceStub(self.channel) + self.openconfig_stub = OpenConfigServiceStub(self.channel) def close(self): if self.channel is not None: self.channel.close() self.channel = None self.stub = None + self.openconfig_stub = None @RETRY_DECORATOR def AddDevice(self, request : Device) -> DeviceId: @@ -82,8 +87,21 @@ class DeviceClient: response = self.stub.MonitorDeviceKpi(request) LOGGER.debug('MonitorDeviceKpi result: {:s}'.format(grpc_message_to_json_string(response))) return response + def ConfigureOpticalDevice(self, request : OpticalConfig) -> OpticalConfigId: LOGGER.debug('ConfigureOpticalDevice request: {:s}'.format(grpc_message_to_json_string(request))) response = self.openconfig_stub.ConfigureOpticalDevice(request) LOGGER.debug('ConfigureOpticalDevice result: {:s}'.format(grpc_message_to_json_string(response))) return response + + def GetDeviceConfiguration(self, request : OpticalConfigList) -> Empty: + LOGGER.debug('ConfigureOpticalDevice request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.openconfig_stub.GetDeviceConfiguration(request) + LOGGER.debug('ConfigureOpticalDevice result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + def DisableOpticalDevice(self, request : OpticalConfig) -> Empty: + LOGGER.debug('DisableOpticalDevice request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.openconfig_stub.DisableOpticalDevice(request) + LOGGER.debug('DisableOpticalDevice result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/device/service/DeviceService.py b/src/device/service/DeviceService.py index 1769a16afb49aab6cb986b49e3ca74b9f3b572be..cac36f62230e42ffd8fbbcba242cadb46486b050 100644 --- a/src/device/service/DeviceService.py +++ b/src/device/service/DeviceService.py @@ -16,7 +16,7 @@ import os from common.Constants import ServiceNameEnum from common.Settings import get_service_port_grpc from common.proto.device_pb2_grpc import add_DeviceServiceServicer_to_server -from common.proto.openconfig_device_pb2_grpc import add_OpenConfigServiceServicer_to_server +from common.proto.optical_device_pb2_grpc import add_OpenConfigServiceServicer_to_server from common.tools.service.GenericGrpcService import GenericGrpcService from device.Config import LOAD_ALL_DEVICE_DRIVERS from .driver_api.DriverInstanceCache import DriverInstanceCache diff --git a/src/device/service/DeviceServiceServicerImpl.py b/src/device/service/DeviceServiceServicerImpl.py index 7546c225e67fd3122ec845b3154606eddb7cd9ff..6e6fa6a9311751888d51e053e323a63d810dad4e 100644 --- a/src/device/service/DeviceServiceServicerImpl.py +++ b/src/device/service/DeviceServiceServicerImpl.py @@ -33,9 +33,11 @@ from .driver_api.DriverInstanceCache import DriverInstanceCache, get_driver from .monitoring.MonitoringLoops import MonitoringLoops from .ErrorMessages import ERROR_MISSING_DRIVER, ERROR_MISSING_KPI from .Tools import ( - check_connect_rules, check_no_endpoints, compute_rules_to_add_delete, configure_rules, deconfigure_rules, - get_device_controller_uuid, populate_config_rules, populate_endpoint_monitoring_resources, populate_endpoints, - populate_initial_config_rules, subscribe_kpi, unsubscribe_kpi, update_endpoints) + check_connect_rules, check_no_endpoints, compute_rules_to_add_delete, configure_rules, + deconfigure_rules, get_device_controller_uuid, populate_config_rules, + populate_endpoint_monitoring_resources, populate_endpoints, populate_initial_config_rules, + subscribe_kpi, unsubscribe_kpi, update_endpoints +) LOGGER = logging.getLogger(__name__) @@ -60,8 +62,7 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): device_uuid = request.device_id.device_uuid.uuid connection_config_rules = check_connect_rules(request.device_config) - if request.device_drivers[0] != DeviceDriverEnum.DEVICEDRIVER_OC: - check_no_endpoints(request.device_endpoints) + check_no_endpoints(request.device_endpoints) t1 = time.time() @@ -107,18 +108,24 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): # (which controller is in charge of which sub-device). new_sub_devices : Dict[str, Device] = dict() new_sub_links : Dict[str, Link] = dict() + + #----- Experimental ------------ + new_optical_configs : Dict[str, OpticalConfig] = dict() if len(device.device_endpoints) == 0: t5 = time.time() # created from request, populate endpoints using driver errors.extend(populate_endpoints( - device, driver, self.monitoring_loops, new_sub_devices, new_sub_links)) + device, driver, self.monitoring_loops, new_sub_devices, new_sub_links, + new_optical_configs + )) t6 = time.time() t_pop_endpoints = t6 - t5 else: t_pop_endpoints = None - if len(device.device_config.config_rules) == len(connection_config_rules): + is_optical_device = request.device_drivers[0] == DeviceDriverEnum.DEVICEDRIVER_OC + if len(device.device_config.config_rules) == len(connection_config_rules) and not is_optical_device: # created from request, populate config rules using driver t7 = time.time() errors.extend(populate_config_rules(device, driver)) @@ -143,13 +150,15 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): else: # ZTP is not deployed; assume the device is ready while onboarding and set them as enabled. device.device_operational_status = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED - - # temporary line - if request.device_drivers[0] == DeviceDriverEnum.DEVICEDRIVER_OC and len(request.device_endpoints) > 0: + + # temporary line + if is_optical_device: #for endpoint in request.device_endpoints: # #endpoint.endpoint_id.device_id.CopyFrom(device.device_id) # pass - device.device_endpoints.extend(request.device_endpoints) + + if 'new_optical_config' in new_optical_configs and 'opticalconfig' in new_optical_configs["new_optical_config"]: + context_client.SetOpticalConfig(new_optical_configs["new_optical_config"]['opticalconfig']) device_id = context_client.SetDevice(device) diff --git a/src/device/service/OpenConfigServicer.py b/src/device/service/OpenConfigServicer.py index 1dddade18e171380132ed4e5850dfbc7e180b4d8..bee2d4d5ccf6a5757b854f2d8b2275c4da64758f 100644 --- a/src/device/service/OpenConfigServicer.py +++ b/src/device/service/OpenConfigServicer.py @@ -16,7 +16,8 @@ import grpc, logging, json from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method from common.method_wrappers.ServiceExceptions import NotFoundException from common.proto.context_pb2 import ( - Device, DeviceId, DeviceOperationalStatusEnum, Empty, OpticalConfig, OpticalConfig + Device, DeviceId, DeviceOperationalStatusEnum, Empty, OpticalConfig, + OpticalConfig, OpticalConfigList ) from common.proto.device_pb2_grpc import DeviceServiceServicer from common.tools.context_queries.Device import get_device @@ -75,21 +76,103 @@ class OpenConfigServicer(DeviceServiceServicer): @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def ConfigureOpticalDevice (self, request : OpticalConfig, context : grpc.ServicerContext) -> Empty: - device_uuid = request.opticalconfig_id.opticalconfig_uuid - resources=[] - config =json.loads(request.config) + device_uuid = request.device_id.device_uuid.uuid + resources : list[dict] = [] + is_all_good = True + config = json.loads(request.config) + results = None + + try: + context_client = ContextClient() + device = get_device( + context_client, device_uuid, rw_copy=True, include_endpoints=True, include_components=False, + include_config_rules=False) + if device is None: + raise NotFoundException('Device', device_uuid, extra_details='loading in ConfigureDevice') + resources, conditions = extract_resources(config=config, device=device) + + driver : _Driver = get_driver(self.driver_instance_cache, device) + results = driver.SetConfig(resources=resources,conditions=conditions) + for result in results: + if not result : + is_all_good = False + + if is_all_good: + #driver.GetConfig(resource_keys=[]) + config = json.loads(request.config) + handled_flow = next((i for i in resources if i['resource_key'] == 'handled_flow'), None) + if handled_flow is not None and len(handled_flow) > 0: + config['flow_handled'] = handled_flow['value'] + request.config=json.dumps(config) + context_client.UpdateOpticalConfig(request) + context_client.close() + except Exception as e: + LOGGER.info("error in configuring %s",e) + return Empty() + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetDeviceConfiguration (self, request : OpticalConfigList, context : grpc.ServicerContext) -> Empty: + context_client = ContextClient() + + for configs in request.opticalconfigs: + device_uuid = configs.device_id.device_uuid.uuid + try: + device = get_device( + context_client, device_uuid, rw_copy=True, include_endpoints=True, include_components=False, + include_config_rules=False) + if device is None: + raise NotFoundException('Device', device_uuid, extra_details='loading in ConfigureDevice') + driver : _Driver = get_driver(self.driver_instance_cache, device) + results = driver.GetConfig(resource_keys=[]) + for resource_data in results : + resource_key, resource_value = resource_data + if resource_key.startswith('/opticalconfigs/opticalconfig/'): + if 'opticalconfig' in resource_value: + context_client.SetOpticalConfig(resource_value['opticalconfig']) + + #TODO: add a control with the NETCONF get + #driver.GetConfig(resource_keys=filter_fields) + except Exception as e: + LOGGER.info("error in configuring %s",e) + context_client.close() + return Empty() + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def DisableOpticalDevice (self, request : OpticalConfig, context : grpc.ServicerContext) -> Empty: + roadm_configuration = None + device_uuid = request.device_id.device_uuid.uuid + resources : list[dict] = [] + is_all_good = True + config = json.loads(request.config) + try: context_client = ContextClient() device = get_device( context_client, device_uuid, rw_copy=True, include_endpoints=True, include_components=False, include_config_rules=False) + if device is None: raise NotFoundException('Device', device_uuid, extra_details='loading in ConfigureDevice') - resources,conditions=extract_resources(config=config,device=device) + + resources, conditions = extract_resources(config=config, device=device) + driver : _Driver = get_driver(self.driver_instance_cache, device) - result = driver.SetConfig(resources=resources,conditions=conditions) - #TODO: add a control with the NETCONF get - #driver.GetConfig(resource_keys=filter_fields) + if 'edit_type' in conditions and conditions['edit_type'] == 'optical-band': + roadm_configuration = driver.GetConfig() + for resource_data in roadm_configuration: + resource_key, resource_value = resource_data + if resource_key.startswith('/opticalconfigs/opticalconfig/'): + roadm_configuration=resource_value["opticalconfig"] + results = driver.DeleteConfig(resources=resources,conditions=conditions,optical_device_configuration=roadm_configuration) + for result in results: + if not result : + is_all_good = False + + if is_all_good: + config = json.loads(request.config) + if "new_config" in config : + context_client.DeleteOpticalChannel(request) + context_client.close() except Exception as e: - LOGGER.info("error in configuring %s",e) + LOGGER.info("error in Disable configuring %s",e) return Empty() diff --git a/src/device/service/Tools.py b/src/device/service/Tools.py index 91926b9e59cccac2e233ac14bbac497bbb0ac15c..967a6a8c19ca4da763f29bfa164f50ad88d27363 100644 --- a/src/device/service/Tools.py +++ b/src/device/service/Tools.py @@ -17,7 +17,9 @@ from typing import Any, Dict, List, Optional, Tuple, Union from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME from common.DeviceTypes import DeviceTypeEnum from common.method_wrappers.ServiceExceptions import InvalidArgumentException, NotFoundException -from common.proto.context_pb2 import ConfigActionEnum, ConfigRule_ACL, Device, DeviceConfig, EndPoint, Link, Location +from common.proto.context_pb2 import ( + ConfigActionEnum, ConfigRule_ACL, Device, DeviceConfig, EndPoint, Link, Location, OpticalConfig +) from common.proto.device_pb2 import MonitoringSettings from common.proto.kpi_sample_types_pb2 import KpiSampleType from common.tools.grpc.ConfigRules import update_config_rule_custom @@ -26,7 +28,8 @@ from common.type_checkers.Checkers import chk_length, chk_type from .driver_api._Driver import _Driver, RESOURCE_ENDPOINTS from .monitoring.MonitoringLoops import MonitoringLoops from .ErrorMessages import ( - ERROR_BAD_RESOURCE, ERROR_DELETE, ERROR_GET, ERROR_GET_INIT, ERROR_MISSING_KPI, ERROR_SAMPLETYPE, ERROR_SET, + ERROR_BAD_RESOURCE, ERROR_DELETE, ERROR_GET, ERROR_GET_INIT, + ERROR_MISSING_KPI, ERROR_SAMPLETYPE, ERROR_SET, ERROR_SUBSCRIBE, ERROR_UNSUBSCRIBE, ERROR_UNSUP_RESOURCE ) @@ -106,7 +109,8 @@ def get_device_controller_uuid(device : Device) -> Optional[str]: def populate_endpoints( device : Device, driver : _Driver, monitoring_loops : MonitoringLoops, - new_sub_devices : Dict[str, Device], new_sub_links : Dict[str, Link] + new_sub_devices : Dict[str, Device], new_sub_links : Dict[str, Link], + new_optical_configs : Dict[str, OpticalConfig] ) -> List[str]: device_uuid = device.device_id.device_uuid.uuid device_name = device.name @@ -237,6 +241,9 @@ def populate_endpoints( _sub_link_endpoint_id.device_id.device_uuid.uuid = device_uuid _sub_link_endpoint_id.endpoint_uuid.uuid = endpoint_uuid + # ----------Experimental -------------- + elif resource_key.startswith('/opticalconfigs/opticalconfig/'): + new_optical_configs["new_optical_config"]=resource_value else: errors.append(ERROR_UNSUP_RESOURCE.format(device_uuid=device_uuid, resource_data=str(resource_data))) continue @@ -454,7 +461,7 @@ def update_endpoints(src_device : Device, dst_device : Device) -> None: def get_edit_target(device : Device, is_opticalband : bool) -> str: if is_opticalband: return 'optical-band' - if device.device_type == DeviceTypeEnum.OPTICAL_ROADM: return 'media-channel' + if device.device_type == DeviceTypeEnum.OPTICAL_ROADM._value_: return 'media-channel' return 'optical-channel' def is_key_existed(key : str, keys_dic = dict, key_name_to_use = None) -> dict: @@ -468,18 +475,20 @@ def is_key_existed(key : str, keys_dic = dict, key_name_to_use = None) -> dict: dic['value'] = None return dic -def extract_resources(config : dict, device : Device) -> list: +def extract_resources(config : dict, device : Device) -> list[list[dict], dict]: conditions = {} - resources = [] + resources : list[dict] = [] resources.append(is_key_existed('channel_namespace', config)) resources.append(is_key_existed('add_transceiver', config)) is_opticalband = config.get('is_opticalband', False) conditions['is_opticalband'] = is_opticalband conditions['edit_type'] = get_edit_target(device, is_opticalband) + if 'flow' in config: #for tuple_value in config['flow'][device.name]: source_vals = [] dest_vals = [] + handled_flow = [] for tuple_value in config['flow']: source_port = None destination_port = None @@ -492,9 +501,10 @@ def extract_resources(config : dict, device : Device) -> list: dst_endpoint_obj = get_endpoint_matching(device, destination_port_uuid) destination_port = dst_endpoint_obj.name dest_vals.append(destination_port) - resources.append({'resource_key': 'source_port', 'value': source_vals}) - resources.append({'resource_key': 'destination_port', 'value': dest_vals }) - + handled_flow.append((source_port, destination_port)) + resources.append({'resource_key': 'source_port', 'value': source_vals }) + resources.append({'resource_key': 'destination_port', 'value': dest_vals }) + resources.append({'resource_key': 'handled_flow', 'value': handled_flow}) if 'new_config' in config: lower_frequency = None upper_frequency = None @@ -502,15 +512,15 @@ def extract_resources(config : dict, device : Device) -> list: resources.append(is_key_existed('frequency', keys_dic=config['new_config'])) resources.append(is_key_existed('operational-mode', keys_dic=config['new_config'])) resources.append(is_key_existed('line-port', keys_dic=config['new_config'])) + resources.append(is_key_existed('status', keys_dic=config['new_config'] , key_name_to_use="admin-state")) resources.append(is_key_existed('band_type', keys_dic=config['new_config'], key_name_to_use='name')) resources.append(is_key_existed('ob_id', keys_dic=config['new_config'], key_name_to_use='optical-band-parent')) - resources.append(is_key_existed('name', keys_dic=config['new_config'], key_name_to_use='channel_name')) + #resources.append(is_key_existed('name', keys_dic=config['new_config'], key_name_to_use='channel_name')) if not is_opticalband: if 'frequency' in config['new_config'] and 'band' in config['new_config'] and conditions['edit_type'] == 'media-channel': - lower_frequency = int(int(config['new_config']['frequency']) - (int(config['new_config']['band'])/2)) - upper_frequency = int(int(config['new_config']['frequency']) + (int(config['new_config']['band'])/2)) - #lower_frequency = (config['new_config']['frequency'] - config['new_config']['band'])/2 - #upper_frequency = (config['new_config']['frequency'] + config['new_config']['band'])/2 + if config['new_config']['frequency'] is not None and config['new_config']['band'] is not None: + lower_frequency = int(int(config['new_config']['frequency']) - (int(config['new_config']['band'])/2)+1) + upper_frequency = int(int(config['new_config']['frequency']) + (int(config['new_config']['band'])/2)) resources.append(is_key_existed('flow_id', keys_dic=config['new_config'], key_name_to_use='index')) #resources.append({'resource_key':'index','value':config['new_config']['flow_id'] if 'flow_id' in config['new_config'] else None}) else: diff --git a/src/device/service/drivers/oc_driver/OCDriver.py b/src/device/service/drivers/oc_driver/OCDriver.py index 89dc791f6982239c3eb878662b02f7f845c6746b..6351f26e57d00e98ac5a011c5f22b5abf7066395 100644 --- a/src/device/service/drivers/oc_driver/OCDriver.py +++ b/src/device/service/drivers/oc_driver/OCDriver.py @@ -13,33 +13,31 @@ # limitations under the License. import json -import anytree, copy, logging, pytz, queue, re, threading +import logging, pytz, queue, re, threading #import lxml.etree as ET -from datetime import datetime, timedelta -from typing import Any, Dict, Iterator, List, Optional, Tuple, Union +from typing import Any, List, Tuple, Union from apscheduler.executors.pool import ThreadPoolExecutor -import xml.etree.ElementTree as ET -from apscheduler.job import Job from apscheduler.jobstores.memory import MemoryJobStore from apscheduler.schedulers.background import BackgroundScheduler from ncclient.manager import Manager, connect_ssh from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method from common.tools.client.RetryDecorator import delay_exponential -from common.type_checkers.Checkers import chk_length, chk_string, chk_type, chk_float +from common.type_checkers.Checkers import chk_type from device.service.driver_api.Exceptions import UnsupportedResourceKeyException from device.service.driver_api._Driver import _Driver -from device.service.driver_api.AnyTreeTools import TreeNode, get_subnode, set_subnode_value #dump_subtree +from device.service.driver_api.AnyTreeTools import TreeNode +from .templates.VPN.common import seperate_port_config #from .Tools import xml_pretty_print, xml_to_dict, xml_to_file -from .templates.Interfaces.interfaces import interface_template -from .templates.VPN.physical import create_optical_channel,add_transceiver,create_media_channel,create_optical_band +from .templates.VPN.roadms import ( + create_optical_band, disable_media_channel, delete_optical_band, create_media_channel_v2 +) +from .templates.VPN.transponder import edit_optical_channel, change_optical_channel_status from .RetryDecorator import retry from context.client.ContextClient import ContextClient -from common.proto.context_pb2 import ( - OpticalConfig, - ConfigActionEnum, Device, DeviceDriverEnum, DeviceId, DeviceList, DeviceOperationalStatusEnum, Empty - ,OpticalConfigId,Uuid) -from .templates.Tools import extractor -from .Tools import generate_uuid_from_numbers +from common.proto.context_pb2 import OpticalConfig +from .templates.descovery_tool.transponders import transponder_values_extractor +from .templates.descovery_tool.roadms import roadm_values_extractor, openroadm_values_extractor + DEBUG_MODE = False logging.getLogger('ncclient.manager').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING) logging.getLogger('ncclient.transport.ssh').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING) @@ -56,13 +54,14 @@ RE_GET_ENDPOINT_FROM_INTERFACE_XPATH = re.compile(r".*interface\[oci\:name\='([^ SAMPLE_EVICTION_SECONDS = 30.0 # seconds SAMPLE_RESOURCE_KEY = 'interfaces/interface/state/counters' -filter_fields= ["frequency","target-output-power","interface","operational-mode","line-port"] +transponder_filter_fields = ["frequency", "target-output-power", "operational-mode", "line-port", "admin-state"] MAX_RETRIES = 15 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect') context_client= ContextClient() port_xml_filter=f"/components/component[state[type='oc-platform-types:PORT']]/*" transceiver_xml_filter="/components/component[state[type='oc-platform-types:TRANSCEIVER']]/*" + class NetconfSessionHandler: def __init__(self, address : str, port : int, **settings) -> None: self.__lock = threading.RLock() @@ -83,6 +82,7 @@ class NetconfSessionHandler: self.__manager_params = settings.get('manager_params', {}) self.__nc_params = settings.get('nc_params', {}) self.__message_renderer = settings.get('message_renderer','jinja') + self.__manager : Manager = None self.__candidate_supported = False @@ -109,10 +109,10 @@ class NetconfSessionHandler: @property def vendor(self): return self.__vendor - + @property def version(self): return self.__version - + @property def message_renderer(self): return self.__message_renderer @@ -120,7 +120,6 @@ class NetconfSessionHandler: def get(self, filter=None, with_defaults=None): # pylint: disable=redefined-builtin with self.__lock: config=self.__manager.get(filter=filter, with_defaults=with_defaults) - return config @RETRY_DECORATOR @@ -128,14 +127,16 @@ class NetconfSessionHandler: self, config, target='running', default_operation=None, test_option=None, error_option=None, format='xml' # pylint: disable=redefined-builtin ): - - - + response = None with self.__lock: response= self.__manager.edit_config( config, target=target, default_operation=default_operation, test_option=test_option, error_option=error_option, format=format) - + + str_respones = str(response) + if re.search(r'<ok/>', str_respones): + return True + return False @RETRY_DECORATOR def locked(self, target): @@ -144,7 +145,7 @@ class NetconfSessionHandler: @RETRY_DECORATOR def commit(self, confirmed=False, timeout=None, persist=None, persist_id=None): return self.__manager.commit(confirmed=confirmed, timeout=timeout, persist=persist, persist_id=persist_id) - + DRIVER_NAME = 'oc' METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': DRIVER_NAME}) def edit_config( # edit the configuration of openconfig devices @@ -153,80 +154,80 @@ def edit_config( commit_per_rule=False, target='running', default_operation='merge', test_option=None, error_option=None, format='xml' ): - #str_method = 'DeleteConfig' if delete else 'SetConfig' + str_method = 'DeleteConfig' if delete else 'SetConfig' results = [] str_config_messages=[] - - - if (conditions['edit_type']=='optical-channel'): - #transponder - str_config_messages = create_optical_channel(resources) - elif (conditions['edit_type']=='optical-band'): - #roadm optical-band - str_config_messages = create_optical_band(resources) - else : - #roadm media-channel - str_config_messages=create_media_channel(resources) - - - + if str_method == 'SetConfig': + if (conditions['edit_type']=='optical-channel'): + #transponder + str_config_messages = edit_optical_channel(resources) + elif (conditions['edit_type']=='optical-band'): + #roadm optical-band + str_config_messages = create_optical_band(resources) + else : + #roadm media-channel + str_config_messages=create_media_channel_v2(resources) + #Disabling of the Configuration + else: + # Device type is Transponder + if (conditions['edit_type'] == "optical-channel"): + _,ports,_=seperate_port_config(resources) + str_config_messages=change_optical_channel_status(state="DISABLED",ports=ports) + + # Device type is Roadm + elif (conditions['edit_type']=='optical-band'): + str_config_messages=delete_optical_band(resources) + else : + str_config_messages=disable_media_channel(resources) + for str_config_message in str_config_messages: - # configuration of the received templates - if str_config_message is None: raise UnsupportedResourceKeyException("CONFIG") - - netconf_handler.edit_config( # configure the device - config=str_config_message, target=target, default_operation=default_operation, - test_option=test_option, error_option=error_option, format=format) - if commit_per_rule: - netconf_handler.commit() # configuration commit - + # configuration of the received templates + if str_config_message is None: raise UnsupportedResourceKeyException("CONFIG") + result= netconf_handler.edit_config( # configure the device + config=str_config_message, target=target, default_operation=default_operation, + test_option=test_option, error_option=error_option, format=format) + if commit_per_rule: + netconf_handler.commit() # configuration commit + #results[i] = True - results.append(True) - + results.append(result) + + return results class OCDriver(_Driver): def __init__(self, address : str, port : int,device_uuid=None, **settings) -> None: super().__init__(DRIVER_NAME, address, port, **settings) self.__logger = logging.getLogger('{:s}:[{:s}:{:s}]'.format(str(__name__), str(self.address), str(self.port))) self.__lock = threading.Lock() - #self.__initial = TreeNode('.') - #self.__running = TreeNode('.') - self.__subscriptions = TreeNode('.') + self.__started = threading.Event() self.__terminate = threading.Event() - self.__scheduler = BackgroundScheduler(daemon=True) # scheduler used to emulate sampling events + self.__scheduler = BackgroundScheduler(daemon=True) self.__scheduler.configure( jobstores = {'default': MemoryJobStore()}, - executors = {'default': ThreadPoolExecutor(max_workers=1)}, # important! 1 = avoid concurrent requests + executors = {'default': ThreadPoolExecutor(max_workers=1)}, job_defaults = {'coalesce': False, 'max_instances': 3}, timezone=pytz.utc) self._temp_address=f"{address}{port}" - self.__out_samples = queue.Queue() + self.__netconf_handler = NetconfSessionHandler(self.address, self.port, **(self.settings)) - - self.__device_uuid=device_uuid - + self.__type = self.settings.get("type","optical-transponder") + self.__device_uuid = device_uuid self.Connect() - #self.GetConfig() - #self.__samples_cache = SamplesCache(self.__netconf_handler, self.__logger) - + def Connect(self) -> bool: with self.__lock: if self.__started.is_set(): return True self.__netconf_handler.connect() - # Connect triggers activation of sampling events that will be scheduled based on subscriptions self.__scheduler.start() self.__started.set() return True def Disconnect(self) -> bool: with self.__lock: - # Trigger termination of loops and processes self.__terminate.set() - # If not started, assume it is already disconnected if not self.__started.is_set(): return True - # Disconnect triggers deactivation of sampling events self.__scheduler.shutdown() self.__netconf_handler.disconnect() return True @@ -238,78 +239,90 @@ class OCDriver(_Driver): @metered_subclass_method(METRICS_POOL) def GetConfig(self, resource_keys : List[str] = []) -> List[Tuple[str, Union[Any, None, Exception]]]: - - chk_type('resources', resource_keys, list) results = [] opticalConfig= OpticalConfig() - j=0 - + with self.__lock: - - - context_client.connect() - config={} - channels_lst=[] - transceivers={} - + config = {} + transceivers = {} + oc_values = {} + ports_result = [] + oc_values["type"] = self.__type try: xml_data = self.__netconf_handler.get().data_xml - transceivers,interfaces,channels_lst,channel_namespace,endpoints=extractor(data_xml=xml_data,resource_keys=filter_fields,dic=config) - - + if self.__type == "optical-transponder": + extracted_values = transponder_values_extractor( + data_xml=xml_data, resource_keys=transponder_filter_fields, dic=config + ) + transceivers, optical_channels_params, channel_namespace, endpoints, ports_result = extracted_values + oc_values["channels"] = optical_channels_params + oc_values["transceivers"] = transceivers + oc_values["channel_namespace"] = channel_namespace + oc_values["endpoints"] = endpoints + oc_values["ports"] = ports_result + elif (self.__type =='openroadm'): + extracted_values=openroadm_values_extractor(data_xml=xml_data, resource_keys=[], dic=oc_values) + ports_result = extracted_values[1] + else: + extracted_values = roadm_values_extractor(data_xml=xml_data, resource_keys=[], dic=config) + ports_result = extracted_values[0] + oc_values['optical_bands']=extracted_values[1] + oc_values['media_channels']=extracted_values[2] + + #results.append((resource_key, e)) # if validation fails, store the exception + + #///////////////////////// store optical configurtaion //////////////////////////////////////////////////////// + + opticalConfig.config=json.dumps(oc_values) + if self.__device_uuid is not None: + opticalConfig.device_id.device_uuid.uuid=self.__device_uuid + results.append((f"/opticalconfigs/opticalconfig/{self.__device_uuid}",{"opticalconfig":opticalConfig})) + # context_client.connect() + # config_id=context_client.SetOpticalConfig(opticalConfig) + # context_client.close() except Exception as e: # pylint: disable=broad-except - MSG = 'Exception retrieving {:s}' - self.__logger.info("error from getConfig %s",e) - self.__logger.exception(MSG.format(e)) - #results.append((resource_key, e)) # if validation fails, store the exception - - #///////////////////////// divider //////////////////////////////////////////////////////// - - - value_dic={} - value_dic["channels"]=channels_lst - value_dic["transceivers"]=transceivers - value_dic["interfaces"]=interfaces - value_dic["channel_namespace"]=channel_namespace - value_dic["endpoints"]=endpoints - - opticalConfig.config=json.dumps(value_dic) - opticalConfig.opticalconfig_id.opticalconfig_uuid=self.__device_uuid if self.__device_uuid is not None else "" - config_id=context_client.SetOpticalConfig(opticalConfig) - - context_client.close() - + MSG = 'Exception retrieving {:s}' + self.__logger.info("error from getConfig %s",e) + self.__logger.exception(MSG.format(e)) + + if len(ports_result) > 0: results.extend(ports_result) return results @metered_subclass_method(METRICS_POOL) def SetConfig(self, resources : List[Tuple[str, Any]],conditions:dict) -> List[Union[bool, Exception]]: if len(resources) == 0: return [] - results=[] + results = [] with self.__lock: - if self.__netconf_handler.use_candidate: - with self.__netconf_handler.locked(target='candidate'): - results = edit_config( - self.__netconf_handler, self.__logger, resources,conditions, target='candidate', - commit_per_rule=self.__netconf_handler.commit_per_rule - ,) + if self.__netconf_handler.use_candidate: + with self.__netconf_handler.locked(target='candidate'): + results = edit_config( + self.__netconf_handler, self.__logger, resources, conditions, target='candidate', + commit_per_rule=self.__netconf_handler.commit_per_rule + ) else: - results = edit_config(self.__netconf_handler, self.__logger, resources,conditions=conditions - ) + results = edit_config( + self.__netconf_handler, self.__logger, resources, conditions=conditions + ) return results @metered_subclass_method(METRICS_POOL) - def DeleteConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: + def DeleteConfig( + self, resources : List[Tuple[str, Any]], conditions : dict, + optical_device_configuration = None + ) -> List[Union[bool, Exception]]: chk_type('resources', resources, list) if len(resources) == 0: return [] + with self.__lock: if self.__netconf_handler.use_candidate: with self.__netconf_handler.locked(target='candidate'): results = edit_config( self.__netconf_handler, self.__logger, resources, target='candidate', delete=True, - commit_per_rule=self.__netconf_handler.commit_per_rule) + commit_per_rule=self.__netconf_handler.commit_per_rule, conditions=conditions + ) else: - results = edit_config(self.__netconf_handler, self.__logger, resources, delete=True) + results = edit_config( + self.__netconf_handler, self.__logger, resources, delete=True, conditions=conditions + ) return results - - diff --git a/src/device/service/drivers/oc_driver/templates/Interfaces/interfaces.py b/src/device/service/drivers/oc_driver/templates/Interfaces/interfaces.py index 87ba8835ac6f7ad66a709be90195e6597bc2bf6c..b8c3812f292270b63dbe1391d922cbd989415458 100644 --- a/src/device/service/drivers/oc_driver/templates/Interfaces/interfaces.py +++ b/src/device/service/drivers/oc_driver/templates/Interfaces/interfaces.py @@ -14,6 +14,7 @@ from yattag import Doc, indent import logging + def interface_template (interface_data:dict) : data={"name":"eth0","ip":"192.168.1.1","prefix-length":'24'} doc, tag, text = Doc().tagtext() @@ -31,13 +32,10 @@ def interface_template (interface_data:dict) : with tag('config'): with tag('ip'):text(interface_data["ip"]) with tag('prefix-length'):text(interface_data["prefix-length"]) - + result = indent( doc.getvalue(), indentation = ' '*2, newline = '\r\n' ) - logging.info("interfaces %s",result) - return result - - \ No newline at end of file + return result diff --git a/src/device/service/drivers/oc_driver/templates/Tools.py b/src/device/service/drivers/oc_driver/templates/Tools.py index 98086adf7bcc1877ca719fec6ef3f7b9dc890941..92607aca88c1581218c97484c7dfcc87831b5912 100644 --- a/src/device/service/drivers/oc_driver/templates/Tools.py +++ b/src/device/service/drivers/oc_driver/templates/Tools.py @@ -19,6 +19,7 @@ from typing import Collection, Dict, Any from yattag import Doc, indent from .VPN.physical import create_optical_channel + def add_value_from_tag(target : Dict, field_name: str, field_value : ET.Element, cast=None) -> None: if isinstance(field_value,str) or field_value is None or field_value.text is None: return field_value = field_value.text @@ -55,9 +56,32 @@ def generate_templates(resource_key: str, resource_value: str, channel:str) -> s data['name']=channel data['resource_key']=resource_key data['value']=resource_value - result_templates.append(create_physical_config(data)) + #result_templates.append(create_physical_config(data)) return result_templates + + +def extract_status (dic:dict,resource_key:str,xml_data:str,channel_name:str): + + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + channel_name=channel_name if 'index' not in channel_name else channel_name['index'] + index=None + if channel_name.find('-') != -1 : + index= channel_name.split("-")[1] + + + namespaces = { "td": "http://openconfig.net/yang/terminal-device"} + channels = root.findall(f".//td:terminal-device/td:logical-channels/td:channel",namespaces) + for channel in channels : + + index_ele= channel.find(f".//td:config[td:index='{index}']/td:{resource_key}",namespaces) + if index_ele is not None : + dic["status"]=index_ele.text + print(index_ele.text) + return dic + + def extract_channel_xmlns (data_xml:str,is_opticalband:bool): xml_bytes = data_xml.encode("utf-8") root = ET.fromstring(xml_bytes) @@ -88,6 +112,7 @@ def extract_channel_xmlns (data_xml:str,is_opticalband:bool): return namespace + def extract_channels_based_on_channelnamespace (xml_data:str,channel_namespace:str,is_opticalband:bool): xml_bytes = xml_data.encode("utf-8") root = ET.fromstring(xml_bytes) @@ -122,6 +147,7 @@ def extract_channels_based_on_channelnamespace (xml_data:str,channel_namespace:s # Retrieve port-name for dest return channels + def extract_channels_based_on_type (xml_data:str): xml_bytes = xml_data.encode("utf-8") root = ET.fromstring(xml_bytes) @@ -140,9 +166,10 @@ def extract_channels_based_on_type (xml_data:str): return channel_names def extract_value(resource_key:str,xml_data:str,dic:dict,channel_name:str,channel_namespace:str): + xml_bytes = xml_data.encode("utf-8") root = ET.fromstring(xml_bytes) - + channel_name=channel_name if 'index' not in channel_name else channel_name['index'] namespace = {'oc': 'http://openconfig.net/yang/platform', 'td': channel_namespace} @@ -153,10 +180,13 @@ def extract_value(resource_key:str,xml_data:str,dic:dict,channel_name:str,channe if (parameter is not None): value = parameter.text dic[resource_key]=value + else : + logging.info("parameter is None") else: + logging.info("element is None") print(" element not found.") - + return dic @@ -192,6 +222,7 @@ def extract_tranceiver (data_xml:str,dic:dict): component_names = [component.text for component in transceiver_components] dic['transceiver']=component_names return dic + def extract_interface (xml_data:str,dic:dict): xml_bytes = xml_data.encode("utf-8") root = ET.fromstring(xml_bytes) @@ -214,6 +245,7 @@ def extract_interface (xml_data:str,dic:dict): else : dic['interface']={} return dic + def has_opticalbands(xml_data:str): xml_bytes = xml_data.encode("utf-8") root = ET.fromstring(xml_bytes) @@ -226,32 +258,237 @@ def has_opticalbands(xml_data:str): else : has_opticalbands=False return has_opticalbands + +def extract_ports_based_on_type (xml_data:str): + pattern = r':\s*PORT\b' + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + namespace = {'oc': 'http://openconfig.net/yang/platform', 'typex': 'http://openconfig.net/yang/platform-types'} + ports = [] + components = root.findall(".//oc:state[oc:type]",namespace) + for component in components: + type_ele = component.find(".//oc:type",namespace) + match = re.search(pattern, type_ele.text) + if match is not None : + name_element= component.find(".//oc:name",namespace) + port_name =name_element.text + port_index=name_element.text.split("-")[1] + port = (port_name,port_index) + ports.append(port) + return ports -def extractor(data_xml:str,resource_keys:list,dic:dict): +def transponder_values_extractor(data_xml:str,resource_keys:list,dic:dict): endpoints=[] is_opticalband=has_opticalbands(xml_data=data_xml) - channel_namespace=extract_channel_xmlns(data_xml=data_xml,is_opticalband=is_opticalband) # channel_names=extract_channels_based_on_type(xml_data=data_xml) # if len(channel_names)==0 : channel_names= extract_channels_based_on_channelnamespace(xml_data=data_xml,channel_namespace=channel_namespace,is_opticalband=is_opticalband) - - lst_dic=[] + ports = extract_ports_based_on_type(data_xml) + optical_channels_params=[] + ports_result=[] if (is_opticalband): endpoints=channel_names else: for channel_name in channel_names: dic={} - for resource_key in resource_keys : + for resource_key in resource_keys : - if (resource_key != 'interface'): - dic=extract_value(dic=dic,resource_key=resource_key,xml_data=data_xml,channel_name=channel_name,channel_namespace=channel_namespace) + if (resource_key != 'admin-state'): + + dic=extract_value(dic=dic,resource_key=resource_key,xml_data=data_xml + ,channel_name=channel_name,channel_namespace=channel_namespace) + else : + dic = extract_status(dic=dic,resource_key=resource_key,xml_data=data_xml, channel_name=channel_name) dic["name"]=channel_name endpoints.append({"endpoint_uuid":{"uuid":channel_name}}) - lst_dic.append(dic) - transceivers_dic=extract_tranceiver(data_xml=data_xml,dic={}) - interfaces_dic=extract_interface(xml_data=data_xml,dic={}) + optical_channels_params.append(dic) + #transceivers_dic=extract_tranceiver(data_xml=data_xml,dic={}) + transceivers_dic={"transceiver":[]} + #interfaces_dic=extract_interface(xml_data=data_xml,dic={}) + if len(ports)>0 : + for port in ports : + endpoint_name,endpoint_id=port + resource_key = '/endpoints/endpoint[{:s}]'.format(endpoint_id) + resource_value = {'uuid': endpoint_id, 'type':endpoint_name} + ports_result.append((resource_key, resource_value)) + + + return [transceivers_dic,optical_channels_params,channel_namespace,endpoints,ports_result] + +######################################################################### + +#################################### ROADMAs ############################ + +########################################################################## + +def extract_roadm_ports (xml_data:str): + + ports =[] + pattern1 = r'\bMG_ON_OPTICAL_PORT_WAVEBAND\b' + pattern2 = r'\bMG_ON_OPTICAL_PORT_MEDIACHANNEL\b' + pattern3 = r'\bINPUT\b' + pattern4 = r'\bOUTPUT\b' + + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + with open('xml.log', 'w') as f: + print(xml_bytes, file=f) + + + namespace = {'oc': 'http://openconfig.net/yang/platform'} + ports_wb_in = [] + ports_mc_in = [] + ports_wb_out = [] + ports_mc_out = [] + components = root.findall('.//oc:component',namespace) + print(f"component {components}") + + + for component in components: + + properties = component.find(".//oc:properties",namespace) + name_element= component.find(".//oc:name",namespace) + print(name_element.text) + if (properties is not None): + wb_x = 0 + mc_x = 0 + in_x = 0 + out_x = 0 + for property in properties : + value = property.find(".//oc:value",namespace) + if (re.search(pattern1,value.text)): + wb_x = 1 + elif (re.search(pattern2,value.text)): + mc_x = 1 + elif (re.search(pattern3,value.text)): + in_x = 1 + elif (re.search(pattern4,value.text)): + out_x = 1 + if wb_x == 1: + if in_x ==1: + ports_wb_in.append(name_element.text) + elif out_x == 1: + ports_wb_out.append(name_element.text) + if mc_x == 1: + if in_x ==1: + ports_mc_in.append(name_element.text) + elif out_x == 1: + ports_mc_out.append(name_element.text) + + return ports_wb_in, ports_wb_out, ports_mc_in, ports_mc_out + + + +def roadm_values_extractor (data_xml:str,resource_keys:list,dic:dict): + ports_result=[] + ports_wb_in, ports_wb_out, ports_mc_in, ports_mc_out = extract_roadm_ports(data_xml) + + #if len(ports)>0 : + # for port in ports : + # + # resource_key = '/endpoints/endpoint[{:s}]'.format(port) + # resource_value = {'uuid': port, 'type':'MG_ON_OPTICAL_PORT_WAVEBAND'} + # ports_result.append((resource_key, resource_value)) + if len(ports_wb_in)>0 : + for port in ports_wb_in: + + resource_key = '/endpoints/endpoint[{:s}]'.format(port) + resource_value = {'uuid': port, 'type':'MG_ON_OPTICAL_PORT_WAVEBAND'} + ports_result.append((resource_key, resource_value)) + + return [ports_result] + + + + #/////////////// OpenRoadm ////////////// + + +def extract_roadm_circuits_pack (xml_data:str): + - return [transceivers_dic,interfaces_dic,lst_dic,channel_namespace,endpoints] \ No newline at end of file + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + # with open('xml.log', 'w') as f: + # print(xml_bytes, file=f) + + + namespace = {'oc': "http://org/openroadm/device"} + + circuits = root.findall('.//oc:circuit-packs',namespace) + + circuits_list =[] + # print(f"component {components}") + + if (circuits is not None): + circuit_info ={} + for circuit in circuits: + + circuit_name = circuit.find(".//oc:circuit-pack-name",namespace) + circuit_type=circuit.find(".//oc:circuit-pack-type",namespace) + circuit_adminstrative_status=circuit.find(".//oc:administrative-state",namespace) + circuit_equipment_state=circuit.find("./oc:equipment-state",namespace) + circuit_mode=circuit.find("./oc:circuit-pack-mode",namespace) + slot= circuit.find("./oc:slot",namespace) + shelf= circuit.find("./oc:shelf",namespace) + ports = circuit.findall("./oc:ports",namespace) + + circuit_ports=[] + if (ports is not None): + + for port in ports : + port_info={} + port_name=port.find('./oc:port-name',namespace) + port_qual= port.find("./oc:port-qual",namespace) + + if port_name is not None : + port_info["port_name"]=port_name.text + if port_qual is not None : + port_info["port_qual"]=port_qual.text + circuit_ports.append(port_info) + if (circuit_name is not None): + circuit_info["circuit_name"]=circuit_name.text + if (circuit_type is not None): + circuit_info["circuit_type"]=circuit_type.text + if (circuit_adminstrative_status is not None): + circuit_info["circuit_adminstrative_status"]=circuit_adminstrative_status.text + if (circuit_equipment_state is not None): + circuit_info["circuit_equipment_state"]=circuit_equipment_state.text + if (circuit_mode is not None): + circuit_info["circuit_mode"]=circuit_mode.text + if (slot is not None): + circuit_info["slot"]=slot.text + if (shelf is not None): + circuit_info["shelf"]=shelf.text + circuit_info["ports"]=circuit_ports + + circuits_list.append(circuit_info) + + + return circuits_list + + + +def extract_openroadm_info(xml_data:str): + roadm_info={"node-id":None,"node-number":None,"node-type":None,'clli':None} + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + namespace = {'oc': "http://org/openroadm/device"} + info = root.findall('.//oc:info',namespace) + if info is not None : + for i in info : + node_id= i.find('.//oc:node-id',namespace) + node_number= i.find('.//oc:node-number',namespace) + node_type=i.find('.//oc:node-type',namespace) + clli=i.find('.//oc:clli',namespace) + if (node_id is not None): + roadm_info['node-id']=node_id.text + if (node_number is not None): + roadm_info['node-number']=node_number.text + if (node_type is not None): + roadm_info['node-type']=node_type.text + if (clli is not None): + roadm_info['clli']=clli.text + return roadm_info diff --git a/src/device/service/drivers/oc_driver/templates/VPN/common.py b/src/device/service/drivers/oc_driver/templates/VPN/common.py new file mode 100644 index 0000000000000000000000000000000000000000..d84afc5563ad9cf1fbc7fda44800b90876ee302e --- /dev/null +++ b/src/device/service/drivers/oc_driver/templates/VPN/common.py @@ -0,0 +1,55 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +def seperate_port_config(resources:list,unwanted_keys=[])->list[list,dict,str]: + config=[] + ports={} + index=None + for item in resources : + if len(unwanted_keys)>0: + if (item['value'] is not None and (item['resource_key'] not in unwanted_keys)): + config.append({'resource_key':item['resource_key'], 'value':item['value']} ) + #if (item['resource_key'] == 'destination_port' or item['resource_key'] == 'source_port') and item['value'] is not None: + # ports[item['resource_key']]=item['value'] + if (item['resource_key'] == 'destination_port' or item['resource_key'] == 'source_port'): + ports[item['resource_key']]=item['value'] + if (item['resource_key']=='index' and item['value'] is not None) : + index=item['value'] + + return [config,ports,index] + +def extract_ports (resources:list): + if len(resources) ==0 :return + ports=[] + flow=next((i for i in resources if i['resource_key']=='handled_flow'),None) + if flow is not None: + ports = flow['value'] + return ports + +def filter_config(resources:list,unwanted_keys=[])->list[list,dict,str]: + config=[] + ports=() + index=None + for item in resources : + if len(unwanted_keys)>0: + if (item['value'] is not None and (item['resource_key'] not in unwanted_keys)): + config.append({'resource_key':item['resource_key'], 'value':item['value']} ) + if (item['resource_key']=='index' and item['value'] is not None) : + index=item['value'] + #if (item['resource_key'] == 'destination_port' or item['resource_key'] == 'source_port') and item['value'] is not None: + # ports[item['resource_key']]=item['value'] + ports = extract_ports(resources=resources) + + return [config,ports,index] diff --git a/src/device/service/drivers/oc_driver/templates/VPN/physical.py b/src/device/service/drivers/oc_driver/templates/VPN/physical.py index 0db6ffa5065ad3013250c3bde4dd160d8c12a498..11e6df5d99f8d365eeaeec3960da52f28c717551 100644 --- a/src/device/service/drivers/oc_driver/templates/VPN/physical.py +++ b/src/device/service/drivers/oc_driver/templates/VPN/physical.py @@ -34,14 +34,14 @@ def seperate_port_config(resources:list,unwanted_keys:list[str])->list[list,dict return [config,ports,index] -def create_optical_channel(resources): +def create_optical_channel(resources:list[dict],ports:list[dict],config:list[dict] ): - unwanted_keys=['destination_port','source_port','channel_namespace','optical-band-parent','index', 'name'] + #unwanted_keys=['destination_port','source_port','channel_namespace','optical-band-parent','index', 'name','admin-state'] results =[] - data={"name":i["value"] for i in resources if i["resource_key"]=="channel_name"} + data ={} data["channel_namespace"]=next((i["value"] for i in resources if i["resource_key"] == "channel_namespace"), None) - config,ports,index=seperate_port_config(resources,unwanted_keys=unwanted_keys) - + #config,ports,index=seperate_port_config(resources,unwanted_keys=unwanted_keys) + port_val = "" if 'destination_port' in ports and ports['destination_port'][0] is not None: port_val = ports['destination_port'][0] @@ -57,10 +57,18 @@ def create_optical_channel(resources): with tag('name'):text("channel-{}".format(port_val)) with tag('config'): with tag('name'):text("channel-{}".format(port_val)) - with tag('optical-channel',xmlns=data["channel_namespace"]): + #with tag('optical-channel', xmlns="http://example.com/flexscale-terminal-device"): + with tag('optical-channel', xmlns=data["channel_namespace"]): with tag('config'): for resource in config: with tag(resource['resource_key']):text(resource['value']) + # with tag('terminal-device', xmlns="http://openconfig.net/yang/terminal-device"): + # with tag('logical-channels'): + # with tag('channel'): + # with tag('index'):text("{}".format(port_val)) + # with tag('config'): + # with tag('index'):text("{}".format(port_val)) + # with tag('admin-state'):text("ENABLED") result = indent( doc.getvalue(), indentation = ' '*2, @@ -119,6 +127,7 @@ def create_optical_band (resources) : results =[] unwanted_keys=['destination_port','source_port','channel_namespace','frequency','optical-band-parent'] config,ports,index= seperate_port_config(resources,unwanted_keys=unwanted_keys) + doc, tag, text = Doc().tagtext() #with tag('config'): with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): @@ -166,6 +175,7 @@ def create_media_channel (resources): results=[] unwanted_keys=['destination_port','source_port','channel_namespace','frequency','operational-mode', 'optical-band-parent'] config,ports,index= seperate_port_config(resources,unwanted_keys=unwanted_keys) + doc, tag, text = Doc().tagtext() #with tag('config'): with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): @@ -206,5 +216,49 @@ def create_media_channel (resources): results.append(result) return results - - \ No newline at end of file + +def change_optical_channel_status (channel_name:str,state:str,ports:list[dict]) : + port_val="" + if 'destination_port' in ports and ports['destination_port'][0] is not None: + port_val = ports['destination_port'][0] + else: + port_val = ports['source_port'][0] + + results=[] + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + + with tag('terminal-device',xmlns="http://openconfig.net/yang/terminal-device"): + with tag("logical-channels"): + with tag('channel'): + with tag('index'):text("{}".format(port_val)) + with tag('config'): + with tag('admin-state'):text("{}".format(state)) + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + + + return results + + +def edit_optical_channel (resources:list[dict]): + unwanted_keys=['destination_port','source_port','channel_namespace','optical-band-parent','index', 'name','admin-state'] + config,ports,index=seperate_port_config(resources,unwanted_keys=unwanted_keys) + results = [] + channel_name=next((i["value"] for i in resources if i["resource_key"]=="channel_name" and i["value"] != None),None) + admin_state= next((i["value"] for i in resources if i["resource_key"]== "admin-state" and i["value"] != None) , None) + + + if channel_name is not None : + if (admin_state is not None): + results.extend(change_optical_channel_status(channel_name=channel_name,state=admin_state,ports=ports)) + if admin_state is None : + results.extend(create_optical_channel(resources=resources,ports=ports,config=config) ) + + return results diff --git a/src/device/service/drivers/oc_driver/templates/VPN/roadms.py b/src/device/service/drivers/oc_driver/templates/VPN/roadms.py new file mode 100644 index 0000000000000000000000000000000000000000..7e076588cc160cf22d773476119f8e91001a5053 --- /dev/null +++ b/src/device/service/drivers/oc_driver/templates/VPN/roadms.py @@ -0,0 +1,357 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + + +from yattag import Doc, indent +import logging +from .common import seperate_port_config ,filter_config + + + + +def create_media_channel_old (resources): + optical_band_namespaces="http://flex-scale-project.eu/yang/flex-scale-mg-on" + results=[] + unwanted_keys=['destination_port','source_port','channel_namespace' + ,'frequency','operational-mode','target-output-power', + "admin-state","flow_handled","channel_num"] + config,ports,index= seperate_port_config(resources,unwanted_keys=unwanted_keys) + + + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('media-channels'): + n = 0 + if 'destination_port' in ports: + n = len(ports['destination_port']) + else: + n = len(ports['source_port']) + for i in range(0, n): + #with tag('channel', operation="create"): + with tag('channel'): + with tag('index'):text(str(int(index)+i)) + with tag('config'): + #with tag('index'):text(index) + for resource in config: + + if resource['resource_key'] == "index": + with tag('index'):text(str(int(index)+i)) + elif resource['resource_key']== 'optical-band-parent' : + with tag('optical-band-parent',xmlns=optical_band_namespaces):text(resource['value']) + else: + with tag(resource['resource_key']):text(resource['value']) + if ('destination_port' in ports) and (ports['destination_port'][i] is not None): + with tag('dest'): + with tag('config'): + with tag('port-name'):text(ports['destination_port'][i]) + if ('source_port' in ports) and (ports['source_port'][i] is not None): + with tag('source'): + with tag('config'): + with tag('port-name'):text(ports['source_port'][i]) + + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results + + + + +def create_media_channel (resources): + optical_band_namespaces="http://flex-scale-project.eu/yang/flex-scale-mg-on" + results=[] + unwanted_keys=['destination_port','source_port','channel_namespace' + ,'frequency','operational-mode','target-output-power', + "admin-state","handled_flow","channel_num"] + + config,ports,index=filter_config(resources,unwanted_keys) + + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('media-channels'): + n = 0 + + for flow in ports: + src,dest=flow + #with tag('channel', operation="create"): + with tag('channel'): + with tag('index'):text(str(int(index)+n)) + with tag('config'): + #with tag('index'):text(index) + for resource in config: + + if resource['resource_key'] == "index": + with tag('index'):text(str(int(index)+n)) + elif resource['resource_key']== 'optical-band-parent' : + with tag('optical-band-parent',xmlns=optical_band_namespaces):text(resource['value']) + else: + with tag(resource['resource_key']):text(resource['value']) + if dest is not None and dest != '0': + with tag('dest'): + with tag('config'): + with tag('port-name'):text(dest) + if src is not None and src != '0': + with tag('source'): + with tag('config'): + with tag('port-name'):text(src) + n+=1 + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results + + + + + +def create_media_channel_v2 (resources): + optical_band_namespaces="http://flex-scale-project.eu/yang/flex-scale-mg-on" + results=[] + unwanted_keys=['destination_port','source_port','channel_namespace' + ,'frequency','operational-mode','target-output-power', + "handled_flow","channel_num"] + + config,ports,index=filter_config(resources,unwanted_keys) + + n = 0 + for flow in ports: + doc, tag, text = Doc().tagtext() + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('media-channels'): + + + src,dest=flow + with tag('channel', operation="create"): + #with tag('channel'): + with tag('index'):text(str(int(index)+n)) + with tag('config'): + #with tag('index'):text(index) + for resource in config: + + if resource['resource_key'] == "index": + with tag('index'):text(str(int(index)+n)) + elif resource['resource_key']== 'optical-band-parent' : + with tag('optical-band-parent',xmlns=optical_band_namespaces):text(int(resource['value'])+int(n)) + elif resource['resource_key']== 'admin-state' : + with tag('admin-status'):text(resource['value']) + else: + with tag(resource['resource_key']):text(resource['value']) + + + if src is not None and src != '0': + with tag('source'): + with tag('config'): + with tag('port-name'):text(src) + if dest is not None and dest != '0': + with tag('dest'): + with tag('config'): + with tag('port-name'):text(dest) + n+=1 + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results + + + + +def create_optical_band_old (resources) : + results =[] + unwanted_keys=['destination_port','source_port','channel_namespace','frequency','optical-band-parent','flow_handled'] + config,ports,index= seperate_port_config(resources,unwanted_keys=unwanted_keys) + + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('optical-bands',xmlns="http://flex-scale-project.eu/yang/flex-scale-mg-on"): + n = 0 + if 'destination_port' in ports: + n = len(ports['destination_port']) + else: + n = len(ports['source_port']) + for i in range(0, n): + #with tag('optical-band', operation="create"): + with tag('optical-band'): + if index is not None: + with tag('index'):text(str(int(index)+i)) + with tag('config'): + #if index is not None: + # with tag('index'):text(str(int(index)+i)) + for resource in config: + if resource['resource_key'] == "index": + with tag('index'):text(str(int(index)+i)) + else: + with tag(resource['resource_key']):text(resource['value']) + with tag('admin-status'):text('ENABLED') + #with tag('fiber-parent'):text(ports['destination_port'] if 'destination_port' in ports else ports['source_port']) + if ('destination_port' in ports) and (ports['destination_port'][i] is not None): + with tag('dest'): + with tag('config'): + with tag('port-name'):text(ports['destination_port'][i]) + if ('source_port' in ports) and (ports['source_port'][i] is not None): + with tag('source'): + with tag('config'): + with tag('port-name'):text(ports['source_port'][i]) + + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results + + + + +def create_optical_band (resources) : + results =[] + unwanted_keys=['destination_port','source_port','channel_namespace','frequency','optical-band-parent','handled_flow'] + config,ports,index= filter_config(resources,unwanted_keys=unwanted_keys) + + #with tag('config'): + n = 0 + for flow in ports: + doc, tag, text = Doc().tagtext() + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('optical-bands',xmlns="http://flex-scale-project.eu/yang/flex-scale-mg-on"): + + + #with tag('optical-band', operation="create"): + src,dest=flow + + with tag('optical-band'): + if index is not None: + with tag('index'):text(str(int(index)+n)) + with tag('config'): + #if index is not None: + # with tag('index'):text(str(int(index)+i)) + for resource in config: + if resource['resource_key'] == "index": + with tag('index'):text(str(int(index)+n)) + else: + with tag(resource['resource_key']):text(resource['value']) + with tag('admin-status'):text('ENABLED') + #with tag('fiber-parent'):text(ports['destination_port'] if 'destination_port' in ports else ports['source_port']) + if dest is not None and dest != '0': + with tag('dest'): + with tag('config'): + with tag('port-name'):text(dest) + if src is not None and src !='0': + with tag('source'): + with tag('config'): + with tag('port-name'):text(src) + n +=1 + + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results + + +def disable_media_channel (resources): + + results=[] + unwanted_keys=['destination_port','source_port','channel_namespace','frequency','operational-mode', 'optical-band-parent'] + config,ports,index= seperate_port_config(resources,unwanted_keys=unwanted_keys) + + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('media-channels'): + with tag("channel",operation="delete"): + with tag('index'):text(str(int(index))) + with tag('config'): + with tag('index'):text(str(int(index))) + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results + +def disable_optical_band (resources:list,state:str): + results=[] + unwanted_keys=['destination_port','source_port','channel_namespace','frequency','operational-mode', 'optical-band-parent'] + config,ports,index= seperate_port_config(resources,unwanted_keys=unwanted_keys) + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('optical-bands',xmlns="http://flex-scale-project.eu/yang/flex-scale-mg-on"): + with tag('optical-band'): + if index is not None: + with tag('index'):text(index) + with tag('config'): + with tag('index'):text(index) + with tag('admin-status'):text(state) + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results + + +def delete_optical_band (resources:list): + results=[] + unwanted_keys=['destination_port','source_port','channel_namespace','frequency','operational-mode', 'optical-band-parent'] + config,ports,index= seperate_port_config(resources,unwanted_keys=unwanted_keys) + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('wavelength-router', xmlns="http://openconfig.net/yang/wavelength-router"): + with tag('optical-bands',xmlns="http://flex-scale-project.eu/yang/flex-scale-mg-on"): + with tag('optical-band',operation="delete"): + if index is not None: + with tag('index'):text(index) + with tag('config'): + with tag('index'):text(index) + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + return results diff --git a/src/device/service/drivers/oc_driver/templates/VPN/transponder.py b/src/device/service/drivers/oc_driver/templates/VPN/transponder.py new file mode 100644 index 0000000000000000000000000000000000000000..a41c7e9a0853a371bf1f6d8d343913c52f9365ac --- /dev/null +++ b/src/device/service/drivers/oc_driver/templates/VPN/transponder.py @@ -0,0 +1,157 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +from yattag import Doc, indent +import logging + +from .common import seperate_port_config + +def add_transceiver (transceiver_name:str): + + doc, tag, text = Doc().tagtext() + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('components', xmlns="http://openconfig.net/yang/platform"): + with tag('component'): + with tag('name'):text(transceiver_name) + with tag("config"): + with tag('name'):text(transceiver_name) + with tag("state"): + with tag('name'):text(transceiver_name) + with tag("type",('xmlns:oc-platform-types',"http://openconfig.net/yang/platform-types")):text("oc-platform-types:TRANSCEIVER") + with tag("transceiver",xmlns="http://openconfig.net/yang/platform/transceiver"): + with tag("config"): + with tag("enabled"):text("true") + with tag("form-factor-preconf",("xmlns:oc-opt-types","http://openconfig.net/yang/transport-types")):text("oc-opt-types:QSFP56_DD_TYPE1") + with tag("ethernet-pmd-preconf",("xmlns:oc-opt-types","http://openconfig.net/yang/transport-types")):text("oc-opt-types:ETH_400GBASE_ZR") + with tag("fec-mode",("xmlns:oc-platform-types","http://openconfig.net/yang/platform-types")):text("oc-platform-types:FEC_AUTO") + with tag("module-functional-type",("xmlns:oc-opt-types","http://openconfig.net/yang/transport-types")):text("oc-opt-types:TYPE_DIGITAL_COHERENT_OPTIC") + with tag("state"): + with tag("enabled"):text("true") + with tag("form-factor-preconf",("xmlns:oc-opt-types","http://openconfig.net/yang/transport-types")):text("oc-opt-types:QSFP56_DD_TYPE1") + with tag("ethernet-pmd-preconf",("xmlns:oc-opt-types","http://openconfig.net/yang/transport-types")):text("oc-opt-types:ETH_400GBASE_ZR") + with tag("fec-mode",("xmlns:oc-platform-types","http://openconfig.net/yang/platform-types")):text("oc-platform-types:FEC_AUTO") + with tag("module-functional-type",("xmlns:oc-opt-types","http://openconfig.net/yang/transport-types")):text("oc-opt-types:TYPE_DIGITAL_COHERENT_OPTIC") + with tag("vendor"):text("Cisco") + with tag("vendor-part"):text("400zr-QSFP-DD") + with tag("vendor-rev"):text("01") + with tag("serial-no"):text("1567321") + with tag("physical-channels"): + with tag("channel"): + with tag("index"):text("1") + with tag("config"): + with tag("index"):text("1") + with tag("associated-optical-channel"):text("channel-4") + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + + + return result + + +def create_optical_channel(resources:list[dict],ports:list[dict],config:list[dict] ): + + #unwanted_keys=['destination_port','source_port','channel_namespace','optical-band-parent','index', 'name','admin-state'] + results =[] + data ={} + data["channel_namespace"]=next((i["value"] for i in resources if i["resource_key"] == "channel_namespace"), None) + #config,ports,index=seperate_port_config(resources,unwanted_keys=unwanted_keys) + + port_val = "" + if 'destination_port' in ports and ports['destination_port'][0] is not None: + port_val = ports['destination_port'][0] + else: + port_val = ports['source_port'][0] + + + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + with tag('components', xmlns="http://openconfig.net/yang/platform"): + with tag('component'): + with tag('name'):text("channel-{}".format(port_val)) + with tag('config'): + with tag('name'):text("channel-{}".format(port_val)) + with tag('optical-channel',xmlns=data["channel_namespace"]): + with tag('config'): + for resource in config: + with tag(resource['resource_key']):text(resource['value']) + with tag('terminal-device', xmlns="http://openconfig.net/yang/terminal-device"): + with tag('logical-channels'): + with tag('channel'): + with tag('index'):text("{}".format(port_val)) + with tag('config'): + with tag('index'):text("{}".format(port_val)) + with tag('admin-state'):text("ENABLED") + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + + + return results + + +def change_optical_channel_status (state:str,ports:list[dict]) : + port_val="" + if 'destination_port' in ports and ports['destination_port'][0] is not None: + port_val = ports['destination_port'][0] + else: + port_val = ports['source_port'][0] + + results=[] + doc, tag, text = Doc().tagtext() + #with tag('config'): + with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"): + + with tag('terminal-device',xmlns="http://openconfig.net/yang/terminal-device"): + with tag("logical-channels"): + with tag('channel'): + with tag('index'):text("{}".format(port_val)) + with tag('config'): + with tag('admin-state'):text("{}".format(state)) + + result = indent( + doc.getvalue(), + indentation = ' '*2, + newline = '' + ) + results.append(result) + + + return results + + +def edit_optical_channel (resources:list[dict]): + + unwanted_keys=['destination_port','source_port','channel_namespace' + ,'optical-band-parent','index', 'name','admin-state','handled_flow'] + config,ports,index=seperate_port_config(resources,unwanted_keys=unwanted_keys) + results = [] + # channel_name=next((i["value"] for i in resources if i["resource_key"]=="channel_name" and i["value"] != None),None) + # admin_state= next((i["value"] for i in resources if i["resource_key"]== "admin-state" and i["value"] != None) , None) + + + + # results.extend(change_optical_channel_status(state=admin_state,ports=ports)) + # else : + + results.extend(create_optical_channel(resources=resources,ports=ports,config=config) ) + + return results diff --git a/src/device/service/drivers/oc_driver/templates/descovery_tool/roadms.py b/src/device/service/drivers/oc_driver/templates/descovery_tool/roadms.py new file mode 100644 index 0000000000000000000000000000000000000000..e27fd923a4d3ec4a69b810667545d5bcae235269 --- /dev/null +++ b/src/device/service/drivers/oc_driver/templates/descovery_tool/roadms.py @@ -0,0 +1,260 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 re +import lxml.etree as ET + +def extract_channel_xmlns (data_xml:str,is_opticalband:bool): + xml_bytes = data_xml.encode("utf-8") + root = ET.fromstring(xml_bytes) + + namespace=None + channels=None + + if (not is_opticalband) : + + optical_channel_namespaces = { + 'ns': 'urn:ietf:params:xml:ns:netconf:base:1.0', + 'oc': 'http://openconfig.net/yang/platform', + } + + channels= root.find('.//{*}optical-channel',optical_channel_namespaces) + if channels is not None : + optical_channel_namespace = channels.tag.replace("optical-channel", "") + namespace=optical_channel_namespace.replace("{", "").replace("}", "") + else : + optical_band_namespaces= { + 'oc':'http://openconfig.net/yang/wavelength-router' + } + + channels= root.find('.//{*}optical-bands',optical_band_namespaces) + if channels is not None: + optical_channel_namespace = channels.tag.replace("optical-bands", "") + namespace=optical_channel_namespace.replace("{", "").replace("}", "") + return namespace + +def extract_optical_bands (data_xml:str,namespace:str): + namespaces={"oc":namespace} + xml_bytes = data_xml.encode("utf-8") + root = ET.fromstring(xml_bytes) + op_bands=[] + optical_bands= root.find('.//oc:optical-bands',namespaces) + + if optical_bands is not None : + optical_bands_ele= optical_bands.findall('.//oc:optical-band',namespaces) + + for optical_band in optical_bands_ele: + band_ele=optical_band.find('.//oc:name',namespaces) + lower_freq_ele=optical_band.find('.//oc:lower-frequency',namespaces) + upper_freq_ele=optical_band.find('.//oc:upper-frequency',namespaces) + admin_status_ele=optical_band.find('.//oc:admin-status',namespaces) + source_ele=optical_band.find('.//oc:source/oc:config/oc:port-name',namespaces) + dest_ele=optical_band.find('.//oc:dest/oc:config/oc:port-name',namespaces) + channel_index= optical_band.find('.//oc:index',namespaces) + op_band_obj={ + 'band_name':band_ele.text if band_ele is not None else None, + 'lower_frequency':lower_freq_ele.text if lower_freq_ele is not None else None, + 'upper_frequency':upper_freq_ele.text if upper_freq_ele is not None else None, + 'status':admin_status_ele.text if admin_status_ele is not None else None, + 'src_port':source_ele.text if source_ele is not None else None, + 'dest_port':dest_ele.text if dest_ele is not None else None, + "channel_index":channel_index.text if channel_index is not None else None + } + op_bands.append(op_band_obj) + + return op_bands + +def extract_media_channels (data_xml:str): + optical_band_namespaces="http://flex-scale-project.eu/yang/flex-scale-mg-on" + namespaces={"oc":"http://openconfig.net/yang/wavelength-router",'ob_parent':optical_band_namespaces} + xml_bytes = data_xml.encode("utf-8") + root = ET.fromstring(xml_bytes) + media_channels= root.find(f'.//oc:media-channels',namespaces) + op_bands=[] + if media_channels is not None : + media_channels_ele= media_channels.findall('.//oc:channel',namespaces) + for optical_band in media_channels_ele: + band_ele=optical_band.find('.//oc:name',namespaces) + lower_freq_ele=optical_band.find('.//oc:lower-frequency',namespaces) + upper_freq_ele=optical_band.find('.//oc:upper-frequency',namespaces) + admin_status_ele=optical_band.find('.//oc:admin-status',namespaces) + source_ele=optical_band.find('.//oc:source/oc:config/oc:port-name',namespaces) + dest_ele=optical_band.find('.//oc:dest/oc:config/oc:port-name',namespaces) + ob_parent=optical_band.find('.//ob_parent:optical-band-parent',namespaces) + channel_index= optical_band.find('.//oc:index',namespaces) + op_band_obj={ + 'band_name':band_ele.text if band_ele is not None else None, + 'lower_frequency':lower_freq_ele.text if lower_freq_ele is not None else None, + 'upper_frequency':upper_freq_ele.text if upper_freq_ele is not None else None, + 'status':admin_status_ele.text if admin_status_ele is not None else None, + 'src_port':source_ele.text if source_ele is not None else None, + 'dest_port':dest_ele.text if dest_ele is not None else None, + 'optical_band_parent':ob_parent.text if ob_parent is not None else None, + 'channel_index':channel_index.text if channel_index is not None else None + } + op_bands.append(op_band_obj) + + return op_bands + +def extract_roadm_ports_old (xml_data:str): + ports =[] + pattern = r'\bMG_ON_OPTICAL_PORT_WAVEBAND\b' + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + with open('xml.log', 'w') as f: + print(xml_bytes, file=f) + + namespace = {'oc': 'http://openconfig.net/yang/platform'} + ports = [] + components = root.findall('.//oc:component',namespace) + print(f"component {components}") + + for component in components: + properties = component.find(".//oc:properties",namespace) + if (properties is not None): + for property in properties : + value = property.find(".//oc:value",namespace) + if (re.search(pattern,value.text)): + name_element= component.find(".//oc:name",namespace) + ports.append(name_element.text) + return ports + +def extract_roadm_ports (xml_data:str): + ports =[] + pattern2=r'\bMG_ON_PORT_TYPE' + pattern = r'\bMG_ON_OPTICAL_PORT_WAVEBAND\b' + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + + namespace = {'oc': 'http://openconfig.net/yang/platform'} + ports = [] + components = root.findall('.//oc:component',namespace) + #print(f"component {components}") + + for component in components: + properties = component.find(".//oc:properties",namespace) + if (properties is not None): + for property in properties : + value = property.find(".//oc:value",namespace) + name= property.find('.//oc:name',namespace) + if (re.search(pattern2,name.text)): + value = property.find(".//oc:value",namespace) + name_element= component.find(".//oc:name",namespace) + print('value',value.text) + ports.append((name_element.text,value.text)) + return ports + +def roadm_values_extractor (data_xml:str,resource_keys:list,dic:dict): + ports_result=[] + ports = extract_roadm_ports(data_xml) + namespcae= extract_channel_xmlns(data_xml,True) + optical_bands=extract_optical_bands(data_xml=data_xml,namespace=namespcae) + media_cahannels=extract_media_channels(data_xml) + if len(ports)>0 : + for port in ports : + name,type=port + resource_key = '/endpoints/endpoint[{:s}]'.format(name) + resource_value = {'uuid': name, 'type':type} + ports_result.append((resource_key, resource_value)) + return [ports_result,optical_bands,media_cahannels] + +#/////////////// OpenRoadm ////////////// + +def extract_roadm_circuits_pack (xml_data:str): + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + # with open('xml.log', 'w') as f: + # print(xml_bytes, file=f) + + namespace = {'oc': "http://org/openroadm/device"} + circuits = root.findall('.//oc:circuit-packs',namespace) + circuits_list =[] + # print(f"component {components}") + if (circuits is not None): + for circuit in circuits: + circuit_info ={} + circuit_ports=[] + circuit_name = circuit.find(".//oc:circuit-pack-name",namespace) + circuit_type=circuit.find(".//oc:circuit-pack-type",namespace) + circuit_adminstrative_status=circuit.find(".//oc:administrative-state",namespace) + circuit_equipment_state=circuit.find("./oc:equipment-state",namespace) + circuit_mode=circuit.find("./oc:circuit-pack-mode",namespace) + slot= circuit.find("./oc:slot",namespace) + shelf= circuit.find("./oc:shelf",namespace) + ports = circuit.findall("./oc:ports",namespace) + + if (ports is not None): + for port in ports : + port_info={} + port_name=port.find('./oc:port-name',namespace) + port_qual= port.find("./oc:port-qual",namespace) + if port_name is not None : + port_info["port_name"]=port_name.text + if port_qual is not None : + port_info["port_qual"]=port_qual.text + circuit_ports.append(port_info) + if (circuit_name is not None): + circuit_info["circuit_name"]=circuit_name.text + if (circuit_type is not None): + circuit_info["circuit_type"]=circuit_type.text + if (circuit_adminstrative_status is not None): + circuit_info["circuit_adminstrative_status"]=circuit_adminstrative_status.text + if (circuit_equipment_state is not None): + circuit_info["circuit_equipment_state"]=circuit_equipment_state.text + if (circuit_mode is not None): + circuit_info["circuit_mode"]=circuit_mode.text + if (slot is not None): + circuit_info["slot"]=slot.text + if (shelf is not None): + circuit_info["shelf"]=shelf.text + circuit_info["ports"]=circuit_ports + circuits_list.append(circuit_info) + return circuits_list + +def extract_openroadm_info(xml_data:str): + roadm_info={"node-id":None,"node-number":None,"node-type":None,'clli':None} + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + namespace = {'oc': "http://org/openroadm/device"} + info = root.findall('.//oc:info',namespace) + if info is not None : + for i in info : + node_id= i.find('.//oc:node-id',namespace) + node_number= i.find('.//oc:node-number',namespace) + node_type=i.find('.//oc:node-type',namespace) + clli=i.find('.//oc:clli',namespace) + if (node_id is not None): + roadm_info['node-id']=node_id.text + if (node_number is not None): + roadm_info['node-number']=node_number.text + if (node_type is not None): + roadm_info['node-type']=node_type.text + if (clli is not None): + roadm_info['clli']=clli.text + return roadm_info + +def openroadm_values_extractor (data_xml:str,resource_keys:list,dic:dict): + ports_result=[] + openroadm_info= extract_openroadm_info(data_xml) + circuits_list = extract_roadm_circuits_pack(data_xml) + dic["openroadm_info"]=openroadm_info + dic["circuits"]=circuits_list + + for circuit in circuits_list : + for port in circuit['ports']: + if port is not None and 'port_name' in port : + resource_key = '/endpoints/endpoint[{:s}]'.format(port["port_name"]) + resource_value = {'uuid': port["port_name"], 'type':port["port_qual"] if "port_qual" in port else None} + ports_result.append((resource_key, resource_value)) + return [dic,ports_result] diff --git a/src/device/service/drivers/oc_driver/templates/descovery_tool/transponders.py b/src/device/service/drivers/oc_driver/templates/descovery_tool/transponders.py new file mode 100644 index 0000000000000000000000000000000000000000..e0ffc12ffd63f2e5b32ea4c7a813acee7d146c58 --- /dev/null +++ b/src/device/service/drivers/oc_driver/templates/descovery_tool/transponders.py @@ -0,0 +1,301 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 re,logging +import json +import lxml.etree as ET +from typing import Collection, Dict, Any + + + +def add_value_from_tag(target : Dict, field_name: str, field_value : ET.Element, cast=None) -> None: + if isinstance(field_value,str) or field_value is None or field_value.text is None: return + field_value = field_value.text + if cast is not None: field_value = cast(field_value) + target[field_name] = field_value + +def add_value_from_collection(target : Dict, field_name: str, field_value : Collection) -> None: + if field_value is None or len(field_value) == 0: return + target[field_name] = field_value + + +def generate_templates(resource_key: str, resource_value: str, channel:str) -> str: # template management to be configured + + result_templates = [] + data={} + data['name']=channel + data['resource_key']=resource_key + data['value']=resource_value + #result_templates.append(create_physical_config(data)) + + return result_templates + + +def extract_status (dic:dict,resource_key:str,xml_data:str,channel_name:str): + + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + channel_name=channel_name if 'index' not in channel_name else channel_name['index'] + index=None + if channel_name.find('-') != -1 : + index= channel_name.split("-")[1] + + + namespaces = { "td": "http://openconfig.net/yang/terminal-device"} + channels = root.findall(f".//td:terminal-device/td:logical-channels/td:channel",namespaces) + for channel in channels : + + index_ele= channel.find(f".//td:config[td:index='{index}']/td:{resource_key}",namespaces) + if index_ele is not None : + dic["status"]=index_ele.text + print(index_ele.text) + return dic + + +def extract_channel_xmlns (data_xml:str,is_opticalband:bool): + xml_bytes = data_xml.encode("utf-8") + root = ET.fromstring(xml_bytes) + + namespace=None + channels=None + + if (not is_opticalband) : + + optical_channel_namespaces = { + 'ns': 'urn:ietf:params:xml:ns:netconf:base:1.0', + 'oc': 'http://openconfig.net/yang/platform', + } + + channels= root.find('.//{*}optical-channel',optical_channel_namespaces) + if channels is not None : + optical_channel_namespace = channels.tag.replace("optical-channel", "") + namespace=optical_channel_namespace.replace("{", "").replace("}", "") + else : + optical_band_namespaces= { + 'oc':'http://openconfig.net/yang/wavelength-router' + } + + channels= root.find('.//{*}optical-bands',optical_band_namespaces) + if channels is not None: + optical_channel_namespace = channels.tag.replace("optical-bands", "") + namespace=optical_channel_namespace.replace("{", "").replace("}", "") + + + return namespace + +def extract_channels_based_on_channelnamespace (xml_data:str,channel_namespace:str,is_opticalband:bool): + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + channels=[] + + # Find the component names whose children include the "optical-channel" element + if (not is_opticalband): + namespace = {'namespace': 'http://openconfig.net/yang/platform','cn':channel_namespace} + + component_names = root.findall('.//namespace:component[cn:optical-channel]',namespace) + + # Extract and print the component names + for component in component_names: + component_name = component.find('namespace:name', namespace).text + channels.append({"index":component_name}) + else : + namespaces = { + 'wr': 'http://openconfig.net/yang/wavelength-router', + 'fs': channel_namespace + } + + wl = root.findall('.//fs:optical-band',namespaces=namespaces) + + for component in wl : + index=component.find('.//fs:index',namespaces).text + dest_port_name = component.find('.//fs:dest/fs:config/fs:port-name', namespaces).text + + # Retrieve port-name for source (assuming it exists in the XML structure) + source_port_name = component.find('.//fs:source/fs:config/fs:port-name', namespaces).text + channels.append({"index":index,"endpoints":(source_port_name,dest_port_name)}) + + # Retrieve port-name for dest + + return channels + +def extract_channels_based_on_type (xml_data:str): + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + + namespace = {'oc': 'http://openconfig.net/yang/platform', 'typex': 'http://openconfig.net/yang/platform-types'} + channel_names = [] + components = root.findall('.//oc:component', namespace) + for component in components: + + type_element = component.find('.//oc:state/oc:type[.="oc-opt-types:OPTICAL_CHANNEL"]',namespaces=namespace) + + if type_element is not None and type_element.text == 'oc-opt-types:OPTICAL_CHANNEL': + name_element = component.find('oc:name', namespace) + if name_element is not None: + channel_names.append(name_element.text) + return channel_names + +def extract_value(resource_key:str,xml_data:str,dic:dict,channel_name:str,channel_namespace:str): + + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + channel_name=channel_name if 'index' not in channel_name else channel_name['index'] + namespace = {'oc': 'http://openconfig.net/yang/platform', + 'td': channel_namespace} + + element = root.find(f'.//oc:component[oc:name="{channel_name}"]', namespace) + + if element is not None: + parameter= element.find(f'.//td:{resource_key}',namespace) + if (parameter is not None): + value = parameter.text + dic[resource_key]=value + else : + logging.info("parameter is None") + + else: + logging.info("element is None") + print(" element not found.") + + return dic + + +def extract_port_value (xml_string:list,port_name:str): + + xml_bytes = xml_string.encode("utf-8") + root = ET.fromstring(xml_bytes) + + namespace = {"oc": "http://openconfig.net/yang/platform"} + component=root.find(f".//oc:component[oc:name='{port_name}']", namespace) + onos_index = component.find( + f".//oc:property//oc:state/oc:name[.='onos-index']/../oc:value", namespace + ).text + + return (port_name,onos_index) + + + + +def extract_tranceiver (data_xml:str,dic:dict): + xml_bytes = data_xml.encode("utf-8") + root = ET.fromstring(xml_bytes) + namespaces = { + 'ns': 'urn:ietf:params:xml:ns:netconf:base:1.0', + 'oc': 'http://openconfig.net/yang/platform', + 'oc-terminal': 'http://openconfig.net/yang/terminal-device', + 'oc-platform-types': 'http://openconfig.net/yang/platform-types' + } + + + transceiver_components = root.findall('.//oc:component/oc:state/[oc:type="oc-platform-types:TRANSCEIVER"]../oc:state/oc:name', namespaces) + + component_names = [component.text for component in transceiver_components] + dic['transceiver']=component_names + return dic + +def extract_interface (xml_data:str,dic:dict): + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + namespaces = { + 'ns': 'urn:ietf:params:xml:ns:netconf:base:1.0', + 'oc': 'http://openconfig.net/yang/interfaces', + } + ip_namespaces = { + 'oc': 'http://openconfig.net/yang/interfaces', + 'ip': 'http://openconfig.net/yang/interfaces/ip', + } + + interfaces = root.findall('.//oc:interfaces/oc:interface', namespaces) + interface_names = [interface.find('oc:name', namespaces).text for interface in interfaces] + interface_enabled=[interface.find('oc:config/oc:enabled', namespaces).text for interface in interfaces] + ip_address_element = root.find('.//ip:ip', ip_namespaces) + interface_prefix_length=root.find('.//ip:prefix-length',ip_namespaces) + if (len(interface_names) > 0): + dic['interface']={"name":interface_names[0],'ip':ip_address_element.text,'enabled':interface_enabled[0],"prefix-length":interface_prefix_length.text} + else : + dic['interface']={} + return dic + +def has_opticalbands(xml_data:str): + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + + has_opticalbands=False + elements= root.find('.//{*}optical-bands') + + if (elements is not None and len(elements) >0): + has_opticalbands=True + else : + has_opticalbands=False + return has_opticalbands + +def extract_ports_based_on_type (xml_data:str): + pattern = r':\s*PORT\b' + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + namespace = {'oc': 'http://openconfig.net/yang/platform', 'typex': 'http://openconfig.net/yang/platform-types'} + ports = [] + components = root.findall(".//oc:state[oc:type]",namespace) + for component in components: + type_ele = component.find(".//oc:type",namespace) + match = re.search(pattern, type_ele.text) + if match is not None : + name_element= component.find(".//oc:name",namespace) + port_name =name_element.text + port_index=name_element.text.split("-")[1] + port = (port_name,port_index) + ports.append(port) + return ports + +def transponder_values_extractor(data_xml:str,resource_keys:list,dic:dict): + + endpoints=[] + is_opticalband=has_opticalbands(xml_data=data_xml) + channel_namespace=extract_channel_xmlns(data_xml=data_xml,is_opticalband=is_opticalband) + # channel_names=extract_channels_based_on_type(xml_data=data_xml) + # if len(channel_names)==0 : + channel_names= extract_channels_based_on_channelnamespace(xml_data=data_xml,channel_namespace=channel_namespace,is_opticalband=is_opticalband) + + ports = extract_ports_based_on_type(data_xml) + optical_channels_params=[] + ports_result=[] + if (is_opticalband): + endpoints=channel_names + else: + + for channel_name in channel_names: + dic={} + for resource_key in resource_keys : + + if (resource_key != 'admin-state'): + + dic=extract_value(dic=dic,resource_key=resource_key,xml_data=data_xml + ,channel_name=channel_name,channel_namespace=channel_namespace) + else : + dic = extract_status(dic=dic,resource_key=resource_key,xml_data=data_xml, channel_name=channel_name) + dic["name"]=channel_name + endpoints.append({"endpoint_uuid":{"uuid":channel_name}}) + optical_channels_params.append(dic) + #transceivers_dic=extract_tranceiver(data_xml=data_xml,dic={}) + transceivers_dic={"transceiver":[]} + #interfaces_dic=extract_interface(xml_data=data_xml,dic={}) + if len(ports)>0 : + for port in ports : + endpoint_name,endpoint_id=port + resource_key = '/endpoints/endpoint[{:s}]'.format(endpoint_id) + resource_value = {'uuid': endpoint_id, 'type':endpoint_name} + ports_result.append((resource_key, resource_value)) + + + return [transceivers_dic,optical_channels_params,channel_namespace,endpoints,ports_result] diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py index 0febb7b1f470bf86dc30754c1db2af262779a25d..97e097c8a94382b71903b4a57ab66382beec5eb2 100644 --- a/src/opticalcontroller/OpticalController.py +++ b/src/opticalcontroller/OpticalController.py @@ -12,19 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +import time from flask import Flask from flask import render_template from flask_restplus import Resource, Api - from tools import * from variables import * from RSA import RSA -import time -import logging +from common.proto.context_pb2 import TopologyId +from google.protobuf.json_format import MessageToDict +global rsa +global links_dict rsa = None -LOGGER = logging.getLogger(__name__) + app = Flask(__name__) api = Api(app, version='1.0', title='Optical controller API', @@ -47,7 +49,7 @@ class AddLightpath(Resource): @staticmethod def put(src, dst, bitrate, bidir=1): - LOGGER.info("INFO: New Lightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) + print("INFO: New Lightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) t0 = time.time()*1000.0 if debug: rsa.g.printGraph() @@ -56,9 +58,9 @@ class AddLightpath(Resource): flow_id = rsa.rsa_computation(src, dst, bitrate, bidir) if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 - t1 = time.time()*1000.0 + t1 = time.time() * 1000.0 elapsed = t1 - t0 - LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + print("INFO: time elapsed = {} ms".format(elapsed)) return rsa.db_flows[flow_id], 200 else: return "Error", 404 @@ -74,18 +76,15 @@ class AddLightpath(Resource): @optical.response(404, 'Error, not found') class AddFlexLightpath(Resource): @staticmethod - def put(src, dst, bitrate,bidir=1, band=None): - + def put(src, dst, bitrate, bidir=1, band=None): + print("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) - LOGGER.info("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) t0 = time.time()*1000.0 if debug: rsa.g.printGraph() if rsa is not None: flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band) - print (f"flow_id {flow_id} and optical_band_id {optical_band_id} ") - LOGGER.debug('flow_id={:s} rsa.db_flows={:s}'.format(str(flow_id), str(rsa.db_flows))) if flow_id is not None: if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 @@ -100,52 +99,125 @@ class AddFlexLightpath(Resource): else: t1 = time.time() * 1000.0 elapsed = t1 - t0 - LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + print("INFO: time elapsed = {} ms".format(elapsed)) return rsa.optical_bands[optical_band_id], 200 else: return "Error", 404 -@optical.route('/DelFlexLightpath/<int:flow_id>/<string:src>/<string:dst>/<int:bitrate>/<int:o_band_id>') + +# @optical.route('/DelFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:o_band_id>') +@optical.route('/DelFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:o_band_id>') +@optical.route('/DelFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:o_band_id>/<int:flow_id>') @optical.response(200, 'Success') @optical.response(404, 'Error, not found') -class DelLightpath(Resource): +class DelFLightpath(Resource): @staticmethod - def delete(flow_id, src, dst, bitrate, o_band_id): - if flow_id in rsa.db_flows.keys(): - flow = rsa.db_flows[flow_id] - bidir = flow["bidir"] - match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate - if bidir: - match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate - if match1 or match2: - ob_id = flow["parent_opt_band"] - rsa.del_flow(flow, ob_id) - rsa.db_flows[flow_id]["is_active"] = False - rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) - if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0: - rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"] - rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id) - - if debug: - LOGGER.info(links_dict) - return "flow {} deleted".format(flow_id), 200 + def delete( src, dst, bitrate, o_band_id,flow_id=None): + flow = None + match1=False + ob_id=None + if flow_id is not None: + + if flow_id in rsa.db_flows.keys(): + flow = rsa.db_flows[flow_id] + match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate + ob_id = flow["parent_opt_band"] + flow['is_active']=False + if flow is not None: + + + bidir = flow["bidir"] + + if bidir: + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate + if match1 or match2: + ob_id = flow["parent_opt_band"] + rsa.del_flow(flow, ob_id) + rsa.db_flows[flow_id]["is_active"] = False + if flow_id in rsa.optical_bands[ob_id]["served_lightpaths"].remove: + rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) + #if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0: + # rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"] + # rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id) + + if debug: + print(rsa.links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 else: - return "flow {} not matching".format(flow_id), 404 + if match1: + # if delete_band !=0 and ob_id is not None: + # print(f"delete_lightpath {delete_band} and ob_id {ob_id}") + # if len( rsa.optical_bands[ob_id]["served_lightpaths"]) != 0: + # return "DELETE_NOT_ALLOWED" ,400 + rsa.del_flow(flow,flow_id,ob_id) + + if debug: + print(f"vor ob_id {ob_id} rsa.optical_bands {rsa.optical_bands[ob_id]}") + print(f"rsa.links_dict {rsa.links_dict}") + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 else: - if match1: - ob_id = flow["parent_opt_band"] - rsa.del_flow(flow, ob_id) - rsa.db_flows[flow_id]["is_active"] = False - rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) - if debug: - LOGGER.info(links_dict) - return "flow {} deleted".format(flow_id), 200 - else: - return "flow {} not matching".format(flow_id), 404 - else: - return "flow id {} does not exist".format(flow_id), 404 + return "flow id {} does not exist".format(flow_id), 404 + +@optical.route('/DelOpticalBand/<string:src>/<string:dst>/<int:o_band_id>',methods=['DELETE']) +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class DelOpticalBand(Resource): + @staticmethod + def delete( src, dst, o_band_id): + flow = None + + ob_id=None + if o_band_id is not None : + + if o_band_id in rsa.optical_bands.keys(): + flow=rsa.optical_bands[o_band_id] + #match1 = flow["src"] == src and flow["dst"] == dst + ob_id=o_band_id + + if flow is not None: + + + bidir = flow["bidir"] + + if bidir: + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] + if match1 or match2: + ob_id = flow["parent_opt_band"] + #rsa.del_flow(flow, ob_id) + rsa.optical_bands[ob_id]["is_active"] = False + # if flow_id in rsa.optical_bands[ob_id]["served_lightpaths"].remove: + # rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) + #if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0: + # rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"] + # rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id) + + if debug: + print(rsa.links_dict) + return "ob_id {} deleted".format(ob_id), 200 + else: + return "ob_id {} not matching".format(ob_id), 404 + else: + if ob_id is not None: + + if len( rsa.optical_bands[ob_id]["served_lightpaths"]) != 0: + return "DELETE_NOT_ALLOWED" ,400 + + rsa.del_band(flow,ob_id) + if debug: + print(f"vor ob_id {ob_id} rsa.optical_bands {rsa.optical_bands[ob_id]}") + print(f"rsa.links_dict {rsa.links_dict}") + return "ob_id {} deleted".format(ob_id), 200 + + else : + return "flow for ob_id {} not found".format(ob_id),400 + else: + return "ob_id {} does not exist".format(ob_id), 404 @optical.route('/DelLightpath/<int:flow_id>/<string:src>/<string:dst>/<int:bitrate>') @@ -162,7 +234,7 @@ class DelLightpath(Resource): rsa.del_flow(flow) rsa.db_flows[flow_id]["is_active"] = False if debug: - LOGGER.info(links_dict) + print(rsa.links_dict) return "flow {} deleted".format(flow_id), 200 else: return "flow {} not matching".format(flow_id), 404 @@ -178,22 +250,21 @@ class GetFlows(Resource): def get(): try: if debug: - LOGGER.info(rsa.db_flows) + print(rsa.db_flows) return rsa.db_flows, 200 except: return "Error", 404 + @optical.route('/GetOpticalBands') @optical.response(200, 'Success') @optical.response(404, 'Error, not found') class GetBands(Resource): @staticmethod def get(): - print("Getting ") - LOGGER.info("Getting") try: if debug: - LOGGER.info(rsa.optical_bands) + print(rsa.optical_bands) return rsa.optical_bands, 200 except: return "Error", 404 @@ -208,7 +279,7 @@ class GetBand(Resource): for ob_idx in rsa.optical_bands.keys(): if str(ob_idx) == str(ob_id): if debug: - LOGGER.info(rsa.optical_bands[ob_id]) + print(rsa.optical_bands[ob_id]) return rsa.optical_bands[ob_idx], 200 return {}, 404 @@ -219,28 +290,73 @@ class GetBand(Resource): class GetFlows(Resource): @staticmethod def get(): - global links_dict + global rsa + #global links_dict + links = None + if rsa is not None : + links = rsa.links_dict try: if debug: - LOGGER.info(links_dict) - return links_dict, 200 + print(links) + return links, 200 except: return "Error", 404 -if __name__ == '__main__': +@optical.route('/GetTopology/<path:context_id>/<path:topology_id>',methods=['GET']) +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetTopology(Resource): + @staticmethod + def get(context_id:str,topology_id:str): + + global rsa + if (rsa is not None): + return "Opticalcontroller is synchronised" ,200 + topog_id = TopologyId() + topog_id.topology_uuid.uuid=topology_id + topog_id.context_id.context_uuid.uuid=context_id + + try: + links_dict = {"optical_links": []} + node_dict = {} + topo, nodes = readTopologyDataFromContext(topog_id) + + for link in topo: + link_dict_type = MessageToDict(link, preserving_proto_field_name=True) + + if "c_slots" in link_dict_type["optical_details"]: + link_dict_type["optical_details"]["c_slots"] = link_dict_type["optical_details"]["c_slots"] + + if "l_slots" in link_dict_type["optical_details"]: + link_dict_type["optical_details"]["l_slots"] = link_dict_type["optical_details"]["l_slots"] + + if "s_slots" in link_dict_type["optical_details"]: + link_dict_type["optical_details"]["s_slots"] = link_dict_type["optical_details"]["s_slots"] + + links_dict["optical_links"].append(link_dict_type) + + for device in nodes : + dev_dic = { + "id":device.device_id.device_uuid.uuid, + #"ip":f"10.30.2.{207+i}", + #"port":"50001", + "type":"OC-ROADM" if device.device_type =="optical-roadm" else "OC-TP", + "driver": "OpticalOC" + } + node_dict[device.name] = dev_dic + #i+=1 + #print(f"refresh_optical controller optical_links_dict= {links_dict}") + #print(f"refresh_optical controller node_dict {node_dict}") + + rsa = RSA(node_dict, links_dict) + if debug: + print(rsa.init_link_slots2()) + return "ok", 200 + except Exception as e: + print(f"err {e}") + return "Error", 400 - # Start metrics server - - LOGGER.info('Starting...') - - - - nodes_dict, links_dict = readTopologyData(nodes_json, topology_json) - - #topologies, links = getTopology() - #print("topologies{} and devices {}".format(topologies,links)) - rsa = RSA(nodes_dict, links_dict) - - app.run(host='0.0.0.0', port=10060, debug=True) +if __name__ == '__main__': + app.run(host='0.0.0.0', port=10060) diff --git a/src/opticalcontroller/README.md b/src/opticalcontroller/README.md index 5fd94c59e51cbd78dd76a7db0f24aaaec4ebd9db..f121055cec91470646b9885bfe90db137027f472 100644 --- a/src/opticalcontroller/README.md +++ b/src/opticalcontroller/README.md @@ -1,17 +1,20 @@ -# optical-controller -This a framework to implement the optical controller for the RMSA algorithm. +# Optical Controller + +This is a framework to test the optical controller for the RMSA algorithm in an isolated manner. + + + +```bash #create a venv python -m venv venv -in linux +# in linux source venv/Scripts/activate -in windows +# in windows venv\Scripts\activate -pip install -r requirements_opt.txt +pip install -r requirements_optical_ctrl_test.txt python OpticalController.py - - - +``` diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py index b15357c98242ad6b18d4068b6f0aa1cb08852d7a..61a74edbecc2ac635398ee8482800514295e9473 100644 --- a/src/opticalcontroller/RSA.py +++ b/src/opticalcontroller/RSA.py @@ -26,15 +26,15 @@ class RSA(): self.flow_id = 0 self.opt_band_id = 0 self.db_flows = {} - self.initGraph() + self.initGraph2() self.c_slot_number = 0 self.l_slot_number = 0 self.s_slot_number = 0 self.optical_bands = {} - def init_link_slots(self, testing): - if not testing: - for l in self.links_dict["links"]: + def init_link_slots(self): + if full_links: + for l in self.links_dict["optical_links"]: for fib in l["optical_link"]["details"]["fibers"]: #fib = self.links_dict[l]["fibers"][f] if len(fib["c_slots"]) > 0: @@ -45,7 +45,7 @@ class RSA(): fib["s_slots"] = list(range(0, Ns)) if debug: print(fib) - for l1 in self.links_dict["links"]: + for l1 in self.links_dict["optical_links"]: for fib1 in l1["optical_link"]["details"]["fibers"]: #fib1 = self.links_dict[l1]["details"]["fibers"][f1] @@ -58,11 +58,35 @@ class RSA(): break return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number) + def init_link_slots2(self): + if full_links: + for l in self.links_dict["optical_links"]: + fib = l["optical_details"] + #fib = self.links_dict[l]["fibers"][f] + if len(fib["c_slots"]) > 0: + for c in range(0, Nc): + fib["c_slots"][c] = 1 + if len(fib["l_slots"]) > 0: + for c in range(0, Nl): + fib["l_slots"][c] = 1 + if len(fib["s_slots"]) > 0: + for c in range(0, Ns): + fib["s_slots"][c] = 1 + if debug: + print(fib) + for l1 in self.links_dict["optical_links"]: + fib1 = l1["optical_details"] + self.c_slot_number = len(fib1["c_slots"].keys()) + self.l_slot_number = len(fib1["l_slots"].keys()) + self.s_slot_number = len(fib1["s_slots"].keys()) + break + return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number) + def initGraph(self): self.g = dijsktra.Graph() for n in self.nodes_dict: self.g.add_vertex(n) - for l in self.links_dict["links"]: + for l in self.links_dict["optical_links"]: if debug: print(l) [s, d] = l["optical_link"]["name"].split('-') @@ -74,6 +98,24 @@ class RSA(): if debug: self.g.printGraph() + def initGraph2(self): + + self.g = dijsktra.Graph() + + for n in self.nodes_dict: + self.g.add_vertex(n) + for l in self.links_dict["optical_links"]: + if debug: + print(l) + [s, d] = l["name"].split('-') + ps = l["optical_details"]["src_port"] + pd = l["optical_details"]["dst_port"] + self.g.add_edge(s, d, ps, pd, 1) + + print("INFO: Graph initiated.2") + if debug: + self.g.printGraph() + def compute_path(self, src, dst): path = dijsktra.shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance())) @@ -95,7 +137,7 @@ class RSA(): self.g.reset_graph() return links, path - def get_slots(self, links, slots, optical_band_id = None): + def get_slots(self, links, slots, optical_band_id=None): if isinstance(slots, int): val_c = slots @@ -120,38 +162,40 @@ class RSA(): add = links[0] if self.nodes_dict[dst_2]["type"] == "OC-TP": drop = links[-1] - + found = 0 for l in links: c_slots[l] = [] l_slots[l] = [] s_slots[l] = [] - found = 0 - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == l: - #for f in self.links_dict[l]['fibers'].keys(): - for fib in link["optical_link"]["details"]["fibers"]: - if l == add: - if 'used' in fib: - if fib["used"]: - #if debug: - print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if l == drop: - if 'used' in fib: - if fib["used"]: - #if debug: - print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if len(fib["c_slots"]) > 0: - c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c)) - if len(fib["l_slots"]) > 0: - l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) - if len(fib["s_slots"]) > 0: - s_slots[l] = combine(s_slots[l], consecutives(fib["s_slots"], val_s)) - if debug: - print(l, c_slots[l]) - found = 1 - if found == 0: + + link = self.get_link_by_name(l) + fib = link["optical_details"] + if l == add: + if 'used' in fib: + if fib["used"]: + #if debug: + print("WARNING!!!: link {}, is already in use".format(l)) + return [], [], [] + if l == drop: + if 'used' in fib: + if fib["used"]: + #if debug: + print("WARNING!!!: link {} is already in use".format(l)) + return [], [], [] + c_found = l_found = s_found = 0 + if len(fib["c_slots"].keys()) > 0: + #c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c)) + c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c)) + c_found = 1 + if len(fib["l_slots"].keys()) > 0: + l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) + l_found = 1 + if len(fib["s_slots"].keys()) > 0: + s_slots[l] = combine(s_slots[l], consecutives(fib["s_slots"], val_s)) + s_found = 1 + if debug: + print(l, c_slots[l]) + if c_found == 0 and l_found == 0 and s_found == 0: return [], [], [] keys = list(c_slots.keys()) @@ -185,60 +229,100 @@ class RSA(): c_sts = common_slots(a_c, b_c) l_sts = common_slots(a_l, b_l) s_sts = common_slots(a_s, b_s) + ''' + if len(fib["l_slots"]) > 0: + l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) + l_found = 1''' if optical_band_id is not None: if "c_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["c_slots"]) > 0: a_c = c_sts - b_c = self.optical_bands[optical_band_id]["c_slots"] + #MOD + b_c = consecutives(self.optical_bands[optical_band_id]["c_slots"], val_c) + #b_c = self.optical_bands[optical_band_id]["c_slots"] c_sts = common_slots(a_c, b_c) - else: - c_sts = [] else: c_sts = [] if "l_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["l_slots"]) > 0: a_l = l_sts - b_l = self.optical_bands[optical_band_id]["l_slots"] + b_l = consecutives(self.optical_bands[optical_band_id]["l_slots"], val_c) l_sts = common_slots(a_l, b_l) - else: - l_sts = [] else: l_sts = [] if "s_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["s_slots"]) > 0: a_s = s_sts - b_s = self.optical_bands[optical_band_id]["s_slots"] + b_s = consecutives(str_list_to_int(self.optical_bands[optical_band_id]["s_slots"].keys()), val_c) s_sts = common_slots(a_s, b_s) - else: - s_sts = [] else: s_sts = [] return c_sts, l_sts, s_sts def update_link(self, fib, slots, band): + #print(fib) for i in slots: - fib[band].remove(i) + fib[band][str(i)] = 0 if 'used' in fib: fib['used'] = True + print(f"fib updated {fib}") + #print(fib) + + def update_link_2(self, fib, slots, band,link): + #print(fib) + for i in slots: + fib[band][str(i)] = 0 + if 'used' in fib: + fib['used'] = True + + set_link_update(fib,link) + #print(fib) def update_optical_band(self, optical_band_id, slots, band): for i in slots: - self.optical_bands[optical_band_id][band].remove(i) + self.optical_bands[optical_band_id][band][str(i)] = 0 + + def augment_optical_band(self, optical_band_id, slots, band): + for i in slots: + self.optical_bands[optical_band_id][band][str(i)] = 1 def restore_link(self, fib, slots, band): for i in slots: - fib[band].append(int(i)) + fib[band][str(i)] = 1 if 'used' in fib: fib['used'] = False - fib[band].sort() + #fib[band].sort() + + def restore_link_2(self, fib, slots, band,link): + print("start restoring link") + for i in slots: + fib[band][str(i)] = 1 + if 'used' in fib: + fib['used'] = False + #fib[band].keys().sort() + set_link_update(fib,link,test="restoration") def restore_optical_band(self, optical_band_id, slots, band): for i in slots: - self.optical_bands[optical_band_id][band].append(int(i)) - self.optical_bands[optical_band_id][band].sort() - - def del_flow(self, flow, o_b_id = None): + self.optical_bands[optical_band_id][band][str(i)] = 1 + + #self.optical_bands[optical_band_id][band].append(int(i)) + #self.optical_bands[optical_band_id][band].sort() + + def restore_optical_band_2(self, optical_band_id, slots, band ,links): + print(f"example of band { band}") + print(f"example of slots {slots}") + print(f"example of self.optical_bands_before { self.optical_bands}") + for i in slots: + self.optical_bands[optical_band_id][band][str(i)] = 1 + print(f"example of self.optical_bands_after { self.optical_bands}") + + #link_name= self.optical_bands[optical_band_id]['links'][0] + #link = self.get_link_by_name(link_name) + #update_optical_band(optical_bands=self.optical_bands,optical_band_id=optical_band_id,band=band,link=link) + + def del_flow(self, flow,flow_id, o_b_id = None): flows = flow["flows"] band = flow["band_type"] slots = flow["slots"] @@ -249,22 +333,123 @@ class RSA(): path = flow["path"] links = flow["links"] bidir = flow["bidir"] + flow_id = flow["flow_id"] - for l in fiber_f.keys(): + for l in links: if debug: print(l) - print(fiber_f[l]) #link = self.links_dict[l] #f = fiber_f[l] #fib = link['fibers'][f] - fib = self.get_fiber_details(l, fiber_f[l]) - if not list_in_list(slots, fib[band]): - self.restore_link(fib, slots, band) + fib = self.get_link_by_name(l)["optical_details"] + + self.restore_link(fib, slots, band) + if debug: + print(fib[band]) + + if o_b_id is not None: + if debug: + print("restoring OB") + print(f"invoking restore_optical_band o_b_id: {o_b_id} , slots {slots} , band {band} ") + self.restore_optical_band(o_b_id, slots, band) + if flow_id in self.optical_bands[o_b_id]["served_lightpaths"]: + if flow_id in self.optical_bands[o_b_id]["served_lightpaths"]: + self.optical_bands[o_b_id]["served_lightpaths"].remove(flow_id) + + #self.restore_optical_band_2(o_b_id, slots, band,links) + + if bidir: + for l in links: + r_l = reverse_link(l) + if debug: + print(r_l) + # link = self.links_dict[l] + # f = fiber_f[l] + # fib = link['fibers'][f] + fib = self.get_link_by_name(r_l)["optical_details"] + if list_in_list(slots, str_list_to_int(fib[band].keys())): + self.restore_link(fib, slots, band, link=l) + if debug: + print(fib[band]) + ''' + for rl in fiber_b.keys(): if debug: - print(fib[band]) + print(rl) + print(fiber_b[rl]) + #rlink = self.links_dict[rl] + #rf = fiber_b[rl] + #rfib = rlink['fibers'][rf] + rfib = self.get_fiber_details(rl, fiber_b[rl]) + if not list_in_list(slots, rfib[band]): + self.restore_link(rfib, slots, band) + if debug: + print(rfib[band]) + ''' + #changed according to TFS development + #if o_b_id is not None: + # rev_o_band_id = self.optical_bands[o_b_id]["reverse_optical_band_id"] + # self.restore_optical_band(rev_o_band_id, slots, band) + return True + + + def del_band(self, flow, o_b_id = None): + print(f"delete band {flow} ") + + flows = flow["flows"] + band = None + #slots = flow["slots"] + fiber_f = flow["fiber_forward"] + fiber_b = flow["fiber_backward"] + op = flow["op-mode"] + n_slots = 0 + path = flow["path"] + bidir = flow["bidir"] + links = [] if o_b_id is not None: + links= self.optical_bands[o_b_id]["links"] + band = self.optical_bands[o_b_id]["band_type"] + n_slots =self.optical_bands[o_b_id]["n_slots"] + if n_slots > 0: + slots=[i+1 for i in range(n_slots)] + + for l in links: + if debug: + print(l) + #link = self.links_dict[l] + #f = fiber_f[l] + #fib = link['fibers'][f] + fib = self.get_link_by_name(l)["optical_details"] + print(f"del_flow_fib {fib } and band {band}") + print(f"del_flow { str_list_to_int(fib[band].keys())}") + + print(f"invoking restore_link_2 fib: {fib} , slots {slots} , band {band} ") + self.restore_link(fib, slots, band) + self.optical_bands[o_b_id]["is_active"]=False + + if debug: + print(fib[band]) + + if o_b_id is not None: + + if debug: + print("restoring OB") + print(f"invoking restore_optical_band o_b_id: {o_b_id} , slots {slots} , band {band} ") self.restore_optical_band(o_b_id, slots, band) + #self.restore_optical_band_2(o_b_id, slots, band,links) if bidir: + for l in links: + r_l = reverse_link(l) + if debug: + print(r_l) + # link = self.links_dict[l] + # f = fiber_f[l] + # fib = link['fibers'][f] + fib = self.get_link_by_name(r_l)["optical_details"] + if list_in_list(slots, str_list_to_int(fib[band].keys())): + self.restore_link(fib, slots, band, link=l) + if debug: + print(fib[band]) + ''' for rl in fiber_b.keys(): if debug: print(rl) @@ -277,17 +462,26 @@ class RSA(): self.restore_link(rfib, slots, band) if debug: print(rfib[band]) + ''' #changed according to TFS development #if o_b_id is not None: # rev_o_band_id = self.optical_bands[o_b_id]["reverse_optical_band_id"] # self.restore_optical_band(rev_o_band_id, slots, band) return True + def del_handler(self, flow,flow_id, o_b_id = None,delete_band=0): + print(f" del_handler flow {flow} flow_id {flow_id} o_b_id {o_b_id} delete_band {delete_band}") + if delete_band != 0: + print(f"delete band del_band") + self.del_band(flow,flow_id,o_b_id=o_b_id) + else : + self.del_flow(flow,flow_id=flow_id,o_b_id=o_b_id) + def get_fibers_forward(self, links, slots, band): fiber_list = {} add = links[0] drop = links[-1] - print(links) + #print(links) ''' for link in self.links_dict["links"]: if link["optical_link"]["name"] == l: @@ -296,85 +490,99 @@ class RSA(): ''' for l in links: - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == l: - for fib in link["optical_link"]["details"]["fibers"]: - #for f in self.links_dict[l]['fibers'].keys(): - #for fib in l["optical_link"]["details"]["fibers"]: - #fib = self.links_dict[l]['fibers'][f] - if l == add: - if 'used' in fib: - if fib["used"]: - if debug: - print("link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if l == drop: - if 'used' in fib: - if fib["used"]: - if debug: - print("link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if list_in_list(slots, fib[band]): - fiber_list[l] = fib["ID"] - self.update_link(fib, slots, band) - break + for link in self.links_dict["optical_links"]: + print(f"tracking link info {link}") + if link["name"] == l: + fib = link["optical_details"] + #for f in self.links_dict[l]['fibers'].keys(): + #for fib in l["optical_link"]["details"]["fibers"]: + #fib = self.links_dict[l]['fibers'][f] + if l == add: + if 'used' in fib: + if fib["used"]: + if debug: + print("link {} is already in use".format(l)) + continue + if l == drop: + if 'used' in fib: + if fib["used"]: + if debug: + print("link {} is already in use".format(l)) + continue + if list_in_list(slots, str_list_to_int(fib[band].keys())): + #fiber_list[l] = fib["ID"] + #self.update_link(fib, slots, band) + self.update_link_2(fib,slots,band,link) + break print("INFO: Path forward computation completed") return fiber_list def get_link_by_name (self, key): - result = None - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == key: + for link in self.links_dict["optical_links"]: + if link["name"] == key: if debug: print(link) - result = link break - return result + return link def get_fiber_details(self, link_key, fiber_id): - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == link_key: + for link in self.links_dict["optical_links"]: + if link["name"] == link_key: if debug: print(link) - for fib in link["optical_link"]["details"]["fibers"]: + for fib in link["optical_details"]: if fib["ID"] == fiber_id: return fib return None - - def get_fibers_backward(self, links, fibers, slots, band): + def get_fibers_backward(self, links, slots, band): fiber_list = {} #r_drop = reverse_link(links[0]) #r_add = reverse_link(links[-1]) - for l in fibers.keys(): - fib = self.get_fiber_details(l, fibers[l]) + for l in links: + fib = self.get_link_by_name(l)["optical_details"] ''' link = self.get_link_by_name(l) #port = self.links_dict[l]["fibers"][fibers[l]]["src_port"] for fib in link["optical_link"]["details"]["fibers"]: if fib["ID"] == fibers[l]: ''' - port = fib["src_port"] + s_port = fib["src_port"] + d_port = fib["dst_port"] + + if debug: + print(l, s_port, d_port) + r_l = reverse_link(l) r_link = self.get_link_by_name(r_l) + if debug: + print(r_l) + #for f in r_link["fibers"].keys(): - for r_fib in r_link["optical_link"]["details"]["fibers"]: - if r_fib["remote_peer_port"] == port: - if list_in_list(slots, r_fib[band]): - fiber_list[r_l] = r_fib["ID"] - self.update_link(r_fib, slots, band) + r_fib = r_link["optical_details"] + if r_fib["remote_peer_port"] == s_port and r_fib["local_peer_port"] == d_port: + if list_in_list(slots, str_list_to_int(r_fib[band].keys())): + #fiber_list[r_l] = r_fib["ID"] + self.update_link(r_fib, slots, band) print("INFO: Path backward computation completed") return fiber_list + #function invoked for lightpaths and OB def select_slots_and_ports(self, links, n_slots, c, l, s, bidir): if debug: - print(self.links_dict) + print (links, n_slots, c, l, s, bidir, self.c_slot_number, self.l_slot_number, self.s_slot_number) band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number) + if debug: + print (band, slots) if band is None: print("No slots available in the three bands") - return None, None, None - if debug: - print(band, slots) + #return None, None, None, {}, {} + return None, None, None, {}, {} + + self.get_fibers_forward(links, slots, band) + if bidir: + self.get_fibers_backward(links, slots, band) + ''' fibers_f = self.get_fibers_forward(links, slots, band) fibers_b = [] @@ -385,6 +593,7 @@ class RSA(): print(fibers_f) print("backward") print(fibers_b) + ''' add = links[0] drop = links[-1] inport = "0" @@ -394,18 +603,22 @@ class RSA(): t_flows = {} #if len(links) == 1: - for lx in fibers_f: - if lx == add: + for llx in links: + if llx == add: inport = "0" r_outport = "0" - if lx == drop: + if llx == drop: outport = "0" r_inport = "0" + ''' f = fibers_f[lx] - src, dst = lx.split("-") + fibx = self.get_fiber_details(lx, f) + ''' + src, dst = llx.split("-") #outport = self.links_dict[lx]['fibers'][f]["src_port"] - outport = fibx["src_port"] + lx = self.get_link_by_name(llx)["optical_details"] + outport = lx["src_port"] t_flows[src] = {} t_flows[src]["f"] = {} @@ -414,14 +627,14 @@ class RSA(): if bidir: #r_inport = self.links_dict[lx]['fibers'][f]["local_peer_port"] - r_inport = fibx["local_peer_port"] + r_inport = lx["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": r_outport} #inport = self.links_dict[lx]['fibers'][f]["dst_port"] - inport = fibx["dst_port"] + inport = lx["dst_port"] if bidir: #r_outport = self.links_dict[lx]['fibers'][f]["remote_peer_port"] - r_outport = fibx["remote_peer_port"] + r_outport = lx["remote_peer_port"] t_flows[dst] = {} t_flows[dst]["f"] = {} t_flows[dst]["b"] = {} @@ -436,8 +649,9 @@ class RSA(): print(t_flows) print("INFO: Flow matrix computed") - return t_flows, band, slots, fibers_f, fibers_b + return t_flows, band, slots, {}, {} + #function ivoked for fs lightpaths only def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id): if debug: print(self.links_dict) @@ -447,22 +661,20 @@ class RSA(): return None, None, None, None, None if debug: print(band, slots) - fibers_f = self.get_fibers_forward(links, slots, band) - self.update_optical_band(o_band_id, slots, band) - fibers_b = [] + self.get_fibers_forward(links, slots, band) if bidir: - fibers_b = self.get_fibers_backward(links, fibers_f, slots, band) + self.get_fibers_backward(links, slots, band) + + #fibers_f = self.get_fibers_forward(links, slots, band) + self.update_optical_band(o_band_id, slots, band) + #fibers_b = [] + #if bidir: + # fibers_b = self.get_fibers_backward(links, fibers_f, slots, band) ''' rev_o_band_id = self.optical_bands[o_band_id]["reverse_optical_band_id"] self.update_optical_band(rev_o_band_id, slots, band) ''' - if debug: - print("forward") - print(fibers_f) - if bidir: - print("backward") - print(fibers_b) add = links[0] drop = links[-1] port_0 = "0" @@ -470,11 +682,10 @@ class RSA(): t_flows = {} #flows_add_side - f = fibers_f[add] src, dst = add.split("-") - fibx = self.get_fiber_details(add, f) + lx = self.get_link_by_name(add)["optical_details"] #outport = self.links_dict[add]['fibers'][f]["src_port"] - outport = fibx["src_port"] + outport = lx["src_port"] #T1 rules t_flows[src] = {} t_flows[src]["f"] = {} @@ -482,7 +693,7 @@ class RSA(): t_flows[src]["f"] = {"in": port_0, "out": outport} if bidir: #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"] - r_inport = fibx["local_peer_port"] + r_inport = lx["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": port_0} #R1 rules @@ -490,27 +701,26 @@ class RSA(): t_flows[dst]["f"] = {} t_flows[dst]["b"] = {} #inport = self.links_dict[add]['fibers'][f]["dst_port"] - inport = fibx["dst_port"] + inport = lx["dst_port"] opt_band_src_port = self.optical_bands[o_band_id]["src_port"] t_flows[dst]["f"] = {"in": inport, "out": opt_band_src_port} #to modify to peer ports if bidir: #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"] - r_inport = fibx["local_peer_port"] + r_inport = lx["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": port_0} if bidir: rev_opt_band_dst_port = self.optical_bands[o_band_id]["rev_dst_port"] #r_outport = self.links_dict[add]['fibers'][f]["remote_peer_port"] - r_outport = fibx["remote_peer_port"] + r_outport = lx["remote_peer_port"] t_flows[dst]["b"] = {"in": rev_opt_band_dst_port, "out": r_outport} #flows_drop_side # R2 rules - f = fibers_f[drop] + ly = self.get_link_by_name(drop)["optical_details"] src, dst = drop.split("-") - fiby = self.get_fiber_details(drop, f) #outport = self.links_dict[drop]['fibers'][f]["src_port"] - outport = fiby["src_port"] + outport = ly["src_port"] t_flows[src] = {} t_flows[src]["f"] = {} @@ -520,17 +730,17 @@ class RSA(): if bidir: rev_opt_band_src_port = self.optical_bands[o_band_id]["rev_src_port"] #r_inport = self.links_dict[drop]['fibers'][f]["local_peer_port"] - r_inport = fiby["local_peer_port"] + r_inport = ly["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": rev_opt_band_src_port} t_flows[dst] = {} t_flows[dst]["f"] = {} t_flows[dst]["b"] = {} #inport = self.links_dict[drop]['fibers'][f]["dst_port"] - inport = fiby["dst_port"] + inport = ly["dst_port"] t_flows[dst]["f"] = {"in": inport, "out": port_0} if bidir: #r_inport = self.links_dict[drop]['fibers'][f]["remote_peer_port"] - r_inport = fiby["remote_peer_port"] + r_inport = ly["remote_peer_port"] t_flows[dst]["b"] = {"in": port_0, "out": r_inport} if debug: @@ -540,7 +750,7 @@ class RSA(): print(t_flows) print("INFO: Flow matrix computed for Flex Lightpath") - return t_flows, band, slots, fibers_f, fibers_b + return t_flows, band, slots, {}, {} def rsa_computation(self, src, dst, rate, bidir): self.flow_id += 1 @@ -565,7 +775,7 @@ class RSA(): if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir) - f0, band = freqency_converter(band_range, slots) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for normal wavelenght connection") @@ -675,50 +885,43 @@ class RSA(): print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir) - f0, band = freqency_converter(band_range, slots) - print(flow_list, band_range, slots, fiber_f, fiber_b) - ''' - - flow_list_b = {} - rev_path = path.copy() - rev_path.reverse() - rev_links = reverse_links(links) - if bidir: - for dev_x in flow_list.keys(): - flow_list_b[dev_x] = {} - flow_list_b[dev_x]["f"] = flow_list[dev_x]["b"] - del flow_list[dev_x]["b"] - rev_path = path.copy() - ''' + if debug: + print(flow_list, band_range, slots, fiber_f, fiber_b) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for optical band") if flow_list is None: self.null_values(self.flow_id) return self.flow_id, [] - slots_i = [] + #slots_i = [] + #for i in slots: + # slots_i.append(int(i)) + slots_i = {} for i in slots: - slots_i.append(int(i)) + slots_i[str(i)] = 1 # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band # links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band + if debug: + print(links) if len(flow_list) > 0: src_port = flow_list[path[0]]['f']['out'] dst_port = flow_list[path[-1]]['f']['in'] - print(flow_list) - if len(fiber_f.keys()) == 1: - link_x = list(fiber_f.keys())[0] + if debug: + print(flow_list) + if len(links) == 1: #fib_x = fiber_f[link_x] #rev_dst_port = self.links_dict[link_x]['fibers'][fib_x]["local_peer_port"] #rev_src_port = self.links_dict[link_x]['fibers'][fib_x]["remote_peer_port"] - fibx = self.get_fiber_details(link_x, fiber_f[link_x]) + fibx = self.get_link_by_name(links[0])["optical_details"] rev_dst_port = fibx["local_peer_port"] rev_src_port = fibx["remote_peer_port"] else: - link_in = list(fiber_f.keys())[0] - link_out = list(fiber_f.keys())[-1] - fib_inx = self.get_fiber_details(link_in, fiber_f[link_in]) - fib_outx = self.get_fiber_details(link_out, fiber_f[link_out]) + link_in = links[0] + link_out = links[-1] + fib_inx = self.get_link_by_name(link_in)["optical_details"] + fib_outx = self.get_link_by_name(link_out)["optical_details"] rev_dst_port = fib_inx["local_peer_port"] rev_src_port = fib_outx["remote_peer_port"] @@ -790,6 +993,7 @@ class RSA(): return self.flow_id, [] optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) return None, optical_band_id + print("INFO: TP to TP connection") self.flow_id += 1 self.db_flows[self.flow_id] = {} self.db_flows[self.flow_id]["flow_id"] = self.flow_id @@ -797,7 +1001,7 @@ class RSA(): self.db_flows[self.flow_id]["dst"] = dst self.db_flows[self.flow_id]["bitrate"] = rate self.db_flows[self.flow_id]["bidir"] = bidir - print("INFO: TP to TP connection") + if band is None: temp_links2 = [] temp_path = [] @@ -816,13 +1020,16 @@ class RSA(): temp_path.append(roadm_dst) temp_path.append(t_dst) existing_ob = self.get_optical_bands(roadm_src, roadm_dst) - if len(existing_ob) > 0: print("INFO: Evaluating existing OB {}".format(existing_ob)) #first checking in existing OB ob_found = 0 for ob_id in existing_ob: + if "is_active" in self.optical_bands[ob_id].keys(): + is_active = self.optical_bands[ob_id]["is_active"] + if not is_active: + continue op, num_slots = map_rate_to_slot(rate) if debug: print(temp_links2) @@ -836,7 +1043,7 @@ class RSA(): c_slots, l_slots, s_slots, bidir, ob_id) - f0, band = freqency_converter(band_range, slots) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for Flex Lightpath with OB already in place") @@ -871,6 +1078,75 @@ class RSA(): return self.flow_id, ob_id else: print("not enough slots") + print("trying to extend OB {}".format(ob_id)) + new_slots = self.extend_optical_band(ob_id, band=None) + + if len(new_slots) > 0: + band_type = self.optical_bands[ob_id]["band_type"] + c_slots = [] + l_slots = [] + s_slots = [] + if band_type == "c_slots": + c_slots = new_slots + elif band_type == "l_slots": + l_slots = new_slots + else: + s_slots = new_slots + op, num_slots = map_rate_to_slot(rate) + if debug: + print(temp_links2) + c_slots, l_slots, s_slots = self.get_slots(temp_links2, num_slots, ob_id) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + #print(c_slots) + #print(l_slots) + #print(s_slots) + if len(c_slots) >= num_slots or len(l_slots) >= num_slots or len(s_slots) >= num_slots: + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs( + temp_links2, num_slots, + c_slots, + l_slots, s_slots, bidir, + ob_id) + f0, band = frequency_converter(band_range, slots) + if debug: + print(f0, band) + print("INFO: RSA completed for Flex Lightpath with OB already in place") + if flow_list is None: + self.null_values(self.flow_id) + continue + slots_i = [] + for i in slots: + slots_i.append(int(i)) + # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band + # links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = temp_links2 + self.db_flows[self.flow_id]["path"] = temp_path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + self.db_flows[self.flow_id]["parent_opt_band"] = ob_id + self.db_flows[self.flow_id]["new_optical_band"] = 1 + #self.db_flows[self.flow_id]["new_optical_band"] = 2 + self.optical_bands[ob_id]["served_lightpaths"].append(self.flow_id) + ''' + if bidir: + rev_ob_id = self.optical_bands[ob_id]["reverse_optical_band_id"] + self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) + ''' + return self.flow_id, ob_id + else: + print("it is not possible to allocate connection in extended OB {}".format(ob_id)) + + if band is None: print("INFO: Not existing optical-band meeting the requirements") else: @@ -879,14 +1155,6 @@ class RSA(): links, path = self.compute_path(src, dst) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) op, num_slots = map_rate_to_slot(rate) - # self.flow_id += 1 - # self.db_flows[self.flow_id] = {} - # self.db_flows[self.flow_id]["flow_id"] = self.flow_id - # self.db_flows[self.flow_id]["src"] = src - # self.db_flows[self.flow_id]["dst"] = dst - # self.db_flows[self.flow_id]["bitrate"] = rate - # self.db_flows[self.flow_id]["bidir"] = bidir - if debug: print(temp_links) c_slots, l_slots, s_slots = self.get_slots(temp_links, num_slots, optical_band_id) @@ -897,7 +1165,7 @@ class RSA(): if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links, num_slots, c_slots, l_slots, s_slots, bidir, optical_band_id) - f0, band = freqency_converter(band_range, slots) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for FLex Lightpath with new OB") @@ -929,3 +1197,42 @@ class RSA(): self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) ''' return self.flow_id, optical_band_id + + def extend_optical_band(self, ob_id, band=None): + ob = self.optical_bands[ob_id] + links = ob["links"] + old_band = ob["band"] + band_type = ob["band_type"] + f0 = ob["freq"] + slots = ob[band_type] + if band is None: + num_slots_ob = map_band_to_slot(old_band/1000.0) + else: + num_slots_ob = map_band_to_slot(band) + new_slots = [] + for l in links: + link = self.get_link_by_name(l) + fib = link["optical_details"][band_type] + #s_slots = get_side_slots_on_link(link, band_type, num_slots_ob, slots) + s_slots, s_num = get_side_slots_on_link(fib, num_slots_ob, slots) + print("NEW SLOTS {}".format(s_slots)) + if len(new_slots) == 0: + new_slots = s_slots + else: + if len(new_slots) < s_num: + new_slots = list_in_list(new_slots, s_slots) + print("NEW SLOTS {}".format(new_slots)) + self.augment_optical_band(ob_id, new_slots, band_type) + new_band = int(len(new_slots)*12.5*1000) + print("{}, {},{},{} ".format(old_band, f0, len(new_slots), new_band)) + final_band = old_band + new_band + final_f0 = int(f0 + new_band/2) + print("{}, {}".format(final_band, final_f0)) + ob["band"] = final_band + ob["freq"] = final_f0 + for link_x in links: + link = self.get_link_by_name(link_x) + fib = link["optical_details"] + self.update_link(fib, new_slots, band_type) + + return new_slots diff --git a/src/opticalcontroller/__init__.py b/src/opticalcontroller/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..3ee6f7071f145e06c3aeaefc09a43ccd88e619e3 100644 --- a/src/opticalcontroller/__init__.py +++ b/src/opticalcontroller/__init__.py @@ -11,3 +11,4 @@ # 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. + diff --git a/src/opticalcontroller/json_files/nodes.json b/src/opticalcontroller/json_files/nodes.json deleted file mode 100644 index 60f017c19d7c7a578c0ddfc2225cab742deb0026..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/nodes.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "R1":{ - "id":0, - "ip":"10.30.2.207", - "port":"50001", - "type":"OC-ROADM", - "driver": "OpticalOC" - }, - - "R2":{ - "id":1, - "ip":"10.30.2.208", - "port":"50001", - "type":"OC-ROADM", - "driver": "OpticalOC" - }, - - "R3":{ - "id":2, - "ip":"10.30.2.209", - "port":"50001", - "type":"OC-ROADM", - "driver": "OpticalOC" - }, - "T1":{ - "id":3, - "ip":"10.30.2.210", - "port":"50001", - "type":"OC-TP", - "driver": "OpticalOC" - }, - "T2":{ - "id":4, - "ip":"10.30.2.211", - "port":"50001", - "type":"OC-TP", - "driver": "OpticalOC" - } -} diff --git a/src/opticalcontroller/json_files/optical_TFSworking.json b/src/opticalcontroller/json_files/optical_TFSworking.json deleted file mode 100644 index ff1841eeea9df1e73bcfb25d07f19d64554f11e1..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/optical_TFSworking.json +++ /dev/null @@ -1,486 +0,0 @@ -{ - "R1-R2": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "3", - "dst_port": "14", - "local_peer_port": "13", - "remote_peer_port": "4", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R1": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "4", - "dst_port": "13", - "local_peer_port": "14", - "remote_peer_port": "3", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T1-R1": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "12", - "local_peer_port": "1", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-T1": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "2", - "dst_port": "1", - "local_peer_port": "12", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T2-R2": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "6", - "dst_port": "15", - "local_peer_port": "6", - "remote_peer_port": "5", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-T2": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "5", - "dst_port": "6", - "local_peer_port": "15", - "remote_peer_port": "6", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - } -} diff --git a/src/opticalcontroller/json_files/optical_topoTFS.json b/src/opticalcontroller/json_files/optical_topoTFS.json deleted file mode 100644 index 7dea474cd676b7c699cffc1c180e14598b987473..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/optical_topoTFS.json +++ /dev/null @@ -1,1836 +0,0 @@ -{ - "R1-R2": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "201", - "local_peer_port": "201", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "202", - "local_peer_port": "202", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R1": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "201", - "local_peer_port": "201", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "202", - "local_peer_port": "202", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-R3": { - "length": 80, - "source": "d2", - "target": "d1", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "201", - "local_peer_port": "203", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "202", - "local_peer_port": "204", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R1": { - "length": 80, - "source": "d1", - "target": "d2", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "203", - "local_peer_port": "201", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "204", - "local_peer_port": "202", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R3": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R2": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T1-R1": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-T1": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T2-R2": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-T2": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - } -} diff --git a/src/opticalcontroller/json_files/tfs.json b/src/opticalcontroller/json_files/tfs.json deleted file mode 100644 index 31803b893b5639e957be33465599573baa475ca2..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/tfs.json +++ /dev/null @@ -1,686 +0,0 @@ -{ - "links": [ - { - "link_id": { - "link_uuid": { - "uuid": "T1->R1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "T1" - } - }, - "endpoint_uuid": { - "uuid": "1" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "12" - } - } - ], - "optical_link": { - "name": "T1-R1", - "details": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "1", - "dst_port": "12", - "local_peer_port": "1", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R1->T1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "2" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "T1" - } - }, - "endpoint_uuid": { - "uuid": "1" - } - } - ], - "optical_link": { - "name": "R1-T1", - "details": { - "length": 0, - "source": "srgT", - "target": "muxT", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "2", - "dst_port": "1", - "local_peer_port": "12", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R1->R2" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "3" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "14" - } - } - ], - "optical_link": { - "name": "R1-R2", - "details": { - "length": 0, - "source": "D1", - "target": "D1", - "fibers": [ - { - "ID": "D11", - "length": 0, - "src_port": "3", - "dst_port": "14", - "local_peer_port": "13", - "remote_peer_port": "4", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R2->R1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "4" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "13" - } - } - ], - "optical_link": { - "name": "R2-R1", - "details": { - "length": 0, - "source": "D1", - "target": "D1", - "fibers": [ - { - "ID": "D11", - "length": 0, - "src_port": "4", - "dst_port": "13", - "local_peer_port": "14", - "remote_peer_port": "3", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "T2->R2" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "T2" - } - }, - "endpoint_uuid": { - "uuid": "6" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "15" - } - } - ], - "optical_link": { - "name": "T2-R2", - "details": { - "length": 0, - "source": "srgT", - "target": "muxT", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "6", - "dst_port": "15", - "local_peer_port": "6", - "remote_peer_port": "5", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R2->T2" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "5" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "T2" - } - }, - "endpoint_uuid": { - "uuid": "6" - } - } - ], - "optical_link": { - "name": "R2-T2", - "details": { - "length": 0, - "source": "srgT", - "target": "muxT", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "5", - "dst_port": "6", - "local_peer_port": "15", - "remote_peer_port": "6", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - } - ] -} \ No newline at end of file diff --git a/src/opticalcontroller/json_files/topo_2_links.json b/src/opticalcontroller/json_files/topo_2_links.json deleted file mode 100644 index 02165938ce675071a4ff4c3424e3b53244d40810..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/topo_2_links.json +++ /dev/null @@ -1,1530 +0,0 @@ -{ - "R1-R3": { - "length": 80, - "source": "d2", - "target": "d1", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "201", - "local_peer_port": "203", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "202", - "local_peer_port": "204", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R1": { - "length": 80, - "source": "d1", - "target": "d2", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "203", - "local_peer_port": "201", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "204", - "local_peer_port": "202", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R3": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R2": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T1-R1": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-T1": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T2-R2": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-T2": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - } -} diff --git a/src/opticalcontroller/json_files/topology-optical.json b/src/opticalcontroller/json_files/topology-optical.json deleted file mode 100644 index e2453b654d53fc3200570ce9c2b17effc964bd25..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/topology-optical.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "r1-r2": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1": { - "src_port": "1T", - "dst_port": "1R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d1-2":{ - "src_port": "2T", - "dst_port": "2R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r2-r1": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1" : { - "src_port": "1T", - "dst_port": "1R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d1-2" : { - "src_port": "2T", - "dst_port": "2R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r1-r3": { - "length": 80, - "source" : "d2", - "target" : "d1", - "fibers" : { - "d2-1":{ - "src_port": "3T", - "dst_port": "1R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d2-2":{ - "src_port": "4T", - "dst_port": "2R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r3-r1": { - "length": 80, - "source" : "d1", - "target" : "d2", - "fibers" : { - "d1-1": { - "src_port": "1T", - "dst_port": "3R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d1-2": { - "src_port": "2T", - "dst_port": "4R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r2-r3": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "src_port": "3T", - "dst_port": "3R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d2-2": { - "src_port": "4T", - "dst_port": "4R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r3-r2": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "src_port": "3T", - "dst_port": "3R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d2-2":{ - "src_port": "4T", - "dst_port": "4R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "t1-r1": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "src_port": "1", - "dst_port": "101R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M2": { - "src_port": "2", - "dst_port": "102R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M3": { - "src_port": "3", - "dst_port": "103R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r1-t1": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "src_port": "101T", - "dst_port": "1", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S2": { - "src_port": "102T", - "dst_port": "2", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S3": { - "src_port": "103T", - "dst_port": "3", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "t2-r2": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "src_port": "1", - "dst_port": "101R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M2": { - "src_port": "2", - "dst_port": "102R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M3": { - "src_port": "3", - "dst_port": "103R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r2-t2": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "src_port": "101T", - "dst_port": "1", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S2": { - "src_port": "102T", - "dst_port": "2", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S3": { - "src_port": "103T", - "dst_port": "3", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - } -} diff --git a/src/opticalcontroller/json_files/topology-optical2.json b/src/opticalcontroller/json_files/topology-optical2.json deleted file mode 100644 index fe8e9866bcc64d52b2f49089ce03af47d72df9d0..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/topology-optical2.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "r1-r2": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1": { - "length": 80, - "src_port": "1T", - "dst_port": "1R", - "local_peer_port": "1R", - "remote_peer_port": "1T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d1-2":{ - "length": 80, - "src_port": "2T", - "dst_port": "2R", - "local_peer_port": "2R", - "remote_peer_port": "2T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r2-r1": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1" : { - "length": 80, - "src_port": "1T", - "dst_port": "1R", - "local_peer_port": "1R", - "remote_peer_port": "1T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d1-2" : { - "length": 80, - "src_port": "2T", - "dst_port": "2R", - "local_peer_port": "2R", - "remote_peer_port": "2T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r1-r3": { - "length": 80, - "source" : "d2", - "target" : "d1", - "fibers" : { - "d2-1":{ - "length": 80, - "src_port": "3T", - "dst_port": "1R", - "local_peer_port": "3R", - "remote_peer_port": "1T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d2-2":{ - "length": 80, - "src_port": "4T", - "dst_port": "2R", - "local_peer_port": "4R", - "remote_peer_port": "2T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r3-r1": { - "length": 80, - "source" : "d1", - "target" : "d2", - "fibers" : { - "d1-1": { - "length": 80, - "src_port": "1T", - "dst_port": "3R", - "local_peer_port": "1R", - "remote_peer_port": "3T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d1-2": { - "length": 80, - "src_port": "2T", - "dst_port": "4R", - "local_peer_port": "2R", - "remote_peer_port": "4T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r2-r3": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "length": 80, - "src_port": "3T", - "dst_port": "3R", - "local_peer_port": "3R", - "remote_peer_port": "3T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d2-2": { - "length": 80, - "src_port": "4T", - "dst_port": "4R", - "local_peer_port": "4R", - "remote_peer_port": "4T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r3-r2": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "length": 80, - "src_port": "3T", - "dst_port": "3R", - "local_peer_port": "3R", - "remote_peer_port": "3T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d2-2":{ - "length": 80, - "src_port": "4T", - "dst_port": "4R", - "local_peer_port": "4R", - "remote_peer_port": "4T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "t1-r1": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "101R", - "local_peer_port": "1", - "remote_peer_port": "101T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "102R", - "local_peer_port": "2", - "remote_peer_port": "102T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "103R", - "local_peer_port": "3", - "remote_peer_port": "103T", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r1-t1": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "length": 0, - "src_port": "101T", - "dst_port": "1", - "local_peer_port": "101R", - "remote_peer_port": "1", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S2": { - "length": 0, - "src_port": "102T", - "dst_port": "2", - "local_peer_port": "102T", - "remote_peer_port": "2", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S3": { - "length": 0, - "src_port": "103T", - "dst_port": "3", - "local_peer_port": "103R", - "remote_peer_port": "3", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "t2-r2": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "101R", - "local_peer_port": "1", - "remote_peer_port": "101T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "102R", - "local_peer_port": "2", - "remote_peer_port": "102T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "103R", - "local_peer_port": "3", - "remote_peer_port": "103T", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r2-t2": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "length": 0, - "src_port": "101T", - "dst_port": "1", - "local_peer_port": "101R", - "remote_peer_port": "1", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S2": { - "length": 0, - "src_port": "102T", - "dst_port": "2", - "local_peer_port": "102R", - "remote_peer_port": "2", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S3": { - "length": 0, - "src_port": "103T", - "dst_port": "3", - "local_peer_port": "103R", - "remote_peer_port": "3", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - } -} diff --git a/src/opticalcontroller/requirements.in b/src/opticalcontroller/requirements.in index 4732ee635a60b8320e25cd2c26388d1cfdfd25cc..15b3ca3a465efe5c9b7f5a217b1f5658a738405c 100644 --- a/src/opticalcontroller/requirements.in +++ b/src/opticalcontroller/requirements.in @@ -12,10 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. +aniso8601==9.0.1 +attrs==23.1.0 +blinker==1.6.2 +click==8.1.7 +colorama==0.4.6 Flask==1.1.2 flask-restplus==0.13.0 +importlib-metadata==6.8.0 +importlib-resources==6.0.1 itsdangerous==1.1.0 Jinja2==2.11.3 +jsonschema==4.19.0 +jsonschema-specifications==2023.7.1 MarkupSafe==1.1.1 -numpy<2.0.0 +numpy==1.23.0 +pkgutil-resolve-name==1.3.10 +pytz==2023.3.post1 +referencing==0.30.2 +rpds-py==0.10.3 +six==1.16.0 Werkzeug==0.16.1 +zipp==3.16.2 diff --git a/src/opticalcontroller/requirements_optical_ctrl_test.txt b/src/opticalcontroller/requirements_optical_ctrl_test.txt new file mode 100644 index 0000000000000000000000000000000000000000..0b1947bee2c7f1e89491dff4f7589d3465d28c38 --- /dev/null +++ b/src/opticalcontroller/requirements_optical_ctrl_test.txt @@ -0,0 +1,21 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +Flask==1.1.2 +flask-restplus==0.13.0 +itsdangerous==1.1.0 +Jinja2==2.11.3 +MarkupSafe==1.1.1 +numpy==1.23.0 +Werkzeug==0.16.1 diff --git a/src/opticalcontroller/tools.py b/src/opticalcontroller/tools.py index a173856b8e7bd00a0e538cd3893e1c762edff8c8..08441f5c0010de1be503ee307410431ddfee54ab 100644 --- a/src/opticalcontroller/tools.py +++ b/src/opticalcontroller/tools.py @@ -12,9 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json import numpy as np from variables import * -import json +from common.proto.context_pb2 import TopologyId , LinkId , OpticalLink , OpticalLinkDetails +from common.tools.object_factory.OpticalLink import correct_slot +from context.client.ContextClient import ContextClient def common_slots(a, b): @@ -24,9 +27,11 @@ def common_slots(a, b): def map_modulation_to_op(mod): if mod == "DP-QPSK": return 1 - if mod == "DP-16QAM": - return 7 - if mod == "DP-64QAM": + elif mod == "DP-8QAM": + return 4 + elif mod == "DP-16QAM": + return 8 + elif mod == "DP-32QAM": return 10 @@ -40,13 +45,19 @@ def map_rate_to_slot(rate): slots = 4 op = map_modulation_to_op(mod) return op, slots - if rate == 400: + elif rate == 400: + mod = "DP-8QAM" + slots = 4 + op = map_modulation_to_op(mod) + return op, slots + elif rate == 800: mod = "DP-16QAM" - slots = 8 + #todo: check slot width + slots = 8#12 (150GHz) op = map_modulation_to_op(mod) return op, slots - if rate == 1000: - mod = "DP-64QAM" + elif rate == 1000: + mod = "DP-32QAM" slots = 18 op = map_modulation_to_op(mod) return op, slots @@ -54,21 +65,34 @@ def map_rate_to_slot(rate): return 2, 5 -def consecutives(x, val): +def consecutives(link, val): res = [] temp = [] + x1 = list(link.keys()) + x = str_list_to_int(x1) x.sort() - temp.append(x[0]) - y = 1 + y = 0 + if debug: + print("BLACK") + print(link) + print(x) + print(x[0]) + if link[str(x[0])] == 1: + temp.append(int(x[0])) + y = 1 for i in range(1, len(x)): - if x[i] == x[i - 1] + 1: + if (int(x[i]) == int(x[i - 1]) + 1) and link[str(x[i])] == 1: y += 1 - temp.append(x[i]) + temp.append(int(x[i])) else: if y >= val: res.extend(temp) - temp = [x[i]] - y = 1 + if link[str(x[i])] == 1: + temp = [int(x[i])] + y = 1 + else: + temp = [] + y = 0 if i == len(x) - 1 and y >= val: res.extend(temp) return res @@ -83,6 +107,14 @@ def combine(ls1, ls2): return temp +def str_list_to_int(str_list): + int_list = [] + for i in str_list: + int_list.append(int(i)) + int_list.sort() + return int_list + + def list_in_list(a, b): # convert list A to numpy array a_arr = np.array(a) @@ -112,7 +144,30 @@ def get_slot_frequency(b, n): return Fl + n * 12.5 -def freqency_converter(b, slots): +def get_side_slots_on_link(link, val, old_slots): + #link = l["optical_details"][band] + x = list(old_slots.keys()) + y = list(link.keys()) + keys = str_list_to_int(x) + keys.sort() + #print("AAAA") + #print(link, val, old_slots, keys) + #print(x) + starting_slot = keys[-1] + num = 0 + res = [] + #print(starting_slot) + for slot_id in range(starting_slot, len(y)): + if link[y[slot_id]] == 1: + num += 1 + res.append(int(y[slot_id])) + else: + return res, 0 + if num == val or slot_id == len(y) - 1: + return res, num + + +def frequency_converter(b, slots): l = len(slots) if debug: print(slots) @@ -135,14 +190,24 @@ def freqency_converter(b, slots): def readTopologyData(nodes, topology): - nodes_file = open(nodes, 'r') - topo_file = open(topology, 'r') - nodes = json.load(nodes_file) - topo = json.load(topo_file) - print(topo) - nodes_file.close() - topo_file.close() - return nodes, topo + nodes_file = open(nodes, 'r') + topo_file = open(topology, 'r') + nodes = json.load(nodes_file) + topo = json.load(topo_file) + #print(topo) + nodes_file.close() + topo_file.close() + return nodes, topo + + +def readTopologyDataFromContext(topology_id:TopologyId): + ctx_client = ContextClient() + ctx_client.connect() + topo_details = ctx_client.GetTopologyDetails(topology_id) + topo = topo_details.optical_links + nodes = topo_details.devices + ctx_client.close() + return topo , nodes def reverse_links(links): @@ -154,23 +219,26 @@ def reverse_links(links): result.append("{}-{}".format(b, a)) return result + def get_links_from_node(topology, node): result = {} - for link in topology["links"]: - if "{}-".format(node) in link["optical_link"]["name"]: - result[link["optical_link"]["name"]] = link + for link in topology["optical_links"]: + if "{}-".format(node) in link["name"]: + result[link["name"]] = link return result + def get_links_to_node(topology, node): result = {} - for link in topology["links"]: - if "-{}".format(node) in link["optical_link"]["name"]: - result[link["optical_link"]["name"]] = link + for link in topology["optical_links"]: + if "-{}".format(node) in link["name"]: + result[link["name"]] = link return result def slot_selection(c, l, s, n_slots, Nc, Nl, Ns): # First Fit + if isinstance(n_slots, int): slot_c = n_slots slot_l = n_slots @@ -183,7 +251,75 @@ def slot_selection(c, l, s, n_slots, Nc, Nl, Ns): return "c_slots", c[0: slot_c] elif len(l) >= slot_l: return "l_slots", l[0: slot_l] - elif len(l) >= slot_s: + elif len(s) >= slot_s: return "s_slots", s[0: slot_s] else: return None, None + +def handle_slot (slot_field, slot): + for key,value in slot.items() : + slot_field[key]=value + + + +def update_optical_band (optical_bands,optical_band_id,band,link): + key_list = optical_bands[optical_band_id][band].keys() + corrected_slots=optical_bands[optical_band_id][band] + print(f"band {band}") + print(f"corrected_slots_before {corrected_slots}") + if (len(key_list) < 20): + corrected_slots=correct_slot(optical_bands[optical_band_id][band]) + + fib={} + print(f"corrected_slots_after {corrected_slots}") + fib['c_slots']=link['optical_details']['c_slots'] + fib['l_slots']=link['optical_details']['l_slots'] + fib['s_slots']=link['optical_details']['s_slots'] + + fib[band]=corrected_slots + fib["src_port"]=optical_bands[optical_band_id]['src_port'] + fib["dst_port"]=optical_bands[optical_band_id]['dst_port'] + fib["local_peer_port"]=link["optical_details"]["local_peer_port"] + fib["remote_peer_port"]=link["optical_details"]["remote_peer_port"] + set_link_update(fib,link,test=f"restoring_optical_band {link['link_id']}") + +def set_link_update (fib:dict,link:dict,test="updating"): + + print(f"invoked from {test}") + print(f"fib updated {fib}") + optical_link = OpticalLink() + linkId = LinkId() + linkId.link_uuid.uuid=link["link_id"]["link_uuid"]["uuid"] + optical_details = OpticalLinkDetails() + optical_link.optical_details.length=0 + if "src_port" in fib : + optical_link.optical_details.src_port=fib["src_port"] + if "dst_port" in fib : + optical_link.optical_details.dst_port=fib["dst_port"] + if "local_peer_port" in fib : + optical_link.optical_details.local_peer_port=fib['local_peer_port'] + if "remote_peer_port" in fib: + optical_link.optical_details.remote_peer_port=fib['remote_peer_port'] + + optical_link.optical_details.used=fib['used'] if 'used' in fib else False + if "c_slots" in fib : + + handle_slot( optical_link.optical_details.c_slots,fib["c_slots"]) + if "s_slots" in fib : + + handle_slot( optical_link.optical_details.s_slots,fib["s_slots"]) + if "l_slots" in fib : + + handle_slot( optical_link.optical_details.l_slots,fib["l_slots"]) + + + optical_link.name=link['name'] + + optical_link.link_id.CopyFrom(linkId) + + ctx_client = ContextClient() + ctx_client.connect() + try: + ctx_client.SetOpticalLink(optical_link) + except Exception as err: + print (f"setOpticalLink {err}") diff --git a/src/opticalcontroller/variables.py b/src/opticalcontroller/variables.py index ca436736b20a525c866ea9745be14bc4db37dfcf..83d073e92009c8796a396d19af0bc737865c77e9 100644 --- a/src/opticalcontroller/variables.py +++ b/src/opticalcontroller/variables.py @@ -23,10 +23,4 @@ Nc = 320 #Nc = 10 Ns = 720 -nodes_json = 'json_files/nodes.json' -topology_json = 'json_files/tfs.json' #LAST -#topology_json = 'json_files/optical_TFSworking.json' #LAST -#topology_json = 'json_files/optical_topoTFS.json' -#topology_json = 'json_files/topo_2_links.json' - -testing = 1 +full_links = 0 diff --git a/src/service/service/ServiceServiceServicerImpl.py b/src/service/service/ServiceServiceServicerImpl.py index 45a8e0b6c0fd9a26b45fc47d55074d8863c0caed..992b11cf3edaaed8211cd70a08452cd091cdf19a 100644 --- a/src/service/service/ServiceServiceServicerImpl.py +++ b/src/service/service/ServiceServiceServicerImpl.py @@ -17,7 +17,8 @@ from typing import Optional from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method from common.method_wrappers.ServiceExceptions import ( AlreadyExistsException, InvalidArgumentException, NotFoundException, NotImplementedException, - OperationFailedException) + OperationFailedException +) from common.proto.context_pb2 import ( Connection, ConstraintActionEnum, Empty, Service, ServiceId, ServiceStatusEnum, ServiceTypeEnum, TopologyId @@ -42,7 +43,8 @@ from .service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory from .task_scheduler.TaskScheduler import TasksScheduler from .tools.GeodesicDistance import gps_distance from .tools.OpticalTools import ( - add_lightpath, delete_lightpath, adapt_reply, get_device_name_from_uuid, get_optical_band + add_lightpath, delete_lightpath, adapt_reply, get_device_name_from_uuid, + get_optical_band, refresh_opticalcontroller, DelFlexLightpath ) @@ -257,6 +259,8 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): DEFAULT_TOPOLOGY_NAME, context_id_x) topology_details = context_client.GetTopologyDetails( TopologyId(**topology_id_x)) + + refresh_opticalcontroller(topology_id_x) # devices = get_devices_in_topology(context_client, TopologyId(**topology_id_x), ContextId(**context_id_x)) devices = topology_details.devices context_uuid_x = topology_details.topology_id.context_id.context_uuid.uuid @@ -292,7 +296,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): parent_ob = reply_json["parent_opt_band"] LOGGER.debug('Parent optical-band={}'.format(parent_ob)) optical_band_txt = get_optical_band(parent_ob) - LOGGER.info('optical-band details={}'.format(optical_band_txt)) + else: LOGGER.debug('expected optical band not found') else: @@ -301,12 +305,11 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): LOGGER.debug('Using existing optical band') else: LOGGER.debug('Using existing optical band') + if reply_txt is not None: optical_reply = adapt_reply( devices, _service, reply_json, context_uuid_x, topology_uuid_x, optical_band_txt ) - LOGGER.info('optical_reply={:s}'.format( - grpc_message_to_json_string(optical_reply))) tasks_scheduler.compose_from_pathcompreply( optical_reply, is_delete=False) @@ -342,6 +345,10 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): if service is None: raise Exception('Service({:s}) not found'.format(grpc_message_to_json_string(request))) # pylint: disable=no-member service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PENDING_REMOVAL + + if service.service_type == ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY: + service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_ACTIVE + context_client.SetService(service) if is_deployed_te() and service.service_type == ServiceTypeEnum.SERVICETYPE_TE: @@ -351,7 +358,14 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): context_client.RemoveService(request) return Empty() - if is_deployed_optical() and service.service_type == ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY: + if service.service_type == ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY: + params = { + "src" : None, + "dst" : None, + "bitrate" : None, + 'ob_id' : None, + 'flow_id' : None + } devs = [] context_id_x = json_context_id(DEFAULT_CONTEXT_NAME) @@ -364,15 +378,38 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): devs.append(endpoint_id.device_id.device_uuid.uuid) src = get_device_name_from_uuid(devices, devs[0]) dst = get_device_name_from_uuid(devices, devs[1]) - - bitrate = int( - float(service.service_constraints[0].custom.constraint_value)) + bitrate = 100 + for constraint in service.service_constraints: + if "bandwidth" in constraint.custom.constraint_type: + bitrate = int(float(constraint.custom.constraint_value)) + break + + bitrate = int(float( + service.service_constraints[0].custom.constraint_value + )) if len(service.service_config.config_rules) > 0: c_rules_dict = json.loads( service.service_config.config_rules[0].custom.resource_value) + ob_id = None + flow_id = None + + if "ob_id" in c_rules_dict: + ob_id = c_rules_dict["ob_id"] if ("flow_id" in c_rules_dict): flow_id = c_rules_dict["flow_id"] - reply = delete_lightpath(flow_id, src, dst, bitrate) + #if ("ob_id" in c_rules_dict): + # ob_id = c_rules_dict["ob_id"] + + params['bitrate'] = bitrate + params['dst' ] = dst + params['src' ] = src + params['ob_id' ] = ob_id + params['flow_id'] = flow_id + + tasks_scheduler = TasksScheduler(self.service_handler_factory) + tasks_scheduler.compose_from_optical_service(service, params=params, is_delete=True) + tasks_scheduler.execute_all() + return Empty() # Normal service # Feed TaskScheduler with this service and the sub-services and sub-connections related to this service. diff --git a/src/service/service/__main__.py b/src/service/service/__main__.py index ae8a9e960cf6a0d720b508fe3ea5592632420c18..d4bbccea4fdb03fa8e8f93d8b9987b8436bb434a 100644 --- a/src/service/service/__main__.py +++ b/src/service/service/__main__.py @@ -16,7 +16,8 @@ import logging, signal, sys, threading from prometheus_client import start_http_server from common.Constants import ServiceNameEnum from common.Settings import ( - ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_log_level, get_metrics_port, + ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, + get_env_var_name, get_log_level, get_metrics_port, wait_for_environment_variables ) from .ServiceService import ServiceService diff --git a/src/service/service/service_handlers/oc/ConfigRules.py b/src/service/service/service_handlers/oc/ConfigRules.py deleted file mode 100644 index 44245705ecdb48d33c9152328a352d736cc3dd27..0000000000000000000000000000000000000000 --- a/src/service/service/service_handlers/oc/ConfigRules.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. - -from typing import Dict, List -from common.tools.object_factory.ConfigRule import json_config_rule_delete, json_config_rule_set -from service.service.service_handler_api.AnyTreeTools import TreeNode - -def setup_config_rules( - service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, - service_settings : TreeNode, endpoint_settings : TreeNode -) -> List[Dict]: - - if service_settings is None: return [] - if endpoint_settings is None: return [] - - json_settings : Dict = service_settings.value - json_endpoint_settings : Dict = endpoint_settings.value - - service_short_uuid = service_uuid.split('-')[-1] - network_instance_name = '{:s}-NetInst'.format(service_short_uuid) - network_interface_desc = '{:s}-NetIf'.format(service_uuid) - network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) - - mtu = json_settings.get('mtu', 1450 ) # 1512 - #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - bgp_as = json_settings.get('bgp_as', 0 ) # 65000 - bgp_route_target = json_settings.get('bgp_route_target', '0:0') # 65000:333 - - #router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' - route_distinguisher = json_endpoint_settings.get('route_distinguisher', '0:0' ) # '60001:801' - sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 - vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 - address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' - address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 - if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) - - json_config_rules = [ - json_config_rule_set( - '/network_instance[{:s}]'.format(network_instance_name), { - 'name': network_instance_name, 'description': network_interface_desc, 'type': 'L3VRF', - 'route_distinguisher': route_distinguisher, - #'router_id': router_id, 'address_families': address_families, - }), - json_config_rule_set( - '/interface[{:s}]'.format(endpoint_name), { - 'name': endpoint_name, 'description': network_interface_desc, 'mtu': mtu, - }), - json_config_rule_set( - '/interface[{:s}]/subinterface[{:d}]'.format(endpoint_name, sub_interface_index), { - 'name': endpoint_name, 'index': sub_interface_index, - 'description': network_subinterface_desc, 'vlan_id': vlan_id, - 'address_ip': address_ip, 'address_prefix': address_prefix, - }), - json_config_rule_set( - '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { - 'name': network_instance_name, 'id': if_subif_name, 'interface': endpoint_name, - 'subinterface': sub_interface_index, - }), - json_config_rule_set( - '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { - 'name': network_instance_name, 'identifier': 'BGP', 'protocol_name': 'BGP', 'as': bgp_as, - }), - json_config_rule_set( - '/network_instance[{:s}]/table_connections[STATIC][BGP][IPV4]'.format(network_instance_name), { - 'name': network_instance_name, 'src_protocol': 'STATIC', 'dst_protocol': 'BGP', - 'address_family': 'IPV4', #'default_import_policy': 'REJECT_ROUTE', - }), - json_config_rule_set( - '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format( - network_instance_name), { - 'name': network_instance_name, 'src_protocol': 'DIRECTLY_CONNECTED', 'dst_protocol': 'BGP', - 'address_family': 'IPV4', #'default_import_policy': 'REJECT_ROUTE', - }), - json_config_rule_set( - '/routing_policy/bgp_defined_set[{:s}_rt_import]'.format(network_instance_name), { - 'ext_community_set_name': '{:s}_rt_import'.format(network_instance_name), - }), - json_config_rule_set( - '/routing_policy/bgp_defined_set[{:s}_rt_import][route-target:{:s}]'.format( - network_instance_name, bgp_route_target), { - 'ext_community_set_name': '{:s}_rt_import'.format(network_instance_name), - 'ext_community_member' : 'route-target:{:s}'.format(bgp_route_target), - }), - json_config_rule_set( - '/routing_policy/policy_definition[{:s}_import]'.format(network_instance_name), { - 'policy_name': '{:s}_import'.format(network_instance_name), - }), - json_config_rule_set( - '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format( - network_instance_name, '3'), { - 'policy_name': '{:s}_import'.format(network_instance_name), 'statement_name': '3', - 'ext_community_set_name': '{:s}_rt_import'.format(network_instance_name), - 'match_set_options': 'ANY', 'policy_result': 'ACCEPT_ROUTE', - }), - json_config_rule_set( - # pylint: disable=duplicate-string-formatting-argument - '/network_instance[{:s}]/inter_instance_policies[{:s}_import]'.format( - network_instance_name, network_instance_name), { - 'name': network_instance_name, 'import_policy': '{:s}_import'.format(network_instance_name), - }), - json_config_rule_set( - '/routing_policy/bgp_defined_set[{:s}_rt_export]'.format(network_instance_name), { - 'ext_community_set_name': '{:s}_rt_export'.format(network_instance_name), - }), - json_config_rule_set( - '/routing_policy/bgp_defined_set[{:s}_rt_export][route-target:{:s}]'.format( - network_instance_name, bgp_route_target), { - 'ext_community_set_name': '{:s}_rt_export'.format(network_instance_name), - 'ext_community_member' : 'route-target:{:s}'.format(bgp_route_target), - }), - json_config_rule_set( - '/routing_policy/policy_definition[{:s}_export]'.format(network_instance_name), { - 'policy_name': '{:s}_export'.format(network_instance_name), - }), - json_config_rule_set( - '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format( - network_instance_name, '3'), { - 'policy_name': '{:s}_export'.format(network_instance_name), 'statement_name': '3', - 'ext_community_set_name': '{:s}_rt_export'.format(network_instance_name), - 'match_set_options': 'ANY', 'policy_result': 'ACCEPT_ROUTE', - }), - json_config_rule_set( - # pylint: disable=duplicate-string-formatting-argument - '/network_instance[{:s}]/inter_instance_policies[{:s}_export]'.format( - network_instance_name, network_instance_name), { - 'name': network_instance_name, 'export_policy': '{:s}_export'.format(network_instance_name), - }), - ] - - return json_config_rules - -def teardown_config_rules( - service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str, - service_settings : TreeNode, endpoint_settings : TreeNode -) -> List[Dict]: - - if service_settings is None: return [] - if endpoint_settings is None: return [] - - json_settings : Dict = service_settings.value - json_endpoint_settings : Dict = endpoint_settings.value - - #mtu = json_settings.get('mtu', 1450 ) # 1512 - #address_families = json_settings.get('address_families', [] ) # ['IPV4'] - #bgp_as = json_settings.get('bgp_as', 0 ) # 65000 - bgp_route_target = json_settings.get('bgp_route_target', '0:0') # 65000:333 - - #router_id = json_endpoint_settings.get('router_id', '0.0.0.0') # '10.95.0.10' - #route_distinguisher = json_endpoint_settings.get('route_distinguisher', '0:0' ) # '60001:801' - sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0 ) # 1 - vlan_id = json_endpoint_settings.get('vlan_id', 1 ) # 400 - #address_ip = json_endpoint_settings.get('address_ip', '0.0.0.0') # '2.2.2.1' - #address_prefix = json_endpoint_settings.get('address_prefix', 24 ) # 30 - - if_subif_name = '{:s}.{:d}'.format(endpoint_name, vlan_id) - service_short_uuid = service_uuid.split('-')[-1] - network_instance_name = '{:s}-NetInst'.format(service_short_uuid) - #network_interface_desc = '{:s}-NetIf'.format(service_uuid) - #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid) - - json_config_rules = [ - json_config_rule_delete( - '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), { - 'name': network_instance_name, 'id': if_subif_name, - }), - json_config_rule_delete( - '/interface[{:s}]/subinterface[{:d}]'.format(endpoint_name, sub_interface_index), { - 'name': endpoint_name, 'index': sub_interface_index, - }), - json_config_rule_delete( - '/interface[{:s}]'.format(endpoint_name), { - 'name': endpoint_name, - }), - json_config_rule_delete( - '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format( - network_instance_name), { - 'name': network_instance_name, 'src_protocol': 'DIRECTLY_CONNECTED', 'dst_protocol': 'BGP', - 'address_family': 'IPV4', - }), - json_config_rule_delete( - '/network_instance[{:s}]/table_connections[STATIC][BGP][IPV4]'.format(network_instance_name), { - 'name': network_instance_name, 'src_protocol': 'STATIC', 'dst_protocol': 'BGP', - 'address_family': 'IPV4', - }), - json_config_rule_delete( - '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), { - 'name': network_instance_name, 'identifier': 'BGP', 'protocol_name': 'BGP', - }), - json_config_rule_delete( - # pylint: disable=duplicate-string-formatting-argument - '/network_instance[{:s}]/inter_instance_policies[{:s}_import]'.format( - network_instance_name, network_instance_name), { - 'name': network_instance_name, - }), - json_config_rule_delete( - '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format( - network_instance_name, '3'), { - 'policy_name': '{:s}_import'.format(network_instance_name), 'statement_name': '3', - }), - json_config_rule_delete( - '/routing_policy/policy_definition[{:s}_import]'.format(network_instance_name), { - 'policy_name': '{:s}_import'.format(network_instance_name), - }), - json_config_rule_delete( - '/routing_policy/bgp_defined_set[{:s}_rt_import][route-target:{:s}]'.format( - network_instance_name, bgp_route_target), { - 'ext_community_set_name': '{:s}_rt_import'.format(network_instance_name), - 'ext_community_member' : 'route-target:{:s}'.format(bgp_route_target), - }), - json_config_rule_delete( - '/routing_policy/bgp_defined_set[{:s}_rt_import]'.format(network_instance_name), { - 'ext_community_set_name': '{:s}_rt_import'.format(network_instance_name), - }), - json_config_rule_delete( - # pylint: disable=duplicate-string-formatting-argument - '/network_instance[{:s}]/inter_instance_policies[{:s}_export]'.format( - network_instance_name, network_instance_name), { - 'name': network_instance_name, - }), - json_config_rule_delete( - '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format( - network_instance_name, '3'), { - 'policy_name': '{:s}_export'.format(network_instance_name), 'statement_name': '3', - }), - json_config_rule_delete( - '/routing_policy/policy_definition[{:s}_export]'.format(network_instance_name), { - 'policy_name': '{:s}_export'.format(network_instance_name), - }), - json_config_rule_delete( - '/routing_policy/bgp_defined_set[{:s}_rt_export][route-target:{:s}]'.format( - network_instance_name, bgp_route_target), { - 'ext_community_set_name': '{:s}_rt_export'.format(network_instance_name), - 'ext_community_member' : 'route-target:{:s}'.format(bgp_route_target), - }), - json_config_rule_delete( - '/routing_policy/bgp_defined_set[{:s}_rt_export]'.format(network_instance_name), { - 'ext_community_set_name': '{:s}_rt_export'.format(network_instance_name), - }), - json_config_rule_delete( - '/network_instance[{:s}]'.format(network_instance_name), { - 'name': network_instance_name - }), - ] - return json_config_rules diff --git a/src/service/service/service_handlers/oc/OCServiceHandler.py b/src/service/service/service_handlers/oc/OCServiceHandler.py index 73ff3b89dea808d7a857cd52d5b4d4e581d218cc..277080d6589d08e9765b16962b2cc5737c2c50af 100644 --- a/src/service/service/service_handlers/oc/OCServiceHandler.py +++ b/src/service/service/service_handlers/oc/OCServiceHandler.py @@ -15,15 +15,18 @@ import json, logging from typing import Any, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method -from common.proto.context_pb2 import ConfigRule, DeviceId, Service +from common.proto.context_pb2 import DeviceId, Service from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_type -from service.service.service_handler_api.Tools import get_device_endpoint_uuids, get_endpoint_matching +from common.DeviceTypes import DeviceTypeEnum +from service.service.service_handler_api.Tools import get_endpoint_matching from service.service.service_handler_api._ServiceHandler import _ServiceHandler from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.task_scheduler.TaskExecutor import TaskExecutor -from .ConfigRules import setup_config_rules, teardown_config_rules -from .OCTools import convert_endpoints_to_flows, handle_flows_names +from .OCTools import ( + convert_endpoints_to_flows, endpoints_to_flows, + #handle_flows_names, check_media_channel_existance +) LOGGER = logging.getLogger(__name__) @@ -47,70 +50,88 @@ class OCServiceHandler(_ServiceHandler): is_opticalband =False #service_uuid = self.__service.service_id.service_uuid.uuid settings=None + if self.__settings_handler.get('/settings-ob_{}'.format(connection_uuid)): is_opticalband=True settings = self.__settings_handler.get('/settings-ob_{}'.format(connection_uuid)) else: settings = self.__settings_handler.get('/settings') - + bidir = settings.value.get("bidir") + LOGGER.debug(f"Bidir bvalue is: {bidir}") # settings = self.__settings_handler.get('/settings') #flow is the new variable that stores input-output relationship - - flows = convert_endpoints_to_flows(endpoints) + #flows = convert_endpoints_to_flows(endpoints) + flows = endpoints_to_flows(endpoints, bidir, is_opticalband) #handled_flows=handle_flows_names(flows=flows,task_executor=self.__task_executor) - - #LOGGER.info("Handled Flows %s",handled_flows) - + results = [] + #new cycle for setting optical devices - for device_uuid in flows.keys(): + for device_uuid, dev_flows in flows.items(): try: - dev_flows = flows[device_uuid] device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) - - - if (settings): - + if settings: self.__task_executor.configure_optical_device(device_obj, settings, dev_flows, is_opticalband) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to configure Device({:s})'.format(str(device_uuid))) results.append(e) - + return results @metered_subclass_method(METRICS_POOL) def DeleteEndpoint( self, endpoints : List[Tuple[str, str, Optional[str]]], connection_uuid : Optional[str] = None ) -> List[Union[bool, Exception]]: + is_opticalband =False + flows = convert_endpoints_to_flows(endpoints) + chk_type('endpoints', endpoints, list) if len(endpoints) == 0: return [] - service_uuid = self.__service.service_id.service_uuid.uuid - settings = self.__settings_handler.get('/settings') + if self.__settings_handler.get('/settings-ob_{}'.format(connection_uuid)): + is_opticalband =True + settings = self.__settings_handler.get('/settings-ob_{}'.format(connection_uuid)) + else: + settings = self.__settings_handler.get('/settings') results = [] - for endpoint in endpoints: + for device_uuid, dev_flows in flows.items(): try: - device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint) - + channel_indexes= [] device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) - endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid) - endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj) - endpoint_name = endpoint_obj.name - - json_config_rules = teardown_config_rules( - service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name, - settings, endpoint_settings) - - if len(json_config_rules) > 0: - del device_obj.device_config.config_rules[:] - for json_config_rule in json_config_rules: - device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) - self.__task_executor.configure_device(device_obj) + if (device_obj.device_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_): + for endpoint in dev_flows: + src , dst = endpoint + src_enpoint_name='0' + dist_enpoint_name='0' + if src !="0": + src_endponit_obj =get_endpoint_matching(device_obj, src) + src_enpoint_name=src_endponit_obj.name + if dst !="0": + dst_endpoint_obj = get_endpoint_matching(device_obj, dst) + dist_enpoint_name=dst_endpoint_obj.name + channel_indexes.append((src_enpoint_name,dist_enpoint_name)) + else: + if not is_opticalband: + if 'flow_id' in settings.value: + channel_indexes.append(settings.value["flow_id"]) + elif is_opticalband: + if "ob_id" in settings.value: + channel_indexes.append(settings.value["ob_id"]) + + if len(channel_indexes) > 0: + errors = self.__task_executor.deconfigure_optical_device( + device=device_obj, channel_indexes=channel_indexes, + is_opticalband=is_opticalband, dev_flow=dev_flows + ) + # if (len(errors)==0): + # service_id =self.__service.service_id + # if not is_opticalband : + # self.__task_executor.delete_setting(service_id,"/settings","value") results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteEndpoint({:s})'.format(str(endpoint))) @@ -157,13 +178,21 @@ class OCServiceHandler(_ServiceHandler): def DeleteConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: chk_type('resources', resources, list) if len(resources) == 0: return [] + service_id = self.__service.service_id results = [] for resource in resources: try: self.__settings_handler.delete(resource[0]) + # self.__task_executor.delete_setting(service_id,"/settings","value") except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteConfig({:s})'.format(str(resource))) results.append(e) return results + + def check_media_channel(self,connection_uuid): + if self.__settings_handler.get('/settings-ob_{}'.format(connection_uuid)): + return False + else: + return True diff --git a/src/service/service/service_handlers/oc/OCTools.py b/src/service/service/service_handlers/oc/OCTools.py index 7b6c344ede5512f32098fd019076ae57fe87028e..e9097c7e7136303586edc1d7c1dc56d89ad0b3dc 100644 --- a/src/service/service/service_handlers/oc/OCTools.py +++ b/src/service/service/service_handlers/oc/OCTools.py @@ -12,11 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -from service.service.service_handler_api.Tools import get_device_endpoint_uuids, get_endpoint_matching -from typing import Dict, Any, List, Optional, Tuple -import logging -from common.proto.context_pb2 import ConfigRule, DeviceId, Service +import logging, json +from typing import Dict, List, Optional, Tuple +from common.proto.context_pb2 import DeviceId, Service from common.tools.object_factory.Device import json_device_id +from service.service.service_handler_api.Tools import get_endpoint_matching log = logging.getLogger(__name__) @@ -116,27 +116,227 @@ def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]]) return entries -def get_device_endpint_name (endpoint_uuid:str,device_uuid:str,task_executor)->Tuple: +def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): + entries = {} + end = len(endpoints) + i = 0 + if bidir: + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + entry_tuple = "0", endpoint_uuid + entries[device_uuid].append(entry_tuple) + next_endpoint = endpoints[i+1] + next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] + if next_device_uuid == device_uuid: + if next_device_uuid not in entries.keys(): + entries[next_device_uuid] = [] + entry_tuple = next_endpoint_uuid, "0" + entries[next_device_uuid].append(entry_tuple) + else: + log.info("error expected device_id {}, found {}".format(device_uuid, next_device_uuid)) + return {} + i = i + 2 + if end > 4: + + while(i < end-2): + #i + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + log.debug("current OCTools step {}, {}, {}".format(i, device_uuid, endpoint_uuid)) + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + #i+1 + next_endpoint = endpoints[i+1] + next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] + if next_device_uuid == device_uuid: + entry_tuple = endpoint_uuid, next_endpoint_uuid + entries[device_uuid].append(entry_tuple) + else: + log.debug("ERROR in bidirectional ob") + log.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) + return {} + #i+2 + next_2_endpoint = endpoints[i+2] + next_2_device_uuid, next_2_endpoint_uuid = next_2_endpoint[0:2] + #i+3 + next_3_endpoint = endpoints[i+3] + next_3_device_uuid, next_3_endpoint_uuid = next_3_endpoint[0:2] + if next_2_device_uuid == next_3_device_uuid and next_3_device_uuid == device_uuid: + entry_tuple = next_2_endpoint_uuid, next_3_endpoint_uuid + entries[device_uuid].append(entry_tuple) + i = i + 4 + else: + log.debug("ERROR in bidirection ob") + return {} + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + entry_tuple = endpoint_uuid, "0", + entries[device_uuid].append(entry_tuple) + next_endpoint = endpoints[i+1] + next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] + if next_device_uuid == device_uuid: + if next_device_uuid not in entries.keys(): + entries[next_device_uuid] = [] + entry_tuple = "0", next_endpoint_uuid + entries[next_device_uuid].append(entry_tuple) + else: + log.debug("error expected device_id {}, found {}".format(device_uuid, next_device_uuid)) + else: + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + entry_tuple = "0", endpoint_uuid + entries[device_uuid].append(entry_tuple) + i = i + 1 + if end > 2: + + while(i < end-1): + #i + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + #i+1 + next_endpoint = endpoints[i+1] + next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] + if next_device_uuid == device_uuid: + entry_tuple = endpoint_uuid, next_endpoint_uuid + entries[device_uuid].append(entry_tuple) + else: + log.debug("ERROR in bidirectional ob") + log.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) + return {} + i = i + 2 + next_endpoint = endpoints[i] + next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] + if next_device_uuid not in entries.keys(): + entries[next_device_uuid] = [] + entry_tuple = next_endpoint_uuid, "0" + entries[next_device_uuid].append(entry_tuple) + return entries + + +def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): + entries = {} + end = len(endpoints) + i = 0 + #tx tp + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + entry_tuple = "0", endpoint_uuid + entries[device_uuid].append(entry_tuple) + i = i + 1 + #if bidir reading 4 endpoints per node + if bidir: + i = i + 1 + while(i < end-2): + #i + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + #i+1 + next_endpoint = endpoints[i+1] + next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] + if next_device_uuid == device_uuid: + entry_tuple = endpoint_uuid, next_endpoint_uuid + entries[device_uuid].append(entry_tuple) + else: + + return {} + #i+2 + + next_2_endpoint = endpoints[i+2] + next_2_device_uuid, next_2_endpoint_uuid = next_2_endpoint[0:2] + #i+3 + next_3_endpoint = endpoints[i+3] + next_3_device_uuid, next_3_endpoint_uuid = next_3_endpoint[0:2] + if next_2_device_uuid == next_3_device_uuid and next_3_device_uuid == device_uuid: + entry_tuple = next_2_endpoint_uuid, next_3_endpoint_uuid + entries[device_uuid].append(entry_tuple) + i = i + 4 + else: + + return {} + else: + while(i < end-1): + #i + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + #i+1 + next_endpoint = endpoints[i+1] + next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] + if next_device_uuid == device_uuid: + entry_tuple = endpoint_uuid, next_endpoint_uuid + entries[device_uuid].append(entry_tuple) + i = i + 2 + else: + return {} + #rx tp + endpoint = endpoints[i] + device_uuid, endpoint_uuid = endpoint[0:2] + if device_uuid not in entries.keys(): + entries[device_uuid] = [] + entry_tuple = endpoint_uuid, "0", + entries[device_uuid].append(entry_tuple) + return entries + +def endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, is_ob: bool)->Dict: + if is_ob: + entries = ob_flows(endpoints, bidir) + else: + entries = conn_flows(endpoints, bidir) + return entries + +def get_device_endpint_name(endpoint_uuid : str, device_uuid : str, task_executor) -> Tuple: device_obj = task_executor.get_device(DeviceId(**json_device_id(device_uuid))) endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid) endpoint_name = endpoint_obj.name return (device_obj.name, endpoint_name) -def handle_flows_names (task_executor,flows:dict)->Dict : - new_flows={} - for index,( device_uuid_key , device_endpoints_list) in enumerate(flows.items()): +def handle_flows_names(task_executor, flows : dict) -> Dict: + new_flows = {} + for index, (device_uuid_key, device_endpoints_list) in enumerate(flows.items()): for endpoint_tupple in device_endpoints_list: - source_port=None - destination_port=None - device_name="" - source_endpoint,destination_endpoint =endpoint_tupple - if (source_endpoint !='0'): - if get_device_endpint_name(source_endpoint,device_uuid_key,task_executor) is not None: - device_name,source_port=get_device_endpint_name(source_endpoint,device_uuid_key,task_executor) - if (destination_endpoint !='0'): - if get_device_endpint_name(destination_endpoint,device_uuid_key,task_executor) is not None: - device_name,destination_port=get_device_endpint_name(destination_endpoint,device_uuid_key,task_executor) - if (device_name not in new_flows): - new_flows[device_name]=[] - new_flows[device_name].append((source_port,destination_port)) + source_port = None + destination_port = None + device_name = "" + source_endpoint, destination_endpoint = endpoint_tupple + if source_endpoint != '0': + if get_device_endpint_name(source_endpoint, device_uuid_key, task_executor) is not None: + device_name, source_port = get_device_endpint_name( + source_endpoint, device_uuid_key, task_executor + ) + if destination_endpoint != '0': + if get_device_endpint_name(destination_endpoint, device_uuid_key, task_executor) is not None: + device_name, destination_port = get_device_endpint_name( + destination_endpoint, device_uuid_key, task_executor + ) + if device_name not in new_flows: + new_flows[device_name] = [] + new_flows[device_name].append((source_port, destination_port)) return new_flows + +def check_media_channel_existance(service : Service): + has_media_channel = False + for config_rule in service.service_config.config_rules: + if isinstance(config_rule.custom.resource_value, str): + settings = json.dumps(config_rule.custom.resource_value) + if "flow_id" in settings: + has_media_channel = True + return has_media_channel diff --git a/src/service/service/task_scheduler/TaskExecutor.py b/src/service/service/task_scheduler/TaskExecutor.py index 70d17027eb48987faef562118bf4fb42dfb9c399..ac06e321d342fc7cddb9f54958a38ed87067c922 100644 --- a/src/service/service/task_scheduler/TaskExecutor.py +++ b/src/service/service/task_scheduler/TaskExecutor.py @@ -21,7 +21,7 @@ from typing import List from common.proto.qkd_app_pb2 import QKDAppStatusEnum from common.proto.context_pb2 import ( Connection, ConnectionId, Device, DeviceDriverEnum, DeviceId, Service, ServiceId, - OpticalConfig, OpticalConfigId + OpticalConfig, OpticalConfigId, ConnectionList, ServiceConfigRule ) from common.proto.qkd_app_pb2 import App, AppId from common.proto.context_pb2 import ContextId @@ -38,6 +38,7 @@ from service.service.service_handler_api.Exceptions import ( ) from service.service.service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory, get_service_handler_class from service.service.tools.ObjectKeys import get_connection_key, get_device_key, get_service_key, get_qkd_app_key +from service.service.tools.object_uuid import opticalconfig_get_uuid if TYPE_CHECKING: from service.service.service_handler_api._ServiceHandler import _ServiceHandler @@ -126,17 +127,27 @@ class TaskExecutor: self._store_grpc_object(CacheableObjectType.DEVICE, device_key, device) # New function Andrea for Optical Devices - def configure_optical_device(self, device : Device, settings : str, flows : list, is_opticalband : bool): + def configure_optical_device( + self, device : Device, settings : str, flows : list, is_opticalband : bool + ): device_key = get_device_key(device.device_id) optical_config_id = OpticalConfigId() - optical_config_id.opticalconfig_uuid = device.device_id.device_uuid.uuid + optical_config_id.opticalconfig_uuid = opticalconfig_get_uuid(device.device_id) + optical_config = OpticalConfig() - setting = settings.value if settings else '' + + setting = settings.value if settings else "" + config_type = None try: result = self._context_client.SelectOpticalConfig(optical_config_id) - if result is not None: - new_config = json.loads(result.config) + + new_config = json.loads(result.config) + if 'type' in new_config: + config_type=new_config['type'] + if config_type == 'optical-transponder': + setting['status']='ENABLED' + if result is not None : new_config["new_config"] = setting new_config["is_opticalband"] = is_opticalband new_config["flow"] = flows @@ -145,7 +156,86 @@ class TaskExecutor: self._device_client.ConfigureOpticalDevice(optical_config) self._store_grpc_object(CacheableObjectType.DEVICE, device_key, device) except Exception as e: - LOGGER.info("error in config my config %s",e) + LOGGER.info("error in configure_optical_device %s",e) + + # Deconfiguring Optical Devices ( CNIT ) + def deconfigure_optical_device( + self, device : Device, channel_indexes : list, is_opticalband : bool, dev_flow : list + ): + errors = [] + flows = [] + indexes = {} + new_config = {} + optical_config_id = OpticalConfigId() + optical_config_id.opticalconfig_uuid = opticalconfig_get_uuid(device.device_id) + # if transponder the channel index is same as its endpoint + if device.device_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + for index in channel_indexes : + flows.append(index) + # if Roadm the channel index is the flow_id ,or ob_id + else: + for index in channel_indexes: + if not is_opticalband: + indexes["flow_id"] = index + else: + indexes["ob_id"] = index + + try: + result = self._context_client.SelectOpticalConfig(optical_config_id) + # for extractor in device service to extract the index , dummy data for freq and band required + indexes["frequency"] = None + indexes["band"] = None + if result is not None: + new_config = json.loads(result.config) + new_config["new_config"]=indexes + new_config["flow"] = flows if len(flows)>0 else dev_flow + new_config["is_opticalband"] = is_opticalband + result.config = json.dumps(new_config) + # new_optical_config.config= json.dumps(new_config) + # new_optical_config.opticalconfig_id.CopyFrom (optical_config_id) + # new_optical_config.device_id.CopyFrom(device.device_id) + self._device_client.DisableOpticalDevice(result) + except Exception as e: + errors.append(e) + LOGGER.info("error in deconfigure_optical_device %s",e) + return errors + + def delete_setting( + self, service_id : ServiceId, config_key : str, config_value : str + ): + service_configRule = ServiceConfigRule() + service_configRule.service_id.CopyFrom( service_id) + service_configRule.configrule_custom.resource_key = config_key + service_configRule.configrule_custom.resource_value = config_value + try: + ctxt = ContextClient() + ctxt.connect() + ctxt.DeleteServiceConfigRule(service_configRule) + ctxt.close() + except Exception as e : + LOGGER.info("error in delete service config rule %s",e) + + def check_service_for_media_channel(self, connections : ConnectionList, item) -> bool: + service = item + if (isinstance(item, ServiceId)): + service = self.get_service(item) + class_service_handler = None + service_handler_settings = {} + for connection in connections.connections: + connection_uuid=connection.connection_id.connection_uuid + if class_service_handler is None: + class_service_handler = self.get_service_handler(connection, service,**service_handler_settings) + if class_service_handler.check_media_channel(connection_uuid): + return True + return False + + def check_connection_for_media_channel( + self, connection : Connection, service : Service + ) -> bool: + service_handler_settings = {} + connection_uuid = connection.connection_id.connection_uuid + service_handler_class = self.get_service_handler(connection, service, **service_handler_settings) + return service_handler_class.check_media_channel(connection_uuid) def get_device_controller(self, device : Device) -> Optional[Device]: #json_controller = None @@ -296,4 +386,3 @@ class TaskExecutor: except Exception as e: LOGGER.error(f"Failed to delete QKD app with AppId {app_id}: {str(e)}") raise e - diff --git a/src/service/service/task_scheduler/TaskScheduler.py b/src/service/service/task_scheduler/TaskScheduler.py index b492b4581b05cb34bed624efd9be2d4f62da5856..c2d8423156fd145a262108701860aeb17df3e6f9 100644 --- a/src/service/service/task_scheduler/TaskScheduler.py +++ b/src/service/service/task_scheduler/TaskScheduler.py @@ -14,17 +14,23 @@ import graphlib, logging, queue, time from typing import TYPE_CHECKING, Dict, Tuple -from common.proto.context_pb2 import Connection, ConnectionId, Service, ServiceId, ServiceStatusEnum +from common.proto.context_pb2 import ( + Connection, ConnectionId, Service, ServiceId, ServiceStatusEnum, ConnectionList +) from common.proto.pathcomp_pb2 import PathCompReply from common.tools.grpc.Tools import grpc_message_to_json_string from context.client.ContextClient import ContextClient from service.service.tools.ObjectKeys import get_connection_key, get_service_key from .tasks._Task import _Task from .tasks.Task_ConnectionConfigure import Task_ConnectionConfigure +from .tasks.Task_OpticalConnectionDeconfigure import Task_OpticalConnectionDeconfigure +from .tasks.Task_OpticalServiceDelete import Task_OpticalServiceDelete from .tasks.Task_ConnectionDeconfigure import Task_ConnectionDeconfigure from .tasks.Task_ServiceDelete import Task_ServiceDelete from .tasks.Task_ServiceSetStatus import Task_ServiceSetStatus from .TaskExecutor import CacheableObjectType, TaskExecutor +from .tasks.Task_OpticalServiceConfigDelete import Task_OpticalServiceConfigDelete +from service.service.tools.OpticalTools import delete_lightpath if TYPE_CHECKING: from service.service.service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory @@ -70,6 +76,7 @@ class TasksScheduler: return service_planned_key, service_active_key def _service_remove(self, service_id : ServiceId) -> Tuple[str, str]: + service_removing_key = self._add_task_if_not_exists(Task_ServiceSetStatus( self._executor, service_id, ServiceStatusEnum.SERVICESTATUS_PENDING_REMOVAL)) @@ -79,6 +86,21 @@ class TasksScheduler: self._dag.add(service_delete_key, service_removing_key) return service_removing_key, service_delete_key + def _optical_service_remove( + self, service_id : ServiceId, has_media_channel : bool, has_optical_band = True + ) -> Tuple[str, str]: + service_removing_key = self._add_task_if_not_exists(Task_ServiceSetStatus( + self._executor, service_id, ServiceStatusEnum.SERVICESTATUS_ACTIVE + )) + + service_delete_key = self._add_task_if_not_exists(Task_OpticalServiceDelete( + self._executor, service_id, has_media_channel, has_optical_band + )) + + # deleting a service requires the service is in removing state + self._dag.add(service_delete_key, service_removing_key) + return service_removing_key, service_delete_key + def _connection_configure(self, connection_id : ConnectionId, service_id : ServiceId) -> str: connection_configure_key = self._add_task_if_not_exists(Task_ConnectionConfigure( self._executor, connection_id)) @@ -97,20 +119,56 @@ class TasksScheduler: def _connection_deconfigure(self, connection_id : ConnectionId, service_id : ServiceId) -> str: connection_deconfigure_key = self._add_task_if_not_exists(Task_ConnectionDeconfigure( - self._executor, connection_id)) + self._executor, connection_id + )) # the connection deconfiguration depends on its connection's service being in removing state service_pending_removal_key = self._add_task_if_not_exists(Task_ServiceSetStatus( - self._executor, service_id, ServiceStatusEnum.SERVICESTATUS_PENDING_REMOVAL)) + self._executor, service_id, ServiceStatusEnum.SERVICESTATUS_PENDING_REMOVAL + )) self._dag.add(connection_deconfigure_key, service_pending_removal_key) # the connection's service depends on the connection deconfiguration to transition to delete service_delete_key = self._add_task_if_not_exists(Task_ServiceDelete( - self._executor, service_id)) + self._executor, service_id + )) self._dag.add(service_delete_key, connection_deconfigure_key) return connection_deconfigure_key + def _optical_connection_deconfigure( + self, connection_id : ConnectionId, service_id : ServiceId, + has_media_channel : bool, has_optical_band = True + ) -> str: + connection_deconfigure_key = self._add_task_if_not_exists(Task_OpticalConnectionDeconfigure( + self._executor, connection_id, has_media_channel=has_media_channel + )) + + # the connection deconfiguration depends on its connection's service being in removing state + service_pending_removal_key = self._add_task_if_not_exists(Task_ServiceSetStatus( + self._executor, service_id, ServiceStatusEnum.SERVICESTATUS_ACTIVE + )) + self._dag.add(connection_deconfigure_key, service_pending_removal_key) + + service_delete_key = self._add_task_if_not_exists(Task_OpticalServiceDelete( + self._executor, service_id, has_media_channel, has_optical_band + )) + self._dag.add(service_delete_key, connection_deconfigure_key) + + return connection_deconfigure_key + + def _optical_service_config_remove( + self, connection_id : ConnectionId, service_id : ServiceId + ) -> str: + service_config_key = self._add_task_if_not_exists(Task_OpticalServiceConfigDelete( + self._executor, connection_id, service_id + )) + service_pending_removal_key = self._add_task_if_not_exists(Task_ServiceSetStatus( + self._executor, service_id, ServiceStatusEnum.SERVICESTATUS_ACTIVE + )) + self._dag.add(service_config_key, service_pending_removal_key) + return service_config_key + def compose_from_pathcompreply(self, pathcomp_reply : PathCompReply, is_delete : bool = False) -> None: t0 = time.time() include_service = self._service_remove if is_delete else self._service_create @@ -132,6 +190,136 @@ class TasksScheduler: t1 = time.time() LOGGER.debug('[compose_from_pathcompreply] elapsed_time: {:f} sec'.format(t1-t0)) + def check_service_for_media_channel( + self, connections : ConnectionList, item + )->Tuple[bool, bool]: + service = item + has_media_channel = False + has_optical_band = False + if isinstance(item, ServiceId): + service = self._executor.get_service(item) + class_service_handler = None + service_handler_settings = {} + for connection in connections.connections: + connection_uuid = connection.connection_id.connection_uuid.uuid + if class_service_handler is None: + class_service_handler = self._executor.get_service_handler( + connection, service, **service_handler_settings + ) + if class_service_handler.check_media_channel(connection_uuid): + has_media_channel = True + else : + has_optical_band = True + return (has_media_channel, has_optical_band) + + def compose_from_optical_service( + self, service : Service, params : dict, is_delete : bool = False + ) -> None: + t0 = time.time() + include_service = self._optical_service_remove if is_delete else self._service_create + include_connection = self._optical_connection_deconfigure if is_delete else self._connection_configure + include_service_config = self._optical_service_config_remove if is_delete else None + + explored_items = set() + pending_items_to_explore = queue.Queue() + pending_items_to_explore.put(service) + has_media_channel = None + has_optical_band = None + reply = None + code = 0 + reply_not_allowed = "DELETE_NOT_ALLOWED" + while not pending_items_to_explore.empty(): + try: + item = pending_items_to_explore.get(block=False) + except queue.Empty: + break + + if isinstance(item, Service): + str_item_key = grpc_message_to_json_string(item.service_id) + if str_item_key in explored_items: continue + connections = self._context_client.ListConnections(item.service_id) + has_media_channel, has_optical_band = self.check_service_for_media_channel( + connections=connections, item=item.service_id + ) + + if len(service.service_config.config_rules) > 0: + reply, code = delete_lightpath( + params['src'], params ['dst'], params['bitrate'], params['ob_id'], + delete_band=not has_media_channel, flow_id= params['flow_id'] + ) + + if code == 400 and reply_not_allowed in reply: + MSG = 'Deleteion for the service is not Allowed , Served Lightpaths is not empty' + raise Exception(MSG) + + include_service( + item.service_id, has_media_channel=has_media_channel, has_optical_band=has_optical_band + ) + self._add_service_to_executor_cache(item) + + for connection in connections.connections: + self._add_connection_to_executor_cache(connection) + pending_items_to_explore.put(connection) + explored_items.add(str_item_key) + + elif isinstance(item, ServiceId): + if code == 400 and reply_not_allowed in reply: break + str_item_key = grpc_message_to_json_string(item) + if str_item_key in explored_items: continue + connections = self._context_client.ListConnections(item) + has_media_channel, has_optical_band = self.check_service_for_media_channel( + connections=connections, item=item + ) + include_service( + item, has_media_channel=has_media_channel, has_optical_band=has_optical_band + ) + self._executor.get_service(item) + + for connection in connections.connections: + self._add_connection_to_executor_cache(connection) + pending_items_to_explore.put(connection) + explored_items.add(str_item_key) + + elif isinstance(item, Connection): + if code == 400 and reply_not_allowed in reply:break + str_item_key = grpc_message_to_json_string(item.connection_id) + if str_item_key in explored_items: continue + connection_key = include_connection( + item.connection_id, item.service_id, has_media_channel=has_media_channel, + has_optical_band=has_optical_band + ) + self._add_connection_to_executor_cache(connection) + + if include_service_config is not None : + connections_list = ConnectionList() + connections_list.connections.append(item) + is_media_channel, _ = self.check_service_for_media_channel( + connections=connections_list, item=service + ) + if has_optical_band and is_media_channel: + include_service_config( + item.connection_id, item.service_id + ) + self._executor.get_service(item.service_id) + pending_items_to_explore.put(item.service_id) + + for sub_service_id in item.sub_service_ids: + _,service_key_done = include_service( + sub_service_id, has_media_channel=has_media_channel, + has_optical_band=has_optical_band + ) + self._executor.get_service(sub_service_id) + self._dag.add(service_key_done, connection_key) + pending_items_to_explore.put(sub_service_id) + + explored_items.add(str_item_key) + else: + MSG = 'Unsupported item {:s}({:s})' + raise Exception(MSG.format(type(item).__name__, grpc_message_to_json_string(item))) + + t1 = time.time() + LOGGER.debug('[compose_from_service] elapsed_time: {:f} sec'.format(t1-t0)) + def compose_from_service(self, service : Service, is_delete : bool = False) -> None: t0 = time.time() include_service = self._service_remove if is_delete else self._service_create @@ -157,7 +345,6 @@ class TasksScheduler: for connection in connections.connections: self._add_connection_to_executor_cache(connection) pending_items_to_explore.put(connection) - explored_items.add(str_item_key) elif isinstance(item, ServiceId): @@ -170,7 +357,6 @@ class TasksScheduler: for connection in connections.connections: self._add_connection_to_executor_cache(connection) pending_items_to_explore.put(connection) - explored_items.add(str_item_key) elif isinstance(item, Connection): @@ -179,7 +365,6 @@ class TasksScheduler: connection_key = include_connection(item.connection_id, item.service_id) self._add_connection_to_executor_cache(connection) - self._executor.get_service(item.service_id) pending_items_to_explore.put(item.service_id) @@ -208,16 +393,20 @@ class TasksScheduler: self._add_connection_to_executor_cache(new_connection) service_updating_key = self._add_task_if_not_exists(Task_ServiceSetStatus( - self._executor, service.service_id, ServiceStatusEnum.SERVICESTATUS_UPDATING)) + self._executor, service.service_id, ServiceStatusEnum.SERVICESTATUS_UPDATING + )) old_connection_deconfigure_key = self._add_task_if_not_exists(Task_ConnectionDeconfigure( - self._executor, old_connection.connection_id)) + self._executor, old_connection.connection_id + )) new_connection_configure_key = self._add_task_if_not_exists(Task_ConnectionConfigure( - self._executor, new_connection.connection_id)) + self._executor, new_connection.connection_id + )) service_active_key = self._add_task_if_not_exists(Task_ServiceSetStatus( - self._executor, service.service_id, ServiceStatusEnum.SERVICESTATUS_ACTIVE)) + self._executor, service.service_id, ServiceStatusEnum.SERVICESTATUS_ACTIVE + )) # the old connection deconfiguration depends on service being in updating state self._dag.add(old_connection_deconfigure_key, service_updating_key) @@ -239,7 +428,7 @@ class TasksScheduler: def execute_all(self, dry_run : bool = False) -> None: ordered_task_keys = list(self._dag.static_order()) - LOGGER.debug('[execute_all] ordered_task_keys={:s}'.format(str(ordered_task_keys))) + LOGGER.info('[execute_all] ordered_task_keys={:s}'.format(str(ordered_task_keys))) results = [] for task_key in ordered_task_keys: diff --git a/src/service/service/task_scheduler/tasks/Task_OpticalConnectionDeconfigure.py b/src/service/service/task_scheduler/tasks/Task_OpticalConnectionDeconfigure.py new file mode 100644 index 0000000000000000000000000000000000000000..b1afdeef19d6526d6f52b05924b5b77a8049da8f --- /dev/null +++ b/src/service/service/task_scheduler/tasks/Task_OpticalConnectionDeconfigure.py @@ -0,0 +1,75 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from common.method_wrappers.ServiceExceptions import OperationFailedException +from common.proto.context_pb2 import ConnectionId +from common.tools.grpc.Tools import grpc_message_to_json_string +from service.service.service_handler_api.Tools import check_errors_deleteendpoint +from service.service.task_scheduler.TaskExecutor import TaskExecutor +from service.service.tools.EndpointIdFormatters import endpointids_to_raw +from service.service.tools.ObjectKeys import get_connection_key +from ._Task import _Task + +KEY_TEMPLATE = 'optical_connection({connection_id:s}):deconfigure' + +class Task_OpticalConnectionDeconfigure(_Task): + def __init__( + self, task_executor : TaskExecutor, connection_id : ConnectionId, + has_media_channel : bool + ) -> None: + super().__init__(task_executor) + self._connection_id = connection_id + self._has_media_channel = has_media_channel + + @property + def connection_id(self) -> ConnectionId: return self._connection_id + + @staticmethod + def build_key(connection_id : ConnectionId) -> str: # pylint: disable=arguments-differ + str_connection_id = get_connection_key(connection_id) + return KEY_TEMPLATE.format(connection_id=str_connection_id) + + @property + def key(self) -> str: return self.build_key(self._connection_id) + + def execute(self) -> None: + connection = self._task_executor.get_connection(self._connection_id) + service = self._task_executor.get_service(connection.service_id) + errors = [] + service_handler_settings = {} + service_handler = self._task_executor.get_service_handler(connection, service, **service_handler_settings) + + endpointids_to_delete = endpointids_to_raw(connection.path_hops_endpoint_ids) + connection_uuid = connection.connection_id.connection_uuid.uuid + if self._has_media_channel: + is_media_channel = service_handler.check_media_channel(connection_uuid) + if is_media_channel: + results_deleteendpoint = service_handler.DeleteEndpoint(endpointids_to_delete, connection_uuid=connection_uuid) + errors = check_errors_deleteendpoint(endpointids_to_delete, results_deleteendpoint) + if len(errors) > 0: + MSG = 'DeleteEndpoint for OpticalConnection({:s}) from Service({:s})' + str_connection = grpc_message_to_json_string(connection) + str_service = grpc_message_to_json_string(service) + raise OperationFailedException(MSG.format(str_connection, str_service), extra_details=errors) + if is_media_channel: + self._task_executor.delete_connection(self._connection_id) + else: + results_deleteendpoint = service_handler.DeleteEndpoint(endpointids_to_delete, connection_uuid=connection_uuid) + errors = check_errors_deleteendpoint(endpointids_to_delete, results_deleteendpoint) + if len(errors) > 0: + MSG = 'DeleteEndpoint for OpticalConnection({:s}) from Service({:s})' + str_connection = grpc_message_to_json_string(connection) + str_service = grpc_message_to_json_string(service) + raise OperationFailedException(MSG.format(str_connection, str_service), extra_details=errors) + self._task_executor.delete_connection(self._connection_id) diff --git a/src/service/service/task_scheduler/tasks/Task_OpticalServiceConfigDelete.py b/src/service/service/task_scheduler/tasks/Task_OpticalServiceConfigDelete.py new file mode 100644 index 0000000000000000000000000000000000000000..4a21d246e8dfcce4f828553df68169a2bbada160 --- /dev/null +++ b/src/service/service/task_scheduler/tasks/Task_OpticalServiceConfigDelete.py @@ -0,0 +1,43 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from common.proto.context_pb2 import ServiceId , ConnectionId +from service.service.task_scheduler.TaskExecutor import TaskExecutor +from service.service.tools.ObjectKeys import get_service_key +from ._Task import _Task + +KEY_TEMPLATE = 'optical_service({service_id:s})_Config:delete' + +class Task_OpticalServiceConfigDelete(_Task): + def __init__( + self, task_executor : TaskExecutor, connection_id : ConnectionId, + service_id : ServiceId + ) -> None: + super().__init__(task_executor) + self._connection_id = connection_id + self._service_id = service_id + + @property + def service_id(self) -> ServiceId: return self._service_id + + @staticmethod + def build_key(service_id : ServiceId) -> str: # pylint: disable=arguments-differ + str_service_id = get_service_key(service_id) + return KEY_TEMPLATE.format(service_id=str_service_id) + + @property + def key(self) -> str: return self.build_key(self._service_id) + + def execute(self) -> None: + self._task_executor.delete_setting(self._service_id, '/settings', 'value') diff --git a/src/service/service/task_scheduler/tasks/Task_OpticalServiceDelete.py b/src/service/service/task_scheduler/tasks/Task_OpticalServiceDelete.py new file mode 100644 index 0000000000000000000000000000000000000000..536d954957ebf1f2d294b9bc435cae7ded7c7531 --- /dev/null +++ b/src/service/service/task_scheduler/tasks/Task_OpticalServiceDelete.py @@ -0,0 +1,45 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + +from common.proto.context_pb2 import ServiceId +from service.service.task_scheduler.TaskExecutor import TaskExecutor +from service.service.tools.ObjectKeys import get_service_key +from ._Task import _Task + +KEY_TEMPLATE = 'optical_service({service_id:s}):delete' + +class Task_OpticalServiceDelete(_Task): + def __init__( + self, task_executor : TaskExecutor, service_id : ServiceId, + has_media_channel : bool, has_optical_band : bool + ) -> None: + super().__init__(task_executor) + self._service_id = service_id + self._has_media_channel = has_media_channel + self._has_optical_band = has_optical_band + + @property + def service_id(self) -> ServiceId: return self._service_id + + @staticmethod + def build_key(service_id : ServiceId) -> str: # pylint: disable=arguments-differ + str_service_id = get_service_key(service_id) + return KEY_TEMPLATE.format(service_id=str_service_id) + + @property + def key(self) -> str: return self.build_key(self._service_id) + + def execute(self) -> None: + if not self._has_media_channel or not self._has_optical_band: + self._task_executor.delete_service(self._service_id) diff --git a/src/service/service/tools/OpticalTools.py b/src/service/service/tools/OpticalTools.py index ca73dce480a46369b47ce4c6baed516168b24817..f62c60ac9d256e277478f1703ed75e992961a4da 100644 --- a/src/service/service/tools/OpticalTools.py +++ b/src/service/service/tools/OpticalTools.py @@ -91,6 +91,7 @@ def get_names_from_uuids(devices: List[Device], device_uuid: str, port_uuid: str return device_name, port_name return "", "" + def get_device_name_from_uuid(devices: List[Device], device_uuid: str): device_name = "" @@ -101,6 +102,17 @@ def get_device_name_from_uuid(devices: List[Device], device_uuid: str): return "" +def refresh_opticalcontroller(topology_id : dict): + topo_id_str = topology_id["topology_uuid"]["uuid"] + cxt_id_str = topology_id["context_id"]["context_uuid"]["uuid"] + headers = {"Content-Type": "application/json"} + base_url = get_optical_controller_base_url() + urlx = "{:s}/GetTopology/{:s}/{:s}".format(base_url, cxt_id_str, topo_id_str) + res = requests.get(urlx, headers=headers) + if res is not None: + log.debug(f"DELETELIGHTPATH Response {res}") + + def add_lightpath(src, dst, bitrate, bidir, ob_band) -> str: if not TESTING: urlx = "" @@ -115,6 +127,7 @@ def add_lightpath(src, dst, bitrate, bidir, ob_band) -> str: bidir = 1 urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(bidir), str(ob_band)) r = requests.put(urlx, headers=headers) + print(f"addpathlight {r}") reply = r.text return reply else: @@ -139,17 +152,30 @@ def get_optical_band(idx) -> str: return optical_band_uni_txt -def delete_lightpath(flow_id, src, dst, bitrate) -> str: +def delete_lightpath( src, dst, bitrate, ob_id, delete_band, flow_id=None) -> str: reply = "200" + delete_band = 1 if delete_band else 0 + base_url = get_optical_controller_base_url() if not TESTING: - base_url = get_optical_controller_base_url() - urlx = "{:s}/DelLightpath/{:s}/{:s}/{:s}/{:s}".format(base_url, str(flow_id), src, dst, str(bitrate)) - + if flow_id is not None: + urlx = "{:s}/DelFlexLightpath/{}/{}/{}/{}/{}".format(base_url, src, dst, bitrate, ob_id, flow_id) + else : + urlx = "{:s}/DelOpticalBand/{}/{}/{}".format(base_url, src, dst, ob_id) headers = {"Content-Type": "application/json"} r = requests.delete(urlx, headers=headers) reply = r.text - return reply + code = r.status_code + return (reply, code) +def DelFlexLightpath (flow_id, src, dst, bitrate, o_band_id): + reply = "200" + base_url = get_optical_controller_base_url() + if not TESTING: + urlx = "{:s}/DelFlexLightpath/{}/{}/{}/{}/{}".format(base_url, flow_id, src, dst, bitrate, o_band_id) + headers = {"Content-Type": "application/json"} + r = requests.delete(urlx, headers=headers) + reply = r.text + return reply def get_lightpaths() -> str: base_url = get_optical_controller_base_url() @@ -160,14 +186,24 @@ def get_lightpaths() -> str: reply = r.text return reply - def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_band_txt) -> PathCompReply: opt_reply = PathCompReply() - topo = TopologyId(context_id=ContextId(context_uuid=Uuid(uuid=context_id)),topology_uuid=Uuid(uuid=topology_id)) + topo = TopologyId( + context_id=ContextId(context_uuid=Uuid(uuid=context_id)), + topology_uuid=Uuid(uuid=topology_id) + ) #add optical band connection first rules_ob= [] ob_id = 0 connection_ob=None + + r = reply_json + if "parent_opt_band" in r.keys(): + ob_id = r["parent_opt_band"] + if "bidir" in r.keys(): + bidir_f = r["bidir"] + else: + bidir_f = False if optical_band_txt != "": ob_json = json.loads(optical_band_txt) ob = ob_json @@ -187,9 +223,18 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b freq = ob["freq"] bx = ob["band"] - lf = int(int(freq)-int(bx/2)) + #+1 is added to avoid overlap in the WSS of MGONs + lf = int(int(freq)-int(bx/2))+1 uf = int(int(freq)+int(bx/2)) - val_ob = {"band_type": band_type, "low-freq": lf, "up-freq": uf, "frequency": freq, "band": bx, "ob_id": ob_id} + val_ob = { + "band_type" : band_type, + "low-freq" : lf, + "up-freq" : uf, + "frequency" : freq, + "band" : bx, + "ob_id" : ob_id, + "bidir" : bidir_f + } rules_ob.append(ConfigRule_Custom(resource_key="/settings-ob_{}".format(uuuid_x), resource_value=json.dumps(val_ob))) bidir_ob = ob["bidir"] for devxb in ob["flows"].keys(): @@ -234,8 +279,7 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b else: log.info("no map device port for device {} port {}".format(devxb, out_end_point_b)) log.debug("optical-band connection {}".format(connection_ob)) - r = reply_json - bidir_f = r["bidir"] + connection_f = add_connection_to_reply(opt_reply) connection_f.connection_id.connection_uuid.uuid = str(uuid.uuid4()) connection_f.service_id.CopyFrom(service.service_id) @@ -278,12 +322,13 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b end_point = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d)), endpoint_uuid=Uuid(uuid=p)) connection_f.path_hops_endpoint_ids.add().CopyFrom(end_point) else: - log.info("no map device port for device {} port {}".format(devx, out_end_point_b)) + log.info("no map device port for device {} port {}".format(devx, out_end_point_b)) + #check that list of endpoints is not empty if connection_ob is not None and len(connection_ob.path_hops_endpoint_ids) == 0: log.debug("deleting empty optical-band connection") opt_reply.connections.remove(connection_ob) - + #inizialize custom optical parameters band = r["band"] if "band" in r else None op_mode = r["op-mode"] if "op-mode" in r else None @@ -298,27 +343,26 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b band_type = "C_BAND" if ob_id != 0: - val = {"frequency": frequency, "operational-mode": op_mode, "band": band, "flow_id": flow_id, "ob_id": ob_id, "band_type": band_type,} + val = {"target-output-power": "1.0", "frequency": frequency, "operational-mode": op_mode, "band": band, "flow_id": flow_id, "ob_id": ob_id, "band_type": band_type, "bidir": bidir_f} else: - val = {"frequency": frequency, "operational-mode": op_mode, "band": band, "flow_id": flow_id, "band_type": band_type,} + val = {"target-output-power": "1.0", "frequency": frequency, "operational-mode": op_mode, "band": band, "flow_id": flow_id, "band_type": band_type, "bidir": bidir_f} custom_rule = ConfigRule_Custom(resource_key="/settings", resource_value=json.dumps(val)) rule = ConfigRule(action=ConfigActionEnum.CONFIGACTION_SET, custom=custom_rule) service.service_config.config_rules.add().CopyFrom(rule) if len(rules_ob) > 0: - for rulex in rules_ob: - rule_ob = ConfigRule(action=ConfigActionEnum.CONFIGACTION_SET, custom=rulex) - service.service_config.config_rules.add().CopyFrom(rule_ob) - + for rulex in rules_ob: + rule_ob = ConfigRule(action=ConfigActionEnum.CONFIGACTION_SET, custom=rulex) + service.service_config.config_rules.add().CopyFrom(rule_ob) + opt_reply.services.add().CopyFrom(service) - - return opt_reply + return opt_reply -def add_service_to_reply(reply : PathCompReply, service : Service)-> Service: +def add_service_to_reply(reply : PathCompReply, service : Service) -> Service: service_x = reply.services.add() service_x.CopyFrom(service) return service_x - -def add_connection_to_reply(reply : PathCompReply)-> Connection: + +def add_connection_to_reply(reply : PathCompReply) -> Connection: conn = reply.connections.add() return conn diff --git a/src/service/service/tools/object_uuid.py b/src/service/service/tools/object_uuid.py new file mode 100644 index 0000000000000000000000000000000000000000..cbcbc71b9b9d4edeb31858e3c22cd0af508210b9 --- /dev/null +++ b/src/service/service/tools/object_uuid.py @@ -0,0 +1,53 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +from common.method_wrappers.ServiceExceptions import InvalidArgumentsException +from typing import Optional, Union +from uuid import UUID, uuid5 +from common.proto.context_pb2 import DeviceId + +# Generate a UUIDv5-like from the SHA-1 of "TFS" and no namespace to be used as the NAMESPACE for all +# the context UUIDs generated. For efficiency purposes, the UUID is hardcoded; however, it is produced +# using the following code: +# from hashlib import sha1 +# from uuid import UUID +# hash = sha1(bytes('TFS', 'utf-8')).digest() +# NAMESPACE_TFS = UUID(bytes=hash[:16], version=5) +NAMESPACE_TFS = UUID('200e3a1f-2223-534f-a100-758e29c37f40') + +def get_uuid_from_string(str_uuid_or_name : Union[str, UUID], prefix_for_name : Optional[str] = None) -> str: + # if UUID given, assume it is already a valid UUID + if isinstance(str_uuid_or_name, UUID): return str_uuid_or_name + if not isinstance(str_uuid_or_name, str): + MSG = 'Parameter({:s}) cannot be used to produce a UUID' + raise Exception(MSG.format(str(repr(str_uuid_or_name)))) + try: + # try to parse as UUID + return str(UUID(str_uuid_or_name)) + except: # pylint: disable=bare-except + # produce a UUID within TFS namespace from parameter + if prefix_for_name is not None: + str_uuid_or_name = '{:s}/{:s}'.format(prefix_for_name, str_uuid_or_name) + return str(uuid5(NAMESPACE_TFS, str_uuid_or_name)) + +def opticalconfig_get_uuid(device_id: DeviceId) -> str: + device_uuid = device_id.device_uuid.uuid + if len(device_uuid) > 0: + return get_uuid_from_string(f"{device_uuid}_opticalconfig") + + raise InvalidArgumentsException([ + ('DeviceId ', device_id), + + ], extra_details=['device_id is required to produce a OpticalConfig UUID']) diff --git a/src/tests/ofc24/.gitlab-ci.yml b/src/tests/ofc24/.gitlab-ci.yml index d7bda488689abe88b8abba9a054307fcf377af46..af4e1aaa6b98beb21a85a4746f61cf9d4916dba7 100644 --- a/src/tests/ofc24/.gitlab-ci.yml +++ b/src/tests/ofc24/.gitlab-ci.yml @@ -138,6 +138,7 @@ end2end_test ofc24: - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/sliceservice -c server - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/webuiservice -c server - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/opticalcontrollerservice -c server - if docker ps -a | grep ${TEST_NAME}; then docker rm -f ${TEST_NAME}; fi diff --git a/src/tests/ofc24/_old/startExtraNetConfigAgent.sh b/src/tests/ofc24/_old/startExtraNetConfigAgent.sh index 197171d2f5e2653e9c38d51c60502984c4d0b345..706010bd11b940af276b74a8366795c6448df8b7 100755 --- a/src/tests/ofc24/_old/startExtraNetConfigAgent.sh +++ b/src/tests/ofc24/_old/startExtraNetConfigAgent.sh @@ -15,10 +15,14 @@ +docker stop na1 +docker rm na1 +docker stop na2 +docker rm na2 -screen -dmS t1 -T xterm sh -c "docker run -p 10.0.2.4:2023:2022 -v ~/tfs-ctrl/src/tests/ofc24/tempOC/files:/files --name na1 -it asgamb1/oc23bgp.img:latest bash" -screen -dmS t2 -T xterm sh -c "docker run -p 10.0.2.4:2024:2022 -v ~/tfs-ctrl/src/tests/ofc24/tempOC/files:/files --name na2 -it asgamb1/oc23bgp.img:latest bash" +screen -dmS t1 -T xterm sh -c "docker run -p 10.0.2.4:2023:2022 -v ~/tfs-ctrl/src/tests/ofc24/tempOC/files:/files --name na1 -it asgamb1/oc23bgp.img:latest sh" +screen -dmS t2 -T xterm sh -c "docker run -p 10.0.2.4:2024:2022 -v ~/tfs-ctrl/src/tests/ofc24/tempOC/files:/files --name na2 -it asgamb1/oc23bgp.img:latest sh" @@ -26,7 +30,7 @@ sleep 4 echo "starting transponder1 " if [ "$( docker container inspect -f '{{.State.Running}}' na1)" = "true" ]; then - docker exec na1 sh -c " cp /files/platform_t1.xml demoECOC21.xml ; + docker exec na1 bash -c " cp /files/platform_t1.xml demoECOC21.xml ; /confd/examples.confd/OC23/startNetconfAgent.sh;" else @@ -36,7 +40,7 @@ fi echo "starting transponder2 " if [ "$( docker container inspect -f '{{.State.Running}}' na2)" = "true" ]; then - docker exec na2 sh -c " cp /files/platform_t2.xml demoECOC21.xml; + docker exec na2 bash -c " cp /files/platform_t2.xml demoECOC21.xml; /confd/examples.confd/OC23/startNetconfAgent.sh " else diff --git a/src/tests/ofc24/descriptors/topology.json b/src/tests/ofc24/descriptors/topology.json index 85bbad55eb8608d2d2a7abad7fffab8fffdae682..f358bf94cebc5ebe51cef25dd3816622dcdb7b64 100644 --- a/src/tests/ofc24/descriptors/topology.json +++ b/src/tests/ofc24/descriptors/topology.json @@ -7,144 +7,1564 @@ ], "devices": [ { - "device_id": {"device_uuid": {"uuid": "T1"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_id": {"device_uuid": {"uuid": "T1.1"}}, "device_type": "optical-transponder", "device_drivers": [11], "device_operational_status": 1, - "device_endpoints": [ - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "T1"}}, "endpoint_uuid": {"uuid": "1"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }} - ], "device_config": {"config_rules": [ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.101"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, - "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, - "endpoints": [{"uuid": "1", "type": "optical", "sample_types": [101, 102, 201, 202]}] + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} }}} ]} }, { - "device_id": {"device_uuid": {"uuid": "T2"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_id": {"device_uuid": {"uuid": "T1.2"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_operational_status": 1, + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.101"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "T1.3"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_operational_status": 1, + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.101"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "T2.1"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_operational_status": 1, + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.102"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "T2.2"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_operational_status": 1, + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.102"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "T2.3"}}, "device_type": "optical-transponder", "device_drivers": [11], "device_operational_status": 1, - "device_endpoints": [ - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "T2"}}, "endpoint_uuid": {"uuid": "6"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }} - ], "device_config": {"config_rules": [ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.102"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, - "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, - "endpoints": [{"uuid": "6", "type": "optical", "sample_types": [101, 102, 201, 202]}] + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} }}} ]} }, { "device_id": {"device_uuid": {"uuid": "R1"}}, "device_type": "optical-roadm", "device_drivers": [11], "device_operational_status": 1, - "device_endpoints": [ - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }}, - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "3"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }}, - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "12"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }}, - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "13"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }} - ], "device_config": {"config_rules": [ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.201"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, - "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, - "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, - "endpoints": [ - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "2"}, - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "3"}, - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "12"}, - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "13"} - ]} - }}] - } + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, "type": "optical-roadm", + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} + }}} + ]} }, { "device_id": {"device_uuid": {"uuid": "R2"}}, "device_type": "optical-roadm", "device_drivers": [11], "device_operational_status": 1, - "device_endpoints": [ - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "4"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }}, - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "5"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }}, - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "14"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }}, - {"endpoint_id": { - "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "15"}, - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} - }} - ], "device_config": {"config_rules": [ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.202"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, - "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, - "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, - "endpoints": [ - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "4"}, - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "5"}, - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "14"}, - {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "15"} - ] + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, "type": "optical-roadm", + "device_params": {"name": "default"}, "manager_params": {"timeout": 120} }}} ]} } ], - "links": [ - {"link_id": {"link_uuid": {"uuid": "T1->R1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "T1"}}, "endpoint_uuid": {"uuid": "1"}}, - {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "12"}} - ]}, - {"link_id": {"link_uuid": {"uuid": "R1->T1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2"}}, - {"device_id": {"device_uuid": {"uuid": "T1"}}, "endpoint_uuid": {"uuid": "1"}} - ]}, - {"link_id": {"link_uuid": {"uuid": "R1->R2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "3"}}, - {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "14"}} - ]}, - {"link_id": {"link_uuid": {"uuid": "R2->R1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "4"}}, - {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "13"}} - ]}, - {"link_id": {"link_uuid": {"uuid": "T2->R2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "T2"}}, "endpoint_uuid": {"uuid": "6"}}, - {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "15"}} - ]}, - {"link_id": {"link_uuid": {"uuid": "R2->T2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "5"}}, - {"device_id": {"device_uuid": {"uuid": "T2"}}, "endpoint_uuid": {"uuid": "6"}} - ]} - ] + "optical_links": [ + { + "name": "T1.1-R1", + "link_id": { + "link_uuid": { + "uuid": "T1.1->R1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T1.1" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "12" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "1", + "dst_port": "12", + "local_peer_port": "1", + "remote_peer_port": "2", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "T1.2-R1", + "link_id": { + "link_uuid": { + "uuid": "T1.2->R1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T1.2" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "13" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "1", + "dst_port": "13", + "local_peer_port": "1", + "remote_peer_port": "3", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "T1.3-R1", + "link_id": { + "link_uuid": { + "uuid": "T1.3->R1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T1.3" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "14" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "1", + "dst_port": "14", + "local_peer_port": "1", + "remote_peer_port": "4", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R1-T1.1", + "link_id": { + "link_uuid": { + "uuid": "R1->T1.1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "2" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T1.1" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "2", + "dst_port": "1", + "local_peer_port": "12", + "remote_peer_port": "1", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R1-T1.2", + "link_id": { + "link_uuid": { + "uuid": "R1->T1.2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "3" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T1.2" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "3", + "dst_port": "1", + "local_peer_port": "13", + "remote_peer_port": "1", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R1-T1.3", + "link_id": { + "link_uuid": { + "uuid": "R1->T1.3" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "4" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T1.3" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "4", + "dst_port": "1", + "local_peer_port": "14", + "remote_peer_port": "1", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R1-R2", + "link_id": { + "link_uuid": { + "uuid": "R1->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "101" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "111" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "101", + "dst_port": "111", + "local_peer_port": "111", + "remote_peer_port": "101", + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R2-R1", + "link_id": { + "link_uuid": { + "uuid": "R2->R1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "101" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "111" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "101", + "dst_port": "111", + "local_peer_port": "111", + "remote_peer_port": "101", + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "T2.1-R2", + "link_id": { + "link_uuid": { + "uuid": "T2.1->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T2.1" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "12" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "6", + "dst_port": "12", + "local_peer_port": "6", + "remote_peer_port": "2", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "T2.2-R2", + "link_id": { + "link_uuid": { + "uuid": "T2.2->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T2.2" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "13" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "6", + "dst_port": "13", + "local_peer_port": "6", + "remote_peer_port": "3", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "T2.3-R2", + "link_id": { + "link_uuid": { + "uuid": "T2.3->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T2.3" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "14" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "6", + "dst_port": "14", + "local_peer_port": "6", + "remote_peer_port": "4", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R2-T2.1", + "link_id": { + "link_uuid": { + "uuid": "R2->T2.1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "2" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T2.1" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "2", + "dst_port": "6", + "local_peer_port": "12", + "remote_peer_port": "6", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R2-T2.2", + "link_id": { + "link_uuid": { + "uuid": "R1->T2.2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "3" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T2.2" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "3", + "dst_port": "6", + "local_peer_port": "13", + "remote_peer_port": "6", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + }, + { + "name": "R2-T2.3", + "link_id": { + "link_uuid": { + "uuid": "R2->T2.3" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "4" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T2.3" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + } + ], + "optical_details": { + "length": 0, + "src_port": "4", + "dst_port": "6", + "local_peer_port": "14", + "remote_peer_port": "6", + "used": false, + "c_slots": { + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, + "20": 1 + }, + "l_slots": { + "101": 1, + "102": 1, + "103": 1, + "104": 1, + "105": 1, + "106": 1, + "107": 1, + "108": 1, + "109": 1, + "110": 1, + "111": 1, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 1, + "119": 1, + "120": 1 + }, + "s_slots": { + "501": 1, + "502": 1, + "503": 1, + "504": 1, + "505": 1, + "506": 1, + "507": 1, + "508": 1, + "509": 1, + "510": 1, + "511": 1, + "512": 1, + "513": 1, + "514": 1, + "515": 1, + "516": 1, + "517": 1, + "518": 1, + "519": 1, + "520": 1 + } + } + } + ] } diff --git a/src/tests/ofc24/get_all.sh b/src/tests/ofc24/get_all.sh new file mode 100755 index 0000000000000000000000000000000000000000..ceb96a34c98823e122a65b38ccef57e9ed2f1ec0 --- /dev/null +++ b/src/tests/ofc24/get_all.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 + +~/tfs-ctrl/src/tests/ofc24/get_bands.sh > bands.json +~/tfs-ctrl/src/tests/ofc24/get_links.sh > links.json +~/tfs-ctrl/src/tests/ofc24/get_lightpath.sh > lightpath.json diff --git a/src/tests/ofc24/get_bands.sh b/src/tests/ofc24/get_bands.sh new file mode 100755 index 0000000000000000000000000000000000000000..c63461e44d8363f768fa1770b88b916e4d5689f7 --- /dev/null +++ b/src/tests/ofc24/get_bands.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 + +ip=$(sudo kubectl get all --all-namespaces | grep service/opticalcontrollerservice | awk '{print $4}') +echo $ip + +#push=$(curl -X GET "http://$ip:10060/OpticalTFS/GetTopology/admin/admin") + +links=$(curl -X GET "http://$ip:10060/OpticalTFS/GetOpticalBands") +echo $links diff --git a/src/tests/ofc24/get_lightpath.sh b/src/tests/ofc24/get_lightpath.sh new file mode 100755 index 0000000000000000000000000000000000000000..eefd46c0ed5ee1435e3b0dc5fa601d7d4a8f9243 --- /dev/null +++ b/src/tests/ofc24/get_lightpath.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 + +ip=$(sudo kubectl get all --all-namespaces | grep service/opticalcontrollerservice | awk '{print $4}') +echo $ip + +#push=$(curl -X GET "http://$ip:10060/OpticalTFS/GetTopology/admin/admin") + +links=$(curl -X GET "http://$ip:10060/OpticalTFS/GetLightpaths") +echo $links diff --git a/src/tests/ofc24/get_links.sh b/src/tests/ofc24/get_links.sh new file mode 100755 index 0000000000000000000000000000000000000000..f1146b4eac873114282a58445c3aad1b33002dd9 --- /dev/null +++ b/src/tests/ofc24/get_links.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 + +ip=$(sudo kubectl get all --all-namespaces | grep service/opticalcontrollerservice | awk '{print $4}') +echo $ip + +#push=$(curl -X GET "http://$ip:10060/OpticalTFS/GetTopology/admin/admin") + +links=$(curl -X GET "http://$ip:10060/OpticalTFS/GetLinks") +echo $links diff --git a/src/tests/ofc24/node-agents-config/platform_r1.xml b/src/tests/ofc24/node-agents-config/platform_r1.xml index b9412d1bda3e5eafc17fc6d3233d2bcc1dffec04..c8569cfec736b6d17e76030bd13d2161c588a726 100644 --- a/src/tests/ofc24/node-agents-config/platform_r1.xml +++ b/src/tests/ofc24/node-agents-config/platform_r1.xml @@ -132,5 +132,122 @@ </property> </properties> </component> - </components> -</config> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>4</name> + <config> + <name>4</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>14</name> + <config> + <name>14</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>101</name> + <config> + <name>101</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>111</name> + <config> + <name>111</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + </components> +</config> \ No newline at end of file diff --git a/src/tests/ofc24/node-agents-config/platform_r2.xml b/src/tests/ofc24/node-agents-config/platform_r2.xml index 317203483a89348c51e354a6c7973239b494f42d..608941ff47123da942df20fa8bebc42769c780e0 100644 --- a/src/tests/ofc24/node-agents-config/platform_r2.xml +++ b/src/tests/ofc24/node-agents-config/platform_r2.xml @@ -16,6 +16,122 @@ <config xmlns="http://tail-f.com/ns/config/1.0"> <components xmlns="http://openconfig.net/yang/platform"> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>2</name> + <config> + <name>2</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D1</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>12</name> + <config> + <name>12</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D1</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>3</name> + <config> + <name>3</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>13</name> + <config> + <name>13</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> <name>4</name> <config> @@ -40,7 +156,7 @@ <name>MG_ON_PORT_DEGREE</name> <config> <name>MG_ON_PORT_DEGREE</name> - <value>D1</value> + <value>D2</value> </config> </property> </properties> @@ -69,15 +185,16 @@ <name>MG_ON_PORT_DEGREE</name> <config> <name>MG_ON_PORT_DEGREE</name> - <value>D1</value> + <value>D2</value> </config> </property> </properties> </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> - <name>5</name> + <name>101</name> <config> - <name>5</name> + <name>101</name> </config> <properties> <property> @@ -104,9 +221,9 @@ </properties> </component> <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> - <name>15</name> + <name>111</name> <config> - <name>15</name> + <name>111</name> </config> <properties> <property> @@ -132,5 +249,5 @@ </property> </properties> </component> - </components> -</config> + </components> +</config> \ No newline at end of file diff --git a/src/tests/ofc24/node-agents-config/transponders_x4.xml b/src/tests/ofc24/node-agents-config/transponders_x4.xml new file mode 100644 index 0000000000000000000000000000000000000000..fb55f02abefa6c5a444d3fecaa2ca049798f9483 --- /dev/null +++ b/src/tests/ofc24/node-agents-config/transponders_x4.xml @@ -0,0 +1,1039 @@ +<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component> + <name>device</name> + <config> + <name>device</name> + </config> + <state> + <name>MellanoxSwitch</name> + <mfg-name>SSSA-CNIT</mfg-name> + <hardware-version>1.0.0</hardware-version> + <firmware-version>1.0.0</firmware-version> + <software-version>1.0.0</software-version> + <serial-no>610610</serial-no> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type> + </state> + </component> + <component> + <name>channel-1</name> + <config> + <name>channel-1</name> + </config> + <state> + <name>channel-1</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-1</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-1</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-2</name> + <config> + <name>channel-2</name> + </config> + <state> + <name>channel-2</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-2</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-2</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-3</name> + <config> + <name>channel-3</name> + </config> + <state> + <name>channel-3</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-3</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-3</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-4</name> + <config> + <name>channel-4</name> + </config> + <state> + <name>channel-4</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-4</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-4</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>transceiver-1</name> + <config> + <name>transceiver-1</name> + </config> + <state> + <name>transceiver-1</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-1</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-2</name> + <config> + <name>transceiver-2</name> + </config> + <state> + <name>transceiver-2</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-2</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-3</name> + <config> + <name>transceiver-3</name> + </config> + <state> + <name>transceiver-3</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-3</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + + <component> + <name>transceiver-4</name> + <config> + <name>transceiver-4</name> + </config> + <state> + <name>transceiver-4</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-4</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>port-1</name> + <config> + <name>port-1</name> + </config> + <state> + <name>port-1</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-1</name> + <config> + <name>channel-1</name> + </config> + <state> + <name>channel-1</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>1</value> + </config> + <state> + <name>onos-index</name> + <value>1</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-2</name> + <config> + <name>port-2</name> + </config> + <state> + <name>port-2</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-2</name> + <config> + <name>channel-2</name> + </config> + <state> + <name>channel-2</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>2</value> + </config> + <state> + <name>onos-index</name> + <value>2</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-3</name> + <config> + <name>port-3</name> + </config> + <state> + <name>port-3</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-3</name> + <config> + <name>channel-3</name> + </config> + <state> + <name>channel-3</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>3</value> + </config> + <state> + <name>onos-index</name> + <value>3</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-4</name> + <config> + <name>port-4</name> + </config> + <state> + <name>port-4</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-4</name> + <config> + <name>channel-4</name> + </config> + <state> + <name>channel-4</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>4</value> + </config> + <state> + <name>onos-index</name> + <value>4</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + </components> + <terminal-device xmlns="http://openconfig.net/yang/terminal-device"> + <logical-channels> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>1</index> + <config> + <index>1</index> + <description>Logical channel 1</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>1</index> + <description>Logical channel 1</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-1</transceiver> + </config> + <state> + <transceiver>transceiver-1</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-1</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-1</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>2</index> + <config> + <index>2</index> + <description>Logical channel 2</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>2</index> + <description>Logical channel 2</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-2</transceiver> + </config> + <state> + <transceiver>transceiver-2</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-2</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-2</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>3</index> + <config> + <index>3</index> + <description>Logical channel 3</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>3</index> + <description>Logical channel 3</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-3</transceiver> + </config> + <state> + <transceiver>transceiver-3</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-3</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-3</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>4</index> + <config> + <index>4</index> + <description>Logical channel 4</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>4</index> + <description>Logical channel 4</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-4</transceiver> + </config> + <state> + <transceiver>transceiver-4</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-4</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-4</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + </logical-channels> + <operational-modes> + <mode> + <mode-id>1</mode-id> + <state> + <mode-id>1</mode-id> + <description>FEC1</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + <mode> + <mode-id>2</mode-id> + <state> + <mode-id>2</mode-id> + <description>FEC2</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + </operational-modes> + </terminal-device> +</config> + diff --git a/src/tests/ofc24/node-agents-config/transponders_x4_2.xml b/src/tests/ofc24/node-agents-config/transponders_x4_2.xml new file mode 100644 index 0000000000000000000000000000000000000000..8d10c593b3c2166b16e8ecea383dadd69c3ac067 --- /dev/null +++ b/src/tests/ofc24/node-agents-config/transponders_x4_2.xml @@ -0,0 +1,1039 @@ +<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component> + <name>device</name> + <config> + <name>device</name> + </config> + <state> + <name>MellanoxSwitch</name> + <mfg-name>SSSA-CNIT</mfg-name> + <hardware-version>1.0.0</hardware-version> + <firmware-version>1.0.0</firmware-version> + <software-version>1.0.0</software-version> + <serial-no>610610</serial-no> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type> + </state> + </component> + <component> + <name>channel-5</name> + <config> + <name>channel-5</name> + </config> + <state> + <name>channel-5</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-5</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-5</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-6</name> + <config> + <name>channel-6</name> + </config> + <state> + <name>channel-6</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-6</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-6</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-7</name> + <config> + <name>channel-7</name> + </config> + <state> + <name>channel-7</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-7</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-7</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-8</name> + <config> + <name>channel-8</name> + </config> + <state> + <name>channel-8</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-8</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-8</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>transceiver-5</name> + <config> + <name>transceiver-5</name> + </config> + <state> + <name>transceiver-5</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-5</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-6</name> + <config> + <name>transceiver-6</name> + </config> + <state> + <name>transceiver-6</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-6</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-7</name> + <config> + <name>transceiver-7</name> + </config> + <state> + <name>transceiver-7</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-7</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + + <component> + <name>transceiver-8</name> + <config> + <name>transceiver-8</name> + </config> + <state> + <name>transceiver-8</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-8</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>port-5</name> + <config> + <name>port-5</name> + </config> + <state> + <name>port-5</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-5</name> + <config> + <name>channel-5</name> + </config> + <state> + <name>channel-5</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>5</value> + </config> + <state> + <name>onos-index</name> + <value>5</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-6</name> + <config> + <name>port-6</name> + </config> + <state> + <name>port-6</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-6</name> + <config> + <name>channel-6</name> + </config> + <state> + <name>channel-6</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>6</value> + </config> + <state> + <name>onos-index</name> + <value>6</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-7</name> + <config> + <name>port-7</name> + </config> + <state> + <name>port-7</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-7</name> + <config> + <name>channel-7</name> + </config> + <state> + <name>channel-7</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>7</value> + </config> + <state> + <name>onos-index</name> + <value>7</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-8</name> + <config> + <name>port-8</name> + </config> + <state> + <name>port-8</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-8</name> + <config> + <name>channel-8</name> + </config> + <state> + <name>channel-8</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>8</value> + </config> + <state> + <name>onos-index</name> + <value>8</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + </components> + <terminal-device xmlns="http://openconfig.net/yang/terminal-device"> + <logical-channels> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>5</index> + <config> + <index>5</index> + <description>Logical channel 5</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>5</index> + <description>Logical channel 5</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-5</transceiver> + </config> + <state> + <transceiver>transceiver-5</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-5</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-5</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>6</index> + <config> + <index>6</index> + <description>Logical channel 6</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>6</index> + <description>Logical channel 6</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-6</transceiver> + </config> + <state> + <transceiver>transceiver-6</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-6</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-6</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>7</index> + <config> + <index>7</index> + <description>Logical channel 7</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>7</index> + <description>Logical channel 7</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-7</transceiver> + </config> + <state> + <transceiver>transceiver-7</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-7</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-7</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>8</index> + <config> + <index>8</index> + <description>Logical channel 8</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>8</index> + <description>Logical channel 8</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-8</transceiver> + </config> + <state> + <transceiver>transceiver-8</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-8</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-8</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + </logical-channels> + <operational-modes> + <mode> + <mode-id>1</mode-id> + <state> + <mode-id>1</mode-id> + <description>FEC1</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + <mode> + <mode-id>2</mode-id> + <state> + <mode-id>2</mode-id> + <description>FEC2</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + </operational-modes> + </terminal-device> +</config> + diff --git a/src/tests/ofc24/r_t.sh b/src/tests/ofc24/r_t.sh new file mode 100755 index 0000000000000000000000000000000000000000..eef73563fbec2aa60e1133d0790e2821867fe997 --- /dev/null +++ b/src/tests/ofc24/r_t.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 + + +docker stop -t 1 t1 +docker stop -t 1 na3 +docker stop -t 1 t2 +docker stop -t 1 na2 + +docker rm t1 +docker rm na3 + +docker rm t2 +docker rm na2 + +screen -dmS t1 -T xterm sh -c "docker run --name t1 -p 10.0.2.4:2023:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/transponders_x4.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS t3 -T xterm sh -c "docker run --name na3 -p 10.0.2.4:2025:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r1.xml init_openconfig-platform.xml ; ./startNetconfAgent.sh'" +screen -dmS t2 -T xterm sh -c "docker run --name t2 -p 10.0.2.4:2024:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/transponders_x4_2.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS t4 -T xterm sh -c "docker run --name na2 -p 10.0.2.4:2026:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r2.xml init_openconfig-platform.xml ; ./startNetconfAgent.sh'" diff --git a/src/tests/ofc24/roadms.sh b/src/tests/ofc24/roadms.sh new file mode 100644 index 0000000000000000000000000000000000000000..032615d555fce47c94a83848a9b24f0ed7ce04ae --- /dev/null +++ b/src/tests/ofc24/roadms.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +docker stop -t 1 na3 +docker stop -t 1 na4 + +docker rm na3 +docker rm na4 + + + +screen -dmS t3 -T xterm sh -c "docker run --name na3 -p 10.0.2.4:2025:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r1.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS t4 -T xterm sh -c "docker run --name na4 -p 10.0.2.4:2026:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r2.xml demoECOC21.xml ; ./startNetconfAgent.sh'" \ No newline at end of file diff --git a/src/tests/ofc24/run_test.sh b/src/tests/ofc24/run_test.sh new file mode 100644 index 0000000000000000000000000000000000000000..b1cbe33c9c9169375b2f88fe5590347d85dd5552 --- /dev/null +++ b/src/tests/ofc24/run_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 + +docker stop na1 +docker rm na1 +screen -dmS t1 -T xterm sh -c "docker run -p 10.0.2.10:2023:2022 -v ~/tfs-ctrl/src/tests/ofc24/tempOC/files:/files --name na1 -it asgamb1/oc23bgp.img:latest" +sleep 2 +if [ "$( docker container inspect -f '{{.State.Running}}' na1)" = "true" ]; then + docker exec na1 sh -c " cp /files/platform_t1.xml demoECOC21.xml ; /confd/examples.confd/OC23/startNetconfAgent.sh; " +else + echo "your container is not running yet" +fi diff --git a/src/tests/ofc24/tempOC/files/platform_r1.xml b/src/tests/ofc24/tempOC/files/platform_r1.xml new file mode 100644 index 0000000000000000000000000000000000000000..02ea8feb47d4da5a4fce657837eb6e3fa749c545 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_r1.xml @@ -0,0 +1,237 @@ +<config xmlns="http://tail-f.com/ns/config/1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>2</name> + <config> + <name>2</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D1</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>12</name> + <config> + <name>12</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D1</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>3</name> + <config> + <name>3</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>13</name> + <config> + <name>13</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>4</name> + <config> + <name>4</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>14</name> + <config> + <name>14</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>101</name> + <config> + <name>101</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>111</name> + <config> + <name>111</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + </components> +</config> \ No newline at end of file diff --git a/src/tests/ofc24/tempOC/files/platform_r2.xml b/src/tests/ofc24/tempOC/files/platform_r2.xml new file mode 100644 index 0000000000000000000000000000000000000000..04d1d8370ffb72d74d1730094a6591115f7c7d6f --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_r2.xml @@ -0,0 +1,237 @@ +<config xmlns="http://tail-f.com/ns/config/1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>2</name> + <config> + <name>2</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D1</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>12</name> + <config> + <name>12</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D1</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>3</name> + <config> + <name>3</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>13</name> + <config> + <name>13</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>4</name> + <config> + <name>4</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>14</name> + <config> + <name>14</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>101</name> + <config> + <name>101</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>OUTPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create"> + <name>111</name> + <config> + <name>111</name> + </config> + <properties> + <property> + <name>MG_ON_PORT_TYPE</name> + <config> + <name>MG_ON_PORT_TYPE</name> + <value>MG_ON_OPTICAL_PORT_WAVEBAND</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DIRECTION</name> + <config> + <name>MG_ON_PORT_DIRECTION</name> + <value>INPUT</value> + </config> + </property> + <property> + <name>MG_ON_PORT_DEGREE</name> + <config> + <name>MG_ON_PORT_DEGREE</name> + <value>D2</value> + </config> + </property> + </properties> + </component> + </components> +</config> \ No newline at end of file diff --git a/src/tests/ofc24/tempOC/files/platform_t1.xml b/src/tests/ofc24/tempOC/files/platform_t1.xml new file mode 100644 index 0000000000000000000000000000000000000000..09f316211dcd5fce4a31de45065bddb276c5b268 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_t1.xml @@ -0,0 +1,295 @@ +<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component> + <name>device</name> + <config> + <name>device</name> + </config> + <state> + <name>MellanoxSwitch</name> + <mfg-name>SSSA-CNIT</mfg-name> + <hardware-version>1.0.0</hardware-version> + <firmware-version>1.0.0</firmware-version> + <software-version>1.0.0</software-version> + <serial-no>610610</serial-no> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type> + </state> + </component> + <component> + <name>channel-1</name> + <config> + <name>channel-1</name> + </config> + <state> + <name>channel-1</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-1</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-1</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>transceiver-1</name> + <config> + <name>transceiver-1</name> + </config> + <state> + <name>transceiver-1</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-1</associated-optical-channel> + </config> + <!--state> + <index>1</index> + <associated-optical-channel>channel-4</associated-optical-channel> + </state--> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>port-1</name> + <config> + <name>port-1</name> + </config> + <state> + <name>port-1</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-1</name> + <config> + <name>channel-1</name> + </config> + <state> + <name>channel-1</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>4</value> + </config> + <state> + <name>onos-index</name> + <value>4</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + </components> + <terminal-device xmlns="http://openconfig.net/yang/terminal-device"> + <logical-channels> + <!--Description: Optical logical link--> + <channel> + + <!--Description: Line (OTN) Port--> + <index>1</index> + <config> + <index>1</index> + <description>Logical channel 1</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>1</index> + <description>Logical channel 1</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-1</transceiver> + </config> + <state> + <transceiver>transceiver-1</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-1</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-1</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + </logical-channels> + <operational-modes> + <mode> + <mode-id>1</mode-id> + <state> + <mode-id>1</mode-id> + <description>FEC1</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + <mode> + <mode-id>2</mode-id> + <state> + <mode-id>2</mode-id> + <description>FEC2</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + </operational-modes> + </terminal-device> +</config> diff --git a/src/tests/ofc24/tempOC/files/platform_t2.xml b/src/tests/ofc24/tempOC/files/platform_t2.xml new file mode 100644 index 0000000000000000000000000000000000000000..03c643c91f176b531ec25bda6fbb36c8bdb1c099 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_t2.xml @@ -0,0 +1,295 @@ +<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component> + <name>device</name> + <config> + <name>device</name> + </config> + <state> + <name>MellanoxSwitch</name> + <mfg-name>SSSA-CNIT</mfg-name> + <hardware-version>1.0.0</hardware-version> + <firmware-version>1.0.0</firmware-version> + <software-version>1.0.0</software-version> + <serial-no>610610</serial-no> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type> + </state> + </component> + <component> + <name>channel-6</name> + <config> + <name>channel-6</name> + </config> + <state> + <name>channel-6</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-6</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-6</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>transceiver-6</name> + <config> + <name>transceiver-6</name> + </config> + <state> + <name>transceiver-6</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-6</associated-optical-channel> + </config> + <!--state> + <index>1</index> + <associated-optical-channel>channel-4</associated-optical-channel> + </state--> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>port-6</name> + <config> + <name>port-6</name> + </config> + <state> + <name>port-6</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-6</name> + <config> + <name>channel-6</name> + </config> + <state> + <name>channel-6</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>4</value> + </config> + <state> + <name>onos-index</name> + <value>4</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + </components> + <terminal-device xmlns="http://openconfig.net/yang/terminal-device"> + <logical-channels> + <!--Description: Optical logical link--> + <channel> + + <!--Description: Line (OTN) Port--> + <index>4</index> + <config> + <index>4</index> + <description>Logical channel 4</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>4</index> + <description>Logical channel 4</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-6</transceiver> + </config> + <state> + <transceiver>transceiver-6</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-6</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-6</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + </logical-channels> + <operational-modes> + <mode> + <mode-id>1</mode-id> + <state> + <mode-id>1</mode-id> + <description>FEC1</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + <mode> + <mode-id>2</mode-id> + <state> + <mode-id>2</mode-id> + <description>FEC2</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + </operational-modes> + </terminal-device> +</config> diff --git a/src/tests/ofc24/tempOC/files/startNetconfAgent.sh b/src/tests/ofc24/tempOC/files/startNetconfAgent.sh new file mode 100644 index 0000000000000000000000000000000000000000..35c95b6574bca3e0b620c356ea0f393137ec1b90 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/startNetconfAgent.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 + +make clean +make all +#make init +cp init_openconfig-platform.xml confd-cdb/ +#cp init_flex-scale-mg-on.xml confd-cdb/ +make start2 diff --git a/src/tests/ofc24/tempOC/files/transponders_x4.xml b/src/tests/ofc24/tempOC/files/transponders_x4.xml new file mode 100644 index 0000000000000000000000000000000000000000..fb55f02abefa6c5a444d3fecaa2ca049798f9483 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/transponders_x4.xml @@ -0,0 +1,1039 @@ +<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component> + <name>device</name> + <config> + <name>device</name> + </config> + <state> + <name>MellanoxSwitch</name> + <mfg-name>SSSA-CNIT</mfg-name> + <hardware-version>1.0.0</hardware-version> + <firmware-version>1.0.0</firmware-version> + <software-version>1.0.0</software-version> + <serial-no>610610</serial-no> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type> + </state> + </component> + <component> + <name>channel-1</name> + <config> + <name>channel-1</name> + </config> + <state> + <name>channel-1</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-1</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-1</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-2</name> + <config> + <name>channel-2</name> + </config> + <state> + <name>channel-2</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-2</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-2</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-3</name> + <config> + <name>channel-3</name> + </config> + <state> + <name>channel-3</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-3</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-3</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-4</name> + <config> + <name>channel-4</name> + </config> + <state> + <name>channel-4</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-4</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-4</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>transceiver-1</name> + <config> + <name>transceiver-1</name> + </config> + <state> + <name>transceiver-1</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-1</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-2</name> + <config> + <name>transceiver-2</name> + </config> + <state> + <name>transceiver-2</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-2</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-3</name> + <config> + <name>transceiver-3</name> + </config> + <state> + <name>transceiver-3</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-3</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + + <component> + <name>transceiver-4</name> + <config> + <name>transceiver-4</name> + </config> + <state> + <name>transceiver-4</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-4</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>port-1</name> + <config> + <name>port-1</name> + </config> + <state> + <name>port-1</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-1</name> + <config> + <name>channel-1</name> + </config> + <state> + <name>channel-1</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>1</value> + </config> + <state> + <name>onos-index</name> + <value>1</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-2</name> + <config> + <name>port-2</name> + </config> + <state> + <name>port-2</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-2</name> + <config> + <name>channel-2</name> + </config> + <state> + <name>channel-2</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>2</value> + </config> + <state> + <name>onos-index</name> + <value>2</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-3</name> + <config> + <name>port-3</name> + </config> + <state> + <name>port-3</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-3</name> + <config> + <name>channel-3</name> + </config> + <state> + <name>channel-3</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>3</value> + </config> + <state> + <name>onos-index</name> + <value>3</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-4</name> + <config> + <name>port-4</name> + </config> + <state> + <name>port-4</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-4</name> + <config> + <name>channel-4</name> + </config> + <state> + <name>channel-4</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>4</value> + </config> + <state> + <name>onos-index</name> + <value>4</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + </components> + <terminal-device xmlns="http://openconfig.net/yang/terminal-device"> + <logical-channels> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>1</index> + <config> + <index>1</index> + <description>Logical channel 1</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>1</index> + <description>Logical channel 1</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-1</transceiver> + </config> + <state> + <transceiver>transceiver-1</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-1</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-1</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>2</index> + <config> + <index>2</index> + <description>Logical channel 2</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>2</index> + <description>Logical channel 2</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-2</transceiver> + </config> + <state> + <transceiver>transceiver-2</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-2</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-2</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>3</index> + <config> + <index>3</index> + <description>Logical channel 3</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>3</index> + <description>Logical channel 3</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-3</transceiver> + </config> + <state> + <transceiver>transceiver-3</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-3</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-3</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>4</index> + <config> + <index>4</index> + <description>Logical channel 4</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>4</index> + <description>Logical channel 4</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-4</transceiver> + </config> + <state> + <transceiver>transceiver-4</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-4</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-4</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + </logical-channels> + <operational-modes> + <mode> + <mode-id>1</mode-id> + <state> + <mode-id>1</mode-id> + <description>FEC1</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + <mode> + <mode-id>2</mode-id> + <state> + <mode-id>2</mode-id> + <description>FEC2</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + </operational-modes> + </terminal-device> +</config> + diff --git a/src/tests/ofc24/tempOC/files/transponders_x4_2.xml b/src/tests/ofc24/tempOC/files/transponders_x4_2.xml new file mode 100644 index 0000000000000000000000000000000000000000..8d10c593b3c2166b16e8ecea383dadd69c3ac067 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/transponders_x4_2.xml @@ -0,0 +1,1039 @@ +<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <components xmlns="http://openconfig.net/yang/platform"> + <component> + <name>device</name> + <config> + <name>device</name> + </config> + <state> + <name>MellanoxSwitch</name> + <mfg-name>SSSA-CNIT</mfg-name> + <hardware-version>1.0.0</hardware-version> + <firmware-version>1.0.0</firmware-version> + <software-version>1.0.0</software-version> + <serial-no>610610</serial-no> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type> + </state> + </component> + <component> + <name>channel-5</name> + <config> + <name>channel-5</name> + </config> + <state> + <name>channel-5</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-5</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-5</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-6</name> + <config> + <name>channel-6</name> + </config> + <state> + <name>channel-6</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-6</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-6</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-7</name> + <config> + <name>channel-7</name> + </config> + <state> + <name>channel-7</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-7</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-7</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>channel-8</name> + <config> + <name>channel-8</name> + </config> + <state> + <name>channel-8</name> + <type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type> + </state> + <optical-channel xmlns="http://openconfig.net/yang/terminal-device"> + <config> + <frequency>191600000</frequency> + <target-output-power>100</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-8</line-port> + </config> + <state> + <frequency>191600000</frequency> + <target-output-power>0</target-output-power> + <operational-mode>0</operational-mode> + <line-port>transceiver-8</line-port> + <group-id>1</group-id> + <output-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </output-power> + <input-power> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </input-power> + <laser-bias-current> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </laser-bias-current> + <chromatic-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </chromatic-dispersion> + <polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </polarization-mode-dispersion> + <second-order-polarization-mode-dispersion> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + </second-order-polarization-mode-dispersion> + <polarization-dependent-loss> + <instant>0</instant> + <avg>0</avg> + <min>0</min> + <max>0</max> + <interval>0</interval> + </polarization-dependent-loss> + </state> + </optical-channel> + </component> + <component> + <name>transceiver-5</name> + <config> + <name>transceiver-5</name> + </config> + <state> + <name>transceiver-5</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-5</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-6</name> + <config> + <name>transceiver-6</name> + </config> + <state> + <name>transceiver-6</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-6</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>transceiver-7</name> + <config> + <name>transceiver-7</name> + </config> + <state> + <name>transceiver-7</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-7</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + + <component> + <name>transceiver-8</name> + <config> + <name>transceiver-8</name> + </config> + <state> + <name>transceiver-8</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type> + </state> + <transceiver xmlns="http://openconfig.net/yang/platform/transceiver"> + <config> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + </config> + <state> + <enabled>true</enabled> + <form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf> + <ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf> + <fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode> + <module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type> + <vendor>Cisco</vendor> + <vendor-part>400zr-QSFP-DD</vendor-part> + <vendor-rev>01</vendor-rev> + <serial-no>1567321</serial-no> + </state> + <physical-channels> + <channel> + <index>1</index> + <config> + <index>1</index> + <associated-optical-channel>channel-8</associated-optical-channel> + </config> + </channel> + </physical-channels> + </transceiver> + </component> + <component> + <name>port-5</name> + <config> + <name>port-5</name> + </config> + <state> + <name>port-5</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-5</name> + <config> + <name>channel-5</name> + </config> + <state> + <name>channel-5</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>5</value> + </config> + <state> + <name>onos-index</name> + <value>5</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-6</name> + <config> + <name>port-6</name> + </config> + <state> + <name>port-6</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-6</name> + <config> + <name>channel-6</name> + </config> + <state> + <name>channel-6</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>6</value> + </config> + <state> + <name>onos-index</name> + <value>6</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-7</name> + <config> + <name>port-7</name> + </config> + <state> + <name>port-7</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-7</name> + <config> + <name>channel-7</name> + </config> + <state> + <name>channel-7</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>7</value> + </config> + <state> + <name>onos-index</name> + <value>7</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + <component> + <name>port-8</name> + <config> + <name>port-8</name> + </config> + <state> + <name>port-8</name> + <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type> + </state> + <subcomponents> + <subcomponent> + <name>channel-8</name> + <config> + <name>channel-8</name> + </config> + <state> + <name>channel-8</name> + </state> + </subcomponent> + </subcomponents> + <properties> + <property> + <name>onos-index</name> + <config> + <name>onos-index</name> + <value>8</value> + </config> + <state> + <name>onos-index</name> + <value>8</value> + </state> + </property> + <property> + <name>odtn-port-type</name> + <config> + <name>odtn-port-type</name> + <value>line</value> + </config> + <state> + <name>odtn-port-type</name> + <value>line</value> + </state> + </property> + </properties> + </component> + </components> + <terminal-device xmlns="http://openconfig.net/yang/terminal-device"> + <logical-channels> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>5</index> + <config> + <index>5</index> + <description>Logical channel 5</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>5</index> + <description>Logical channel 5</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-5</transceiver> + </config> + <state> + <transceiver>transceiver-5</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-5</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-5</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>6</index> + <config> + <index>6</index> + <description>Logical channel 6</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>6</index> + <description>Logical channel 6</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-6</transceiver> + </config> + <state> + <transceiver>transceiver-6</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-6</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-6</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>7</index> + <config> + <index>7</index> + <description>Logical channel 7</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>7</index> + <description>Logical channel 7</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-7</transceiver> + </config> + <state> + <transceiver>transceiver-7</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-7</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-7</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + <!--Description: Optical logical link--> + <channel> + <!--Description: Line (OTN) Port--> + <index>8</index> + <config> + <index>8</index> + <description>Logical channel 8</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + </config> + <state> + <index>8</index> + <description>Logical channel 8</description> + <admin-state>DISABLED</admin-state> + <logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type> + <loopback-mode>NONE</loopback-mode> + <link-state>UP</link-state> + </state> + <ingress> + <config> + <transceiver>transceiver-8</transceiver> + </config> + <state> + <transceiver>transceiver-8</transceiver> + </state> + </ingress> + <otn> + <config> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + </config> + <state> + <tti-msg-expected>test1</tti-msg-expected> + <tti-msg-transmit>test1</tti-msg-transmit> + <tti-msg-auto>0</tti-msg-auto> + <tti-msg-recv>0</tti-msg-recv> + <rdi-msg>0</rdi-msg> + <errored-seconds>0</errored-seconds> + <severely-errored-seconds>0</severely-errored-seconds> + <unavailable-seconds>0</unavailable-seconds> + <code-violations>0</code-violations> + <fec-uncorrectable-words>0</fec-uncorrectable-words> + <fec-corrected-bytes>0</fec-corrected-bytes> + <fec-corrected-bits>0</fec-corrected-bits> + <background-block-errors>0</background-block-errors> + <pre-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </pre-fec-ber> + <post-fec-ber> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + </post-fec-ber> + <q-value> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </q-value> + <esnr> + <instant>0.0</instant> + <avg>0.0</avg> + <min>0.0</min> + <max>0.0</max> + <interval>0</interval> + </esnr> + </state> + </otn> + <logical-channel-assignments> + <assignment> + <index>1</index> + <config> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-8</optical-channel> + </config> + <state> + <index>1</index> + <description>Optical channel assigned 100</description> + <allocation>100</allocation> + <assignment-type>OPTICAL_CHANNEL</assignment-type> + <optical-channel>channel-8</optical-channel> + </state> + </assignment> + </logical-channel-assignments> + </channel> + </logical-channels> + <operational-modes> + <mode> + <mode-id>1</mode-id> + <state> + <mode-id>1</mode-id> + <description>FEC1</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + <mode> + <mode-id>2</mode-id> + <state> + <mode-id>2</mode-id> + <description>FEC2</description> + <vendor-id>Ericsson</vendor-id> + </state> + </mode> + </operational-modes> + </terminal-device> +</config> + diff --git a/src/tests/ofc24/transponders.sh b/src/tests/ofc24/transponders.sh new file mode 100644 index 0000000000000000000000000000000000000000..17fe4a5e7ebcbc653e1f43291addbc15670c03f6 --- /dev/null +++ b/src/tests/ofc24/transponders.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +docker stop -t 1 tna1 +docker stop -t 1 tna2 + +docker rm tna1 +docker rm tna2 + + + +screen -dmS tt1 -T xterm sh -c "docker run --name tna1 -p 10.0.2.4:2023:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/platform_t1.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS tt2 -T xterm sh -c "docker run --name tna2 -p 10.0.2.4:2024:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/platform_t2.xml demoECOC21.xml ; ./startNetconfAgent.sh'" diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py index f137c247e1c4d2f4be5707e72e4140ab75f8e886..4c39e3c033717d1e6e48120a5ebf27fd327ecac9 100644 --- a/src/webui/service/__init__.py +++ b/src/webui/service/__init__.py @@ -21,7 +21,8 @@ from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from qkd_app.client.QKDAppClient import QKDAppClient from common.Settings import ( - is_deployed_bgpls, is_deployed_load_gen, is_deployed_policy, is_deployed_qkd_app, is_deployed_slice + is_deployed_bgpls, is_deployed_load_gen, is_deployed_optical, + is_deployed_policy, is_deployed_qkd_app, is_deployed_slice ) def get_working_context() -> str: @@ -86,34 +87,43 @@ def create_app(use_config=None, web_app_root=None): app.register_blueprint(healthz, url_prefix='/healthz') - from webui.service.js.routes import js # pylint: disable=import-outside-toplevel + from webui.service.js.routes import js # pylint: disable=import-outside-toplevel app.register_blueprint(js) - from webui.service.main.routes import main # pylint: disable=import-outside-toplevel + from webui.service.main.routes import main # pylint: disable=import-outside-toplevel app.register_blueprint(main) - from webui.service.load_gen.routes import load_gen # pylint: disable=import-outside-toplevel + from webui.service.load_gen.routes import load_gen # pylint: disable=import-outside-toplevel app.register_blueprint(load_gen) - from webui.service.service.routes import service # pylint: disable=import-outside-toplevel + from webui.service.base_optical.route import base_optical # pylint: disable=import-outside-toplevel + app.register_blueprint(base_optical) + + from webui.service.opticalconfig.routes import opticalconfig # pylint: disable=import-outside-toplevel + app.register_blueprint(opticalconfig) + + from webui.service.optical_link.routes import optical_link # pylint: disable=import-outside-toplevel + app.register_blueprint(optical_link) + + from webui.service.service.routes import service # pylint: disable=import-outside-toplevel app.register_blueprint(service) - from webui.service.slice.routes import slice # pylint: disable=import-outside-toplevel,redefined-builtin + from webui.service.slice.routes import slice # pylint: disable=import-outside-toplevel,redefined-builtin app.register_blueprint(slice) - from webui.service.device.routes import device # pylint: disable=import-outside-toplevel + from webui.service.device.routes import device # pylint: disable=import-outside-toplevel app.register_blueprint(device) - from webui.service.bgpls.routes import bgpls # pylint: disable=import-outside-toplevel + from webui.service.bgpls.routes import bgpls # pylint: disable=import-outside-toplevel app.register_blueprint(bgpls) - from webui.service.link.routes import link # pylint: disable=import-outside-toplevel + from webui.service.link.routes import link # pylint: disable=import-outside-toplevel app.register_blueprint(link) - from webui.service.qkd_app.routes import qkd_app # pylint: disable=import-outside-toplevel + from webui.service.qkd_app.routes import qkd_app # pylint: disable=import-outside-toplevel app.register_blueprint(qkd_app) - from webui.service.policy_rule.routes import policy_rule # pylint: disable=import-outside-toplevel + from webui.service.policy_rule.routes import policy_rule # pylint: disable=import-outside-toplevel app.register_blueprint(policy_rule) app.jinja_env.globals.update({ # pylint: disable=no-member @@ -126,6 +136,7 @@ def create_app(use_config=None, web_app_root=None): 'is_deployed_bgpls' : is_deployed_bgpls, 'is_deployed_load_gen': is_deployed_load_gen, + 'is_deployed_optical' : is_deployed_optical, 'is_deployed_policy' : is_deployed_policy, 'is_deployed_qkd_app' : is_deployed_qkd_app, 'is_deployed_slice' : is_deployed_slice, diff --git a/src/webui/service/base_optical/__init__.py b/src/webui/service/base_optical/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3ee6f7071f145e06c3aeaefc09a43ccd88e619e3 --- /dev/null +++ b/src/webui/service/base_optical/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + diff --git a/src/webui/service/base_optical/route.py b/src/webui/service/base_optical/route.py new file mode 100644 index 0000000000000000000000000000000000000000..84fb8a97572e9e6f9f2056cae3ad9087a7390720 --- /dev/null +++ b/src/webui/service/base_optical/route.py @@ -0,0 +1,33 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +from flask import render_template, Blueprint +#from common.proto.context_pb2 import Empty, OpticalConfigList +#from context.client.ContextClient import ContextClient +#from device.client.DeviceClient import DeviceClient + +base_optical = Blueprint('base_optical', __name__, url_prefix='/base_optical') +#device_client = DeviceClient() +#context_client = ContextClient() + +@base_optical.get('/') +def home(): + # context_client.connect() + # opticalConfig_list:OpticalConfigList = context_client.GetOpticalConfig(Empty()) + # context_client.close() + # device_client.connect() + # device_client.GetDeviceConfiguration(opticalConfig_list) + # device_client.close() + return render_template("base_optical/home.html") diff --git a/src/webui/service/main/routes.py b/src/webui/service/main/routes.py index 52944a31c439472055d65e9e75249465dcbca7f7..97c97331d415b8c2d059f5bb65236ba6563d48c3 100644 --- a/src/webui/service/main/routes.py +++ b/src/webui/service/main/routes.py @@ -153,11 +153,24 @@ def topology(): 'source': link.link_endpoint_ids[0].device_id.device_uuid.uuid, 'target': link.link_endpoint_ids[1].device_id.device_uuid.uuid, }) - - return jsonify({'devices': devices, 'links': links}) + + optical_links = [] + for link in response.optical_links: + if len(link.link_endpoint_ids) != 2: + str_link = grpc_message_to_json_string(link) + LOGGER.warning('Unexpected link with len(endpoints) != 2: {:s}'.format(str_link)) + continue + optical_links.append({ + 'id': link.link_id.link_uuid.uuid, + 'name': link.name, + 'source': link.link_endpoint_ids[0].device_id.device_uuid.uuid, + 'target': link.link_endpoint_ids[1].device_id.device_uuid.uuid, + }) + + return jsonify({'devices': devices, 'links': links, 'optical_links': optical_links}) except: # pylint: disable=bare-except LOGGER.exception('Error retrieving topology') - return jsonify({'devices': [], 'links': []}) + return jsonify({'devices': [], 'links': [], 'optical_links': []}) finally: context_client.close() diff --git a/src/webui/service/optical_link/__init__.py b/src/webui/service/optical_link/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7c7568fdb6e3b1446aa9412ad32a0a5948ba949b --- /dev/null +++ b/src/webui/service/optical_link/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + diff --git a/src/webui/service/optical_link/routes.py b/src/webui/service/optical_link/routes.py new file mode 100644 index 0000000000000000000000000000000000000000..bc4ed8c6a14d31512398341984029f07fc2bcc6c --- /dev/null +++ b/src/webui/service/optical_link/routes.py @@ -0,0 +1,108 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +from flask import current_app, render_template, Blueprint, flash, session, redirect, url_for +from common.proto.context_pb2 import Empty, OpticalLink, LinkId, OpticalLinkList +from common.tools.context_queries.EndPoint import get_endpoint_names +from common.tools.context_queries.Topology import get_topology +from context.client.ContextClient import ContextClient + +optical_link = Blueprint('optical_link', __name__, url_prefix='/optical_link') +context_client = ContextClient() + +@optical_link.get('/') +def home(): + if 'context_uuid' not in session or 'topology_uuid' not in session: + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) + + context_uuid = session['context_uuid'] + topology_uuid = session['topology_uuid'] + + links, endpoint_ids = list(), list() + device_names, endpoints_data = dict(), dict() + + context_client.connect() + grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) + if grpc_topology is None: + flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') + else: + grpc_links : OpticalLinkList = context_client.GetOpticalLinkList(Empty()) + for link_ in grpc_links.optical_links: + links.append(link_) + endpoint_ids.extend(link_.link_endpoint_ids) + device_names, endpoints_data = get_endpoint_names(context_client, endpoint_ids) + context_client.close() + + return render_template( + 'optical_link/home.html', links=links, device_names=device_names, + endpoints_data=endpoints_data + ) + + +@optical_link.route('detail/<path:link_uuid>', methods=('GET', 'POST')) +def detail(link_uuid: str): + context_client.connect() + # pylint: disable=no-member + link_id = LinkId() + link_id.link_uuid.uuid = link_uuid + link_obj = context_client.GetOpticalLink(link_id) + c_slots=s_slots=l_slots=None + if link_obj is None: + flash('Optical Link({:s}) not found'.format(str(link_uuid)), 'danger') + link_obj = OpticalLink() + device_names, endpoints_data = dict(), dict() + else: + device_names, endpoints_data = get_endpoint_names(context_client, link_obj.link_endpoint_ids) + c_slots = link_obj.optical_details.c_slots + l_slots = link_obj.optical_details.l_slots + s_slots = link_obj.optical_details.s_slots + + context_client.close() + + return render_template( + 'optical_link/detail.html', link=link_obj, device_names=device_names, + endpoints_data=endpoints_data, c_slots=c_slots, l_slots=l_slots, s_slots=s_slots + ) + + +@optical_link.get('<path:link_uuid>/delete') +def delete(link_uuid): + try: + request = LinkId() + request.link_uuid.uuid = link_uuid # pylint: disable=no-member + context_client.connect() + context_client.DeleteOpticalLink(request) + context_client.close() + + flash(f'Optical Link "{link_uuid}" deleted successfully!', 'success') + except Exception as e: # pylint: disable=broad-except + flash(f'Problem deleting link "{link_uuid}": {e.details()}', 'danger') + current_app.logger.exception(e) + return redirect(url_for('optical_link.home')) + + +@optical_link.get("delete_all") +def delete_all(): + try: + context_client.connect() + optical_link_list : OpticalLinkList = context_client.GetOpticalLinkList(Empty()) + for optical_link in optical_link_list.optical_links: + context_client.DeleteOpticalLink(optical_link.link_id) + context_client.close() + flash(f"All Optical Link Deleted Successfully",'success') + except Exception as e: + flash(f"Problem in delete all optical link => {e}",'danger') + return redirect(url_for('optical_link.home')) diff --git a/src/webui/service/opticalconfig/__init__.py b/src/webui/service/opticalconfig/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3ee6f7071f145e06c3aeaefc09a43ccd88e619e3 --- /dev/null +++ b/src/webui/service/opticalconfig/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + diff --git a/src/webui/service/opticalconfig/forms.py b/src/webui/service/opticalconfig/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..e9cb283eb00e07fa6ad10e78c377d921ac4c506d --- /dev/null +++ b/src/webui/service/opticalconfig/forms.py @@ -0,0 +1,41 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + + +from flask_wtf import FlaskForm +from wtforms import StringField, SelectField, SubmitField + +class UpdateDeviceForm(FlaskForm): + power = StringField('Power') + frequency = StringField("Frequency") + operational_mode = StringField("Operational Mode") + line_port = SelectField("Line Port") + submit = SubmitField('Update') + +class AddTrancseiver(FlaskForm): + transceiver = StringField("Transceiver") + submit = SubmitField('Add') + +class UpdateInterfaceForm(FlaskForm): + ip = StringField("IP Address") + prefix_length = StringField("Prefix Length") + +DEVICE_STATUS = [ + ('', 'Select...'), + ('DISABLED', 'DISABLED'), + ('ENABLED', 'ENABLED') +] + +class UpdateStatusForm(FlaskForm): + status = SelectField("Device Status", choices=DEVICE_STATUS) diff --git a/src/webui/service/opticalconfig/routes.py b/src/webui/service/opticalconfig/routes.py new file mode 100644 index 0000000000000000000000000000000000000000..79a487a4e80d96d3f6a6bab1e813202e6679ee66 --- /dev/null +++ b/src/webui/service/opticalconfig/routes.py @@ -0,0 +1,329 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 json, logging +from flask import ( + request, redirect, render_template, Blueprint, flash, session, url_for, + current_app, make_response +) +from common.proto.context_pb2 import ( + Empty, OpticalConfig, OpticalConfigId, OpticalConfigList +) +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from service.client.ServiceClient import ServiceClient +from slice.client.SliceClient import SliceClient +from .forms import UpdateDeviceForm, AddTrancseiver, UpdateStatusForm +from common.tools.context_queries.OpticalConfig import opticalconfig_get_uuid + + +opticalconfig = Blueprint('opticalconfig', __name__,url_prefix="/opticalconfig") + +context_client = ContextClient() +device_client = DeviceClient() +service_client = ServiceClient() +slice_client = SliceClient() + +LOGGER = logging.getLogger(__name__) + +DESCRIPTOR_LOADER_NUM_WORKERS = 10 + +@opticalconfig.get("/") +def home() : + list_config = [] + channels_num = 0 + if 'context_uuid' not in session or 'topology_uuid' not in session: + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) + context_uuid = session['context_uuid'] + topology_uuid = session['topology_uuid'] + + context_client.connect() + opticalConfig_list : OpticalConfigList = context_client.GetOpticalConfig(Empty()) + for configs in opticalConfig_list.opticalconfigs: + value = json.loads(configs.config) if type(configs.config)==str else configs.config + config_type = value["type"] + if 'channels' in value: + channels_num = len(value['channels']) + value["channels_number"] = channels_num + # value['operationalMode']=value['operational-mode'] + # value['targetOutputPower']=value['target-output-power'] + value['opticalconfig_id']=configs.opticalconfig_id + # value['line_port']=value["line-port"] + list_config.append(value) + + context_client.close() + return render_template('opticalconfig/home.html', config=list_config) + +@opticalconfig.route('<path:config_uuid>/detail',methods=['GET']) +def show_details(config_uuid): + opticalconfigId = OpticalConfigId() + opticalconfigId.opticalconfig_uuid = config_uuid + device_details = [] + + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + if (response and response.opticalconfig_id.opticalconfig_uuid !=''): + opticalConfig = OpticalConfig() + opticalConfig.CopyFrom(response) + + device_name = "" + config = json.loads(opticalConfig.config) + if "device_name" in config: + device_name = config["device_name"] + + config_type = config["type"] + if config_type == 'optical-transponder': + if 'channels' in config: + for channel in config['channels'] : + new_config = { + "name" : channel['name'], + 'operationalMode' : channel['operational-mode'] if 'operational-mode' in channel else '', + 'targetOutputPower': channel['target-output-power'] if 'target-output-power' in channel else '', + "frequency" : channel['frequency'] if 'frequency' in channel else '', + 'line_port' : channel["line-port"] if 'line-port' in channel else '', + "status" : channel['status'] if 'status' in channel else "", + } + device_details.append(new_config) + + if config_type == 'optical-roadm': + if 'channels' in config: + for channel in config['channels'] : + new_config = { + "band_name" : channel['band_name'] if 'band_name' in channel else None, + 'type' : channel['type'] if 'type' in channel else '', + 'src_port' : channel['src_port'] if 'src_port' in channel else '', + 'dest_port' : channel['dest_port'] if 'dest_port' in channel else '', + "lower_frequency" : channel['lower_frequency'] if 'lower_frequency' in channel else '', + "upper_frequency" : channel['upper_frequency'] if 'upper_frequency' in channel else '', + "status" : channel['status'] if 'status' in channel else "", + 'optical_band_parent' : channel['optical_band_parent'] if 'optical_band_parent' in channel else '', + 'channel_index' : channel['channel_index'] if 'channel_index' in channel else '', + } + device_details.append(new_config) + + return render_template( + 'opticalconfig/details.html', device=device_details, config_id=config_uuid, + device_name=device_name, type=config_type + ) + + +@opticalconfig.route('<path:opticalconfig_uuid>/delete', methods=['GET']) +def delete_opitcalconfig (opticalconfig_uuid) : + try : + opticalconfigId = OpticalConfigId() + opticalconfigId.opticalconfig_uuid = opticalconfig_uuid + context_client.connect() + context_client.DeleteOpticalConfig(opticalconfigId) + context_client.close() + flash(f'OpticalConfig "{opticalconfig_uuid}" deleted successfully!', 'success') + except Exception as e: # pylint: disable=broad-except + flash(f'Problem deleting optical config {opticalconfig_uuid}', 'danger') + current_app.logger.exception(e) + return redirect(url_for('opticalconfig.home')) + + +@opticalconfig.route('/update_opticalconfig', methods=['POST']) +def update_externally(): + if (request.method == 'POST'): + data = request.get_json() + devices = data.get('devices') + + myResponse = [] + status_code = '' + for device in devices : + port = device.get("port") + channel_name = f"channel-{port}" + device_name = device.get("device_name") + + if device_name: + opticalconfig_uuid = opticalconfig_get_uuid(device_name=device_name) + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid = opticalconfig_uuid + context_client.connect() + opticalconfig = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + + if opticalconfig and opticalconfig.opticalconfig_id.opticalconfig_uuid != '' : + new_opticalconfig = OpticalConfig() + new_opticalconfig.CopyFrom(opticalconfig) + config = json.loads(opticalconfig.config) + channels = config['channels'] + target_channel = next((item for item in channels if item["name"]['index'] == channel_name) , None) + target_power = device.get( "target-output-power") + freq = device.get("frequency") + mode = device.get("operational-mode") + status = device.get("status","ENABLED") + + if target_channel: + if target_power is not None : + target_channel["target-output-power"] =str(target_power) + if freq is not None : + target_channel["frequency"] = freq + if mode is not None : + target_channel["operational-mode"] = mode + if status is not None : + target_channel["status"] = "ENABLED" + #del target_channel['name'] + config["new_config"]=target_channel + config["new_config"]["channel_name"]=channel_name + config["flow"]=[(port,'0')] + opticalconfig.config =json.dumps(config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticalconfig) + device_client.close() + + myResponse.append(f"device {device_name} port {port} is updated successfully") + status_code = 200 + except Exception as e: # pylint: disable=broad-except + myResponse.append(f"Problem updating the device. {e}") + status_code = 500 + break + else : + myResponse.append(f"requested channel {channel_name} is not existed") + status_code = 400 + break + else : + myResponse.append(f"requested device {device_name} is not existed") + status_code = 400 + break + + response=make_response(f'{myResponse}') + response.status_code=status_code + return response + + #return redirect(url_for('opticalconfig.show_details',config_uuid=opticalconfig_uuid)) + #return redirect(url_for('opticalconfig.home')) + +@opticalconfig.route('<path:config_uuid>/<path:channel_name>/update', methods=['GET', 'POST']) +def update(config_uuid, channel_name): + form = UpdateDeviceForm() + + opticalconfigId = OpticalConfigId() + opticalconfigId.opticalconfig_uuid = config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + + opticalconfig = OpticalConfig() + opticalconfig.CopyFrom(response) + config =json.loads(opticalconfig.config) + new_config={} + for channel in config['channels']: + if (channel["name"] == channel_name): + new_config=channel + form.frequency.default = channel["frequency"] + form.operational_mode.default=channel["operational-mode"] + form.power.default=channel["target-output-power"] + form.line_port.choices = [("","")] + + for transceiver in config["transceivers"]['transceiver']: + form.line_port.choices.append((transceiver,transceiver)) + + # listing enum values + if form.validate_on_submit(): + new_config["target-output-power"] =form.power.data if form.power.data != '' else new_config['target-output-power'] + new_config["frequency"]=form.frequency.data if form.frequency.data != '' else new_config['frequency'] + new_config["operational-mode"]=form.operational_mode.data if form.operational_mode.data != '' else new_config['operational-mode'] + new_config["line-port"]=form.line_port.data if form.line_port.data != '' else new_config['line-port'] + opticalconfig.config =json.dumps(new_config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticalconfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template('device/update.html', device=response, form=form, submit_text='Update Device',channel_name=channel_name) + + +@opticalconfig.route('refresh_all',methods=['POST','GET']) +def refresh_all (): + context_client.connect() + opticalConfig_list:OpticalConfigList = context_client.GetOpticalConfig(Empty()) + context_client.close() + device_client.connect() + device_client.GetDeviceConfiguration(opticalConfig_list) + device_client.close() + return home() + + +@opticalconfig.route('<path:config_uuid>/add_transceiver', methods=['GET','POST']) +def add_transceiver (config_uuid): + config={} + addtrancseiver=AddTrancseiver() + opticalconfigId=OpticalConfig() + opticalconfigId.opticalconfig_uuid=config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + opticlConfig=OpticalConfig() + opticlConfig.CopyFrom(response) + + if addtrancseiver.validate_on_submit(): + config["add_transceiver"]=addtrancseiver.transceiver.data + opticlConfig.config=json.dumps(config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticlConfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.update',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template('opticalconfig/add_transceiver.html',form=addtrancseiver, submit_text='Add Trancseiver') + + +@opticalconfig.route('<path:config_uuid>/<path:channel_name>/update_status', methods=['GET','POST']) +def update_status (config_uuid,channel_name): + config = {} + form = UpdateStatusForm() + + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid=config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + opticlConfig=OpticalConfig() + opticlConfig.CopyFrom(response) + config=json.loads(opticlConfig.config) + new_config={} + port="" + if form.validate_on_submit(): + if channel_name: + port = channel_name.split('-')[1] + new_config["status"]=form.status.data + new_config["name"]=channel_name + config["flow"]=[(port,'0')] + config["new_config"]=new_config + opticlConfig.config=json.dumps(config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticlConfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template( + 'opticalconfig/update_status.html', form=form, channel_name=channel_name, + submit_text='Update Device Status' + ) diff --git a/src/webui/service/templates/base.html b/src/webui/service/templates/base.html index 432f1a095be1a682624a45decf2355310e58238b..1402f40c43f3066b0cb09017dfb81f0e4911333f 100644 --- a/src/webui/service/templates/base.html +++ b/src/webui/service/templates/base.html @@ -90,6 +90,16 @@ </li> {% endif %} + {% if is_deployed_optical() %} + <li class="nav-item"> + {% if '/base_optical/' in request.path %} + <a class="nav-link active" aria-current="page" href="{{ url_for('base_optical.home') }}">Optical Config</a> + {% else %} + <a class="nav-link" href="{{ url_for('base_optical.home') }}">Optical Config</a> + {% endif %} + </li> + {% endif %} + {% if is_deployed_policy() %} <li class="nav-item"> {% if '/policy_rule/' in request.path %} diff --git a/src/webui/service/templates/base_optical/home.html b/src/webui/service/templates/base_optical/home.html new file mode 100644 index 0000000000000000000000000000000000000000..6c1e55b140f28e8bfdc60162a77b8756f6cee7a3 --- /dev/null +++ b/src/webui/service/templates/base_optical/home.html @@ -0,0 +1,36 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + --> + + {% extends 'base.html' %} + + {% block content %} + <h1>Optical Configurations</h1> + + <div class="row"> + <div class="col"> + <a href="{{ url_for('opticalconfig.home') }}" class="btn btn-primary" style="margin-bottom: 10px;"> + + Optical Devices + </a> + </div> + <div class="col"> + <a href="{{ url_for('optical_link.home') }}" class="btn btn-primary" style="margin-bottom: 10px;"> + + Optical Links + </a> + </div> + </div> + {% endblock %} diff --git a/src/webui/service/templates/js/topology.js b/src/webui/service/templates/js/topology.js index caba65fe5359fb64499408886c36c30377cfbbeb..8f5a383c6e90467f8a00df22c8bfb223f3b1e841 100644 --- a/src/webui/service/templates/js/topology.js +++ b/src/webui/service/templates/js/topology.js @@ -51,7 +51,7 @@ const svg = d3.select('#topology') ; // svg objects -var link, node; +var link, node, optical_link; // values for all forces forceProperties = { @@ -85,6 +85,23 @@ d3.json("{{ url_for('main.topology') }}", function(data) { .attr("stroke-dasharray", function(l) { return l.name.toLowerCase().includes('mgmt') ? "5,5" : "0"; }); + + optical_link = svg.append("g").attr("class", "links").style('stroke', '#aaa') + .selectAll("line") + .data(data.optical_links) + .enter() + .append("line") + .attr("opacity", 1) + .attr("stroke", function(l) { + return l.name.toLowerCase().includes('mgmt') ? '#AAAAAA' : '#555555'; + }) + .attr("stroke-width", function(l) { + return l.name.toLowerCase().includes('mgmt') ? 1 : 2; + }) + .attr("stroke-dasharray", function(l) { + return l.name.toLowerCase().includes('mgmt') ? "5,5" : "0"; + }); + node = svg.append("g").attr("class", "devices").attr('r', 20).style('fill', '#69b3a2') .selectAll("circle") .data(data.devices) @@ -101,6 +118,8 @@ d3.json("{{ url_for('main.topology') }}", function(data) { node.append("title").text(function(n) { return n.name; }); // link tooltip link.append("title").text(function(l) { return l.name; }); + // optical link tooltip + optical_link.append("title").text(function(l) { return l.name; }); // link style //link @@ -116,7 +135,14 @@ d3.json("{{ url_for('main.topology') }}", function(data) { .id(function(d) {return d.id;}) .distance(forceProperties.link.distance) .iterations(forceProperties.link.iterations) - .links(forceProperties.link.enabled ? data.links : [])) + .links(forceProperties.link.enabled ? data.links.length>0? data.links :[]:[])) +// ------------------ Experimental : Optical link part + .force("link", d3.forceLink() + .id(function(d) {return d.id;}) + .distance(forceProperties.link.distance) + .iterations(forceProperties.link.iterations) + .links(forceProperties.link.enabled ? data.optical_links.length>0?data.optical_links:[]:[])) + .force("charge", d3.forceManyBody() .strength(forceProperties.charge.strength * forceProperties.charge.enabled) .distanceMin(forceProperties.charge.distanceMin) @@ -147,6 +173,12 @@ function ticked() { .attr('x2', function(d) { return d.target.x; }) .attr('y2', function(d) { return d.target.y; }); + optical_link + .attr('x1', function(d) { return d.source.x; }) + .attr('y1', function(d) { return d.source.y; }) + .attr('x2', function(d) { return d.target.x; }) + .attr('y2', function(d) { return d.target.y; }); + node .attr('x', function(d) { return d.x-icon_width/2; }) .attr('y', function(d) { return d.y-icon_height/2; }); diff --git a/src/webui/service/templates/optical_link/detail.html b/src/webui/service/templates/optical_link/detail.html new file mode 100644 index 0000000000000000000000000000000000000000..d8274e6dfde59b29801bb3d49010285c48eeee25 --- /dev/null +++ b/src/webui/service/templates/optical_link/detail.html @@ -0,0 +1,158 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. + --> + +{% extends 'base.html' %} + +{% block content %} +<h1>Link {{ link.name }} ({{ link.link_id.link_uuid.uuid }})</h1> +<div class="row mb-3"> + <div class="col-sm-3"> + <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('optical_link.home') }}'"> + <i class="bi bi-box-arrow-in-left"></i> + Back to link list + </button> + </div> + <div class="col-sm-3"> + <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete link</button> --> + <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal"> + <i class="bi bi-x-square"></i> + Delete link + </button> + </div> +</div> + +<br> +<div class="row mb-3"> + <div class="col-sm-4"> + <b>UUID: </b>{{ link.link_id.link_uuid.uuid }}<br> + <b>Name: </b>{{ link.name }}<br> + </div> + <div class="col-sm-8"> + <table class="table table-striped table-hover"> + <thead> + <tr> + <th scope="col">Endpoint UUID</th> + <th scope="col">Name</th> + <th scope="col">Device</th> + <th scope="col">Endpoint Type</th> + </tr> + </thead> + <tbody> + {% for endpoint in link.link_endpoint_ids %} + <tr> + <td> + {{ endpoint.endpoint_uuid.uuid }} + </td> + <td> + {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, (endpoint.endpoint_uuid.uuid, ''))[0] }} + </td> + <td> + <a href="{{ url_for('device.detail', device_uuid=endpoint.device_id.device_uuid.uuid) }}"> + {{ device_names.get(endpoint.device_id.device_uuid.uuid, endpoint.device_id.device_uuid.uuid) }} + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> + <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> + <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> + </svg> + </a> + </td> + <td> + {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, ('', '-'))[1] }} + </td> + </tr> + {% endfor %} + </tbody> + </table> + </div> +</div> + + + +<b>Optical Link Detail:</b> +<table class="table table-striped table-hover"> + <thead> + <tr> + <th scope="col">Key</th> + <th scope="col">Value</th> + </tr> + </thead> + <tbody> + {% for field_descriptor, field_value in link.optical_details.ListFields() %} + {% if field_descriptor.name != "c_slots" and field_descriptor.name != "s_slots" and field_descriptor.name != "l_slots" %} + <tr> + <td> + {{ field_descriptor.name }} + </td> + <td> + {{ field_value }} + </td> + </tr> + {%endif%} + {% endfor %} + {%if c_slots %} + <tr> + <td> + c_slots + </td> + <td> + {{ c_slots }} + </td> + </tr> + {%endif%} + {%if l_slots %} + <tr> + <td> + l_slots + </td> + <td> + {{ l_slots }} + </td> + </tr> + {%endif%} + {%if s_slots %} + <tr> + <td> + s_slots + </td> + <td> + {{ s_slots }} + </td> + </tr> + {%endif%} + </tbody> +</table> +<!-- Modal --> +<div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" + aria-labelledby="staticBackdropLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="staticBackdropLabel">Delete link?</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + Are you sure you want to delete the link "{{ link.link_id.link_uuid.uuid }}"? + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">No</button> + <a type="button" class="btn btn-danger" + href="{{ url_for('optical_link.delete', link_uuid=link.link_id.link_uuid.uuid) }}"><i + class="bi bi-exclamation-diamond"></i>Yes</a> + </div> + </div> + </div> +</div> + +{% endblock %} diff --git a/src/webui/service/templates/optical_link/home.html b/src/webui/service/templates/optical_link/home.html new file mode 100644 index 0000000000000000000000000000000000000000..2f1b8e4af149bee70524943233800d2eb5a740d5 --- /dev/null +++ b/src/webui/service/templates/optical_link/home.html @@ -0,0 +1,122 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. +--> + +{% extends 'base.html' %} + + {% block content %} + <h1>Optical Links</h1> + + <div class="row"> + + <div class="col"> + {{ links | length }} links found in context <i>{{ session['context_uuid'] }}</i> + </div> + <div class="col-sm-3"> + <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete link</button> --> + <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal"> + <i class="bi bi-x-square"></i> + Delete All Optical Links + </button> + </div> + <!-- <div class="col"> + <form> + <div class="input-group"> + <input type="text" aria-label="Search" placeholder="Search..." class="form-control"/> + <button type="submit" class="btn btn-primary">Search</button> + </div> + </form> + </div> --> + </div> + + <table class="table table-striped table-hover"> + <thead> + <tr> + <th scope="col">UUID</th> + <th scope="col">Name</th> + <th scope="col">Endpoints</th> + <th scope="col"></th> + </tr> + </thead> + <tbody> + {% if links %} + {% for link in links %} + <tr> + <td> + {{ link.link_id.link_uuid.uuid }} + </td> + <td> + {{ link.name }} + </td> + + <td> + <ul> + {% for endpoint in link.link_endpoint_ids %} + <li> + {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, (endpoint.endpoint_uuid.uuid, ''))[0] }} / + Device: + <a href="{{ url_for('device.detail', device_uuid=endpoint.device_id.device_uuid.uuid) }}"> + {{ device_names.get(endpoint.device_id.device_uuid.uuid, endpoint.device_id.device_uuid.uuid) }} + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> + <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> + <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> + </svg> + </a> + </li> + {% endfor %} + </ul> + </td> + + <td> + <a href="{{ url_for('optical_link.detail', link_uuid=link.link_id.link_uuid.uuid) }}"> + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> + <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> + <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> + </svg> + </a> + </td> + </tr> + {% endfor %} + {% else %} + <tr> + <td colspan="7">No links found</td> + </tr> + {% endif %} + </tbody> + + </table> + +<div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" + aria-labelledby="staticBackdropLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="staticBackdropLabel">Delete All Optical links?</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + Are you sure you want to delete all the links ? + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">No</button> + <a type="button" class="btn btn-danger" + href="{{ url_for('optical_link.delete_all') }}"><i + class="bi bi-exclamation-diamond"></i>Yes</a> + </div> + </div> + </div> +</div> + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/add_transceiver.html b/src/webui/service/templates/opticalconfig/add_transceiver.html new file mode 100644 index 0000000000000000000000000000000000000000..d10faa7f146fcef18c4f865fe969cf6620e13c15 --- /dev/null +++ b/src/webui/service/templates/opticalconfig/add_transceiver.html @@ -0,0 +1,56 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. +--> + +{% extends 'base.html' %} + +{% block content %} +<h1>Add Transceiver </h1> +<br /> +<form id="Add_transceiver" method="POST"> + {{ form.hidden_tag() }} + <fieldset> + <div class="row mb-3 "> + <div class="col-12"> + {{ form.transceiver.label(class="col-sm-2 col-form-label") }} + <div class="col-sm-10"> + {% if form.transceiver.errors %} + {{ form.transceiver(class="form-control is-invalid") }} + <div class="invalid-feedback"> + {% for error in form.transceiver.errors %} + <span>{{ error }}</span> + {% endfor %} + </div> + {% else %} + + {{ form.transceiver(class="col-sm-7 form-control") }} + + {% endif %} + </div> + + </div> + <button type="submit" class="btn btn-primary"> + <i class="bi bi-plus-circle-fill"></i> + {{ submit_text }} + </button> + <button type="button" class="btn btn-block btn-secondary" onclick="javascript: history.back()"> + <i class="bi bi-box-arrow-in-left"></i> + Cancel + </button> + </div> + </fieldset> +</form> + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/details.html b/src/webui/service/templates/opticalconfig/details.html new file mode 100644 index 0000000000000000000000000000000000000000..70b17331097f24733729345d252ce1090e568018 --- /dev/null +++ b/src/webui/service/templates/opticalconfig/details.html @@ -0,0 +1,152 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. +--> + + + +{% extends 'base.html' %} + +{% block content %} + + +<h1>Optical Configurations</h1> + +<div class="row"> + + {% if device %} + <div class="col-sm-12"> + <span>Device ID:</span> + <h5>{{config_id}}</h5> + </div> + <div class="col-sm-12"> + <div class="col-sm-12"> + <div class="row mb-3 "> + + <div class="col-sm-3"> + <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('opticalconfig.home') }}'"> + <i class="bi bi-box-arrow-in-left"></i> + Back to device list + </button> + </div> + <div class="col-sm-3"> + <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete device</button> --> + <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal"> + <i class="bi bi-x-square"></i> + Delete Optical Config + </button> + </div> + </div> + </div> + <div class="col-sm-12"> + <span>Device Name:</span> + <span>{{device_name}}</span> + </div> + + </div> + + {% if type == 'optical-transponder' %} + <table class="table table-striped table-hover"> + <thead> + <tr> + <th scope="col">channel name</th> + <th scope="col">Frequency</th> + <th scope="col">Target Output Power</th> + <th scope="col">Operational Mode</th> + <th scope="col">Line Port</th> + <th scope="col">Channel Status</th> + </tr> + </thead> + <tbody> + + {% for channel in device %} + <tr style="background-color:{%if channel.status == 'DISABLED' %} gray {% endif %};"> + <td>{{channel.name.index}}</td> + <td>{{channel.frequency}}</td> + <td> {{channel.targetOutputPower}}</td> + <td>{{channel.operationalMode}}</td> + <td>{{channel.line_port}}</td> + <td> {{channel.status}}</td> + </tr> + {% endfor %} + </tbody> + </table> + {%else%} + <table class="table table-striped table-hover"> + <thead> + <tr> + <th scope="col">Channel Index</th> + <th scope="col">Optical Band Parent</th> + <th scope="col">Band Name</th> + <th scope="col">Lower Frequency</th> + <th scope="col">Upper Frequency</th> + <th scope="col">type</th> + <th scope="col"> Source Port</th> + <th scope="col">Destination Port</th> + <th scope="col">Channel Status </th> + + </tr> + </thead> + <tbody> + + {% for channel in device %} + <tr> + <td>{{channel.channel_index}}</td> + <td>{{channel.optical_band_parent}}</td> + <td> {{channel.band_name}}</td> + <td>{{channel.lower_frequency}}</td> + <td>{{channel.upper_frequency}}</td> + <td> {{channel.type}}</td> + <td>{{channel.src_port}}</td> + <td>{{channel.dest_port}}</td> + <td> {{channel.status}}</td> + + </tr> + {% endfor %} + + </tbody> + </table> + + {% endif%} + +</div> + +{% else %} +<div class="col"> + <h4 colspan="7">No devices found</h4> +</div> +{% endif %} +<div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" + aria-labelledby="staticBackdropLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="staticBackdropLabel">Delete Optical Config?</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + Are you sure you want to delete the Optical Config "{{config_id}}"? + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">No</button> + <a type="button" class="btn btn-danger" + href="{{ url_for('opticalconfig.delete_opitcalconfig', opticalconfig_uuid=config_id) }}"><i + class="bi bi-exclamation-diamond"></i>Yes</a> + </div> + </div> + </div> +</div> +</div> + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/home.html b/src/webui/service/templates/opticalconfig/home.html new file mode 100644 index 0000000000000000000000000000000000000000..a8127de5b3eec45d8e3e09d2561939814b65df46 --- /dev/null +++ b/src/webui/service/templates/opticalconfig/home.html @@ -0,0 +1,113 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. +--> + +{% extends 'base.html' %} + +{% block content %} + <h1>Optical Configurations</h1> + {% if config %} + <div class="row"> + <div class="col-sm-12"> + <div class="row mb-3 "> + + <div class="col-sm-3"> + <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('base_optical.home') }}'"> + <i class="bi bi-box-arrow-in-left"></i> + Back to main + </button> + </div> + <div class="col-sm-3"> + <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete device</button> --> + <!-- <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal"> + <i class="bi bi-x-square"></i> + Delete All + </button> --> + <button type="button" class="btn btn-info" + onclick="window.location.href='{{ url_for('opticalconfig.refresh_all') }}'"> + <i class="bi bi-arrow-clockwise"></i> + Refresh + </button> + </div> + </div> + </div> + + + <table class="table table-striped table-hover"> + <thead> + <tr> + <th scope="col">UUID</th> + <th scope="col">Device Name</th> + <th scope="col">Device Type</th> + <th scope="col">Channels Number</th> + + </tr> + </thead> + <tbody> + + {% for device in config %} + <tr> + <td>{{device.opticalconfig_id.opticalconfig_uuid}}</td> + <td>{{device.device_name}}</td> + <td> {{device.type}}</td> + {% if device.channels_number %} + <td>{{ device.channels_number }}</td> + {%else%} + <td>__ </td> + {%endif%} + {% if device.opticalconfig_id %} + <td> + <a href="{{ url_for('opticalconfig.show_details', config_uuid=device.opticalconfig_id.opticalconfig_uuid) }}"> + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> + <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> + <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> + </svg> + </a> + </td> + {%endif%} + </tr> + {% endfor %} + + </tbody> + </table> + + </div> + + {% else %} + <div class="col"> + <h4 colspan="7">No devices found</h4> + </div> + {% endif %} + <!-- <div class="col"> + <a href="{{ url_for('service.add') }}" class="btn btn-primary" style="margin-bottom: 10px;"> + <i class="bi bi-plus"></i> + Add New Service + </a> + </div> --> + + <!-- Only display XR service addition button if there are XR constellations. Otherwise it might confuse + user, as other service types do not have GUI to add service yet. --> + + <!-- <div class="col"> + <form> + <div class="input-group"> + <input type="text" aria-label="Search" placeholder="Search..." class="form-control"/> + <button type="submit" class="btn btn-primary">Search</button> + </div> + </form> + </div> --> + </div> + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/update_interface.html b/src/webui/service/templates/opticalconfig/update_interface.html new file mode 100644 index 0000000000000000000000000000000000000000..5c9b7b79c419861b287b0e4aae17e60cfbda18cc --- /dev/null +++ b/src/webui/service/templates/opticalconfig/update_interface.html @@ -0,0 +1,90 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. +--> + +{% extends 'base.html' %} + +{% block content %} +<div class="col-sm-12 d-flex flex-column"> + + <h1>Update Device {{ device.opticalconfig_id.opticalconfig_uuid }}</h1> + <h2> interface :{{interface_name}}</h2> +</div> +<br /> +<form id="update_device" method="POST"> + {{ form.hidden_tag() }} + <fieldset> + <div class="row mb-3 "> + <div class="col-12"> + {{ form.ip.label(class="col-sm-2 col-form-label") }} + <div class="col-sm-10"> + {% if form.ip.errors %} + {{ form.ip(class="form-control is-invalid") }} + <div class="invalid-feedback"> + {% for error in form.ip.errors %} + <span>{{ error }}</span> + {% endfor %} + </div> + {% else %} + + {{ form.ip(class="col-sm-7 form-control") }} + + {% endif %} + </div> + </div> + <div class="col-12 "> + {{ form.prefix_length.label(class="col-sm-2 col-form-label") }} + <div class="col-sm-10"> + {% if form.prefix_length.errors %} + {{ form.prefix_length(class="form-control is-invalid") }} + <div class="invalid-feedback"> + {% for error in form.prefix_length.errors %} + <span>{{ error }}</span> + {% endfor %} + </div> + {% else %} + + + {{ form.prefix_length(class="col-sm-7 form-control") }} + + {% endif %} + </div> + + + </div> + </div> + <div class="col-sm-12"> + <div class="row"> + <div class="col-sm-3"> + + <button type="submit" class="btn btn-primary"> + <i class="bi bi-plus-circle-fill"></i> + update interface + </button> + </div> + <div class="col-sm-3 mx-1"> + + <button type="button" class="btn btn-block btn-secondary" onclick="javascript: history.back()"> + <i class="bi bi-box-arrow-in-left"></i> + Cancel + </button> + </div> + </div> + </div> + </div> + </fieldset> +</form> + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/update_status.html b/src/webui/service/templates/opticalconfig/update_status.html new file mode 100644 index 0000000000000000000000000000000000000000..e52bfbebbe29813a49841829c57f66862baf77f8 --- /dev/null +++ b/src/webui/service/templates/opticalconfig/update_status.html @@ -0,0 +1,67 @@ +<!-- + Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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. +--> + +{% extends 'base.html' %} + +{% block content %} +<h1>Update Channel Status </h1> +<br /> +<div> + channel : <span class="font-weight-bold">{{channel_name}}</span> +</div> +<form id="update_status" method="POST"> + {{ form.hidden_tag() }} + <fieldset> + <div class="row mb-3 "> + <div class="col-12"> + {{ form.status.label(class="col-sm-2 col-form-label") }} + <div class="col-sm-10"> + {% if form.status.errors %} + {{ form.status(class="form-control is-invalid") }} + <div class="invalid-feedback"> + {% for error in form.status.errors %} + <span>{{ error }}</span> + {% endfor %} + </div> + {% else %} + + {{ form.status(class="col-sm-7 form-control") }} + + {% endif %} + </div> + + </div> + <div class="row gx-2"> + <div class="col-5"> + <button type="submit" class="btn btn-primary" > + <i class="bi bi-plus-circle-fill"></i> + {{ submit_text }} + </button> + <div class="col-5"> + + <button type="button" class="btn btn-block btn-secondary" onclick="javascript: history.back()"> + <i class="bi bi-box-arrow-in-left"></i> + Cancel + </button> + </div> + </div> + </div> + + </div> + </fieldset> +</form> + +{% endblock %}