diff options
author | Bartosz Gardziejewski <bartosz.gardziejewski@nokia.com> | 2021-03-17 10:40:23 +0100 |
---|---|---|
committer | Bartosz Gardziejewski <bartosz.gardziejewski@nokia.com> | 2021-03-23 12:23:43 +0100 |
commit | 3b73097920be148bc82ce4a1c719cc42da8fc721 (patch) | |
tree | e535ef5119dfe6f9a55824560fe7a676f22f6459 /src | |
parent | 29c2b0edfb72940a8617207e3ee2aaeb9ac115ab (diff) |
Create python application for config change subscription.
Signed-off-by: Bartosz Gardziejewski <bartosz.gardziejewski@nokia.com>
Change-Id: I690a188d155bed70f799ef1c6b947c9ecb1a5f47
Issue-ID: INT-1869
Diffstat (limited to 'src')
25 files changed, 794 insertions, 0 deletions
diff --git a/src/python/README.md b/src/python/README.md new file mode 100644 index 0000000..90906c6 --- /dev/null +++ b/src/python/README.md @@ -0,0 +1,17 @@ +# Netconf Server Python Application +This application is providing core Netconf Server capabilities. +It is started in detached mode on image startup. + +Application capabilities: + - Subscribing on config change per model. + - Models to subscribe to are loaded from configuration file, + provided as application parameter. + - When configuration of one of models change + information about change are logged + + +## Testing +Tox file with pytest are used fo testing. + +## Logging +Application prints logs on to the console and to file `/logs/netconf_saver.log` diff --git a/src/python/netconf_server/__init__.py b/src/python/netconf_server/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/netconf_server/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/netconf_server/netconf_server.py b/src/python/netconf_server/netconf_server.py new file mode 100644 index 0000000..b790604 --- /dev/null +++ b/src/python/netconf_server/netconf_server.py @@ -0,0 +1,39 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import logging + +from netconf_server.sysrepo_interface.config_change_data import ConfigChangeData + +logger = logging.getLogger("netconf_saver") + + +class NetconfServer(object): + + def __init__(self, subscriptions: list): + self.subscriptions = subscriptions + + def run(self, session): + for subscription in self.subscriptions: + subscription.callback_function = self.__on_module_configuration_change + subscription.subscribe_on_model_change(session) + + @staticmethod + def __on_module_configuration_change(config_change_data: ConfigChangeData): + logger.info("Received module changed: %s , %s " % (config_change_data.event, config_change_data.changes)) diff --git a/src/python/netconf_server/netconf_server_factory.py b/src/python/netconf_server/netconf_server_factory.py new file mode 100644 index 0000000..28297ad --- /dev/null +++ b/src/python/netconf_server/netconf_server_factory.py @@ -0,0 +1,40 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import logging + +from netconf_server.netconf_server import NetconfServer +from netconf_server.sysrepo_interface.config_change_subscriber import ConfigChangeSubscriber + +logger = logging.getLogger("netconf_saver") + + +class NetconfServerFactory(object): + + def __init__(self, modules_to_subscribe_names: list): + self.modules_to_subscribe_names = modules_to_subscribe_names + + def create(self) -> NetconfServer: + subscriptions = list() + for module_name in self.modules_to_subscribe_names: + subscriptions.append( + ConfigChangeSubscriber(module_name) + ) + return NetconfServer(subscriptions) + diff --git a/src/python/netconf_server/sysrepo_configuration/__init__.py b/src/python/netconf_server/sysrepo_configuration/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/netconf_server/sysrepo_configuration/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/netconf_server/sysrepo_configuration/sysrepo_configuration.py b/src/python/netconf_server/sysrepo_configuration/sysrepo_configuration.py new file mode 100644 index 0000000..fa48098 --- /dev/null +++ b/src/python/netconf_server/sysrepo_configuration/sysrepo_configuration.py @@ -0,0 +1,24 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +class SysrepoConfiguration(object): + + def __init__(self, models_to_subscribe_to: list): + self.models_to_subscribe_to = models_to_subscribe_to diff --git a/src/python/netconf_server/sysrepo_configuration/sysrepo_configuration_loader.py b/src/python/netconf_server/sysrepo_configuration/sysrepo_configuration_loader.py new file mode 100644 index 0000000..dc7ac90 --- /dev/null +++ b/src/python/netconf_server/sysrepo_configuration/sysrepo_configuration_loader.py @@ -0,0 +1,58 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +import logging +import os +from configparser import ConfigParser + +from netconf_server.sysrepo_configuration.sysrepo_configuration import SysrepoConfiguration + +MODELS_LIST_TAG = "models" +SUBSCRIPTION_TAG = "SUBSCRIPTION" + +logger = logging.getLogger("sysrep_configuration_loader") + + +class SysrepoConfigurationLoader(object): + + # configuration_file must be in .ini format + @staticmethod + def load_configuration(configuration_file: str) -> SysrepoConfiguration: + if os.path.isfile(configuration_file): + config_object = ConfigParser() + config_object.read(configuration_file) + if SUBSCRIPTION_TAG in config_object and MODELS_LIST_TAG in config_object[SUBSCRIPTION_TAG]: + logger.info("Loading configuration from file %s" % configuration_file) + models_to_subscribe_to = config_object[SUBSCRIPTION_TAG][MODELS_LIST_TAG].split(",") + return SysrepoConfiguration(models_to_subscribe_to) + else: + logger.warning("Loading configuration failed, %s is not valid configuration file" % configuration_file) + raise ConfigLoadingException( + "Loading sysrepo configuration have failed, %s is not correct config file" % configuration_file + ) + else: + logger.warning("Loading configuration failed, %s does not exist or is not a file" % configuration_file) + raise ConfigLoadingException( + "Loading sysrepo configuration have failed, %s is not valid file" % configuration_file + ) + + +class ConfigLoadingException(Exception): + pass diff --git a/src/python/netconf_server/sysrepo_interface/__init__.py b/src/python/netconf_server/sysrepo_interface/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/netconf_server/sysrepo_interface/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/netconf_server/sysrepo_interface/config_change_data.py b/src/python/netconf_server/sysrepo_interface/config_change_data.py new file mode 100644 index 0000000..8e329b5 --- /dev/null +++ b/src/python/netconf_server/sysrepo_interface/config_change_data.py @@ -0,0 +1,28 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +class ConfigChangeData(object): + + def __init__(self, event: str, req_id: int, changes: list): + self.event = event + self.req_id = req_id + self.changes = changes + + diff --git a/src/python/netconf_server/sysrepo_interface/config_change_subscriber.py b/src/python/netconf_server/sysrepo_interface/config_change_subscriber.py new file mode 100644 index 0000000..faa8254 --- /dev/null +++ b/src/python/netconf_server/sysrepo_interface/config_change_subscriber.py @@ -0,0 +1,49 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +import logging + +from netconf_server.sysrepo_interface.config_change_data import ConfigChangeData + +logger = logging.getLogger("sysrep_config_change_subscriber") + + +class ConfigChangeSubscriber(object): + + def __init__(self, module_name: str, callback_function: callable = None): + self.module_name = module_name + if callback_function is None: + self.callback_function = self.default_callback + else: + self.callback_function = callback_function + + def subscribe_on_model_change(self, session): + logger.info("Subscribing on config change for module %s" % self.module_name) + session.subscribe_module_change( + self.module_name, None, self.on_module_have_changed, asyncio_register=True + ) + + async def on_module_have_changed(self, event: str, req_id: int, changes: list, private_data: any): + logger.debug("Module changed: %s (request ID %s)" % (event, req_id)) + self.callback_function(ConfigChangeData(event, req_id, changes)) + + @staticmethod + def default_callback(config_change_data: ConfigChangeData): + logger.info("Received module changed: %s , %s " % (config_change_data.event, config_change_data.changes)) diff --git a/src/python/netconf_server/sysrepo_interface/sysrepo_client.py b/src/python/netconf_server/sysrepo_interface/sysrepo_client.py new file mode 100644 index 0000000..fcd29e2 --- /dev/null +++ b/src/python/netconf_server/sysrepo_interface/sysrepo_client.py @@ -0,0 +1,29 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import sysrepo + + +class SysrepoClient(object): + + @staticmethod + def run_in_session(method_to_run: callable, *extra_args): + with sysrepo.SysrepoConnection() as connection: + with connection.start_session() as session: + method_to_run(session, *extra_args) diff --git a/src/python/netconf_server_application.py b/src/python/netconf_server_application.py new file mode 100644 index 0000000..e112490 --- /dev/null +++ b/src/python/netconf_server_application.py @@ -0,0 +1,55 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import asyncio +import sys +import logging + +from netconf_server.netconf_server import NetconfServer +from netconf_server.netconf_server_factory import NetconfServerFactory +from netconf_server.sysrepo_configuration.sysrepo_configuration_loader import SysrepoConfigurationLoader, \ + ConfigLoadingException +from netconf_server.sysrepo_interface.sysrepo_client import SysrepoClient + +logging.basicConfig( + handlers=[logging.StreamHandler(), logging.FileHandler("/logs/netconf_saver.log")], + level=logging.DEBUG +) +logger = logging.getLogger("netconf_saver") + + +def run_server_forever(session, server: NetconfServer): + server.run(session) + asyncio.get_event_loop().run_forever() + + +def create_configured_server() -> NetconfServer: + configuration = SysrepoConfigurationLoader.load_configuration(sys.argv[1]) + return NetconfServerFactory(configuration.models_to_subscribe_to).create() + + +if __name__ == "__main__": + if len(sys.argv) >= 2: + try: + netconf_server = create_configured_server() + SysrepoClient().run_in_session(run_server_forever, netconf_server) + except ConfigLoadingException: + logger.error("File to load configuration from file %s" % sys.argv[1]) + else: + logger.error("Missing path to file with configuration argument required to start netconf server.") diff --git a/src/python/requirements.txt b/src/python/requirements.txt new file mode 100644 index 0000000..ee6c404 --- /dev/null +++ b/src/python/requirements.txt @@ -0,0 +1,21 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +sysrepo==0.4.2 diff --git a/src/python/setup.py b/src/python/setup.py new file mode 100644 index 0000000..394143f --- /dev/null +++ b/src/python/setup.py @@ -0,0 +1,32 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import setuptools + +with open('requirements.txt') as f: + required = f.read().splitlines() + +setuptools.setup( + name="netconf-server", + version="1.0.0", + description="Application that exposes REST API for managing sysrepo", + packages=setuptools.find_packages(include=['netconf_server', 'netconf_server.*']), + classifiers=["Programming Language :: Python :: 3.6"], + install_requires=required +) diff --git a/src/python/test-requirements.txt b/src/python/test-requirements.txt new file mode 100644 index 0000000..4c3f573 --- /dev/null +++ b/src/python/test-requirements.txt @@ -0,0 +1,22 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +pytest==6.2.2 + diff --git a/src/python/tests/__init__.py b/src/python/tests/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/tests/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/tests/mocs/__init__.py b/src/python/tests/mocs/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/tests/mocs/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/tests/mocs/mocked_session.py b/src/python/tests/mocs/mocked_session.py new file mode 100644 index 0000000..d7adb1b --- /dev/null +++ b/src/python/tests/mocs/mocked_session.py @@ -0,0 +1,34 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import asyncio + + +class MockedSession(object): + + def __init__(self): + self.__callback = None + + def subscribe_module_change(self, module_name, _, on_module_have_changed, asyncio_register=True): + self.__callback = on_module_have_changed + pass + + def call_config_changed(self): + loop = asyncio.get_event_loop() + loop.run_until_complete(self.__callback('event', 'req_id', 'changes', 'private_data')) diff --git a/src/python/tests/netconf_server/__init__.py b/src/python/tests/netconf_server/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/tests/netconf_server/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/tests/netconf_server/sysrepo_configuration/__init__.py b/src/python/tests/netconf_server/sysrepo_configuration/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/tests/netconf_server/sysrepo_configuration/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/tests/netconf_server/sysrepo_configuration/test_sysrepo_configuration_loader.py b/src/python/tests/netconf_server/sysrepo_configuration/test_sysrepo_configuration_loader.py new file mode 100644 index 0000000..e5462e4 --- /dev/null +++ b/src/python/tests/netconf_server/sysrepo_configuration/test_sysrepo_configuration_loader.py @@ -0,0 +1,84 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import unittest +import os + +from netconf_server.sysrepo_configuration.sysrepo_configuration_loader import \ + SysrepoConfigurationLoader, ConfigLoadingException + +test_config_file_name = "./test-subscription-configuration.ini" +test_config_file_content = '[SUBSCRIPTION]\nmodels = test-module,test-module-2\n' + +test_wrong_config_file_name = "./test-subscription-wrong-configuration.ini" +test_wrong_config_file_content = '[SUBSCRIPTION]\n' + +test_non_existing_config_file_name = "./test-subscription-non-existing-configuration.ini" + + +class TestSysrepoConfigurationLoader(unittest.TestCase): + + def test_should_load_configuration_from_file(self): + # when + config = SysrepoConfigurationLoader.load_configuration(test_config_file_name) + + # then + self.assertEqual(config.models_to_subscribe_to, ["test-module", "test-module-2"]) + + def test_should_raise_exception_if_given_configuration_file_is_wrong(self): + # then + with self.assertRaises(ConfigLoadingException): + # when + SysrepoConfigurationLoader.load_configuration(test_wrong_config_file_name) + + def test_should_raise_exception_if_given_configuration_file_does_not_exist(self): + # then + with self.assertRaises(ConfigLoadingException): + # when + SysrepoConfigurationLoader.load_configuration(test_non_existing_config_file_name) + + @classmethod + def setUpClass(cls): + cls.__create_configuration_file() + cls.__create_wrong_configuration_file() + + @classmethod + def tearDownClass(cls): + cls.__remove_configuration_files() + cls.__remove_wrong_configuration_files() + + @staticmethod + def __create_configuration_file(): + f = open(test_config_file_name, "a") + f.write(test_config_file_content) + f.close() + + @staticmethod + def __remove_configuration_files(): + os.remove(test_config_file_name) + + @staticmethod + def __create_wrong_configuration_file(): + f = open(test_wrong_config_file_name, "a") + f.write(test_wrong_config_file_content) + f.close() + + @staticmethod + def __remove_wrong_configuration_files(): + os.remove(test_wrong_config_file_name) diff --git a/src/python/tests/netconf_server/sysrepo_interface/__init__.py b/src/python/tests/netconf_server/sysrepo_interface/__init__.py new file mode 100644 index 0000000..eeb06d5 --- /dev/null +++ b/src/python/tests/netconf_server/sysrepo_interface/__init__.py @@ -0,0 +1,19 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### diff --git a/src/python/tests/netconf_server/sysrepo_interface/test_config_change_subscriber.py b/src/python/tests/netconf_server/sysrepo_interface/test_config_change_subscriber.py new file mode 100644 index 0000000..9817ba4 --- /dev/null +++ b/src/python/tests/netconf_server/sysrepo_interface/test_config_change_subscriber.py @@ -0,0 +1,46 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import unittest +from unittest.mock import MagicMock + +from netconf_server.sysrepo_interface.config_change_data import ConfigChangeData +from netconf_server.sysrepo_interface.config_change_subscriber import ConfigChangeSubscriber +from tests.mocs.mocked_session import MockedSession + + +class TestConfigChangeSubscriber(unittest.TestCase): + + @staticmethod + def __test_callback(config_change_data: ConfigChangeData): + pass + + def test_should_create_subscriber_and_call_callback_when_session_detects_change(self): + # given + self.__test_callback = MagicMock() + subscriber = ConfigChangeSubscriber("test", self.__test_callback) + session = MockedSession() + subscriber.subscribe_on_model_change(session) + self.__test_callback.assert_not_called() + + # when + session.call_config_changed() + + # then + self.__test_callback.assert_called_once() diff --git a/src/python/tests/netconf_server/test_netconf_server.py b/src/python/tests/netconf_server/test_netconf_server.py new file mode 100644 index 0000000..6306dd9 --- /dev/null +++ b/src/python/tests/netconf_server/test_netconf_server.py @@ -0,0 +1,53 @@ +### +# ============LICENSE_START======================================================= +# Netconf Server +# ================================================================================ +# Copyright (C) 2021 Nokia. All rights reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### +import unittest +from unittest.mock import MagicMock + +from netconf_server.netconf_server_factory import NetconfServerFactory +from tests.mocs.mocked_session import MockedSession + + +class TestNetconfServer(unittest.TestCase): + + def test_should_create_and_run_netconf_server_with_one_model(self): + # given + modules_to_subscribe_names = ["test"] + server = NetconfServerFactory(modules_to_subscribe_names).create() + session = MockedSession() + session.subscribe_module_change = MagicMock() + + # when + server.run(session) + + # then + session.subscribe_module_change.assert_called_once() + + def test_should_create_and_run_netconf_server_with_multiple_models(self): + # given + modules_to_subscribe_names = ["test", "test2", "test3"] + server = NetconfServerFactory(modules_to_subscribe_names).create() + session = MockedSession() + session.subscribe_module_change = MagicMock() + + # when + server.run(session) + + # then + self.assertEqual(session.subscribe_module_change.call_count, 3) diff --git a/src/python/tox.ini b/src/python/tox.ini new file mode 100644 index 0000000..dd76991 --- /dev/null +++ b/src/python/tox.ini @@ -0,0 +1,11 @@ +[tox] +envlist = py36 +skipsdist = true + +[testenv] +commands = pytest +basepython = python3 +deps = -r test-requirements.txt + +[testenv:pytest] +commands = pytest -v |