Commit 144df730 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Device component - NETCONF DSCM Driver:

- Remove, not needed
parent a2b6f2fe
Loading
Loading
Loading
Loading
+0 −130
Original line number Diff line number Diff line
# 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

+0 −14
Original line number Diff line number Diff line
# 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.
+0 −31
Original line number Diff line number Diff line
<components xmlns="http://openconfig.net/yang/platform">
    <component{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
        <name>{{name}}</name>
        <optical-channel xmlns="http://openconfig.net/yang/terminal-device-digital-subcarriers">
            {% if operation is defined and operation != 'delete' %}
            <config>
                {% if frequency is defined %}<frequency>{{frequency}}</frequency>{% endif %}
                {% if target_output_power is defined %}<target-output-power>{{target_output_power}}</target-output-power>{% endif %}
                {% if operational_mode is defined %}<operational-mode>{{operational_mode}}</operational-mode>{% endif %}

                {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %}
                    {% for group in digital_sub_carriers_group %}
                    <digital-subcarriers-group>
                        <digital-subcarriers-group-id>{{group.digital_sub_carriers_group_id}}</digital-subcarriers-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 %}
                            <digital-subcarrier-id>
                                <subcarrier-id>{{sub_carrier.sub_carrier_id}}</subcarrier-id>
                                <active>{{sub_carrier.active}}</active>
                            </digital-subcarrier-id>
                            {% endfor %}
                        {% endif %}
                    </digital-subcarriers-group>
                    {% endfor %}
                {% endif %}
            </config>
            {% endif %}
        </optical-channel>
    </component>
</components>
+0 −31
Original line number Diff line number Diff line
<components xmlns="http://openconfig.net/yang/platform">
    <component{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
        <name>{{name}}</name>
        <optical-channel xmlns="http://openconfig.net/yang/terminal-device-digital-subcarriers">
            {% if operation is defined and operation != 'delete' %}
            <config>
                {% if frequency is defined %}<frequency>{{frequency}}</frequency>{% endif %}
                {% if target_output_power is defined %}<target-output-power>{{target_output_power}}</target-output-power>{% endif %}
                {% if operational_mode is defined %}<operational-mode>{{operational_mode}}</operational-mode>{% endif %}

                {% if digital_sub_carriers_group is defined and digital_sub_carriers_group %}
                    {% for group in digital_sub_carriers_group %}
                    <digital-subcarriers-group>
                        <digital-subcarriers-group-id>{{group.digital_sub_carriers_group_id}}</digital-subcarriers-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 %}
                            <digital-subcarrier-id>
                                <subcarrier-id>{{sub_carrier.sub_carrier_id}}</subcarrier-id>
                                <active>{{sub_carrier.active}}</active>
                            </digital-subcarrier-id>
                            {% endfor %}
                        {% endif %}
                    </digital-subcarriers-group>
                    {% endfor %}
                {% endif %}
            </config>
            {% endif %}
        </optical-channel>
    </component>
</components>
+0 −99
Original line number Diff line number Diff line
<components xmlns="http://openconfig.net/yang/platform">
  <component>
    <name>channel-1</name>
    <optical-channel xmlns="http://openconfig.net/yang/terminal-device-digital-subcarriers">
      <config>
        <frequency>195000000</frequency>
        <target-output-power>-3.0</target-output-power>
        <operational-mode>1</operational-mode>
        <line-port>port-1</line-port>
        <digital-subcarrier-spacing>50.0</digital-subcarrier-spacing>
        <digital-subcarriers-group>
          <digital-subcarriers-group-id>1</digital-subcarriers-group-id>
          <number-of-digital-subcarriers>4</number-of-digital-subcarriers>
          <digital-subcarrier-group-size>100</digital-subcarrier-group-size>
          <digital-subcarrier-id>
            <subcarrier-id>1</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>2</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>3</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>4</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
        </digital-subcarriers-group>
        <digital-subcarriers-group>
  	    <digital-subcarriers-group-id>2</digital-subcarriers-group-id>
          <number-of-digital-subcarriers>4</number-of-digital-subcarriers>
          <digital-subcarrier-group-size>100</digital-subcarrier-group-size>
          <digital-subcarrier-id>
            <subcarrier-id>5</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>6</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>7</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>8</subcarrier-id>
            <active>true</active>
            <digital-subcarrier-output-power>0.0</digital-subcarrier-output-power>
          </digital-subcarrier-id>
        </digital-subcarriers-group>
        <digital-subcarriers-group>
          <digital-subcarriers-group-id>3</digital-subcarriers-group-id>
          <number-of-digital-subcarriers>4</number-of-digital-subcarriers>
          <digital-subcarrier-group-size>100</digital-subcarrier-group-size>
          <digital-subcarrier-id>
            <subcarrier-id>9</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>10</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>11</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>12</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
        </digital-subcarriers-group>
        <digital-subcarriers-group>
          <digital-subcarriers-group-id>4</digital-subcarriers-group-id>
          <number-of-digital-subcarriers>4</number-of-digital-subcarriers>
          <digital-subcarrier-group-size>100</digital-subcarrier-group-size>
          <digital-subcarrier-id>
            <subcarrier-id>13</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>14</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>15</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
          <digital-subcarrier-id>
            <subcarrier-id>16</subcarrier-id>
            <active>true</active>
          </digital-subcarrier-id>
        </digital-subcarriers-group>
      </config>
    </optical-channel>
  </component>
</components>
Loading