From e030b9f84f7cf560b75e6711e204b915764889c9 Mon Sep 17 00:00:00 2001 From: Anders Ingemann Date: Sun, 5 Jun 2016 11:41:18 +0200 Subject: [PATCH] Fix bug with task list generation Only tasks from the loaded provider and plugins were considered, when creating the task graph. This was a problem with the prebootstrapped plugin specifically, which could be used with both ec2 and vbox. Fixed the problem by loading all known plugins and providers and adding them to the taskgraph, nothing less will do. --- bootstrapvz/base/tasklist.py | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/bootstrapvz/base/tasklist.py b/bootstrapvz/base/tasklist.py index 5b7c404..13811ae 100644 --- a/bootstrapvz/base/tasklist.py +++ b/bootstrapvz/base/tasklist.py @@ -23,9 +23,10 @@ class TaskList(object): """ # Get a hold of every task we can find, so that we can topologically sort # all tasks, rather than just the subset we are going to run. - from bootstrapvz.common import tasks as common_tasks - modules = [common_tasks, info.manifest.modules['provider']] + info.manifest.modules['plugins'] - all_tasks = set(get_all_tasks(modules)) + # We pass in the modules which the manifest has already loaded in order + # to support third-party plugins, which are not in the bootstrapvz package + # and therefore wouldn't be discovered. + all_tasks = set(get_all_tasks([info.manifest.modules['provider']] + info.manifest.modules['plugins'])) # Create a list for us to run task_list = create_list(self.tasks, all_tasks) # Output the tasklist @@ -118,18 +119,39 @@ def create_list(taskset, all_tasks): return sorted_tasks -def get_all_tasks(modules): +def get_all_tasks(loaded_modules): """Gets a list of all task classes in the package :return: A list of all tasks in the package :rtype: list """ + import pkgutil import os.path - # Get generators that return all classes in a module - generators = [] - for module in modules: + import bootstrapvz + bootstrapvz_root = os.path.dirname(bootstrapvz.__file__) + module_paths = set([(os.path.join(bootstrapvz_root, 'common/tasks'), 'bootstrapvz.common.tasks.')]) + + for module in loaded_modules: module_path = os.path.dirname(module.__file__) module_prefix = module.__name__ + '.' + module_paths.add((module_path, module_prefix)) + + providers = os.path.join(os.path.dirname(bootstrapvz.__file__), 'providers') + for module_loader, module_name, ispkg in pkgutil.iter_modules([providers, 'bootstrapvz.providers']): + module_path = os.path.join(module_loader.path, module_name) + # The prefix param seems to do nothing, so we prefix the module name ourselves + module_prefix = 'bootstrapvz.providers.{}.'.format(module_name) + module_paths.add((module_path, module_prefix)) + + plugins = os.path.join(os.path.dirname(bootstrapvz.__file__), 'plugins') + for module_loader, module_name, ispkg in pkgutil.iter_modules([plugins, 'bootstrapvz.plugins']): + module_path = os.path.join(module_loader.path, module_name) + module_prefix = 'bootstrapvz.plugins.{}.'.format(module_name) + module_paths.add((module_path, module_prefix)) + + # Get generators that return all classes in a module + generators = [] + for (module_path, module_prefix) in module_paths: generators.append(get_all_classes(module_path, module_prefix)) import itertools classes = itertools.chain(*generators)