def _check_num_keypairs_quota(self, context, count): keypair_resource = self.quota.resources['keypairs'] quotas = self.quota.get_quota_limit_and_usage( context, {'keyparis': keypair_resource}, context.tenant) limit = quotas['keypairs']['limit'] in_use = quotas['keypairs']['in_use'] reserved = quotas['keypairs']['reserved'] available_quota = limit - in_use - reserved if count <= available_quota: return count else: raise exception.OverQuota(overs='keypairs')
def _check_num_servers_quota(self, context, min_count, max_count): ins_resource = self.quota.resources['servers'] quotas = self.quota.get_quota_limit_and_usage( context, {'servers': ins_resource}, context.tenant) limit = quotas['servers']['limit'] in_use = quotas['servers']['in_use'] reserved = quotas['servers']['reserved'] available_quota = limit - in_use - reserved if max_count <= available_quota: return max_count elif min_count <= available_quota and max_count > available_quota: return available_quota else: raise exception.OverQuota(overs='servers')
def quota_reserve(self, context, resources, quotas, deltas, expire, until_refresh, max_age, project_id, is_allocated_reserve=False): # NOTE(wanghao): Now we still doesn't support contenxt.elevated() yet. # We can support it later. elevated = context with _session_for_write() as session: if project_id is None: project_id = context.project_id # Get the current usages usages = self._get_quota_usages(context, project_id) allocated = self.quota_allocated_get_all_by_project( context, project_id) allocated.pop('project_id') # Handle usage refresh work = set(deltas.keys()) while work: resource = work.pop() # Do we need to refresh the usage? refresh = False if resource not in usages: usages[resource] = self._quota_usage_create( elevated, project_id, resource, 0, 0, until_refresh or None, session=session) refresh = True elif usages[resource].in_use < 0: refresh = True elif usages[resource].until_refresh is not None: usages[resource].until_refresh -= 1 if usages[resource].until_refresh <= 0: refresh = True elif max_age and usages[resource].updated_at is not None and ( (usages[resource].updated_at - timeutils.utcnow()).seconds >= max_age): refresh = True # OK, refresh the usage if refresh: # Grab the sync routine sync = self.QUOTA_SYNC_FUNCTIONS[resources[resource].sync] updates = sync(elevated, project_id) for res, in_use in updates.items(): # Make sure we have a destination for the usage! if res not in usages: usages[res] = self._quota_usage_create( elevated, project_id, res, 0, 0, until_refresh or None, session=session) # Update the usage usages[res].in_use = in_use usages[res].until_refresh = until_refresh or None # Because more than one resource may be refreshed # by the call to the sync routine, and we don't # want to double-sync, we make sure all refreshed # resources are dropped from the work set. work.discard(res) # Check for deltas that would go negative if is_allocated_reserve: unders = [ r for r, delta in deltas.items() if delta < 0 and delta + allocated.get(r, 0) < 0 ] else: unders = [ r for r, delta in deltas.items() if delta < 0 and delta + usages[r].in_use < 0 ] # Now, let's check the quotas overs = [ r for r, delta in deltas.items() if quotas[r] >= 0 and delta >= 0 and quotas[r] < delta + usages[r].total + allocated.get(r, 0) ] # Create the reservations if not overs: reservations = [] for resource, delta in deltas.items(): usage = usages[resource] allocated_id = None if is_allocated_reserve: try: quota = self.quota_get(context, project_id, resource) except exception.ProjectQuotaNotFound: # If we were using the default quota, create DB # entry quota = self.quota_create(context, project_id, resource, quotas[resource], 0) # Since there's no reserved/total for allocated, update # allocated immediately and subtract on rollback # if needed self.quota_allocated_update(context, project_id, resource, quota.allocated + delta) allocated_id = quota.id usage = None reservation = self._reservation_create( elevated, uuidutils.generate_uuid(), usage, project_id, resource, delta, expire, session=session, allocated_id=allocated_id) reservations.append(reservation) # Also update the reserved quantity if delta > 0 and not is_allocated_reserve: usages[resource].reserved += delta if unders: LOG.warning( "Change will make usage less than 0 for the " "following resources: %s", unders) if overs: usages = { k: dict(in_use=v.in_use, reserved=v.reserved, allocated=allocated.get(k, 0)) for k, v in usages.items() } raise exception.OverQuota(overs=sorted(overs), quotas=quotas, usages=usages) return reservations