1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
| [root@controller ~]
import sqlalchemy as sa
from neutron.common import exceptions from neutron.db import model_base from neutron.db import models_v2
''' quota数据库表的表结构,tenant默认集成的配额从这里获取 mysql> desc quotas; +-----------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+---------+-------+ | id | varchar(36) | NO | PRI | NULL | | | tenant_id | varchar(255) | YES | MUL | NULL | | | resource | varchar(255) | YES | | NULL | | | limit | int(11) | YES | | NULL | | +-----------+--------------+------+-----+---------+-------+ ''' class Quota(model_base.BASEV2, models_v2.HasId): """Represent a single quota override for a tenant.
If there is no row for a given tenant id and resource, then the default for the quota class is used. """ tenant_id = sa.Column(sa.String(255), index=True) resource = sa.Column(sa.String(255)) limit = sa.Column(sa.Integer)
''' quota配额的具体实现,根据数据库的配置内容,实现quota的控制,即quota的增删改查方法 ''' class DbQuotaDriver(object): """Driver to perform necessary checks to enforce quotas and obtain quota information.
The default driver utilizes the local database. """
''' 得到租户tenant的quota,执行neutron quota-show --tenant-id uuid时调用的方法 ''' @staticmethod def get_tenant_quotas(context, resources, tenant_id): """Given a list of resources, retrieve the quotas for the given tenant.
:param context: The request context, for access checks. :param resources: A dictionary of the registered resource keys. :param tenant_id: The ID of the tenant to return quotas for. :return dict: from resource name to dict of name and limit """
tenant_quota = dict((key, resource.default) for key, resource in resources.items())
q_qry = context.session.query(Quota).filter_by(tenant_id=tenant_id) tenant_quota.update((q['resource'], q['limit']) for q in q_qry)
return tenant_quota
''' quota的删除,即执行neutron quota-delete 的方法,删除之后,tenant将会集成默认的的quota配置 ''' @staticmethod def delete_tenant_quota(context, tenant_id): """Delete the quota entries for a given tenant_id.
Atfer deletion, this tenant will use default quota values in conf. """ with context.session.begin(): tenant_quotas = context.session.query(Quota) tenant_quotas = tenant_quotas.filter_by(tenant_id=tenant_id) tenant_quotas.delete()
''' 得到所有租户tenant的配额资源,即执行neutron quota-list所查看的内容 ''' @staticmethod def get_all_quotas(context, resources): """Given a list of resources, retrieve the quotas for the all tenants.
:param context: The request context, for access checks. :param resources: A dictionary of the registered resource keys. :return quotas: list of dict of tenant_id:, resourcekey1: resourcekey2: ... """ tenant_default = dict((key, resource.default) for key, resource in resources.items())
all_tenant_quotas = {}
for quota in context.session.query(Quota): tenant_id = quota['tenant_id']
tenant_quota = all_tenant_quotas.get(tenant_id) if tenant_quota is None: tenant_quota = tenant_default.copy() tenant_quota['tenant_id'] = tenant_id all_tenant_quotas[tenant_id] = tenant_quota
tenant_quota[quota['resource']] = quota['limit']
return all_tenant_quotas.values()
''' 更新quota的配置,即执行neutron quota-update命令的具体实现 ''' @staticmethod def update_quota_limit(context, tenant_id, resource, limit): with context.session.begin(): tenant_quota = context.session.query(Quota).filter_by( tenant_id=tenant_id, resource=resource).first()
if tenant_quota: tenant_quota.update({'limit': limit}) else: tenant_quota = Quota(tenant_id=tenant_id, resource=resource, limit=limit) context.session.add(tenant_quota)
def _get_quotas(self, context, tenant_id, resources, keys): """Retrieves the quotas for specific resources.
A helper method which retrieves the quotas for the specific resources identified by keys, and which apply to the current context.
:param context: The request context, for access checks. :param tenant_id: the tenant_id to check quota. :param resources: A dictionary of the registered resources. :param keys: A list of the desired quotas to retrieve.
""" desired = set(keys) sub_resources = dict((k, v) for k, v in resources.items() if k in desired)
if len(keys) != len(sub_resources): unknown = desired - set(sub_resources.keys()) raise exceptions.QuotaResourceUnknown(unknown=sorted(unknown))
quotas = DbQuotaDriver.get_tenant_quotas( context, sub_resources, tenant_id)
return dict((k, v) for k, v in quotas.items())
''' neutron quota的校验,即在执行过程中,调用该方法,确认tenant的quota是否在合理的范围内 ''' def limit_check(self, context, tenant_id, resources, values): """Check simple quota limits.
For limits--those quotas for which there is no usage synchronization function--this method checks that a set of proposed values are permitted by the limit restriction.
This method will raise a QuotaResourceUnknown exception if a given resource is unknown or if it is not a simple limit resource.
If any of the proposed values is over the defined quota, an OverQuota exception will be raised with the sorted list of the resources which are too high. Otherwise, the method returns nothing.
:param context: The request context, for access checks. :param tenant_id: The tenant_id to check the quota. :param resources: A dictionary of the registered resources. :param values: A dictionary of the values to check against the quota. """
unders = [key for key, val in values.items() if val < 0] if unders: raise exceptions.InvalidQuotaValue(unders=sorted(unders))
quotas = self._get_quotas(context, tenant_id, resources, values.keys())
overs = [key for key, val in values.items() if quotas[key] >= 0 and quotas[key] < val] if overs: raise exceptions.OverQuota(overs=sorted(overs))
|