Example #1
0
    def test_set_resources_quota_usage_dirty_with_empty_list(self):
        self._create_quota_usage('goals', 26)
        self._create_quota_usage('assists', 11)
        self._create_quota_usage('bookings', 3)
        # Expect all the resources for the tenant to be set dirty
        self.assertEqual(
            3,
            quota_api.set_resources_quota_usage_dirty(self.context, [],
                                                      self.tenant_id))
        usage_info_goals = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'goals', self.tenant_id)
        usage_info_assists = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'assists', self.tenant_id)
        usage_info_bookings = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'bookings', self.tenant_id)
        self._verify_quota_usage(usage_info_goals, expected_dirty=True)
        self._verify_quota_usage(usage_info_assists, expected_dirty=True)
        self._verify_quota_usage(usage_info_bookings, expected_dirty=True)

        # Higuain is clean now
        self.assertEqual(
            1,
            quota_api.set_quota_usage_dirty(self.context,
                                            'goals',
                                            self.tenant_id,
                                            dirty=False))
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'goals', self.tenant_id)
        self._verify_quota_usage(usage_info, expected_dirty=False)
Example #2
0
 def test_set_resources_quota_usage_dirty(self):
     self._create_quota_usage('goals', 26)
     self._create_quota_usage('assists', 11)
     self._create_quota_usage('bookings', 3)
     self.assertEqual(2, quota_api.set_resources_quota_usage_dirty(
         self.context, ['goals', 'bookings'], self.tenant_id))
     usage_info_goals = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     usage_info_assists = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'assists', self.tenant_id)
     usage_info_bookings = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'bookings', self.tenant_id)
     self._verify_quota_usage(usage_info_goals, expected_dirty=True)
     self._verify_quota_usage(usage_info_assists, expected_dirty=False)
     self._verify_quota_usage(usage_info_bookings, expected_dirty=True)
Example #3
0
 def test_set_resources_quota_usage_dirty(self):
     self._create_quota_usage('goals', 26)
     self._create_quota_usage('assists', 11)
     self._create_quota_usage('bookings', 3)
     self.assertEqual(2, quota_api.set_resources_quota_usage_dirty(
         self.context, ['goals', 'bookings'], self.tenant_id))
     usage_info_goals = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     usage_info_assists = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'assists', self.tenant_id)
     usage_info_bookings = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'bookings', self.tenant_id)
     self._verify_quota_usage(usage_info_goals, expected_dirty=True)
     self._verify_quota_usage(usage_info_assists, expected_dirty=False)
     self._verify_quota_usage(usage_info_bookings, expected_dirty=True)
Example #4
0
 def test_set_quota_usage_dirty(self):
     self._create_quota_usage('goals', 26)
     # Higuain needs a shower after the match
     self.assertEqual(1, quota_api.set_quota_usage_dirty(
         self.context, 'goals', self.tenant_id))
     usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     self._verify_quota_usage(usage_info,
                              expected_dirty=True)
     # Higuain is clean now
     self.assertEqual(1, quota_api.set_quota_usage_dirty(
         self.context, 'goals', self.tenant_id, dirty=False))
     usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     self._verify_quota_usage(usage_info,
                              expected_dirty=False)
Example #5
0
    def count(self, context, _plugin, tenant_id, resync_usage=False):
        """Return the current usage count for the resource."""
        # Load current usage data
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            context, self.name, tenant_id)
        # If dirty or missing, calculate actual resource usage querying
        # the database and set/create usage info data
        # NOTE: this routine "trusts" usage counters at service startup. This
        # assumption is generally valid, but if the database is tampered with,
        # or if data migrations do not take care of usage counters, the
        # assumption will not hold anymore
        if (tenant_id in self._dirty_tenants or not usage_info
                or usage_info.dirty):
            LOG.debug(("Usage tracker for resource:%(resource)s and tenant:"
                       "%(tenant_id)s is out of sync, need to count used "
                       "quota"), {
                           'resource': self.name,
                           'tenant_id': tenant_id
                       })
            in_use = context.session.query(
                self._model_class).filter_by(tenant_id=tenant_id).count()
            # Update quota usage, if requested (by default do not do that, as
            # typically one counts before adding a record, and that would mark
            # the usage counter as dirty again)
            if resync_usage or not usage_info:
                usage_info = self._resync(context, tenant_id, in_use)
            else:
                usage_info = quota_api.QuotaUsageInfo(usage_info.resource,
                                                      usage_info.tenant_id,
                                                      in_use,
                                                      usage_info.reserved,
                                                      usage_info.dirty)

        return usage_info.total
Example #6
0
 def test_get_quota_usage_by_tenant_and_resource(self):
     self._create_quota_usage('goals', 26)
     usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     self._verify_quota_usage(usage_info,
                              expected_resource='goals',
                              expected_used=26)
Example #7
0
    def count(self, context, _plugin, tenant_id, resync_usage=False):
        """Return the current usage count for the resource."""
        # Load current usage data
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            context, self.name, tenant_id)
        # If dirty or missing, calculate actual resource usage querying
        # the database and set/create usage info data
        # NOTE: this routine "trusts" usage counters at service startup. This
        # assumption is generally valid, but if the database is tampered with,
        # or if data migrations do not take care of usage counters, the
        # assumption will not hold anymore
        if (tenant_id in self._dirty_tenants or not usage_info
            or usage_info.dirty):
            LOG.debug(("Usage tracker for resource:%(resource)s and tenant:"
                       "%(tenant_id)s is out of sync, need to count used "
                       "quota"), {'resource': self.name,
                                  'tenant_id': tenant_id})
            in_use = context.session.query(self._model_class).filter_by(
                tenant_id=tenant_id).count()
            # Update quota usage, if requested (by default do not do that, as
            # typically one counts before adding a record, and that would mark
            # the usage counter as dirty again)
            if resync_usage or not usage_info:
                usage_info = self._resync(context, tenant_id, in_use)
            else:
                usage_info = quota_api.QuotaUsageInfo(usage_info.resource,
                                                      usage_info.tenant_id,
                                                      in_use,
                                                      usage_info.reserved,
                                                      usage_info.dirty)

        return usage_info.total
Example #8
0
 def test_set_quota_usage_dirty(self):
     self._create_quota_usage('goals', 26)
     # Higuain needs a shower after the match
     self.assertEqual(1, quota_api.set_quota_usage_dirty(
         self.context, 'goals', self.tenant_id))
     usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     self._verify_quota_usage(usage_info,
                              expected_dirty=True)
     # Higuain is clean now
     self.assertEqual(1, quota_api.set_quota_usage_dirty(
         self.context, 'goals', self.tenant_id, dirty=False))
     usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     self._verify_quota_usage(usage_info,
                              expected_dirty=False)
Example #9
0
 def test_get_quota_usage_by_tenant_and_resource(self):
     self._create_quota_usage('goals', 26)
     usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id)
     self._verify_quota_usage(usage_info,
                              expected_resource='goals',
                              expected_used=26)
Example #10
0
    def count(self, context, _plugin, tenant_id, resync_usage=True):
        """Return the current usage count for the resource.

        This method will fetch aggregate information for resource usage
        data, unless usage data are marked as "dirty".
        In the latter case resource usage will be calculated counting
        rows for tenant_id in the resource's database model.
        Active reserved amount are instead always calculated by summing
        amounts for matching records in the 'reservations' database model.

        The _plugin and _resource parameters are unused but kept for
        compatibility with the signature of the count method for
        CountableResource instances.
        """
        # Load current usage data, setting a row-level lock on the DB
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            context, self.name, tenant_id, lock_for_update=True)
        # Always fetch reservations, as they are not tracked by usage counters
        reservations = quota_api.get_reservations_for_resources(
            context, tenant_id, [self.name])
        reserved = reservations.get(self.name, 0)

        # If dirty or missing, calculate actual resource usage querying
        # the database and set/create usage info data
        # NOTE: this routine "trusts" usage counters at service startup. This
        # assumption is generally valid, but if the database is tampered with,
        # or if data migrations do not take care of usage counters, the
        # assumption will not hold anymore
        if (tenant_id in self._dirty_tenants or not usage_info
                or usage_info.dirty):
            LOG.debug(("Usage tracker for resource:%(resource)s and tenant:"
                       "%(tenant_id)s is out of sync, need to count used "
                       "quota"), {
                           'resource': self.name,
                           'tenant_id': tenant_id
                       })
            in_use = context.session.query(
                self._model_class).filter_by(tenant_id=tenant_id).count()

            # Update quota usage, if requested (by default do not do that, as
            # typically one counts before adding a record, and that would mark
            # the usage counter as dirty again)
            if resync_usage:
                usage_info = self._resync(context, tenant_id, in_use)
            else:
                resource = usage_info.resource if usage_info else self.name
                tenant_id = usage_info.tenant_id if usage_info else tenant_id
                dirty = usage_info.dirty if usage_info else True
                usage_info = quota_api.QuotaUsageInfo(resource, tenant_id,
                                                      in_use, dirty)

            LOG.debug(("Quota usage for %(resource)s was recalculated. "
                       "Used quota:%(used)d."), {
                           'resource': self.name,
                           'used': usage_info.used
                       })
        return usage_info.used + reserved
Example #11
0
    def count(self, context, _plugin, tenant_id, resync_usage=False):
        """Return the current usage count for the resource.

        This method will fetch aggregate information for resource usage
        data, unless usage data are marked as "dirty".
        In the latter case resource usage will be calculated counting
        rows for tenant_id in the resource's database model.
        Active reserved amount are instead always calculated by summing
        amounts for matching records in the 'reservations' database model.

        The _plugin and _resource parameters are unused but kept for
        compatibility with the signature of the count method for
        CountableResource instances.
        """
        # Load current usage data, setting a row-level lock on the DB
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            context, self.name, tenant_id, lock_for_update=True)
        # Always fetch reservations, as they are not tracked by usage counters
        reservations = quota_api.get_reservations_for_resources(
            context, tenant_id, [self.name])
        reserved = reservations.get(self.name, 0)

        # If dirty or missing, calculate actual resource usage querying
        # the database and set/create usage info data
        # NOTE: this routine "trusts" usage counters at service startup. This
        # assumption is generally valid, but if the database is tampered with,
        # or if data migrations do not take care of usage counters, the
        # assumption will not hold anymore
        if (tenant_id in self._dirty_tenants or
            not usage_info or usage_info.dirty):
            LOG.debug(("Usage tracker for resource:%(resource)s and tenant:"
                       "%(tenant_id)s is out of sync, need to count used "
                       "quota"), {'resource': self.name,
                                  'tenant_id': tenant_id})
            in_use = context.session.query(self._model_class).filter_by(
                tenant_id=tenant_id).count()

            # Update quota usage, if requested (by default do not do that, as
            # typically one counts before adding a record, and that would mark
            # the usage counter as dirty again)
            if resync_usage or not usage_info:
                usage_info = self._resync(context, tenant_id, in_use)
            else:
                # NOTE(salv-orlando): Passing 0 for reserved amount as
                # reservations are currently not supported
                usage_info = quota_api.QuotaUsageInfo(usage_info.resource,
                                                      usage_info.tenant_id,
                                                      in_use,
                                                      usage_info.dirty)

            LOG.debug(("Quota usage for %(resource)s was recalculated. "
                       "Used quota:%(used)d."),
                      {'resource': self.name,
                       'used': usage_info.used})
        return usage_info.used + reserved
Example #12
0
    def count(self, context, _plugin, tenant_id, resync_usage=False):
        """Return the current usage count for the resource.

        This method will fetch the information from resource usage data,
        unless usage data are marked as "dirty", in which case both used and
        reserved resource are explicitly counted.

        The _plugin and _resource parameters are unused but kept for
        compatibility with the signature of the count method for
        CountableResource instances.
        """
        # Load current usage data, setting a row-level lock on the DB
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            context, self.name, tenant_id, lock_for_update=True)
        # If dirty or missing, calculate actual resource usage querying
        # the database and set/create usage info data
        # NOTE: this routine "trusts" usage counters at service startup. This
        # assumption is generally valid, but if the database is tampered with,
        # or if data migrations do not take care of usage counters, the
        # assumption will not hold anymore
        if (tenant_id in self._dirty_tenants or not usage_info
                or usage_info.dirty):
            LOG.debug(("Usage tracker for resource:%(resource)s and tenant:"
                       "%(tenant_id)s is out of sync, need to count used "
                       "quota"), {
                           'resource': self.name,
                           'tenant_id': tenant_id
                       })
            in_use = context.session.query(
                self._model_class).filter_by(tenant_id=tenant_id).count()

            # Update quota usage, if requested (by default do not do that, as
            # typically one counts before adding a record, and that would mark
            # the usage counter as dirty again)
            if resync_usage or not usage_info:
                usage_info = self._resync(context,
                                          tenant_id,
                                          in_use,
                                          reserved=0)
            else:
                # NOTE(salv-orlando): Passing 0 for reserved amount as
                # reservations are currently not supported
                usage_info = quota_api.QuotaUsageInfo(usage_info.resource,
                                                      usage_info.tenant_id,
                                                      in_use, 0,
                                                      usage_info.dirty)

            LOG.debug(
                ("Quota usage for %(resource)s was recalculated. "
                 "Used quota:%(used)d; Reserved quota:%(reserved)d"), {
                     'resource': self.name,
                     'used': usage_info.used,
                     'reserved': usage_info.reserved
                 })
        return usage_info.total
Example #13
0
    def test_set_resources_quota_usage_dirty_with_empty_list(self):
        self._create_quota_usage('goals', 26)
        self._create_quota_usage('assists', 11)
        self._create_quota_usage('bookings', 3)
        # Expect all the resources for the tenant to be set dirty
        self.assertEqual(3, quota_api.set_resources_quota_usage_dirty(
            self.context, [], self.tenant_id))
        usage_info_goals = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'goals', self.tenant_id)
        usage_info_assists = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'assists', self.tenant_id)
        usage_info_bookings = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'bookings', self.tenant_id)
        self._verify_quota_usage(usage_info_goals, expected_dirty=True)
        self._verify_quota_usage(usage_info_assists, expected_dirty=True)
        self._verify_quota_usage(usage_info_bookings, expected_dirty=True)

        # Higuain is clean now
        self.assertEqual(1, quota_api.set_quota_usage_dirty(
            self.context, 'goals', self.tenant_id, dirty=False))
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            self.context, 'goals', self.tenant_id)
        self._verify_quota_usage(usage_info,
                                 expected_dirty=False)
Example #14
0
    def count_used(self, context, tenant_id, resync_usage=True):
        """Returns the current usage count for the resource.

        :param context: The request context.
        :param tenant_id: The ID of the tenant
        :param resync_usage: Default value is set to True. Syncs
            with in_use usage.
        """
        # Load current usage data, setting a row-level lock on the DB
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            context, self.name, tenant_id)

        # If dirty or missing, calculate actual resource usage querying
        # the database and set/create usage info data
        # NOTE: this routine "trusts" usage counters at service startup. This
        # assumption is generally valid, but if the database is tampered with,
        # or if data migrations do not take care of usage counters, the
        # assumption will not hold anymore
        if (tenant_id in self._dirty_tenants or not usage_info
                or usage_info.dirty):
            LOG.debug(("Usage tracker for resource:%(resource)s and tenant:"
                       "%(tenant_id)s is out of sync, need to count used "
                       "quota"), {
                           'resource': self.name,
                           'tenant_id': tenant_id
                       })
            in_use = context.session.query(
                self._model_class.tenant_id).filter_by(
                    tenant_id=tenant_id).count()

            # Update quota usage, if requested (by default do not do that, as
            # typically one counts before adding a record, and that would mark
            # the usage counter as dirty again)
            if resync_usage:
                usage_info = self._resync(context, tenant_id, in_use)
            else:
                resource = usage_info.resource if usage_info else self.name
                tenant_id = usage_info.tenant_id if usage_info else tenant_id
                dirty = usage_info.dirty if usage_info else True
                usage_info = quota_api.QuotaUsageInfo(resource, tenant_id,
                                                      in_use, dirty)

            LOG.debug(("Quota usage for %(resource)s was recalculated. "
                       "Used quota:%(used)d."), {
                           'resource': self.name,
                           'used': usage_info.used
                       })
        return usage_info.used
Example #15
0
    def count_used(self, context, tenant_id, resync_usage=True):
        """Returns the current usage count for the resource.

        :param context: The request context.
        :param tenant_id: The ID of the tenant
        :param resync_usage: Default value is set to True. Syncs
            with in_use usage.
        """
        # Load current usage data, setting a row-level lock on the DB
        usage_info = quota_api.get_quota_usage_by_resource_and_tenant(
            context, self.name, tenant_id)

        # If dirty or missing, calculate actual resource usage querying
        # the database and set/create usage info data
        # NOTE: this routine "trusts" usage counters at service startup. This
        # assumption is generally valid, but if the database is tampered with,
        # or if data migrations do not take care of usage counters, the
        # assumption will not hold anymore
        if (tenant_id in self._dirty_tenants or
                not usage_info or usage_info.dirty):
            LOG.debug(("Usage tracker for resource:%(resource)s and tenant:"
                       "%(tenant_id)s is out of sync, need to count used "
                       "quota"), {'resource': self.name,
                                  'tenant_id': tenant_id})
            in_use = context.session.query(
                self._model_class.tenant_id).filter_by(
                tenant_id=tenant_id).count()

            # Update quota usage, if requested (by default do not do that, as
            # typically one counts before adding a record, and that would mark
            # the usage counter as dirty again)
            if resync_usage:
                usage_info = self._resync(context, tenant_id, in_use)
            else:
                resource = usage_info.resource if usage_info else self.name
                tenant_id = usage_info.tenant_id if usage_info else tenant_id
                dirty = usage_info.dirty if usage_info else True
                usage_info = quota_api.QuotaUsageInfo(
                    resource, tenant_id, in_use, dirty)

            LOG.debug(("Quota usage for %(resource)s was recalculated. "
                       "Used quota:%(used)d."),
                      {'resource': self.name,
                       'used': usage_info.used})
        return usage_info.used
Example #16
0
 def _verify_dirty_bit(self, resource_name, expected_value=True):
     usage = quota_db_api.get_quota_usage_by_resource_and_tenant(
         self.ctx, resource_name, self._tenant_id)
     self.assertEqual(expected_value, usage.dirty)
Example #17
0
 def test_get_non_existing_quota_usage_returns_none(self):
     self.assertIsNone(quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id))
Example #18
0
 def test_get_non_existing_quota_usage_returns_none(self):
     self.assertIsNone(quota_api.get_quota_usage_by_resource_and_tenant(
         self.context, 'goals', self.tenant_id))
Example #19
0
 def _verify_dirty_bit(self, resource_name, expected_value=True):
     usage = quota_db_api.get_quota_usage_by_resource_and_tenant(
         self.ctx, resource_name, self._tenant_id)
     self.assertEqual(expected_value, usage.dirty)