def _translate_section(self, section, sub_section, data, mapping): cfn_objects = {} obj_name = section[:-1] err_msg = _('"%%s" is not a valid keyword inside a %s ' 'definition') % obj_name for name, attrs in sorted(data.items()): cfn_object = {} if not attrs: args = {'object_name': obj_name, 'sub_section': sub_section} message = _('Each %(object_name)s must contain a ' '%(sub_section)s key.') % args raise exception.StackValidationFailed(message=message) try: for attr, attr_value in six.iteritems(attrs): cfn_attr = self._translate(attr, mapping, err_msg) cfn_object[cfn_attr] = attr_value cfn_objects[name] = cfn_object except AttributeError: message = _('"%(section)s" must contain a map of ' '%(obj_name)s maps. Found a [%(_type)s] ' 'instead') % {'section': section, '_type': type(attrs), 'obj_name': obj_name} raise exception.StackValidationFailed(message=message) except KeyError as e: # an invalid keyword was found raise exception.StackValidationFailed(message=e.args[0]) return cfn_objects
def validate(self): res = super(Pool, self).validate() if res: return res if self.properties[self.SESSION_PERSISTENCE] is not None: session_p = self.properties[self.SESSION_PERSISTENCE] persistence_type = session_p[self.SESSION_PERSISTENCE_TYPE] if persistence_type == self.APP_COOKIE: if not session_p.get(self.SESSION_PERSISTENCE_COOKIE_NAME): msg = (_('Property %(cookie)s is required when %(sp)s ' 'type is set to %(app)s.') % { 'cookie': self.SESSION_PERSISTENCE_COOKIE_NAME, 'sp': self.SESSION_PERSISTENCE, 'app': self.APP_COOKIE }) raise exception.StackValidationFailed(message=msg) elif persistence_type == self.SOURCE_IP: if session_p.get(self.SESSION_PERSISTENCE_COOKIE_NAME): msg = (_('Property %(cookie)s must NOT be specified when ' '%(sp)s type is set to %(ip)s.') % { 'cookie': self.SESSION_PERSISTENCE_COOKIE_NAME, 'sp': self.SESSION_PERSISTENCE, 'ip': self.SOURCE_IP }) raise exception.StackValidationFailed(message=msg)
def validate(self): super(RemoteStack, self).validate() try: self.heat() except Exception as ex: exc_info = dict(region=self._region_name, exc=six.text_type(ex)) msg = _('Cannot establish connection to Heat endpoint at region ' '"%(region)s" due to "%(exc)s"') % exc_info raise exception.StackValidationFailed(message=msg) try: params = self.properties[self.PARAMETERS] env = environment.get_child_environment(self.stack.env, params) tmpl = template_format.parse(self.properties[self.TEMPLATE]) args = { 'template': tmpl, 'files': self.stack.t.files, 'environment': env.user_env_as_dict(), } self.heat().stacks.validate(**args) except Exception as ex: exc_info = dict(region=self._region_name, exc=six.text_type(ex)) LOG.error(_LE('exception: %s'), type(ex)) msg = _('Failed validating stack template using Heat endpoint at ' 'region "%(region)s" due to "%(exc)s"') % exc_info raise exception.StackValidationFailed(message=msg)
def validate(self): super(Subnet, self).validate() subnetpool = self.properties[self.SUBNETPOOL] prefixlen = self.properties[self.PREFIXLEN] cidr = self.properties[self.CIDR] if subnetpool and cidr: raise exception.ResourcePropertyConflict(self.SUBNETPOOL, self.CIDR) if not subnetpool and not cidr: raise exception.PropertyUnspecifiedError(self.SUBNETPOOL, self.CIDR) if prefixlen and cidr: raise exception.ResourcePropertyConflict(self.PREFIXLEN, self.CIDR) ra_mode = self.properties[self.IPV6_RA_MODE] address_mode = self.properties[self.IPV6_ADDRESS_MODE] if (self.properties[self.IP_VERSION] == 4) and (ra_mode or address_mode): msg = _('ipv6_ra_mode and ipv6_address_mode are not supported ' 'for ipv4.') raise exception.StackValidationFailed(message=msg) if ra_mode and address_mode and (ra_mode != address_mode): msg = _('When both ipv6_ra_mode and ipv6_address_mode are set, ' 'they must be equal.') raise exception.StackValidationFailed(message=msg) gateway_ip = self.properties.get(self.GATEWAY_IP) if (gateway_ip and gateway_ip not in ['~', ''] and not netutils.is_valid_ip(gateway_ip)): msg = (_('Gateway IP address "%(gateway)s" is in ' 'invalid format.'), gateway_ip) raise exception.StackValidationFailed(message=msg)
def validate(self): super(LoadBalancer, self).validate() lb_type = self.properties[self.TYPE] bandwidth = self.properties[self.BANDWIDTH] vip_subnet = self.properties[self.VIP_SUBNET] az = self.properties[self.AVAILABILITY_ZONE] sec_group = self.properties[self.SECURITY_GROUP] if lb_type == self.EXTERNAL: if not bandwidth: msg = (_('The %(bdw)s must be provided when lb is %(type)s.') % { 'bdw': self.BANDWIDTH, 'type': lb_type }) raise exception.StackValidationFailed(message=msg) elif lb_type == self.INTERNAL: if vip_subnet is None or az is None or sec_group is None: msg = (_('The %(sub)s, %(az)s and %(sg)s must be provided ' 'when lb is %(type)s.') % { 'sub': self.VIP_SUBNET, 'az': self.AVAILABILITY_ZONE, 'sg': self.SECURITY_GROUP, 'type': lb_type }) raise exception.StackValidationFailed(message=msg)
def validate(self): """Validate any of the provided params.""" super(LaunchConfiguration, self).validate() # now we don't support without snapshot_id in bdm bdm = self.properties.get(self.BLOCK_DEVICE_MAPPINGS) if bdm: for mapping in bdm: ebs = mapping.get(self.EBS) if ebs: snapshot_id = ebs.get(self.SNAPSHOT_ID) if not snapshot_id: msg = _("SnapshotId is missing, this is required " "when specifying BlockDeviceMappings.") raise exception.StackValidationFailed(message=msg) else: msg = _("Ebs is missing, this is required " "when specifying BlockDeviceMappings.") raise exception.StackValidationFailed(message=msg) # validate the 'InstanceId', 'ImageId' and 'InstanceType', # if without 'InstanceId', 'ImageId' and 'InstanceType' are required instance_id = self.properties.get(self.INSTANCE_ID) if not instance_id: image_id = self.properties.get(self.IMAGE_ID) instance_type = self.properties.get(self.INSTANCE_TYPE) if not image_id or not instance_type: msg = _('If without InstanceId, ' 'ImageId and InstanceType are required.') raise exception.StackValidationFailed(message=msg)
def _validate_prefix_bounds(self): min_prefixlen = self.properties[self.MIN_PREFIXLEN] default_prefixlen = self.properties[self.DEFAULT_PREFIXLEN] max_prefixlen = self.properties[self.MAX_PREFIXLEN] msg_fmt = _('Illegal prefix bounds: %(key1)s=%(value1)s, ' '%(key2)s=%(value2)s.') # min_prefixlen can not be greater than max_prefixlen if min_prefixlen and max_prefixlen and min_prefixlen > max_prefixlen: msg = msg_fmt % dict(key1=self.MAX_PREFIXLEN, value1=max_prefixlen, key2=self.MIN_PREFIXLEN, value2=min_prefixlen) raise exception.StackValidationFailed(message=msg) if default_prefixlen: # default_prefixlen can not be greater than max_prefixlen if max_prefixlen and default_prefixlen > max_prefixlen: msg = msg_fmt % dict(key1=self.MAX_PREFIXLEN, value1=max_prefixlen, key2=self.DEFAULT_PREFIXLEN, value2=default_prefixlen) raise exception.StackValidationFailed(message=msg) # min_prefixlen can not be greater than default_prefixlen if min_prefixlen and min_prefixlen > default_prefixlen: msg = msg_fmt % dict(key1=self.MIN_PREFIXLEN, value1=min_prefixlen, key2=self.DEFAULT_PREFIXLEN, value2=default_prefixlen) raise exception.StackValidationFailed(message=msg)
def validate(self): super(Listener, self).validate() protocol = self.properties[self.PROTOCOL] session_sticky = self.properties[self.SESSION_STICKY] sticky_type = self.properties[self.STICKY_SESSION_TYPE] certificate = self.properties[self.CERTIFICATE] tcp_timeout = self.properties[self.TCP_TIMEOUT] if protocol == self.HTTP and session_sticky: if sticky_type != 'insert': msg = (_('Property %(sticky_type)s should be "insert" ' 'when %(protocol)s is %(http)s and ' '%(session_sticky)s is enabled.') % {'sticky_type': self.STICKY_SESSION_TYPE, 'protocol': self.PROTOCOL, 'http': self.HTTP, 'session_sticky': self.SESSION_STICKY}) raise exception.StackValidationFailed(message=msg) if protocol == self.HTTPS: if not certificate: msg = (_('Property %(cert)s is required when %(protocol)s ' 'is %(https)s') % {'cert': self.CERTIFICATE, 'protocol': self.PROTOCOL, 'https': self.HTTPS}) raise exception.StackValidationFailed(message=msg) if tcp_timeout and protocol != self.TCP: msg = (_('Property %(tcpt)s is valid when %(protocol)s ' 'is %(tcp)s') % {'tcpt': self.TCP_TIMEOUT, 'protocol': self.PROTOCOL, 'tcp': self.TCP}) raise exception.StackValidationFailed(message=msg)
def validate(self): """Validate the provided params.""" super(RBACPolicy, self).validate() action = self.properties[self.ACTION] obj_type = self.properties[self.OBJECT_TYPE] obj_id_or_name = self.properties[self.OBJECT_ID] # Validate obj_type and action per SUPPORTED_TYPES_ACTIONS. if obj_type not in self.SUPPORTED_TYPES_ACTIONS: msg = (_("Invalid object_type: %(obj_type)s. " "Valid object_type :%(value)s") % { 'obj_type': obj_type, 'value': self.SUPPORTED_TYPES_ACTIONS.keys() }) raise exception.StackValidationFailed(message=msg) if action not in self.SUPPORTED_TYPES_ACTIONS[obj_type]: msg = (_("Invalid action %(action)s for object type " "%(obj_type)s. Valid actions :%(value)s") % { 'action': action, 'obj_type': obj_type, 'value': self.SUPPORTED_TYPES_ACTIONS[obj_type] }) raise exception.StackValidationFailed(message=msg) # Make sure the value of object_id is correct. neutronV20.find_resourceid_by_name_or_id(self.client(), obj_type, obj_id_or_name)
def validate(self): """Validate the parameter group. Validate that each parameter belongs to only one Parameter Group and that each parameter name in the group references a valid parameter. """ LOG.debug('Validating Parameter Groups: %s', ', '.join(self.parameter_names)) if self.parameter_groups: if not isinstance(self.parameter_groups, list): raise exception.StackValidationFailed( error=_('Parameter Groups error'), path=[PARAMETER_GROUPS], message=_('The %s should be a list.') % PARAMETER_GROUPS) # Loop through groups and validate parameters grouped_parameters = [] for group in self.parameter_groups: parameters = group.get(PARAMETERS) if parameters is None: raise exception.StackValidationFailed( error=_('Parameter Groups error'), path=[PARAMETER_GROUPS, group.get('label', '')], message=_('The %s must be provided for ' 'each parameter group.') % PARAMETERS) if not isinstance(parameters, list): raise exception.StackValidationFailed( error=_('Parameter Groups error'), path=[PARAMETER_GROUPS, group.get('label', '')], message=_('The %s of parameter group ' 'should be a list.') % PARAMETERS) for param in parameters: # Check if param has been added to a previous group if param in grouped_parameters: raise exception.StackValidationFailed( error=_('Parameter Groups error'), path=[PARAMETER_GROUPS, group.get('label', '')], message=_( 'The %s parameter must be assigned to one ' 'parameter group only.') % param) else: grouped_parameters.append(param) # Check that grouped parameter references a valid Parameter if param not in self.parameter_names: raise exception.StackValidationFailed( error=_('Parameter Groups error'), path=[PARAMETER_GROUPS, group.get('label', '')], message=_( 'The grouped parameter %s does not reference ' 'a valid parameter.') % param)
def validate(self, with_value=True): try: for key in self.data: if key not in self.props: msg = _("Unknown Property %s") % key raise exception.StackValidationFailed(message=msg) for (key, prop) in self.props.items(): # check that update_allowed and immutable # do not contradict each other if prop.update_allowed() and prop.immutable(): msg = _("Property %(prop)s: %(ua)s and %(im)s " "cannot both be True") % { 'prop': key, 'ua': prop.schema.UPDATE_ALLOWED, 'im': prop.schema.IMMUTABLE } raise exception.InvalidSchemaError(message=msg) if with_value: try: self._get_property_value(key, validate=True) except exception.StackValidationFailed as ex: path = [key] path.extend(ex.path) raise exception.StackValidationFailed( path=path, message=ex.error_message) except ValueError as e: if prop.required() and key not in self.data: path = [] else: path = [key] raise exception.StackValidationFailed( path=path, message=six.text_type(e)) # are there unimplemented Properties if not prop.implemented() and key in self.data: msg = _("Property %s not implemented yet") % key raise exception.StackValidationFailed(message=msg) except exception.StackValidationFailed as ex: # NOTE(prazumovsky): should reraise exception for adding specific # error name and error_prefix to path for correct error message # building. path = self.error_prefix path.extend(ex.path) raise exception.StackValidationFailed(error=ex.error or 'Property error', path=path, message=ex.error_message)
def rsrc_defn_item(name, snippet): data = self.parse(stack, snippet) depends = data.get(RES_DEPENDS_ON) if isinstance(depends, six.string_types): depends = [depends] deletion_policy = function.resolve(data.get(RES_DELETION_POLICY)) if deletion_policy is not None: if deletion_policy not in six.iterkeys(self.deletion_policies): msg = _('Invalid deletion policy "%s"') % deletion_policy raise exception.StackValidationFailed(message=msg) else: deletion_policy = self.deletion_policies[deletion_policy] kwargs = { 'resource_type': data.get(RES_TYPE), 'properties': data.get(RES_PROPERTIES), 'metadata': data.get(RES_METADATA), 'depends': depends, 'deletion_policy': deletion_policy, 'update_policy': data.get(RES_UPDATE_POLICY), 'description': data.get(RES_DESCRIPTION) or '' } defn = rsrc_defn.ResourceDefinition(name, **kwargs) return name, defn
def validate(self, validate_value=True, context=None): """Validates the parameter. This method validates if the parameter's schema is valid, and if the default value - if present - or the user-provided value for the parameter comply with the schema. """ err_msg = _("Parameter '%(name)s' is invalid: %(exp)s") try: self.schema.validate(context) if not validate_value: return if self.user_value is not None: self._validate(self.user_value, context) elif self.has_default(): self._validate(self.default(), context) else: raise exception.UserParameterMissing(key=self.name) except exception.StackValidationFailed as ex: msg = err_msg % dict(name=self.name, exp=six.text_type(ex)) raise exception.StackValidationFailed(message=msg) except exception.InvalidSchemaError as ex: msg = err_msg % dict(name=self.name, exp=six.text_type(ex)) raise exception.InvalidSchemaError(message=msg)
def validate(self): """Validate any of the provided params.""" super(NetworkGateway, self).validate() connections = self.properties[self.CONNECTIONS] for connection in connections: segmentation_type = connection[self.SEGMENTATION_TYPE] segmentation_id = connection.get(self.SEGMENTATION_ID) if segmentation_type == 'vlan' and segmentation_id is None: msg = _("segmentation_id must be specified for using vlan") raise exception.StackValidationFailed(message=msg) if segmentation_type == 'flat' and segmentation_id: msg = _("segmentation_id cannot be specified except 0 for " "using flat") raise exception.StackValidationFailed(message=msg)
def _validate_against_facade(self, facade_cls): facade_schemata = properties.schemata(facade_cls.properties_schema) for n, fs in facade_schemata.items(): if fs.required and n not in self.properties_schema: msg = (_("Required property %(n)s for facade %(type)s " "missing in provider") % { 'n': n, 'type': self.type() }) raise exception.StackValidationFailed(message=msg) ps = self.properties_schema.get(n) if (n in self.properties_schema and (fs.allowed_param_prop_type() != ps.type)): # Type mismatch msg = (_("Property %(n)s type mismatch between facade %(type)s" " (%(fs_type)s) and provider (%(ps_type)s)") % { 'n': n, 'type': self.type(), 'fs_type': fs.type, 'ps_type': ps.type }) raise exception.StackValidationFailed(message=msg) for n, ps in self.properties_schema.items(): if ps.required and n not in facade_schemata: # Required property for template not present in facade msg = (_("Provider requires property %(n)s " "unknown in facade %(type)s") % { 'n': n, 'type': self.type() }) raise exception.StackValidationFailed(message=msg) facade_attrs = facade_cls.attributes_schema.copy() facade_attrs.update(facade_cls.base_attributes_schema) for attr in facade_attrs: if attr not in self.attributes_schema: msg = (_("Attribute %(attr)s for facade %(type)s " "missing in provider") % { 'attr': attr, 'type': self.type() }) raise exception.StackValidationFailed(message=msg)
def meta_serialize(self, metadata): """Serialize non-string metadata values before sending them to Nova.""" if not isinstance(metadata, collections.Mapping): raise exception.StackValidationFailed( message=_("nova server metadata needs to be a Map.")) return dict((key, (value if isinstance(value, six.string_types ) else jsonutils.dumps(value))) for (key, value) in metadata.items())
def validate(self): """Make sure all the AllowedResources are present.""" super(AccessPolicy, self).validate() resources = self.properties[self.ALLOWED_RESOURCES] # All of the provided resource names must exist in this stack for res in resources: if res not in self.stack: msg = _("AccessPolicy resource %s not in stack") % res raise exception.StackValidationFailed(message=msg)
def validate(self): """Validate any of the provided params.""" res = super(Instance, self).validate() if res: return res # check validity of security groups vs. network interfaces security_groups = self._get_security_groups() network_interfaces = self.properties.get(self.NETWORK_INTERFACES) if security_groups and network_interfaces: raise exception.ResourcePropertyConflict( '/'.join([self.SECURITY_GROUPS, self.SECURITY_GROUP_IDS]), self.NETWORK_INTERFACES) # check bdm property # now we don't support without snapshot_id in bdm bdm = self.properties.get(self.BLOCK_DEVICE_MAPPINGS) if bdm: for mapping in bdm: ebs = mapping.get(self.EBS) if ebs: snapshot_id = ebs.get(self.SNAPSHOT_ID) if not snapshot_id: msg = _("SnapshotId is missing, this is required " "when specifying BlockDeviceMappings.") raise exception.StackValidationFailed(message=msg) else: msg = _("Ebs is missing, this is required " "when specifying BlockDeviceMappings.") raise exception.StackValidationFailed(message=msg) subnet_id = self.properties.get(self.SUBNET_ID) if network_interfaces and subnet_id: # consider the old templates, we only to log to warn user # NetworkInterfaces has higher priority than SubnetId LOG.warning( _LW('"%(subnet)s" will be ignored if specified ' '"%(net_interfaces)s". So if you specified the ' '"%(net_interfaces)s" property, ' 'do not specify "%(subnet)s" property.'), { 'subnet': self.SUBNET_ID, 'net_interfaces': self.NETWORK_INTERFACES })
def validate(self): super(GlanceImage, self).validate() container_format = self.properties[self.CONTAINER_FORMAT] if (container_format in ['ami', 'ari', 'aki'] and self.properties[self.DISK_FORMAT] != container_format): msg = _("Invalid mix of disk and container formats. When " "setting a disk or container format to one of 'aki', " "'ari', or 'ami', the container and disk formats must " "match.") raise exception.StackValidationFailed(message=msg)
def get_class_to_instantiate(self, resource_type, resource_name=None): if resource_type == "": msg = _('Resource "%s" has no type') % resource_name raise exception.StackValidationFailed(message=msg) elif resource_type is None: msg = _('Non-empty resource type is required ' 'for resource "%s"') % resource_name raise exception.StackValidationFailed(message=msg) elif not isinstance(resource_type, six.string_types): msg = _('Resource "%s" type is not a string') % resource_name raise exception.StackValidationFailed(message=msg) try: info = self.get_resource_info(resource_type, resource_name=resource_name) except exception.EntityNotFound as exc: raise exception.StackValidationFailed(message=six.text_type(exc)) return info.get_class_to_instantiate()
def validate(self): super(Member, self).validate() members = self.properties[self.MEMBERS] server_ids = [m['server_id'] for m in members] if len(server_ids) != len(set(server_ids)): msg = (_('The %(sid)s must be different in property %(mem)s.') % { 'sid': self.SERVER_ID, 'mem': self.MEMBERS }) raise exception.StackValidationFailed(message=msg)
def validate_constraints(self, value, context=None, skipped=None): if not skipped: skipped = [] try: for constraint in self.constraints: if type(constraint) not in skipped: constraint.validate(value, self, context) except ValueError as ex: raise exception.StackValidationFailed(message=six.text_type(ex))
def _validate_prefixes_for_update(self, prop_diff): old_prefixes = self.properties[self.PREFIXES] new_prefixes = prop_diff[self.PREFIXES] # check new_prefixes is a superset of old_prefixes if not netutils.is_prefix_subset(old_prefixes, new_prefixes): msg = (_('Property %(key)s updated value %(new)s should ' 'be superset of existing value ' '%(old)s.') % dict(key=self.PREFIXES, new=sorted(new_prefixes), old=sorted(old_prefixes))) raise exception.StackValidationFailed(message=msg)
def validate(self): super(CinderVolumeType, self).validate() if self.properties[self.PROJECTS]: if self.cinder().volume_api_version == 1: raise exception.NotSupported( feature=_('Using Cinder API V1, volume type access')) if self.properties[self.IS_PUBLIC]: msg = (_('Can not specify property "%s" ' 'if the volume type is public.') % self.PROJECTS) raise exception.StackValidationFailed(message=msg)
def validate_with_client(self, client, value): senlin_client = client.client(CLIENT_NAME) type_list = senlin_client.policy_types() names = [pt['name'] for pt in type_list] if value not in names: not_found_message = ( _("Unable to find senlin policy type '%(pt)s', " "available policy types are %(pts)s.") % {'pt': value, 'pts': names} ) raise exception.StackValidationFailed(message=not_found_message)
def validate_hadoop_version(self, plugin_name, hadoop_version): plugin = self.client().plugins.get(plugin_name) allowed_versions = plugin.versions if hadoop_version not in allowed_versions: msg = (_("Requested plugin '%(plugin)s' doesn\'t support version " "'%(version)s'. Allowed versions are %(allowed)s") % { 'plugin': plugin_name, 'version': hadoop_version, 'allowed': ', '.join(allowed_versions) }) raise exception.StackValidationFailed(message=msg)
def validate(self): """Validate any of the provided parameters.""" super(ElasticIpAssociation, self).validate() eip = self.properties[self.EIP] allocation_id = self.properties[self.ALLOCATION_ID] instance_id = self.properties[self.INSTANCE_ID] ni_id = self.properties[self.NETWORK_INTERFACE_ID] # to check EIP and ALLOCATION_ID, should provide one of if bool(eip) == bool(allocation_id): msg = _("Either 'EIP' or 'AllocationId' must be provided.") raise exception.StackValidationFailed(message=msg) # to check if has EIP, also should specify InstanceId if eip and not instance_id: msg = _("Must specify 'InstanceId' if you specify 'EIP'.") raise exception.StackValidationFailed(message=msg) # to check InstanceId and NetworkInterfaceId, should provide # at least one if not instance_id and not ni_id: raise exception.PropertyUnspecifiedError('InstanceId', 'NetworkInterfaceId')
def validate(self): """Resource's validation. Validates to ensure that segmentation_id is not there for flat network type. """ super(ProviderNet, self).validate() if (self.properties[self.PROVIDER_SEGMENTATION_ID] and self.properties[self.PROVIDER_NETWORK_TYPE] != 'vlan'): msg = _('segmentation_id not allowed for flat network type.') raise exception.StackValidationFailed(message=msg)
def validate(self): super(HealthCheck, self).validate() protocol = self.properties[self.PROTOCOL] uri = self.properties[self.URI] if uri and protocol != self.HTTP: msg = (_('Property %(uri)s is valid if %(protocol)s ' 'is %(http)s.') % { 'uri': self.URI, 'protocol': self.PROTOCOL, 'http': self.HTTP }) raise exception.StackValidationFailed(message=msg)
def validate(self): # check validity of group size min_size = self.properties[self.MIN_SIZE] max_size = self.properties[self.MAX_SIZE] if max_size < min_size: msg = _("MinSize can not be greater than MaxSize") raise exception.StackValidationFailed(message=msg) if min_size < 0: msg = _("The size of AutoScalingGroup can not be less than zero") raise exception.StackValidationFailed(message=msg) if self.properties[self.DESIRED_CAPACITY] is not None: desired_capacity = self.properties[self.DESIRED_CAPACITY] if desired_capacity < min_size or desired_capacity > max_size: msg = _("DesiredCapacity must be between MinSize and MaxSize") raise exception.StackValidationFailed(message=msg) # TODO(pasquier-s): once Neutron is able to assign subnets to # availability zones, it will be possible to specify multiple subnets. # For now, only one subnet can be specified. The bug #1096017 tracks # this issue. if (self.properties.get(self.VPCZONE_IDENTIFIER) and len(self.properties[self.VPCZONE_IDENTIFIER]) != 1): raise exception.NotSupported(feature=_("Anything other than one " "VPCZoneIdentifier")) # validate properties InstanceId and LaunchConfigurationName # for aws auto scaling group. # should provide just only one of if self.type() == 'AWS::AutoScaling::AutoScalingGroup': instanceId = self.properties.get(self.INSTANCE_ID) launch_config = self.properties.get(self.LAUNCH_CONFIGURATION_NAME) if bool(instanceId) == bool(launch_config): msg = _("Either 'InstanceId' or 'LaunchConfigurationName' " "must be provided.") raise exception.StackValidationFailed(message=msg) super(AutoScalingGroup, self).validate()