Exemplo n.º 1
0
 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'])
Exemplo n.º 2
0
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
Exemplo n.º 3
0
 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'])
Exemplo n.º 4
0
 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'])
Exemplo n.º 5
0
 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'])
Exemplo n.º 6
0
    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)