From 9080f0f86118ec151eb9ca7f19f1807efc337d1e Mon Sep 17 00:00:00 2001 From: mansoca Date: Tue, 21 Oct 2025 11:26:00 +0000 Subject: [PATCH 01/13] Add DSCM NetConf Driver and associated test scripts - Implemented NetConfDriver for managing device configurations via NETCONF protocol. - Created run_tests_locally-device-netconf-dscm.sh script for local testing of driver functionalities. - Added Jinja2 templates for generating configuration XML for hub and leaf devices. - Developed test cases in test_dscm_netconf_hub_leaf.py to validate configuration retrieval and setting for hub and leaf devices. - Added example XML files for expected configurations and actual results for testing purposes. --- .../run_tests_locally-device-netconf-dscm.sh | 27 ++ .../drivers/netconf_dscm/NetConfDriver.py | 130 ++++++++++ .../service/drivers/netconf_dscm/__init__.py | 14 + .../templates/edit_config_hub_template.xml | 31 +++ .../templates/edit_config_leaf_template.xml | 31 +++ .../netconf_dscm/templates/edit_dscm_hub.xml | 99 +++++++ .../templates/edit_dscm_leaves.xml | 101 ++++++++ .../templates/test_hub_template.xml | 39 +++ .../component/config/edit_config.xml | 14 + .../templates/components/component/get.xml | 3 + .../component/optical_channel/get.xml | 11 + src/device/tests/dscm/Fixtures.py | 58 +++++ src/device/tests/dscm/__init__.py | 13 + src/device/tests/dscm/actual_hub.xml | 21 ++ src/device/tests/dscm/rendered_hub.xml | 60 +++++ .../tests/dscm/test_dscm_netconf_hub_leaf.py | 243 ++++++++++++++++++ 16 files changed, 895 insertions(+) create mode 100755 scripts/run_tests_locally-device-netconf-dscm.sh create mode 100644 src/device/service/drivers/netconf_dscm/NetConfDriver.py create mode 100644 src/device/service/drivers/netconf_dscm/__init__.py create mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml create mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml create mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml create mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml create mode 100644 src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml create mode 100644 src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml create mode 100644 src/device/service/drivers/openconfig/templates/components/component/get.xml create mode 100644 src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml create mode 100644 src/device/tests/dscm/Fixtures.py create mode 100644 src/device/tests/dscm/__init__.py create mode 100644 src/device/tests/dscm/actual_hub.xml create mode 100644 src/device/tests/dscm/rendered_hub.xml create mode 100644 src/device/tests/dscm/test_dscm_netconf_hub_leaf.py diff --git a/scripts/run_tests_locally-device-netconf-dscm.sh b/scripts/run_tests_locally-device-netconf-dscm.sh new file mode 100755 index 000000000..e01667e33 --- /dev/null +++ b/scripts/run_tests_locally-device-netconf-dscm.sh @@ -0,0 +1,27 @@ +# Copyright 2022-2025 ETSI 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. + + +PROJECTDIR=`pwd` + +cd $PROJECTDIR/src + +python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \ + device/tests/dscm/test_dscm_netconf_hub_leaf.py::test_get_default_hub_config + +python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \ + device/tests/dscm/test_dscm_netconf_hub_leaf.py::test_get_default_leaves_config + +# python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \ +# device/tests/dscm/test_dscm_netconf_hub_leaf.py::test_get_and_remove_topology_context diff --git a/src/device/service/drivers/netconf_dscm/NetConfDriver.py b/src/device/service/drivers/netconf_dscm/NetConfDriver.py new file mode 100644 index 000000000..20fcab5f8 --- /dev/null +++ b/src/device/service/drivers/netconf_dscm/NetConfDriver.py @@ -0,0 +1,130 @@ +# Copyright 2022-2025 ETSI 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 ast import Dict +from common.method_wrappers.Decorator import MetricsPool +from device.service.driver_api._Driver import _Driver +from jinja2 import Environment, FileSystemLoader +from typing import Any, List, Tuple, Union +import logging +import os +import subprocess + +DRIVER_NAME = 'dscm-netconf' +METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': DRIVER_NAME}) +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.INFO) + +class NetConfDriver(_Driver): + def __init__(self, address : str, port : int, **settings) -> None: + super().__init__(DRIVER_NAME, address, port, **settings) + + def GetConfig(self, resources: List[str]) -> List[Tuple[str, Union[Any, None, Exception]]]: # pyright: ignore[reportIncompatibleMethodOverride] + results = [] + for resource_path in resources: + if not resource_path.startswith('/'): + raise ValueError(f"Invalid resource path: {resource_path}. Must start with '/'") + command = [ + "netconf-console2", + f"--host={self.address}", + f"--port={self.port}", + "--tcp", + "--get-config", + f"{resource_path}" + ] + LOGGER.info(f"Executing command: {' '.join(command)}") + try: + result = subprocess.run(command, capture_output=True, text=True, timeout=10) + if result.returncode == 0: + LOGGER.info(f"Get-config successful for {resource_path}") + # LOGGER.info(result.stdout) + results.append(result.stdout) + else: + MSG = 'Exception retrieving {:s}: {:s}' + LOGGER.exception(f"Get-config failed for {resource_path}: {result.stderr}") + results.append(Exception(MSG.format(resource_path, result.stderr))) + except Exception as e: + LOGGER.exception("Command timed out") + results.append(e) + return results + + def SetConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: + results = [] + for node, config in resources: + # rendered_config = self.populated_xml_template(node, config) + self.populated_xml_template(node, config) + command = [ + "netconf-console2", + f"--host={self.address}", + f"--port={self.port}", + "--tcp", + "--edit-config", + f"{node}.xml" # rendered_config + ] + LOGGER.info(f"Executing command: {' '.join(command)}") + try: + result = subprocess.run(command, capture_output=True, text=True, timeout=10) + LOGGER.info(f"Command output: {result.stdout}") + if result.returncode == 0: + LOGGER.info(f"Set-config successful for {node}") + results.append(True) + else: + MSG = 'Exception setting {:s}: {:s}' + LOGGER.exception(f"Set-config failed for {node}: {result.stderr}") + results.append(Exception(MSG.format(node, result.stderr))) + except Exception as e: + LOGGER.exception("Command timed out") + results.append(e) + return results + + + def populated_xml_template(self, node : str, config: Dict): + try: + # Get the directory of this file to locate the template + current_dir = os.path.dirname(os.path.abspath(__file__)) + template_dir = os.path.join(current_dir, 'templates') + # template_dir = 'templates/' + LOGGER.info(f"Template directory: {template_dir}") + + # Set up Jinja2 environment + env = Environment(loader=FileSystemLoader(template_dir)) + if node == 'T2.1': + LOGGER.info("Using hub template: edit_config_hub_template.xml") + # template = env.get_template('test_hub_template.xml') + template = env.get_template('edit_config_hub_template.xml') + elif node in ['T1.1', 'T1.2', 'T1.3']: + template = env.get_template('edit_config_leaf_template.xml') + else: + raise ValueError(f"Unknown node: {node}") + + # Render the template with config values + rendered_xml = template.render(**config) + + LOGGER.info(f"Rendered XML:\n{rendered_xml}") + # return rendered_xml + + # Write to file + output_file = f"{node}.xml" + with open(output_file, 'w') as f: + f.write(rendered_xml) + + LOGGER.info(f"XML template populated and saved to {output_file}") + return True + + except Exception as e: + LOGGER.exception(f"Failed to populate XML template: {e}") + # return False + + diff --git a/src/device/service/drivers/netconf_dscm/__init__.py b/src/device/service/drivers/netconf_dscm/__init__.py new file mode 100644 index 000000000..3ccc21c7d --- /dev/null +++ b/src/device/service/drivers/netconf_dscm/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022-2025 ETSI 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/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml b/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml new file mode 100644 index 000000000..3ef82a186 --- /dev/null +++ b/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml @@ -0,0 +1,31 @@ + + + {{name}} + + {% if operation is defined and operation != 'delete' %} + + {% if frequency is defined %}{{frequency}}{% endif %} + {% if target_output_power is defined %}{{target_output_power}}{% endif %} + {% if operational_mode is defined %}{{operational_mode}}{% endif %} + + {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} + {% for group in digital_sub_carriers_group %} + + {{group.digital_sub_carriers_group_id}} + + {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} + {% for sub_carrier in group.digital_sub_carrier_id %} + + {{sub_carrier.sub_carrier_id}} + {{sub_carrier.active}} + + {% endfor %} + {% endif %} + + {% endfor %} + {% endif %} + + {% endif %} + + + \ No newline at end of file diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml b/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml new file mode 100644 index 000000000..3ef82a186 --- /dev/null +++ b/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml @@ -0,0 +1,31 @@ + + + {{name}} + + {% if operation is defined and operation != 'delete' %} + + {% if frequency is defined %}{{frequency}}{% endif %} + {% if target_output_power is defined %}{{target_output_power}}{% endif %} + {% if operational_mode is defined %}{{operational_mode}}{% endif %} + + {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} + {% for group in digital_sub_carriers_group %} + + {{group.digital_sub_carriers_group_id}} + + {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} + {% for sub_carrier in group.digital_sub_carrier_id %} + + {{sub_carrier.sub_carrier_id}} + {{sub_carrier.active}} + + {% endfor %} + {% endif %} + + {% endfor %} + {% endif %} + + {% endif %} + + + \ No newline at end of file diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml b/src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml new file mode 100644 index 000000000..21eb62ebe --- /dev/null +++ b/src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml @@ -0,0 +1,99 @@ + + + channel-1 + + + 195000000 + -3.0 + 1 + port-1 + 50.0 + + 1 + 4 + 100 + + 1 + true + + + 2 + true + + + 3 + true + + + 4 + true + + + + 2 + 4 + 100 + + 5 + true + + + 6 + true + + + 7 + true + + + 8 + true + 0.0 + + + + 3 + 4 + 100 + + 9 + true + + + 10 + true + + + 11 + true + + + 12 + true + + + + 4 + 4 + 100 + + 13 + true + + + 14 + true + + + 15 + true + + + 16 + true + + + + + + diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml b/src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml new file mode 100644 index 000000000..093b25b90 --- /dev/null +++ b/src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml @@ -0,0 +1,101 @@ + + + channel-1 + + + 195006250 + -99.0 + 1 + port-1 + 50.0 + + 1 + 4 + 100 + + 1 + true + + + 2 + true + + + 3 + true + + + 4 + true + + + + + + + channel-3 + + + 195018750 + -99.0 + 1 + port-3 + 50.0 + + 1 + 4 + 100 + + 1 + true + + + 2 + true + + + 3 + true + + + 4 + true + + + + + + + channel-5 + + + 195031250 + -99.0 + 1 + port-5 + 50.0 + + 1 + 4 + 100 + + 1 + true + + + 2 + true + + + 3 + true + + + 4 + true + + + + + + diff --git a/src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml b/src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml new file mode 100644 index 000000000..19a8d2ea8 --- /dev/null +++ b/src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml @@ -0,0 +1,39 @@ + + + {{ name }} + + {% if operation is defined and operation != 'delete' %} + + {% if frequency is defined %} + {{ frequency }} + {% endif %} + + {% if target_output_power is defined %} + {{ target_output_power }} + {% endif %} + + {% if operational_mode is defined %} + {{ operational_mode }} + {% endif %} + + {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} + {% for group in digital_sub_carriers_group %} + + {{ group.digital_sub_carriers_group_id }} + + {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} + {% for sub_carrier in group.digital_sub_carrier_id %} + + {{ sub_carrier.sub_carrier_id }} + {% if sub_carrier.active %}true{% else %}false{% endif %} + + {% endfor %} + {% endif %} + + {% endfor %} + {% endif %} + + {% endif %} + + + diff --git a/src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml b/src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml new file mode 100644 index 000000000..67ed5d1dd --- /dev/null +++ b/src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml @@ -0,0 +1,14 @@ + + + {{name}} + + {% if operation is defined and operation != 'delete' %} + + {% if frequency is defined %}{{frequency}}{% endif %} + {% if target_output_power is defined %}{{target_output_power}}{% endif %} + {% if operational_mode is defined %}{{operational_mode}}{% endif %} + + {% endif %} + + + diff --git a/src/device/service/drivers/openconfig/templates/components/component/get.xml b/src/device/service/drivers/openconfig/templates/components/component/get.xml new file mode 100644 index 000000000..aa25ed1e3 --- /dev/null +++ b/src/device/service/drivers/openconfig/templates/components/component/get.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml b/src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml new file mode 100644 index 000000000..89250f818 --- /dev/null +++ b/src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml @@ -0,0 +1,11 @@ + + + {% if component_name %} + {{ component_name }} + {% endif %} + + + + + + diff --git a/src/device/tests/dscm/Fixtures.py b/src/device/tests/dscm/Fixtures.py new file mode 100644 index 000000000..458d0d786 --- /dev/null +++ b/src/device/tests/dscm/Fixtures.py @@ -0,0 +1,58 @@ +# Copyright 2022-2024 ETSI 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 pytest +import logging + +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from service.client.ServiceClient import ServiceClient +from kpi_manager.client.KpiManagerClient import KpiManagerClient + + +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.DEBUG) + + +@pytest.fixture(scope='session') +def context_client(): + _client = ContextClient(host="10.152.183.127") + _client.connect() + LOGGER.info('Yielding Connected ContextClient...') + yield _client + _client.close() + +@pytest.fixture(scope='session') +def device_client(): + _client = DeviceClient(host="10.152.183.95") + _client.connect() + LOGGER.info('Yielding Connected DeviceClient...') + yield _client + _client.close() + +@pytest.fixture(scope='session') +def service_client(): + _client = ServiceClient(host="10.152.183.47") + _client.connect() + LOGGER.info('Yielding Connected DeviceClient...') + yield _client + _client.close() + +@pytest.fixture(scope='session') +def kpi_manager_client(): + _client = KpiManagerClient(host="10.152.183.118") + LOGGER.info('Yielding Connected KpiManagerClient...') + yield _client + _client.close() + LOGGER.info('Closed KpiManagerClient...') diff --git a/src/device/tests/dscm/__init__.py b/src/device/tests/dscm/__init__.py new file mode 100644 index 000000000..7363515f0 --- /dev/null +++ b/src/device/tests/dscm/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022-2025 ETSI 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/device/tests/dscm/actual_hub.xml b/src/device/tests/dscm/actual_hub.xml new file mode 100644 index 000000000..5a71bf052 --- /dev/null +++ b/src/device/tests/dscm/actual_hub.xml @@ -0,0 +1,21 @@ + +1 +4 +100 + +1 +false + + +2 +false + + +3 +false + + +4 +false + + \ No newline at end of file diff --git a/src/device/tests/dscm/rendered_hub.xml b/src/device/tests/dscm/rendered_hub.xml new file mode 100644 index 000000000..415ee4744 --- /dev/null +++ b/src/device/tests/dscm/rendered_hub.xml @@ -0,0 +1,60 @@ + + + channel-1 + + + 195000000 + 0.0 + 9 + + 1 + + + 1 + True + + + + 2 + True + + + + 3 + True + + + + 4 + True + + + + + + 1 + + + 5 + True + + + + 6 + True + + + + 7 + True + + + + 8 + True + + + + + + \ No newline at end of file diff --git a/src/device/tests/dscm/test_dscm_netconf_hub_leaf.py b/src/device/tests/dscm/test_dscm_netconf_hub_leaf.py new file mode 100644 index 000000000..7c707a769 --- /dev/null +++ b/src/device/tests/dscm/test_dscm_netconf_hub_leaf.py @@ -0,0 +1,243 @@ +# Copyright 2022-2025 ETSI 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, os, pytest, time +from typing import Dict, Tuple +from device.service.drivers.netconf_dscm.NetConfDriver import NetConfDriver + +logging.basicConfig(level=logging.DEBUG) +LOGGER = logging.getLogger(__name__) + +DEVICES = { + 'hub': {'address': '10.30.7.7', 'port': 2023, 'settings': {}}, + 'leaf': {'address': '10.30.7.8', 'port': 2023, 'settings': {}} + } + +@pytest.fixture(autouse=True) +def log_each(request): + LOGGER.info(f">>>>>> START {request.node.name} >>>>>>") + yield + LOGGER.info(f"<<<<<< END {request.node.name} <<<<<<") + +@pytest.fixture(scope='session') +def get_driver_hub() -> Tuple[NetConfDriver, None]: # pyright: ignore[reportInvalidTypeForm] + driver = NetConfDriver( + DEVICES['hub']['address'], DEVICES['hub']['port'], **(DEVICES['hub']['settings']) + ) + yield driver # pyright: ignore[reportReturnType] + time.sleep(1) + +@pytest.fixture(scope='session') +def get_driver_leaf() -> Tuple[NetConfDriver, None]: # pyright: ignore[reportInvalidTypeForm] + driver = NetConfDriver( + DEVICES['leaf']['address'], DEVICES['leaf']['port'], **(DEVICES['leaf']['settings']) + ) + yield driver # pyright: ignore[reportReturnType] + time.sleep(1) + + +# --- Directly Testing SBI +def test_get_default_hub_config(get_driver_hub) -> Dict: + data = { + "name": "channel-1", + "frequency": 195000000, + "operational_mode": 1, + "target_output_power": 0.0, + "operation" : "merge", + "digital_sub_carriers_group": [ + { + "digital_sub_carriers_group_id": 1, + "digital_sub_carrier_id": [ + { + "sub_carrier_id": 1, + "active": "true" + }, + { + "sub_carrier_id": 2, + "active": "true" + }, + { + "sub_carrier_id": 3, + "active": "true" + }, + { + "sub_carrier_id": 4, + "active": "true" + } + ] + }, + { + "digital_sub_carriers_group_id": 2, + "digital_sub_carrier_id": [ + { + "sub_carrier_id": 5, + "active": "true" + }, + { + "sub_carrier_id": 6, + "active": "true" + }, + { + "sub_carrier_id": 7, + "active": "true" + }, + { + "sub_carrier_id": 8, + "active": "true" + } + ] + } + ], + } + node = 'T2.1' + result_config = get_driver_hub.SetConfig([(node, data)]) + assert result_config is not None + +def test_get_default_leaves_config(get_driver_leaf) -> Dict: + data = { + "name" : "channel-1", # "channel-1", "channel-3", "channel-5" + "frequency" : 195006250, # "195006250", 195018750, 195031250 + "operational_mode" : 1, + "target_output_power": -99, # should be -99 + "operation" : "merge", + "digital_sub_carriers_group": [ + { + "digital_sub_carriers_group_id": 1, + "digital_sub_carrier_id": [ + { + "sub_carrier_id": 1, + "active": "false" # should be set to false + }, + { + "sub_carrier_id": 2, + "active": "false" + }, + { + "sub_carrier_id": 3, + "active": "false" + }, + { + "sub_carrier_id": 4, + "active": "false" + } + ] + } + ], + } + node = 'T1.1' + result_config = get_driver_leaf.SetConfig([(node, data)]) + assert result_config is not None + +# netconf-console2 --host=10.30.7.7 --port=2023 --tcp --get-config -x '/components/component[name="channel-1"]/optical-channel/state/input-power/instant' + +# def test_get_config(get_driver): +# path = '/components/component[name="channel-1"]/optical-channel/state/input-power/instant' +# result_config = get_driver.GetConfig([path]) +# assert result_config is not None +# LOGGER.info(f"GetConfig result: {result_config}") + +# netconf-console2 --host=10.30.7.7 --port=2023 --tcp --edit-config edit_dscm_hub.xml + +# def test_set_config_hub(get_driver_hub): +# data = { +# "name": "channel-1", +# "frequency": "195000000", +# "target_output_power": "-3.0", +# "operational_mode": "1", +# "operation": "merge", +# "digital_subcarriers_groups": [ +# { "group_id": 1, "digital-subcarrier-id": [{ "subcarrier-id": 1, "active": True}, ]}, +# { "group_id": 2, "digital-subcarrier-id": [{ "subcarrier-id": 2, "active": True}, ]}, +# { "group_id": 3, "digital-subcarrier-id": [{ "subcarrier-id": 3, "active": True}, ]}, +# { "group_id": 4, "digital-subcarrier-id": [{ "subcarrier-id": 4, "active": True}, ]}, +# ], +# } +# node = 'hub' +# result_config = get_driver_hub.SetConfig([(node, data)]) +# assert result_config is not None +# # LOGGER.info(f"SetConfig result: {result_config}") + +# def test_set_config_leaf(get_driver_leaf): +# data = { +# "operation": "merge", +# "channels": +# [ +# { +# "name": "channel-1", +# "frequency": "195006250", +# "target_output_power": "-99.0", +# "operational_mode": "1", +# "digital_subcarriers_groups": +# [{ "group_id": 1 }] +# }, +# { +# "name": "channel-3", +# "frequency": "195018750", +# "target_output_power": "-99.0", +# "operational_mode": "1", +# "digital_subcarriers_groups": +# [{ "group_id": 1 }] +# }, +# { +# "name": "channel-5", +# "frequency": "195031250", +# "target_output_power": "-99.0", +# "operational_mode": "1", +# "digital_subcarriers_groups": +# [{ "group_id": 1 }] +# } +# ] +# } +# node = 'leaf' +# result_config = get_driver_leaf.SetConfig([(node, data)]) +# assert result_config is not None +# # LOGGER.info(f"SetConfig result: {result_config}") + + +# def test_dscm_netconf_hub(drivers): +# path = '/components/component[name="channel-1"]/config' +# data = json.dumps( +# { "name": "channel-1", +# "frequency": "195000000", +# "target_output_power": "-3.0", +# "operational_mode": "1", +# } +# ) +# config_to_set = [(path, data)] +# result_config = drivers['DSCM1'].SetConfig(config_to_set) +# assert result_config is not None +# LOGGER.info(f"SetConfig result: {result_config}") + + + +from common.tools.context_queries.Topology import get_topology +from common.proto.context_pb2 import TopologyId, ContextId +from .Fixtures import context_client +def test_get_and_remove_topology_context(context_client): + response = get_topology(context_client = context_client, topology_uuid = "admin", context_uuid = "admin") + LOGGER.info(f"Topology: {response}") + assert response is not None + # create context_id and topology_id from response + context_id = ContextId() + context_id = response.topology_id.context_id + topology_id = TopologyId() + topology_id = response.topology_id + # Remove Topology + topology_id.context_id.CopyFrom(context_id) + response = context_client.RemoveTopology(topology_id) + LOGGER.info(f"Topology removed Sucessfully") + # Remove Context + response = context_client.RemoveContext(context_id) + LOGGER.info(f"Context removed Sucessfully") -- GitLab From 283dee2252bad0af76ee983d7c32d7d0b069f30b Mon Sep 17 00:00:00 2001 From: mansoca Date: Tue, 21 Oct 2025 11:29:59 +0000 Subject: [PATCH 02/13] Add DSCM NetConf Driver and associated test scripts (2nd commit) - Implemented NetConfDriver for managing device configurations via NETCONF protocol. - Created run_tests_locally-device-netconf-dscm.sh script for local testing of driver functionalities. - Added Jinja2 templates for generating configuration XML for hub and leaf devices. - Developed test cases in test_dscm_netconf_hub_leaf.py to validate configuration retrieval and setting for hub and leaf devices. - Added example XML files for expected configurations and actual results for testing purposes. --- src/device/requirements.in | 1 + src/device/service/drivers/__init__.py | 11 +++++++ .../drivers/openconfig/templates/Namespace.py | 32 ++++++++++--------- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/device/requirements.in b/src/device/requirements.in index 10139bc2c..0a75ac159 100644 --- a/src/device/requirements.in +++ b/src/device/requirements.in @@ -27,6 +27,7 @@ Jinja2==3.0.3 libyang==2.8.4 macaddress ncclient==0.6.15 +netconf-console2==3.0.1 numpy<2.0.0 p4runtime==1.3.0 pandas==1.5.* diff --git a/src/device/service/drivers/__init__.py b/src/device/service/drivers/__init__.py index 788b09edd..c8058f5e3 100644 --- a/src/device/service/drivers/__init__.py +++ b/src/device/service/drivers/__init__.py @@ -252,3 +252,14 @@ if LOAD_ALL_DEVICE_DRIVERS: FilterFieldEnum.DRIVER : DeviceDriverEnum.DEVICEDRIVER_QKD, } ])) + +if LOAD_ALL_DEVICE_DRIVERS: + from .netconf_dscm.NetConfDriver import NetConfDriver # pylint: disable=wrong-import-position + DRIVERS.append( + (NetConfDriver, [ + { + # Real DSCM, specifying NetConf Driver => use NetConfDriver + FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.DSCM_NODE, + FilterFieldEnum.DRIVER : DeviceDriverEnum.DRVICEDRIVER_NETCONF_DSCM, + } + ])) diff --git a/src/device/service/drivers/openconfig/templates/Namespace.py b/src/device/service/drivers/openconfig/templates/Namespace.py index 4604481bb..9455ed3b3 100644 --- a/src/device/service/drivers/openconfig/templates/Namespace.py +++ b/src/device/service/drivers/openconfig/templates/Namespace.py @@ -13,22 +13,23 @@ # limitations under the License. -NAMESPACE_NETCONF = 'urn:ietf:params:xml:ns:netconf:base:1.0' +NAMESPACE_NETCONF = 'urn:ietf:params:xml:ns:netconf:base:1.0' -NAMESPACE_ACL = 'http://openconfig.net/yang/acl' -NAMESPACE_BGP_POLICY = 'http://openconfig.net/yang/bgp-policy' -NAMESPACE_INTERFACES = 'http://openconfig.net/yang/interfaces' -NAMESPACE_INTERFACES_IP = 'http://openconfig.net/yang/interfaces/ip' -NAMESPACE_NETWORK_INSTANCE = 'http://openconfig.net/yang/network-instance' -NAMESPACE_NETWORK_INSTANCE_TYPES = 'http://openconfig.net/yang/network-instance-types' -NAMESPACE_OPENCONFIG_TYPES = 'http://openconfig.net/yang/openconfig-types' -NAMESPACE_PLATFORM = 'http://openconfig.net/yang/platform' -NAMESPACE_PLATFORM_PORT = 'http://openconfig.net/yang/platform/port' -NAMESPACE_POLICY_TYPES = 'http://openconfig.net/yang/policy-types' -NAMESPACE_POLICY_TYPES_2 = 'http://openconfig.net/yang/policy_types' -NAMESPACE_ROUTING_POLICY = 'http://openconfig.net/yang/routing-policy' -NAMESPACE_VLAN = 'http://openconfig.net/yang/vlan' -NAMESPACE_PLATFORM_TRANSCEIVER = 'http://openconfig.net/yang/platform/transceiver' +NAMESPACE_ACL = 'http://openconfig.net/yang/acl' +NAMESPACE_BGP_POLICY = 'http://openconfig.net/yang/bgp-policy' +NAMESPACE_INTERFACES = 'http://openconfig.net/yang/interfaces' +NAMESPACE_INTERFACES_IP = 'http://openconfig.net/yang/interfaces/ip' +NAMESPACE_NETWORK_INSTANCE = 'http://openconfig.net/yang/network-instance' +NAMESPACE_NETWORK_INSTANCE_TYPES = 'http://openconfig.net/yang/network-instance-types' +NAMESPACE_OPENCONFIG_TYPES = 'http://openconfig.net/yang/openconfig-types' +NAMESPACE_PLATFORM = 'http://openconfig.net/yang/platform' +NAMESPACE_PLATFORM_PORT = 'http://openconfig.net/yang/platform/port' +NAMESPACE_POLICY_TYPES = 'http://openconfig.net/yang/policy-types' +NAMESPACE_POLICY_TYPES_2 = 'http://openconfig.net/yang/policy_types' +NAMESPACE_ROUTING_POLICY = 'http://openconfig.net/yang/routing-policy' +NAMESPACE_VLAN = 'http://openconfig.net/yang/vlan' +NAMESPACE_PLATFORM_TRANSCEIVER = 'http://openconfig.net/yang/platform/transceiver' +NAMESPACE_TERMINAL_DEVICE_DIGITAL_SUBCARRIERS = 'http://openconfig.net/yang/terminal-device-digital-subcarriers' NAMESPACES = { 'nc' : NAMESPACE_NETCONF, @@ -46,4 +47,5 @@ NAMESPACES = { 'ocrp' : NAMESPACE_ROUTING_POLICY, 'ocv' : NAMESPACE_VLAN, 'ocptr': NAMESPACE_PLATFORM_TRANSCEIVER, + 'octds': NAMESPACE_TERMINAL_DEVICE_DIGITAL_SUBCARRIERS, } -- GitLab From 6d4f771791b29f16a463aed3d9d934f1d661bfb3 Mon Sep 17 00:00:00 2001 From: mansoca Date: Tue, 21 Oct 2025 11:32:58 +0000 Subject: [PATCH 03/13] fix: add missing newline at end of XML files --- .../drivers/netconf_dscm/templates/edit_config_hub_template.xml | 2 +- .../netconf_dscm/templates/edit_config_leaf_template.xml | 2 +- src/device/tests/dscm/actual_hub.xml | 2 +- src/device/tests/dscm/rendered_hub.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml b/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml index 3ef82a186..4149bccda 100644 --- a/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml +++ b/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml @@ -28,4 +28,4 @@ {% endif %} - \ No newline at end of file + diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml b/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml index 3ef82a186..4149bccda 100644 --- a/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml +++ b/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml @@ -28,4 +28,4 @@ {% endif %} - \ No newline at end of file + diff --git a/src/device/tests/dscm/actual_hub.xml b/src/device/tests/dscm/actual_hub.xml index 5a71bf052..32067b11e 100644 --- a/src/device/tests/dscm/actual_hub.xml +++ b/src/device/tests/dscm/actual_hub.xml @@ -18,4 +18,4 @@ 4 false - \ No newline at end of file + diff --git a/src/device/tests/dscm/rendered_hub.xml b/src/device/tests/dscm/rendered_hub.xml index 415ee4744..14a9d37d9 100644 --- a/src/device/tests/dscm/rendered_hub.xml +++ b/src/device/tests/dscm/rendered_hub.xml @@ -57,4 +57,4 @@ - \ No newline at end of file + -- GitLab From 09b8ca59baf41064624b598a8b0dca8eb622ad8e Mon Sep 17 00:00:00 2001 From: Waleed Akbar Date: Wed, 29 Oct 2025 17:39:12 +0000 Subject: [PATCH 04/13] Updates in SBI to add support of DSCM pluggables - Remove unused DeviceDriverEnum entry - Update test script for integration testing - added new templates for DSCM configuration - update jinja main file to prcess DSCM pluggables request --- proto/context.proto | 1 - .../run_tests_locally-service-pluggable.sh | 7 +++-- .../drivers/openconfig/templates/__init__.py | 21 +++++++++++++ .../1/config/edit_config_hub_template.xml | 31 +++++++++++++++++++ .../1/config/edit_config_leaf_template.xml | 31 +++++++++++++++++++ 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_hub_template.xml create mode 100644 src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml diff --git a/proto/context.proto b/proto/context.proto index 4833d9c22..9fde6a3c1 100644 --- a/proto/context.proto +++ b/proto/context.proto @@ -252,7 +252,6 @@ enum DeviceDriverEnum { DEVICEDRIVER_RYU = 18; DEVICEDRIVER_GNMI_NOKIA_SRLINUX = 19; DEVICEDRIVER_OPENROADM = 20; - DRVICEDRIVER_NETCONF_DSCM = 21; } enum DeviceOperationalStatusEnum { diff --git a/scripts/run_tests_locally-service-pluggable.sh b/scripts/run_tests_locally-service-pluggable.sh index 600c1edf7..e749bd43c 100755 --- a/scripts/run_tests_locally-service-pluggable.sh +++ b/scripts/run_tests_locally-service-pluggable.sh @@ -17,7 +17,10 @@ PROJECTDIR=`pwd` cd $PROJECTDIR/src RCFILE=$PROJECTDIR/coverage/.coveragerc -python3 -m pytest --log-level=info --log-cli-level=info --verbose \ - pluggables/tests/test_Pluggables.py +# to run integration test: -m integration +python3 -m pytest --log-level=info --log-cli-level=info --verbose -m "not integration" \ + pluggables/tests/test_pluggables_with_SBI.py +# python3 -m pytest --log-level=info --log-cli-level=info --verbose \ +# pluggables/tests/test_Pluggables.py echo "Bye!" diff --git a/src/device/service/drivers/openconfig/templates/__init__.py b/src/device/service/drivers/openconfig/templates/__init__.py index 3704791d8..514c3a696 100644 --- a/src/device/service/drivers/openconfig/templates/__init__.py +++ b/src/device/service/drivers/openconfig/templates/__init__.py @@ -136,6 +136,27 @@ def compose_config( # template generation templates.append(JINJA_ENV.get_template(enable_ingress_filter_path)) templates.append(JINJA_ENV.get_template(acl_entry_path)) templates.append(JINJA_ENV.get_template(acl_ingress_path)) + elif "pluggable" in resource_key: # MANAGING DSCM (Digital Subcarrier Modules) + # Resource key format: /pluggable/{template_index}/config/{template_identifier} + # Example: /pluggable/1/config/hub or /pluggable/1/config/leaf + # Extract template identifier (hub or leaf) from the resource key + key_parts = resource_key.strip('/').split('/') + if len(key_parts) >= 4 and key_parts[-1] in ['hub', 'leaf']: + template_identifier = key_parts[-1] # 'hub' or 'leaf' + template_index = key_parts[1] if len(key_parts) > 1 else '1' + + # Build template path: pluggable/{index}/config/edit_config_{hub|leaf}_template.xml + template_path = f'pluggable/{template_index}/config/edit_config_{template_identifier}_template.xml' + templates.append(JINJA_ENV.get_template(template_path)) + + LOGGER.info(f"Loading DSCM template: {template_path}") + else: + # Fallback to generic template if format doesn't match expected pattern + LOGGER.warning(f"Unexpected DSCM resource key format: {resource_key}, using default template") + template_name = '{:s}/edit_config.xml'.format(RE_REMOVE_FILTERS.sub('', resource_key)) + templates.append(JINJA_ENV.get_template(template_name)) + + data : Dict[str, Any] = json.loads(resource_value) else: template_name = '{:s}/edit_config.xml'.format(RE_REMOVE_FILTERS.sub('', resource_key)) templates.append(JINJA_ENV.get_template(template_name)) diff --git a/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_hub_template.xml b/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_hub_template.xml new file mode 100644 index 000000000..4149bccda --- /dev/null +++ b/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_hub_template.xml @@ -0,0 +1,31 @@ + + + {{name}} + + {% if operation is defined and operation != 'delete' %} + + {% if frequency is defined %}{{frequency}}{% endif %} + {% if target_output_power is defined %}{{target_output_power}}{% endif %} + {% if operational_mode is defined %}{{operational_mode}}{% endif %} + + {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} + {% for group in digital_sub_carriers_group %} + + {{group.digital_sub_carriers_group_id}} + + {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} + {% for sub_carrier in group.digital_sub_carrier_id %} + + {{sub_carrier.sub_carrier_id}} + {{sub_carrier.active}} + + {% endfor %} + {% endif %} + + {% endfor %} + {% endif %} + + {% endif %} + + + diff --git a/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml b/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml new file mode 100644 index 000000000..4149bccda --- /dev/null +++ b/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml @@ -0,0 +1,31 @@ + + + {{name}} + + {% if operation is defined and operation != 'delete' %} + + {% if frequency is defined %}{{frequency}}{% endif %} + {% if target_output_power is defined %}{{target_output_power}}{% endif %} + {% if operational_mode is defined %}{{operational_mode}}{% endif %} + + {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} + {% for group in digital_sub_carriers_group %} + + {{group.digital_sub_carriers_group_id}} + + {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} + {% for sub_carrier in group.digital_sub_carrier_id %} + + {{sub_carrier.sub_carrier_id}} + {{sub_carrier.active}} + + {% endfor %} + {% endif %} + + {% endfor %} + {% endif %} + + {% endif %} + + + -- GitLab From 80ada479432659790a59dcd1da9d15714572ee5b Mon Sep 17 00:00:00 2001 From: Waleed Akbar Date: Thu, 30 Oct 2025 09:14:28 +0000 Subject: [PATCH 05/13] Replaces two hub and leaf templates with generic template --- src/device/service/drivers/__init__.py | 36 +++++++------------ .../drivers/openconfig/templates/__init__.py | 23 +++--------- ...onfig_hub_template.xml => edit_config.xml} | 0 .../1/config/edit_config_leaf_template.xml | 31 ---------------- .../service/PluggablesServiceServicerImpl.py | 32 ++++------------- 5 files changed, 25 insertions(+), 97 deletions(-) rename src/device/service/drivers/openconfig/templates/pluggable/1/config/{edit_config_hub_template.xml => edit_config.xml} (100%) delete mode 100644 src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml diff --git a/src/device/service/drivers/__init__.py b/src/device/service/drivers/__init__.py index ed6f24fbf..92fdff911 100644 --- a/src/device/service/drivers/__init__.py +++ b/src/device/service/drivers/__init__.py @@ -98,19 +98,19 @@ if LOAD_ALL_DEVICE_DRIVERS: } ])) -if LOAD_ALL_DEVICE_DRIVERS: - from .gnmi_openconfig.GnmiOpenConfigDriver import GnmiOpenConfigDriver # pylint: disable=wrong-import-position - DRIVERS.append( - (GnmiOpenConfigDriver, [ - { - # Real Packet Router, specifying gNMI OpenConfig Driver => use GnmiOpenConfigDriver - FilterFieldEnum.DEVICE_TYPE: [ - DeviceTypeEnum.PACKET_POP, - DeviceTypeEnum.PACKET_ROUTER, - ], - FilterFieldEnum.DRIVER : DeviceDriverEnum.DEVICEDRIVER_GNMI_OPENCONFIG, - } - ])) +# if LOAD_ALL_DEVICE_DRIVERS: +# from .gnmi_openconfig.GnmiOpenConfigDriver import GnmiOpenConfigDriver # pylint: disable=wrong-import-position +# DRIVERS.append( +# (GnmiOpenConfigDriver, [ +# { +# # Real Packet Router, specifying gNMI OpenConfig Driver => use GnmiOpenConfigDriver +# FilterFieldEnum.DEVICE_TYPE: [ +# DeviceTypeEnum.PACKET_POP, +# DeviceTypeEnum.PACKET_ROUTER, +# ], +# FilterFieldEnum.DRIVER : DeviceDriverEnum.DEVICEDRIVER_GNMI_OPENCONFIG, +# } +# ])) if LOAD_ALL_DEVICE_DRIVERS: from .gnmi_nokia_srlinux.GnmiNokiaSrLinuxDriver import GnmiNokiaSrLinuxDriver # pylint: disable=wrong-import-position @@ -251,13 +251,3 @@ if LOAD_ALL_DEVICE_DRIVERS: } ])) -if LOAD_ALL_DEVICE_DRIVERS: - from .netconf_dscm.NetConfDriver import NetConfDriver # pylint: disable=wrong-import-position - DRIVERS.append( - (NetConfDriver, [ - { - # Real DSCM, specifying NetConf Driver => use NetConfDriver - FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.DSCM_NODE, - FilterFieldEnum.DRIVER : DeviceDriverEnum.DRVICEDRIVER_NETCONF_DSCM, - } - ])) diff --git a/src/device/service/drivers/openconfig/templates/__init__.py b/src/device/service/drivers/openconfig/templates/__init__.py index 514c3a696..eca314a84 100644 --- a/src/device/service/drivers/openconfig/templates/__init__.py +++ b/src/device/service/drivers/openconfig/templates/__init__.py @@ -137,24 +137,11 @@ def compose_config( # template generation templates.append(JINJA_ENV.get_template(acl_entry_path)) templates.append(JINJA_ENV.get_template(acl_ingress_path)) elif "pluggable" in resource_key: # MANAGING DSCM (Digital Subcarrier Modules) - # Resource key format: /pluggable/{template_index}/config/{template_identifier} - # Example: /pluggable/1/config/hub or /pluggable/1/config/leaf - # Extract template identifier (hub or leaf) from the resource key - key_parts = resource_key.strip('/').split('/') - if len(key_parts) >= 4 and key_parts[-1] in ['hub', 'leaf']: - template_identifier = key_parts[-1] # 'hub' or 'leaf' - template_index = key_parts[1] if len(key_parts) > 1 else '1' - - # Build template path: pluggable/{index}/config/edit_config_{hub|leaf}_template.xml - template_path = f'pluggable/{template_index}/config/edit_config_{template_identifier}_template.xml' - templates.append(JINJA_ENV.get_template(template_path)) - - LOGGER.info(f"Loading DSCM template: {template_path}") - else: - # Fallback to generic template if format doesn't match expected pattern - LOGGER.warning(f"Unexpected DSCM resource key format: {resource_key}, using default template") - template_name = '{:s}/edit_config.xml'.format(RE_REMOVE_FILTERS.sub('', resource_key)) - templates.append(JINJA_ENV.get_template(template_name)) + # Use generic pluggable template for all devices (hub and leaf) + # Resource key format: /pluggable/{template_index}/config + template_name = '{:s}/edit_config.xml'.format(RE_REMOVE_FILTERS.sub('', resource_key)) + templates.append(JINJA_ENV.get_template(template_name)) + LOGGER.info(f"Loading DSCM template: {template_name}") data : Dict[str, Any] = json.loads(resource_value) else: diff --git a/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_hub_template.xml b/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config.xml similarity index 100% rename from src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_hub_template.xml rename to src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config.xml diff --git a/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml b/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml deleted file mode 100644 index 4149bccda..000000000 --- a/src/device/service/drivers/openconfig/templates/pluggable/1/config/edit_config_leaf_template.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - {{name}} - - {% if operation is defined and operation != 'delete' %} - - {% if frequency is defined %}{{frequency}}{% endif %} - {% if target_output_power is defined %}{{target_output_power}}{% endif %} - {% if operational_mode is defined %}{{operational_mode}}{% endif %} - - {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} - {% for group in digital_sub_carriers_group %} - - {{group.digital_sub_carriers_group_id}} - - {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} - {% for sub_carrier in group.digital_sub_carrier_id %} - - {{sub_carrier.sub_carrier_id}} - {{sub_carrier.active}} - - {% endfor %} - {% endif %} - - {% endfor %} - {% endif %} - - {% endif %} - - - diff --git a/src/pluggables/service/PluggablesServiceServicerImpl.py b/src/pluggables/service/PluggablesServiceServicerImpl.py index 098c4f9ac..c34b0999f 100644 --- a/src/pluggables/service/PluggablesServiceServicerImpl.py +++ b/src/pluggables/service/PluggablesServiceServicerImpl.py @@ -60,42 +60,24 @@ class PluggablesServiceServicerImpl(PluggablesServiceServicer): LOGGER.info(f"Translated pluggable config to NETCONF format: {netconf_config}") - # Step 2: Extract device IP address from _connect/address config rule - device_address = None - for config_rule in device.device_config.config_rules: # type: ignore - if config_rule.custom.resource_key == '_connect/address': # type: ignore - device_address = config_rule.custom.resource_value # type: ignore - break - - # Step 3: Determine the appropriate template based on device IP address (TODO: This need to be updated later) - if device_address == '10.30.7.7': - template_identifier = 'hub' - elif device_address == '10.30.7.8': - template_identifier = 'leaf' - else: - LOGGER.warning(f"Cannot determine device type from IP address {device_address}, defaulting to hub template") - raise InvalidArgumentException( 'Device IP address', device_address, extra_details='Unknown device IP adress') - - LOGGER.info(f"Using template identifier: {template_identifier} for device {device.name} (IP: {device_address})") - - # Step 4: Create configuration rule with template-specific resource key - # For simplicity, we use a fixed pluggable index of 1 for template lookup - template_index = 1 # TODO: This should be dynamic based on actual pluggable index - resource_key = f"/pluggable/{template_index}/config/{template_identifier}" + # Step 2: Create configuration rule with generic pluggable template + # Use template index 1 for standard pluggable configuration + template_index = 1 + resource_key = f"/pluggable/{template_index}/config" # Create config rule dict and convert to protobuf config_json = json.dumps(netconf_config) config_rule_dict = json_config_rule_set(resource_key, config_json) config_rule = create_config_rule_from_dict(config_rule_dict) - # Step 5: Create a minimal Device object with only the DSCM config rule + # Step 3: Create a minimal Device object with only the DSCM config rule config_device = Device() config_device.device_id.device_uuid.uuid = device_uuid # type: ignore config_device.device_config.config_rules.append(config_rule) # type: ignore - LOGGER.info(f"Created minimal device with config rule: resource_key={resource_key}, template={template_identifier}") + LOGGER.info(f"Created minimal device with config rule: resource_key={resource_key}") - # Step 6: Call ConfigureDevice to push the configuration + # Step 4: Call ConfigureDevice to push the configuration try: device_id = self.device_client.ConfigureDevice(config_device) LOGGER.info(f"Successfully configured device {device_id.device_uuid.uuid}") # type: ignore -- GitLab From c83234cb2d9f8c36374e188a29b3279775ca1803 Mon Sep 17 00:00:00 2001 From: Waleed Akbar Date: Thu, 30 Oct 2025 09:32:19 +0000 Subject: [PATCH 06/13] feat: Add channel_name field to PluggableConfig and update related translation logic. --- proto/pluggables.proto | 1 + src/pluggables/service/config_translator.py | 18 ++++++++++++------ src/pluggables/tests/testmessages.py | 2 ++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/proto/pluggables.proto b/proto/pluggables.proto index 8036a24be..da5e8081b 100644 --- a/proto/pluggables.proto +++ b/proto/pluggables.proto @@ -82,6 +82,7 @@ message PluggableConfig { double center_frequency_mhz = 3; // center frequency in MHz int32 operational_mode = 4; // e.g., 0=off and 1=on int32 line_port = 5; // line port number + string channel_name = 6; // channel name repeated DigitalSubcarrierGroupConfig dsc_groups = 10; } diff --git a/src/pluggables/service/config_translator.py b/src/pluggables/service/config_translator.py index d28e2ae01..4c0e8c765 100644 --- a/src/pluggables/service/config_translator.py +++ b/src/pluggables/service/config_translator.py @@ -30,23 +30,29 @@ def create_config_rule_from_dict(config_rule_dict: Dict[str, Any]) -> ConfigRule def translate_pluggable_config_to_netconf( pluggable_config: PluggableConfig, # type: ignore - component_name: str = "channel-1" # channel-1 for HUB and channel-1/3/5 for LEAF + component_name: str = "channel-1" # Fallback if channel_name not provided (channel-1 for HUB and channel-1/3/5 for LEAF) ) -> Dict[str, Any]: """ Translate PluggableConfig protobuf message to the format expected by NetConfDriver. Args: pluggable_config: PluggableConfig message containing DSC groups and subcarriers - component_name: Name of the optical channel component (default: "channel-1") + component_name: Fallback name if channel_name is not specified in config (default: "channel-1") Returns: Dictionary in the format expected by NetConfDriver templates: """ - + if not pluggable_config or not pluggable_config.dsc_groups: LOGGER.warning("Empty pluggable config provided") return { - "name": component_name, + "name": channel_name, "operation": "delete" } + if hasattr(pluggable_config, 'channel_name') and pluggable_config.channel_name: + channel_name = pluggable_config.channel_name + LOGGER.debug(f"Using channel_name from PluggableConfig: {channel_name}") + else: + channel_name = component_name + LOGGER.debug(f"Using fallback component_name: {channel_name}") if not hasattr(pluggable_config, 'center_frequency_mhz') or pluggable_config.center_frequency_mhz <= 0: raise ValueError("center_frequency_mhz is required and must be greater than 0 in PluggableConfig") @@ -88,14 +94,14 @@ def translate_pluggable_config_to_netconf( # Build the final configuration dictionary config = { - "name": component_name, + "name": channel_name, "frequency": center_frequency_mhz, "operational_mode": operational_mode, "target_output_power": target_output_power, "digital_sub_carriers_group": digital_sub_carriers_groups } - LOGGER.info(f"Translated pluggable config to NETCONF format: component={component_name}, " + LOGGER.info(f"Translated pluggable config to NETCONF format: component={channel_name}, " f"frequency={center_frequency_mhz} MHz, groups={len(digital_sub_carriers_groups)}") return config diff --git a/src/pluggables/tests/testmessages.py b/src/pluggables/tests/testmessages.py index c7a7fe934..c18924bab 100644 --- a/src/pluggables/tests/testmessages.py +++ b/src/pluggables/tests/testmessages.py @@ -57,6 +57,7 @@ def create_pluggable_request( _request.initial_config.operational_mode = 1 # Operational mode _request.initial_config.target_output_power_dbm = -10.0 # Target output power _request.initial_config.line_port = 1 # Line port number + _request.initial_config.channel_name = "channel-1" # Channel name for component # Add sample DSC group configuration dsc_group = _request.initial_config.dsc_groups.add() @@ -202,6 +203,7 @@ def create_configure_pluggable_request( _request.config.operational_mode = 1 # Operational mode _request.config.target_output_power_dbm = -10.0 # Target output power _request.config.line_port = 1 # Line port number + _request.config.channel_name = "channel-1" # Channel name for component # Add DSC group configuration group_1 = _request.config.dsc_groups.add() -- GitLab From 144df730351025c46b5c263154c3524f21aa35df Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 4 Nov 2025 16:45:11 +0000 Subject: [PATCH 07/13] Device component - NETCONF DSCM Driver: - Remove, not needed --- .../drivers/netconf_dscm/NetConfDriver.py | 130 ------------------ .../service/drivers/netconf_dscm/__init__.py | 14 -- .../templates/edit_config_hub_template.xml | 31 ----- .../templates/edit_config_leaf_template.xml | 31 ----- .../netconf_dscm/templates/edit_dscm_hub.xml | 99 ------------- .../templates/edit_dscm_leaves.xml | 101 -------------- .../templates/test_hub_template.xml | 39 ------ 7 files changed, 445 deletions(-) delete mode 100644 src/device/service/drivers/netconf_dscm/NetConfDriver.py delete mode 100644 src/device/service/drivers/netconf_dscm/__init__.py delete mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml delete mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml delete mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml delete mode 100644 src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml delete mode 100644 src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml diff --git a/src/device/service/drivers/netconf_dscm/NetConfDriver.py b/src/device/service/drivers/netconf_dscm/NetConfDriver.py deleted file mode 100644 index 20fcab5f8..000000000 --- a/src/device/service/drivers/netconf_dscm/NetConfDriver.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2022-2025 ETSI 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 ast import Dict -from common.method_wrappers.Decorator import MetricsPool -from device.service.driver_api._Driver import _Driver -from jinja2 import Environment, FileSystemLoader -from typing import Any, List, Tuple, Union -import logging -import os -import subprocess - -DRIVER_NAME = 'dscm-netconf' -METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': DRIVER_NAME}) -LOGGER = logging.getLogger(__name__) -LOGGER.setLevel(logging.INFO) - -class NetConfDriver(_Driver): - def __init__(self, address : str, port : int, **settings) -> None: - super().__init__(DRIVER_NAME, address, port, **settings) - - def GetConfig(self, resources: List[str]) -> List[Tuple[str, Union[Any, None, Exception]]]: # pyright: ignore[reportIncompatibleMethodOverride] - results = [] - for resource_path in resources: - if not resource_path.startswith('/'): - raise ValueError(f"Invalid resource path: {resource_path}. Must start with '/'") - command = [ - "netconf-console2", - f"--host={self.address}", - f"--port={self.port}", - "--tcp", - "--get-config", - f"{resource_path}" - ] - LOGGER.info(f"Executing command: {' '.join(command)}") - try: - result = subprocess.run(command, capture_output=True, text=True, timeout=10) - if result.returncode == 0: - LOGGER.info(f"Get-config successful for {resource_path}") - # LOGGER.info(result.stdout) - results.append(result.stdout) - else: - MSG = 'Exception retrieving {:s}: {:s}' - LOGGER.exception(f"Get-config failed for {resource_path}: {result.stderr}") - results.append(Exception(MSG.format(resource_path, result.stderr))) - except Exception as e: - LOGGER.exception("Command timed out") - results.append(e) - return results - - def SetConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: - results = [] - for node, config in resources: - # rendered_config = self.populated_xml_template(node, config) - self.populated_xml_template(node, config) - command = [ - "netconf-console2", - f"--host={self.address}", - f"--port={self.port}", - "--tcp", - "--edit-config", - f"{node}.xml" # rendered_config - ] - LOGGER.info(f"Executing command: {' '.join(command)}") - try: - result = subprocess.run(command, capture_output=True, text=True, timeout=10) - LOGGER.info(f"Command output: {result.stdout}") - if result.returncode == 0: - LOGGER.info(f"Set-config successful for {node}") - results.append(True) - else: - MSG = 'Exception setting {:s}: {:s}' - LOGGER.exception(f"Set-config failed for {node}: {result.stderr}") - results.append(Exception(MSG.format(node, result.stderr))) - except Exception as e: - LOGGER.exception("Command timed out") - results.append(e) - return results - - - def populated_xml_template(self, node : str, config: Dict): - try: - # Get the directory of this file to locate the template - current_dir = os.path.dirname(os.path.abspath(__file__)) - template_dir = os.path.join(current_dir, 'templates') - # template_dir = 'templates/' - LOGGER.info(f"Template directory: {template_dir}") - - # Set up Jinja2 environment - env = Environment(loader=FileSystemLoader(template_dir)) - if node == 'T2.1': - LOGGER.info("Using hub template: edit_config_hub_template.xml") - # template = env.get_template('test_hub_template.xml') - template = env.get_template('edit_config_hub_template.xml') - elif node in ['T1.1', 'T1.2', 'T1.3']: - template = env.get_template('edit_config_leaf_template.xml') - else: - raise ValueError(f"Unknown node: {node}") - - # Render the template with config values - rendered_xml = template.render(**config) - - LOGGER.info(f"Rendered XML:\n{rendered_xml}") - # return rendered_xml - - # Write to file - output_file = f"{node}.xml" - with open(output_file, 'w') as f: - f.write(rendered_xml) - - LOGGER.info(f"XML template populated and saved to {output_file}") - return True - - except Exception as e: - LOGGER.exception(f"Failed to populate XML template: {e}") - # return False - - diff --git a/src/device/service/drivers/netconf_dscm/__init__.py b/src/device/service/drivers/netconf_dscm/__init__.py deleted file mode 100644 index 3ccc21c7d..000000000 --- a/src/device/service/drivers/netconf_dscm/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2022-2025 ETSI 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/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml b/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml deleted file mode 100644 index 4149bccda..000000000 --- a/src/device/service/drivers/netconf_dscm/templates/edit_config_hub_template.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - {{name}} - - {% if operation is defined and operation != 'delete' %} - - {% if frequency is defined %}{{frequency}}{% endif %} - {% if target_output_power is defined %}{{target_output_power}}{% endif %} - {% if operational_mode is defined %}{{operational_mode}}{% endif %} - - {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} - {% for group in digital_sub_carriers_group %} - - {{group.digital_sub_carriers_group_id}} - - {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} - {% for sub_carrier in group.digital_sub_carrier_id %} - - {{sub_carrier.sub_carrier_id}} - {{sub_carrier.active}} - - {% endfor %} - {% endif %} - - {% endfor %} - {% endif %} - - {% endif %} - - - diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml b/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml deleted file mode 100644 index 4149bccda..000000000 --- a/src/device/service/drivers/netconf_dscm/templates/edit_config_leaf_template.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - {{name}} - - {% if operation is defined and operation != 'delete' %} - - {% if frequency is defined %}{{frequency}}{% endif %} - {% if target_output_power is defined %}{{target_output_power}}{% endif %} - {% if operational_mode is defined %}{{operational_mode}}{% endif %} - - {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} - {% for group in digital_sub_carriers_group %} - - {{group.digital_sub_carriers_group_id}} - - {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} - {% for sub_carrier in group.digital_sub_carrier_id %} - - {{sub_carrier.sub_carrier_id}} - {{sub_carrier.active}} - - {% endfor %} - {% endif %} - - {% endfor %} - {% endif %} - - {% endif %} - - - diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml b/src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml deleted file mode 100644 index 21eb62ebe..000000000 --- a/src/device/service/drivers/netconf_dscm/templates/edit_dscm_hub.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - channel-1 - - - 195000000 - -3.0 - 1 - port-1 - 50.0 - - 1 - 4 - 100 - - 1 - true - - - 2 - true - - - 3 - true - - - 4 - true - - - - 2 - 4 - 100 - - 5 - true - - - 6 - true - - - 7 - true - - - 8 - true - 0.0 - - - - 3 - 4 - 100 - - 9 - true - - - 10 - true - - - 11 - true - - - 12 - true - - - - 4 - 4 - 100 - - 13 - true - - - 14 - true - - - 15 - true - - - 16 - true - - - - - - diff --git a/src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml b/src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml deleted file mode 100644 index 093b25b90..000000000 --- a/src/device/service/drivers/netconf_dscm/templates/edit_dscm_leaves.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - channel-1 - - - 195006250 - -99.0 - 1 - port-1 - 50.0 - - 1 - 4 - 100 - - 1 - true - - - 2 - true - - - 3 - true - - - 4 - true - - - - - - - channel-3 - - - 195018750 - -99.0 - 1 - port-3 - 50.0 - - 1 - 4 - 100 - - 1 - true - - - 2 - true - - - 3 - true - - - 4 - true - - - - - - - channel-5 - - - 195031250 - -99.0 - 1 - port-5 - 50.0 - - 1 - 4 - 100 - - 1 - true - - - 2 - true - - - 3 - true - - - 4 - true - - - - - - diff --git a/src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml b/src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml deleted file mode 100644 index 19a8d2ea8..000000000 --- a/src/device/service/drivers/netconf_dscm/templates/test_hub_template.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - {{ name }} - - {% if operation is defined and operation != 'delete' %} - - {% if frequency is defined %} - {{ frequency }} - {% endif %} - - {% if target_output_power is defined %} - {{ target_output_power }} - {% endif %} - - {% if operational_mode is defined %} - {{ operational_mode }} - {% endif %} - - {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %} - {% for group in digital_sub_carriers_group %} - - {{ group.digital_sub_carriers_group_id }} - - {% if group.digital_sub_carrier_id is defined and group.digital_sub_carrier_id %} - {% for sub_carrier in group.digital_sub_carrier_id %} - - {{ sub_carrier.sub_carrier_id }} - {% if sub_carrier.active %}true{% else %}false{% endif %} - - {% endfor %} - {% endif %} - - {% endfor %} - {% endif %} - - {% endif %} - - - -- GitLab From 32dc8224c1b10f99a851d460f34cbc3830fe813e Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 4 Nov 2025 16:46:40 +0000 Subject: [PATCH 08/13] Test Scripts: - Remove unneeded script for Device NETCONF DSCM Driver --- .../run_tests_locally-device-netconf-dscm.sh | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100755 scripts/run_tests_locally-device-netconf-dscm.sh diff --git a/scripts/run_tests_locally-device-netconf-dscm.sh b/scripts/run_tests_locally-device-netconf-dscm.sh deleted file mode 100755 index e01667e33..000000000 --- a/scripts/run_tests_locally-device-netconf-dscm.sh +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2022-2025 ETSI 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. - - -PROJECTDIR=`pwd` - -cd $PROJECTDIR/src - -python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \ - device/tests/dscm/test_dscm_netconf_hub_leaf.py::test_get_default_hub_config - -python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \ - device/tests/dscm/test_dscm_netconf_hub_leaf.py::test_get_default_leaves_config - -# python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \ -# device/tests/dscm/test_dscm_netconf_hub_leaf.py::test_get_and_remove_topology_context -- GitLab From a0f44c047486cecff13120bfe2bc01fd99a9a752 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 4 Nov 2025 16:50:27 +0000 Subject: [PATCH 09/13] Device component - NETCONF DSCM Driver: - Remove, unneeded files --- .../components/component/config/edit_config.xml | 14 -------------- .../templates/components/component/get.xml | 3 --- .../components/component/optical_channel/get.xml | 11 ----------- 3 files changed, 28 deletions(-) delete mode 100644 src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml delete mode 100644 src/device/service/drivers/openconfig/templates/components/component/get.xml delete mode 100644 src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml diff --git a/src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml b/src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml deleted file mode 100644 index 67ed5d1dd..000000000 --- a/src/device/service/drivers/openconfig/templates/components/component/config/edit_config.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - {{name}} - - {% if operation is defined and operation != 'delete' %} - - {% if frequency is defined %}{{frequency}}{% endif %} - {% if target_output_power is defined %}{{target_output_power}}{% endif %} - {% if operational_mode is defined %}{{operational_mode}}{% endif %} - - {% endif %} - - - diff --git a/src/device/service/drivers/openconfig/templates/components/component/get.xml b/src/device/service/drivers/openconfig/templates/components/component/get.xml deleted file mode 100644 index aa25ed1e3..000000000 --- a/src/device/service/drivers/openconfig/templates/components/component/get.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml b/src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml deleted file mode 100644 index 89250f818..000000000 --- a/src/device/service/drivers/openconfig/templates/components/component/optical_channel/get.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - {% if component_name %} - {{ component_name }} - {% endif %} - - - - - - -- GitLab From a3e0231aff11c551324f0102ccd6e32b161d47e0 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 4 Nov 2025 16:55:53 +0000 Subject: [PATCH 10/13] Pre-merge code cleanup, remove unneeded files --- src/device/service/drivers/__init__.py | 28 ++++++------ src/device/tests/dscm/actual_hub.xml | 21 --------- src/device/tests/dscm/rendered_hub.xml | 60 -------------------------- 3 files changed, 13 insertions(+), 96 deletions(-) delete mode 100644 src/device/tests/dscm/actual_hub.xml delete mode 100644 src/device/tests/dscm/rendered_hub.xml diff --git a/src/device/service/drivers/__init__.py b/src/device/service/drivers/__init__.py index 92fdff911..ba5298292 100644 --- a/src/device/service/drivers/__init__.py +++ b/src/device/service/drivers/__init__.py @@ -98,19 +98,19 @@ if LOAD_ALL_DEVICE_DRIVERS: } ])) -# if LOAD_ALL_DEVICE_DRIVERS: -# from .gnmi_openconfig.GnmiOpenConfigDriver import GnmiOpenConfigDriver # pylint: disable=wrong-import-position -# DRIVERS.append( -# (GnmiOpenConfigDriver, [ -# { -# # Real Packet Router, specifying gNMI OpenConfig Driver => use GnmiOpenConfigDriver -# FilterFieldEnum.DEVICE_TYPE: [ -# DeviceTypeEnum.PACKET_POP, -# DeviceTypeEnum.PACKET_ROUTER, -# ], -# FilterFieldEnum.DRIVER : DeviceDriverEnum.DEVICEDRIVER_GNMI_OPENCONFIG, -# } -# ])) +if LOAD_ALL_DEVICE_DRIVERS: + from .gnmi_openconfig.GnmiOpenConfigDriver import GnmiOpenConfigDriver # pylint: disable=wrong-import-position + DRIVERS.append( + (GnmiOpenConfigDriver, [ + { + # Real Packet Router, specifying gNMI OpenConfig Driver => use GnmiOpenConfigDriver + FilterFieldEnum.DEVICE_TYPE: [ + DeviceTypeEnum.PACKET_POP, + DeviceTypeEnum.PACKET_ROUTER, + ], + FilterFieldEnum.DRIVER : DeviceDriverEnum.DEVICEDRIVER_GNMI_OPENCONFIG, + } + ])) if LOAD_ALL_DEVICE_DRIVERS: from .gnmi_nokia_srlinux.GnmiNokiaSrLinuxDriver import GnmiNokiaSrLinuxDriver # pylint: disable=wrong-import-position @@ -234,7 +234,6 @@ if LOAD_ALL_DEVICE_DRIVERS: # Real Packet Router, specifying OpenConfig Driver => use OpenConfigDriver FilterFieldEnum.DEVICE_TYPE: [ DeviceTypeEnum.OPEN_ROADM, - ], FilterFieldEnum.DRIVER : DeviceDriverEnum.DEVICEDRIVER_OPENROADM, } @@ -250,4 +249,3 @@ if LOAD_ALL_DEVICE_DRIVERS: FilterFieldEnum.DRIVER : DeviceDriverEnum.DEVICEDRIVER_QKD, } ])) - diff --git a/src/device/tests/dscm/actual_hub.xml b/src/device/tests/dscm/actual_hub.xml deleted file mode 100644 index 32067b11e..000000000 --- a/src/device/tests/dscm/actual_hub.xml +++ /dev/null @@ -1,21 +0,0 @@ - -1 -4 -100 - -1 -false - - -2 -false - - -3 -false - - -4 -false - - diff --git a/src/device/tests/dscm/rendered_hub.xml b/src/device/tests/dscm/rendered_hub.xml deleted file mode 100644 index 14a9d37d9..000000000 --- a/src/device/tests/dscm/rendered_hub.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - channel-1 - - - 195000000 - 0.0 - 9 - - 1 - - - 1 - True - - - - 2 - True - - - - 3 - True - - - - 4 - True - - - - - - 1 - - - 5 - True - - - - 6 - True - - - - 7 - True - - - - 8 - True - - - - - - -- GitLab From 43c83ac9ed32988b31ea78304d4749d7583c4e64 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 4 Nov 2025 16:56:12 +0000 Subject: [PATCH 11/13] Device component: - Add missing dependencies in Dockerfile --- src/device/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/device/Dockerfile b/src/device/Dockerfile index e33f4e980..d74263414 100644 --- a/src/device/Dockerfile +++ b/src/device/Dockerfile @@ -82,6 +82,8 @@ COPY src/context/__init__.py context/__init__.py COPY src/context/client/. context/client/ COPY src/monitoring/__init__.py monitoring/__init__.py COPY src/monitoring/client/. monitoring/client/ +COPY src/kpi_manager/__init__.py kpi_manager/__init__.py +COPY src/kpi_manager/client/. kpi_manager/client/ # Clone test mock tools RUN mkdir -p tests/tools/mock_ietf_actn_sdn_ctrl -- GitLab From 0d290dddb5068374479b2cbc6a85c93560e49312 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 4 Nov 2025 16:58:01 +0000 Subject: [PATCH 12/13] Device component: - Remove unneeded Python library --- src/device/requirements.in | 1 - 1 file changed, 1 deletion(-) diff --git a/src/device/requirements.in b/src/device/requirements.in index 0a75ac159..10139bc2c 100644 --- a/src/device/requirements.in +++ b/src/device/requirements.in @@ -27,7 +27,6 @@ Jinja2==3.0.3 libyang==2.8.4 macaddress ncclient==0.6.15 -netconf-console2==3.0.1 numpy<2.0.0 p4runtime==1.3.0 pandas==1.5.* -- GitLab From ecf801eb495186da411c96ff87750b2fbd30b719 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Tue, 4 Nov 2025 17:23:51 +0000 Subject: [PATCH 13/13] NBI component: - Add missing dependencies in Dockerfile --- src/nbi/Dockerfile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/nbi/Dockerfile b/src/nbi/Dockerfile index 1a08ddbe1..1b0d841f3 100644 --- a/src/nbi/Dockerfile +++ b/src/nbi/Dockerfile @@ -77,18 +77,20 @@ COPY src/context/__init__.py context/__init__.py COPY src/context/client/. context/client/ COPY src/device/__init__.py device/__init__.py COPY src/device/client/. device/client/ -COPY src/service/__init__.py service/__init__.py -COPY src/service/client/. service/client/ -COPY src/slice/__init__.py slice/__init__.py -COPY src/slice/client/. slice/client/ +COPY src/osm_client/__init__.py osm_client/__init__.py +COPY src/osm_client/client/. osm_client/client/ +COPY src/pluggables/__init__.py pluggables/__init__.py +COPY src/pluggables/client/. pluggables/client/ COPY src/qkd_app/__init__.py qkd_app/__init__.py COPY src/qkd_app/client/. qkd_app/client/ COPY src/qos_profile/__init__.py qos_profile/__init__.py COPY src/qos_profile/client/. qos_profile/client/ -COPY src/osm_client/__init__.py osm_client/__init__.py -COPY src/osm_client/client/. osm_client/client/ +COPY src/service/__init__.py service/__init__.py +COPY src/service/client/. service/client/ COPY src/simap_connector/__init__.py simap_connector/__init__.py COPY src/simap_connector/client/. simap_connector/client/ +COPY src/slice/__init__.py slice/__init__.py +COPY src/slice/client/. slice/client/ COPY src/vnt_manager/__init__.py vnt_manager/__init__.py COPY src/vnt_manager/client/. vnt_manager/client/ RUN mkdir -p /var/teraflow/tests/tools -- GitLab