def find_resource_managers(names=None, admin_required=None): """Returns resource managers. :param names: List of names in format <service> or <service>.<resource> that is used for filtering resource manager classes :param admin_required: None -> returns all ResourceManagers True -> returns only admin ResourceManagers False -> returns only non admin ResourceManagers """ names = set(names or []) resource_managers = [] for manager in discover.itersubclasses(base.ResourceManager): if admin_required is not None: if admin_required != manager._admin_required: continue if (manager._service in names or "%s.%s" % (manager._service, manager._resource) in names): resource_managers.append(manager) resource_managers.sort(key=lambda x: x._order) found_names = set() for mgr in resource_managers: found_names.add(mgr._service) found_names.add("%s.%s" % (mgr._service, mgr._resource)) missing = names - found_names if missing: LOG.warning("Missing resource managers: %s" % ", ".join(missing)) return resource_managers
def get_all(cls, namespace=None, allow_hidden=False, name=None): """Return all subclass plugins of plugin. All plugins that are not configured will be ignored. :param namespace: return only plugins from specified namespace. :param name: return only plugins with specified name. :param allow_hidden: if False return only non hidden plugins """ plugins = [] for p in discover.itersubclasses(cls): if not issubclass(p, Plugin): continue if not p._meta_is_inited(raise_exc=False): continue if name and name != p.get_name(): continue if namespace and namespace != p.get_namespace(): continue if not allow_hidden and p.is_hidden(): continue plugins.append(p) return plugins
def cleanup(spec, names=None, superclass=plugin.Plugin, owner_id=None): """Generic cleaner. This method goes through all plugins. Filter those and left only plugins with _service from services or _resource from resources. :param spec: a spec for Docker client :param names: Use only resource managers that have names in this list. :param superclass: The plugin superclass to perform cleanup for. E.g., this could be ``rally.task.scenario.Scenario`` to cleanup all Scenario resources. :param owner_id: The UUID of an owner of resource. If it was created at workload level, it should be workload UUID. If it was created at subtask level, it should be subtask UUID. """ resource_classes = [ cls for cls in discover.itersubclasses(superclass) if issubclass(cls, rutils.RandomNameGeneratorMixin) ] if not resource_classes and issubclass(superclass, rutils.RandomNameGeneratorMixin): resource_classes.append(superclass) docker = service.Docker(spec) for manager in find_resource_managers(names): LOG.debug("Cleaning up docker %s objects" % manager._name) SeekAndDestroy(manager, docker, resource_classes=resource_classes, owner_id=owner_id).exterminate()
def test_all_scenarios_have_docstrings(self): ignored_params = ["self", "scenario_obj"] for scenario_group in discover.itersubclasses(scenario.Scenario): if scenario_group.__module__.startswith("tests."): continue for method in dir(scenario_group): if scenario.Scenario.is_scenario(scenario_group, method): scenario_inst = getattr(scenario_group, method) scenario_name = scenario_group.__name__ + "." + method self.assertIsNotNone(scenario_inst.__doc__, "%s doensn't have a docstring." % scenario_name) doc = utils.parse_docstring(scenario_inst.__doc__) short_description = doc["short_description"] self.assertIsNotNone(short_description, "Docstring for %s should have " "at least a one-line description." % scenario_name) self.assertFalse(short_description.startswith("Test"), "One-line description for %s " "should be declarative and not start " "with 'Test(s) ...'" % scenario_name) params_count = scenario_inst.__code__.co_argcount params = scenario_inst.__code__.co_varnames[:params_count] documented_params = [p["name"] for p in doc["params"]] for param in params: if param not in ignored_params: self.assertIn(param, documented_params, "Docstring for %(scenario)s should " "describe the '%(param)s' parameter " "in the :param <name>: clause." % {"scenario": scenario_name, "param": param})
def test_res_manager_special_field(self): for res_mgr in discover.itersubclasses(base.ResourceManager): manager_name = "%s.%s" % (res_mgr.__module__, res_mgr.__name__) fields = filter(lambda x: not x.startswith("__"), dir(res_mgr)) available_opts = set( [ "_admin_required", "_perform_for_admin_only", "_tenant_resource", "_service", "_resource", "_order", "_max_attempts", "_timeout", "_interval", "_threads", "_manager", "id", "is_deleted", "delete", "list", "supports_extension", ] ) extra_opts = set(fields) - available_opts self.assertFalse( extra_opts, ("ResourceManager %(name)s contains extra fields: %(opts)s." " Remove them to pass this test") % {"name": manager_name, "opts": ", ".join(extra_opts)}, )
def cleanup(names=None, admin_required=None, admin=None, users=None, api_versions=None, superclass=plugin.Plugin, task_id=None): """Generic cleaner. This method goes through all plugins. Filter those and left only plugins with _service from services or _resource from resources. Then goes through all passed users and using cleaners cleans all related resources. :param names: Use only resource managers that have names in this list. There are in as _service or (%s.%s % (_service, _resource)) from :param admin_required: If None -> return all plugins If True -> return only admin plugins If False -> return only non admin plugins :param admin: rally.deployment.credential.Credential that corresponds to OpenStack admin. :param users: List of OpenStack users that was used during testing. Every user has next structure: { "id": <uuid1>, "tenant_id": <uuid2>, "credential": <rally.deployment.credential.Credential> } :param superclass: The plugin superclass to perform cleanup for. E.g., this could be ``rally.task.scenario.Scenario`` to cleanup all Scenario resources. :param task_id: The UUID of task """ if api_versions: LOG.warning("'api_version' argument of 'cleanup' method is deprecated" " since rally-openstack 1.3.0 . API information should be" " included into credentials object, you can directly" " remove passed api_versions argument.") resource_classes = [ cls for cls in discover.itersubclasses(superclass) if issubclass(cls, rutils.RandomNameGeneratorMixin) ] if not resource_classes and issubclass(superclass, rutils.RandomNameGeneratorMixin): resource_classes.append(superclass) for manager in find_resource_managers(names, admin_required): LOG.debug("Cleaning up %(service)s %(resource)s objects" % { "service": manager._service, "resource": manager._resource }) SeekAndDestroy(manager, admin, users, api_versions=api_versions, resource_classes=resource_classes, task_id=task_id).exterminate()
def list(self): managers_classes = discover.itersubclasses(ResourceManager) resources = [] for cls in managers_classes: manager = cls(self.clients) if manager.is_available(): resources.extend(manager.get_resources()) return sorted(self._deduplicate(resources))
def list(self): managers_classes = discover.itersubclasses(ResourceManager) resources = [] for cls in managers_classes: manager = cls(self.clients) if manager.is_available(): resources.extend(manager.get_resources()) return resources
def list(self): managers_classes = discover.itersubclasses(ResourceManager) resources = [] for cls in managers_classes: manager = cls(self.clients) if manager.is_available(): resources.extend(manager.get_resources()) return sorted(self._deduplicate(resources), key=(lambda x: str(type(x)) + repr(x)))
def list(self): # NOTE(stpierre): any plugin can create a nova network via the # network wrapper, and that network's name will be created # according to its owner's random name generation # parameters. so we need to check if there are nova networks # whose name pattern matches those of any loaded plugin that # implements RandomNameGeneratorMixin classes = list(discover.itersubclasses(utils.RandomNameGeneratorMixin)) return [net for net in self._manager().list() if utils.name_matches_object(net.label, *classes)]
def validate(self, context, config, plugin_cls, plugin_cfg): res_mgrs = discover.itersubclasses(resources.ResourceManager) names = set([r._name for r in res_mgrs]) missing = set(plugin_cfg) missing -= names missing = ", ".join(missing) if missing: return self.fail("Couldn't find cleanup resource managers: %s" % missing)
def test_itersubclasses_with_type(self): class A(type): pass class B(A): pass class C(B): pass self.assertEqual([B, C], list(discover.itersubclasses(A)))
def _get_descriptions(self, base_cls, subclass_filter=None): descriptions = [] subclasses = discover.itersubclasses(base_cls) if subclass_filter: subclasses = filter(subclass_filter, subclasses) for entity in subclasses: name = entity.get_name() doc = utils.parse_docstring(entity.__doc__) description = doc["short_description"] or "" descriptions.append((name, description)) descriptions.sort(key=lambda d: d[0]) return descriptions
def find_exception(response): """Discover a proper exception class based on response object.""" global _exception_map if _exception_map is None: _exception_map = dict( (e.error_code, e) for e in discover.itersubclasses(RallyException)) exc_class = _exception_map.get(response.status_code, RallyException) error_data = response.json()["error"] if error_data["args"]: return exc_class(error_data["args"]) return exc_class(error_data["msg"])
def test_itersubclasses_with_multiple_inheritance(self): class A(object): pass class B(A): pass class C(A): pass class D(B, C): pass self.assertEqual([B, D, C], list(discover.itersubclasses(A)))
def test_itersubclasses(self): class A(object): pass class B(A): pass class C(A): pass class D(C): pass self.assertEqual([B, C, D], list(discover.itersubclasses(A)))
def get_all(cls, namespace=None): """Return all subclass plugins of plugin. All plugins that are not configured will be ignored. :param namespace: return only plugins from specified namespace. """ plugins = [] for p in discover.itersubclasses(cls): if issubclass(p, Plugin) and p._meta_is_inited(raise_exc=False): if not namespace or namespace == p.get_namespace(): plugins.append(getattr(p, "func_ref", p)) return plugins
def list_benchmark_scenarios(scenario_cls): """List all scenarios in the benchmark scenario class & its subclasses. Returns the method names in format <Class name>.<Method name>, which is used in the test config. :param scenario_cls: the base class for searching scenarios in :returns: List of strings """ scenario_classes = (list(discover.itersubclasses(scenario_cls)) + [scenario_cls]) benchmark_scenarios = [[ "%s.%s" % (scenario.__name__, func) for func in dir(scenario) if Scenario.is_scenario(scenario, func) ] for scenario in scenario_classes] benchmark_scenarios_flattened = list( itertools.chain.from_iterable(benchmark_scenarios)) return benchmark_scenarios_flattened
def get_scenario_by_name(name): """Return benchmark scenario method by name. :param name: name of the benchmark scenario being searched for (either a full name (e.g, 'NovaServers.boot_server') or just a method name (e.g., 'boot_server') :returns: function object """ if "." in name: scenario_group, scenario_name = name.split(".", 1) scenario_cls = Scenario.get_by_name(scenario_group) if Scenario.is_scenario(scenario_cls, scenario_name): return getattr(scenario_cls, scenario_name) else: for scenario_cls in discover.itersubclasses(Scenario): if Scenario.is_scenario(scenario_cls, name): return getattr(scenario_cls, name) raise exceptions.NoSuchScenario(name=name)
def cleanup(names=None, admin_required=None, admin=None, users=None, api_versions=None, superclass=plugin.Plugin, task_id=None): """Generic cleaner. This method goes through all plugins. Filter those and left only plugins with _service from services or _resource from resources. Then goes through all passed users and using cleaners cleans all related resources. :param names: Use only resource managers that have names in this list. There are in as _service or (%s.%s % (_service, _resource)) from :param admin_required: If None -> return all plugins If True -> return only admin plugins If False -> return only non admin plugins :param admin: rally.deployment.credential.Credential that corresponds to OpenStack admin. :param users: List of OpenStack users that was used during testing. Every user has next structure: { "id": <uuid1>, "tenant_id": <uuid2>, "credential": <rally.deployment.credential.Credential> } :param superclass: The plugin superclass to perform cleanup for. E.g., this could be ``rally.task.scenario.Scenario`` to cleanup all Scenario resources. :param task_id: The UUID of task """ resource_classes = [cls for cls in discover.itersubclasses(superclass) if issubclass(cls, rutils.RandomNameGeneratorMixin)] if not resource_classes and issubclass(superclass, rutils.RandomNameGeneratorMixin): resource_classes.append(superclass) for manager in find_resource_managers(names, admin_required): LOG.debug("Cleaning up %(service)s %(resource)s objects" % {"service": manager._service, "resource": manager._resource}) SeekAndDestroy(manager, admin, users, api_versions=api_versions, resource_classes=resource_classes, task_id=task_id).exterminate()
def list_resource_names(admin_required=None): """List all resource managers names. Returns all service names and all combination of service.resource names. :param admin_required: None -> returns all ResourceManagers True -> returns only admin ResourceManagers False -> returns only non admin ResourceManagers """ res_mgrs = discover.itersubclasses(base.ResourceManager) if admin_required is not None: res_mgrs = filter(lambda cls: cls._admin_required == admin_required, res_mgrs) names = set() for cls in res_mgrs: names.add(cls._service) names.add("%s.%s" % (cls._service, cls._resource)) return names
def _get_all_plugins_bases(self): """Return grouped and sorted all plugins bases.""" bases = [] bases_names = [] for p in discover.itersubclasses(plugin.Plugin): base_ref = getattr(p, "base_ref", None) if base_ref == p: name = self._parse_class_name(p) if name in bases_names: raise Exception("Two base classes with same name '%s' are " "detected." % name) bases_names.append(name) category_of_base = "Common" for cname, cbases in CATEGORIES.items(): if name in cbases: category_of_base = cname bases.append((category_of_base, name, p)) return sorted(bases)
def list_benchmark_scenarios(scenario_cls): """List all scenarios in the benchmark scenario class & its subclasses. Returns the method names in format <Class name>.<Method name>, which is used in the test config. :param scenario_cls: the base class for searching scenarios in :returns: List of strings """ scenario_classes = (list(discover.itersubclasses(scenario_cls)) + [scenario_cls]) benchmark_scenarios = [ ["%s.%s" % (scenario.__name__, func) for func in dir(scenario) if Scenario.is_scenario(scenario, func)] for scenario in scenario_classes ] benchmark_scenarios_flattened = list( itertools.chain.from_iterable(benchmark_scenarios)) return benchmark_scenarios_flattened
def test_res_manager_special_field(self): for res_mgr in discover.itersubclasses(base.ResourceManager): manager_name = "%s.%s" % (res_mgr.__module__, res_mgr.__name__) fields = filter(lambda x: not x.startswith("__"), dir(res_mgr)) available_opts = set([ "_admin_required", "_perform_for_admin_only", "_tenant_resource", "_service", "_resource", "_order", "_max_attempts", "_timeout", "_interval", "_threads", "_manager", "id", "is_deleted", "delete", "list", "supports_extension" ]) extra_opts = set(fields) - available_opts self.assertFalse( extra_opts, ("ResourceManager %(name)s contains extra fields: %(opts)s." " Remove them to pass this test") % {"name": manager_name, "opts": ", ".join(extra_opts)})
def discover_impl(self): """Discover implementation for service One Service can have different implementations(not only in terms of versioning, for example Network service of OpenStack has Nova-network and Neutron implementation. they are quite different). Each of such implementations can support several versions. This method is designed to choose the proper helper class based on available services in the cloud and based on expected version. Returns a tuple with implementation class as first element, a set of all implementations as a second element """ # find all classes with unified implementation impls = { cls: cls._meta_get("impl") for cls in discover.itersubclasses(self.__class__) if (cls._meta_is_inited(raise_exc=False) and cls._meta_get("impl")) } service_names = {o._meta_get("name") for o in impls.values()} enabled_services = None # let's make additional calls to cloud only when we need to make a # decision based on available services if len(service_names) > 1: enabled_services = list(self._clients.services().values()) for cls, impl in impls.items(): if (enabled_services is not None and impl._meta_get("name") not in enabled_services): continue if cls.is_applicable(self._clients): return cls, impls return None, impls
def get_all(cls, platform=None, allow_hidden=False, name=None): """Return all subclass plugins of plugin. All plugins that are not configured will be ignored. :param platform: return only plugins for specific platform. :param name: return only plugins with specified name. :param allow_hidden: if False return only non hidden plugins """ plugins = [] for p in discover.itersubclasses(cls): if not issubclass(p, Plugin): continue if not p._meta_is_inited(raise_exc=False): continue if name and name != p.get_name(): continue if platform and platform != p.get_platform(): continue if not allow_hidden and p.is_hidden(): continue plugins.append(p) return plugins
def find_resource_managers(names=None): """Returns resource managers. :param names: List of names that is used for filtering resource manager classes """ names = set(names or []) resource_managers = [] for manager in discover.itersubclasses(resources.ResourceManager): if manager._name in names: resource_managers.append(manager) resource_managers.sort(key=lambda x: x._order) found_names = set() for mgr in resource_managers: found_names.add(mgr._name) missing = names - found_names if missing: LOG.warning("Missing resource managers: %s" % ", ".join(missing)) return resource_managers
def test_all_scenarios_have_docstrings(self): ignored_params = ["self", "scenario_obj"] for scenario_group in discover.itersubclasses(base.Scenario): if scenario_group.__module__.startswith("tests."): continue for method in dir(scenario_group): if base.Scenario.is_scenario(scenario_group, method): scenario = getattr(scenario_group, method) scenario_name = scenario_group.__name__ + "." + method self.assertIsNotNone( scenario.__doc__, "%s doensn't have a docstring." % scenario_name) doc = utils.parse_docstring(scenario.__doc__) short_description = doc["short_description"] self.assertIsNotNone( short_description, "Docstring for %s should have " "at least a one-line description." % scenario_name) self.assertFalse( short_description.startswith("Test"), "One-line description for %s " "should be declarative and not start " "with 'Test(s) ...'" % scenario_name) params_count = scenario.__code__.co_argcount params = scenario.__code__.co_varnames[:params_count] documented_params = [p["name"] for p in doc["params"]] for param in params: if param not in ignored_params: self.assertIn( param, documented_params, "Docstring for %(scenario)s should " "describe the '%(param)s' parameter " "in the :param <name>: clause." % { "scenario": scenario_name, "param": param })
def get_by_name(name): """Returns Scenario class by name.""" for scenario in discover.itersubclasses(Scenario): if name == scenario.__name__: return scenario raise exceptions.NoSuchScenario(name=name)
def test_all_scenario_groups_have_docstrings(self): for scenario_group in discover.itersubclasses(scenario.Scenario): self._assert_class_has_docstrings(scenario_group, long_description=False)
def test_all_SLA_have_docstrings(self): for s in discover.itersubclasses(sla.SLA): self._assert_class_has_docstrings(s, long_description=False)
def test_all_scenario_groups_have_docstrings(self): for scenario_group in discover.itersubclasses(base.Scenario): self._assert_class_has_docstrings(scenario_group, long_description=False)