aboutsummaryrefslogtreecommitdiffstats
path: root/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'core/loader')
-rw-r--r--core/loader/__init__.py20
-rwxr-xr-xcore/loader/loader.py153
-rw-r--r--core/loader/loader_servant.py180
3 files changed, 353 insertions, 0 deletions
diff --git a/core/loader/__init__.py b/core/loader/__init__.py
new file mode 100644
index 00000000..023f30a6
--- /dev/null
+++ b/core/loader/__init__.py
@@ -0,0 +1,20 @@
+# 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.
+
+"""Loader package
+
+This packet is responsible for loading classes & creating instances
+of requested objects. This component directly depends upon conf.
+"""
+from .loader import Loader
diff --git a/core/loader/loader.py b/core/loader/loader.py
new file mode 100755
index 00000000..57787751
--- /dev/null
+++ b/core/loader/loader.py
@@ -0,0 +1,153 @@
+# 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.
+
+"""Loader module definition.
+"""
+
+from conf import settings
+from core.loader.loader_servant import LoaderServant
+from tools.pkt_gen.trafficgen import ITrafficGenerator
+from tools.collectors.collector import ICollector
+from vswitches.vswitch import IVSwitch
+
+class Loader(object):
+ """Loader class - main object context holder.
+ """
+ _trafficgen_loader = None
+ _metrics_loader = None
+ _vswitch_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._trafficgen_loader = LoaderServant(
+ settings.getValue('TRAFFICGEN_DIR'),
+ settings.getValue('TRAFFICGEN'),
+ ITrafficGenerator)
+
+ self._metrics_loader = LoaderServant(
+ settings.getValue('COLLECTOR_DIR'),
+ settings.getValue('COLLECTOR'),
+ ICollector)
+
+ self._vswitch_loader = LoaderServant(
+ settings.getValue('VSWITCH_DIR'),
+ settings.getValue('VSWITCH'),
+ IVSwitch)
+
+ def get_trafficgen(self):
+ """Returns a new instance configured traffic generator.
+
+ :return: ITrafficGenerator implementation if available, None otherwise.
+ """
+ return self._trafficgen_loader.get_class()()
+
+ def get_trafficgen_class(self):
+ """Returns type of currently configured traffic generator.
+
+ :return: Type of ITrafficGenerator implementation if available.
+ None otherwise.
+ """
+ return self._trafficgen_loader.get_class()
+
+ def get_trafficgens(self):
+ """Returns dictionary of all available traffic generators.
+
+ :return: Dictionary of traffic generators.
+ - key: name of the class which implements ITrafficGenerator,
+ - value: Type of traffic generator which implements
+ ITrafficGenerator.
+ """
+ return self._trafficgen_loader.get_classes()
+
+ def get_trafficgens_printable(self):
+ """Returns all available traffic generators in printable format.
+
+ :return: String containing printable list of traffic generators.
+ """
+ return self._trafficgen_loader.get_classes_printable()
+
+ def get_collector(self):
+ """Returns instance of currently configured collector implementation.
+
+ :return: ICollector implementation if available, None otherwise.
+ """
+ return self._metrics_loader.get_class()()
+
+ def get_collector_class(self):
+ """Returns type of currently configured collector implementation.
+
+ :return: Type of ICollector implementation if available.
+ None otherwise.
+ """
+ return self._metrics_loader.get_class()
+
+ def get_collectors(self):
+ """Returns dictionary of all available collectors.
+
+ :return: Dictionary of collectors.
+ - key: name of the class which implements ICollector,
+ - value: Type of traffic generator which implements ICollector.
+ """
+ return self._metrics_loader.get_classes()
+
+ def get_collectors_printable(self):
+ """Returns all available collectors in printable format.
+
+ :return: String containing printable list of collectors.
+ """
+ return self._metrics_loader.get_classes_printable()
+
+ def get_vswitch(self):
+ """Returns instance of currently configured vswitch implementation.
+
+ :return: IVSwitch implementation if available, None otherwise.
+ """
+ return self._vswitch_loader.get_class()()
+
+ def get_vswitch_class(self):
+ """Returns type of currently configured vswitch implementation.
+
+ :return: Type of IVSwitch implementation if available.
+ None otherwise.
+ """
+ return self._vswitch_loader.get_class()
+
+ def get_vswitches(self):
+ """Returns dictionary of all available vswitches.
+
+ :return: Dictionary of vswitches.
+ - key: name of the class which implements IVSwitch,
+ - value: Type of traffic generator which implements IVSwitch.
+ """
+ return self._vswitch_loader.get_classes()
+
+ def get_vswitches_printable(self):
+ """Returns all available vswitches in printable format.
+
+ :return: String containing printable list of vswitches.
+ """
+ return self._vswitch_loader.get_classes_printable()
+
+ def get_vnf_class(self):
+ """Returns a new instance of the configured VNF
+
+ Currently always returns None
+ """
+ #TODO: Load the VNF class
+ return None
diff --git a/core/loader/loader_servant.py b/core/loader/loader_servant.py
new file mode 100644
index 00000000..7966532c
--- /dev/null
+++ b/core/loader/loader_servant.py
@@ -0,0 +1,180 @@
+# 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.
+
+"""Loader servant module used by Loader.
+
+Module is inteded to be private to serve only Loader itself, nevertheless
+some methods are exposed outside and can be used by any other clients:
+- load_modules(self, path, interface)
+- load_module(self, path, interface, class_name)
+Those method are stateless static members.
+
+"""
+import os
+from os import sys
+import imp
+import fnmatch
+import logging
+
+
+class LoaderServant(object):
+ """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 = []
+
+ for (name, mod) in list(out.items()):
+ desc = (mod.__doc__ or 'No description').strip().split('\n')[0]
+ results.append((name, desc))
+
+ output = [
+ 'Classes derived from: ' + self._interface.__name__ + '\n======\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: " + 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 system metric loggers defined in the module
+ gens = dict((k, v) for (k, v) in list(mod.__dict__.items())
+ if type(v) == type and
+ issubclass(v, interface) and k != 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]
+
+ 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 ' + filename)
+ raise
+
+ mods.append((modname, mod))
+
+ return mods