Commit 0d52683a authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Interdomain component:

- AbstractDevice: Improved formatting in method to_json()
- AbstractDevice: Activated addition of devices to interdomain topology
- AbstractDevice: Corrected default topology for abstract device endpoints
- AbstractLink: Improved formatting in method to_json()
- AbstractLink: Activated addition of links to interdomain topology
- AbstractLink: Updated internal data structures
- TopologyAbstractor: Enhanced log and exception messages
- TopologyAbstractor: Resolved variable obfuscation
- TopologyAbstractor: Minor cosmetic changes
- TopologyAbstractor: Enhanced inference of abstract links in device events
parent 16134c8a
Loading
Loading
Loading
Loading
+19 −15
Original line number Diff line number Diff line
@@ -14,13 +14,14 @@

import copy, logging
from typing import Dict, Optional
from common.Constants import DEFAULT_CONTEXT_NAME, INTERDOMAIN_TOPOLOGY_NAME
from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME
from common.DeviceTypes import DeviceTypeEnum
from common.proto.context_pb2 import Device, DeviceDriverEnum, DeviceOperationalStatusEnum, EndPoint
from common.proto.context_pb2 import ContextId, Device, DeviceDriverEnum, DeviceOperationalStatusEnum, EndPoint
from common.tools.context_queries.CheckType import (
    device_type_is_datacenter, device_type_is_network, endpoint_type_is_border)
from common.tools.context_queries.Device import get_device
from common.tools.context_queries.Device import add_device_to_topology, get_device
from common.tools.grpc.Tools import grpc_message_to_json
from common.tools.object_factory.Context import json_context_id
from common.tools.object_factory.Device import json_device
from context.client.ContextClient import ContextClient
from .Tools import replace_device_uuids_by_names
@@ -55,7 +56,13 @@ class AbstractDevice:
            'device_name' : self.__device_name,
            'device_type' : self.__device_type,
            'device' : grpc_message_to_json(self.__device),
            'device_endpoint_to_abstract' : self.__device_endpoint_to_abstract,
            'device_endpoint_to_abstract' : {
                device_name : {
                    endpoint_name : grpc_message_to_json(endpoint)
                    for endpoint_name, endpoint in endpoints.items()
                }
                for device_name, endpoints in self.__device_endpoint_to_abstract.items()
            },
            'abstract_endpoint_to_device' : self.__abstract_endpoint_to_device,
        }

@@ -81,16 +88,13 @@ class AbstractDevice:
        else:
            self._load_existing(local_interdomain_device)

        #is_datacenter = device_type_is_datacenter(self.__device_type)
        #is_network = device_type_is_network(self.__device_type)
        #if is_datacenter or is_network:
        #    # Add abstract device to topologies [INTERDOMAIN_TOPOLOGY_NAME]
        #    admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
        #    topology_uuids = [INTERDOMAIN_TOPOLOGY_NAME]
        #    for topology_uuid in topology_uuids:
        #        # This action is done automatically; commented out by now.
        #        add_device_to_topology(
        #            self.__context_client, admin_context_id, topology_uuid, self.__device_name)
        is_datacenter = device_type_is_datacenter(self.__device_type)
        is_network = device_type_is_network(self.__device_type)
        if is_datacenter or is_network:
            # Add abstract device to INTERDOMAIN_TOPOLOGY_NAME topology
            admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
            topology_name = INTERDOMAIN_TOPOLOGY_NAME
            add_device_to_topology(self.__context_client, admin_context_id, topology_name, self.__device_name)

        # seems not needed; to be removed in future releases
        #if is_datacenter and create_abstract_device:
@@ -164,7 +168,7 @@ class AbstractDevice:

    def _add_endpoint(self, device_name : str, endpoint_name : str, endpoint_type : str) -> EndPoint:
        interdomain_endpoint = self.__device.device_endpoints.add()
        interdomain_endpoint.endpoint_id.topology_id.topology_uuid.uuid = INTERDOMAIN_TOPOLOGY_NAME
        interdomain_endpoint.endpoint_id.topology_id.topology_uuid.uuid = DEFAULT_TOPOLOGY_NAME
        interdomain_endpoint.endpoint_id.topology_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
        interdomain_endpoint.endpoint_id.device_id.device_uuid.uuid = self.__device.name
        interdomain_endpoint.endpoint_id.endpoint_uuid.uuid = endpoint_name
+32 −21
Original line number Diff line number Diff line
@@ -15,8 +15,10 @@
import copy, logging
from typing import Dict, List, Optional, Tuple
from common.Constants import DEFAULT_CONTEXT_NAME, INTERDOMAIN_TOPOLOGY_NAME
from common.proto.context_pb2 import EndPointId, Link
from common.tools.context_queries.Link import get_link
from common.proto.context_pb2 import ContextId, EndPointId, Link
from common.tools.context_queries.Link import add_link_to_topology, get_link
from common.tools.grpc.Tools import grpc_message_to_json
from common.tools.object_factory.Context import json_context_id
from common.tools.object_factory.Link import json_link
from context.client.ContextClient import ContextClient
from .Tools import replace_link_uuids_by_names
@@ -39,14 +41,20 @@ class AbstractLink:
        self.__link_name : str = link_name
        self.__link : Optional[Link] = None

        # Dict[(device_name, endpoint_name), abstract EndPointId]
        self.__device_endpoint_to_abstract : Dict[Tuple[str, str], EndPointId] = dict()
        # Dict[device_name, Dict[endpoint_name, abstract EndPointId]]
        self.__device_endpoint_to_abstract : Dict[str, Dict[str, EndPointId]] = dict()

    def to_json(self) -> Dict:
        return {
            'link_name' : self.__link_name,
            'link' : self.__link,
            'device_endpoint_to_abstract' : self.__device_endpoint_to_abstract,
            'link' : grpc_message_to_json(self.__link),
            'device_endpoint_to_abstract' : {
                device_name : {
                    endpoint_name : grpc_message_to_json(endpoint_id)
                    for endpoint_name, endpoint_id in endpoint_ids.items()
                }
                for device_name, endpoint_ids in self.__device_endpoint_to_abstract.items()
            },
        }

    @property
@@ -80,13 +88,10 @@ class AbstractLink:
        else:
            self._load_existing(local_interdomain_link)

        ## Add abstract link to topologies [INTERDOMAIN_TOPOLOGY_NAME]
        #admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
        #topology_uuids = [INTERDOMAIN_TOPOLOGY_NAME]
        #for topology_uuid in topology_uuids:
        #    # This action is done automatically; commented out by now.
        #    add_link_to_topology(
        #        self.__context_client, admin_context_id, topology_uuid, self.__link_name)
        # Add abstract link to INTERDOMAIN_TOPOLOGY_NAME topology
        admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
        topology_name = INTERDOMAIN_TOPOLOGY_NAME
        add_link_to_topology(self.__context_client, admin_context_id, topology_name, self.__link_name)

        return create_abstract_link

@@ -106,7 +111,8 @@ class AbstractLink:
        for endpoint_id in self.__link.link_endpoint_ids:
            device_name = endpoint_id.device_id.device_uuid.uuid
            endpoint_name = endpoint_id.endpoint_uuid.uuid
            self.__device_endpoint_to_abstract.setdefault((device_name, endpoint_name), endpoint_id)
            endpoints = self.__device_endpoint_to_abstract.setdefault(device_name, dict())
            endpoints.setdefault(endpoint_name, endpoint_id)

    def _add_endpoint(self, device_name : str, endpoint_name : str) -> None:
        endpoint_id = self.__link.link_endpoint_ids.add()
@@ -114,7 +120,8 @@ class AbstractLink:
        endpoint_id.topology_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
        endpoint_id.device_id.device_uuid.uuid = device_name
        endpoint_id.endpoint_uuid.uuid = endpoint_name
        self.__device_endpoint_to_abstract.setdefault((device_name, endpoint_name), endpoint_id)
        endpoints = self.__device_endpoint_to_abstract.setdefault(device_name, dict())
        endpoints.setdefault(endpoint_name, endpoint_id)

    def _remove_endpoint(self, device_name : str, endpoint_name : str) -> None:
        device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_name, {})
@@ -126,7 +133,8 @@ class AbstractLink:

        # for each endpoint in abstract link that is not in link; remove from abstract link
        device_endpoint_to_abstract = copy.deepcopy(self.__device_endpoint_to_abstract)
        for device_name, endpoint_name in device_endpoint_to_abstract.keys():
        for device_name, endpoints in device_endpoint_to_abstract.items():
            for endpoint_name in endpoints.keys():
                if (device_name, endpoint_name) in link_endpoint_names: continue
                # remove endpoint_id that is not in link
                self._remove_endpoint(device_name, endpoint_name)
@@ -135,7 +143,10 @@ class AbstractLink:
        # for each endpoint in link that is not in abstract link; add to abstract link
        for device_name, endpoint_name in link_endpoint_names:
            # if already added; just check endpoint type is not modified
            if (device_name, endpoint_name) in self.__device_endpoint_to_abstract: continue
            endpoints = self.__device_endpoint_to_abstract.get(device_name, {})
            endpoint = endpoints.get(endpoint_name)
            if endpoint is not None: continue

            # otherwise, add it to the abstract device
            self._add_endpoint(device_name, endpoint_name)
            updated = True
+12 −13
Original line number Diff line number Diff line
@@ -253,7 +253,7 @@ class TopologyAbstractor(threading.Thread):
        }
        str_interdomain_devices = {
            interdomain_device_name : grpc_message_to_json(interdomain_device)
            for interdomain_device_name,interdomain_device in interdomain_devices
            for interdomain_device_name,interdomain_device in interdomain_devices.items()
        }
        LOGGER.info('[_infer_abstract_links] interdomain_devices={:s}'.format(str(str_interdomain_devices)))

@@ -266,8 +266,7 @@ class TopologyAbstractor(threading.Thread):
            abstract_link_name = AbstractLink.compose_name(device_name, endpoint_name, endpoint_name, device_name)
            LOGGER.info('[_infer_abstract_links] abstract_link_name={:s}'.format(str(abstract_link_name)))
            LOGGER.info('[_infer_abstract_links] abstract_links={:s}'.format(str({
                abstract_link_name : abstract_link_obj.to_json()
                for abstract_link_name, abstract_link_obj in self.abstract_links.items()
                al_name : al_obj.to_json() for al_name, al_obj in self.abstract_links.items()
            })))
            if abstract_link_name in self.abstract_links: continue

@@ -320,7 +319,7 @@ class TopologyAbstractor(threading.Thread):
        if dlt_connector_client is not None: dlt_connector_client.close()

    def _process_event_topology(self, event : TopologyEvent, dlt_record_sender : DltRecordSender) -> None:
        LOGGER.debug('Processing TopologyEvent({:s})'.format(grpc_message_to_json_string(event)))
        LOGGER.info('Processing TopologyEvent({:s})'.format(grpc_message_to_json_string(event)))
        topology_id = event.topology_id
        topology_uuid = topology_id.topology_uuid.uuid
        context_uuid = topology_id.context_id.context_uuid.uuid
@@ -359,7 +358,7 @@ class TopologyAbstractor(threading.Thread):
        LOGGER.info('  topology_name={:s}'.format(str(topology_name)))
        LOGGER.info('  topology_uuids={:s}'.format(str(topology_uuids)))
        if (topology_uuid in topology_uuids) or (topology_name in topology_uuids):
            MSG = 'Ignoring ({:s}/{:s})({:s}/{:s}) TopologyEvent({:s})... Not a domain topology'
            MSG = 'Ignoring ({:s}/{:s})({:s}/{:s}) TopologyEvent({:s})... Not a domain/interdomain topology'
            args = context_uuid, context_name, topology_uuid, topology_name, grpc_message_to_json_string(event)
            LOGGER.warning(MSG.format(*args))
            return
@@ -385,7 +384,7 @@ class TopologyAbstractor(threading.Thread):
            self._infer_abstract_links(device, dlt_record_sender)

    def _process_event_device(self, event : DeviceEvent, dlt_record_sender : DltRecordSender) -> None:
        LOGGER.debug('Processing DeviceEvent({:s})'.format(grpc_message_to_json_string(event)))
        LOGGER.info('Processing DeviceEvent({:s})'.format(grpc_message_to_json_string(event)))

        device_uuid = event.device_id.device_uuid.uuid
        device = get_device(
@@ -407,16 +406,16 @@ class TopologyAbstractor(threading.Thread):
        if abstract_device_name is None:
            MSG = 'Ignoring DeviceEvent({:s}). Abstract Device not found'
            LOGGER.warning(MSG.format(grpc_message_to_json_string(event)))
            return

        else:
            abstract_topology_id = self.abstract_device_to_topology_id[abstract_device_name]
            self._update_abstract_device(
                device, dlt_record_sender, abstract_topology_id, abstract_device_name=abstract_device_name)

        if abstract_device_name is not None or device_name in self.abstract_device_to_topology_id:
            self._infer_abstract_links(device, dlt_record_sender)

    def _process_event_link(self, event : LinkEvent, dlt_record_sender : DltRecordSender) -> None:
        LOGGER.debug('Processing LinkEvent({:s})'.format(grpc_message_to_json_string(event)))
        LOGGER.info('Processing LinkEvent({:s})'.format(grpc_message_to_json_string(event)))

        link_uuid = event.link_id.link_uuid.uuid
        link = get_link(self.context_client, link_uuid, rw_copy=True)