From d5a010aa2e40cafabf012b096f508b144f9d3d8b Mon Sep 17 00:00:00 2001 From: opensource-tnbt Date: Wed, 29 Jul 2020 17:56:51 +0530 Subject: SDV: First commit. Moving contents from parent cirv to cirv-sdv Remove pycache Signed-off-by: Sridhar K. N. Rao Change-Id: I3744157eb6616591159abe3eca133160d803dda3 --- sdv/core/__init__.py | 19 ++++ sdv/core/component_factory.py | 32 +++++++ sdv/core/loader/__init__.py | 18 ++++ sdv/core/loader/loader.py | 129 +++++++++++++++++++++++++++ sdv/core/loader/loader_servant.py | 183 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 381 insertions(+) create mode 100644 sdv/core/__init__.py create mode 100644 sdv/core/component_factory.py create mode 100644 sdv/core/loader/__init__.py create mode 100644 sdv/core/loader/loader.py create mode 100644 sdv/core/loader/loader_servant.py (limited to 'sdv/core') diff --git a/sdv/core/__init__.py b/sdv/core/__init__.py new file mode 100644 index 0000000..2441d38 --- /dev/null +++ b/sdv/core/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2015 Intel Corporation. +# +# 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. + +"""Core structural interfaces and their implementations +""" + +# flake8: noqa +import core.component_factory diff --git a/sdv/core/component_factory.py b/sdv/core/component_factory.py new file mode 100644 index 0000000..396aa28 --- /dev/null +++ b/sdv/core/component_factory.py @@ -0,0 +1,32 @@ +# Copyright 2020 Spirent Communications. +# +# 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. + +""" +Create Components. +""" + + +def create_swprevalidator(swprevalidator_class): + """ Create Pre-Validators""" + return swprevalidator_class() + + +def create_swpostvalidator(swpostvalidator_class): + """ Create Post-Validators""" + return swpostvalidator_class() + + +def create_linkvalidator(linkprevalidator_class): + """ Create Link-Validators""" + return linkprevalidator_class() diff --git a/sdv/core/loader/__init__.py b/sdv/core/loader/__init__.py new file mode 100644 index 0000000..e86c48e --- /dev/null +++ b/sdv/core/loader/__init__.py @@ -0,0 +1,18 @@ +# 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. + +""" +Core: Loader Component. +""" + +# flake8: noqa +from .loader import Loader diff --git a/sdv/core/loader/loader.py b/sdv/core/loader/loader.py new file mode 100644 index 0000000..c9f8e96 --- /dev/null +++ b/sdv/core/loader/loader.py @@ -0,0 +1,129 @@ +# Copyright 2020 Intel Corporation, Spirent Communications. +# +# 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. + +""" +Abstract class for Software Prevalidations. +Implementors, please inherit from this class. +""" + +from conf import settings +from core.loader.loader_servant import LoaderServant +from SoftwarePreValid.swprevalidator import ISwPreValidator +from SoftwarePostValid.swpostvalidator import ISwPostValidator +from NwLinksValid.nwlinksvalidator import INwLinksValidator + + +# pylint: disable=too-many-public-methods +class Loader(): + """Loader class - main object context holder. + """ + _swvalidator_loader = None + + def __init__(self): + """Loader ctor - initialization method. + + All data is read from configuration each time Loader instance is + created. It is up to creator to maintain object life cycle if this + behavior is unwanted. + """ + self._swprevalidator_loader = LoaderServant( + settings.getValue('SW_PRE_VALID_DIR'), + settings.getValue('SW_PRE_VALIDATOR'), + ISwPreValidator) + self._swpostvalidator_loader = LoaderServant( + settings.getValue('SW_POST_VALID_DIR'), + settings.getValue('SW_POST_VALIDATOR'), + ISwPostValidator) + self._nwlinksvalidator_loader = LoaderServant( + settings.getValue('NW_LINKS_VALID_DIR'), + settings.getValue('NW_LINKS_VALIDATOR'), + INwLinksValidator) + + def get_swprevalidator(self): + """ Returns a new instance configured Software Validator + :return: ISwPreValidator implementation if available, None otherwise + """ + return self._swprevalidator_loader.get_class()() + + def get_swprevalidator_class(self): + """Returns type of currently configured Software Validator. + + :return: Type of ISwPreValidator implementation if available. + None otherwise. + """ + return self._swprevalidator_loader.get_class() + + def get_swprevalidators(self): + """ + Get Prevalidators + """ + return self._swprevalidator_loader.get_classes() + + def get_swprevalidators_printable(self): + """ + Get Prevalidators for printing + """ + return self._swprevalidator_loader.get_classes_printable() + + def get_swpostvalidator(self): + """ Returns a new instance configured Software Validator + :return: ISwPostValidator implementation if available, None otherwise + """ + return self._swpostvalidator_loader.get_class()() + + def get_swpostvalidator_class(self): + """Returns type of currently configured Software Validator. + + :return: Type of ISwPostValidator implementation if available. + None otherwise. + """ + return self._swpostvalidator_loader.get_class() + + def get_swpostvalidators(self): + """ + Get Postvalidators + """ + return self._swpostvalidator_loader.get_classes() + + def get_swpostvalidators_printable(self): + """ + Get Postvalidators for printing + """ + return self._swpostvalidator_loader.get_classes_printable() + + def get_nwlinksvalidator(self): + """ Returns a new instance configured Nw-Links Validator + :return: INwLinksValidator implementation if available, None otherwise + """ + return self._nwlinksvalidator_loader.get_class()() + + def get_nwlinksvalidator_class(self): + """Returns type of currently configured Nw-Links Validator. + + :return: Type of NwLinksValidator implementation if available. + None otherwise. + """ + return self._nwlinksvalidator_loader.get_class() + + def get_nwlinkvalidators(self): + """ + Get Linkvalidators + """ + return self._nwlinksvalidator_loader.get_classes() + + def get_nwlinkvalidators_printable(self): + """ + Get Linkvalidators for printing + """ + return self._nwlinksvalidator_loader.get_classes_printable() diff --git a/sdv/core/loader/loader_servant.py b/sdv/core/loader/loader_servant.py new file mode 100644 index 0000000..4e55c67 --- /dev/null +++ b/sdv/core/loader/loader_servant.py @@ -0,0 +1,183 @@ +# Copyright 2020 Intel Corporation, Spirent Communications. +# +# 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. + +""" +Loader Support Module. +""" + +import os +from os import sys +import imp +import fnmatch +import logging +from conf import settings + + +class LoaderServant(): + """Class implements basic dynamic import operations. + """ + _class_name = None + _path = None + _interface = None + + def __init__(self, path, class_name, interface): + """LoaderServant constructor + + Intializes all data needed for import operations. + + Attributes: + path: path to directory which contains implementations derived from + interface. + class_name: Class name which will be returned in get_class + method, if such definition exists in directory + represented by path, + interface: interface type. Every object which doesn't + implement this particular interface will be + filtered out. + """ + self._class_name = class_name + self._path = path + self._interface = interface + + def get_class(self): + """Returns class type based on parameters passed in __init__. + + :return: Type of the found class. + None if class hasn't been found + """ + + return self.load_module(path=self._path, + interface=self._interface, + class_name=self._class_name) + + def get_classes(self): + """Returns all classes in path derived from interface + + :return: Dictionary with following data: + - key: String representing class name, + - value: Class type. + """ + return self.load_modules(path=self._path, + interface=self._interface) + + def get_classes_printable(self): + """Returns all classes derived from _interface found in path + + :return: String - list of classes in printable format. + """ + + out = self.load_modules(path=self._path, + interface=self._interface) + results = [] + + # sort modules to produce the same output everytime + for (name, mod) in sorted(out.items()): + desc = (mod.__doc__ or 'No description').strip().split('\n')[0] + results.append((name, desc)) + + header = 'Classes derived from: ' + self._interface.__name__ + output = [header + '\n' + '=' * len(header) + '\n'] + + for (name, desc) in results: + output.append('* %-18s%s' % ('%s:' % name, desc)) + + output.append('') + + output.append('') + + return '\n'.join(output) + + @staticmethod + def load_module(path, interface, class_name): + """Imports everything from given path and returns class type + + This is based on following conditions: + - Class is derived from interface, + - Class type name matches class_name. + + :return: Type of the found class. + None if class hasn't been found + """ + + results = LoaderServant.load_modules( + path=path, interface=interface) + + if class_name in results: + logging.info( + "Class found: %s.", class_name) + return results.get(class_name) + + return None + + @staticmethod + def load_modules(path, interface): + """Returns dictionary of class name/class type found in path + + This is based on following conditions: + - classes found under path are derived from interface. + - class is not interface itself. + + :return: Dictionary with following data: + - key: String representing class name, + - value: Class type. + """ + result = {} + + for _, mod in LoaderServant._load_all_modules(path): + # find all classes derived from given interface, but suppress + # interface itself and any abstract class starting with iface name + gens = dict((k, v) for (k, v) in list(mod.__dict__.items()) + if isinstance(v, type) and + issubclass(v, interface) and + not k.startswith(interface.__name__)) + if gens: + for (genname, gen) in list(gens.items()): + result[genname] = gen + return result + + @staticmethod + def _load_all_modules(path): + """Load all modules from ``path`` directory. + + This is based on the design used by OFTest: + https://github.com/floodlight/oftest/blob/master/oft + + :param path: Path to a folder of modules. + + :return: List of modules in a folder. + """ + mods = [] + + for root, _, filenames in os.walk(path): + # Iterate over each python file + for filename in fnmatch.filter(filenames, '[!.]*.py'): + modname = os.path.splitext(os.path.basename(filename))[0] + + # skip module load if it is excluded by configuration + if modname in settings.getValue('EXCLUDE_MODULES'): + continue + + try: + if modname in sys.modules: + mod = sys.modules[modname] + else: + mod = imp.load_module( + modname, *imp.find_module(modname, [root])) + except ImportError: + logging.error('Could not import file %s', filename) + raise + + mods.append((modname, mod)) + + return mods -- cgit 1.2.3-korg