Skip to content
Snippets Groups Projects
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
No related branches found
No related tags found
1 merge request!148Draft: Resolve "Adapt InterDomain and DLT components for Release 3.0 to automate NFV-SDN'22 experiment"
...@@ -14,13 +14,14 @@ ...@@ -14,13 +14,14 @@
import copy, logging import copy, logging
from typing import Dict, Optional 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.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 ( from common.tools.context_queries.CheckType import (
device_type_is_datacenter, device_type_is_network, endpoint_type_is_border) 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.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 common.tools.object_factory.Device import json_device
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from .Tools import replace_device_uuids_by_names from .Tools import replace_device_uuids_by_names
...@@ -55,7 +56,13 @@ class AbstractDevice: ...@@ -55,7 +56,13 @@ class AbstractDevice:
'device_name' : self.__device_name, 'device_name' : self.__device_name,
'device_type' : self.__device_type, 'device_type' : self.__device_type,
'device' : grpc_message_to_json(self.__device), '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, 'abstract_endpoint_to_device' : self.__abstract_endpoint_to_device,
} }
...@@ -81,16 +88,13 @@ class AbstractDevice: ...@@ -81,16 +88,13 @@ class AbstractDevice:
else: else:
self._load_existing(local_interdomain_device) self._load_existing(local_interdomain_device)
#is_datacenter = device_type_is_datacenter(self.__device_type) is_datacenter = device_type_is_datacenter(self.__device_type)
#is_network = device_type_is_network(self.__device_type) is_network = device_type_is_network(self.__device_type)
#if is_datacenter or is_network: if is_datacenter or is_network:
# # Add abstract device to topologies [INTERDOMAIN_TOPOLOGY_NAME] # Add abstract device to INTERDOMAIN_TOPOLOGY_NAME topology
# admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
# topology_uuids = [INTERDOMAIN_TOPOLOGY_NAME] topology_name = INTERDOMAIN_TOPOLOGY_NAME
# for topology_uuid in topology_uuids: add_device_to_topology(self.__context_client, admin_context_id, topology_name, self.__device_name)
# # This action is done automatically; commented out by now.
# add_device_to_topology(
# self.__context_client, admin_context_id, topology_uuid, self.__device_name)
# seems not needed; to be removed in future releases # seems not needed; to be removed in future releases
#if is_datacenter and create_abstract_device: #if is_datacenter and create_abstract_device:
...@@ -164,7 +168,7 @@ class AbstractDevice: ...@@ -164,7 +168,7 @@ class AbstractDevice:
def _add_endpoint(self, device_name : str, endpoint_name : str, endpoint_type : str) -> EndPoint: def _add_endpoint(self, device_name : str, endpoint_name : str, endpoint_type : str) -> EndPoint:
interdomain_endpoint = self.__device.device_endpoints.add() 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.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.device_id.device_uuid.uuid = self.__device.name
interdomain_endpoint.endpoint_id.endpoint_uuid.uuid = endpoint_name interdomain_endpoint.endpoint_id.endpoint_uuid.uuid = endpoint_name
......
...@@ -15,8 +15,10 @@ ...@@ -15,8 +15,10 @@
import copy, logging import copy, logging
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
from common.Constants import DEFAULT_CONTEXT_NAME, INTERDOMAIN_TOPOLOGY_NAME from common.Constants import DEFAULT_CONTEXT_NAME, INTERDOMAIN_TOPOLOGY_NAME
from common.proto.context_pb2 import EndPointId, Link from common.proto.context_pb2 import ContextId, EndPointId, Link
from common.tools.context_queries.Link import get_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 common.tools.object_factory.Link import json_link
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from .Tools import replace_link_uuids_by_names from .Tools import replace_link_uuids_by_names
...@@ -39,14 +41,20 @@ class AbstractLink: ...@@ -39,14 +41,20 @@ class AbstractLink:
self.__link_name : str = link_name self.__link_name : str = link_name
self.__link : Optional[Link] = None self.__link : Optional[Link] = None
# Dict[(device_name, endpoint_name), abstract EndPointId] # Dict[device_name, Dict[endpoint_name, abstract EndPointId]]
self.__device_endpoint_to_abstract : Dict[Tuple[str, str], EndPointId] = dict() self.__device_endpoint_to_abstract : Dict[str, Dict[str, EndPointId]] = dict()
def to_json(self) -> Dict: def to_json(self) -> Dict:
return { return {
'link_name' : self.__link_name, 'link_name' : self.__link_name,
'link' : self.__link, 'link' : grpc_message_to_json(self.__link),
'device_endpoint_to_abstract' : self.__device_endpoint_to_abstract, '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 @property
...@@ -80,13 +88,10 @@ class AbstractLink: ...@@ -80,13 +88,10 @@ class AbstractLink:
else: else:
self._load_existing(local_interdomain_link) self._load_existing(local_interdomain_link)
## Add abstract link to topologies [INTERDOMAIN_TOPOLOGY_NAME] # Add abstract link to INTERDOMAIN_TOPOLOGY_NAME topology
#admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) admin_context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
#topology_uuids = [INTERDOMAIN_TOPOLOGY_NAME] topology_name = INTERDOMAIN_TOPOLOGY_NAME
#for topology_uuid in topology_uuids: add_link_to_topology(self.__context_client, admin_context_id, topology_name, self.__link_name)
# # This action is done automatically; commented out by now.
# add_link_to_topology(
# self.__context_client, admin_context_id, topology_uuid, self.__link_name)
return create_abstract_link return create_abstract_link
...@@ -106,7 +111,8 @@ class AbstractLink: ...@@ -106,7 +111,8 @@ class AbstractLink:
for endpoint_id in self.__link.link_endpoint_ids: for endpoint_id in self.__link.link_endpoint_ids:
device_name = endpoint_id.device_id.device_uuid.uuid device_name = endpoint_id.device_id.device_uuid.uuid
endpoint_name = endpoint_id.endpoint_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: def _add_endpoint(self, device_name : str, endpoint_name : str) -> None:
endpoint_id = self.__link.link_endpoint_ids.add() endpoint_id = self.__link.link_endpoint_ids.add()
...@@ -114,7 +120,8 @@ class AbstractLink: ...@@ -114,7 +120,8 @@ class AbstractLink:
endpoint_id.topology_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME endpoint_id.topology_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
endpoint_id.device_id.device_uuid.uuid = device_name endpoint_id.device_id.device_uuid.uuid = device_name
endpoint_id.endpoint_uuid.uuid = endpoint_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: def _remove_endpoint(self, device_name : str, endpoint_name : str) -> None:
device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_name, {}) device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_name, {})
...@@ -126,16 +133,20 @@ class AbstractLink: ...@@ -126,16 +133,20 @@ class AbstractLink:
# for each endpoint in abstract link that is not in link; remove from abstract link # 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) 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():
if (device_name, endpoint_name) in link_endpoint_names: continue for endpoint_name in endpoints.keys():
# remove endpoint_id that is not in link if (device_name, endpoint_name) in link_endpoint_names: continue
self._remove_endpoint(device_name, endpoint_name) # remove endpoint_id that is not in link
updated = True self._remove_endpoint(device_name, endpoint_name)
updated = True
# for each endpoint in link that is not in abstract link; add to abstract link # for each endpoint in link that is not in abstract link; add to abstract link
for device_name, endpoint_name in link_endpoint_names: for device_name, endpoint_name in link_endpoint_names:
# if already added; just check endpoint type is not modified # 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 # otherwise, add it to the abstract device
self._add_endpoint(device_name, endpoint_name) self._add_endpoint(device_name, endpoint_name)
updated = True updated = True
......
...@@ -253,7 +253,7 @@ class TopologyAbstractor(threading.Thread): ...@@ -253,7 +253,7 @@ class TopologyAbstractor(threading.Thread):
} }
str_interdomain_devices = { str_interdomain_devices = {
interdomain_device_name : grpc_message_to_json(interdomain_device) 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))) LOGGER.info('[_infer_abstract_links] interdomain_devices={:s}'.format(str(str_interdomain_devices)))
...@@ -266,8 +266,7 @@ class TopologyAbstractor(threading.Thread): ...@@ -266,8 +266,7 @@ class TopologyAbstractor(threading.Thread):
abstract_link_name = AbstractLink.compose_name(device_name, endpoint_name, endpoint_name, device_name) 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_link_name={:s}'.format(str(abstract_link_name)))
LOGGER.info('[_infer_abstract_links] abstract_links={:s}'.format(str({ LOGGER.info('[_infer_abstract_links] abstract_links={:s}'.format(str({
abstract_link_name : abstract_link_obj.to_json() al_name : al_obj.to_json() for al_name, al_obj in self.abstract_links.items()
for abstract_link_name, abstract_link_obj in self.abstract_links.items()
}))) })))
if abstract_link_name in self.abstract_links: continue if abstract_link_name in self.abstract_links: continue
...@@ -320,7 +319,7 @@ class TopologyAbstractor(threading.Thread): ...@@ -320,7 +319,7 @@ class TopologyAbstractor(threading.Thread):
if dlt_connector_client is not None: dlt_connector_client.close() if dlt_connector_client is not None: dlt_connector_client.close()
def _process_event_topology(self, event : TopologyEvent, dlt_record_sender : DltRecordSender) -> None: 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_id = event.topology_id
topology_uuid = topology_id.topology_uuid.uuid topology_uuid = topology_id.topology_uuid.uuid
context_uuid = topology_id.context_id.context_uuid.uuid context_uuid = topology_id.context_id.context_uuid.uuid
...@@ -359,7 +358,7 @@ class TopologyAbstractor(threading.Thread): ...@@ -359,7 +358,7 @@ class TopologyAbstractor(threading.Thread):
LOGGER.info(' topology_name={:s}'.format(str(topology_name))) LOGGER.info(' topology_name={:s}'.format(str(topology_name)))
LOGGER.info(' topology_uuids={:s}'.format(str(topology_uuids))) LOGGER.info(' topology_uuids={:s}'.format(str(topology_uuids)))
if (topology_uuid in topology_uuids) or (topology_name in 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) args = context_uuid, context_name, topology_uuid, topology_name, grpc_message_to_json_string(event)
LOGGER.warning(MSG.format(*args)) LOGGER.warning(MSG.format(*args))
return return
...@@ -385,7 +384,7 @@ class TopologyAbstractor(threading.Thread): ...@@ -385,7 +384,7 @@ class TopologyAbstractor(threading.Thread):
self._infer_abstract_links(device, dlt_record_sender) self._infer_abstract_links(device, dlt_record_sender)
def _process_event_device(self, event : DeviceEvent, dlt_record_sender : DltRecordSender) -> None: 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_uuid = event.device_id.device_uuid.uuid
device = get_device( device = get_device(
...@@ -407,16 +406,16 @@ class TopologyAbstractor(threading.Thread): ...@@ -407,16 +406,16 @@ class TopologyAbstractor(threading.Thread):
if abstract_device_name is None: if abstract_device_name is None:
MSG = 'Ignoring DeviceEvent({:s}). Abstract Device not found' MSG = 'Ignoring DeviceEvent({:s}). Abstract Device not found'
LOGGER.warning(MSG.format(grpc_message_to_json_string(event))) LOGGER.warning(MSG.format(grpc_message_to_json_string(event)))
return else:
abstract_topology_id = self.abstract_device_to_topology_id[abstract_device_name]
abstract_topology_id = self.abstract_device_to_topology_id[abstract_device_name] self._update_abstract_device(
self._update_abstract_device( device, dlt_record_sender, abstract_topology_id, abstract_device_name=abstract_device_name)
device, dlt_record_sender, abstract_topology_id, abstract_device_name=abstract_device_name)
self._infer_abstract_links(device, dlt_record_sender) 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: 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_uuid = event.link_id.link_uuid.uuid
link = get_link(self.context_client, link_uuid, rw_copy=True) link = get_link(self.context_client, link_uuid, rw_copy=True)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment