def add_quota_usage(self, quota_name, usage_delta, validate=False): if usage_delta < 0: # Avoid race conditions by using F expressions. # See also: https://docs.djangoproject.com/en/dev/ref/models/expressions/#avoiding-race-conditions-using-f # Skip update if it would result in negative value. return self.quotas.filter( name=quota_name, usage__gte=-usage_delta).update(usage=F('usage') + usage_delta) quota = self.get_or_create_quota(quota_name) if validate and quota.is_exceeded(usage_delta): raise exceptions.QuotaValidationError( _('%(quota)s "%(name)s" quota is over limit. Required: %(usage)s, limit: %(limit)s.' ) % dict( quota=self, name=quota_name, usage=quota.usage + usage_delta, limit=quota.limit, )) quota.usage += usage_delta if quota.usage < 0: logger.error( '%(quota)s "%(name)s" quota usage should not be negative. ' 'Current usage: %(usage)s, delta: %(usage_delta)s', dict( quota=self, name=quota_name, usage=quota.usage, usage_delta=usage_delta, ), ) quota.usage = 0 quota.save(update_fields=['usage'])
def validate_quotas(nodes, tenant_spl): quota_sources = [ tenant_spl, tenant_spl.project, tenant_spl.customer, tenant_spl.service, tenant_spl.service.settings, ] for quota_name in ['storage', 'vcpu', 'ram']: requested = sum(get_node_quota(quota_name, node) for node in nodes) for source in quota_sources: try: quota = source.quotas.get(name=quota_name) if quota.limit != -1 and (quota.usage + requested > quota.limit): raise quotas_exceptions.QuotaValidationError( _( '"%(name)s" quota is over limit. Required: %(usage)s, limit: %(limit)s.' ) % dict( name=quota_name, usage=quota.usage + requested, limit=quota.limit, ) ) except ObjectDoesNotExist: pass
def add_quota_usage(self, quota_name, usage_delta, validate=False): if usage_delta < 0: # Skip update if it would result in negative value. # We need to use save so that pre_save/post_save signals are emitted. for quota in self.quotas.filter(name=quota_name, usage__gte=-usage_delta): quota.usage += usage_delta quota.save(update_fields=['usage']) return quota = self.get_or_create_quota(quota_name) if validate and quota.is_exceeded(usage_delta): raise exceptions.QuotaValidationError( _( '%(quota)s "%(name)s" quota is over limit. Required: %(usage)s, limit: %(limit)s.' ) % dict( quota=self, name=quota_name, usage=quota.usage + usage_delta, limit=quota.limit, ) ) quota.usage += usage_delta if quota.usage < 0: logger.error( '%(quota)s "%(name)s" quota usage should not be negative. ' 'Current usage: %(usage)s, delta: %(usage_delta)s', dict( quota=self, name=quota_name, usage=quota.usage, usage_delta=usage_delta, ), ) quota.usage = 0 quota.save(update_fields=['usage'])
def add_quota_usage(self, quota_name, usage_delta, fail_silently=False, validate=False): quota = self.quotas.get(name=quota_name) if validate and quota.is_exceeded(usage_delta): raise exceptions.QuotaValidationError( _('%(quota)s "%(name)s" quota is over limit. Required: %(usage)s, limit: %(limit)s.') % dict( quota=self, name=quota_name, usage=quota.usage + usage_delta, limit=quota.limit)) quota.usage += usage_delta if quota.usage < 0: logger.error('%(quota)s "%(name)s" quota usage should not be negative. ' 'Current usage: %(usage)s, delta: %(usage_delta)s', dict(quota=self, name=quota_name, usage=quota.usage, usage_delta=usage_delta)) quota.usage = 0 quota.save(update_fields=['usage'])
def add_quota_usage(self, quota_name, usage_delta, fail_silently=False, validate=False): quota = self.quotas.get(name=quota_name) if validate and quota.is_exceeded(usage_delta): raise exceptions.QuotaValidationError( _('%(quota)s "%(name)s" quota is over limit. Required: %(usage)s, limit: %(limit)s.' ) % dict(quota=self, name=quota_name, usage=quota.usage + usage_delta, limit=quota.limit)) quota.usage += usage_delta quota.save(update_fields=['usage'])
def validate(self, attrs): # Skip validation on update if self.instance: return attrs nodes = attrs.get('node_set') spl = attrs.get('service_project_link') for node in nodes: error_message = {} for node_param in ['storage', 'memory', 'cpu', 'subnet']: if not node.get(node_param): error_message[node_param] = 'This field is required.' if error_message: raise serializers.ValidationError(error_message) memory = node.pop('memory') cpu = node.pop('cpu') subnet = node.pop('subnet') roles = node.pop('roles') try: settings = subnet.settings project = spl.project instance_spl = openstack_tenant_models.OpenStackTenantServiceProjectLink.objects.get( project=project, service__settings=settings) except ObjectDoesNotExist: raise serializers.ValidationError( 'No matching instance service project link found.') flavors = openstack_tenant_models.Flavor.objects.filter( cores__gte=cpu, ram__gte=memory, settings=instance_spl.service.settings).\ order_by('cores', 'ram') if not flavors: raise serializers.ValidationError('No matching flavor found.') try: base_image_name = spl.service.settings.get_option( 'base_image_name') image = openstack_tenant_models.Image.objects.get( name=base_image_name, settings=instance_spl.service.settings) except ObjectDoesNotExist: raise serializers.ValidationError('No matching image found.') try: group = openstack_tenant_models.SecurityGroup.objects.get( name='default', settings=instance_spl.service.settings) except ObjectDoesNotExist: raise serializers.ValidationError('No matching group found.') flavor = flavors[0] node['flavor'] = flavor.uuid node['vcpu'] = flavor.cores node['ram'] = flavor.ram node['image'] = image.uuid node['subnet'] = subnet.uuid node['tenant_service_project_link'] = instance_spl.id node['roles'] = list(roles) node['group'] = group.uuid # check quotas quota_sources = [ instance_spl, instance_spl.project, instance_spl.customer, instance_spl.service, instance_spl.service.settings ] for quota_name in ['storage', 'vcpu', 'ram']: requested = sum([node[quota_name] for node in nodes]) for source in quota_sources: try: quota = source.quotas.get(name=quota_name) if quota.limit != -1 and (quota.usage + requested > quota.limit): raise quotas_exceptions.QuotaValidationError( _('"%(name)s" quota is over limit. Required: %(usage)s, limit: %(limit)s.' ) % dict(name=quota_name, usage=quota.usage + requested, limit=quota.limit)) except ObjectDoesNotExist: pass return super(ClusterSerializer, self).validate(attrs)