Skip to content
Snippets Groups Projects
Commit 315bd644 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch 'release/2.0.1' of https://labs.etsi.org/rep/tfs/controller into feat/slice-grouping

parents b6fdf507 0066c66f
No related branches found
No related tags found
2 merge requests!142Release TeraFlowSDN 2.1,!64Slice Grouping
Showing
with 330 additions and 663 deletions
# 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.
import logging
from common.tools.descriptor.Loader import DescriptorLoader, compose_notifications
from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient
from service.client.ServiceClient import ServiceClient
from slice.client.SliceClient import SliceClient
LOGGER = logging.getLogger(__name__)
LOGGERS = {
'success': LOGGER.info,
'danger' : LOGGER.error,
'error' : LOGGER.error,
}
def load_scenario_from_descriptor(
descriptor_file : str, context_client : ContextClient, device_client : DeviceClient,
service_client : ServiceClient, slice_client : SliceClient
) -> DescriptorLoader:
with open(descriptor_file, 'r', encoding='UTF-8') as f:
descriptors = f.read()
descriptor_loader = DescriptorLoader(
descriptors,
context_client=context_client, device_client=device_client,
service_client=service_client, slice_client=slice_client)
results = descriptor_loader.process()
num_errors = 0
for message,level in compose_notifications(results):
LOGGERS.get(level)(message)
if level != 'success': num_errors += 1
if num_errors > 0:
MSG = 'Failed to load descriptors in file {:s}'
raise Exception(MSG.format(str(descriptor_file)))
return descriptor_loader
\ No newline at end of file
...@@ -15,25 +15,30 @@ ...@@ -15,25 +15,30 @@
# SDN controller descriptor loader # SDN controller descriptor loader
# Usage example (WebUI): # Usage example (WebUI):
# descriptors = json.loads(descriptors_data_from_client) # descriptors = json.loads(
# descriptors=descriptors_data_from_client, num_workers=10,
# context_client=..., device_client=..., service_client=..., slice_client=...)
# descriptor_loader = DescriptorLoader(descriptors) # descriptor_loader = DescriptorLoader(descriptors)
# results = descriptor_loader.process() # results = descriptor_loader.process()
# for message,level in compose_notifications(results): # for message,level in compose_notifications(results):
# flash(message, level) # flash(message, level)
# Usage example (pytest): # Usage example (pytest):
# with open('path/to/descriptor.json', 'r', encoding='UTF-8') as f:
# descriptors = json.loads(f.read())
# descriptor_loader = DescriptorLoader( # descriptor_loader = DescriptorLoader(
# descriptors, context_client=..., device_client=..., service_client=..., slice_client=...) # descriptors_file='path/to/descriptor.json', num_workers=10,
# context_client=..., device_client=..., service_client=..., slice_client=...)
# results = descriptor_loader.process() # results = descriptor_loader.process()
# loggers = {'success': LOGGER.info, 'danger': LOGGER.error, 'error': LOGGER.error} # check_results(results, descriptor_loader)
# for message,level in compose_notifications(results): # descriptor_loader.validate()
# loggers.get(level)(message) # # do test ...
# descriptor_loader.unload()
import concurrent.futures, json, logging, operator import concurrent.futures, json, logging, operator
from typing import Any, Dict, List, Optional, Tuple, Union from typing import Any, Dict, List, Optional, Tuple, Union
from common.proto.context_pb2 import Connection, Context, Device, Link, Service, Slice, Topology from common.proto.context_pb2 import (
Connection, Context, ContextId, Device, DeviceId, Empty, Link, LinkId, Service, ServiceId, Slice, SliceId,
Topology, TopologyId)
from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
from service.client.ServiceClient import ServiceClient from service.client.ServiceClient import ServiceClient
...@@ -44,6 +49,11 @@ from .Tools import ( ...@@ -44,6 +49,11 @@ from .Tools import (
get_descriptors_add_topologies, split_devices_by_rules) get_descriptors_add_topologies, split_devices_by_rules)
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
LOGGERS = {
'success': LOGGER.info,
'danger' : LOGGER.error,
'error' : LOGGER.error,
}
ENTITY_TO_TEXT = { ENTITY_TO_TEXT = {
# name => singular, plural # name => singular, plural
...@@ -67,25 +77,26 @@ TypeResults = List[Tuple[str, str, int, List[str]]] # entity_name, action, num_o ...@@ -67,25 +77,26 @@ TypeResults = List[Tuple[str, str, int, List[str]]] # entity_name, action, num_o
TypeNotification = Tuple[str, str] # message, level TypeNotification = Tuple[str, str] # message, level
TypeNotificationList = List[TypeNotification] TypeNotificationList = List[TypeNotification]
def compose_notifications(results : TypeResults) -> TypeNotificationList:
notifications = []
for entity_name, action_name, num_ok, error_list in results:
entity_name_singluar,entity_name_plural = ENTITY_TO_TEXT[entity_name]
action_infinitive, action_past = ACTION_TO_TEXT[action_name]
num_err = len(error_list)
for error in error_list:
notifications.append((f'Unable to {action_infinitive} {entity_name_singluar} {error}', 'error'))
if num_ok : notifications.append((f'{str(num_ok)} {entity_name_plural} {action_past}', 'success'))
if num_err: notifications.append((f'{str(num_err)} {entity_name_plural} failed', 'danger'))
return notifications
class DescriptorLoader: class DescriptorLoader:
def __init__( def __init__(
self, descriptors : Union[str, Dict], num_workers : int = 1, self, descriptors : Optional[Union[str, Dict]] = None, descriptors_file : Optional[str] = None,
num_workers : int = 1,
context_client : Optional[ContextClient] = None, device_client : Optional[DeviceClient] = None, context_client : Optional[ContextClient] = None, device_client : Optional[DeviceClient] = None,
service_client : Optional[ServiceClient] = None, slice_client : Optional[SliceClient] = None service_client : Optional[ServiceClient] = None, slice_client : Optional[SliceClient] = None
) -> None: ) -> None:
self.__descriptors = json.loads(descriptors) if isinstance(descriptors, str) else descriptors if (descriptors is None) == (descriptors_file is None):
raise Exception('Exactly one of "descriptors" or "descriptors_file" is required')
if descriptors_file is not None:
with open(descriptors_file, 'r', encoding='UTF-8') as f:
self.__descriptors = json.loads(f.read())
self.__descriptor_file_path = descriptors_file
else: # descriptors is not None
self.__descriptors = json.loads(descriptors) if isinstance(descriptors, str) else descriptors
self.__descriptor_file_path = '<dict>'
self.__num_workers = num_workers
self.__dummy_mode = self.__descriptors.get('dummy_mode' , False) self.__dummy_mode = self.__descriptors.get('dummy_mode' , False)
self.__contexts = self.__descriptors.get('contexts' , []) self.__contexts = self.__descriptors.get('contexts' , [])
self.__topologies = self.__descriptors.get('topologies' , []) self.__topologies = self.__descriptors.get('topologies' , [])
...@@ -95,8 +106,6 @@ class DescriptorLoader: ...@@ -95,8 +106,6 @@ class DescriptorLoader:
self.__slices = self.__descriptors.get('slices' , []) self.__slices = self.__descriptors.get('slices' , [])
self.__connections = self.__descriptors.get('connections', []) self.__connections = self.__descriptors.get('connections', [])
self.__num_workers = num_workers
self.__contexts_add = None self.__contexts_add = None
self.__topologies_add = None self.__topologies_add = None
self.__devices_add = None self.__devices_add = None
...@@ -111,6 +120,24 @@ class DescriptorLoader: ...@@ -111,6 +120,24 @@ class DescriptorLoader:
self.__results : TypeResults = list() self.__results : TypeResults = list()
@property
def descriptor_file_path(self) -> Optional[str]: return self.__descriptor_file_path
@property
def num_workers(self) -> int: return self.__num_workers
@property
def context_client(self) -> Optional[ContextClient]: return self.__ctx_cli
@property
def device_client(self) -> Optional[DeviceClient]: return self.__dev_cli
@property
def service_client(self) -> Optional[ServiceClient]: return self.__svc_cli
@property
def slice_client(self) -> Optional[SliceClient]: return self.__slc_cli
@property @property
def contexts(self) -> List[Dict]: return self.__contexts def contexts(self) -> List[Dict]: return self.__contexts
...@@ -269,3 +296,85 @@ class DescriptorLoader: ...@@ -269,3 +296,85 @@ class DescriptorLoader:
error_list = [str_error for _,str_error in sorted(error_list, key=operator.itemgetter(0))] error_list = [str_error for _,str_error in sorted(error_list, key=operator.itemgetter(0))]
self.__results.append((entity_name, action_name, num_ok, error_list)) self.__results.append((entity_name, action_name, num_ok, error_list))
def validate(self) -> None:
self.__ctx_cli.connect()
contexts = self.__ctx_cli.ListContexts(Empty())
assert len(contexts.contexts) == self.num_contexts
for context_uuid, num_topologies in self.num_topologies.items():
response = self.__ctx_cli.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = self.__ctx_cli.ListDevices(Empty())
assert len(response.devices) == self.num_devices
response = self.__ctx_cli.ListLinks(Empty())
assert len(response.links) == self.num_links
for context_uuid, num_services in self.num_services.items():
response = self.__ctx_cli.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == num_services
for context_uuid, num_slices in self.num_slices.items():
response = self.__ctx_cli.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == num_slices
def unload(self) -> None:
self.__ctx_cli.connect()
self.__dev_cli.connect()
self.__svc_cli.connect()
self.__slc_cli.connect()
for _, slice_list in self.slices.items():
for slice_ in slice_list:
self.__slc_cli.DeleteSlice(SliceId(**slice_['slice_id']))
for _, service_list in self.services.items():
for service in service_list:
self.__svc_cli.DeleteService(ServiceId(**service['service_id']))
for link in self.links:
self.__ctx_cli.RemoveLink(LinkId(**link['link_id']))
for device in self.devices:
self.__dev_cli.DeleteDevice(DeviceId(**device['device_id']))
for _, topology_list in self.topologies.items():
for topology in topology_list:
self.__ctx_cli.RemoveTopology(TopologyId(**topology['topology_id']))
for context in self.contexts:
self.__ctx_cli.RemoveContext(ContextId(**context['context_id']))
def compose_notifications(results : TypeResults) -> TypeNotificationList:
notifications = []
for entity_name, action_name, num_ok, error_list in results:
entity_name_singluar,entity_name_plural = ENTITY_TO_TEXT[entity_name]
action_infinitive, action_past = ACTION_TO_TEXT[action_name]
num_err = len(error_list)
for error in error_list:
notifications.append((f'Unable to {action_infinitive} {entity_name_singluar} {error}', 'error'))
if num_ok : notifications.append((f'{str(num_ok)} {entity_name_plural} {action_past}', 'success'))
if num_err: notifications.append((f'{str(num_err)} {entity_name_plural} failed', 'danger'))
return notifications
def check_descriptor_load_results(results : TypeResults, descriptor_loader : DescriptorLoader) -> None:
num_errors = 0
for message,level in compose_notifications(results):
LOGGERS.get(level)(message)
if level != 'success': num_errors += 1
if num_errors > 0:
MSG = 'Failed to load descriptors from "{:s}"'
raise Exception(MSG.format(str(descriptor_loader.descriptor_file_path)))
def validate_empty_scenario(context_client : ContextClient) -> None:
response = context_client.ListContexts(Empty())
assert len(response.contexts) == 0
response = context_client.ListDevices(Empty())
assert len(response.devices) == 0
response = context_client.ListLinks(Empty())
assert len(response.links) == 0
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
# limitations under the License. # limitations under the License.
import logging, time import logging, time
from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, Empty from common.proto.context_pb2 import ContextId, Empty
from common.proto.monitoring_pb2 import KpiDescriptorList from common.proto.monitoring_pb2 import KpiDescriptorList
from common.tests.LoadScenario import load_scenario_from_descriptor from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results, validate_empty_scenario
from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
...@@ -27,44 +27,25 @@ LOGGER = logging.getLogger(__name__) ...@@ -27,44 +27,25 @@ LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG) LOGGER.setLevel(logging.DEBUG)
DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json' DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_scenario_bootstrap( def test_scenario_bootstrap(
context_client : ContextClient, # pylint: disable=redefined-outer-name context_client : ContextClient, # pylint: disable=redefined-outer-name
device_client : DeviceClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name
) -> None: ) -> None:
# ----- List entities - Ensure database is empty ------------------------------------------------------------------- validate_empty_scenario(context_client)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == 0
response = context_client.ListDevices(Empty()) descriptor_loader = DescriptorLoader(
assert len(response.devices) == 0 descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
results = descriptor_loader.process()
response = context_client.ListLinks(Empty()) check_descriptor_load_results(results, descriptor_loader)
assert len(response.links) == 0 descriptor_loader.validate()
# ----- Load Scenario ----------------------------------------------------------------------------------------------
descriptor_loader = load_scenario_from_descriptor(
DESCRIPTOR_FILE, context_client, device_client, None, None)
# ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty()) # Verify the scenario has no services/slices
assert len(response.links) == descriptor_loader.num_links response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0
for context_uuid, _ in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == 0
def test_scenario_kpis_created( def test_scenario_kpis_created(
context_client : ContextClient, # pylint: disable=redefined-outer-name context_client : ContextClient, # pylint: disable=redefined-outer-name
......
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
# limitations under the License. # limitations under the License.
import logging import logging
from common.tools.descriptor.Loader import DescriptorLoader from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId
from common.tools.descriptor.Loader import DescriptorLoader, validate_empty_scenario
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from common.proto.context_pb2 import ContextId, DeviceId, Empty, LinkId, TopologyId
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
from tests.Fixtures import context_client, device_client # pylint: disable=unused-import from tests.Fixtures import context_client, device_client # pylint: disable=unused-import
...@@ -24,57 +25,20 @@ LOGGER = logging.getLogger(__name__) ...@@ -24,57 +25,20 @@ LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG) LOGGER.setLevel(logging.DEBUG)
DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json' DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_scenario_cleanup(
def test_services_removed(
context_client : ContextClient, # pylint: disable=redefined-outer-name context_client : ContextClient, # pylint: disable=redefined-outer-name
device_client : DeviceClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name
) -> None: ) -> None:
# ----- List entities - Ensure service is removed ------------------------------------------------------------------ # Verify the scenario has no services/slices
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f: response = context_client.GetContext(ADMIN_CONTEXT_ID)
descriptors = f.read() assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0
descriptor_loader = DescriptorLoader(descriptors)
# Load descriptors and validate the base scenario
response = context_client.ListContexts(Empty()) descriptor_loader = DescriptorLoader(
assert len(response.contexts) == descriptor_loader.num_contexts descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
descriptor_loader.validate()
for context_uuid, num_topologies in descriptor_loader.num_topologies.items(): descriptor_loader.unload()
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid))) validate_empty_scenario(context_client)
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, _ in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == 0
# ----- Delete Links, Devices, Topologies, Contexts ----------------------------------------------------------------
for link in descriptor_loader.links:
context_client.RemoveLink(LinkId(**link['link_id']))
for device in descriptor_loader.devices:
device_client .DeleteDevice(DeviceId(**device['device_id']))
for context_uuid, topology_list in descriptor_loader.topologies.items():
for topology in topology_list:
context_client.RemoveTopology(TopologyId(**topology['topology_id']))
for context in descriptor_loader.contexts:
context_client.RemoveContext(ContextId(**context['context_id']))
# ----- List entities - Ensure database is empty again -------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == 0
response = context_client.ListDevices(Empty())
assert len(response.devices) == 0
response = context_client.ListLinks(Empty())
assert len(response.links) == 0
...@@ -13,83 +13,61 @@ ...@@ -13,83 +13,61 @@
# limitations under the License. # limitations under the License.
import logging, random import logging, random
from common.DeviceTypes import DeviceTypeEnum from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, Empty from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
from common.proto.kpi_sample_types_pb2 import KpiSampleType from common.proto.kpi_sample_types_pb2 import KpiSampleType
from common.tools.descriptor.Loader import DescriptorLoader from common.tools.descriptor.Loader import DescriptorLoader
from common.tools.grpc.Tools import grpc_message_to_json_string from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from monitoring.client.MonitoringClient import MonitoringClient from monitoring.client.MonitoringClient import MonitoringClient
from tests.Fixtures import context_client, device_client, monitoring_client # pylint: disable=unused-import from tests.Fixtures import context_client, monitoring_client # pylint: disable=unused-import
from tests.tools.mock_osm.MockOSM import MockOSM from tests.tools.mock_osm.MockOSM import MockOSM
from .Fixtures import osm_wim # pylint: disable=unused-import from .Fixtures import osm_wim # pylint: disable=unused-import
from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG) LOGGER.setLevel(logging.DEBUG)
DEVTYPE_EMU_PR = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value
DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json' DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
# ----- List entities - Ensure scenario is ready ------------------------------------------------------------------- # Load descriptors and validate the base scenario
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f: descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
descriptors = f.read() descriptor_loader.validate()
descriptor_loader = DescriptorLoader(descriptors)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, num_services in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == 0
# Verify the scenario has no services/slices
response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0
# ----- Create Service --------------------------------------------------------------------------------------------- # Create Connectivity Service
service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS) service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
osm_wim.get_connectivity_service_status(service_uuid) osm_wim.get_connectivity_service_status(service_uuid)
# Ensure slices and services are created
# ----- List entities - Ensure service is created ------------------------------------------------------------------ response = context_client.ListSlices(ADMIN_CONTEXT_ID)
response = context_client.ListContexts(Empty()) LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
assert len(response.contexts) == descriptor_loader.num_contexts assert len(response.slices) == 1 # OSM slice
for context_uuid, num_topologies in descriptor_loader.num_topologies.items(): response = context_client.ListServices(ADMIN_CONTEXT_ID)
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid))) LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
assert len(response.topologies) == num_topologies assert len(response.services) == 2 # 1xL3NM + 1xTAPI
response = context_client.ListDevices(Empty()) for service in response.services:
assert len(response.devices) == descriptor_loader.num_devices service_id = service.service_id
response = context_client.ListConnections(service_id)
response = context_client.ListLinks(Empty()) LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
assert len(response.links) == descriptor_loader.num_links grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
for context_uuid, num_services in descriptor_loader.num_services.items(): if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
response = context_client.ListServices(ContextId(**json_context_id(context_uuid))) assert len(response.connections) == 1 # 1 connection per service
LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
assert len(response.services) == 2*num_services # OLS & L3NM => (L3NM + TAPI) assert len(response.connections) == 1 # 1 connection per service
else:
for service in response.services: str_service = grpc_message_to_json_string(service)
service_id = service.service_id raise Exception('Unexpected ServiceType: {:s}'.format(str_service))
response = context_client.ListConnections(service_id)
LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
grpc_message_to_json_string(service_id), len(response.connections),
grpc_message_to_json_string(response)))
assert len(response.connections) == 1 # one connection per service
def test_scenario_kpi_values_created( def test_scenario_kpi_values_created(
......
...@@ -14,86 +14,61 @@ ...@@ -14,86 +14,61 @@
import logging import logging
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.DeviceTypes import DeviceTypeEnum from common.proto.context_pb2 import ContextId, ServiceTypeEnum
from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
from common.tools.descriptor.Loader import DescriptorLoader from common.tools.descriptor.Loader import DescriptorLoader
from common.tools.object_factory.Context import json_context_id
from common.tools.grpc.Tools import grpc_message_to_json_string from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from tests.Fixtures import context_client # pylint: disable=unused-import from tests.Fixtures import context_client # pylint: disable=unused-import
from tests.tools.mock_osm.MockOSM import MockOSM from tests.tools.mock_osm.MockOSM import MockOSM
from .Fixtures import osm_wim # pylint: disable=unused-import from .Fixtures import osm_wim # pylint: disable=unused-import
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG) LOGGER.setLevel(logging.DEBUG)
DEVTYPE_EMU_PR = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value
DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json' DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
# ----- List entities - Ensure service is created ------------------------------------------------------------------ # Ensure slices and services are created
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f: response = context_client.ListSlices(ADMIN_CONTEXT_ID)
descriptors = f.read() LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
assert len(response.slices) == 1 # OSM slice
descriptor_loader = DescriptorLoader(descriptors) response = context_client.ListServices(ADMIN_CONTEXT_ID)
LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
assert len(response.services) == 2 # 1xL3NM + 1xTAPI
response = context_client.ListContexts(Empty()) service_uuids = set()
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
l3nm_service_uuids = set()
response = context_client.ListServices(ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)))
assert len(response.services) == 2 # OLS & L3NM => (L3NM + TAPI)
for service in response.services: for service in response.services:
service_id = service.service_id service_id = service.service_id
response = context_client.ListConnections(service_id)
LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM: if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
assert len(response.connections) == 1 # 1 connection per service
service_uuid = service_id.service_uuid.uuid service_uuid = service_id.service_uuid.uuid
l3nm_service_uuids.add(service_uuid) service_uuids.add(service_uuid)
osm_wim.conn_info[service_uuid] = {} osm_wim.conn_info[service_uuid] = {}
elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
response = context_client.ListConnections(service_id) assert len(response.connections) == 1 # 1 connection per service
LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( else:
grpc_message_to_json_string(service_id), len(response.connections), str_service = grpc_message_to_json_string(service)
grpc_message_to_json_string(response))) raise Exception('Unexpected ServiceType: {:s}'.format(str_service))
assert len(response.connections) == 1 # one connection per service
# Identify service to delete # Identify service to delete
assert len(l3nm_service_uuids) == 1 # assume a single L3NM service has been created assert len(service_uuids) == 1 # assume a single L3NM service has been created
l3nm_service_uuid = set(l3nm_service_uuids).pop() service_uuid = set(service_uuids).pop()
# ----- Delete Service ---------------------------------------------------------------------------------------------
osm_wim.delete_connectivity_service(l3nm_service_uuid)
# ----- List entities - Ensure service is removed ------------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty()) # Delete Connectivity Service
assert len(response.devices) == descriptor_loader.num_devices osm_wim.delete_connectivity_service(service_uuid)
response = context_client.ListLinks(Empty()) # Verify the scenario has no services/slices
assert len(response.links) == descriptor_loader.num_links response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0
for context_uuid, num_services in descriptor_loader.num_services.items(): # Load descriptors and validate the base scenario
response = context_client.ListServices(ContextId(**json_context_id(context_uuid))) descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
assert len(response.services) == 0 descriptor_loader.validate()
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
import logging import logging
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, Empty from common.proto.context_pb2 import ContextId
from common.tests.LoadScenario import load_scenario_from_descriptor from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results, validate_empty_scenario
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
...@@ -31,45 +31,15 @@ def test_scenario_bootstrap( ...@@ -31,45 +31,15 @@ def test_scenario_bootstrap(
context_client : ContextClient, # pylint: disable=redefined-outer-name context_client : ContextClient, # pylint: disable=redefined-outer-name
device_client : DeviceClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name
) -> None: ) -> None:
# ----- List entities - Ensure database is empty ------------------------------------------------------------------- validate_empty_scenario(context_client)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == 0
response = context_client.ListDevices(Empty()) descriptor_loader = DescriptorLoader(
assert len(response.devices) == 0 descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
results = descriptor_loader.process()
check_descriptor_load_results(results, descriptor_loader)
descriptor_loader.validate()
response = context_client.ListLinks(Empty()) # Verify the scenario has no services/slices
assert len(response.links) == 0
# ----- Load Scenario ----------------------------------------------------------------------------------------------
descriptor_loader = load_scenario_from_descriptor(
DESCRIPTOR_FILE, context_client, device_client, None, None)
# ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, _ in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == 0
for context_uuid, _ in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == 0
# This scenario assumes no services are created beforehand
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
import logging import logging
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, DeviceId, Empty, LinkId, TopologyId from common.proto.context_pb2 import ContextId
from common.tools.descriptor.Loader import DescriptorLoader from common.tools.descriptor.Loader import DescriptorLoader, validate_empty_scenario
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
...@@ -27,64 +27,18 @@ LOGGER.setLevel(logging.DEBUG) ...@@ -27,64 +27,18 @@ LOGGER.setLevel(logging.DEBUG)
DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json' DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_services_removed( def test_scenario_cleanup(
context_client : ContextClient, # pylint: disable=redefined-outer-name context_client : ContextClient, # pylint: disable=redefined-outer-name
device_client : DeviceClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name
) -> None: ) -> None:
# ----- List entities - Ensure service is removed ------------------------------------------------------------------ # Verify the scenario has no services/slices
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
descriptors = f.read()
descriptor_loader = DescriptorLoader(descriptors)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, _ in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == 0
for context_uuid, _ in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == 0
# This scenario assumes no services are created beforehand
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
# Load descriptors and validate the base scenario
# ----- Delete Links, Devices, Topologies, Contexts ---------------------------------------------------------------- descriptor_loader = DescriptorLoader(
for link in descriptor_loader.links: descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
context_client.RemoveLink(LinkId(**link['link_id'])) descriptor_loader.validate()
descriptor_loader.unload()
for device in descriptor_loader.devices: validate_empty_scenario(context_client)
device_client .DeleteDevice(DeviceId(**device['device_id']))
for context_uuid, topology_list in descriptor_loader.topologies.items():
for topology in topology_list:
context_client.RemoveTopology(TopologyId(**topology['topology_id']))
for context in descriptor_loader.contexts:
context_client.RemoveContext(ContextId(**context['context_id']))
# ----- List entities - Ensure database is empty again -------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == 0
response = context_client.ListDevices(Empty())
assert len(response.devices) == 0
response = context_client.ListLinks(Empty())
assert len(response.links) == 0
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
import logging import logging
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum from common.proto.context_pb2 import ContextId, ServiceTypeEnum
from common.tools.descriptor.Loader import DescriptorLoader from common.tools.descriptor.Loader import DescriptorLoader
from common.tools.grpc.Tools import grpc_message_to_json_string from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
...@@ -31,57 +31,23 @@ DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json' ...@@ -31,57 +31,23 @@ DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
# ----- List entities - Ensure scenario is ready ------------------------------------------------------------------- # Load descriptors and validate the base scenario
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f: descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
descriptors = f.read() descriptor_loader.validate()
descriptor_loader = DescriptorLoader(descriptors) # Verify the scenario has no services/slices
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, num_services in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == num_services
for context_uuid, num_slices in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == num_slices
# This scenario assumes no services are created beforehand
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
# Create Connectivity Service
# ----- Create Service ---------------------------------------------------------------------------------------------
service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS) service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
osm_wim.get_connectivity_service_status(service_uuid) osm_wim.get_connectivity_service_status(service_uuid)
# Ensure slices and services are created
# ----- List entities - Ensure service is created ------------------------------------------------------------------ response = context_client.ListSlices(ADMIN_CONTEXT_ID)
response = context_client.ListContexts(Empty()) LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
assert len(response.contexts) == descriptor_loader.num_contexts assert len(response.slices) == 1 # OSM slice
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
response = context_client.ListServices(ADMIN_CONTEXT_ID) response = context_client.ListServices(ADMIN_CONTEXT_ID)
LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
......
...@@ -14,14 +14,14 @@ ...@@ -14,14 +14,14 @@
import logging import logging
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum from common.proto.context_pb2 import ContextId, ServiceTypeEnum
from common.tools.descriptor.Loader import DescriptorLoader from common.tools.descriptor.Loader import DescriptorLoader
from common.tools.object_factory.Context import json_context_id
from common.tools.grpc.Tools import grpc_message_to_json_string from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from tests.Fixtures import context_client # pylint: disable=unused-import from tests.Fixtures import context_client # pylint: disable=unused-import
from tests.tools.mock_osm.MockOSM import MockOSM from tests.tools.mock_osm.MockOSM import MockOSM
from .Fixtures import osm_wim # pylint: disable=unused-import from .Fixtures import osm_wim # pylint: disable=unused-import
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG) LOGGER.setLevel(logging.DEBUG)
...@@ -30,44 +30,27 @@ DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json' ...@@ -30,44 +30,27 @@ DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
# ----- List entities - Ensure service is created ------------------------------------------------------------------ # Ensure slices and services are created
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f: response = context_client.ListSlices(ADMIN_CONTEXT_ID)
descriptors = f.read() LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
assert len(response.slices) == 1 # OSM slice
descriptor_loader = DescriptorLoader(descriptors)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
service_uuids = set()
response = context_client.ListServices(ADMIN_CONTEXT_ID) response = context_client.ListServices(ADMIN_CONTEXT_ID)
LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
assert len(response.services) == 3 # 1xL2NM + 2xTAPI assert len(response.services) == 3 # 1xL2NM + 2xTAPI
service_uuids = set()
for service in response.services: for service in response.services:
service_id = service.service_id service_id = service.service_id
if service.service_type == ServiceTypeEnum.SERVICETYPE_L2NM:
service_uuid = service_id.service_uuid.uuid
service_uuids.add(service_uuid)
osm_wim.conn_info[service_uuid] = {}
response = context_client.ListConnections(service_id) response = context_client.ListConnections(service_id)
LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response))) grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
if service.service_type == ServiceTypeEnum.SERVICETYPE_L2NM: if service.service_type == ServiceTypeEnum.SERVICETYPE_L2NM:
assert len(response.connections) == 2 # 2 connections per service (primary + backup) assert len(response.connections) == 2 # 2 connections per service (primary + backup)
service_uuid = service_id.service_uuid.uuid
service_uuids.add(service_uuid)
osm_wim.conn_info[service_uuid] = {}
elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE: elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
assert len(response.connections) == 1 # 1 connection per service assert len(response.connections) == 1 # 1 connection per service
else: else:
...@@ -78,34 +61,14 @@ def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # p ...@@ -78,34 +61,14 @@ def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # p
assert len(service_uuids) == 1 # assume a single L2NM service has been created assert len(service_uuids) == 1 # assume a single L2NM service has been created
service_uuid = set(service_uuids).pop() service_uuid = set(service_uuids).pop()
# Delete Connectivity Service
# ----- Delete Service ---------------------------------------------------------------------------------------------
osm_wim.delete_connectivity_service(service_uuid) osm_wim.delete_connectivity_service(service_uuid)
# Verify the scenario has no services/slices
# ----- List entities - Ensure service is removed ------------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, num_services in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == num_services
for context_uuid, num_slices in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == num_slices
# This scenario assumes no services are created beforehand
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
# Load descriptors and validate the base scenario
descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
descriptor_loader.validate()
...@@ -16,7 +16,7 @@ import logging, time ...@@ -16,7 +16,7 @@ import logging, time
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, Empty from common.proto.context_pb2 import ContextId, Empty
from common.proto.monitoring_pb2 import KpiDescriptorList from common.proto.monitoring_pb2 import KpiDescriptorList
from common.tests.LoadScenario import load_scenario_from_descriptor from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results, validate_empty_scenario
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
...@@ -33,45 +33,15 @@ def test_scenario_bootstrap( ...@@ -33,45 +33,15 @@ def test_scenario_bootstrap(
context_client : ContextClient, # pylint: disable=redefined-outer-name context_client : ContextClient, # pylint: disable=redefined-outer-name
device_client : DeviceClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name
) -> None: ) -> None:
# ----- List entities - Ensure database is empty ------------------------------------------------------------------- validate_empty_scenario(context_client)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == 0
response = context_client.ListDevices(Empty()) descriptor_loader = DescriptorLoader(
assert len(response.devices) == 0 descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
results = descriptor_loader.process()
response = context_client.ListLinks(Empty()) check_descriptor_load_results(results, descriptor_loader)
assert len(response.links) == 0 descriptor_loader.validate()
# ----- Load Scenario ----------------------------------------------------------------------------------------------
descriptor_loader = load_scenario_from_descriptor(
DESCRIPTOR_FILE, context_client, device_client, None, None)
# ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, _ in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == 0
for context_uuid, _ in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == 0
# This scenario assumes no services are created beforehand # Verify the scenario has no services/slices
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
import logging import logging
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, DeviceId, Empty, LinkId, TopologyId from common.proto.context_pb2 import ContextId
from common.tools.descriptor.Loader import DescriptorLoader from common.tools.descriptor.Loader import DescriptorLoader, validate_empty_scenario
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
...@@ -27,64 +27,18 @@ LOGGER.setLevel(logging.DEBUG) ...@@ -27,64 +27,18 @@ LOGGER.setLevel(logging.DEBUG)
DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json' DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_services_removed( def test_scenario_cleanup(
context_client : ContextClient, # pylint: disable=redefined-outer-name context_client : ContextClient, # pylint: disable=redefined-outer-name
device_client : DeviceClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name
) -> None: ) -> None:
# ----- List entities - Ensure service is removed ------------------------------------------------------------------ # Verify the scenario has no services/slices
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
descriptors = f.read()
descriptor_loader = DescriptorLoader(descriptors)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, _ in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == 0
for context_uuid, _ in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == 0
# This scenario assumes no services are created beforehand
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
# Load descriptors and validate the base scenario
# ----- Delete Links, Devices, Topologies, Contexts ---------------------------------------------------------------- descriptor_loader = DescriptorLoader(
for link in descriptor_loader.links: descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
context_client.RemoveLink(LinkId(**link['link_id'])) descriptor_loader.validate()
descriptor_loader.unload()
for device in descriptor_loader.devices: validate_empty_scenario(context_client)
device_client .DeleteDevice(DeviceId(**device['device_id']))
for context_uuid, topology_list in descriptor_loader.topologies.items():
for topology in topology_list:
context_client.RemoveTopology(TopologyId(**topology['topology_id']))
for context in descriptor_loader.contexts:
context_client.RemoveContext(ContextId(**context['context_id']))
# ----- List entities - Ensure database is empty again -------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == 0
response = context_client.ListDevices(Empty())
assert len(response.devices) == 0
response = context_client.ListLinks(Empty())
assert len(response.links) == 0
...@@ -21,7 +21,7 @@ from common.tools.grpc.Tools import grpc_message_to_json_string ...@@ -21,7 +21,7 @@ from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from monitoring.client.MonitoringClient import MonitoringClient from monitoring.client.MonitoringClient import MonitoringClient
from tests.Fixtures import context_client, device_client, monitoring_client # pylint: disable=unused-import from tests.Fixtures import context_client, monitoring_client # pylint: disable=unused-import
from tests.tools.mock_osm.MockOSM import MockOSM from tests.tools.mock_osm.MockOSM import MockOSM
from .Fixtures import osm_wim # pylint: disable=unused-import from .Fixtures import osm_wim # pylint: disable=unused-import
from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE
...@@ -33,61 +33,27 @@ DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json' ...@@ -33,61 +33,27 @@ DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
# ----- List entities - Ensure scenario is ready ------------------------------------------------------------------- # Load descriptors and validate the base scenario
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f: descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
descriptors = f.read() descriptor_loader.validate()
descriptor_loader = DescriptorLoader(descriptors) # Verify the scenario has no services/slices
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, num_services in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == num_services
for context_uuid, num_slices in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == num_slices
# This scenario assumes no services are created beforehand
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
# Create Connectivity Service
# ----- Create Service ---------------------------------------------------------------------------------------------
service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS) service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
osm_wim.get_connectivity_service_status(service_uuid) osm_wim.get_connectivity_service_status(service_uuid)
# Ensure slices and services are created
# ----- List entities - Ensure service is created ------------------------------------------------------------------ response = context_client.ListSlices(ADMIN_CONTEXT_ID)
response = context_client.ListContexts(Empty()) LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
assert len(response.contexts) == descriptor_loader.num_contexts assert len(response.slices) == 1 # OSM slice
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
response = context_client.ListServices(ADMIN_CONTEXT_ID) response = context_client.ListServices(ADMIN_CONTEXT_ID)
LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
assert len(response.services) == 2 # OLS & L3NM => (L3NM + TAPI) assert len(response.services) == 2 # 1xL3NM + 1xTAPI
for service in response.services: for service in response.services:
service_id = service.service_id service_id = service.service_id
...@@ -104,7 +70,6 @@ def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # ...@@ -104,7 +70,6 @@ def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): #
raise Exception('Unexpected ServiceType: {:s}'.format(str_service)) raise Exception('Unexpected ServiceType: {:s}'.format(str_service))
def test_scenario_kpi_values_created( def test_scenario_kpi_values_created(
monitoring_client: MonitoringClient, # pylint: disable=redefined-outer-name monitoring_client: MonitoringClient, # pylint: disable=redefined-outer-name
) -> None: ) -> None:
......
...@@ -14,10 +14,10 @@ ...@@ -14,10 +14,10 @@
import logging import logging
from common.Constants import DEFAULT_CONTEXT_NAME from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum from common.proto.context_pb2 import ContextId, ServiceTypeEnum
from common.tools.descriptor.Loader import DescriptorLoader from common.tools.descriptor.Loader import DescriptorLoader
from common.tools.object_factory.Context import json_context_id
from common.tools.grpc.Tools import grpc_message_to_json_string from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from tests.Fixtures import context_client # pylint: disable=unused-import from tests.Fixtures import context_client # pylint: disable=unused-import
from tests.tools.mock_osm.MockOSM import MockOSM from tests.tools.mock_osm.MockOSM import MockOSM
...@@ -30,44 +30,27 @@ DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json' ...@@ -30,44 +30,27 @@ DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
# ----- List entities - Ensure service is created ------------------------------------------------------------------ # Ensure slices and services are created
with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f: response = context_client.ListSlices(ADMIN_CONTEXT_ID)
descriptors = f.read() LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
assert len(response.slices) == 1 # OSM slice
descriptor_loader = DescriptorLoader(descriptors)
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
service_uuids = set()
response = context_client.ListServices(ADMIN_CONTEXT_ID) response = context_client.ListServices(ADMIN_CONTEXT_ID)
LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
assert len(response.services) == 2 # OLS & L3NM => (L3NM + TAPI) assert len(response.services) == 2 # 1xL3NM + 1xTAPI
service_uuids = set()
for service in response.services: for service in response.services:
service_id = service.service_id service_id = service.service_id
if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
service_uuid = service_id.service_uuid.uuid
service_uuids.add(service_uuid)
osm_wim.conn_info[service_uuid] = {}
response = context_client.ListConnections(service_id) response = context_client.ListConnections(service_id)
LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( LOGGER.info(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response))) grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM: if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
assert len(response.connections) == 1 # 1 connection per service assert len(response.connections) == 1 # 1 connection per service
service_uuid = service_id.service_uuid.uuid
service_uuids.add(service_uuid)
osm_wim.conn_info[service_uuid] = {}
elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE: elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
assert len(response.connections) == 1 # 1 connection per service assert len(response.connections) == 1 # 1 connection per service
else: else:
...@@ -78,34 +61,14 @@ def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # p ...@@ -78,34 +61,14 @@ def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # p
assert len(service_uuids) == 1 # assume a single L3NM service has been created assert len(service_uuids) == 1 # assume a single L3NM service has been created
service_uuid = set(service_uuids).pop() service_uuid = set(service_uuids).pop()
# Delete Connectivity Service
# ----- Delete Service ---------------------------------------------------------------------------------------------
osm_wim.delete_connectivity_service(service_uuid) osm_wim.delete_connectivity_service(service_uuid)
# Verify the scenario has no services/slices
# ----- List entities - Ensure service is removed ------------------------------------------------------------------
response = context_client.ListContexts(Empty())
assert len(response.contexts) == descriptor_loader.num_contexts
for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
assert len(response.topologies) == num_topologies
response = context_client.ListDevices(Empty())
assert len(response.devices) == descriptor_loader.num_devices
response = context_client.ListLinks(Empty())
assert len(response.links) == descriptor_loader.num_links
for context_uuid, num_services in descriptor_loader.num_services.items():
response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
assert len(response.services) == num_services
for context_uuid, num_slices in descriptor_loader.num_slices.items():
response = context_client.ListSlices(ContextId(**json_context_id(context_uuid)))
assert len(response.slices) == num_slices
# This scenario assumes no services are created beforehand
response = context_client.GetContext(ADMIN_CONTEXT_ID) response = context_client.GetContext(ADMIN_CONTEXT_ID)
assert len(response.service_ids) == 0 assert len(response.service_ids) == 0
assert len(response.slice_ids) == 0 assert len(response.slice_ids) == 0
# Load descriptors and validate the base scenario
descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
descriptor_loader.validate()
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
import logging, sys import logging, sys
from common.tests.LoadScenario import load_scenario_from_descriptor from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results
from context.client.ContextClient import ContextClient from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient from device.client.DeviceClient import DeviceClient
from service.client.ServiceClient import ServiceClient from service.client.ServiceClient import ServiceClient
...@@ -29,7 +29,12 @@ def main(): ...@@ -29,7 +29,12 @@ def main():
slice_client = SliceClient() slice_client = SliceClient()
LOGGER.info('Loading scenario...') LOGGER.info('Loading scenario...')
load_scenario_from_descriptor(sys.argv[1], context_client, device_client, service_client, slice_client) descriptor_loader = DescriptorLoader(
descriptors_file=sys.argv[1], context_client=context_client, device_client=device_client,
service_client=service_client, slice_client=slice_client)
results = descriptor_loader.process()
check_descriptor_load_results(results, descriptor_loader)
descriptor_loader.validate()
LOGGER.info('Done!') LOGGER.info('Done!')
return 0 return 0
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment