From b1f99066bd8ff787c126ed26ab71fa67b30f15d5 Mon Sep 17 00:00:00 2001 From: Juro Bystricky Date: Mon, 6 Feb 2017 09:49:37 -0800 Subject: testimage: Implement custom target loading This patch implements custom target loading for testimage, currently missing due to major changes to the test framework. Custom targets can be defined in various meta-layers, so we need an extra path information in order to find them. Any other additional info is retrieved as usual via the variables TEST_TARGET and TEST_SUITES (From OE-Core rev: 1dc8010afd71fe46fb28bb86fb7c07a5fbd3d7cf) Signed-off-by: Juro Bystricky Signed-off-by: Richard Purdie --- meta/classes/testimage.bbclass | 2 +- meta/lib/oeqa/runtime/context.py | 74 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass index c6e4cec426..366c6f5d7b 100644 --- a/meta/classes/testimage.bbclass +++ b/meta/classes/testimage.bbclass @@ -238,7 +238,7 @@ def testimage_main(d): # the robot dance target = OERuntimeTestContextExecutor.getTarget( - d.getVar("TEST_TARGET"), None, d.getVar("TEST_TARGET_IP"), + d.getVar("TEST_TARGET"), d.getVar("BBPATH"), None, d.getVar("TEST_TARGET_IP"), d.getVar("TEST_SERVER_IP"), **target_kwargs) # test context diff --git a/meta/lib/oeqa/runtime/context.py b/meta/lib/oeqa/runtime/context.py index e5e0141c2a..ea1b4a643e 100644 --- a/meta/lib/oeqa/runtime/context.py +++ b/meta/lib/oeqa/runtime/context.py @@ -89,7 +89,7 @@ class OERuntimeTestContextExecutor(OETestContextExecutor): help="Qemu boot configuration, only needed when target_type is QEMU.") @staticmethod - def getTarget(target_type, logger, target_ip, server_ip, **kwargs): + def getTarget(target_type, target_modules_path, logger, target_ip, server_ip, **kwargs): target = None if target_type == 'simpleremote': @@ -97,11 +97,79 @@ class OERuntimeTestContextExecutor(OETestContextExecutor): elif target_type == 'qemu': target = OEQemuTarget(logger, target_ip, server_ip, **kwargs) else: - # TODO: Implement custom target module loading - raise TypeError("target_type %s isn't supported" % target_type) + # Custom target module loading + try: + controller = OERuntimeTestContextExecutor.getControllerModule(target_type, target_modules_path) + target = controller(logger, target_ip, server_ip, **kwargs) + except ImportError as e: + raise TypeError("Failed to import %s from available controller modules" % target_type) return target + # Search oeqa.controllers module directory for and return a controller + # corresponding to the given target name. + # AttributeError raised if not found. + # ImportError raised if a provided module can not be imported. + @staticmethod + def getControllerModule(target, target_modules_path): + controllerslist = OERuntimeTestContextExecutor._getControllerModulenames(target_modules_path) + controller = OERuntimeTestContextExecutor._loadControllerFromName(target, controllerslist) + return controller + + # Return a list of all python modules in lib/oeqa/controllers for each + # layer in bbpath + @staticmethod + def _getControllerModulenames(target_modules_path): + + controllerslist = [] + + def add_controller_list(path): + if not os.path.exists(os.path.join(path, '__init__.py')): + raise OSError('Controllers directory %s exists but is missing __init__.py' % path) + files = sorted([f for f in os.listdir(path) if f.endswith('.py') and not f.startswith('_')]) + for f in files: + module = 'oeqa.controllers.' + f[:-3] + if module not in controllerslist: + controllerslist.append(module) + else: + raise RuntimeError("Duplicate controller module found for %s. Layers should create unique controller module names" % module) + + extpath = target_modules_path.split(':') + for p in extpath: + controllerpath = os.path.join(p, 'lib', 'oeqa', 'controllers') + if os.path.exists(controllerpath): + add_controller_list(controllerpath) + return controllerslist + + # Search for and return a controller from given target name and + # set of module names. + # Raise AttributeError if not found. + # Raise ImportError if a provided module can not be imported + @staticmethod + def _loadControllerFromName(target, modulenames): + for name in modulenames: + obj = OERuntimeTestContextExecutor._loadControllerFromModule(target, name) + if obj: + return obj + raise AttributeError("Unable to load {0} from available modules: {1}".format(target, str(modulenames))) + + # Search for and return a controller or None from given module name + @staticmethod + def _loadControllerFromModule(target, modulename): + obj = None + # import module, allowing it to raise import exception + try: + module = __import__(modulename, globals(), locals(), [target]) + except Exception as e: + return obj + # look for target class in the module, catching any exceptions as it + # is valid that a module may not have the target class. + try: + obj = getattr(module, target) + except: + obj = None + return obj + @staticmethod def readPackagesManifest(manifest): if not manifest or not os.path.exists(manifest): -- cgit v1.2.3-54-g00ecf