def obj_from_id(resource_config, resources, typename): """Return the resource whose name matches the id. resource_config has to contain `id`, as it is used to lookup a resource. :param resource_config: resource to be transformed :param resources: iterable containing all resources :param typename: name which describes the type of resource :returns: resource object mapped to `id` """ if "id" in resource_config: matching = [ resource for resource in resources if resource.id == resource_config["id"] ] if len(matching) == 1: return matching[0] elif len(matching) > 1: raise exceptions.MultipleMatchesFound( needle="{typename} with id '{id}'".format( typename=typename.title(), id=resource_config["id"]), haystack=matching) else: raise exceptions.InvalidScenarioArgument( "{typename} with id '{id}' not found".format( typename=typename.title(), id=resource_config["id"])) else: raise exceptions.InvalidScenarioArgument( "{typename} 'id' not found in '{resource_config}'".format( typename=typename.title(), resource_config=resource_config))
def obj_from_name(resource_config, resources, typename): """Return the resource whose name matches the pattern. resource_config has to contain `name`, as it is used to lookup a resource. Value of the name will be treated as regexp. An `InvalidScenarioArgument` is thrown if the pattern does not match unambiguously. :param resource_config: resource to be transformed :param resources: iterable containing all resources :param typename: name which describes the type of resource :returns: resource object uniquely mapped to `name` or `regex` """ if "name" in resource_config: # In a case of pattern string exactly matches resource name matching_exact = [ resource for resource in resources if resource.name == resource_config["name"] ] if len(matching_exact) == 1: return matching_exact[0] elif len(matching_exact) > 1: raise exceptions.InvalidScenarioArgument( "{typename} with name '{pattern}' " "is ambiguous, possible matches " "by id: {ids}".format(typename=typename.title(), pattern=resource_config["name"], ids=", ".join( map(operator.attrgetter("id"), matching_exact)))) # Else look up as regex patternstr = resource_config["name"] elif "regex" in resource_config: patternstr = resource_config["regex"] else: raise exceptions.InvalidScenarioArgument( "{typename} 'id', 'name', or 'regex' not found " "in '{resource_config}' ".format(typename=typename.title(), resource_config=resource_config)) pattern = re.compile(patternstr) matching = [ resource for resource in resources if re.search(pattern, resource.name) ] if not matching: raise exceptions.InvalidScenarioArgument( "{typename} with pattern '{pattern}' not found".format( typename=typename.title(), pattern=pattern.pattern)) elif len(matching) > 1: raise exceptions.InvalidScenarioArgument( "{typename} with name '{pattern}' is ambiguous, possible matches " "by id: {ids}".format(typename=typename.title(), pattern=pattern.pattern, ids=", ".join( map(operator.attrgetter("id"), matching)))) return matching[0]
def _validate_helper(validators, clients, config, task): for validator in validators: try: result = validator(config, clients=clients, task=task) except Exception as e: raise exceptions.InvalidScenarioArgument(e) else: if not result.is_valid: raise exceptions.InvalidScenarioArgument(result.msg)
def _validate_helper(validators, clients, config, deployment): for validator in validators: try: result = validator(config, clients=clients, deployment=deployment) except Exception as e: LOG.exception(e) raise exceptions.InvalidScenarioArgument(e) else: if not result.is_valid: raise exceptions.InvalidScenarioArgument(result.msg)
def pre_process(self, resource_spec, config): path = os.path.expanduser(resource_spec) if os.path.isfile(path): return path try: head = requests.head(path) if head.status_code == 200: return path raise exceptions.InvalidScenarioArgument( "Url %s unavailable (code %s)" % (path, head.status_code)) except Exception as ex: raise exceptions.InvalidScenarioArgument( "Url error %s (%s)" % (path, ex))
def test_validator_image_not_in_context(self, mock_glance_image_transform): config = { "args": { "image": "fake_image" }, "context": { "images": { "fake_image_name": "foo" } } } clients = self.credentials["openstack"]["users"][ 0].get.return_value.clients.return_value clients.glance().images.get = mock.Mock() result = self.validator.validate(config, self.credentials, None, None) self.assertIsNone(result) mock_glance_image_transform.assert_called_once_with( clients=clients, resource_config=config["args"]["image"]) clients.glance().images.get.assert_called_with("image_id") exs = [exceptions.InvalidScenarioArgument(), glance_exc.HTTPNotFound()] for ex in exs: clients.glance().images.get.side_effect = ex result = self.validator.validate(config, credentials, None, None) self.assertEqual("Image 'fake_image' not found", result.msg)
def test__validate_config_semanitc_helper_invalid_arg(self, mock_validate): mock_validate.side_effect = exceptions.InvalidScenarioArgument() eng = engine.BenchmarkEngine(mock.MagicMock(), mock.MagicMock()) self.assertRaises(exceptions.InvalidBenchmarkConfig, eng._validate_config_semantic_helper, "a", "u", "n", "p", mock.MagicMock(), {})
def test_validator_image_not_in_context(self, mock_glance_image_transform): config = { "args": { "image": "fake_image" }, "contexts": { "images": { "fake_image_name": "foo" } } } clients = self.context["users"][0]["credential"].clients.return_value clients.glance().images.get = mock.Mock() result = self.validator.validate(self.context, config, None, None) self.assertIsNone(result) mock_glance_image_transform.assert_called_once_with( clients=clients, resource_config=config["args"]["image"]) clients.glance().images.get.assert_called_with("image_id") exs = [exceptions.InvalidScenarioArgument(), glance_exc.HTTPNotFound()] for ex in exs: clients.glance().images.get.side_effect = ex e = self.assertRaises(validators.validation.ValidationError, self.validator.validate, self.context, config, None, None) self.assertEqual("Image 'fake_image' not found", e.message)
def test__get_validated_image_exceptions(self, mock_glance_image): mock_glance_image.return_value.pre_process.return_value = "image_id" clients = mock.Mock() clients.glance().images.get.side_effect = glance_exc.HTTPNotFound("") e = self.assertRaises( validators.validation.ValidationError, self.validator._get_validated_image, config, clients, "image") self.assertEqual("Image '%s' not found" % config["args"]["image"], e.message) mock_glance_image.assert_called_once_with( context={"admin": {"credential": clients.credential}}) mock_glance_image.return_value.pre_process.assert_called_once_with( config["args"]["image"], config={}) clients.glance().images.get.assert_called_with("image_id") mock_glance_image.return_value.pre_process.reset_mock() clients.side_effect = exceptions.InvalidScenarioArgument("") e = self.assertRaises( validators.validation.ValidationError, self.validator._get_validated_image, config, clients, "image") self.assertEqual("Image '%s' not found" % config["args"]["image"], e.message) mock_glance_image.return_value.pre_process.assert_called_once_with( config["args"]["image"], config={}) clients.glance().images.get.assert_called_with("image_id")
def test__get_validated_flavor(self, mock_flavor): mock_flavor.return_value.pre_process.return_value = "flavor_id" clients = mock.Mock() clients.nova().flavors.get.return_value = "flavor" result = self.validator._get_validated_flavor(self.config, clients, "flavor") self.assertEqual("flavor", result) mock_flavor.assert_called_once_with( context={"admin": {"credential": clients.credential}} ) mock_flavor_obj = mock_flavor.return_value mock_flavor_obj.pre_process.assert_called_once_with( self.config["args"]["flavor"], config={}) clients.nova().flavors.get.assert_called_once_with(flavor="flavor_id") mock_flavor_obj.pre_process.reset_mock() clients.side_effect = exceptions.InvalidScenarioArgument("") result = self.validator._get_validated_flavor( self.config, clients, "flavor") self.assertEqual("flavor", result) mock_flavor_obj.pre_process.assert_called_once_with( self.config["args"]["flavor"], config={}) clients.nova().flavors.get.assert_called_with(flavor="flavor_id")
def test__get_validated_image_exceptions(self, mock_glance_image_transform): clients = mock.Mock() clients.glance().images.get.return_value = "image" clients.glance().images.get.side_effect = glance_exc.HTTPNotFound("") result = self.validator._get_validated_image(config, clients, "image") self.assertIsInstance(result[0], validators.ValidationResult) self.assertFalse(result[0].is_valid) self.assertEqual(result[0].msg, "Image '%s' not found" % config["args"]["image"]) self.assertIsNone(result[1]) mock_glance_image_transform.assert_called_once_with( clients=clients, resource_config=config["args"]["image"]) clients.glance().images.get.assert_called_with("image_id") clients.side_effect = exceptions.InvalidScenarioArgument("") result = self.validator._get_validated_image(config, clients, "image") self.assertIsInstance(result[0], validators.ValidationResult) self.assertFalse(result[0].is_valid) self.assertEqual(result[0].msg, "Image '%s' not found" % config["args"]["image"]) self.assertIsNone(result[1]) mock_glance_image_transform.assert_called_with( clients=clients, resource_config=config["args"]["image"]) clients.glance().images.get.assert_called_with("image_id")
def _get_flavor_from_context(self, config, flavor_value): if "flavors" not in config.get("context", {}): raise exceptions.InvalidScenarioArgument("No flavors context") flavors = [flavors_ctx.FlavorConfig(**f) for f in config["context"]["flavors"]] resource = types.obj_from_name(resource_config=flavor_value, resources=flavors, typename="flavor") flavor = flavors_ctx.FlavorConfig(**resource) flavor.id = "<context flavor: %s>" % flavor.name return (ValidationResult(True), flavor)
def validate_semantic(cls, config, admin, users, task): """Check if the image service is available.""" try: glance = users[0].glance() list(glance.images.list(limit=0)) except Exception as e: message = _( "The image service is unavailable, Reason: %(reason)s") % { "reason": six.text_type(e) } raise exceptions.InvalidScenarioArgument(message=message)
def _id_from_name(resource_config, resources, typename): """Return the id of the resource whose name matches the pattern. When resource_config contains `name`, an exact match is used. When resource_config contains `regex`, a pattern match is used. An `InvalidScenarioArgument` is thrown if the pattern does not match unambiguously. :param resource_config: resource to be transformed :param resources: iterable containing all resources :param typename: name which describes the type of resource :returns: resource id uniquely mapped to `name` or `regex` """ if resource_config.get('name'): patternstr = "^{0}$".format(resource_config.get('name')) elif resource_config.get('regex'): patternstr = resource_config.get('regex') else: raise exceptions.InvalidScenarioArgument( "{typename} 'id', 'name', or 'regex' not found " "in '{resource_config}' ".format(typename=typename.title(), resource_config=resource_config)) pattern = re.compile(patternstr) matching = filter(lambda resource: re.search(pattern, resource.name), resources) if not matching: raise exceptions.InvalidScenarioArgument( "{typename} with pattern '{pattern}' not found".format( typename=typename.title(), pattern=pattern.pattern)) elif len(matching) > 1: raise exceptions.InvalidScenarioArgument( "{typename} with name '{pattern}' is ambiguous, possible matches " "by id: {ids}".format(typename=typename.title(), pattern=pattern.pattern, ids=", ".join( map(operator.attrgetter("id"), matching)))) return matching[0].id
def transform(cls, clients, resource_config): """Check whether file exists or url available. :param clients: openstack admin client handles :param resource_config: path or url :returns: url or expanded file path """ path = os.path.expanduser(resource_config) if os.path.isfile(path): return path try: head = requests.head(path) if head.status_code == 200: return path raise exceptions.InvalidScenarioArgument( "Url %s unavailable (code %s)" % (path, head.status_code)) except Exception as ex: raise exceptions.InvalidScenarioArgument("Url error %s (%s)" % (path, ex))
def pre_process(self, resource_spec, config): resource_id = resource_spec.get("id") if resource_id: return resource_id else: neutronclient = self._clients.neutron() for net in neutronclient.list_networks()["networks"]: if net["name"] == resource_spec.get("name"): return net["id"] raise exceptions.InvalidScenarioArgument( "Neutron network with name '{name}' not found".format( name=resource_spec.get("name")))
def transform(cls, clients, resource_config): """Transform the resource config to id. :param clients: openstack admin client handles :param resource_config: scenario config with `id`, `name` or `regex` :returns: id matching resource """ resource_id = resource_config.get("id") if resource_id: return resource_id else: neutronclient = clients.neutron() for net in neutronclient.list_networks()["networks"]: if net["name"] == resource_config.get("name"): return net["id"] raise exceptions.InvalidScenarioArgument( "Neutron network with name '{name}' not found".format( name=resource_config.get("name")))
def test__get_validated_flavor(self, mock_flavor_transform): clients = mock.Mock() clients.nova().flavors.get.return_value = "flavor" result = self.validator._get_validated_flavor(self.config, clients, "flavor") self.assertEqual("flavor", result) mock_flavor_transform.assert_called_once_with( clients=clients, resource_config=self.config["args"]["flavor"]) clients.nova().flavors.get.assert_called_once_with(flavor="flavor_id") clients.side_effect = exceptions.InvalidScenarioArgument("") result = self.validator._get_validated_flavor(self.config, clients, "flavor") self.assertEqual("flavor", result) mock_flavor_transform.assert_called_with( clients=clients, resource_config=self.config["args"]["flavor"]) clients.nova().flavors.get.assert_called_with(flavor="flavor_id")
def test__get_validated_image_exceptions(self, mock_glance_image_transform): clients = mock.Mock() clients.glance().images.get.return_value = "image" clients.glance().images.get.side_effect = glance_exc.HTTPNotFound("") e = self.assertRaises(validators.validation.ValidationError, self.validator._get_validated_image, config, clients, "image") self.assertEqual("Image '%s' not found" % config["args"]["image"], e.message) mock_glance_image_transform.assert_called_once_with( clients=clients, resource_config=config["args"]["image"]) clients.glance().images.get.assert_called_with("image_id") clients.side_effect = exceptions.InvalidScenarioArgument("") e = self.assertRaises(validators.validation.ValidationError, self.validator._get_validated_image, config, clients, "image") self.assertEqual("Image '%s' not found" % config["args"]["image"], e.message) mock_glance_image_transform.assert_called_with( clients=clients, resource_config=config["args"]["image"]) clients.glance().images.get.assert_called_with("image_id")
def _find_resource(self, resource_spec, resources): """Return the resource whose name matches the pattern. .. note:: This method is a modified version of `rally.task.types.obj_from_name`. The difference is supporting the case of returning the latest version of resource in case of `accurate=False` option. :param resource_spec: resource specification to find. Expected keys: * name - The exact name of resource to search. If no exact match and value of *accurate* key is False (default behaviour), name will be interpreted as a regexp * regexp - a regexp of resource name to match. If several resources match and value of *accurate* key is False (default behaviour), the latest resource will be returned. :param resources: iterable containing all resources :raises InvalidScenarioArgument: if the pattern does not match anything. :returns: resource object mapped to `name` or `regex` """ if "name" in resource_spec: # In a case of pattern string exactly matches resource name matching_exact = [ resource for resource in resources if resource.name == resource_spec["name"] ] if len(matching_exact) == 1: return matching_exact[0] elif len(matching_exact) > 1: raise exceptions.InvalidScenarioArgument( "%(typename)s with name '%(pattern)s' " "is ambiguous, possible matches " "by id: %(ids)s" % { "typename": self.get_name().title(), "pattern": resource_spec["name"], "ids": ", ".join( map(operator.attrgetter("id"), matching_exact)) }) if resource_spec.get("accurate", False): raise exceptions.InvalidScenarioArgument( "%(typename)s with name '%(name)s' not found" % { "typename": self.get_name().title(), "name": resource_spec["name"] }) # Else look up as regex patternstr = resource_spec["name"] elif "regex" in resource_spec: patternstr = resource_spec["regex"] else: raise exceptions.InvalidScenarioArgument( "%(typename)s 'id', 'name', or 'regex' not found " "in '%(resource_spec)s' " % { "typename": self.get_name().title(), "resource_spec": resource_spec }) pattern = re.compile(patternstr) matching = [ resource for resource in resources if re.search(pattern, resource.name or "") ] if not matching: raise exceptions.InvalidScenarioArgument( "%(typename)s with pattern '%(pattern)s' not found" % { "typename": self.get_name().title(), "pattern": pattern.pattern }) elif len(matching) > 1: if not resource_spec.get("accurate", False): return sorted(matching, key=lambda o: o.name or "")[-1] raise exceptions.InvalidScenarioArgument( "%(typename)s with name '%(pattern)s' is ambiguous, possible " "matches by id: %(ids)s" % { "typename": self.get_name().title(), "pattern": pattern.pattern, "ids": ", ".join(map(operator.attrgetter("id"), matching)) }) return matching[0]
def _validate_helper(validators, clients, args, task): for validator in validators: result = validator(clients=clients, task=task, **args) if not result.is_valid: raise exceptions.InvalidScenarioArgument(message=result.msg)