def _validate_flavor(self, obj, name_or_id, reason=None): flavor = None msg = '' try: flavor = self.compute(obj).flavor_find(name_or_id, False) except exc.InternalError as ex: msg = six.text_type(ex) if reason is None: # reaons is 'validate' if ex.code == 404: msg = _( "The specified %(k)s '%(v)s' could not be found.") % { 'k': self.FLAVOR, 'v': name_or_id } raise exc.InvalidSpec(message=msg) else: raise if flavor is not None: if not flavor.is_disabled: return flavor msg = _("The specified %(k)s '%(v)s' is disabled") % { 'k': self.FLAVOR, 'v': name_or_id } if reason == 'create': raise exc.EResourceCreation(type='server', message=msg) elif reason == 'update': raise exc.EResourceUpdate(type='server', id=obj.physical_id, message=msg) else: raise exc.InvalidSpec(message=msg)
def validate(self, context, validate_props=False): super(LoadBalancingPolicy, self).validate(context, validate_props) if not validate_props: return True nc = self.network(context.user, context.project) # validate pool subnet name_or_id = self.pool_spec.get(self.POOL_SUBNET) try: nc.subnet_get(name_or_id) except exc.InternalError: msg = _( "The specified %(key)s '%(value)s' could not be found.") % { 'key': self.POOL_SUBNET, 'value': name_or_id } raise exc.InvalidSpec(message=msg) # validate VIP subnet name_or_id = self.vip_spec.get(self.VIP_SUBNET) try: nc.subnet_get(name_or_id) except exc.InternalError: msg = _( "The specified %(key)s '%(value)s' could not be found.") % { 'key': self.VIP_SUBNET, 'value': name_or_id } raise exc.InvalidSpec(message=msg)
def validate(self): # validate cron expression if specified if TIME_CONSTRAINTS in self.spec: tcs = self.alarm_properties[TIME_CONSTRAINTS] for tc in tcs: exp = tc.get(TC_START, '') try: croniter.croniter(exp) except Exception as ex: msg = _("Invalid cron expression specified for property " "'%(property)s' (%(exp)s): %(ex)s") % { 'property': TC_START, 'exp': exp, 'ex': six.text_type(ex) } raise exc.InvalidSpec(message=msg) tz = tc.get(TC_TIMEZONE, '') try: pytz.timezone(tz) except Exception as ex: msg = _("Invalid timezone value specified for property " "'%(property)s' (%(tz)s): %(ex)s") % { 'property': TC_TIMEZONE, 'tz': tz, 'ex': six.text_type(ex) } raise exc.InvalidSpec(message=msg)
def do_validate(self, obj): """Validate if the spec has provided valid configuration. :param obj: The node object. """ cluster = self.properties[self.HOST_CLUSTER] node = self.properties[self.HOST_NODE] if all([cluster, node]): msg = _("Either '%(c)s' or '%(n)s' must be specified, but not " "both.") % {'c': self.HOST_CLUSTER, 'n': self.HOST_NODE} raise exc.InvalidSpec(message=msg) if not any([cluster, node]): msg = _("Either '%(c)s' or '%(n)s' must be specified." ) % {'c': self.HOST_CLUSTER, 'n': self.HOST_NODE} raise exc.InvalidSpec(message=msg) if cluster: try: co.Cluster.find(self.context, cluster) except (exc.ResourceNotFound, exc.MultipleChoices): msg = _("The specified %(key)s '%(val)s' could not be found " "or is not unique." ) % {'key': self.HOST_CLUSTER, 'val': cluster} raise exc.InvalidSpec(message=msg) if node: try: no.Node.find(self.context, node) except (exc.ResourceNotFound, exc.MultipleChoices): msg = _("The specified %(key)s '%(val)s' could not be found " "or is not unique." ) % {'key': self.HOST_NODE, 'val': node} raise exc.InvalidSpec(message=msg)
def validate(self, context, validate_props=False): super(LoadBalancingPolicy, self).validate(context, validate_props) if not validate_props: return True nc = self.network(context.user_id, context.project_id) oc = self.octavia(context.user_id, context.project_id) # validate pool subnet name_or_id = self.pool_spec.get(self.POOL_SUBNET) try: nc.subnet_get(name_or_id) except exc.InternalError: msg = _("The specified %(key)s '%(value)s' could not be found." ) % {'key': self.POOL_SUBNET, 'value': name_or_id} raise exc.InvalidSpec(message=msg) # validate VIP subnet or network subnet_name_or_id = self.vip_spec.get(self.VIP_SUBNET) network_name_or_id = self.vip_spec.get(self.VIP_NETWORK) if not subnet_name_or_id and not network_name_or_id: msg = _("At least one of VIP Subnet or Network must be defined.") raise exc.InvalidSpec(message=msg) try: # Check subnet if it is set obj_type = self.VIP_SUBNET name_or_id = subnet_name_or_id if name_or_id: nc.subnet_get(name_or_id) # Check network if it is set obj_type = self.VIP_NETWORK name_or_id = network_name_or_id if name_or_id: nc.network_get(name_or_id) # TODO(rm_work): We *could* do more validation here to catch issues # at validation time, like verifying the subnet's network_id is the # same as the id of the network, if both are set -- but for now we # will just leave that up to the LB API, which means if there is a # failure, it won't be caught until attach time. except exc.InternalError: msg = _("The specified %(key)s '%(value)s' could not be found." ) % {'key': obj_type, 'value': name_or_id} raise exc.InvalidSpec(message=msg) # validate loadbalancer if self.lb: try: oc.loadbalancer_get(self.lb) except exc.InternalError: msg = _("The specified %(key)s '%(value)s' could not be found." ) % {'key': self.LOADBALANCER, 'value': self.lb} raise exc.InvalidSpec(message=msg)
def validate(self, context, validate_props=False): super(ScalingPolicy, self).validate(context, validate_props) if self.adjustment_number <= 0: msg = _("the 'number' for 'adjustment' must be > 0") raise exc.InvalidSpec(message=msg) if self.adjustment_min_step < 0: msg = _("the 'min_step' for 'adjustment' must be >= 0") raise exc.InvalidSpec(message=msg) if self.cooldown < 0: msg = _("the 'cooldown' for 'adjustment' must be >= 0") raise exc.InvalidSpec(message=msg)
def create(cls, ctx, name, spec, metadata=None): """Create a profile object and validate it. :param ctx: The requesting context. :param name: The name for the profile object. :param spec: A dict containing the detailed spec. :param metadata: An optional dictionary specifying key-value pairs to be associated with the profile. :returns: An instance of Profile. """ if metadata is None: metadata = {} try: profile = cls(name, spec, metadata=metadata, user=ctx.user_id, project=ctx.project_id) profile.validate(True) except (exc.ResourceNotFound, exc.ESchema) as ex: error = _("Failed in creating profile %(name)s: %(error)s" ) % {"name": name, "error": six.text_type(ex)} raise exc.InvalidSpec(message=error) profile.store(ctx) return profile
def test_profile_create_with_spec_validation_failed(self, mock_call, mock_parse, mock_enforce): self._mock_enforce_setup(mock_enforce, 'create', True) body = { 'profile': { 'name': 'test_profile', 'spec': { 'type': 'test_profile_type', 'version': '1.0', 'properties': {'param': 'value'}, }, 'metadata': {}, } } req = self._post('/profiles', jsonutils.dumps(body)) obj = mock.Mock() mock_parse.return_value = obj msg = 'Spec validation error (param): value' error = senlin_exc.InvalidSpec(message=msg) mock_call.side_effect = shared.to_remote_error(error) resp = shared.request_with_middleware(fault.FaultWrapper, self.controller.create, req, body=body) self.assertEqual(400, resp.json['code']) self.assertEqual('InvalidSpec', resp.json['error']['type']) mock_parse.assert_called_once_with( 'ProfileCreateRequest', mock.ANY, body, 'profile') mock_call.assert_called_once_with( req.context, 'profile_create', obj)
def test_profile_validate_invalide_spec(self, mock_call, mock_parse, mock_enforce): self._mock_enforce_setup(mock_enforce, 'validate', True) body = { 'profile': { 'spec': { 'type': 'os.nova.server', 'version': '1.0' } } } req = self._post('/profiles/validate', jsonutils.dumps(body), version='1.2') msg = 'Spec validation error' error = senlin_exc.InvalidSpec(message=msg) mock_call.side_effect = shared.to_remote_error(error) obj = mock.Mock() mock_parse.return_value = obj resp = shared.request_with_middleware(fault.FaultWrapper, self.controller.validate, req, body=body) self.assertEqual(400, resp.json['code']) self.assertEqual('InvalidSpec', resp.json['error']['type'])
def test_policy_create_failed_validation(self): self.spec['properties'] = {'KEY2': 1} self.patchobject(fakes.TestPolicy, 'validate', side_effect=exception.InvalidSpec(message='BOOM')) ex = self.assertRaises(rpc.ExpectedException, self.eng.policy_create, self.ctx, 'p-2', self.spec) self.assertEqual(exception.SenlinBadRequest, ex.exc_info[0])
def validate(self): super(ServerProfile, self).validate() if self.properties[self.TIMEOUT] > cfg.CONF.default_action_timeout: suggest = cfg.CONF.default_action_timeout err = _("Value of the 'timeout' property must be lower than the " "upper limit (%s).") % suggest raise exception.InvalidSpec(message=err)
def test_trigger_create_failed_validation(self): spec = parser.simple_parse(trigger_spec) self.patchobject(fakes.TestTrigger, 'validate', side_effect=exception.InvalidSpec(message='BOOM')) ex = self.assertRaises(rpc.ExpectedException, self.eng.trigger_create, self.ctx, 't1', spec) self.assertEqual(exception.InvalidSpec, ex.exc_info[0])
def test_profile_create_invalid_spec(self, mock_create): self._setup_fakes() mock_create.side_effect = exc.InvalidSpec(message="badbad") body = vorp.ProfileCreateRequestBody(name='foo', spec=self.spec) req = vorp.ProfileCreateRequest(profile=body) ex = self.assertRaises(rpc.ExpectedException, self.svc.profile_create, self.ctx, req.obj_to_primitive()) self.assertEqual(exc.InvalidSpec, ex.exc_info[0]) self.assertEqual("badbad", six.text_type(ex.exc_info[1]))
def test_policy_create_failed_validation(self): self._setup_fakes() mock_validate = self.patchobject(fakes.TestPolicy, 'validate') mock_validate.side_effect = exc.InvalidSpec(message='BOOM') req = orpo.PolicyCreateRequestBody(name='Fake', spec=self.spec) ex = self.assertRaises(rpc.ExpectedException, self.eng.policy_create, self.ctx, req.obj_to_primitive()) self.assertEqual(exc.InvalidSpec, ex.exc_info[0]) self.assertEqual('BOOM', six.text_type(ex.exc_info[1]))
def test_profile_create_failed_validation(self): self._setup_fakes() mock_validate = self.patchobject(fakes.TestProfile, 'validate') mock_validate.side_effect = exc.InvalidSpec(message='BOOM') ex = self.assertRaises(rpc.ExpectedException, self.eng.profile_create, self.ctx, 'p-2', self.spec) self.assertEqual(exc.BadRequest, ex.exc_info[0]) self.assertEqual('The request is malformed: BOOM', six.text_type(ex.exc_info[1]))
def test_policy_validate_failed(self): self._setup_fakes() mock_validate = self.patchobject(fakes.TestPolicy, 'validate') mock_validate.side_effect = exc.InvalidSpec(message='BOOM') body = orpo.PolicyValidateRequestBody(spec=self.spec) ex = self.assertRaises(rpc.ExpectedException, self.svc.policy_validate, self.ctx, body.obj_to_primitive()) self.assertEqual(exc.InvalidSpec, ex.exc_info[0]) self.assertEqual('BOOM', str(ex.exc_info[1]))
def validate(self, context, validate_props=False): super(HealthPolicy, self).validate(context, validate_props=validate_props) if len(self.recover_actions) > 1: message = _( "Only one '%s' is supported for now.") % self.RECOVERY_ACTIONS raise exc.ESchema(message=message) if self.interval < cfg.CONF.health_check_interval_min: message = _("Specified interval of %(interval)d seconds has to be " "larger than health_check_interval_min of " "%(min_interval)d seconds set in configuration.") % { "interval": self.interval, "min_interval": cfg.CONF.health_check_interval_min } raise exc.InvalidSpec(message=message) # check valid detection types polling_types = [ consts.NODE_STATUS_POLLING, consts.NODE_STATUS_POLL_URL ] has_valid_polling_types = all(d.type in polling_types for d in self.detection_modes) has_valid_lifecycle_type = (len(self.detection_modes) == 1 and self.detection_modes[0].type == consts.LIFECYCLE_EVENTS) if not has_valid_polling_types and not has_valid_lifecycle_type: message = ("Invalid detection modes in health policy: %s" % ', '.join([d.type for d in self.detection_modes])) raise exc.InvalidSpec(message=message) if len(self.detection_modes) != len(set(self.detection_modes)): message = ("Duplicate detection modes are not allowed in " "health policy: %s" % ', '.join([d.type for d in self.detection_modes])) raise exc.InvalidSpec(message=message)
def validate(self, validate_props=False): '''Validate the schema and the data provided.''' # general validation self.spec_data.validate() self.properties.validate() # validate template template = self.properties[self.TEMPLATE] template_url = self.properties[self.TEMPLATE_URL] if not template and not template_url: msg = _("Both template and template_url are not specified " "for profile '%s'.") % self.name raise exc.InvalidSpec(message=msg) if validate_props: self.do_validate(obj=self)
def test_policy_create_invalid_value(self): self._setup_fakes() spec = copy.deepcopy(self.spec) spec['properties']['KEY2'] = 'value3' mock_validate = self.patchobject(fakes.TestPolicy, 'validate') mock_validate.side_effect = exc.InvalidSpec( message="The specified KEY2 'value3' could not be found.") req = orpo.PolicyCreateRequestBody(name='Fake', spec=spec) ex = self.assertRaises(rpc.ExpectedException, self.svc.policy_create, self.ctx, req.obj_to_primitive()) self.assertEqual(exc.InvalidSpec, ex.exc_info[0]) self.assertEqual("The specified KEY2 'value3' could not be " "found.", str(ex.exc_info[1]))
def validate(self, context, validate_props=False): super(RegionPlacementPolicy, self).validate(context, validate_props) if not validate_props: return True kc = self.keystone(context.user_id, context.project_id) input_regions = sorted(self.regions.keys()) valid_regions = kc.validate_regions(input_regions) invalid_regions = sorted(set(input_regions) - set(valid_regions)) if invalid_regions: msg = _("The specified regions '%(value)s' could not be " "found.") % {'value': invalid_regions} raise exc.InvalidSpec(message=msg) return True
def test_create(self): exobj = None try: {}['key'] except Exception: ex = exception.InvalidSpec(message='boom') exobj = base.ExceptionPayload.from_exception(ex) sot = base.NodeActionPayload(node=self.node, action=self.action, exception=exobj) self.assertTrue(sot.obj_attr_is_set('node')) self.assertTrue(sot.obj_attr_is_set('action')) self.assertTrue(sot.obj_attr_is_set('exception')) self.assertIsNotNone(sot.exception)
def validate(self, context, validate_props=False): super(AffinityPolicy, self).validate(context, validate_props) if not validate_props: return True az_name = self.properties.get(self.AVAILABILITY_ZONE) if az_name: nc = self.nova(context.user, context.project) valid_azs = nc.validate_azs([az_name]) if not valid_azs: msg = _("The specified %(key)s '%(value)s' could not be " "found.") % {'key': self.AVAILABILITY_ZONE, 'value': az_name} raise exc.InvalidSpec(message=msg) return True
def validate(self, context, validate_props=False): super(HealthPolicy, self).validate(context, validate_props=validate_props) if len(self.recover_actions) > 1: message = _( "Only one '%s' is supported for now.") % self.RECOVERY_ACTIONS raise exc.ESchema(message=message) if self.interval < cfg.CONF.health_check_interval_min: message = _("Specified interval of %(interval)d seconds has to be " "larger than health_check_interval_min of " "%(min_interval)d seconds set in configuration.") % { "interval": self.interval, "min_interval": cfg.CONF.health_check_interval_min } raise exc.InvalidSpec(message=message)
def validate(self, context, validate_props=False): super(ZonePlacementPolicy, self).validate(context, validate_props) if not validate_props: return True nc = self.nova(context.user_id, context.project_id) input_azs = sorted(self.zones.keys()) valid_azs = nc.validate_azs(input_azs) invalid_azs = sorted(set(input_azs) - set(valid_azs)) if invalid_azs: msg = _("The specified %(key)s '%(value)s' could not be " "found.") % {'key': self.ZONE_NAME, 'value': list(invalid_azs)} raise exc.InvalidSpec(message=msg) return True
def _validate_keypair(self, obj, name_or_id, reason=None): try: return self.compute(obj).keypair_find(name_or_id, False) except exc.InternalError as ex: if reason == 'create': raise exc.EResourceCreation(type='server', message=six.text_type(ex)) elif reason == 'update': raise exc.EResourceUpdate(type='server', id=obj.physical_id, message=six.text_type(ex)) elif ex.code == 404: msg = _("The specified %(k)s '%(v)s' could not be found.") % { 'k': self.KEY_NAME, 'v': name_or_id } raise exc.InvalidSpec(message=msg) else: raise
def do_validate(self, obj): '''Validate if the spec has provided info for stack creation.''' kwargs = { 'stack_name': obj.name, 'template': self.properties[self.TEMPLATE], 'timeout_mins': self.properties[self.TIMEOUT], 'disable_rollback': self.properties[self.DISABLE_ROLLBACK], 'parameters': self.properties[self.PARAMETERS], 'files': self.properties[self.FILES], 'environment': self.properties[self.ENVIRONMENT], } try: self.heat(obj).stacks.validate(**kwargs) except Exception as ex: msg = _('Failed validate stack template due to ' '"%s"') % six.text_type(ex) raise exception.InvalidSpec(message=msg) return True
def _validate_az(self, obj, az_name, reason=None): try: res = self.compute(obj).validate_azs([az_name]) except exc.InternalError as ex: if reason == 'create': raise exc.EResourceCreation(type='server', message=six.text_type(ex)) else: raise if not res: msg = _("The specified %(key)s '%(value)s' could not be found") % { 'key': self.AVAILABILITY_ZONE, 'value': az_name } if reason == 'create': raise exc.EResourceCreation(type='server', message=msg) else: raise exc.InvalidSpec(message=msg) return az_name
def do_validate(self, obj): """Validate the stack template used by a node. :param obj: Node object to operate. :returns: True if validation succeeds. :raises: `InvalidSpec` exception is raised if template is invalid. """ kwargs = { 'stack_name': utils.random_name(), 'template': self.properties[self.TEMPLATE], 'template_url': self.properties[self.TEMPLATE_URL], 'parameters': self.properties[self.PARAMETERS], 'files': self.properties[self.FILES], 'environment': self.properties[self.ENVIRONMENT], 'preview': True, } try: self.orchestration(obj).stack_create(**kwargs) except exc.InternalError as ex: msg = _('Failed in validating template: %s') % six.text_type(ex) raise exc.InvalidSpec(message=msg) return True
def _validate_network(self, obj, network, reason=None): result = {} error = None # check network net_ident = network.get(self.NETWORK) if net_ident: try: net = self.network(obj).network_get(net_ident) if reason == 'update': result['net_id'] = net.id else: result['uuid'] = net.id except exc.InternalError as ex: error = six.text_type(ex) # check port port_ident = network.get(self.PORT) if not error and port_ident: try: port = self.network(obj).port_find(port_ident) if port.status != 'DOWN': error = _( "The status of the port %(port)s must be DOWN") % { 'port': port_ident } if reason == 'update': result['port_id'] = port.id else: result['port'] = port.id except exc.InternalError as ex: error = six.text_type(ex) elif port_ident is None and net_ident is None: error = _("'%(port)s' is required if '%(net)s' is omitted") % { 'port': self.PORT, 'net': self.NETWORK } fixed_ip = network.get(self.FIXED_IP) if not error and fixed_ip: if port_ident is not None: error = _("The '%(port)s' property and the '%(fixed_ip)s' " "property cannot be specified at the same time") % { 'port': self.PORT, 'fixed_ip': self.FIXED_IP } else: if reason == 'update': result['fixed_ips'] = [{'ip_address': fixed_ip}] else: result['fixed_ip'] = fixed_ip if error: if reason == 'create': raise exc.EResourceCreation(type='server', message=error) elif reason == 'update': raise exc.EResourceUpdate(type='server', id=obj.physical_id, message=error) else: raise exc.InvalidSpec(message=error) return result