Commit 08cb94c6 authored by Pablo Armingol's avatar Pablo Armingol
Browse files

Update NBI + DEVICE

NBI:
* New NBI for IPoWDM services

DEVICE:
* Management of IPoWDM services in Emulated driver
* Management of IPoWDM services in ietf_l3vpn driver
parent bf9f7c11
Loading
Loading
Loading
Loading
+82 −30
Original line number Original line Diff line number Diff line
@@ -25,7 +25,8 @@ from device.service.driver_api._Driver import _Driver
from device.service.driver_api.AnyTreeTools import TreeNode, dump_subtree, get_subnode, set_subnode_value
from device.service.driver_api.AnyTreeTools import TreeNode, dump_subtree, get_subnode, set_subnode_value
from .Constants import SPECIAL_RESOURCE_MAPPINGS
from .Constants import SPECIAL_RESOURCE_MAPPINGS
from .SyntheticSamplingParameters import SyntheticSamplingParameters, do_sampling
from .SyntheticSamplingParameters import SyntheticSamplingParameters, do_sampling
from .Tools import compose_resource_endpoint
from .Tools import compose_resource_endpoint,connect_to_xr_agent
import requests


LOGGER = logging.getLogger(__name__)
LOGGER = logging.getLogger(__name__)


@@ -38,6 +39,7 @@ class EmulatedDriver(_Driver):
    def __init__(self, address : str, port : int, **settings) -> None:
    def __init__(self, address : str, port : int, **settings) -> None:
        super().__init__(DRIVER_NAME, address, port, **settings)
        super().__init__(DRIVER_NAME, address, port, **settings)
        self.__lock = threading.Lock()
        self.__lock = threading.Lock()
        self.__address = address
        self.__initial = TreeNode('.')
        self.__initial = TreeNode('.')
        self.__running = TreeNode('.')
        self.__running = TreeNode('.')
        self.__subscriptions = TreeNode('.')
        self.__subscriptions = TreeNode('.')
@@ -117,6 +119,10 @@ class EmulatedDriver(_Driver):
        chk_type('resources', resources, list)
        chk_type('resources', resources, list)
        if len(resources) == 0: return []
        if len(resources) == 0: return []
        results = []
        results = []
        if 'ipowdm_ruleset' in str(resources):
            connect_to_xr_agent(resources)
            results.append(True)
        else:
            resolver = anytree.Resolver(pathattr='name')
            resolver = anytree.Resolver(pathattr='name')
            with self.__lock:
            with self.__lock:
                for i,resource in enumerate(resources):
                for i,resource in enumerate(resources):
@@ -131,12 +137,58 @@ class EmulatedDriver(_Driver):
                        LOGGER.exception('Exception validating {:s}: {:s}'.format(str_resource_name, str(resource_key)))
                        LOGGER.exception('Exception validating {:s}: {:s}'.format(str_resource_name, str(resource_key)))
                        results.append(e) # if validation fails, store the exception
                        results.append(e) # if validation fails, store the exception
                        continue
                        continue

                    try:
                    try:
                        resource_value = json.loads(resource_value)
                        resource_value = json.loads(resource_value)
                    except: # pylint: disable=bare-except
                    except: # pylint: disable=bare-except
                        pass
                        pass


                    if resource_key.startswith('/ipowdm/service/'):
                        LOGGER.info('[%s] Legacy IPoWDM Service Provisioning: Payload=%s', self.__address, str(resource_value))
                    elif resource_key.startswith('/ipowdm/l3nm/'):
                        LOGGER.info('[%s] L3NM Service Provisioning: Payload=%s', self.__address, str(resource_value))
                    elif resource_key.startswith('/ipowdm/pluggables/'):
                        LOGGER.info('[%s] Pluggables Service Provisioning: Payload=%s', self.__address, str(resource_value))
                        try:
                            key_parts = resource_key.split('/')
                            if len(key_parts) >= 5:
                                service_uuid_raw = key_parts[3]
                                # Normalize UUID: if serviceId contains '-pluggable-', take the part before it
                                if "-pluggable-" in service_uuid_raw:
                                     service_uuid = service_uuid_raw.split("-pluggable-")[0]
                                else:
                                     service_uuid = service_uuid_raw

                                if not hasattr(EmulatedDriver, 'pluggables_pending'):
                                    EmulatedDriver.pluggables_pending = {}

                                if service_uuid in EmulatedDriver.pluggables_pending:
                                    stored_payload = EmulatedDriver.pluggables_pending.pop(service_uuid)
                                    current_payload = resource_value

                                    def format_entry(payload):
                                        config = payload.get('config', {})
                                        return {
                                            'uuid': payload.get('device'),
                                            'power': config.get('target-output-power', 0.0),
                                            'frequency': config.get('frequency', 0.0)
                                        }
                                    combined_data = [
                                        {'src': format_entry(stored_payload)},
                                        {'dst': format_entry(current_payload)}
                                    ]
                                    LOGGER.info('[%s] Pluggables Service Provisioning Aggregated: %s', self.__address, json.dumps(combined_data, indent=2))
                                    # TODO Dynamic IP
                                    url = "http://192.168.88.17:9849/api-v0/transponders"
                                    headers = {'Content-Type': 'application/json'}
                                    response = requests.post(url, json=combined_data, headers=headers)
                                    LOGGER.info('[%s] Pluggables Service Provisioning Response: %s', self.__address, str(response.text))
                                else:
                                    EmulatedDriver.pluggables_pending[service_uuid] = resource_value
                                    LOGGER.debug('[%s] Pluggables Service Partial Provisioning stored for %s', self.__address, service_uuid)
                        except Exception as e:
                            LOGGER.warning("Error processing Pluggables aggregation: %s", str(e))
                            LOGGER.info('[%s] Pluggables Service Provisioning: Payload=%s', self.__address, str(resource_value))

                    set_subnode_value(resolver, self.__running, resource_path, resource_value)
                    set_subnode_value(resolver, self.__running, resource_path, resource_value)


                    match = RE_GET_ENDPOINT_FROM_INTERFACE.match(resource_key)
                    match = RE_GET_ENDPOINT_FROM_INTERFACE.match(resource_key)
+26 −1
Original line number Original line Diff line number Diff line
@@ -12,12 +12,14 @@
# See the License for the specific language governing permissions and
# See the License for the specific language governing permissions and
# limitations under the License.
# limitations under the License.


import json
import logging
import logging
from typing import Any, Dict, Optional, Tuple
import requests
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from common.type_checkers.Checkers import chk_attribute, chk_string, chk_type
from common.type_checkers.Checkers import chk_attribute, chk_string, chk_type
from device.service.driver_api._Driver import RESOURCE_ENDPOINTS
from device.service.driver_api._Driver import RESOURCE_ENDPOINTS
from .Constants import SPECIAL_RESOURCE_MAPPINGS
from .Constants import SPECIAL_RESOURCE_MAPPINGS
from typing import Any, Dict, Optional, Tuple


LOGGER = logging.getLogger(__name__)
LOGGER = logging.getLogger(__name__)


@@ -107,3 +109,26 @@ def compose_resource_endpoint(endpoint_data : Dict[str, Any]) -> Optional[Tuple[
    except: # pylint: disable=bare-except
    except: # pylint: disable=bare-except
        LOGGER.exception('Problem composing endpoint({:s})'.format(str(endpoint_data)))
        LOGGER.exception('Problem composing endpoint({:s})'.format(str(endpoint_data)))
        return None
        return None

# TODO Dynamic IP
def connect_to_xr_agent(resources):
    rule_set = resources[0][1]['rule_set']
    nodes = [
        {'src': {
            'uuid': rule_set['src'][0]['uuid'],
            'power': rule_set['src'][0]['power'],
            'frequency': rule_set['src'][0]['frequency']
        }},
        {'dst': {
            'uuid': rule_set['dst'][0]['uuid'],
            'power': rule_set['dst'][0]['power'],
            'frequency': rule_set['dst'][0]['frequency']
        }}
    ]
    url = "http://192.168.88.17:9849/api-v0/transponders"
    headers = {
            "Content-Type": "application/json",
            "Expect": ""
        }
    json_data = json.dumps(nodes)
    requests.post(url, data=json_data, headers=headers, timeout=10)
+7 −1
Original line number Original line Diff line number Diff line
@@ -190,10 +190,16 @@ class IetfL3VpnDriver(_Driver):
        if len(resources) == 0: return results
        if len(resources) == 0: return results
        with self.__lock:
        with self.__lock:
            if 'ipowdm' in str(resources):
            if 'ipowdm' in str(resources):
                scheme = self.settings.get('scheme', 'http')
                controller_url = f"{scheme}://{self.address}:{self.port}"
                LOGGER.info('=' * 80)
                LOGGER.info('IPoWDM SERVICE RECEIVED')
                LOGGER.info('=' * 80)

                for resource in resources:
                for resource in resources:
                    if 'ipowdm' in str(resource):
                    if 'ipowdm' in str(resource):
                        try:
                        try:
                            create_request(resource)
                            create_request(resource, controller_url)
                            LOGGER.info('Request created successfully')
                            LOGGER.info('Request created successfully')
                            results.append((resource, True))
                            results.append((resource, True))
                        except Exception as e:
                        except Exception as e:
+3 −2
Original line number Original line Diff line number Diff line
@@ -144,7 +144,8 @@ class TfsApiClient(RestApiClient):
                cr_rk : str = cr['custom']['resource_key']
                cr_rk : str = cr['custom']['resource_key']
                if not cr_rk.startswith('/endpoints/endpoint['): continue
                if not cr_rk.startswith('/endpoints/endpoint['): continue
                settings = json.loads(cr['custom']['resource_value'])
                settings = json.loads(cr['custom']['resource_value'])
                ep_name = settings['name']
                ep_name = settings.get('name', settings.get('uuid'))
                if ep_name:
                    config_rule_dict[ep_name] = settings
                    config_rule_dict[ep_name] = settings


            for json_endpoint in json_device['device_endpoints']:
            for json_endpoint in json_device['device_endpoints']:
+27 −7
Original line number Original line Diff line number Diff line
@@ -3,24 +3,44 @@
        {
        {
            "service_id": {
            "service_id": {
                "context_id": {"context_uuid": {"uuid": "admin"}},
                "context_id": {"context_uuid": {"uuid": "admin"}},
                "service_uuid": {"uuid": "IPoWDM"}
                "service_uuid": {"uuid": "644c4aa6-c2e2-4db0-9d6e-869522c4141c"}
            },
            },
            "service_type": 12,
            "service_type": 12,
            "service_status": {"service_status": 1},
            "service_status": {"service_status": 1},
            "service_endpoint_ids": [
            "service_endpoint_ids": [
                {"device_id": {"device_uuid": {"uuid": "IP1"}},"endpoint_uuid": {"uuid": "PORT-xe4"}},
                {"device_id": {"device_uuid": {"uuid": "Phoenix1"}},"endpoint_uuid": {"uuid": "PORT-xe4"}},
                {"device_id": {"device_uuid": {"uuid": "IP2"}},"endpoint_uuid": {"uuid": "PORT-xe4"}}
                {"device_id": {"device_uuid": {"uuid": "Phoenix2"}},"endpoint_uuid": {"uuid": "PORT-xe4"}}
            ],
            ],
            "service_constraints": [],
            "service_constraints": [],
            "service_config": {"config_rules": [
            "service_config": {"config_rules": [
                {"action": 1, "ipowdm": {
                {"action": 1, "ipowdm": {
                    "endpoint_id": {
                    "endpoint_id": {
                        "device_id": {"device_uuid": {"uuid": "IP1"}},
                        "device_id": {"device_uuid": {"uuid": "Phoenix1"}},
                        "endpoint_uuid": {"uuid": "PORT-xe4"}
                        "endpoint_uuid": {"uuid": "PORT-xe4"}
                    },
                    },
                    "rule_set": {
                    "rule_set": {
                        "src"  : [],
                                "src": [
                        "dst"  : []
                                    {
                                        "uuid": "Phoenix-1",
                                        "ip_address": "10.10.1.1",
                                        "ip_mask": "/24",
                                        "vlan_id": 100,
                                        "power": 0.0,
                                        "frequency": 194700.0
                                    }
                                ],
                                "dst": [
                                    {
                                        "uuid": "Phoenix-2",
                                        "ip_address": "10.10.2.1",
                                        "ip_mask": "/24",
                                        "vlan_id": 100,
                                        "power": 0.0,
                                        "frequency": 194700.0
                                    }
                                ],
                                "bw": 100,
                                "uuid": "644c4aa6-c2e2-4db0-9d6e-869522c4141c"
                            }
                            }
                }}
                }}
            ]}
            ]}
Loading