diff --git a/manifests/contextservice.yaml b/manifests/contextservice.yaml index 96735bf5f89f682f31131c123ee9884a1becbfdb..bd2ea1f72fa938bee7aed3e3b3f2c15a3102dc84 100644 --- a/manifests/contextservice.yaml +++ b/manifests/contextservice.yaml @@ -40,7 +40,11 @@ spec: - name: MB_BACKEND value: "nats" - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" + - name: ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY + value: "TRUE" + - name: ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY + value: "TRUE" envFrom: - secretRef: name: crdb-data diff --git a/manifests/deviceservice.yaml b/manifests/deviceservice.yaml index 77e421f297fefc8979b9cd6e3415c58be611a53a..7f7885dafa8c87764bc34cb6b21122bba0e80584 100644 --- a/manifests/deviceservice.yaml +++ b/manifests/deviceservice.yaml @@ -39,7 +39,7 @@ spec: - containerPort: 9192 env: - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" startupProbe: exec: command: ["/bin/grpc_health_probe", "-addr=:2020"] diff --git a/manifests/dltservice.yaml b/manifests/dltservice.yaml index 5e8f745f78b14ea4f8881b8992ef788ce89fdcc2..6fe993582db62048704157eed579f6d2ad72a974 100644 --- a/manifests/dltservice.yaml +++ b/manifests/dltservice.yaml @@ -35,12 +35,12 @@ spec: - containerPort: 9192 env: - name: LOG_LEVEL - value: "INFO" - ## for debug purposes - #- name: DLT_GATEWAY_HOST - # value: "mock-blockchain.tfs-bchain.svc.cluster.local" - #- name: DLT_GATEWAY_PORT - # value: "50051" + value: "DEBUG" + ## For debug purposes. Comment out DLT_GATEWAY_HOST and DLT_GATEWAY_PORT to use the DLT Gateway component. + - name: DLT_GATEWAY_HOST + value: "mock-blockchain.tfs-bchain.svc.cluster.local" + - name: DLT_GATEWAY_PORT + value: "50051" readinessProbe: exec: command: ["/bin/grpc_health_probe", "-addr=:8080"] @@ -49,35 +49,36 @@ spec: command: ["/bin/grpc_health_probe", "-addr=:8080"] resources: requests: - cpu: 50m - memory: 64Mi + cpu: 250m + memory: 128Mi limits: - cpu: 500m - memory: 512Mi - - name: gateway - image: labs.etsi.org:5050/tfs/controller/dlt-gateway:latest - imagePullPolicy: Always - ports: - - containerPort: 50051 - #readinessProbe: - # httpGet: - # path: /health - # port: 8081 - # initialDelaySeconds: 5 - # timeoutSeconds: 5 - #livenessProbe: - # httpGet: - # path: /health - # port: 8081 - # initialDelaySeconds: 5 - # timeoutSeconds: 5 - resources: - requests: - cpu: 200m - memory: 512Mi - limits: - cpu: 700m + cpu: 1000m memory: 1024Mi + ## To use a real BlockChain uncomment the gateway container. + #- name: gateway + # image: labs.etsi.org:5050/tfs/controller/dlt-gateway:latest + # imagePullPolicy: Always + # ports: + # - containerPort: 50051 + # #readinessProbe: + # # httpGet: + # # path: /health + # # port: 8081 + # # initialDelaySeconds: 5 + # # timeoutSeconds: 5 + # #livenessProbe: + # # httpGet: + # # path: /health + # # port: 8081 + # # initialDelaySeconds: 5 + # # timeoutSeconds: 5 + # resources: + # requests: + # cpu: 250m + # memory: 512Mi + # limits: + # cpu: 1000m + # memory: 1024Mi --- apiVersion: v1 kind: Service diff --git a/manifests/interdomainservice.yaml b/manifests/interdomainservice.yaml index a235834025724cb11e6b26364f25ae9feb28fe8c..8ecf3cd65b9b976bece1cb0ec9d66930393386aa 100644 --- a/manifests/interdomainservice.yaml +++ b/manifests/interdomainservice.yaml @@ -35,9 +35,9 @@ spec: - containerPort: 9192 env: - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" - name: TOPOLOGY_ABSTRACTOR - value: "DISABLE" + value: "ENABLE" readinessProbe: exec: command: ["/bin/grpc_health_probe", "-addr=:10010"] @@ -47,7 +47,7 @@ spec: resources: requests: cpu: 250m - memory: 64Mi + memory: 128Mi limits: cpu: 1000m memory: 1024Mi diff --git a/manifests/mock_blockchain.yaml b/manifests/mock_blockchain.yaml index 1093610f8a0cf4d735e16e99df56cb78fd6481fc..14cff5e71b4ed6358c6529fc25ca17ca0e5a81ac 100644 --- a/manifests/mock_blockchain.yaml +++ b/manifests/mock_blockchain.yaml @@ -43,10 +43,10 @@ spec: command: ["/bin/grpc_health_probe", "-addr=:50051"] resources: requests: - cpu: 100m - memory: 512Mi + cpu: 250m + memory: 128Mi limits: - cpu: 700m + cpu: 1000m memory: 1024Mi --- apiVersion: v1 diff --git a/manifests/nbiservice.yaml b/manifests/nbiservice.yaml index de97ba364d71d2b5a7f55211867a0a5062c521a4..f5477aeb40582717aa6477ef0baad0de4f51b297 100644 --- a/manifests/nbiservice.yaml +++ b/manifests/nbiservice.yaml @@ -37,7 +37,7 @@ spec: - containerPort: 9192 env: - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" readinessProbe: exec: command: ["/bin/grpc_health_probe", "-addr=:9090"] diff --git a/manifests/pathcompservice.yaml b/manifests/pathcompservice.yaml index 87d907a728d0b689dcedde730fad7a2e886a6659..0ebd1811bc77d374e12d20f7c822fb19e89a874d 100644 --- a/manifests/pathcompservice.yaml +++ b/manifests/pathcompservice.yaml @@ -36,9 +36,9 @@ spec: - containerPort: 9192 env: - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" - name: ENABLE_FORECASTER - value: "YES" + value: "NO" readinessProbe: exec: command: ["/bin/grpc_health_probe", "-addr=:10020"] diff --git a/manifests/serviceservice.yaml b/manifests/serviceservice.yaml index 7d7bdaa4ef9ad4972da6236071810c63a9faa4f8..3865fd6c0bee8d5222d57c50df58435a5669b9e1 100644 --- a/manifests/serviceservice.yaml +++ b/manifests/serviceservice.yaml @@ -36,7 +36,7 @@ spec: - containerPort: 9192 env: - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" readinessProbe: exec: command: ["/bin/grpc_health_probe", "-addr=:3030"] diff --git a/manifests/sliceservice.yaml b/manifests/sliceservice.yaml index e7e5c1604a8b971424ff5f7e5bf292c4b263cbfe..61f5b1d21e0e6305449020fccb139a0dfe21b046 100644 --- a/manifests/sliceservice.yaml +++ b/manifests/sliceservice.yaml @@ -36,7 +36,7 @@ spec: - containerPort: 9192 env: - name: LOG_LEVEL - value: "INFO" + value: "DEBUG" - name: SLICE_GROUPING value: "DISABLE" envFrom: diff --git a/manifests/webuiservice.yaml b/manifests/webuiservice.yaml index 43caa9f04b56d6477d82c5a5bb22cb292eec8a90..61bb933127b7300c43f809c11ca6426dc740fb87 100644 --- a/manifests/webuiservice.yaml +++ b/manifests/webuiservice.yaml @@ -56,7 +56,7 @@ spec: timeoutSeconds: 1 resources: requests: - cpu: 50m + cpu: 250m memory: 128Mi limits: cpu: 1000m @@ -97,7 +97,7 @@ spec: cpu: 250m memory: 512Mi limits: - cpu: 500m + cpu: 1000m memory: 1024Mi --- apiVersion: v1 diff --git a/src/common/message_broker/backend/nats/NatsBackendThread.py b/src/common/message_broker/backend/nats/NatsBackendThread.py index 3ac32b0cb8f7b4be2d693753e39919b82ab3948f..4cb31a7844f407d3e1f97e3e01f811a12c5cee4b 100644 --- a/src/common/message_broker/backend/nats/NatsBackendThread.py +++ b/src/common/message_broker/backend/nats/NatsBackendThread.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import asyncio, logging, nats, nats.errors, queue, threading +import asyncio, logging, nats, nats.errors, queue, threading, uuid from typing import List from common.message_broker.Message import Message @@ -49,16 +49,17 @@ class NatsBackendThread(threading.Thread): self._publish_queue.put_nowait(Message(topic_name, message_content)) async def _run_subscriber( - self, topic_name : str, timeout : float, out_queue : queue.Queue[Message], unsubscribe : threading.Event, - ready_event : threading.Event + self, str_uuid : str, topic_name : str, timeout : float, out_queue : queue.Queue[Message], + unsubscribe : threading.Event, ready_event : threading.Event ) -> None: try: - LOGGER.info('[_run_subscriber] NATS URI: {:s}'.format(str(self._nats_uri))) + LOGGER.info('[_run_subscriber][uuid={:s}] NATS URI: {:s}'.format(str_uuid, str(self._nats_uri))) client = await nats.connect(servers=[self._nats_uri]) server_version = client.connected_server_version - LOGGER.info('[_run_subscriber] Connected! NATS Server version: {:s}'.format(str(repr(server_version)))) + LOGGER.info('[_run_subscriber][uuid={:s}] Connected! NATS Server version: {:s}'.format( + str_uuid, str(repr(server_version)))) subscription = await client.subscribe(topic_name) - LOGGER.info('[_run_subscriber] Subscribed!') + LOGGER.info('[_run_subscriber][uuid={:s}] Subscribed!'.format(str_uuid)) ready_event.set() while not self._terminate.is_set() and not unsubscribe.is_set(): try: @@ -71,19 +72,21 @@ class NatsBackendThread(threading.Thread): await subscription.unsubscribe() await client.drain() except Exception: # pylint: disable=broad-exception-caught - LOGGER.exception('[_run_subscriber] Unhandled Exception') + LOGGER.exception('[_run_subscriber][uuid={:s}] Unhandled Exception'.format(str_uuid)) def subscribe( self, topic_name : str, timeout : float, out_queue : queue.Queue[Message], unsubscribe : threading.Event ) -> None: ready_event = threading.Event() + str_uuid = str(uuid.uuid4()) + LOGGER.info('[subscribe][uuid={:s}] Creating subscriber task...'.format(str_uuid)) task = self._event_loop.create_task( - self._run_subscriber(topic_name, timeout, out_queue, unsubscribe, ready_event) + self._run_subscriber(str_uuid, topic_name, timeout, out_queue, unsubscribe, ready_event) ) self._tasks.append(task) - LOGGER.info('[subscribe] Waiting for subscriber to be ready...') + LOGGER.info('[subscribe][uuid={:s}] Waiting for subscriber to be ready...'.format(str_uuid)) is_ready = ready_event.wait(timeout=120) - LOGGER.info('[subscribe] Subscriber is Ready? {:s}'.format(str(is_ready))) + LOGGER.info('[subscribe][uuid={:s}] Subscriber is Ready? {:s}'.format(str_uuid, str(is_ready))) def run(self) -> None: asyncio.set_event_loop(self._event_loop) diff --git a/src/common/tools/descriptor/Loader.py b/src/common/tools/descriptor/Loader.py index 916a73d300011c62fc008fc7437df8a71f6a9838..73d53bf430eff1e9db2f68b39b461355c032b1c1 100644 --- a/src/common/tools/descriptor/Loader.py +++ b/src/common/tools/descriptor/Loader.py @@ -240,11 +240,16 @@ class DescriptorLoader: self._process_descr('slice', 'add', self.__ctx_cli.SetSlice, Slice, self.__slices ) self._process_descr('connection', 'add', self.__ctx_cli.SetConnection, Connection, self.__connections ) - # Update context and topology is useless: - # - devices and links are assigned to topologies automatically by Context component - # - topologies, services, and slices are assigned to contexts automatically by Context component + # By default the Context component automatically assigns devices and links to topologies based on their + # endpoints, and assigns topologies, services, and slices to contexts based on their identifiers. + + # The following statement is useless; up to now, any use case requires assigning a topology, service, or + # slice to a different context. #self._process_descr('context', 'update', self.__ctx_cli.SetContext, Context, self.__contexts ) - #self._process_descr('topology', 'update', self.__ctx_cli.SetTopology, Topology, self.__topologies ) + + # In some cases, it might be needed to assign devices and links to multiple topologies; the + # following statement performs that assignment. + self._process_descr('topology', 'update', self.__ctx_cli.SetTopology, Topology, self.__topologies ) #self.__ctx_cli.close() @@ -272,11 +277,16 @@ class DescriptorLoader: self._process_descr('slice', 'add', self.__slc_cli.CreateSlice, Slice, self.__slices_add ) self._process_descr('slice', 'update', self.__slc_cli.UpdateSlice, Slice, self.__slices ) - # Update context and topology is useless: - # - devices and links are assigned to topologies automatically by Context component - # - topologies, services, and slices are assigned to contexts automatically by Context component + # By default the Context component automatically assigns devices and links to topologies based on their + # endpoints, and assigns topologies, services, and slices to contexts based on their identifiers. + + # The following statement is useless; up to now, any use case requires assigning a topology, service, or + # slice to a different context. #self._process_descr('context', 'update', self.__ctx_cli.SetContext, Context, self.__contexts ) - #self._process_descr('topology', 'update', self.__ctx_cli.SetTopology, Topology, self.__topologies ) + + # In some cases, it might be needed to assign devices and links to multiple topologies; the + # following statement performs that assignment. + self._process_descr('topology', 'update', self.__ctx_cli.SetTopology, Topology, self.__topologies ) #self.__slc_cli.close() #self.__svc_cli.close() diff --git a/src/context/Config.py b/src/context/Config.py index 1549d9811aa5d1c193a44ad45d0d7773236c0612..344b34a09e76b50028f3a3bfbcc47278f1dfbbcc 100644 --- a/src/context/Config.py +++ b/src/context/Config.py @@ -12,3 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +from common.Settings import get_setting + +TRUE_VALUES = {'Y', 'YES', 'T', 'TRUE', 'E', 'ENABLE', 'ENABLED'} +def is_enabled(setting_name : str, default_value : bool) -> bool: + _is_enabled = get_setting(setting_name, default=None) + if _is_enabled is None: return default_value + str_is_enabled = str(_is_enabled).upper() + return str_is_enabled in TRUE_VALUES + +ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY = is_enabled('ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY', True) +ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY = is_enabled('ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY', True) diff --git a/src/context/service/database/Topology.py b/src/context/service/database/Topology.py index 1f0fb6c0b3c400d58ea83bc857e97bc50a1324a3..083ec8350059e382380386bf6c855dce6dd5cbb5 100644 --- a/src/context/service/database/Topology.py +++ b/src/context/service/database/Topology.py @@ -17,17 +17,20 @@ from sqlalchemy.dialects.postgresql import insert from sqlalchemy.engine import Engine from sqlalchemy.orm import Session, selectinload, sessionmaker from sqlalchemy_cockroachdb import run_transaction -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Set from common.proto.context_pb2 import ( ContextId, Empty, EventTypeEnum, Topology, TopologyDetails, TopologyId, TopologyIdList, TopologyList) from common.message_broker.MessageBroker import MessageBroker from common.method_wrappers.ServiceExceptions import NotFoundException from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Topology import json_topology_id +from context.Config import ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY, ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY from .models.DeviceModel import DeviceModel from .models.LinkModel import LinkModel from .models.TopologyModel import TopologyDeviceModel, TopologyLinkModel, TopologyModel from .uuids.Context import context_get_uuid +from .uuids.Device import device_get_uuid +from .uuids.Link import link_get_uuid from .uuids.Topology import topology_get_uuid from .Events import notify_event_context, notify_event_topology @@ -98,11 +101,33 @@ def topology_set(db_engine : Engine, messagebroker : MessageBroker, request : To # topology. Explicit addition into the topology is done automatically when creating the devices and links, based # on the topologies specified in the endpoints associated with the devices and links. - if len(request.device_ids) > 0: # pragma: no cover - LOGGER.warning('Items in field "device_ids" ignored. This field is used for retrieval purposes only.') + related_devices : List[Dict] = list() + if ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY: + device_uuids : Set[str] = set() + for device_id in request.device_ids: + device_uuid = device_get_uuid(device_id) + if device_uuid not in device_uuids: continue + related_devices.append({'topology_uuid': topology_uuid, 'device_uuid': device_uuid}) + device_uuids.add(device_uuid) + else: + if len(request.device_ids) > 0: # pragma: no cover + MSG = 'ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY={:s}; '.format(str(ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY)) + MSG += 'Items in field "device_ids" ignored. This field is used for retrieval purposes only.' + LOGGER.warning(MSG) - if len(request.link_ids) > 0: # pragma: no cover - LOGGER.warning('Items in field "link_ids" ignored. This field is used for retrieval purposes only.') + related_links : List[Dict] = list() + if ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY: + link_uuids : Set[str] = set() + for link_id in request.link_ids: + link_uuid = link_get_uuid(link_id) + if link_uuid not in link_uuids: continue + related_links.append({'topology_uuid': topology_uuid, 'link_uuid': link_uuid}) + link_uuids.add(link_uuid) + else: + if len(request.link_ids) > 0: # pragma: no cover + MSG = 'ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY={:s}; '.format(str(ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY)) + MSG += 'Items in field "link_ids" ignored. This field is used for retrieval purposes only.' + LOGGER.warning(MSG) now = datetime.datetime.utcnow() topology_data = [{ @@ -124,7 +149,27 @@ def topology_set(db_engine : Engine, messagebroker : MessageBroker, request : To ) stmt = stmt.returning(TopologyModel.created_at, TopologyModel.updated_at) created_at,updated_at = session.execute(stmt).fetchone() - return updated_at > created_at + updated = updated_at > created_at + + updated_topology_device = False + if len(related_devices) > 0: + stmt = insert(TopologyDeviceModel).values(related_devices) + stmt = stmt.on_conflict_do_nothing( + index_elements=[TopologyDeviceModel.topology_uuid, TopologyDeviceModel.device_uuid] + ) + topology_device_inserts = session.execute(stmt) + updated_topology_device = int(topology_device_inserts.rowcount) > 0 + + updated_topology_link = False + if len(related_links) > 0: + stmt = insert(TopologyLinkModel).values(related_links) + stmt = stmt.on_conflict_do_nothing( + index_elements=[TopologyLinkModel.topology_uuid, TopologyLinkModel.link_uuid] + ) + topology_link_inserts = session.execute(stmt) + updated_topology_link = int(topology_link_inserts.rowcount) > 0 + + return updated or updated_topology_device or updated_topology_link updated = run_transaction(sessionmaker(bind=db_engine), callback) context_id = json_context_id(context_uuid) diff --git a/src/dlt/connector/service/event_dispatcher/DltEventDispatcher.py b/src/dlt/connector/service/event_dispatcher/DltEventDispatcher.py index 78d375efafc0329048654d34033bb46b00cb3bdf..9e829e37cd5579104c8cba08105614e17bfbf2b8 100644 --- a/src/dlt/connector/service/event_dispatcher/DltEventDispatcher.py +++ b/src/dlt/connector/service/event_dispatcher/DltEventDispatcher.py @@ -13,11 +13,11 @@ # limitations under the License. import grpc, json, logging, threading -from typing import Any, Dict, Set +from typing import Set from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME from common.proto.context_pb2 import ContextId, Device, EventTypeEnum, Link, Slice, TopologyId from common.proto.dlt_connector_pb2 import DltSliceId -from common.proto.dlt_gateway_pb2 import DltRecordEvent, DltRecordOperationEnum, DltRecordTypeEnum +from common.proto.dlt_gateway_pb2 import DltRecordEvent, DltRecordTypeEnum from common.tools.context_queries.Context import create_context from common.tools.context_queries.Device import add_device_to_topology from common.tools.context_queries.Link import add_link_to_topology @@ -66,9 +66,15 @@ class DltEventDispatcher(threading.Thread): def run(self) -> None: clients = Clients() - create_context(clients.context_client, DEFAULT_CONTEXT_NAME) - create_topology(clients.context_client, DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME) - create_topology(clients.context_client, DEFAULT_CONTEXT_NAME, INTERDOMAIN_TOPOLOGY_NAME) + create_context( + clients.context_client, DEFAULT_CONTEXT_NAME, + name=DEFAULT_CONTEXT_NAME) + create_topology( + clients.context_client, DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME, + name=DEFAULT_TOPOLOGY_NAME) + create_topology( + clients.context_client, DEFAULT_CONTEXT_NAME, INTERDOMAIN_TOPOLOGY_NAME, + name=INTERDOMAIN_TOPOLOGY_NAME) dlt_events_collector = DltEventsCollector(clients.dlt_gateway_client, log_events_received=True) dlt_events_collector.start() @@ -77,37 +83,42 @@ class DltEventDispatcher(threading.Thread): event = dlt_events_collector.get_event(block=True, timeout=GET_EVENT_TIMEOUT) if event is None: continue - existing_topology_ids = clients.context_client.ListTopologyIds(ADMIN_CONTEXT_ID) - local_domain_uuids = { - topology_id.topology_uuid.uuid for topology_id in existing_topology_ids.topology_ids - } - local_domain_uuids.discard(DEFAULT_TOPOLOGY_NAME) - local_domain_uuids.discard(INTERDOMAIN_TOPOLOGY_NAME) + existing_topologies = clients.context_client.ListTopologies(ADMIN_CONTEXT_ID) + local_domain_names = {topology.name for topology in existing_topologies.topologies} + local_domain_names.discard(DEFAULT_TOPOLOGY_NAME) + local_domain_names.discard(INTERDOMAIN_TOPOLOGY_NAME) - self.dispatch_event(clients, local_domain_uuids, event) + self.dispatch_event(clients, local_domain_names, event) dlt_events_collector.stop() clients.close() - def dispatch_event(self, clients : Clients, local_domain_uuids : Set[str], event : DltRecordEvent) -> None: + def dispatch_event(self, clients : Clients, local_domain_names : Set[str], event : DltRecordEvent) -> None: record_type : DltRecordTypeEnum = event.record_id.type # {UNDEFINED/CONTEXT/TOPOLOGY/DEVICE/LINK/SERVICE/SLICE} if record_type == DltRecordTypeEnum.DLTRECORDTYPE_DEVICE: - self._dispatch_device(clients, local_domain_uuids, event) + self._dispatch_device(clients, local_domain_names, event) elif record_type == DltRecordTypeEnum.DLTRECORDTYPE_LINK: - self._dispatch_link(clients, local_domain_uuids, event) + self._dispatch_link(clients, local_domain_names, event) elif record_type == DltRecordTypeEnum.DLTRECORDTYPE_SLICE: - self._dispatch_slice(clients, local_domain_uuids, event) + self._dispatch_slice(clients, local_domain_names, event) else: raise NotImplementedError('EventType: {:s}'.format(grpc_message_to_json_string(event))) - def _dispatch_device(self, clients : Clients, local_domain_uuids : Set[str], event : DltRecordEvent) -> None: + def _dispatch_device(self, clients : Clients, local_domain_names : Set[str], event : DltRecordEvent) -> None: domain_uuid : str = event.record_id.domain_uuid.uuid - if domain_uuid in local_domain_uuids: - MSG = '[_dispatch_device] Ignoring DLT event received (local): {:s}' + # TODO: to be checked! + if domain_uuid in {DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME}: + MSG = '[_dispatch_device] Ignoring DLT event received (discard domain): {:s}' LOGGER.info(MSG.format(grpc_message_to_json_string(event))) return + # TODO: to be checked! + if domain_uuid in local_domain_names: + MSG = '[_dispatch_device] Ignoring DLT event received (local_domain_names={:s}): {:s}' + LOGGER.info(MSG.format(str(local_domain_names), grpc_message_to_json_string(event))) + return + MSG = '[_dispatch_device] DLT event received (remote): {:s}' LOGGER.info(MSG.format(grpc_message_to_json_string(event))) @@ -117,23 +128,36 @@ class DltEventDispatcher(threading.Thread): record = clients.dlt_gateway_client.GetFromDlt(event.record_id) LOGGER.info('[_dispatch_device] record={:s}'.format(grpc_message_to_json_string(record))) - create_context(clients.context_client, domain_uuid) - create_topology(clients.context_client, domain_uuid, DEFAULT_TOPOLOGY_NAME) + # TODO: to be checked! device = Device(**json.loads(record.data_json)) + device_name = None if len(device.name) == 0 else device.name + create_context(clients.context_client, domain_uuid, name=device_name) + create_topology(clients.context_client, domain_uuid, DEFAULT_TOPOLOGY_NAME, name=DEFAULT_TOPOLOGY_NAME) clients.context_client.SetDevice(device) + + # TODO: to be checked! device_uuid = device.device_id.device_uuid.uuid # pylint: disable=no-member add_device_to_topology(clients.context_client, ADMIN_CONTEXT_ID, INTERDOMAIN_TOPOLOGY_NAME, device_uuid) + + # TODO: to be checked! domain_context_id = ContextId(**json_context_id(domain_uuid)) add_device_to_topology(clients.context_client, domain_context_id, DEFAULT_TOPOLOGY_NAME, device_uuid) elif event_type in {EventTypeEnum.EVENTTYPE_DELETE}: raise NotImplementedError('Delete Device') - def _dispatch_link(self, clients : Clients, local_domain_uuids : Set[str], event : DltRecordEvent) -> None: + def _dispatch_link(self, clients : Clients, local_domain_names : Set[str], event : DltRecordEvent) -> None: domain_uuid : str = event.record_id.domain_uuid.uuid - if domain_uuid in local_domain_uuids: - MSG = '[_dispatch_link] Ignoring DLT event received (local): {:s}' - LOGGER.info(MSG.format(grpc_message_to_json_string(event))) + # TODO: to be checked! + #if domain_uuid in {DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME}: + # MSG = '[_dispatch_link] Ignoring DLT event received (discard domain): {:s}' + # LOGGER.info(MSG.format(grpc_message_to_json_string(event))) + # return + + # TODO: to be checked! + if domain_uuid in local_domain_names: + MSG = '[_dispatch_link] Ignoring DLT event received (local_domain_names={:s}): {:s}' + LOGGER.info(MSG.format(str(local_domain_names), grpc_message_to_json_string(event))) return MSG = '[_dispatch_link] DLT event received (remote): {:s}' @@ -147,12 +171,14 @@ class DltEventDispatcher(threading.Thread): link = Link(**json.loads(record.data_json)) clients.context_client.SetLink(link) + + # TODO: to be checked! link_uuid = link.link_id.link_uuid.uuid # pylint: disable=no-member add_link_to_topology(clients.context_client, ADMIN_CONTEXT_ID, INTERDOMAIN_TOPOLOGY_NAME, link_uuid) elif event_type in {EventTypeEnum.EVENTTYPE_DELETE}: raise NotImplementedError('Delete Link') - def _dispatch_slice(self, clients : Clients, local_domain_uuids : Set[str], event : DltRecordEvent) -> None: + def _dispatch_slice(self, clients : Clients, local_domain_names : Set[str], event : DltRecordEvent) -> None: event_type : EventTypeEnum = event.event.event_type # {UNDEFINED/CREATE/UPDATE/REMOVE} domain_uuid : str = event.record_id.domain_uuid.uuid @@ -164,10 +190,12 @@ class DltEventDispatcher(threading.Thread): context_uuid = slice_.slice_id.context_id.context_uuid.uuid owner_uuid = slice_.slice_owner.owner_uuid.uuid - create_context(clients.context_client, context_uuid) - create_topology(clients.context_client, context_uuid, DEFAULT_TOPOLOGY_NAME) - if domain_uuid in local_domain_uuids: + # TODO: to be checked! + create_context(clients.context_client, context_uuid, name=context_uuid) + create_topology(clients.context_client, context_uuid, DEFAULT_TOPOLOGY_NAME, name=DEFAULT_TOPOLOGY_NAME) + + if domain_uuid in local_domain_names: # it is for "me" if event_type in {EventTypeEnum.EVENTTYPE_CREATE, EventTypeEnum.EVENTTYPE_UPDATE}: try: @@ -190,7 +218,7 @@ class DltEventDispatcher(threading.Thread): elif event_type in {EventTypeEnum.EVENTTYPE_DELETE}: raise NotImplementedError('Delete Slice') - elif owner_uuid in local_domain_uuids: + elif owner_uuid in local_domain_names: # it is owned by me # just update it locally LOGGER.info('[_dispatch_slice] updating locally') @@ -206,4 +234,3 @@ class DltEventDispatcher(threading.Thread): else: MSG = '[_dispatch_slice] Ignoring DLT event received (remote): {:s}' LOGGER.info(MSG.format(grpc_message_to_json_string(event))) - diff --git a/src/interdomain/service/RemoteDomainClients.py b/src/interdomain/service/RemoteDomainClients.py index adc6fe52b554d119db951189abcefe9e58860985..f50e2f7292c0c7fab990f22f0a51928340808dea 100644 --- a/src/interdomain/service/RemoteDomainClients.py +++ b/src/interdomain/service/RemoteDomainClients.py @@ -55,7 +55,11 @@ class RemoteDomainClients(threading.Thread): self.lock = threading.Lock() self.peer_domains = {} self.context_client = ContextClient() - self.context_event_collector = EventsCollector(self.context_client) + self.context_event_collector = EventsCollector( + self.context_client, activate_context_collector=False, activate_topology_collector=False, + activate_device_collector=True, activate_link_collector=False, activate_service_collector=False, + activate_slice_collector=False, activate_connection_collector=False + ) def stop(self): self.terminate.set() diff --git a/src/interdomain/service/topology_abstractor/AbstractDevice.py b/src/interdomain/service/topology_abstractor/AbstractDevice.py index 47832acc02c78b5cfc095fb3ecceccfb6b9a774f..2e62f6215f0da174ef72ad22163d502d3c3ab106 100644 --- a/src/interdomain/service/topology_abstractor/AbstractDevice.py +++ b/src/interdomain/service/topology_abstractor/AbstractDevice.py @@ -14,80 +14,87 @@ 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 ( - ContextId, Device, DeviceDriverEnum, DeviceId, 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 add_device_to_topology, get_existing_device_uuids +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, json_device_id +from common.tools.object_factory.Device import json_device from context.client.ContextClient import ContextClient -from context.service.database.uuids.EndPoint import endpoint_get_uuid +from .Tools import replace_device_uuids_by_names + +# Remark on UUIDs: +# TopologyAbstractor, AbstractDevice and AbstractLink are used +# to compose network reporesentations to be forwarded to remote +# instances. Constraining it to use UUIDs is pointless given +# these UUIDs, to be unique, need to be bound to the local +# context/topology UUIDs, which might be different than that for +# the remote TeraFlowSDN instances. For this very reason, we use +# the device/link/endpoint/topology/context names as UUIDs, to +# prevent UUID-related issues. LOGGER = logging.getLogger(__name__) class AbstractDevice: - def __init__(self, device_uuid : str, device_name : str, device_type : DeviceTypeEnum): + def __init__(self, device_name : str, device_type : DeviceTypeEnum): self.__context_client = ContextClient() - self.__device_uuid : str = device_uuid self.__device_name : str = device_name self.__device_type : DeviceTypeEnum = device_type self.__device : Optional[Device] = None - self.__device_id : Optional[DeviceId] = None - # Dict[device_uuid, Dict[endpoint_uuid, abstract EndPoint]] + # Dict[device_name, Dict[endpoint_name, abstract EndPoint]] self.__device_endpoint_to_abstract : Dict[str, Dict[str, EndPoint]] = dict() - # Dict[endpoint_uuid, device_uuid] + # Dict[endpoint_name, device_name] self.__abstract_endpoint_to_device : Dict[str, str] = dict() def to_json(self) -> Dict: return { - 'device_uuid' : self.__device_uuid, 'device_name' : self.__device_name, 'device_type' : self.__device_type, - 'device' : self.__device, - 'device_id' : self.__device_id, - 'device_endpoint_to_abstract' : self.__device_endpoint_to_abstract, + 'device' : grpc_message_to_json(self.__device), + '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, } - @property - def uuid(self) -> str: return self.__device_uuid - @property def name(self) -> str: return self.__device_name - @property - def device_id(self) -> Optional[DeviceId]: return self.__device_id - @property def device(self) -> Optional[Device]: return self.__device - def get_endpoint(self, device_uuid : str, endpoint_uuid : str) -> Optional[EndPoint]: - return self.__device_endpoint_to_abstract.get(device_uuid, {}).get(endpoint_uuid) + def get_endpoint(self, device_name : str, endpoint_name : str) -> Optional[EndPoint]: + return self.__device_endpoint_to_abstract.get(device_name, {}).get(endpoint_name) def initialize(self) -> bool: if self.__device is not None: return False - existing_device_uuids = get_existing_device_uuids(self.__context_client) - create_abstract_device = self.__device_uuid not in existing_device_uuids + local_interdomain_device = get_device( + self.__context_client, self.__device_name, rw_copy=True, include_endpoints=True, + include_config_rules=False, include_components=False) + create_abstract_device = local_interdomain_device is None if create_abstract_device: self._create_empty() else: - self._load_existing() + 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] - context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) - topology_uuids = [INTERDOMAIN_TOPOLOGY_NAME] - for topology_uuid in topology_uuids: - add_device_to_topology(self.__context_client, context_id, topology_uuid, self.__device_uuid) + # 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: @@ -101,27 +108,25 @@ class AbstractDevice: # if device_type_is_datacenter(device.device_type): continue # self.update_endpoints(device) - return True + return create_abstract_device def _create_empty(self) -> None: - device_uuid = self.__device_uuid - + device_name = self.__device_name device = Device(**json_device( - device_uuid, self.__device_type.value, DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED, - name=self.__device_name, endpoints=[], config_rules=[], drivers=[DeviceDriverEnum.DEVICEDRIVER_UNDEFINED] + device_name, self.__device_type.value, DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED, + name=device_name, endpoints=[], config_rules=[], drivers=[DeviceDriverEnum.DEVICEDRIVER_UNDEFINED] )) self.__context_client.SetDevice(device) - self.__device = device - self.__device_id = self.__device.device_id + self.__device = device # Store copy with names as UUIDs - def _load_existing(self) -> None: + def _load_existing(self, local_interdomain_device : Device) -> None: self.__device_endpoint_to_abstract = dict() self.__abstract_endpoint_to_device = dict() - self.__device_id = DeviceId(**json_device_id(self.__device_uuid)) - self.__device = self.__context_client.GetDevice(self.__device_id) + replace_device_uuids_by_names(self.__context_client, local_interdomain_device) + + self.__device = local_interdomain_device self.__device_type = self.__device.device_type - device_uuid = self.__device_id.device_uuid.uuid device_type = self.__device_type is_datacenter = device_type_is_datacenter(device_type) @@ -132,67 +137,63 @@ class AbstractDevice: # for each endpoint in abstract device, populate internal data structures and mappings for interdomain_endpoint in self.__device.device_endpoints: - endpoint_uuid : str = interdomain_endpoint.endpoint_id.endpoint_uuid.uuid + endpoint_name : str = interdomain_endpoint.name if is_network: - endpoint_uuid,device_uuid = endpoint_uuid.split('@', maxsplit=1) + endpoint_name,device_name = endpoint_name.split('@', maxsplit=1) + else: + device_name = self.__device_name self.__device_endpoint_to_abstract\ - .setdefault(device_uuid, {}).setdefault(endpoint_uuid, interdomain_endpoint) + .setdefault(device_name, {}).setdefault(endpoint_name, interdomain_endpoint) self.__abstract_endpoint_to_device\ - .setdefault(endpoint_uuid, device_uuid) - - def _update_endpoint_name(self, device_uuid : str, endpoint_uuid : str, endpoint_name : str) -> bool: - device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_uuid, {}) - interdomain_endpoint = device_endpoint_to_abstract.get(endpoint_uuid) - interdomain_endpoint_name = interdomain_endpoint.name - if endpoint_name == interdomain_endpoint_name: return False - interdomain_endpoint.name = endpoint_name - return True - - def _update_endpoint_type(self, device_uuid : str, endpoint_uuid : str, endpoint_type : str) -> bool: - device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_uuid, {}) - interdomain_endpoint = device_endpoint_to_abstract.get(endpoint_uuid) + .setdefault(endpoint_name, device_name) + + # This method becomes useless; the endpoint name is considered a primary key; cannot be updated + #def _update_endpoint_name(self, device_uuid : str, endpoint_uuid : str, endpoint_name : str) -> bool: + # device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_uuid, {}) + # interdomain_endpoint = device_endpoint_to_abstract.get(endpoint_uuid) + # interdomain_endpoint_name = interdomain_endpoint.name + # if endpoint_name == interdomain_endpoint_name: return False + # interdomain_endpoint.name = endpoint_name + # return True + + def _update_endpoint_type(self, device_name : str, endpoint_name : str, endpoint_type : str) -> bool: + device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_name, {}) + interdomain_endpoint = device_endpoint_to_abstract.get(endpoint_name) interdomain_endpoint_type = interdomain_endpoint.endpoint_type if endpoint_type == interdomain_endpoint_type: return False interdomain_endpoint.endpoint_type = endpoint_type return True - def _add_endpoint( - self, device_uuid : str, endpoint_uuid : 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.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.CopyFrom(self.__device_id) + interdomain_endpoint.endpoint_id.device_id.device_uuid.uuid = self.__device.name interdomain_endpoint.endpoint_id.endpoint_uuid.uuid = endpoint_name interdomain_endpoint.name = endpoint_name interdomain_endpoint.endpoint_type = endpoint_type - uuids = endpoint_get_uuid(interdomain_endpoint.endpoint_id, endpoint_name=endpoint_name, allow_random=False) - _, _, interdomain_endpoint_uuid = uuids - self.__device_endpoint_to_abstract\ - .setdefault(device_uuid, {}).setdefault(endpoint_uuid, interdomain_endpoint) + .setdefault(device_name, {}).setdefault(endpoint_name, interdomain_endpoint) self.__abstract_endpoint_to_device\ - .setdefault(interdomain_endpoint_uuid, device_uuid) + .setdefault(endpoint_name, device_name) return interdomain_endpoint - def _remove_endpoint( - self, device_uuid : str, endpoint_uuid : str, interdomain_endpoint : EndPoint - ) -> None: - self.__abstract_endpoint_to_device.pop(endpoint_uuid, None) - device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_uuid, {}) - device_endpoint_to_abstract.pop(endpoint_uuid, None) + def _remove_endpoint(self, device_name : str, endpoint_name : str, interdomain_endpoint : EndPoint) -> None: + self.__abstract_endpoint_to_device.pop(endpoint_name, None) + device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_name, {}) + device_endpoint_to_abstract.pop(endpoint_name, None) self.__device.device_endpoints.remove(interdomain_endpoint) def update_endpoints(self, device : Device) -> bool: if device_type_is_datacenter(self.__device.device_type): return False - device_uuid = device.device_id.device_uuid.uuid - device_border_endpoint_uuids = { - endpoint.endpoint_id.endpoint_uuid.uuid : (endpoint.name, endpoint.endpoint_type) + device_name = device.name + device_border_endpoint_names = { + endpoint.name : endpoint.endpoint_type for endpoint in device.device_endpoints if endpoint_type_is_border(endpoint.endpoint_type) } @@ -200,24 +201,27 @@ class AbstractDevice: updated = False # for each border endpoint in abstract device that is not in device; remove from abstract device - device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_uuid, {}) + device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_name, {}) _device_endpoint_to_abstract = copy.deepcopy(device_endpoint_to_abstract) - for endpoint_uuid, interdomain_endpoint in _device_endpoint_to_abstract.items(): - if endpoint_uuid in device_border_endpoint_uuids: continue + for endpoint_name, interdomain_endpoint in _device_endpoint_to_abstract.items(): + if endpoint_name in device_border_endpoint_names: continue # remove interdomain endpoint that is not in device - self._remove_endpoint(device_uuid, endpoint_uuid, interdomain_endpoint) + self._remove_endpoint(device_name, endpoint_name, interdomain_endpoint) updated = True # for each border endpoint in device that is not in abstract device; add to abstract device - for endpoint_uuid,(endpoint_name, endpoint_type) in device_border_endpoint_uuids.items(): - # if already added; just check endpoint name and type are not modified - if endpoint_uuid in self.__abstract_endpoint_to_device: - updated = updated or self._update_endpoint_name(device_uuid, endpoint_uuid, endpoint_name) - updated = updated or self._update_endpoint_type(device_uuid, endpoint_uuid, endpoint_type) + for endpoint_name,endpoint_type in device_border_endpoint_names.items(): + abstract_endpoint = self.__device_endpoint_to_abstract.get(device_name, {}).get(endpoint_name) + abstract_endpoint_name = None if abstract_endpoint is None else abstract_endpoint.name + + # if already added; just check endpoint type is not modified + if abstract_endpoint_name in self.__abstract_endpoint_to_device: + #updated = updated or self._update_endpoint_name(device_name, endpoint_name, endpoint_name) + updated = updated or self._update_endpoint_type(device_name, endpoint_name, endpoint_type) continue # otherwise, add it to the abstract device - self._add_endpoint(device_uuid, endpoint_uuid, endpoint_name, endpoint_type) + self._add_endpoint(device_name, endpoint_name, endpoint_type) updated = True return updated diff --git a/src/interdomain/service/topology_abstractor/AbstractLink.py b/src/interdomain/service/topology_abstractor/AbstractLink.py index 76b2a0311b2213d35c1b5461e06c324f9304b934..bb1a02334c45b0606c090ccd951f8d3cc8b9ba65 100644 --- a/src/interdomain/service/topology_abstractor/AbstractLink.py +++ b/src/interdomain/service/topology_abstractor/AbstractLink.py @@ -15,122 +15,140 @@ 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 ContextId, EndPointId, Link, LinkId -from common.tools.context_queries.Link import add_link_to_topology, get_existing_link_uuids +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, json_link_id +from common.tools.object_factory.Link import json_link from context.client.ContextClient import ContextClient +from .Tools import replace_link_uuids_by_names + +# Remark on UUIDs: +# TopologyAbstractor, AbstractDevice and AbstractLink are used +# to compose network reporesentations to be forwarded to remote +# instances. Constraining it to use UUIDs is pointless given +# these UUIDs, to be unique, need to be bound to the local +# context/topology UUIDs, which might be different than that for +# the remote TeraFlowSDN instances. For this very reason, we use +# the device/link/endpoint/topology/context names as UUIDs, to +# prevent UUID-related issues. LOGGER = logging.getLogger(__name__) class AbstractLink: - def __init__(self, link_uuid : str): + def __init__(self, link_name : str): self.__context_client = ContextClient() - self.__link_uuid : str = link_uuid + self.__link_name : str = link_name self.__link : Optional[Link] = None - self.__link_id : Optional[LinkId] = None - # Dict[(device_uuid, endpoint_uuid), 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_uuid' : self.__link_uuid, - 'link' : self.__link, - 'link_id' : self.__link_id, - 'device_endpoint_to_abstract' : self.__device_endpoint_to_abstract, + 'link_name' : self.__link_name, + '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 - def uuid(self) -> str: return self.__link_uuid - - @property - def link_id(self) -> Optional[LinkId]: return self.__link_id + def name(self) -> str: return self.__link_name @property def link(self) -> Optional[Link]: return self.__link @staticmethod - def compose_uuid( - device_uuid_a : str, endpoint_uuid_a : str, device_uuid_z : str, endpoint_uuid_z : str + def compose_name( + device_name_a : str, endpoint_name_a : str, device_name_z : str, endpoint_name_z : str ) -> str: # sort endpoints lexicographically to prevent duplicities - link_endpoint_uuids = sorted([ - (device_uuid_a, endpoint_uuid_a), - (device_uuid_z, endpoint_uuid_z) + link_endpoint_names = sorted([ + (device_name_a, endpoint_name_a), + (device_name_z, endpoint_name_z) ]) - link_uuid = '{:s}/{:s}=={:s}/{:s}'.format( - link_endpoint_uuids[0][0], link_endpoint_uuids[0][1], - link_endpoint_uuids[1][0], link_endpoint_uuids[1][1]) - return link_uuid + link_name = '{:s}/{:s}=={:s}/{:s}'.format( + link_endpoint_names[0][0], link_endpoint_names[0][1], + link_endpoint_names[1][0], link_endpoint_names[1][1]) + return link_name def initialize(self) -> bool: if self.__link is not None: return False - existing_link_uuids = get_existing_link_uuids(self.__context_client) + local_interdomain_link = get_link(self.__context_client, self.__link_name, rw_copy=False) + create_abstract_link = local_interdomain_link is None - create = self.__link_uuid not in existing_link_uuids - if create: + if create_abstract_link: self._create_empty() else: - self._load_existing() + self._load_existing(local_interdomain_link) - # Add abstract link to topologies [INTERDOMAIN_TOPOLOGY_NAME] - context_id = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) - topology_uuids = [INTERDOMAIN_TOPOLOGY_NAME] - for topology_uuid in topology_uuids: - add_link_to_topology(self.__context_client, context_id, topology_uuid, self.__link_uuid) + # 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 + return create_abstract_link def _create_empty(self) -> None: - link = Link(**json_link(self.__link_uuid, endpoint_ids=[])) + link_name = self.__link_name + link = Link(**json_link(link_name, name=link_name, endpoint_ids=[])) self.__context_client.SetLink(link) - self.__link = link - self.__link_id = self.__link.link_id - - def _load_existing(self) -> None: - self.__link_id = LinkId(**json_link_id(self.__link_uuid)) - self.__link = self.__context_client.GetLink(self.__link_id) + self.__link = link # Store copy with names as UUIDs + def _load_existing(self, local_interdomain_link : Link) -> None: self.__device_endpoint_to_abstract = dict() + self.__link = local_interdomain_link + replace_link_uuids_by_names(self.__context_client, local_interdomain_link) + # for each endpoint in abstract link, populate internal data structures and mappings for endpoint_id in self.__link.link_endpoint_ids: - device_uuid : str = endpoint_id.device_id.device_uuid.uuid - endpoint_uuid : str = endpoint_id.endpoint_uuid.uuid - self.__device_endpoint_to_abstract.setdefault((device_uuid, endpoint_uuid), endpoint_id) + device_name = endpoint_id.device_id.device_uuid.uuid + endpoint_name = endpoint_id.endpoint_uuid.uuid + endpoints = self.__device_endpoint_to_abstract.setdefault(device_name, dict()) + endpoints.setdefault(endpoint_name, endpoint_id) - def _add_endpoint(self, device_uuid : str, endpoint_uuid : str) -> None: + def _add_endpoint(self, device_name : str, endpoint_name : str) -> None: endpoint_id = self.__link.link_endpoint_ids.add() endpoint_id.topology_id.topology_uuid.uuid = INTERDOMAIN_TOPOLOGY_NAME endpoint_id.topology_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME - endpoint_id.device_id.device_uuid.uuid = device_uuid - endpoint_id.endpoint_uuid.uuid = endpoint_uuid - self.__device_endpoint_to_abstract.setdefault((device_uuid, endpoint_uuid), endpoint_id) - - def _remove_endpoint(self, device_uuid : str, endpoint_uuid : str) -> None: - device_endpoint_to_abstract = self.__device_endpoint_to_abstract.get(device_uuid, {}) - endpoint_id = device_endpoint_to_abstract.pop(endpoint_uuid, None) + endpoint_id.device_id.device_uuid.uuid = device_name + endpoint_id.endpoint_uuid.uuid = endpoint_name + 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, {}) + endpoint_id = device_endpoint_to_abstract.pop(endpoint_name, None) if endpoint_id is not None: self.__link.link_endpoint_ids.remove(endpoint_id) - def update_endpoints(self, link_endpoint_uuids : List[Tuple[str, str]] = []) -> bool: + def update_endpoints(self, link_endpoint_names : List[Tuple[str, str]] = []) -> bool: updated = False # 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_uuid, endpoint_uuid in device_endpoint_to_abstract.keys(): - if (device_uuid, endpoint_uuid) in link_endpoint_uuids: continue - # remove endpoint_id that is not in link - self._remove_endpoint(device_uuid, endpoint_uuid) - updated = True + 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) + updated = True # for each endpoint in link that is not in abstract link; add to abstract link - for device_uuid, endpoint_uuid in link_endpoint_uuids: + for device_name, endpoint_name in link_endpoint_names: # if already added; just check endpoint type is not modified - if (device_uuid, endpoint_uuid) 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_uuid, endpoint_uuid) + self._add_endpoint(device_name, endpoint_name) updated = True return updated diff --git a/src/interdomain/service/topology_abstractor/ToDo.txt b/src/interdomain/service/topology_abstractor/ToDo.txt new file mode 100644 index 0000000000000000000000000000000000000000..203a38a9d3aee1b65d1d3f17be9c4e12d48a693b --- /dev/null +++ b/src/interdomain/service/topology_abstractor/ToDo.txt @@ -0,0 +1,22 @@ +for some reason, context(inter):topology(admin) is being created + - applies when topology abstractor is activated + - seems it is not due to interdomain, but DLT + - check if DLT is creating context(inter) and rest of weird entities + - given now IDC works with names, might happen that + - DLT is not recognizing local events + - IDC is sending to DLT wrong records + - revalidate all logs + +- re-validate nfv-sdn'22 demo + +- in domain 1, context(admin)/topo(admin) abstracted domain is shown +- in domain 1, context(admin)/topo(inter) not rendered properly +- in domain 1 there is a wrongly formatted link: +UUID Name Endpoints +2a955dca-7282-51b6-bf02-46be28ad4b0e DC1/D1==R1@D1/DC1 D1 / Device: DC1 + DC1 / Device: R1@D1 +2adc48f1-fbea-5a3d-a7e1-3a28a1351ffa 37b8964d-dac2-5a2b-8bae-35d3154fbf20/DC1==cda90d2f-e7b0-5837-8f2e-2fb29dd9b367/86fce79b-e474-54d7-8a6f-5b2c10cad6c2 + DC1 / Device: D1 + D1 / Device: DC1 + +- in domain 2 it is shown an error in webui while accessing context(d1)/topo(admin) diff --git a/src/interdomain/service/topology_abstractor/Tools.py b/src/interdomain/service/topology_abstractor/Tools.py new file mode 100644 index 0000000000000000000000000000000000000000..e3d640f3cc0150a46c5d122ed822268017806493 --- /dev/null +++ b/src/interdomain/service/topology_abstractor/Tools.py @@ -0,0 +1,86 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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 typing import Dict, Tuple +from common.proto.context_pb2 import Device, Link +from common.tools.context_queries.Context import get_context +from common.tools.context_queries.EndPoint import get_endpoint_names +from common.tools.context_queries.Topology import get_topology +from context.client.ContextClient import ContextClient + +def get_context_name( + context_client : ContextClient, context_names_cache : Dict[str, str], context_uuid : str +) -> str: + if context_uuid not in context_names_cache: + context = get_context(context_client, context_uuid) + context_name = context.name + context_names_cache[context_uuid] = context_name + context_names_cache[context_name] = context_name + else: + context_name = context_names_cache[context_uuid] + return context_name + +def get_topology_name( + context_client : ContextClient, topology_names_cache : Dict[Tuple[str, str], str], + context_name : str, topology_uuid : str +) -> str: + topology_key = (context_name, topology_uuid) + if topology_key not in topology_names_cache: + topology = get_topology(context_client, topology_uuid, context_uuid=context_name) + topology_name = topology.name + topology_names_cache[(context_name, topology_uuid)] = topology_name + topology_names_cache[(context_name, topology_name)] = topology_name + else: + topology_name = topology_names_cache[topology_key] + return topology_name + +def replace_device_uuids_by_names( + context_client : ContextClient, device : Device, context_names_cache : Dict[str, str] = dict(), + topology_names_cache : Dict[Tuple[str, str], str] = dict() +) -> None: + device_name = device.name + device.device_id.device_uuid.uuid = device_name + + for endpoint in device.device_endpoints: + endpoint.endpoint_id.endpoint_uuid.uuid = endpoint.name + endpoint.endpoint_id.device_id.device_uuid.uuid = device_name + + context_uuid = endpoint.endpoint_id.topology_id.context_id.context_uuid.uuid + context_name = get_context_name(context_client, context_names_cache, context_uuid) + endpoint.endpoint_id.topology_id.context_id.context_uuid.uuid = context_name + + topology_uuid = endpoint.endpoint_id.topology_id.topology_uuid.uuid + topology_name = get_topology_name(context_client, topology_names_cache, context_name, topology_uuid) + endpoint.endpoint_id.topology_id.topology_uuid.uuid = topology_name + +def replace_link_uuids_by_names( + context_client : ContextClient, link : Link, context_names_cache : Dict[str, str] = dict(), + topology_names_cache : Dict[Tuple[str, str], str] = dict() +) -> None: + link.link_id.link_uuid.uuid = link.name + + device_names, endpoints_data = get_endpoint_names(context_client, link.link_endpoint_ids) + + # for each endpoint in abstract link, populate internal data structures and mappings + for endpoint_id in link.link_endpoint_ids: + endpoint_id.device_id.device_uuid.uuid = device_names[endpoint_id.device_id.device_uuid.uuid] + endpoint_id.endpoint_uuid.uuid = endpoints_data[endpoint_id.endpoint_uuid.uuid][0] + + context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid + context_name = get_context_name(context_client, context_names_cache, context_uuid) + endpoint_id.topology_id.context_id.context_uuid.uuid = context_name + + topology_uuid = endpoint_id.topology_id.topology_uuid.uuid + topology_name = get_topology_name(context_client, topology_names_cache, context_name, topology_uuid) + endpoint_id.topology_id.topology_uuid.uuid = topology_name diff --git a/src/interdomain/service/topology_abstractor/TopologyAbstractor.py b/src/interdomain/service/topology_abstractor/TopologyAbstractor.py index 0d9faa0408fe77dceaf5652b144590f9beb4a88d..c22c3ec2f6e3e5492625a75a4252e4982e73c19c 100644 --- a/src/interdomain/service/topology_abstractor/TopologyAbstractor.py +++ b/src/interdomain/service/topology_abstractor/TopologyAbstractor.py @@ -13,23 +13,21 @@ # limitations under the License. import logging, threading -from typing import Dict, Optional, Tuple +from typing import Dict, List, Optional, Tuple from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME, ServiceNameEnum from common.DeviceTypes import DeviceTypeEnum from common.Settings import ( ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, find_environment_variables, get_env_var_name) from common.proto.context_pb2 import ( - ContextEvent, ContextId, Device, DeviceEvent, DeviceId, EndPoint, EndPointId, Link, LinkEvent, TopologyId, - TopologyEvent) + ContextId, Device, DeviceEvent, EndPoint, EndPointId, Link, LinkEvent, TopologyId, TopologyEvent) from common.tools.context_queries.CheckType import ( device_type_is_datacenter, device_type_is_network, endpoint_type_is_border) -from common.tools.context_queries.Context import create_context -from common.tools.context_queries.Device import get_uuids_of_devices_in_topology #, get_devices_in_topology -#from common.tools.context_queries.Link import get_links_in_topology -from common.tools.context_queries.Topology import create_missing_topologies -from common.tools.grpc.Tools import grpc_message_to_json_string +from common.tools.context_queries.Context import create_context, get_context +from common.tools.context_queries.Device import get_device, get_devices_in_topology +from common.tools.context_queries.Link import get_link +from common.tools.context_queries.Topology import create_missing_topologies, get_topology_details +from common.tools.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string from common.tools.object_factory.Context import json_context_id -from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.Topology import json_topology_id from context.client.ContextClient import ContextClient from context.client.EventsCollector import EventsCollector @@ -37,8 +35,19 @@ from dlt.connector.client.DltConnectorClient import DltConnectorClient from .AbstractDevice import AbstractDevice from .AbstractLink import AbstractLink from .DltRecordSender import DltRecordSender +from .Tools import replace_device_uuids_by_names, replace_link_uuids_by_names from .Types import EventTypes +# Remark on UUIDs: +# TopologyAbstractor, AbstractDevice and AbstractLink are used +# to compose network reporesentations to be forwarded to remote +# instances. Constraining it to use UUIDs is pointless given +# these UUIDs, to be unique, need to be bound to the local +# context/topology UUIDs, which might be different than that for +# the remote TeraFlowSDN instances. For this very reason, we use +# the device/link/endpoint/topology/context names as UUIDs, to +# prevent UUID-related issues. + LOGGER = logging.getLogger(__name__) ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) @@ -50,10 +59,14 @@ class TopologyAbstractor(threading.Thread): self.terminate = threading.Event() self.context_client = ContextClient() - self.context_event_collector = EventsCollector(self.context_client) + self.context_event_collector = EventsCollector( + self.context_client, activate_context_collector=False, activate_topology_collector=True, + activate_device_collector=True, activate_link_collector=True, activate_service_collector=False, + activate_slice_collector=False, activate_connection_collector=False + ) - self.real_to_abstract_device_uuid : Dict[str, str] = dict() - self.real_to_abstract_link_uuid : Dict[str, str] = dict() + self.real_to_abstract_device : Dict[str, str] = dict() + self.real_to_abstract_link : Dict[str, str] = dict() self.abstract_device_to_topology_id : Dict[str, TopologyId] = dict() self.abstract_link_to_topology_id : Dict[str, TopologyId] = dict() @@ -61,17 +74,22 @@ class TopologyAbstractor(threading.Thread): self.abstract_devices : Dict[str, AbstractDevice] = dict() self.abstract_links : Dict[Tuple[str,str], AbstractLink] = dict() + self.context_names_cache : Dict[str, str] = dict() + self.topology_names_cache : Dict[Tuple[str, str], str] = dict() + def stop(self): self.terminate.set() def run(self) -> None: + LOGGER.info('Starting...') self.context_client.connect() create_context(self.context_client, DEFAULT_CONTEXT_NAME) - topology_uuids = [DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME] - create_missing_topologies(self.context_client, ADMIN_CONTEXT_ID, topology_uuids) + topology_names = [DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME] + create_missing_topologies(self.context_client, ADMIN_CONTEXT_ID, topology_names) self.context_event_collector.start() + LOGGER.info('Running...') while not self.terminate.is_set(): event = self.context_event_collector.get_event(timeout=0.1) if event is None: continue @@ -79,6 +97,7 @@ class TopologyAbstractor(threading.Thread): LOGGER.info('Processing Event({:s})...'.format(grpc_message_to_json_string(event))) self.update_abstraction(event) + LOGGER.info('Stopping...') self.context_event_collector.stop() self.context_client.close() @@ -100,129 +119,177 @@ class TopologyAbstractor(threading.Thread): # return False def _get_or_create_abstract_device( - self, device_uuid : str, device_name : str, device_type : DeviceTypeEnum, dlt_record_sender : DltRecordSender, + self, device_name : str, device_type : DeviceTypeEnum, dlt_record_sender : DltRecordSender, abstract_topology_id : TopologyId ) -> AbstractDevice: - abstract_device = self.abstract_devices.get(device_uuid) + abstract_device = self.abstract_devices.get(device_name) changed = False if abstract_device is None: - abstract_device = AbstractDevice(device_uuid, device_name, device_type) + abstract_device = AbstractDevice(device_name, device_type) changed = abstract_device.initialize() if changed: dlt_record_sender.add_device(abstract_topology_id, abstract_device.device) - self.abstract_devices[device_uuid] = abstract_device - self.abstract_device_to_topology_id[device_uuid] = abstract_topology_id + self.abstract_devices[device_name] = abstract_device + self.abstract_device_to_topology_id[device_name] = abstract_topology_id return abstract_device def _update_abstract_device( self, device : Device, dlt_record_sender : DltRecordSender, abstract_topology_id : TopologyId, - abstract_device_uuid : Optional[str] = None + abstract_device_name : Optional[str] = None ) -> None: - device_uuid = device.device_id.device_uuid.uuid device_name = device.name if device_type_is_datacenter(device.device_type): - abstract_device_uuid = device_uuid + abstract_device_name = device_name abstract_device = self._get_or_create_abstract_device( - device_uuid, device_name, DeviceTypeEnum.EMULATED_DATACENTER, dlt_record_sender, abstract_topology_id) + device_name, DeviceTypeEnum.EMULATED_DATACENTER, dlt_record_sender, abstract_topology_id) elif device_type_is_network(device.device_type): LOGGER.warning('device_type is network; not implemented') return else: abstract_device = self._get_or_create_abstract_device( - abstract_device_uuid, None, DeviceTypeEnum.NETWORK, dlt_record_sender, abstract_topology_id) - self.real_to_abstract_device_uuid[device_uuid] = abstract_device_uuid + abstract_device_name, DeviceTypeEnum.NETWORK, dlt_record_sender, abstract_topology_id) + self.real_to_abstract_device[device_name] = abstract_device_name changed = abstract_device.update_endpoints(device) if changed: dlt_record_sender.add_device(abstract_topology_id, abstract_device.device) def _get_or_create_abstract_link( - self, link_uuid : str, dlt_record_sender : DltRecordSender, abstract_topology_id : TopologyId + self, link_name : str, dlt_record_sender : DltRecordSender, abstract_topology_id : TopologyId ) -> AbstractLink: - abstract_link = self.abstract_links.get(link_uuid) + abstract_link = self.abstract_links.get(link_name) changed = False if abstract_link is None: - abstract_link = AbstractLink(link_uuid) + abstract_link = AbstractLink(link_name) changed = abstract_link.initialize() if changed: dlt_record_sender.add_link(abstract_topology_id, abstract_link.link) - self.abstract_links[link_uuid] = abstract_link - self.abstract_link_to_topology_id[link_uuid] = abstract_topology_id + self.abstract_links[link_name] = abstract_link + self.abstract_link_to_topology_id[link_name] = abstract_topology_id return abstract_link def _get_link_endpoint_data(self, endpoint_id : EndPointId) -> Optional[Tuple[AbstractDevice, EndPoint]]: - device_uuid : str = endpoint_id.device_id.device_uuid.uuid - endpoint_uuid : str = endpoint_id.endpoint_uuid.uuid - abstract_device_uuid = self.real_to_abstract_device_uuid.get(device_uuid) - if abstract_device_uuid is None: return None - abstract_device = self.abstract_devices.get(abstract_device_uuid) + device_name : str = endpoint_id.device_id.device_uuid.uuid + endpoint_name : str = endpoint_id.endpoint_uuid.uuid + abstract_device_name = self.real_to_abstract_device.get(device_name) + if abstract_device_name is None: return None + abstract_device = self.abstract_devices.get(abstract_device_name) if abstract_device is None: return None - endpoint = abstract_device.get_endpoint(device_uuid, endpoint_uuid) + endpoint = abstract_device.get_endpoint(device_name, endpoint_name) if endpoint is None: return None return abstract_device, endpoint - def _compute_abstract_link(self, link : Link) -> Optional[str]: - if len(link.link_endpoint_ids) != 2: return None + def _compute_abstract_link(self, link : Link) -> Optional[Tuple[str, List[Tuple[str, str]]]]: + LOGGER.info('[_compute_abstract_link] link={:s}'.format(grpc_message_to_json_string(link))) + if len(link.link_endpoint_ids) != 2: + LOGGER.warning('[_compute_abstract_link] !=2 eps') + return None link_endpoint_data_A = self._get_link_endpoint_data(link.link_endpoint_ids[0]) - if link_endpoint_data_A is None: return None + if link_endpoint_data_A is None: + LOGGER.warning('[_compute_abstract_link] link_endpoint_data_A is None') + return None abstract_device_A, endpoint_A = link_endpoint_data_A - if not endpoint_type_is_border(endpoint_A.endpoint_type): return None + LOGGER.info('[_compute_abstract_link] abstract_device_A={:s}'.format(str(abstract_device_A.to_json()))) + LOGGER.info('[_compute_abstract_link] endpoint_A={:s}'.format(grpc_message_to_json_string(endpoint_A))) + if not endpoint_type_is_border(endpoint_A.endpoint_type): + LOGGER.warning('[_compute_abstract_link] endpoint_A not border') + return None link_endpoint_data_Z = self._get_link_endpoint_data(link.link_endpoint_ids[-1]) - if link_endpoint_data_Z is None: return None + if link_endpoint_data_Z is None: + LOGGER.warning('[_compute_abstract_link] link_endpoint_data_Z is None') + return None abstract_device_Z, endpoint_Z = link_endpoint_data_Z - if not endpoint_type_is_border(endpoint_Z.endpoint_type): return None - - link_uuid = AbstractLink.compose_uuid( - abstract_device_A.uuid, endpoint_A.endpoint_id.endpoint_uuid.uuid, - abstract_device_Z.uuid, endpoint_Z.endpoint_id.endpoint_uuid.uuid + LOGGER.info('[_compute_abstract_link] abstract_device_Z={:s}'.format(str(abstract_device_Z.to_json()))) + LOGGER.info('[_compute_abstract_link] endpoint_Z={:s}'.format(grpc_message_to_json_string(endpoint_Z))) + if not endpoint_type_is_border(endpoint_Z.endpoint_type): + LOGGER.warning('[_compute_abstract_link] endpoint_Z not border') + return None + + link_name = AbstractLink.compose_name( + abstract_device_A.name, endpoint_A.name, + abstract_device_Z.name, endpoint_Z.name ) + LOGGER.info('[_compute_abstract_link] link_name={:s}'.format(str(link_name))) # sort endpoints lexicographically to prevent duplicities - link_endpoint_uuids = sorted([ - (abstract_device_A.uuid, endpoint_A.endpoint_id.endpoint_uuid.uuid), - (abstract_device_Z.uuid, endpoint_Z.endpoint_id.endpoint_uuid.uuid) + link_endpoint_names = sorted([ + (abstract_device_A.name, endpoint_A.name), + (abstract_device_Z.name, endpoint_Z.name) ]) + LOGGER.info('[_compute_abstract_link] link_endpoint_names={:s}'.format(str(link_endpoint_names))) - return link_uuid, link_endpoint_uuids + return link_name, link_endpoint_names def _update_abstract_link( self, link : Link, dlt_record_sender : DltRecordSender, abstract_topology_id : TopologyId ) -> None: - abstract_link_specs = self._compute_abstract_link(link) - if abstract_link_specs is None: return - abstract_link_uuid, link_endpoint_uuids = abstract_link_specs + LOGGER.info('[_update_abstract_link] link={:s}'.format(grpc_message_to_json_string(link))) + LOGGER.info('[_update_abstract_link] abstract_topology_id={:s}'.format(grpc_message_to_json_string(abstract_topology_id))) - abstract_link = self._get_or_create_abstract_link(abstract_link_uuid, dlt_record_sender, abstract_topology_id) - link_uuid = link.link_id.link_uuid.uuid - self.real_to_abstract_link_uuid[link_uuid] = abstract_link_uuid - changed = abstract_link.update_endpoints(link_endpoint_uuids) + abstract_link_specs = self._compute_abstract_link(link) + if abstract_link_specs is None: + LOGGER.warning('[_update_abstract_link] abstract_link_specs is None') + return + abstract_link_name, link_endpoint_names = abstract_link_specs + LOGGER.info('[_update_abstract_link] abstract_link_name={:s}'.format(str(abstract_link_name))) + LOGGER.info('[_update_abstract_link] link_endpoint_names={:s}'.format(str(link_endpoint_names))) + + abstract_link = self._get_or_create_abstract_link(abstract_link_name, dlt_record_sender, abstract_topology_id) + LOGGER.info('[_update_abstract_link] abstract_link={:s}'.format(str(abstract_link.to_json()))) + link_name = link.name + LOGGER.info('[_update_abstract_link] link_name={:s}'.format(str(link_name))) + self.real_to_abstract_link[link_name] = abstract_link_name + changed = abstract_link.update_endpoints(link_endpoint_names) + LOGGER.info('[_update_abstract_link] changed={:s}'.format(str(changed))) if changed: dlt_record_sender.add_link(abstract_topology_id, abstract_link.link) def _infer_abstract_links(self, device : Device, dlt_record_sender : DltRecordSender) -> None: - device_uuid = device.device_id.device_uuid.uuid + device_name = device.name + LOGGER.info('[_infer_abstract_links] device_name={:s}'.format(str(device_name))) - interdomain_device_uuids = get_uuids_of_devices_in_topology( + interdomain_devices = get_devices_in_topology( self.context_client, ADMIN_CONTEXT_ID, INTERDOMAIN_TOPOLOGY_NAME) + interdomain_devices = { + interdomain_device.name : interdomain_device + for interdomain_device in interdomain_devices + } + str_interdomain_devices = { + interdomain_device_name : grpc_message_to_json(interdomain_device) + for interdomain_device_name,interdomain_device in interdomain_devices.items() + } + LOGGER.info('[_infer_abstract_links] interdomain_devices={:s}'.format(str(str_interdomain_devices))) for endpoint in device.device_endpoints: + LOGGER.info('[_infer_abstract_links] endpoint={:s}'.format(grpc_message_to_json_string(endpoint))) if not endpoint_type_is_border(endpoint.endpoint_type): continue - endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid - - abstract_link_uuid = AbstractLink.compose_uuid(device_uuid, endpoint_uuid, endpoint_uuid, device_uuid) - if abstract_link_uuid in self.abstract_links: continue - - if endpoint_uuid not in interdomain_device_uuids: continue - remote_device = self.context_client.GetDevice(DeviceId(**json_device_id(endpoint_uuid))) - remote_device_border_endpoint_uuids = { - endpoint.endpoint_id.endpoint_uuid.uuid : endpoint.endpoint_type + endpoint_name = endpoint.name + LOGGER.info('[_infer_abstract_links] endpoint_name={:s}'.format(str(endpoint_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_links={:s}'.format(str({ + 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 + + remote_device = interdomain_devices.get(endpoint_name) + LOGGER.info('[_infer_abstract_links] remote_device={:s}'.format(grpc_message_to_json_string(remote_device))) + if remote_device is None: continue + + remote_device_border_endpoint_names = { + endpoint.name : endpoint.endpoint_type for endpoint in remote_device.device_endpoints if endpoint_type_is_border(endpoint.endpoint_type) } - if device_uuid not in remote_device_border_endpoint_uuids: continue + LOGGER.info('[_infer_abstract_links] remote_device_border_endpoint_names={:s}'.format( + str(remote_device_border_endpoint_names))) + if device_name not in remote_device_border_endpoint_names: continue - link_endpoint_uuids = sorted([(device_uuid, endpoint_uuid), (endpoint_uuid, device_uuid)]) + link_endpoint_names = sorted([(device_name, endpoint_name), (endpoint_name, device_name)]) + LOGGER.info('[_infer_abstract_links] link_endpoint_names={:s}'.format(str(link_endpoint_names))) abstract_link = self._get_or_create_abstract_link( - abstract_link_uuid, dlt_record_sender, INTERDOMAIN_TOPOLOGY_ID) - changed = abstract_link.update_endpoints(link_endpoint_uuids) + abstract_link_name, dlt_record_sender, INTERDOMAIN_TOPOLOGY_ID) + LOGGER.info('[_infer_abstract_links] abstract_link={:s}'.format(str(abstract_link.to_json()))) + changed = abstract_link.update_endpoints(link_endpoint_names) if changed: dlt_record_sender.add_link(INTERDOMAIN_TOPOLOGY_ID, abstract_link.link) def update_abstraction(self, event : EventTypes) -> None: @@ -239,77 +306,136 @@ class TopologyAbstractor(threading.Thread): dlt_record_sender = DltRecordSender(self.context_client, dlt_connector_client) - if isinstance(event, ContextEvent): - LOGGER.debug('Processing ContextEvent({:s})'.format(grpc_message_to_json_string(event))) - LOGGER.warning('Ignoring ContextEvent({:s})'.format(grpc_message_to_json_string(event))) + if isinstance(event, TopologyEvent): + self._process_event_topology(event, dlt_record_sender) + elif isinstance(event, DeviceEvent): + self._process_event_device(event, dlt_record_sender) + elif isinstance(event, LinkEvent): + self._process_event_link(event, dlt_record_sender) + else: + LOGGER.warning('Unsupported Event({:s})'.format(grpc_message_to_json_string(event))) - elif isinstance(event, TopologyEvent): - LOGGER.debug('Processing TopologyEvent({:s})'.format(grpc_message_to_json_string(event))) - topology_id = event.topology_id - topology_uuid = topology_id.topology_uuid.uuid - context_id = topology_id.context_id - context_uuid = context_id.context_uuid.uuid - topology_uuids = {DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME} + dlt_record_sender.commit() + if dlt_connector_client is not None: dlt_connector_client.close() - context = self.context_client.GetContext(context_id) - context_name = context.name + def _process_event_topology(self, event : TopologyEvent, dlt_record_sender : DltRecordSender) -> None: + 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 + topology_uuids = {DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME} + + context = get_context(self.context_client, context_uuid, rw_copy=True) + if context is None: + MSG = 'Ignoring TopologyEvent({:s})... Context not found' + LOGGER.warning(MSG.format(grpc_message_to_json_string(event))) + return - topology_details = self.context_client.GetTopologyDetails(topology_id) - topology_name = topology_details.name + context_name = context.name + context.context_id.context_uuid.uuid = context_name - if ((context_uuid == DEFAULT_CONTEXT_NAME) or (context_name == DEFAULT_CONTEXT_NAME)) and \ - (topology_uuid not in topology_uuids) and (topology_name not in topology_uuids): + topology_details = get_topology_details( + self.context_client, topology_uuid, context_uuid=context_uuid, rw_copy=True) + if topology_details is None: + MSG = 'Ignoring TopologyEvent({:s})... TopologyDetails not found' + LOGGER.warning(MSG.format(grpc_message_to_json_string(event))) + return - abstract_topology_id = TopologyId(**json_topology_id(topology_uuid, context_id=ADMIN_CONTEXT_ID)) - self._get_or_create_abstract_device( - topology_uuid, topology_name, DeviceTypeEnum.NETWORK, dlt_record_sender, abstract_topology_id) + topology_name = topology_details.name + topology_details.topology_id.topology_uuid.uuid = topology_name + topology_details.topology_id.context_id.context_uuid.uuid = context_name + + LOGGER.info(' context_uuid={:s}'.format(str(context_uuid))) + LOGGER.info(' context_name={:s}'.format(str(context_name))) + LOGGER.info(' DEFAULT_CONTEXT_NAME={:s}'.format(str(DEFAULT_CONTEXT_NAME))) + if (context_uuid != DEFAULT_CONTEXT_NAME) and (context_name != DEFAULT_CONTEXT_NAME): + MSG = 'Ignoring ({:s}/{:s})({:s}/{:s}) TopologyEvent({:s})... Wrong context name' + args = context_uuid, context_name, topology_uuid, topology_name, grpc_message_to_json_string(event) + LOGGER.warning(MSG.format(*args)) + return - #devices = get_devices_in_topology(self.context_client, context_id, topology_uuid) - for device in topology_details.devices: - self._update_abstract_device( - device, dlt_record_sender, abstract_topology_id, abstract_device_uuid=topology_uuid) + LOGGER.info(' topology_uuid={:s}'.format(str(topology_uuid))) + 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/interdomain topology' + args = context_uuid, context_name, topology_uuid, topology_name, grpc_message_to_json_string(event) + LOGGER.warning(MSG.format(*args)) + return - #links = get_links_in_topology(self.context_client, context_id, topology_uuid) - for link in topology_details.links: - self._update_abstract_link(link, dlt_record_sender, abstract_topology_id) - - for device in topology_details.devices: - self._infer_abstract_links(device, dlt_record_sender) + abstract_topology_id = TopologyId(**json_topology_id(topology_name, context_id=ADMIN_CONTEXT_ID)) + self._get_or_create_abstract_device( + topology_name, DeviceTypeEnum.NETWORK, dlt_record_sender, abstract_topology_id) - else: - MSG = 'Ignoring ({:s}/{:s})({:s}/{:s}) TopologyEvent({:s})' - args = context_uuid, context_name, topology_uuid, topology_name, grpc_message_to_json_string(event) - LOGGER.warning(MSG.format(*args)) + for device in topology_details.devices: + replace_device_uuids_by_names( + self.context_client, device, context_names_cache=self.context_names_cache, + topology_names_cache=self.topology_names_cache) + self._update_abstract_device( + device, dlt_record_sender, abstract_topology_id, abstract_device_name=topology_name) - elif isinstance(event, DeviceEvent): - LOGGER.debug('Processing DeviceEvent({:s})'.format(grpc_message_to_json_string(event))) - device_id = event.device_id - device_uuid = device_id.device_uuid.uuid - abstract_device_uuid = self.real_to_abstract_device_uuid.get(device_uuid) - device = self.context_client.GetDevice(device_id) - if abstract_device_uuid is None: - LOGGER.warning('Ignoring DeviceEvent({:s})'.format(grpc_message_to_json_string(event))) - else: - abstract_topology_id = self.abstract_device_to_topology_id[abstract_device_uuid] - self._update_abstract_device( - device, dlt_record_sender, abstract_topology_id, abstract_device_uuid=abstract_device_uuid) + for link in topology_details.links: + replace_link_uuids_by_names( + self.context_client, link, context_names_cache=self.context_names_cache, + topology_names_cache=self.topology_names_cache) + self._update_abstract_link(link, dlt_record_sender, abstract_topology_id) + for device in topology_details.devices: self._infer_abstract_links(device, dlt_record_sender) - elif isinstance(event, LinkEvent): - LOGGER.debug('Processing LinkEvent({:s})'.format(grpc_message_to_json_string(event))) - link_id = event.link_id - link_uuid = link_id.link_uuid.uuid - abstract_link_uuid = self.real_to_abstract_link_uuid.get(link_uuid) - if abstract_link_uuid is None: - LOGGER.warning('Ignoring LinkEvent({:s})'.format(grpc_message_to_json_string(event))) - else: - abstract_topology_id = self.abstract_link_to_topology_id[abstract_link_uuid] - link = self.context_client.GetLink(link_id) - self._update_abstract_link(link, dlt_record_sender, abstract_topology_id) + def _process_event_device(self, event : DeviceEvent, dlt_record_sender : DltRecordSender) -> None: + LOGGER.info('Processing DeviceEvent({:s})'.format(grpc_message_to_json_string(event))) + device_uuid = event.device_id.device_uuid.uuid + device = get_device( + self.context_client, device_uuid, rw_copy=True, include_endpoints=True, + include_config_rules=False, include_components=False) + if device is None: + MSG = 'Ignoring DeviceEvent({:s})... Device not found' + LOGGER.warning(MSG.format(grpc_message_to_json_string(event))) + return + + replace_device_uuids_by_names( + self.context_client, device, context_names_cache=self.context_names_cache, + topology_names_cache=self.topology_names_cache) + + device_name = device.name + LOGGER.info(' device_name={:s}'.format(str(device_name))) + LOGGER.info(' real_to_abstract_device={:s}'.format(str(self.real_to_abstract_device))) + abstract_device_name = self.real_to_abstract_device.get(device_name) + if abstract_device_name is None: + MSG = 'Ignoring DeviceEvent({:s}). Abstract Device not found' + LOGGER.warning(MSG.format(grpc_message_to_json_string(event))) else: - LOGGER.warning('Unsupported Event({:s})'.format(grpc_message_to_json_string(event))) + 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) - dlt_record_sender.commit() - if dlt_connector_client is not None: dlt_connector_client.close() + 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.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) + if link is None: + MSG = ' Ignoring LinkEvent({:s})... Link not found' + LOGGER.warning(MSG.format(grpc_message_to_json_string(event))) + return + + replace_link_uuids_by_names( + self.context_client, link, context_names_cache=self.context_names_cache, + topology_names_cache=self.topology_names_cache) + + link_name = link.name + LOGGER.info(' link_name={:s}'.format(str(link_name))) + LOGGER.info(' real_to_abstract_link={:s}'.format(str(self.real_to_abstract_link))) + abstract_link_name = self.real_to_abstract_link.get(link_name) + if abstract_link_name is None: + MSG = ' Ignoring LinkEvent({:s}). Abstract Link not found' + LOGGER.warning(MSG.format(grpc_message_to_json_string(event))) + return + + abstract_topology_id = self.abstract_link_to_topology_id[abstract_link_name] + self._update_abstract_link(link, dlt_record_sender, abstract_topology_id) diff --git a/src/tests/scenario2/deploy_all.sh b/src/tests/scenario2/deploy_all.sh index 1eac2e4da701d2f2c60f8690c4784b59522a8b72..a8e93d139e4b3e02891836a4ba02b7b90d35b462 100755 --- a/src/tests/scenario2/deploy_all.sh +++ b/src/tests/scenario2/deploy_all.sh @@ -45,12 +45,12 @@ source nfvsdn22/deploy_specs_dom2.sh ./deploy/all.sh mv tfs_runtime_env_vars.sh tfs_runtime_env_vars_dom2.sh -# Deploy TFS for Domain 3 -source nfvsdn22/deploy_specs_dom3.sh -./deploy/all.sh -mv tfs_runtime_env_vars.sh tfs_runtime_env_vars_dom3.sh - -# Deploy TFS for Domain 4 -source nfvsdn22/deploy_specs_dom4.sh -./deploy/all.sh -mv tfs_runtime_env_vars.sh tfs_runtime_env_vars_dom4.sh +## Deploy TFS for Domain 3 +#source nfvsdn22/deploy_specs_dom3.sh +#./deploy/all.sh +#mv tfs_runtime_env_vars.sh tfs_runtime_env_vars_dom3.sh +# +## Deploy TFS for Domain 4 +#source nfvsdn22/deploy_specs_dom4.sh +#./deploy/all.sh +#mv tfs_runtime_env_vars.sh tfs_runtime_env_vars_dom4.sh diff --git a/src/tests/scenario2/descriptors/domain1.json b/src/tests/scenario2/descriptors/domain1.json index 043b3955f017631203a437cf853c3617cddf93c8..3e2c79a4f841887e721dbb1590b4efd7ca6078e9 100644 --- a/src/tests/scenario2/descriptors/domain1.json +++ b/src/tests/scenario2/descriptors/domain1.json @@ -1,32 +1,10 @@ { "contexts": [ - { - "context_id": {"context_uuid": {"uuid": "admin"}}, - "topology_ids": [ - {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"}} - ], "service_ids": [] - } + {"context_id": {"context_uuid": {"uuid": "admin"}}} ], "topologies": [ - { - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"}}, - "device_ids": [ - {"device_uuid": {"uuid": "DC1"}}, - {"device_uuid": {"uuid": "R1@D1"}}, - {"device_uuid": {"uuid": "R2@D1"}}, - {"device_uuid": {"uuid": "R3@D1"}}, - {"device_uuid": {"uuid": "R4@D1"}}, - {"device_uuid": {"uuid": "R5@D1"}} - ], "link_ids": [ - {"link_uuid": {"uuid": "DC1/D1==R1@D1/DC1"}}, - {"link_uuid": {"uuid": "R1@D1/2==R2@D1/1"}}, - {"link_uuid": {"uuid": "R2@D1/3==R3@D1/2"}}, - {"link_uuid": {"uuid": "R2@D1/5==R5@D1/2"}}, - {"link_uuid": {"uuid": "R3@D1/4==R4@D1/3"}}, - {"link_uuid": {"uuid": "R4@D1/5==R5@D1/4"}}, - {"link_uuid": {"uuid": "R5@D1/1==R1@D1/5"}} - ] - } + {"topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "inter"}}}, + {"topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"}}} ], "devices": [ { @@ -35,8 +13,8 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/border", "uuid": "D1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "int"} + {"uuid": "D1", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "inter"}, + {"uuid": "int", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "inter"} ]}}} ]} }, @@ -46,9 +24,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "5"}, - {"sample_types": [], "type": "copper/border", "uuid": "DC1"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "5", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "DC1", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D1"} ]}}} ]} }, @@ -58,9 +36,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "3"}, - {"sample_types": [], "type": "copper/internal", "uuid": "5"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "5", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"} ]}}} ]} }, @@ -70,8 +48,8 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "4"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "4", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"} ]}}} ]} }, @@ -81,9 +59,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "3"}, - {"sample_types": [], "type": "copper/internal", "uuid": "5"}, - {"sample_types": [], "type": "copper/border", "uuid": "D2"} + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "5", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "D2", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D1"} ]}}} ]} }, @@ -93,55 +71,73 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "4"}, - {"sample_types": [], "type": "copper/border", "uuid": "D3"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "4", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D1"}, + {"uuid": "D3", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D1"} ]}}} ]} } ], "links": [ - { - "link_id": {"link_uuid": {"uuid": "DC1/D1==R1@D1/DC1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "DC1"}}, "endpoint_uuid": {"uuid": "D1"}}, - {"device_id": {"device_uuid": {"uuid": "R1@D1"}}, "endpoint_uuid": {"uuid": "DC1"}} - ] - }, { "link_id": {"link_uuid": {"uuid": "R1@D1/2==R2@D1/1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1@D1"}}, "endpoint_uuid": {"uuid": "2"}}, - {"device_id": {"device_uuid": {"uuid": "R2@D1"}}, "endpoint_uuid": {"uuid": "1"}} + {"device_id": {"device_uuid": {"uuid": "R1@D1"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }}, + {"device_id": {"device_uuid": {"uuid": "R2@D1"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D1/3==R3@D1/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D1"}}, "endpoint_uuid": {"uuid": "3"}}, - {"device_id": {"device_uuid": {"uuid": "R3@D1"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D1"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }}, + {"device_id": {"device_uuid": {"uuid": "R3@D1"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D1/5==R5@D1/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D1"}}, "endpoint_uuid": {"uuid": "5"}}, - {"device_id": {"device_uuid": {"uuid": "R5@D1"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D1"}}, "endpoint_uuid": {"uuid": "5"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }}, + {"device_id": {"device_uuid": {"uuid": "R5@D1"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R3@D1/4==R4@D1/3"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R3@D1"}}, "endpoint_uuid": {"uuid": "4"}}, - {"device_id": {"device_uuid": {"uuid": "R4@D1"}}, "endpoint_uuid": {"uuid": "3"}} + {"device_id": {"device_uuid": {"uuid": "R3@D1"}}, "endpoint_uuid": {"uuid": "4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }}, + {"device_id": {"device_uuid": {"uuid": "R4@D1"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R4@D1/5==R5@D1/4"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R4@D1"}}, "endpoint_uuid": {"uuid": "5"}}, - {"device_id": {"device_uuid": {"uuid": "R5@D1"}}, "endpoint_uuid": {"uuid": "4"}} + {"device_id": {"device_uuid": {"uuid": "R4@D1"}}, "endpoint_uuid": {"uuid": "5"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }}, + {"device_id": {"device_uuid": {"uuid": "R5@D1"}}, "endpoint_uuid": {"uuid": "4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R5@D1/1==R1@D1/5"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R5@D1"}}, "endpoint_uuid": {"uuid": "1"}}, - {"device_id": {"device_uuid": {"uuid": "R1@D1"}}, "endpoint_uuid": {"uuid": "5"}} + {"device_id": {"device_uuid": {"uuid": "R5@D1"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }}, + {"device_id": {"device_uuid": {"uuid": "R1@D1"}}, "endpoint_uuid": {"uuid": "5"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D1"} + }} ] } ] diff --git a/src/tests/scenario2/descriptors/domain2.json b/src/tests/scenario2/descriptors/domain2.json index 81d397abfd3571b1177a06172188b00eed2f3afc..6e25d3891ba9fadc8720abf59597dfc220903569 100644 --- a/src/tests/scenario2/descriptors/domain2.json +++ b/src/tests/scenario2/descriptors/domain2.json @@ -1,34 +1,9 @@ { "contexts": [ - { - "context_id": {"context_uuid": {"uuid": "admin"}}, - "topology_ids": [ - {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"}} - ], "service_ids": [] - } + {"context_id": {"context_uuid": {"uuid": "admin"}}} ], "topologies": [ - { - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"}}, - "device_ids": [ - {"device_uuid": {"uuid": "R1@D2"}}, - {"device_uuid": {"uuid": "R2@D2"}}, - {"device_uuid": {"uuid": "R3@D2"}}, - {"device_uuid": {"uuid": "R4@D2"}}, - {"device_uuid": {"uuid": "R5@D2"}}, - {"device_uuid": {"uuid": "R6@D2"}} - ], "link_ids": [ - {"link_uuid": {"uuid": "R1@D2/2==R2@D2/1"}}, - {"link_uuid": {"uuid": "R1@D2/6==R6@D2/1"}}, - {"link_uuid": {"uuid": "R1@D2/5==R5@D2/1"}}, - {"link_uuid": {"uuid": "R2@D2/3==R3@D2/2"}}, - {"link_uuid": {"uuid": "R2@D2/4==R4@D2/2"}}, - {"link_uuid": {"uuid": "R2@D2/5==R5@D2/2"}}, - {"link_uuid": {"uuid": "R2@D2/6==R6@D2/2"}}, - {"link_uuid": {"uuid": "R3@D2/6==R6@D2/3"}}, - {"link_uuid": {"uuid": "R4@D2/5==R5@D2/4"}} - ] - } + {"topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"}}} ], "devices": [ { @@ -37,10 +12,10 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "5"}, - {"sample_types": [], "type": "copper/internal", "uuid": "6"}, - {"sample_types": [], "type": "copper/border", "uuid": "D1"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "5", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "6", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "D1", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D2"} ]}}} ]} }, @@ -50,11 +25,11 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "3"}, - {"sample_types": [], "type": "copper/internal", "uuid": "4"}, - {"sample_types": [], "type": "copper/internal", "uuid": "5"}, - {"sample_types": [], "type": "copper/internal", "uuid": "6"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "4", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "5", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "6", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"} ]}}} ]} }, @@ -64,8 +39,8 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "6"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "6", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"} ]}}} ]} }, @@ -75,9 +50,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "5"}, - {"sample_types": [], "type": "copper/border", "uuid": "D4"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "5", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "D4", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D2"} ]}}} ]} }, @@ -87,10 +62,10 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "4"}, - {"sample_types": [], "type": "copper/border", "uuid": "D3"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "4", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "D3", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D2"} ]}}} ]} }, @@ -100,9 +75,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "3"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"}, + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D2"} ]}}} ]} } @@ -110,56 +85,92 @@ "links": [ { "link_id": {"link_uuid": {"uuid": "R1@D2/2==R2@D2/1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1@D2"}}, "endpoint_uuid": {"uuid": "2"}}, - {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "1"}} + {"device_id": {"device_uuid": {"uuid": "R1@D2"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R1@D2/6==R6@D2/1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1@D2"}}, "endpoint_uuid": {"uuid": "6"}}, - {"device_id": {"device_uuid": {"uuid": "R6@D2"}}, "endpoint_uuid": {"uuid": "1"}} + {"device_id": {"device_uuid": {"uuid": "R1@D2"}}, "endpoint_uuid": {"uuid": "6"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R6@D2"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R1@D2/5==R5@D2/1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1@D2"}}, "endpoint_uuid": {"uuid": "5"}}, - {"device_id": {"device_uuid": {"uuid": "R5@D2"}}, "endpoint_uuid": {"uuid": "1"}} + {"device_id": {"device_uuid": {"uuid": "R1@D2"}}, "endpoint_uuid": {"uuid": "5"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R5@D2"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D2/3==R3@D2/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "3"}}, - {"device_id": {"device_uuid": {"uuid": "R3@D2"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R3@D2"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D2/4==R4@D2/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "4"}}, - {"device_id": {"device_uuid": {"uuid": "R4@D2"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R4@D2"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D2/5==R5@D2/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "5"}}, - {"device_id": {"device_uuid": {"uuid": "R5@D2"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "5"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R5@D2"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D2/6==R6@D2/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "6"}}, - {"device_id": {"device_uuid": {"uuid": "R6@D2"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D2"}}, "endpoint_uuid": {"uuid": "6"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R6@D2"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R3@D2/6==R6@D2/3"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R3@D2"}}, "endpoint_uuid": {"uuid": "6"}}, - {"device_id": {"device_uuid": {"uuid": "R6@D2"}}, "endpoint_uuid": {"uuid": "3"}} + {"device_id": {"device_uuid": {"uuid": "R3@D2"}}, "endpoint_uuid": {"uuid": "6"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R6@D2"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R4@D2/5==R5@D2/4"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R4@D2"}}, "endpoint_uuid": {"uuid": "5"}}, - {"device_id": {"device_uuid": {"uuid": "R5@D2"}}, "endpoint_uuid": {"uuid": "4"}} + {"device_id": {"device_uuid": {"uuid": "R4@D2"}}, "endpoint_uuid": {"uuid": "5"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }}, + {"device_id": {"device_uuid": {"uuid": "R5@D2"}}, "endpoint_uuid": {"uuid": "4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D2"} + }} ] } ] diff --git a/src/tests/scenario2/descriptors/domain3.json b/src/tests/scenario2/descriptors/domain3.json index 3a8e47d30dcef471b388f46d4ba5df5df4716256..f4655b82f138141510a9fde4814a13fa7965e0bd 100644 --- a/src/tests/scenario2/descriptors/domain3.json +++ b/src/tests/scenario2/descriptors/domain3.json @@ -1,28 +1,9 @@ { "contexts": [ - { - "context_id": {"context_uuid": {"uuid": "admin"}}, - "topology_ids": [ - {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"}} - ], "service_ids": [] - } + {"context_id": {"context_uuid": {"uuid": "admin"}}} ], "topologies": [ - { - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"}}, - "device_ids": [ - {"device_uuid": {"uuid": "R1@D3"}}, - {"device_uuid": {"uuid": "R2@D3"}}, - {"device_uuid": {"uuid": "R3@D3"}}, - {"device_uuid": {"uuid": "R4@D3"}} - ], "link_ids": [ - {"link_uuid": {"uuid": "R1@D3/2==R2@D3/1"}}, - {"link_uuid": {"uuid": "R2@D3/3==R3@D3/2"}}, - {"link_uuid": {"uuid": "R3@D3/4==R4@D3/3"}}, - {"link_uuid": {"uuid": "R4@D3/1==R1@D3/4"}}, - {"link_uuid": {"uuid": "R2@D3/4==R4@D3/2"}} - ] - } + {"topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"}}} ], "devices": [ { @@ -31,9 +12,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "4"}, - {"sample_types": [], "type": "copper/border", "uuid": "D1"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "4", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "D1", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "inter"} ]}}} ]} }, @@ -43,10 +24,10 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "3"}, - {"sample_types": [], "type": "copper/internal", "uuid": "4"}, - {"sample_types": [], "type": "copper/border", "uuid": "D2"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "4", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "D2", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "inter"} ]}}} ]} }, @@ -56,9 +37,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "4"}, - {"sample_types": [], "type": "copper/border", "uuid": "D4"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "4", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "D4", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "inter"} ]}}} ]} }, @@ -68,9 +49,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "3"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"}, + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "admin"} ]}}} ]} } @@ -78,32 +59,52 @@ "links": [ { "link_id": {"link_uuid": {"uuid": "R1@D3/2==R2@D3/1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1@D3"}}, "endpoint_uuid": {"uuid": "2"}}, - {"device_id": {"device_uuid": {"uuid": "R2@D3"}}, "endpoint_uuid": {"uuid": "1"}} + {"device_id": {"device_uuid": {"uuid": "R1@D3"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }}, + {"device_id": {"device_uuid": {"uuid": "R2@D3"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D3/3==R3@D3/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D3"}}, "endpoint_uuid": {"uuid": "3"}}, - {"device_id": {"device_uuid": {"uuid": "R3@D3"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D3"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }}, + {"device_id": {"device_uuid": {"uuid": "R3@D3"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R3@D3/4==R4@D3/3"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R3@D3"}}, "endpoint_uuid": {"uuid": "4"}}, - {"device_id": {"device_uuid": {"uuid": "R4@D3"}}, "endpoint_uuid": {"uuid": "3"}} + {"device_id": {"device_uuid": {"uuid": "R3@D3"}}, "endpoint_uuid": {"uuid": "4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }}, + {"device_id": {"device_uuid": {"uuid": "R4@D3"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R4@D3/1==R1@D3/4"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R4@D3"}}, "endpoint_uuid": {"uuid": "1"}}, - {"device_id": {"device_uuid": {"uuid": "R1@D3"}}, "endpoint_uuid": {"uuid": "4"}} + {"device_id": {"device_uuid": {"uuid": "R4@D3"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }}, + {"device_id": {"device_uuid": {"uuid": "R1@D3"}}, "endpoint_uuid": {"uuid": "4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D3/4==R4@D3/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D3"}}, "endpoint_uuid": {"uuid": "4"}}, - {"device_id": {"device_uuid": {"uuid": "R4@D3"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D3"}}, "endpoint_uuid": {"uuid": "4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }}, + {"device_id": {"device_uuid": {"uuid": "R4@D3"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D3"} + }} ] } ] diff --git a/src/tests/scenario2/descriptors/domain4.json b/src/tests/scenario2/descriptors/domain4.json index d9e2d049ad2417beb96b8f3434ed9e94febb4808..4607deb909f46f9b9750d4267cecb79fab2ebb86 100644 --- a/src/tests/scenario2/descriptors/domain4.json +++ b/src/tests/scenario2/descriptors/domain4.json @@ -1,27 +1,9 @@ { "contexts": [ - { - "context_id": {"context_uuid": {"uuid": "admin"}}, - "topology_ids": [ - {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"}} - ], "service_ids": [] - } + {"context_id": {"context_uuid": {"uuid": "admin"}}} ], "topologies": [ - { - "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"}}, - "device_ids": [ - {"device_uuid": {"uuid": "DC2"}}, - {"device_uuid": {"uuid": "R1@D4"}}, - {"device_uuid": {"uuid": "R2@D4"}}, - {"device_uuid": {"uuid": "R3@D4"}} - ], "link_ids": [ - {"link_uuid": {"uuid": "R3@D4/DC2==DC2/D4"}}, - {"link_uuid": {"uuid": "R1@D4/2==R2@D4/1"}}, - {"link_uuid": {"uuid": "R1@D4/3==R3@D4/1"}}, - {"link_uuid": {"uuid": "R2@D4/3==R3@D4/2"}} - ] - } + {"topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"}}} ], "devices": [ { @@ -30,8 +12,8 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/border", "uuid": "D4"}, - {"sample_types": [], "type": "copper/internal", "uuid": "int"} + {"uuid": "D4", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D4"}, + {"uuid": "int", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D4"} ]}}} ]} }, @@ -41,9 +23,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/internal", "uuid": "3"}, - {"sample_types": [], "type": "copper/border", "uuid": "D3"} + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D4"}, + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D4"}, + {"uuid": "D3", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D4"} ]}}} ]} }, @@ -53,9 +35,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "3"}, - {"sample_types": [], "type": "copper/border", "uuid": "D2"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D4"}, + {"uuid": "3", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D4"}, + {"uuid": "D2", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D4"} ]}}} ]} }, @@ -65,9 +47,9 @@ {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ - {"sample_types": [], "type": "copper/internal", "uuid": "1"}, - {"sample_types": [], "type": "copper/internal", "uuid": "2"}, - {"sample_types": [], "type": "copper/border", "uuid": "DC2"} + {"uuid": "1", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D4"}, + {"uuid": "2", "type": "copper/internal", "context_uuid": "admin", "topology_uuid": "D4"}, + {"uuid": "DC2", "type": "copper/border", "context_uuid": "admin", "topology_uuid": "D4"} ]}}} ]} } @@ -75,26 +57,42 @@ "links": [ { "link_id": {"link_uuid": {"uuid": "R3@D4/DC2==DC2/D4"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "DC2"}}, "endpoint_uuid": {"uuid": "D4"}}, - {"device_id": {"device_uuid": {"uuid": "R3@D4"}}, "endpoint_uuid": {"uuid": "DC2"}} + {"device_id": {"device_uuid": {"uuid": "DC2"}}, "endpoint_uuid": {"uuid": "D4"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }}, + {"device_id": {"device_uuid": {"uuid": "R3@D4"}}, "endpoint_uuid": {"uuid": "DC2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R1@D4/2==R2@D4/1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1@D4"}}, "endpoint_uuid": {"uuid": "2"}}, - {"device_id": {"device_uuid": {"uuid": "R2@D4"}}, "endpoint_uuid": {"uuid": "1"}} + {"device_id": {"device_uuid": {"uuid": "R1@D4"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }}, + {"device_id": {"device_uuid": {"uuid": "R2@D4"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R1@D4/3==R3@D4/1"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R1@D4"}}, "endpoint_uuid": {"uuid": "3"}}, - {"device_id": {"device_uuid": {"uuid": "R3@D4"}}, "endpoint_uuid": {"uuid": "1"}} + {"device_id": {"device_uuid": {"uuid": "R1@D4"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }}, + {"device_id": {"device_uuid": {"uuid": "R3@D4"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }} ] }, { "link_id": {"link_uuid": {"uuid": "R2@D4/3==R3@D4/2"}}, "link_endpoint_ids": [ - {"device_id": {"device_uuid": {"uuid": "R2@D4"}}, "endpoint_uuid": {"uuid": "3"}}, - {"device_id": {"device_uuid": {"uuid": "R3@D4"}}, "endpoint_uuid": {"uuid": "2"}} + {"device_id": {"device_uuid": {"uuid": "R2@D4"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }}, + {"device_id": {"device_uuid": {"uuid": "R3@D4"}}, "endpoint_uuid": {"uuid": "2"}, "topology_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "D4"} + }} ] } ] diff --git a/src/tests/scenario2/dump_logs.sh b/src/tests/scenario2/dump_logs.sh index c7acedbf613b66f3ec08bd1628e8e1ab76b9bc5e..ab3ed0899cf9f4adec566b4f1f8d291d82d77d16 100755 --- a/src/tests/scenario2/dump_logs.sh +++ b/src/tests/scenario2/dump_logs.sh @@ -30,7 +30,8 @@ kubectl --namespace tfs-dom1 logs deployments/pathcompservice backend > tmp/tfs- kubectl --namespace tfs-dom1 logs deployments/sliceservice server > tmp/tfs-dom1/exec/slice.log kubectl --namespace tfs-dom1 logs deployments/interdomainservice server > tmp/tfs-dom1/exec/interdomain.log kubectl --namespace tfs-dom1 logs deployments/dltservice connector > tmp/tfs-dom1/exec/dlt-connector.log -kubectl --namespace tfs-dom1 logs deployments/dltservice gateway > tmp/tfs-dom1/exec/dlt-gateway.log +#kubectl --namespace tfs-dom1 logs deployments/dltservice gateway > tmp/tfs-dom1/exec/dlt-gateway.log +kubectl --namespace tfs-dom1 logs deployments/computeservice server > tmp/tfs-dom1/exec/compute.log kubectl --namespace tfs-dom1 logs deployments/webuiservice server > tmp/tfs-dom1/exec/webui.log printf "\n" @@ -45,38 +46,41 @@ kubectl --namespace tfs-dom2 logs deployments/pathcompservice backend > tmp/tfs- kubectl --namespace tfs-dom2 logs deployments/sliceservice server > tmp/tfs-dom2/exec/slice.log kubectl --namespace tfs-dom2 logs deployments/interdomainservice server > tmp/tfs-dom2/exec/interdomain.log kubectl --namespace tfs-dom2 logs deployments/dltservice connector > tmp/tfs-dom2/exec/dlt-connector.log -kubectl --namespace tfs-dom2 logs deployments/dltservice gateway > tmp/tfs-dom2/exec/dlt-gateway.log +#kubectl --namespace tfs-dom2 logs deployments/dltservice gateway > tmp/tfs-dom2/exec/dlt-gateway.log +kubectl --namespace tfs-dom2 logs deployments/computeservice server > tmp/tfs-dom2/exec/compute.log kubectl --namespace tfs-dom2 logs deployments/webuiservice server > tmp/tfs-dom2/exec/webui.log printf "\n" -echo "Collecting logs for Domain 3..." -rm -rf tmp/tfs-dom3/exec -mkdir -p tmp/tfs-dom3/exec -kubectl --namespace tfs-dom3 logs deployments/contextservice server > tmp/tfs-dom3/exec/context.log -kubectl --namespace tfs-dom3 logs deployments/deviceservice server > tmp/tfs-dom3/exec/device.log -kubectl --namespace tfs-dom3 logs deployments/serviceservice server > tmp/tfs-dom3/exec/service.log -kubectl --namespace tfs-dom3 logs deployments/pathcompservice frontend > tmp/tfs-dom3/exec/pathcomp-frontend.log -kubectl --namespace tfs-dom3 logs deployments/pathcompservice backend > tmp/tfs-dom3/exec/pathcomp-backend.log -kubectl --namespace tfs-dom3 logs deployments/sliceservice server > tmp/tfs-dom3/exec/slice.log -kubectl --namespace tfs-dom3 logs deployments/interdomainservice server > tmp/tfs-dom3/exec/interdomain.log -kubectl --namespace tfs-dom3 logs deployments/dltservice connector > tmp/tfs-dom3/exec/dlt-connector.log -kubectl --namespace tfs-dom3 logs deployments/dltservice gateway > tmp/tfs-dom3/exec/dlt-gateway.log -kubectl --namespace tfs-dom3 logs deployments/webuiservice server > tmp/tfs-dom3/exec/webui.log -printf "\n" - -echo "Collecting logs for Domain 4..." -rm -rf tmp/tfs-dom4/exec -mkdir -p tmp/tfs-dom4/exec -kubectl --namespace tfs-dom4 logs deployments/contextservice server > tmp/tfs-dom4/exec/context.log -kubectl --namespace tfs-dom4 logs deployments/deviceservice server > tmp/tfs-dom4/exec/device.log -kubectl --namespace tfs-dom4 logs deployments/serviceservice server > tmp/tfs-dom4/exec/service.log -kubectl --namespace tfs-dom4 logs deployments/pathcompservice frontend > tmp/tfs-dom4/exec/pathcomp-frontend.log -kubectl --namespace tfs-dom4 logs deployments/pathcompservice backend > tmp/tfs-dom4/exec/pathcomp-backend.log -kubectl --namespace tfs-dom4 logs deployments/sliceservice server > tmp/tfs-dom4/exec/slice.log -kubectl --namespace tfs-dom4 logs deployments/interdomainservice server > tmp/tfs-dom4/exec/interdomain.log -kubectl --namespace tfs-dom4 logs deployments/dltservice connector > tmp/tfs-dom4/exec/dlt-connector.log -kubectl --namespace tfs-dom4 logs deployments/dltservice gateway > tmp/tfs-dom4/exec/dlt-gateway.log -kubectl --namespace tfs-dom4 logs deployments/webuiservice server > tmp/tfs-dom4/exec/webui.log -printf "\n" +#echo "Collecting logs for Domain 3..." +#rm -rf tmp/tfs-dom3/exec +#mkdir -p tmp/tfs-dom3/exec +#kubectl --namespace tfs-dom3 logs deployments/contextservice server > tmp/tfs-dom3/exec/context.log +#kubectl --namespace tfs-dom3 logs deployments/deviceservice server > tmp/tfs-dom3/exec/device.log +#kubectl --namespace tfs-dom3 logs deployments/serviceservice server > tmp/tfs-dom3/exec/service.log +#kubectl --namespace tfs-dom3 logs deployments/pathcompservice frontend > tmp/tfs-dom3/exec/pathcomp-frontend.log +#kubectl --namespace tfs-dom3 logs deployments/pathcompservice backend > tmp/tfs-dom3/exec/pathcomp-backend.log +#kubectl --namespace tfs-dom3 logs deployments/sliceservice server > tmp/tfs-dom3/exec/slice.log +#kubectl --namespace tfs-dom3 logs deployments/interdomainservice server > tmp/tfs-dom3/exec/interdomain.log +#kubectl --namespace tfs-dom3 logs deployments/dltservice connector > tmp/tfs-dom3/exec/dlt-connector.log +##kubectl --namespace tfs-dom3 logs deployments/dltservice gateway > tmp/tfs-dom3/exec/dlt-gateway.log +#kubectl --namespace tfs-dom3 logs deployments/computeservice server > tmp/tfs-dom3/exec/compute.log +#kubectl --namespace tfs-dom3 logs deployments/webuiservice server > tmp/tfs-dom3/exec/webui.log +#printf "\n" +# +#echo "Collecting logs for Domain 4..." +#rm -rf tmp/tfs-dom4/exec +#mkdir -p tmp/tfs-dom4/exec +#kubectl --namespace tfs-dom4 logs deployments/contextservice server > tmp/tfs-dom4/exec/context.log +#kubectl --namespace tfs-dom4 logs deployments/deviceservice server > tmp/tfs-dom4/exec/device.log +#kubectl --namespace tfs-dom4 logs deployments/serviceservice server > tmp/tfs-dom4/exec/service.log +#kubectl --namespace tfs-dom4 logs deployments/pathcompservice frontend > tmp/tfs-dom4/exec/pathcomp-frontend.log +#kubectl --namespace tfs-dom4 logs deployments/pathcompservice backend > tmp/tfs-dom4/exec/pathcomp-backend.log +#kubectl --namespace tfs-dom4 logs deployments/sliceservice server > tmp/tfs-dom4/exec/slice.log +#kubectl --namespace tfs-dom4 logs deployments/interdomainservice server > tmp/tfs-dom4/exec/interdomain.log +#kubectl --namespace tfs-dom4 logs deployments/dltservice connector > tmp/tfs-dom4/exec/dlt-connector.log +##kubectl --namespace tfs-dom4 logs deployments/dltservice gateway > tmp/tfs-dom4/exec/dlt-gateway.log +#kubectl --namespace tfs-dom4 logs deployments/computeservice server > tmp/tfs-dom4/exec/compute.log +#kubectl --namespace tfs-dom4 logs deployments/webuiservice server > tmp/tfs-dom4/exec/webui.log +#printf "\n" echo "Done!"