From 5ca82a812a0a4eb6d654c3e25994bfc396df24a9 Mon Sep 17 00:00:00 2001 From: Hoson Ryoma <92765511+ryoma-hoson@users.noreply.github.com> Date: Tue, 17 May 2022 16:47:17 +0900 Subject: [PATCH] xlate/openconfig: add cache datastore option This change adds a runtime option for the OpenConfig translator to use a cache datastore. It may improve the response speed to retrieve operational states of OpenConfig models. However, it also introduces differences between the operational states and actual states of the device as a side effect. --- src/xlate/openconfig/README.md | 6 +- .../goldstone/xlate/openconfig/cache.py | 67 + .../xlate/openconfig/cache_updater.py | 90 ++ .../goldstone/xlate/openconfig/interfaces.py | 22 +- .../goldstone/xlate/openconfig/lib.py | 132 +- .../goldstone/xlate/openconfig/main.py | 33 +- .../goldstone/xlate/openconfig/platform.py | 31 +- .../goldstone/xlate/openconfig/telemetry.py | 25 +- .../xlate/openconfig/terminal_device.py | 46 +- src/xlate/openconfig/tests/lib.py | 48 +- src/xlate/openconfig/tests/test.py | 2 +- src/xlate/openconfig/tests/test_cache.py | 1348 +++++++++++++++++ src/xlate/openconfig/tests/test_interface.py | 26 +- src/xlate/openconfig/tests/test_platform.py | 74 +- .../openconfig/tests/test_terminal_device.py | 3 +- 15 files changed, 1823 insertions(+), 130 deletions(-) create mode 100644 src/xlate/openconfig/goldstone/xlate/openconfig/cache.py create mode 100644 src/xlate/openconfig/goldstone/xlate/openconfig/cache_updater.py create mode 100644 src/xlate/openconfig/tests/test_cache.py diff --git a/src/xlate/openconfig/README.md b/src/xlate/openconfig/README.md index c2555e51..d364b6b8 100644 --- a/src/xlate/openconfig/README.md +++ b/src/xlate/openconfig/README.md @@ -50,7 +50,7 @@ sudo pip3 install . ```sh $ gsxlated-openconfig -h -usage: gsxlated-openconfig [-h] [-v] operational-modes-file +usage: gsxlated-openconfig [-h] [-v] [-c {none,in-memory}] operational-modes-file positional arguments: operational-modes-file @@ -59,10 +59,12 @@ positional arguments: options: -h, --help show this help message and exit -v, --verbose enable detailed output + -c {none,in-memory}, --cache-datastore {none,in-memory} + select cache datastore ``` Example: ```sh -gsxlated-openconfig operational-modes.json +gsxlated-openconfig -c none operational-modes.json ``` diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/cache.py b/src/xlate/openconfig/goldstone/xlate/openconfig/cache.py new file mode 100644 index 00000000..fc76f2e8 --- /dev/null +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/cache.py @@ -0,0 +1,67 @@ +"""Cache datastore for OpenConfig translators.""" + + +from abc import abstractmethod +import logging + + +logger = logging.getLogger(__name__) + + +class CacheDataNotExistError(Exception): + pass + + +class Cache: + """Base for cache datastore. + + It is an abstract class. You should implement a subclass for each datastore type. + """ + + @abstractmethod + def get(self, module): + """Get operational state data of a module from the cache datastore. + + Args: + module (str): Module name. + + Returns: + dict: Operational state data of a module. + + Raises: + CacheDataNotExistError: Data for the module does not exist in the cache datastore. + """ + pass + + @abstractmethod + def set(self, module, data): + """Set operational state data of an OpenConfig model to the cache datastore. + + Args: + module (str): Module name. + data (dict): Operational state data of a model. + """ + pass + + +class InMemoryCache(Cache): + """In-memory cache datastore. + + Attribute: + _data (dict): Operational state data for modules. A key is a module name. + """ + + def __init__(self): + self._data = {} + + def get(self, module): + try: + return self._data[module] + except KeyError as e: + logger.error("%s is not cached.", module) + raise CacheDataNotExistError( + f"Cache data for {module} does not exist in the cache datastore" + ) from e + + def set(self, module, data): + self._data[module] = data diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/cache_updater.py b/src/xlate/openconfig/goldstone/xlate/openconfig/cache_updater.py new file mode 100644 index 00000000..65b2cc54 --- /dev/null +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/cache_updater.py @@ -0,0 +1,90 @@ +"""Cache data updater for OpenConfig translators.""" + +import asyncio +import logging +from .interfaces import InterfacesObjectTree +from .platform import PlatformObjectTree +from .terminal_device import TerminalDeviceObjectTree +from .telemetry import TelemetryObjectTree +from goldstone.lib.errors import Error as ConnectorError +from goldstone.lib.connector.sysrepo import Connector + + +logger = logging.getLogger(__name__) + + +DEFAULT_UPDATE_INTERVAL = 5 + + +class CacheUpdater: + """Cache data updater for OpenConfig translators. + + Args: + cache (Cache): Cache datastore instance to use. + operational_modes (dict): Supported operational-modes. + update_interval (int): Interval seconds between executions of the update task. + """ + + def __init__( + self, cache, operational_modes, update_interval=DEFAULT_UPDATE_INTERVAL + ): + self._cache = cache + self._operational_modes = operational_modes + self._update_interval = update_interval + self._connector = Connector() + self._required_data = [] + self._object_trees = { + "openconfig-interfaces": InterfacesObjectTree(), + "openconfig-platform": PlatformObjectTree(self._operational_modes), + "openconfig-terminal-device": TerminalDeviceObjectTree( + self._operational_modes + ), + "openconfig-telemetry": TelemetryObjectTree(), + } + for _, object_tree in self._object_trees.items(): + for data in object_tree.required_data(): + if not data in self._required_data: + self._required_data.append(data) + + def _get_gs(self): + """Get operational state data of Goldstone primitive models from the central datastore. + + Returns: + dict: Operational state data of Goldstone primitive models. + """ + gs = {} + for d in self._required_data: + try: + gs[d["name"]] = self._connector.get_operational( + d["xpath"], d["default"] + ) + except ConnectorError as e: + logger.error("Failed to get source data from %s. %s", d["name"], e) + return gs + + async def _update(self): + """Update cache datastore.""" + gs = self._get_gs() + for module, object_tree in self._object_trees.items(): + try: + self._cache.set(module, object_tree.create(gs)) + except Exception as e: + logger.error("Failed to update cache data for %s. %s", module, e) + + async def _update_loop(self): + """Update task coroutine.""" + while True: + await asyncio.sleep(self._update_interval) + await self._update() + + async def start(self): + """Start a service. + + Returns: + list: List of coroutine objects. + """ + return [self._update_loop()] + + async def stop(self): + """Stop a service.""" + pass diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/interfaces.py b/src/xlate/openconfig/goldstone/xlate/openconfig/interfaces.py index 22c5365b..2282f54b 100644 --- a/src/xlate/openconfig/goldstone/xlate/openconfig/interfaces.py +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/interfaces.py @@ -15,6 +15,7 @@ from .lib import ( OpenConfigChangeHandler, OpenConfigObjectFactory, + OpenConfigObjectTree, OpenConfigServer, ) from .platform import ComponentNameResolver @@ -471,11 +472,24 @@ def create(self, gs): return result +class InterfacesObjectTree(OpenConfigObjectTree): + """OpenConfigObjectTree for the openconfig-interfaces module. + + It creates an operational state tree of the openconfig-interfaces module. + """ + + def __init__(self): + super().__init__() + self.objects = { + "interfaces": {"interface": InterfaceFactory(ComponentNameResolver())} + } + + class InterfaceServer(OpenConfigServer): """InterfaceServer provides a service for the openconfig-interfaces module to central datastore.""" - def __init__(self, conn, reconciliation_interval=10): - super().__init__(conn, "openconfig-interfaces", reconciliation_interval) + def __init__(self, conn, cache, reconciliation_interval=10): + super().__init__(conn, "openconfig-interfaces", cache, reconciliation_interval) self.handlers = { "interfaces": { "interface": { @@ -498,9 +512,7 @@ def __init__(self, conn, reconciliation_interval=10): } } } - self.objects = { - "interfaces": {"interface": InterfaceFactory(ComponentNameResolver())} - } + self._object_tree = InterfacesObjectTree() async def reconcile(self): # NOTE: This should be implemented as a separated class of function to remove the dependency from the diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/lib.py b/src/xlate/openconfig/goldstone/xlate/openconfig/lib.py index d114c3b9..cec674c6 100644 --- a/src/xlate/openconfig/goldstone/xlate/openconfig/lib.py +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/lib.py @@ -13,7 +13,9 @@ The classes this framework library provides are: - OpenConfigServer: provides a service for an OpenConfig module. e.g. "openconfig-interfaces" - It has "OpenConfigObjectFactory"s and "OpenConfigChangeHandler"s. + It has "OpenConfigObjectTree"s and "OpenConfigChangeHandler"s. +- OpenConfigObjectTree: creates a data tree instance that includes operational states for an OpenConfig module. + It has "OpenConfigObjectFactory"s. - OpenConfigObjectFactory: creates OpenConfig objects by translating Goldstone operational state data. - OpenConfigChangeHandler: configure a device with provided OpenConfig configuration state data. @@ -27,6 +29,7 @@ import libyang from goldstone.lib.core import ChangeHandler, ServerBase from goldstone.lib.errors import Error, InvalArgError, NotFoundError +from .cache import CacheDataNotExistError logger = logging.getLogger(__name__) @@ -180,7 +183,7 @@ class OpenConfigObjectFactory: @abstractmethod def required_data(self): - """Return required data list to create OpenConfig objects. + """Return a list of required data to create OpenConfig objects. Returns: list: List of required data dictionaries. @@ -205,6 +208,64 @@ def create(self, gs): pass +class OpenConfigObjectTree: + """Data tree factory base for OpenConfig modules. + + It creates an operational state data tree of an OpenConfig module. It has "OpenConfigObjectFactory"s related to the + module. You should implement the "self.objects" attribute in your subclass. + + Attributes: + objects (dict): OpenConfigObjectFactory instances for an OpenConfig module. + A dictionary key represents a data node. + """ + + def __init__(self): + self.objects = {} + + def _create_tree(self, gs, subtree): + result = {} + for k, v in subtree.items(): + if isinstance(v, dict): + result[k] = self._create_tree(gs, v) + elif isinstance(v, OpenConfigObjectFactory): + result[k] = v.create(gs) + return result + + def _get_factories(self, subtree): + result = [] + for _, v in subtree.items(): + if isinstance(v, dict): + result += self._get_factories(v) + elif isinstance(v, OpenConfigObjectFactory): + result.append(v) + return result + + def required_data(self): + """Return a list of required data to create OpenConfig objects. + + Returns: + list: List of required data dictionaries. See OpenConfigObjectFactory.required_data(). + """ + required_data = [] + factories = self._get_factories(self.objects) + for factory in factories: + for data in factory.required_data(): + if not data in required_data: + required_data.append(data) + return required_data + + def create(self, gs): + """Create an operational state data tree of an OpenConfig module. + + Args: + gs (dict): Data from Goldstone native/primitive models. + + Returns: + dict: Operational state data tree of an Openconfig module. + """ + return self._create_tree(gs, self.objects) + + class OpenConfigServer(ServerBase): """Server base for OpenConfig translators. @@ -222,6 +283,8 @@ class OpenConfigServer(ServerBase): Args: conn (Connector): Connection to the central datastore. module (str): YANG module name of the service. e.g. "openconfig-interfaces" + cache (Cache): Cache datastore instance to store operational state data of OpenConfig modules. + If it is None, OpenConfigServer does not use cached data. reconciliation_interval (int): Interval seconds between executions of the reconcile task. Attributes: @@ -239,21 +302,16 @@ class OpenConfigServer(ServerBase): } } } - objects (dict): "OpenConfigObjectFactory" instances for each OpenConfig subtree. - e.g. - { - "interfaces": { - "interface": InterfaceFactory(ComponentNameResolver()) # InterfaceFactory for /interfaces/interface - } - } """ - def __init__(self, conn, module, reconciliation_interval=10): + def __init__(self, conn, module, cache, reconciliation_interval=10): super().__init__(conn, module) + self.module = module self.reconciliation_interval = reconciliation_interval self.reconcile_task = None self.handlers = {} - self.objects = {} + self._cache = cache + self._object_tree = None async def reconcile(self): """Reconcile between OpenConfig configuration state and Goldstone configuration state.""" @@ -307,22 +365,12 @@ async def post(self, user): logger.error("Failed to apply changes. %s", e) raise e - async def _create_objects(self, factory): - required_data = factory.required_data() - src = {} + def _get_gs(self, required_data): + gs = {} for d in required_data: data = self.get_operational_data(d["xpath"], d["default"]) - src[d["name"]] = data - return factory.create(src) - - async def _create_tree(self, subtree): - result = {} - for k, v in subtree.items(): - if isinstance(v, dict): - result[k] = await self._create_tree(v) - elif isinstance(v, OpenConfigObjectFactory): - result[k] = await self._create_objects(v) - return result + gs[d["name"]] = data + return gs async def oper_cb(self, xpath, priv): """Callback function to get operational state of the service. @@ -335,9 +383,33 @@ async def oper_cb(self, xpath, priv): {"name": "Ethernet1/0/2", "state": {"oper-status": "DOWN"}}, ]}} """ - try: - result = await self._create_tree(self.objects) - except Exception as e: - logger.error("Operational state creation failed. %s", e) - raise e + if self._cache is None: + try: + required_data = self._object_tree.required_data() + gs = self._get_gs(required_data) + result = self._object_tree.create(gs) + except Exception as e: + logger.error( + "Failed to create operational state data for %s by an error: %s", + self.module, + e, + ) + raise e + else: + try: + result = self._cache.get(self.module) + except CacheDataNotExistError as e: + logger.error( + "The operational state data for %s was not cached in the cache datastore. %s", + self.module, + e, + ) + raise e + except Exception as e: + logger.error( + "Failed to get operational state data for %s from the cache datastore by an error: %s", + self.module, + e, + ) + raise e return result diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/main.py b/src/xlate/openconfig/goldstone/xlate/openconfig/main.py index 916e59d2..17400b91 100644 --- a/src/xlate/openconfig/goldstone/xlate/openconfig/main.py +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/main.py @@ -12,11 +12,19 @@ from .platform import PlatformServer from .terminal_device import TerminalDeviceServer from .telemetry import TelemetryServer +from .cache import InMemoryCache +from .cache_updater import CacheUpdater logger = logging.getLogger(__name__) +CACHES = { + "none": None, + "in-memory": InMemoryCache, +} + + def load_operational_modes(operational_modes_file): try: with open(operational_modes_file, "r", encoding="utf-8") as f: @@ -44,18 +52,21 @@ def load_operational_modes(operational_modes_file): def main(): - async def _main(operational_modes): + async def _main(cache, operational_modes): loop = asyncio.get_event_loop() stop_event = asyncio.Event() loop.add_signal_handler(signal.SIGINT, stop_event.set) loop.add_signal_handler(signal.SIGTERM, stop_event.set) conn = Connector() - ifserver = InterfaceServer(conn) - pfserver = PlatformServer(conn, operational_modes) - tdserver = TerminalDeviceServer(conn, operational_modes) - tlserver = TelemetryServer(conn) + ifserver = InterfaceServer(conn, cache) + pfserver = PlatformServer(conn, cache, operational_modes) + tdserver = TerminalDeviceServer(conn, cache, operational_modes) + tlserver = TelemetryServer(conn, cache) servers = [ifserver, pfserver, tdserver, tlserver] + if cache is not None: + cacheupdater = CacheUpdater(cache, operational_modes) + servers.append(cacheupdater) try: tasks = list( @@ -88,6 +99,13 @@ async def _main(operational_modes): metavar="operational-modes-file", help="path to operational-modes config file", ) + parser.add_argument( + "-c", + "--cache-datastore", + choices=CACHES.keys(), + default="none", + help="select cache datastore", + ) args = parser.parse_args() fmt = "%(levelname)s %(module)s %(funcName)s l.%(lineno)d | %(message)s" @@ -103,9 +121,12 @@ async def _main(operational_modes): else: logging.basicConfig(level=logging.INFO, format=fmt) + cache = CACHES[args.cache_datastore] + if cache is not None: + cache = cache() operational_modes = load_operational_modes(args.operational_modes_file) - asyncio.run(_main(operational_modes)) + asyncio.run(_main(cache, operational_modes)) if __name__ == "__main__": diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/platform.py b/src/xlate/openconfig/goldstone/xlate/openconfig/platform.py index ef9cd2a4..a1ab2460 100644 --- a/src/xlate/openconfig/goldstone/xlate/openconfig/platform.py +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/platform.py @@ -20,6 +20,7 @@ from .lib import ( OpenConfigChangeHandler, OpenConfigObjectFactory, + OpenConfigObjectTree, OpenConfigServer, ) @@ -1724,6 +1725,26 @@ def create(self, gs): return result +class PlatformObjectTree(OpenConfigObjectTree): + """OpenConfigObjectTree for the openconfig-platform module. + + It creates an operational state data tree of the openconfig-platform module. + + Args: + operational_modes (dict): Supported operational-modes. + """ + + def __init__(self, operational_modes): + super().__init__() + self.objects = { + "components": { + "component": ComponentFactory( + operational_modes, ComponentNameResolver() + ) + } + } + + class PlatformServer(OpenConfigServer): """PlatformServer provides a service for the openconfig-platform module to central datastore. @@ -1735,8 +1756,8 @@ class PlatformServer(OpenConfigServer): cnr (ComponentNameResolver): OpenConfig component name resolver. """ - def __init__(self, conn, operational_modes, reconciliation_interval=10): - super().__init__(conn, "openconfig-platform", reconciliation_interval) + def __init__(self, conn, cache, operational_modes, reconciliation_interval=10): + super().__init__(conn, "openconfig-platform", cache, reconciliation_interval) self.handlers = { "components": { "component": { @@ -1767,11 +1788,7 @@ def __init__(self, conn, operational_modes, reconciliation_interval=10): } self.operational_modes = operational_modes self.cnr = ComponentNameResolver() - self.objects = { - "components": { - "component": ComponentFactory(self.operational_modes, self.cnr) - } - } + self._object_tree = PlatformObjectTree(self.operational_modes) async def reconcile(self): # TODO: implement diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/telemetry.py b/src/xlate/openconfig/goldstone/xlate/openconfig/telemetry.py index 9524c27c..d3c5a21d 100644 --- a/src/xlate/openconfig/goldstone/xlate/openconfig/telemetry.py +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/telemetry.py @@ -8,7 +8,7 @@ """ -from .lib import OpenConfigObjectFactory, OpenConfigServer +from .lib import OpenConfigObjectFactory, OpenConfigObjectTree, OpenConfigServer class DynamicSubscription: @@ -109,15 +109,14 @@ def create(self, gs): return result -class TelemetryServer(OpenConfigServer): - """TelemetryServer provides a service for the openconfig-telemetry module to central datastore. +class TelemetryObjectTree(OpenConfigObjectTree): + """OpenConfigObjectTree for the openconfig-telemetry module. - The server provides operational state information of subscriptions. + It creates an operational state data tree of the openconfig-telemetry module. """ - def __init__(self, conn, reconciliation_interval=10): - super().__init__(conn, "openconfig-telemetry", reconciliation_interval) - self.handlers = {"telemetry-system": {}} + def __init__(self): + super().__init__() self.objects = { "telemetry-system": { "subscriptions": { @@ -127,3 +126,15 @@ def __init__(self, conn, reconciliation_interval=10): } } } + + +class TelemetryServer(OpenConfigServer): + """TelemetryServer provides a service for the openconfig-telemetry module to central datastore. + + The server provides operational state information of subscriptions. + """ + + def __init__(self, conn, cache, reconciliation_interval=10): + super().__init__(conn, "openconfig-telemetry", cache, reconciliation_interval) + self.handlers = {"telemetry-system": {}} + self._object_tree = TelemetryObjectTree() diff --git a/src/xlate/openconfig/goldstone/xlate/openconfig/terminal_device.py b/src/xlate/openconfig/goldstone/xlate/openconfig/terminal_device.py index a7e82a42..924e86bd 100644 --- a/src/xlate/openconfig/goldstone/xlate/openconfig/terminal_device.py +++ b/src/xlate/openconfig/goldstone/xlate/openconfig/terminal_device.py @@ -18,7 +18,7 @@ import logging import struct import base64 -from .lib import OpenConfigObjectFactory, OpenConfigServer +from .lib import OpenConfigObjectFactory, OpenConfigServer, OpenConfigObjectTree from .platform import ComponentFactory, ComponentNameResolver @@ -855,6 +855,33 @@ def create(self, gs): return operational_modes +class TerminalDeviceObjectTree(OpenConfigObjectTree): + """OpenConfigObjectTree for the openconfig-terminal-device module. + + It creates an operational state data tree of the openconfig-terminal-device module. + + Args: + operational_modes (dict): Supported operational-modes. + """ + + def __init__(self, operational_modes): + super().__init__() + cnr = ComponentNameResolver() + self.objects = { + "terminal-device": { + "logical-channels": { + "channel": LogicalChannelFactory( + cnr, + ComponentFactory(operational_modes, cnr), + ) + }, + "operational-modes": { + "mode": OperationalModeFactory(operational_modes) + }, + } + } + + class TerminalDeviceServer(OpenConfigServer): """TerminalDeviceServer provides a service for the openconfig-terminal-device module to central datastore. @@ -865,20 +892,13 @@ class TerminalDeviceServer(OpenConfigServer): operational_modes (dict): Suppoerted operational-modes. """ - def __init__(self, conn, operational_modes, reconciliation_interval=10): - super().__init__(conn, "openconfig-terminal-device", reconciliation_interval) + def __init__(self, conn, cache, operational_modes, reconciliation_interval=10): + super().__init__( + conn, "openconfig-terminal-device", cache, reconciliation_interval + ) self.handlers = {"terminal-device": {}} self.operational_modes = operational_modes - cnr = ComponentNameResolver() - cf = ComponentFactory(self.operational_modes, cnr) - self.objects = { - "terminal-device": { - "logical-channels": {"channel": LogicalChannelFactory(cnr, cf)}, - "operational-modes": { - "mode": OperationalModeFactory(self.operational_modes) - }, - } - } + self._object_tree = TerminalDeviceObjectTree(self.operational_modes) async def reconcile(self): pass diff --git a/src/xlate/openconfig/tests/lib.py b/src/xlate/openconfig/tests/lib.py index 6d1e9ce1..570a6fe8 100644 --- a/src/xlate/openconfig/tests/lib.py +++ b/src/xlate/openconfig/tests/lib.py @@ -1,5 +1,6 @@ """Library for tests for translator services.""" +# pylint: disable=C0103 import unittest import os @@ -11,7 +12,6 @@ from queue import Empty from goldstone.lib.core import ServerBase, ChangeHandler, NoOp from goldstone.lib.connector.sysrepo import Connector -from goldstone.lib.util import call def load_operational_modes(): @@ -204,6 +204,10 @@ async def evloop(): conn.stop() +class NoneClass: + pass + + class XlateTestCase(unittest.IsolatedAsyncioTestCase): """Test case base class for translator servers. @@ -212,10 +216,22 @@ class XlateTestCase(unittest.IsolatedAsyncioTestCase): XLATE_SERVER_OPT (list): Arguments that will be given to the server. XLATE_MODULES (list): Module names the server will provide. MOCK_MODULES (list): Module names the server will use. + CACHE_DATASTORE (Cache): Cache class for XLATE_SERVER and CACHE_UPDATER. + CACHE_UPDATER (CacheUpdater): CacheUpdater class to test. """ + XLATE_SERVER = NoneClass + XLATE_SERVER_OPT = [] + XLATE_MODULES = [] + MOCK_MODULES = [] + CACHE_DATASTORE = NoneClass + CACHE_UPDATER = NoneClass + async def asyncSetUp(self): - logging.basicConfig(level=logging.DEBUG) + logging.basicConfig(level=logging.CRITICAL) + # NOTE: Enable for debugging. + # logging.basicConfig(level=logging.DEBUG) + # self.maxDiff = None self.conn = Connector() for module in self.MOCK_MODULES: @@ -228,10 +244,27 @@ async def asyncSetUp(self): self.process = Process(target=run_mock_server, args=(self.q, self.MOCK_MODULES)) self.process.start() - self.server = self.XLATE_SERVER( - self.conn, reconciliation_interval=1, *self.XLATE_SERVER_OPT - ) - self.tasks = list(asyncio.create_task(c) for c in await self.server.start()) + cache = None + if self.CACHE_DATASTORE is not NoneClass: + cache = self.CACHE_DATASTORE() + self.servers = [] + if self.XLATE_SERVER is not NoneClass: + self.server = self.XLATE_SERVER( + self.conn, cache, reconciliation_interval=1, *self.XLATE_SERVER_OPT + ) + self.servers.append(self.server) + if self.CACHE_UPDATER is not NoneClass: + operational_mode = load_operational_modes() + self.cache_updater = self.CACHE_UPDATER( + cache, + operational_mode, + update_interval=0.1, + ) + self.servers.append(self.cache_updater) + + self.tasks = [] + for server in self.servers: + self.tasks += list(asyncio.create_task(c) for c in await server.start()) async def run_xlate_test(self, test): """Run a test as a thread. @@ -269,7 +302,8 @@ def set_mock_change_handler(self, server, path, handler): ) async def asyncTearDown(self): - await call(self.server.stop) + for server in self.servers: + await server.stop() self.tasks = [t.cancel() for t in self.tasks] self.conn.stop() self.q.put({"type": "stop"}) diff --git a/src/xlate/openconfig/tests/test.py b/src/xlate/openconfig/tests/test.py index 365c4c92..20b26999 100644 --- a/src/xlate/openconfig/tests/test.py +++ b/src/xlate/openconfig/tests/test.py @@ -9,4 +9,4 @@ sys.path.insert(0, "../../../lib/") sys.path.insert(0, "../") testsuite = unittest.TestLoader().discover(".") - unittest.TextTestRunner().run(testsuite) + unittest.TextTestRunner(verbosity=2).run(testsuite) diff --git a/src/xlate/openconfig/tests/test_cache.py b/src/xlate/openconfig/tests/test_cache.py new file mode 100644 index 00000000..cbf19baf --- /dev/null +++ b/src/xlate/openconfig/tests/test_cache.py @@ -0,0 +1,1348 @@ +"""Tests of the cache feature for OpenConfig translators.""" + +# pylint: disable=W0212 + +import unittest +import time +from goldstone.xlate.openconfig.cache import InMemoryCache, CacheDataNotExistError +from goldstone.xlate.openconfig.cache_updater import CacheUpdater +from tests.lib import XlateTestCase, load_operational_modes + +operational_modes = load_operational_modes() + + +class TestInMemoryCache(unittest.TestCase): + """Tests for InMemoryCache.""" + + def test_get(self): + inmemory_cache = InMemoryCache() + data = { + "interfaces": { + "interface": [ + {"name": "Ethernet1/0/1", "state": {"oper-status": "UP"}}, + {"name": "Ethernet1/0/2", "state": {"oper-status": "DOWN"}}, + ] + } + } + inmemory_cache._data["openconfig-interfaces"] = data + self.assertEqual(inmemory_cache.get("openconfig-interfaces"), data) + + def test_get_not_exist(self): + inmemory_cache = InMemoryCache() + with self.assertRaises(CacheDataNotExistError): + inmemory_cache.get("openconfig-interfaces") + + def test_set(self): + inmemory_cache = InMemoryCache() + data = { + "interfaces": { + "interface": [ + {"name": "Ethernet1/0/1", "state": {"oper-status": "UP"}}, + {"name": "Ethernet1/0/2", "state": {"oper-status": "DOWN"}}, + ] + } + } + inmemory_cache.set("openconfig-interfaces", data) + self.assertEqual(inmemory_cache._data["openconfig-interfaces"], data) + + def test_set_exist(self): + inmemory_cache = InMemoryCache() + data = { + "interfaces": { + "interface": [ + {"name": "Ethernet1/0/1", "state": {"oper-status": "UP"}}, + {"name": "Ethernet1/0/2", "state": {"oper-status": "DOWN"}}, + ] + } + } + inmemory_cache._data["openconfig-interfaces"] = data + updated_data = { + "interfaces": { + "interface": [ + {"name": "Ethernet1/0/1", "state": {"oper-status": "DOWN"}}, + {"name": "Ethernet1/0/2", "state": {"oper-status": "UP"}}, + ] + } + } + inmemory_cache.set("openconfig-interfaces", updated_data) + self.assertEqual(inmemory_cache._data["openconfig-interfaces"], updated_data) + + +class TestCacheUpdater(XlateTestCase): + """Tests for CacheUpdater.""" + + MOCK_MODULES = [ + "goldstone-interfaces", + "goldstone-platform", + "goldstone-transponder", + "goldstone-gearbox", + "goldstone-system", + ] + CACHE_DATASTORE = InMemoryCache + CACHE_UPDATER = CacheUpdater + WAIT_MOCK = 2 + + async def test_create_cache_interfaces(self): + mock_data_interfaces = { + "interfaces": { + "interface": [ + { + "name": "Ethernet1/0/1", + "state": { + "name": "Ethernet1/0/1", + "description": "Ethernet interface.", + "admin-status": "UP", + "oper-status": "UP", + "counters": { + "in-octets": 1000, + "in-unicast-pkts": 100, + "in-broadcast-pkts": 200, + "in-multicast-pkts": 300, + "in-discards": 400, + "in-errors": 500, + "in-unknown-protos": 600, + "out-octets": 2000, + "out-unicast-pkts": 100, + "out-broadcast-pkts": 200, + "out-multicast-pkts": 300, + "out-discards": 400, + "out-errors": 500, + }, + }, + "ethernet": { + "state": { + "mtu": 10000, + "fec": "RS", + } + }, + "component-connection": {"platform": {"component": "port1"}}, + }, + { + "name": "Ethernet1/0/2", + "state": { + "name": "Ethernet1/0/2", + "description": "Ethernet interface.", + "admin-status": "DOWN", + "oper-status": "DOWN", + }, + "ethernet": { + "state": { + "mtu": 10000, + "fec": "NONE", + } + }, + "component-connection": {"platform": {"component": "port2"}}, + }, + { + "name": "Ethernet1/1/1", + "state": { + "name": "Ethernet1/1/1", + }, + "component-connection": { + "transponder": { + "module": "piu1", + "host-interface": "1", + } + }, + }, + { + "name": "Ethernet1/1/2", + "state": { + "name": "Ethernet1/1/2", + }, + "component-connection": { + "transponder": { + "module": "piu1", + "host-interface": "2", + } + }, + }, + ] + } + } + self.set_mock_oper_data("goldstone-interfaces", mock_data_interfaces) + mock_data_platform = { + "components": { + "component": [ + { + "name": "port1", + "state": { + "name": "port1", + "type": "TRANSCEIVER", + }, + "transceiver": { + "state": { + "presence": "PRESENT", + } + }, + }, + { + "name": "port2", + "state": { + "name": "port2", + "type": "TRANSCEIVER", + }, + "transceiver": { + "state": { + "presence": "PRESENT", + } + }, + }, + ] + } + } + self.set_mock_oper_data("goldstone-platform", mock_data_platform) + mock_data_transponder = { + "modules": { + "module": [ + { + "name": "piu1", + "state": { + "name": "piu1", + "localtion": "1", + }, + "network-interface": [ + { + "name": "1", + "state": { + "name": "1", + "line-rate": "400g", + "modulation-format": "dp-16-qam", + "fec-type": "ofec", + "client-signal-mapping-type": "flexo-lr", + "current-pre-fec-ber": "OiIFOA==", + "current-ber-period": 1000000, + }, + }, + ], + "host-interface": [ + { + "name": "1", + "state": { + "name": "1", + "index": 1, + "signal-rate": "100-gbe", + }, + }, + { + "name": "2", + "state": { + "name": "2", + "index": 2, + "signal-rate": "100-gbe", + }, + }, + ], + } + ] + } + } + self.set_mock_oper_data("goldstone-transponder", mock_data_transponder) + + mock_data_gearbox = { + "gearboxes": { + "gearbox": [ + { + "name": "1", + "state": { + "name": "1", + }, + "connections": { + "connection": [ + { + "client-interface": "Ethernet1/0/1", + "line-interface": "Ethernet1/1/1", + }, + { + "client-interface": "Ethernet1/0/2", + "line-interface": "Ethernet1/1/2", + }, + ] + }, + } + ] + } + } + self.set_mock_oper_data("goldstone-gearbox", mock_data_gearbox) + + def test(): + time.sleep(self.WAIT_MOCK) # wait for the mock server and cache updating + data = self.cache_updater._cache.get("openconfig-interfaces") + expected = { + "interfaces": { + "interface": [ + { + "name": "Ethernet1/0/1", + "state": { + "name": "Ethernet1/0/1", + "type": "iana-if-type:ethernetCsmacd", + "mtu": 10000, + "description": "Ethernet interface.", + "enabled": True, + "admin-status": "UP", + "oper-status": "UP", + "counters": { + "in-octets": 1000, + "in-pkts": 2100, + "in-unicast-pkts": 100, + "in-broadcast-pkts": 200, + "in-multicast-pkts": 300, + "in-discards": 400, + "in-errors": 500, + "in-unknown-protos": 600, + "out-octets": 2000, + "out-pkts": 1500, + "out-unicast-pkts": 100, + "out-broadcast-pkts": 200, + "out-multicast-pkts": 300, + "out-discards": 400, + "out-errors": 500, + }, + "hardware-port": "client-port1", + }, + "ethernet": { + "state": { + "fec-mode": "FEC_RS528", + }, + }, + }, + { + "name": "Ethernet1/0/2", + "state": { + "name": "Ethernet1/0/2", + "type": "iana-if-type:ethernetCsmacd", + "mtu": 10000, + "description": "Ethernet interface.", + "enabled": False, + "admin-status": "DOWN", + "oper-status": "DOWN", + "hardware-port": "client-port2", + }, + "ethernet": { + "state": { + "fec-mode": "FEC_DISABLED", + }, + }, + }, + { + "name": "Ethernet1/1/1", + "state": { + "name": "Ethernet1/1/1", + "type": "iana-if-type:ethernetCsmacd", + }, + }, + { + "name": "Ethernet1/1/2", + "state": { + "name": "Ethernet1/1/2", + "type": "iana-if-type:ethernetCsmacd", + }, + }, + ] + } + } + self.assertEqual(data, expected) + + await self.run_xlate_test(test) + + async def test_create_cache_platform(self): + mock_data_platform = { + "components": { + "component": [ + { + "name": "SYS", + "state": { + "type": "SYS", + "id": 1, + "description": "System Information", + }, + "sys": { + "state": { + "onie-info": { + "manufacturer": "Manufacturer", + "serial-number": "Serial number", + "part-number": "Part number", + } + } + }, + }, + { + "name": "THERMAL SENSOR1", + "state": {"type": "THERMAL"}, + "thermal": {"state": {"temperature": 10000}}, + }, + { + "name": "THERMAL SENSOR2", + "state": {"type": "THERMAL"}, + "thermal": {"state": {"temperature": 20000}}, + }, + { + "name": "port1", + "state": { + "name": "port1", + "type": "TRANSCEIVER", + "id": 200, + "description": "QSFP-28 transceiver information.", + }, + "transceiver": { + "state": { + "presence": "PRESENT", + "vendor": "Vendor Name", + "serial": "Serial number", + "model": "Model number", + } + }, + }, + { + "name": "fan", + "state": { + "name": "fan", + "type": "FAN", + "id": 300, + "description": "Fan information.", + }, + "fan": {"state": {"fan-state": "PRESENT", "status": "RUNNING"}}, + }, + { + "name": "power supply", + "state": { + "name": "power supply", + "type": "PSU", + "id": 400, + "description": "PSU information.", + }, + "psu": { + "state": { + "psu-state": "PRESENT", + "status": "RUNNING", + "serial": "Serial number", + "model": "Model number", + "output-power": 50000, + } + }, + }, + ] + } + } + self.set_mock_oper_data("goldstone-platform", mock_data_platform) + mock_data_system = { + "system": {"state": {"software-version": "Software version"}} + } + self.set_mock_oper_data("goldstone-system", mock_data_system) + mock_data_interface = { + "interfaces": { + "interface": [ + { + "name": "Ethernet1/0/1", + "state": { + "name": "Ethernet1/0/1", + "oper-status": "UP", + "admin-status": "UP", + }, + "component-connection": {"platform": {"component": "port1"}}, + }, + { + "name": "Ethernet1/1/1", + "state": { + "name": "Ethernet1/1/1", + }, + "component-connection": { + "transponder": { + "module": "piu1", + "host-interface": "1", + } + }, + }, + ] + } + } + self.set_mock_oper_data("goldstone-interfaces", mock_data_interface) + mock_data_transponder = { + "modules": { + "module": [ + { + "name": "piu1", + "state": { + "name": "piu1", + "oper-status": "ready", + "id": 100, + "description": "CFP2-DCO module information.", + "vendor-name": "Vendor Name", + "firmware-version": "Firmware Version", + "vendor-serial-number": "Vendor Serial number", + "vendor-part-number": "Vendor Part number", + "location": "1", + "temp": 1.3372036854775807, + "admin-status": "up", + }, + "network-interface": [ + { + "name": "1", + "state": { + "name": "1", + "oper-status": "ready", + "id": 10, + "description": "CFP2-DCO network-interface information.", + "index": 1, + "current-chromatic-dispersion": 2000, + "current-input-power": 1.3372036854775807, + "current-output-power": 2.3372036854775807, + "tx-laser-freq": 100000000, + "output-power": 3.3372036854775807, + "line-rate": "100g", + "modulation-format": "dp-qpsk", + "fec-type": "sc-fec", + "client-signal-mapping-type": "otu4-lr", + }, + } + ], + "host-interface": [ + { + "name": "1", + "state": { + "name": "1", + "index": 1, + "signal-rate": "100-gbe", + }, + }, + ], + } + ] + } + } + self.set_mock_oper_data("goldstone-transponder", mock_data_transponder) + mock_data_gearbox = { + "gearboxes": { + "gearbox": [ + { + "name": "1", + "state": { + "name": "1", + }, + "connections": { + "connection": [ + { + "client-interface": "Ethernet1/0/1", + "line-interface": "Ethernet1/1/1", + }, + ] + }, + } + ] + } + } + self.set_mock_oper_data("goldstone-gearbox", mock_data_gearbox) + + def test(): + time.sleep(self.WAIT_MOCK) # wait for the mock server and cache updating + data = self.cache_updater._cache.get("openconfig-platform") + expected = { + "components": { + "component": [ + { + "name": "CHASSIS", + "state": { + "name": "CHASSIS", + "type": "openconfig-platform-types:CHASSIS", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "1", + "description": "System Information", + "mfg-name": "Manufacturer", + "software-version": "Software version", + "serial-no": "Serial number", + "part-no": "Part number", + "temperature": {"instant": 10.0}, + "removable": False, + }, + "subcomponents": { + "subcomponent": [ + { + "name": "line-piu1", + "state": {"name": "line-piu1"}, + }, + { + "name": "client-port1", + "state": {"name": "client-port1"}, + }, + {"name": "fan", "state": {"name": "fan"}}, + { + "name": "power supply", + "state": {"name": "power supply"}, + }, + ] + }, + }, + { + "name": "line-piu1", + "state": { + "name": "line-piu1", + "type": "openconfig-platform-types:PORT", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "100", + "description": "CFP2-DCO module information.", + "location": "1", + "parent": "CHASSIS", + "removable": False, + }, + "subcomponents": { + "subcomponent": [ + { + "name": "transceiver-line-piu1", + "state": {"name": "transceiver-line-piu1"}, + } + ] + }, + "port": { + "optical-port": { + "state": { + "admin-state": "ENABLED", + "optical-port-type": "openconfig-transport-types:TERMINAL_LINE", + } + } + }, + }, + { + "name": "transceiver-line-piu1", + "state": { + "name": "transceiver-line-piu1", + "type": "openconfig-platform-types:TRANSCEIVER", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "100", + "description": "CFP2-DCO module information.", + "mfg-name": "Vendor Name", + "software-version": "Firmware Version", + "serial-no": "Vendor Serial number", + "part-no": "Vendor Part number", + "location": "1", + "parent": "line-piu1", + "temperature": {"instant": 1.3}, + "removable": True, + }, + "subcomponents": { + "subcomponent": [ + { + "name": "och-transceiver-line-piu1-1", + "state": { + "name": "och-transceiver-line-piu1-1" + }, + } + ] + }, + }, + { + "name": "och-transceiver-line-piu1-1", + "state": { + "name": "och-transceiver-line-piu1-1", + "type": "openconfig-transport-types:OPTICAL_CHANNEL", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "10", + "description": "CFP2-DCO network-interface information.", + "location": "1", + "parent": "transceiver-line-piu1", + "removable": False, + }, + "optical-channel": { + "state": { + "chromatic-dispersion": {"instant": 2000.0}, + "input-power": {"instant": 1.34}, + "output-power": {"instant": 2.34}, + "frequency": 100, + "target-output-power": 3.34, + "operational-mode": 100, + } + }, + "properties": { + "property": [ + { + "name": "CROSS_CONNECTION", + "state": { + "name": "CROSS_CONNECTION", + "value": "PRESET", + }, + }, + { + "name": "latency", + "state": {"name": "latency", "value": None}, + }, + ] + }, + }, + { + "name": "client-port1", + "state": { + "name": "client-port1", + "type": "openconfig-platform-types:PORT", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "200", + "description": "QSFP-28 transceiver information.", + "parent": "CHASSIS", + "removable": False, + }, + "subcomponents": { + "subcomponent": [ + { + "name": "transceiver-client-port1", + "state": {"name": "transceiver-client-port1"}, + } + ] + }, + "port": { + "optical-port": { + "state": { + "admin-state": "ENABLED", + "optical-port-type": "openconfig-transport-types:TERMINAL_CLIENT", + } + } + }, + }, + { + "name": "transceiver-client-port1", + "state": { + "name": "transceiver-client-port1", + "type": "openconfig-platform-types:TRANSCEIVER", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "200", + "description": "QSFP-28 transceiver information.", + "mfg-name": "Vendor Name", + "serial-no": "Serial number", + "part-no": "Model number", + "parent": "client-port1", + "removable": True, + }, + }, + { + "name": "fan", + "state": { + "name": "fan", + "type": "openconfig-platform-types:FAN", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "300", + "description": "Fan information.", + "parent": "CHASSIS", + }, + }, + { + "name": "power supply", + "state": { + "name": "power supply", + "type": "openconfig-platform-types:POWER_SUPPLY", + "oper-status": "openconfig-platform-types:ACTIVE", + "id": "400", + "description": "PSU information.", + "serial-no": "Serial number", + "part-no": "Model number", + "parent": "CHASSIS", + "used-power": 50, + }, + }, + ] + } + } + self.assertEqual(data, expected) + + await self.run_xlate_test(test) + + async def test_create_cache_terminal_device(self): + mock_data_interface = { + "interfaces": { + "interface": [ + { + "name": "Ethernet1/0/1", + "state": { + "name": "Ethernet1/0/1", + }, + "component-connection": {"platform": {"component": "port1"}}, + }, + { + "name": "Ethernet1/0/2", + "state": { + "name": "Ethernet1/0/2", + }, + "component-connection": {"platform": {"component": "port2"}}, + }, + { + "name": "Ethernet1/0/3", + "state": { + "name": "Ethernet1/0/3", + }, + "component-connection": {"platform": {"component": "port3"}}, + }, + { + "name": "Ethernet1/0/4", + "state": { + "name": "Ethernet1/0/4", + }, + "component-connection": {"platform": {"component": "port4"}}, + }, + { + "name": "Ethernet1/1/1", + "state": { + "name": "Ethernet1/1/1", + }, + "component-connection": { + "transponder": { + "module": "piu1", + "host-interface": "1", + } + }, + }, + { + "name": "Ethernet1/1/2", + "state": { + "name": "Ethernet1/1/2", + }, + "component-connection": { + "transponder": { + "module": "piu1", + "host-interface": "2", + } + }, + }, + { + "name": "Ethernet1/1/3", + "state": { + "name": "Ethernet1/1/3", + }, + "component-connection": { + "transponder": { + "module": "piu1", + "host-interface": "3", + } + }, + }, + { + "name": "Ethernet1/1/4", + "state": { + "name": "Ethernet1/1/4", + }, + "component-connection": { + "transponder": { + "module": "piu1", + "host-interface": "4", + } + }, + }, + ] + } + } + self.set_mock_oper_data("goldstone-interfaces", mock_data_interface) + mock_data_platform = { + "components": { + "component": [ + { + "name": "port1", + "state": { + "name": "port1", + "type": "TRANSCEIVER", + }, + "transceiver": { + "state": { + "presence": "PRESENT", + } + }, + }, + { + "name": "port2", + "state": { + "name": "port2", + "type": "TRANSCEIVER", + }, + "transceiver": { + "state": { + "presence": "PRESENT", + } + }, + }, + { + "name": "port3", + "state": { + "name": "port3", + "type": "TRANSCEIVER", + }, + "transceiver": { + "state": { + "presence": "PRESENT", + } + }, + }, + { + "name": "port4", + "state": { + "name": "port4", + "type": "TRANSCEIVER", + }, + "transceiver": { + "state": { + "presence": "PRESENT", + } + }, + }, + ] + } + } + self.set_mock_oper_data("goldstone-platform", mock_data_platform) + mock_data_transponder = { + "modules": { + "module": [ + { + "name": "piu1", + "state": { + "name": "piu1", + "localtion": "1", + }, + "network-interface": [ + { + "name": "1", + "state": { + "name": "1", + "line-rate": "400g", + "modulation-format": "dp-16-qam", + "fec-type": "ofec", + "client-signal-mapping-type": "flexo-lr", + "current-pre-fec-ber": "OiIFOA==", + "current-ber-period": 1000000, + }, + }, + ], + "host-interface": [ + { + "name": "1", + "state": { + "name": "1", + "index": 1, + "signal-rate": "100-gbe", + }, + }, + { + "name": "2", + "state": { + "name": "2", + "index": 2, + "signal-rate": "100-gbe", + }, + }, + { + "name": "3", + "state": { + "name": "3", + "index": 3, + "signal-rate": "100-gbe", + }, + }, + { + "name": "4", + "state": { + "name": "4", + "index": 4, + "signal-rate": "100-gbe", + }, + }, + ], + } + ] + } + } + self.set_mock_oper_data("goldstone-transponder", mock_data_transponder) + mock_data_gearbox = { + "gearboxes": { + "gearbox": [ + { + "name": "1", + "state": { + "name": "1", + }, + "connections": { + "connection": [ + { + "client-interface": "Ethernet1/0/1", + "line-interface": "Ethernet1/1/1", + }, + { + "client-interface": "Ethernet1/0/2", + "line-interface": "Ethernet1/1/2", + }, + { + "client-interface": "Ethernet1/0/3", + "line-interface": "Ethernet1/1/3", + }, + { + "client-interface": "Ethernet1/0/4", + "line-interface": "Ethernet1/1/4", + }, + ] + }, + } + ] + } + } + self.set_mock_oper_data("goldstone-gearbox", mock_data_gearbox) + + def test(): + time.sleep(self.WAIT_MOCK) # wait for the mock server and cache updating + data = self.cache_updater._cache.get("openconfig-terminal-device") + expected = { + "terminal-device": { + "logical-channels": { + "channel": [ + # Client signal for client-port1 + { + "index": 0, + "state": { + "index": 0, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_100GE", + "logical-channel-type": "openconfig-transport-types:PROT_ETHERNET", + }, + "ingress": { + "state": { + "transceiver": "transceiver-client-port1", + }, + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 1, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Lower order ODU for client-port1 + { + "index": 1, + "state": { + "index": 1, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_ODU4", + "logical-channel-type": "openconfig-transport-types:PROT_OTN", + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 8, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Client signal for client-port2 + { + "index": 2, + "state": { + "index": 2, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_100GE", + "logical-channel-type": "openconfig-transport-types:PROT_ETHERNET", + }, + "ingress": { + "state": { + "transceiver": "transceiver-client-port2", + }, + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 3, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Lower order ODU for client-port2 + { + "index": 3, + "state": { + "index": 3, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_ODU4", + "logical-channel-type": "openconfig-transport-types:PROT_OTN", + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 8, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Client signal for client-port3 + { + "index": 4, + "state": { + "index": 4, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_100GE", + "logical-channel-type": "openconfig-transport-types:PROT_ETHERNET", + }, + "ingress": { + "state": { + "transceiver": "transceiver-client-port3", + }, + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 5, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Lower order ODU for client-port3 + { + "index": 5, + "state": { + "index": 5, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_ODU4", + "logical-channel-type": "openconfig-transport-types:PROT_OTN", + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 8, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Client signal for client-port4 + { + "index": 6, + "state": { + "index": 6, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_100GE", + "logical-channel-type": "openconfig-transport-types:PROT_ETHERNET", + }, + "ingress": { + "state": { + "transceiver": "transceiver-client-port4", + }, + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 7, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Lower order ODU for client-port4 + { + "index": 7, + "state": { + "index": 7, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_100G", + "trib-protocol": "openconfig-transport-types:PROT_ODU4", + "logical-channel-type": "openconfig-transport-types:PROT_OTN", + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 8, + "mapping": "openconfig-transport-types:GMP", + "allocation": 100.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # Higher order ODU for och-transceiver-line-piu1-1 + { + "index": 8, + "state": { + "index": 8, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_400G", + "trib-protocol": "openconfig-transport-types:PROT_ODUCN", + "logical-channel-type": "openconfig-transport-types:PROT_OTN", + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "LOGICAL_CHANNEL", + "logical-channel": 9, + "mapping": "openconfig-transport-types:GMP", + "allocation": 400.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + # OTU for och-transceiver-line-piu1-1 + { + "index": 9, + "state": { + "index": 9, + "description": "", + "admin-state": "ENABLED", + "rate-class": "openconfig-transport-types:TRIB_RATE_400G", + "trib-protocol": "openconfig-transport-types:PROT_OTUCN", + "logical-channel-type": "openconfig-transport-types:PROT_OTN", + }, + "otn": { + "state": { + "tributary-slot-granularity": "openconfig-transport-types:TRIB_SLOT_5G", + "pre-fec-ber": { + "instant": "0.000618058722466230", + "interval": 1000000000, + }, + } + }, + "logical-channel-assignments": { + "assignment": [ + { + "index": 0, + "state": { + "index": 0, + "assignment-type": "OPTICAL_CHANNEL", + "optical-channel": "och-transceiver-line-piu1-1", + "mapping": "openconfig-transport-types:GMP", + "allocation": 400.000, + "tributary-slot-index": 0, + }, + } + ] + }, + }, + ] + }, + "operational-modes": { + "mode": [ + { + "mode-id": 100, + "state": { + "mode-id": 100, + "description": "100G, DP-QPSK, SC-FEC, OTU4-LR, 28.0GHz", + "vendor-id": "example vendor", + }, + }, + { + "mode-id": 101, + "state": { + "mode-id": 101, + "description": "100G, DP-QPSK, oFEC, FlexO-LR, 31.6GHz", + "vendor-id": "example vendor", + }, + }, + { + "mode-id": 200, + "state": { + "mode-id": 200, + "description": "200G, DP-16QAM, oFEC, FlexO-LR, 31.6GHz", + "vendor-id": "example vendor", + }, + }, + { + "mode-id": 201, + "state": { + "mode-id": 201, + "description": "200G, DP-QPSK, oFEC, FlexO-LR, 63.1GHz", + "vendor-id": "example vendor", + }, + }, + { + "mode-id": 300, + "state": { + "mode-id": 300, + "description": "300G, DP-8QAM, oFEC, FlexO-LR, 63.1GHz", + "vendor-id": "example vendor", + }, + }, + { + "mode-id": 400, + "state": { + "mode-id": 400, + "description": "400G, DP-16QAM, oFEC, FlexO-LR, 63.1GHz", + "vendor-id": "example vendor", + }, + }, + ] + }, + } + } + self.assertEqual(data, expected) + + await self.run_xlate_test(test) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/xlate/openconfig/tests/test_interface.py b/src/xlate/openconfig/tests/test_interface.py index 31ff5210..0d0b6062 100644 --- a/src/xlate/openconfig/tests/test_interface.py +++ b/src/xlate/openconfig/tests/test_interface.py @@ -1,4 +1,4 @@ -"""Tests of OpenConfig translater for openconfig-interfaces.""" +"""Tests of OpenConfig translator for openconfig-interfaces.""" import unittest @@ -399,7 +399,7 @@ def tearDown(self): def test_set_interface_not_configured(self): # Target interface has not been configured. - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/config/enabled" value = True change = Change(sysrepo.ChangeCreated(xpath, value)) @@ -440,7 +440,7 @@ def test_set_interface_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/config/enabled" value = True change = Change(sysrepo.ChangeCreated(xpath, value)) @@ -483,7 +483,7 @@ def test_set_item_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/config/enabled" value = True change = Change(sysrepo.ChangeCreated(xpath, value)) @@ -516,7 +516,7 @@ def test_set_item_configured(self): def test_delete_interface_not_configured(self): # Target interface has not been configured. - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/config/enabled" change = Change(sysrepo.ChangeDeleted(xpath)) user = { @@ -553,7 +553,7 @@ def test_delete_interface_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/config/enabled" change = Change(sysrepo.ChangeDeleted(xpath)) user = { @@ -592,7 +592,7 @@ def test_delete_item_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/config/enabled" change = Change(sysrepo.ChangeDeleted(xpath)) user = { @@ -641,7 +641,7 @@ def tearDown(self): def test_set_interface_not_configured(self): # Target interface has not been configured. - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/ethernet/config/fec-mode" value = "FEC_FC" change = Change(sysrepo.ChangeCreated(xpath, value)) @@ -682,7 +682,7 @@ def test_set_interface_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/ethernet/config/fec-mode" value = "FEC_FC" change = Change(sysrepo.ChangeCreated(xpath, value)) @@ -725,7 +725,7 @@ def test_set_item_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/ethernet/config/fec-mode" value = "FEC_FC" change = Change(sysrepo.ChangeCreated(xpath, value)) @@ -758,7 +758,7 @@ def test_set_item_configured(self): def test_delete_interface_not_configured(self): # Target interface has not been configured. - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/ethernet/config/fec-mode" change = Change(sysrepo.ChangeDeleted(xpath)) user = { @@ -795,7 +795,7 @@ def test_delete_interface_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/ethernet/config/fec-mode" change = Change(sysrepo.ChangeDeleted(xpath)) user = { @@ -834,7 +834,7 @@ def test_delete_item_configured(self): ) self.conn.apply() - server = InterfaceServer(self.conn) + server = InterfaceServer(self.conn, None) xpath = "/openconfig-interfaces:interfaces/interface[name='Ethernet1/0/1']/ethernet/config/fec-mode" change = Change(sysrepo.ChangeDeleted(xpath)) user = { diff --git a/src/xlate/openconfig/tests/test_platform.py b/src/xlate/openconfig/tests/test_platform.py index f0ad59dd..13dd4f8f 100644 --- a/src/xlate/openconfig/tests/test_platform.py +++ b/src/xlate/openconfig/tests/test_platform.py @@ -1,4 +1,4 @@ -"""Tests of OpenConfig translater for openconfig-platform.""" +"""Tests of OpenConfig translator for openconfig-platform.""" import unittest @@ -2853,7 +2853,7 @@ def tearDown(self): # Test for terminal line port. def test_set_terminal_line_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='line-piu1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -2899,7 +2899,7 @@ def test_set_terminal_line_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='line-piu1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -2950,7 +2950,7 @@ def test_set_terminal_line_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='line-piu1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -2988,7 +2988,7 @@ def test_set_terminal_line_item_configured(self): def test_delete_terminal_line_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='line-piu1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3033,7 +3033,7 @@ def test_delete_terminal_line_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='line-piu1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3083,7 +3083,7 @@ def test_delete_terminal_line_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='line-piu1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3199,7 +3199,7 @@ def join_mock_servers(self): def test_set_terminal_client_interface_not_configured(self): # Target interface has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='client-port1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3258,7 +3258,7 @@ def test_set_terminal_client_interface_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='client-port1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3326,7 +3326,7 @@ def test_set_terminal_client_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='client-port1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3376,7 +3376,7 @@ def test_set_terminal_client_item_configured(self): def test_delete_terminal_client_interface_not_configured(self): # Target interface has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='client-port1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3429,7 +3429,7 @@ def test_delete_terminal_client_interface_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='client-port1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3490,7 +3490,7 @@ def test_delete_terminal_client_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='client-port1']/port/" "openconfig-transport-line-common:optical-port/config/admin-state" @@ -3553,7 +3553,7 @@ def tearDown(self): def test_set_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -3610,7 +3610,7 @@ def test_set_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -3673,7 +3673,7 @@ def test_set_netif_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -3742,7 +3742,7 @@ def test_set_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -3796,7 +3796,7 @@ def test_set_item_configured(self): def test_delete_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -3843,7 +3843,7 @@ def test_delete_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -3896,7 +3896,7 @@ def test_delete_netif_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -3955,7 +3955,7 @@ def test_delete_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/frequency" @@ -4018,7 +4018,7 @@ def tearDown(self): def test_set_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4075,7 +4075,7 @@ def test_set_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4138,7 +4138,7 @@ def test_set_netif_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4207,7 +4207,7 @@ def test_set_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4260,7 +4260,7 @@ def test_set_item_configured(self): def test_delete_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4307,7 +4307,7 @@ def test_delete_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4360,7 +4360,7 @@ def test_delete_netif_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4419,7 +4419,7 @@ def test_delete_item_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/target-output-power" @@ -4482,7 +4482,7 @@ def tearDown(self): def test_set_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" @@ -4561,7 +4561,7 @@ def test_set_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" @@ -4646,7 +4646,7 @@ def test_set_netif_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" @@ -4752,7 +4752,7 @@ def test_set_items_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" @@ -4843,7 +4843,7 @@ def test_set_items_configured(self): def test_delete_module_not_configured(self): # Target module has not been configured. - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" @@ -4898,7 +4898,7 @@ def test_delete_module_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" @@ -4959,7 +4959,7 @@ def test_delete_netif_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" @@ -5041,7 +5041,7 @@ def test_delete_items_configured(self): ) self.conn.apply() - server = PlatformServer(self.conn, operational_modes) + server = PlatformServer(self.conn, None, operational_modes) xpath = ( "/openconfig-platform:components/component[name='och-transceiver-line-piu1-1']/" "openconfig-terminal-device:optical-channel/config/operational-mode" diff --git a/src/xlate/openconfig/tests/test_terminal_device.py b/src/xlate/openconfig/tests/test_terminal_device.py index cced98b1..298a98f5 100644 --- a/src/xlate/openconfig/tests/test_terminal_device.py +++ b/src/xlate/openconfig/tests/test_terminal_device.py @@ -1,4 +1,4 @@ -"""Tests of OpenConfig translater for openconfig-terminal-device.""" +"""Tests of OpenConfig translator for openconfig-terminal-device.""" import unittest @@ -3120,7 +3120,6 @@ def test_create_4x100gbe_client_400g_line_flexo_no_transponder(self): }, }, ] - self.maxDiff = None self.assertEqual(data, expected) def test_create_twice(self):