Commit 3acc9abd authored by Pablo Armingol's avatar Pablo Armingol
Browse files

Amplifier Impementation with OCM

1) New device png
2) Amplifier management
parent e728dc1c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -49,6 +49,10 @@ class DeviceTypeEnum(Enum):
    XR_CONSTELLATION                = 'xr-constellation'
    QKD_NODE                        = 'qkd-node'
    OPEN_ROADM                      = 'openroadm'
    AMPLIFIER                       = 'amplifier'
    OADM_L                          = 'oadm_l'
    OADM_R                          = 'oadm_r'
    MUX_DEMUX                       = 'mux_demux'

    # ETSI TeraFlowSDN controller
    TERAFLOWSDN_CONTROLLER          = 'teraflowsdn'
+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ RESOURCE_SERVICES = '__services__'
RESOURCE_ACL = '__acl__'
RESOURCE_INVENTORY = '__inventory__'
RESOURCE_RULES = "__rules__"

RESOURCE_PHOTONPATH = "__photonpath__"

class _Driver:
    def __init__(self, name : str, address: str, port: int, **settings) -> None:
+4 −3
Original line number Diff line number Diff line
@@ -110,8 +110,8 @@ class NetconfSessionHandler:
    @RETRY_DECORATOR
    def get(self, filter=None, with_defaults=None): # pylint: disable=redefined-builtin
        with self.__lock:
            if self.__vendor == 'JUNIPER'and not 'component' in str(filter):
                return self.__manager.get_config(source="running", filter=filter, with_defaults=with_defaults)
            if self.__vendor == 'JUNIPER':
                if not 'component' in str(filter): return self.__manager.get_config(source="running", filter=filter, with_defaults=with_defaults)
            else:
                return self.__manager.get(filter=filter, with_defaults=with_defaults)

@@ -319,8 +319,9 @@ class OpenConfigDriver(_Driver):
                try:
                    chk_string(str_resource_name, resource_key, allow_empty=False)
                    str_filter = get_filter(resource_key)
                    #self.__logger.debug('[GetConfig] str_filter = {:s}'.format(str(str_filter)))
                    self.__logger.debug('[GetConfig] str_filter = {:s}'.format(str(str_filter)))
                    if str_filter is None: str_filter = resource_key
                    if self.__netconf_handler.vendor == 'PHOTONPATH' and not 'amplifier' in str(str_filter): continue
                    xml_data = self.__netconf_handler.get(filter=str_filter).data_ele
                    if isinstance(xml_data, Exception): raise xml_data
                    results.extend(parse(resource_key, xml_data))
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ 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_PHOTONPATH             = 'http://photon-path.com/yang/optical-amplifier'

NAMESPACES = {
    'nc'   : NAMESPACE_NETCONF,
@@ -46,4 +47,5 @@ NAMESPACES = {
    'ocrp' : NAMESPACE_ROUTING_POLICY,
    'ocv'  : NAMESPACE_VLAN,
    'ocptr': NAMESPACE_PLATFORM_TRANSCEIVER,
    'ocpp' : NAMESPACE_PHOTONPATH
}
+168 −0
Original line number Diff line number Diff line
# 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 copy, logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES
from .Tools import add_value_from_tag
from lxml import etree

LOGGER = logging.getLogger(__name__)

XPATH_OLS_STATE     = "//ocpp:amplifier-ols/ocpp:state"
XPATH_OLS_AMPLIFIER = "//ocpp:amplifier-ols/ocpp:optical-amplifier/ocpp:amplifiers/ocpp:amplifier/ocpp:config"
XPATH_OLS_CHANNEL   = "//ocpp:amplifier-ols/ocpp:channel-monitors/ocpp:channel-monitor/ocpp:config"
XPATH_GRID_CHANNEL  = "//ocpp:flex-grid-channels/ocpp:flex-grid-channel/ocpp:state" 
def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
    response = []
    for xml_ols_state in xml_data.xpath(XPATH_OLS_STATE, namespaces=NAMESPACES):
        ols = {}
        # LOGGER.info('xml_ols_state = {:s}'.format(str(ET.tostring(xml_ols_state))))

        ols_name = xml_ols_state.find('ocpp:mfg-name', namespaces=NAMESPACES)
        if not ols_name is None: add_value_from_tag(ols, 'mfg-name', ols_name)

        ols_date = xml_ols_state.find('ocpp:mfg-date', namespaces=NAMESPACES)
        if not ols_date is None: add_value_from_tag(ols, 'mfg-date', ols_date)

        ols_hw = xml_ols_state.find('ocpp:hardware-version', namespaces=NAMESPACES)
        if not ols_hw is None: add_value_from_tag(ols, 'hardware-version', ols_hw)

        ols_fw = xml_ols_state.find('ocpp:firmware-version', namespaces=NAMESPACES)
        if not ols_fw is None: add_value_from_tag(ols, 'firmware-version', ols_fw)

        ols_sw = xml_ols_state.find('ocpp:software-version', namespaces=NAMESPACES)
        if not ols_sw is None: add_value_from_tag(ols, 'software-version', ols_sw)

        ols_type = xml_ols_state.find('ocpp:type', namespaces=NAMESPACES)
        if not ols_type is None: add_value_from_tag(ols, 'type', ols_type)

        ols_serial = xml_ols_state.find('ocpp:serial-no', namespaces=NAMESPACES)
        if not ols_serial is None: add_value_from_tag(ols, 'serial-no', ols_serial)

        ols_part = xml_ols_state.find('ocpp:part-no', namespaces=NAMESPACES)
        if not ols_part is None: add_value_from_tag(ols, 'part-no', ols_part)

        ols_model = xml_ols_state.find('ocpp:model-name', namespaces=NAMESPACES)
        if not ols_model is None: add_value_from_tag(ols, 'model-name', ols_model)

        ols_status = xml_ols_state.find('ocpp:oper-status', namespaces=NAMESPACES)
        if not ols_status is None: add_value_from_tag(ols, 'oper-status', ols_status)

        response.append(('/ols[{:s}]'.format(str(ols_name.text)), ols))
    
    for xml_amplifier in xml_data.xpath(XPATH_OLS_AMPLIFIER, namespaces=NAMESPACES):
        ols = {}
        # LOGGER.info('xml_amplifier = {:s}'.format(str(ET.tostring(xml_amplifier))))

        amp_name = xml_amplifier.find('ocpp:name', namespaces=NAMESPACES)
        if not amp_name is None: add_value_from_tag(ols, 'name', amp_name)

        amp_type = xml_amplifier.find('ocpp:type', namespaces=NAMESPACES)
        if not amp_type is None: add_value_from_tag(ols, 'type', amp_type)

        amp_target = xml_amplifier.find('ocpp:target-gain', namespaces=NAMESPACES)
        if not amp_target is None: add_value_from_tag(ols, 'target-gain', amp_target)

        amp_min = xml_amplifier.find('ocpp:min-gain', namespaces=NAMESPACES)
        if not amp_min is None: add_value_from_tag(ols, 'min-gain', amp_min)

        amp_max = xml_amplifier.find('ocpp:max-gain', namespaces=NAMESPACES)
        if not amp_max is None: add_value_from_tag(ols, 'max-gain', amp_max)

        amp_tilt = xml_amplifier.find('ocpp:target-gain-tilt', namespaces=NAMESPACES)
        if not amp_tilt is None: add_value_from_tag(ols, 'target-gain-tilt', amp_tilt)

        amp_gain = xml_amplifier.find('ocpp:gain-range', namespaces=NAMESPACES)
        if not amp_gain is None: add_value_from_tag(ols, 'gain-range', amp_gain)

        amp_mode = xml_amplifier.find('ocpp:amp-mode', namespaces=NAMESPACES)
        if not amp_mode is None: add_value_from_tag(ols, 'amp-mode', amp_mode)

        amp_power = xml_amplifier.find('ocpp:target-output-power', namespaces=NAMESPACES)
        if not amp_power is None: add_value_from_tag(ols, 'target-output-power', amp_power)

        amp_max_power = xml_amplifier.find('ocpp:target-output-power', namespaces=NAMESPACES)
        if not amp_max_power is None: add_value_from_tag(ols, 'target-output-power', amp_max_power)

        amp_enabled = xml_amplifier.find('ocpp:enabled', namespaces=NAMESPACES)
        if not amp_enabled is None: add_value_from_tag(ols, 'enabled', amp_enabled)

        amp_max_out_p = xml_amplifier.find('ocpp:max-output-power', namespaces=NAMESPACES)
        if not amp_max_out_p is None: add_value_from_tag(ols, 'max-output-power', amp_max_out_p)

        amp_in_p = xml_amplifier.find('ocpp:ingress-port', namespaces=NAMESPACES)
        if not amp_in_p is None: add_value_from_tag(ols, 'ingress-port', amp_in_p)

        amp_out_p = xml_amplifier.find('ocpp:egress-port', namespaces=NAMESPACES)
        if not amp_out_p is None: add_value_from_tag(ols, 'egress-port', amp_out_p)

        amp_actual_gain = xml_amplifier.find("ocpp:actual-gain/ocpp:instant", namespaces=NAMESPACES)
        add_value_from_tag(ols, 'actual-gain', amp_actual_gain)

        amp_in_p_t = xml_amplifier.find('ocpp:input-power-total/ocpp:instant', namespaces=NAMESPACES)
        if not amp_in_p_t is None: add_value_from_tag(ols, 'input-power-total', amp_in_p_t)

        amp_in_p_c = xml_amplifier.find('ocpp:input-power-c-band/ocpp:instant', namespaces=NAMESPACES)
        if not amp_in_p_c is None: add_value_from_tag(ols, 'input-power-c', amp_in_p_c)

        amp_in_p_l = xml_amplifier.find('ocpp:input-power-l-band/ocpp:instant', namespaces=NAMESPACES)
        if not amp_in_p_l is None: add_value_from_tag(ols, 'input-power-l', amp_in_p_l)

        amp_out_p_t = xml_amplifier.find('ocpp:output-power-total/ocpp:instant', namespaces=NAMESPACES)
        if not amp_out_p_t is None: add_value_from_tag(ols, 'output-power-total', amp_out_p_t)

        amp_out_p_c = xml_amplifier.find('ocpp:output-power-c-band/ocpp:instant', namespaces=NAMESPACES)
        if not amp_out_p_c is None: add_value_from_tag(ols, 'output-power-c', amp_out_p_c)

        amp_out_p_l = xml_amplifier.find('ocpp:output-power-l-band/ocpp:instant', namespaces=NAMESPACES)
        if not amp_out_p_l is None: add_value_from_tag(ols, 'output-power-l', amp_out_p_l)

        amp_las_b = xml_amplifier.find('ocpp:laser-bias-current/ocpp:instant', namespaces=NAMESPACES)
        if not amp_las_b is None: add_value_from_tag(ols, 'laser-bias', amp_las_b)

        response.append(('/amplifier[{:s}]'.format(str(amp_name.text)), ols))

    for xml_channel in xml_data.xpath(XPATH_OLS_CHANNEL, namespaces=NAMESPACES):
        channel = {}
        # LOGGER.info('xml_channel = {:s}'.format(str(ET.tostring(xml_channel))))

        channel_name = xml_channel.find('ocpp:name', namespaces=NAMESPACES)
        if not channel_name is None: add_value_from_tag(channel, 'name', channel_name)

        channel_port = xml_channel.find('ocpp:monitor-port', namespaces=NAMESPACES)
        if not channel_port is None: add_value_from_tag(channel, 'monitor-port', channel_port)

        channel_enabled = xml_channel.find('ocpp:enabled', namespaces=NAMESPACES)
        if not channel_enabled is None: add_value_from_tag(channel, 'enabled', channel_enabled)

        response.append(('amplifier/channel/{:s}'.format(str(channel_name.text)), channel))

        for xml_grid_channel in xml_channel.xpath(XPATH_GRID_CHANNEL, namespaces=NAMESPACES):
            grid = {}
            channel_index = xml_grid_channel.find('ocpp:index', namespaces=NAMESPACES)
            if not channel_index is None: add_value_from_tag(grid, 'index', channel_index)

            channel_lower = xml_grid_channel.find('ocpp:lower-frequency', namespaces=NAMESPACES)
            if not channel_lower is None: add_value_from_tag(grid, 'lower-frequency', channel_lower)

            channel_upper = xml_grid_channel.find('ocpp:upper-frequency', namespaces=NAMESPACES)
            if not channel_upper is None:  add_value_from_tag(grid, 'upper-frequency', channel_upper)

            channel_pow = xml_grid_channel.find('ocpp:power', namespaces=NAMESPACES)
            if not channel_pow is None:  add_value_from_tag(grid, 'power', channel_pow, cast = float)

            response.append(('amplifier/channel[{:s}]/flex_grid[{:s}]'.format(str(channel_name.text),str(channel_index.text)), grid))

    return response
Loading