Coverage for nova/conf/quota.py: 83%

22 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-17 15:08 +0000

1# Copyright 2010 United States Government as represented by the 

2# Administrator of the National Aeronautics and Space Administration. 

3# All Rights Reserved. 

4# 

5# Licensed under the Apache License, Version 2.0 (the "License"); you may 

6# not use this file except in compliance with the License. You may obtain 

7# a copy of the License at 

8# 

9# http://www.apache.org/licenses/LICENSE-2.0 

10# 

11# Unless required by applicable law or agreed to in writing, software 

12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

14# License for the specific language governing permissions and limitations 

15# under the License. 

16 

17import re 

18 

19import os_resource_classes as orc 

20from oslo_config import cfg 

21from oslo_config import types as cfg_types 

22 

23 

24class UnifiedLimitsResource(cfg_types.String): 

25 

26 # NOTE(melwitt): Attempting to import nova.limit.(local|placement) for 

27 # LEGACY_LIMITS resource names results in error: 

28 # AttributeError: module 'nova' has no attribute 'conf' 

29 resources = { 

30 'server_metadata_items', 'server_injected_files', 

31 'server_injected_file_content_bytes', 

32 'server_injected_file_path_bytes', 'server_key_pairs', 'server_groups', 

33 'server_group_members', 'servers'} 

34 

35 def __call__(self, value): 

36 super().__call__(value) 

37 valid_resources = self.resources 

38 valid_resources |= {f'class:{cls}' for cls in orc.STANDARDS} 

39 custom_regex = r'^class:CUSTOM_[A-Z0-9_]+$' 

40 if value in valid_resources or re.fullmatch(custom_regex, value): 40 ↛ 42line 40 didn't jump to line 42 because the condition on line 40 was always true

41 return value 

42 msg = ( 

43 f'Value {value} is not a valid resource class name. Must be ' 

44 f'one of: {valid_resources} or a custom resource class name ' 

45 f'of the form {custom_regex[1:-1]}') 

46 raise ValueError(msg) 

47 

48 

49quota_group = cfg.OptGroup( 

50 name='quota', 

51 title='Quota Options', 

52 help=""" 

53Quota options allow to manage quotas in openstack deployment. 

54""") 

55 

56quota_opts = [ 

57 cfg.IntOpt('instances', 

58 min=-1, 

59 default=10, 

60 deprecated_group='DEFAULT', 

61 deprecated_name='quota_instances', 

62 help=""" 

63The number of instances allowed per project. 

64 

65Possible Values 

66 

67* A positive integer or 0. 

68* -1 to disable the quota. 

69"""), 

70 cfg.IntOpt('cores', 

71 min=-1, 

72 default=20, 

73 deprecated_group='DEFAULT', 

74 deprecated_name='quota_cores', 

75 help=""" 

76The number of instance cores or vCPUs allowed per project. 

77 

78Possible values: 

79 

80* A positive integer or 0. 

81* -1 to disable the quota. 

82"""), 

83 cfg.IntOpt('ram', 

84 min=-1, 

85 default=50 * 1024, 

86 deprecated_group='DEFAULT', 

87 deprecated_name='quota_ram', 

88 help=""" 

89The number of megabytes of instance RAM allowed per project. 

90 

91Possible values: 

92 

93* A positive integer or 0. 

94* -1 to disable the quota. 

95"""), 

96 cfg.IntOpt('metadata_items', 

97 min=-1, 

98 default=128, 

99 deprecated_group='DEFAULT', 

100 deprecated_name='quota_metadata_items', 

101 help=""" 

102The number of metadata items allowed per instance. 

103 

104Users can associate metadata with an instance during instance creation. This 

105metadata takes the form of key-value pairs. 

106 

107Possible values: 

108 

109* A positive integer or 0. 

110* -1 to disable the quota. 

111"""), 

112 cfg.IntOpt('injected_files', 

113 min=-1, 

114 default=5, 

115 deprecated_group='DEFAULT', 

116 deprecated_name='quota_injected_files', 

117 help=""" 

118The number of injected files allowed. 

119 

120File injection allows users to customize the personality of an instance by 

121injecting data into it upon boot. Only text file injection is permitted: binary 

122or ZIP files are not accepted. During file injection, any existing files that 

123match specified files are renamed to include ``.bak`` extension appended with a 

124timestamp. 

125 

126Possible values: 

127 

128* A positive integer or 0. 

129* -1 to disable the quota. 

130"""), 

131 cfg.IntOpt('injected_file_content_bytes', 

132 min=-1, 

133 default=10 * 1024, 

134 deprecated_group='DEFAULT', 

135 deprecated_name='quota_injected_file_content_bytes', 

136 help=""" 

137The number of bytes allowed per injected file. 

138 

139Possible values: 

140 

141* A positive integer or 0. 

142* -1 to disable the quota. 

143"""), 

144 cfg.IntOpt('injected_file_path_length', 

145 min=-1, 

146 default=255, 

147 deprecated_group='DEFAULT', 

148 deprecated_name='quota_injected_file_path_length', 

149 help=""" 

150The maximum allowed injected file path length. 

151 

152Possible values: 

153 

154* A positive integer or 0. 

155* -1 to disable the quota. 

156"""), 

157 cfg.IntOpt('key_pairs', 

158 min=-1, 

159 default=100, 

160 deprecated_group='DEFAULT', 

161 deprecated_name='quota_key_pairs', 

162 help=""" 

163The maximum number of key pairs allowed per user. 

164 

165Users can create at least one key pair for each project and use the key pair 

166for multiple instances that belong to that project. 

167 

168Possible values: 

169 

170* A positive integer or 0. 

171* -1 to disable the quota. 

172"""), 

173 cfg.IntOpt('server_groups', 

174 min=-1, 

175 default=10, 

176 deprecated_group='DEFAULT', 

177 deprecated_name='quota_server_groups', 

178 help=""" 

179The maximum number of server groups per project. 

180 

181Server groups are used to control the affinity and anti-affinity scheduling 

182policy for a group of servers or instances. Reducing the quota will not affect 

183any existing group, but new servers will not be allowed into groups that have 

184become over quota. 

185 

186Possible values: 

187 

188* A positive integer or 0. 

189* -1 to disable the quota. 

190"""), 

191 cfg.IntOpt('server_group_members', 

192 min=-1, 

193 default=10, 

194 deprecated_group='DEFAULT', 

195 deprecated_name='quota_server_group_members', 

196 help=""" 

197The maximum number of servers per server group. 

198 

199Possible values: 

200 

201* A positive integer or 0. 

202* -1 to disable the quota. 

203"""), 

204 cfg.StrOpt('driver', 

205 default='nova.quota.DbQuotaDriver', 

206 choices=[ 

207 ('nova.quota.DbQuotaDriver', '(deprecated) Stores quota limit ' 

208 'information in the database and relies on the ``quota_*`` ' 

209 'configuration options for default quota limit values. Counts ' 

210 'quota usage on-demand.'), 

211 ('nova.quota.NoopQuotaDriver', 'Ignores quota and treats all ' 

212 'resources as unlimited.'), 

213 ('nova.quota.UnifiedLimitsDriver', 'Uses Keystone unified limits ' 

214 'to store quota limit information and relies on resource ' 

215 'usage counting from Placement. Counts quota usage on-demand. ' 

216 'Resources missing unified limits in Keystone will be treated ' 

217 'as a quota limit of 0, so it is important to ensure all ' 

218 'resources have registered limits in Keystone. The ``nova-manage ' 

219 'limits migrate_to_unified_limits`` command can be used to copy ' 

220 'existing quota limits from the Nova database to Keystone ' 

221 'unified limits via the Keystone API. Alternatively, unified ' 

222 'limits can be created manually using the OpenStackClient or ' 

223 'by calling the Keystone API directly.'), 

224 ], 

225 help=""" 

226Provides abstraction for quota checks. Users can configure a specific 

227driver to use for quota checks. 

228"""), 

229 cfg.BoolOpt('recheck_quota', 

230 default=True, 

231 help=""" 

232Recheck quota after resource creation to prevent allowing quota to be exceeded. 

233 

234This defaults to True (recheck quota after resource creation) but can be set to 

235False to avoid additional load if allowing quota to be exceeded because of 

236racing requests is considered acceptable. For example, when set to False, if a 

237user makes highly parallel REST API requests to create servers, it will be 

238possible for them to create more servers than their allowed quota during the 

239race. If their quota is 10 servers, they might be able to create 50 during the 

240burst. After the burst, they will not be able to create any more servers but 

241they will be able to keep their 50 servers until they delete them. 

242 

243The initial quota check is done before resources are created, so if multiple 

244parallel requests arrive at the same time, all could pass the quota check and 

245create resources, potentially exceeding quota. When recheck_quota is True, 

246quota will be checked a second time after resources have been created and if 

247the resource is over quota, it will be deleted and OverQuota will be raised, 

248usually resulting in a 403 response to the REST API user. This makes it 

249impossible for a user to exceed their quota with the caveat that it will, 

250however, be possible for a REST API user to be rejected with a 403 response in 

251the event of a collision close to reaching their quota limit, even if the user 

252has enough quota available when they made the request. 

253"""), 

254 cfg.BoolOpt( 

255 'count_usage_from_placement', 

256 default=False, 

257 help=""" 

258Enable the counting of quota usage from the placement service. 

259 

260Starting in Train, it is possible to count quota usage for cores and ram from 

261the placement service and instances from the API database instead of counting 

262from cell databases. 

263 

264This works well if there is only one Nova deployment running per placement 

265deployment. However, if an operator is running more than one Nova deployment 

266sharing a placement deployment, they should not set this option to True because 

267currently the placement service has no way to partition resource providers per 

268Nova deployment. When this option is left as the default or set to False, Nova 

269will use the legacy counting method to count quota usage for instances, cores, 

270and ram from its cell databases. 

271 

272Note that quota usage behavior related to resizes will be affected if this 

273option is set to True. Placement resource allocations are claimed on the 

274destination while holding allocations on the source during a resize, until the 

275resize is confirmed or reverted. During this time, when the server is in 

276VERIFY_RESIZE state, quota usage will reflect resource consumption on both the 

277source and the destination. This can be beneficial as it reserves space for a 

278revert of a downsize, but it also means quota usage will be inflated until a 

279resize is confirmed or reverted. 

280 

281Behavior will also be different for unscheduled servers in ERROR state. A 

282server in ERROR state that has never been scheduled to a compute host will 

283not have placement allocations, so it will not consume quota usage for cores 

284and ram. 

285 

286Behavior will be different for servers in SHELVED_OFFLOADED state. A server in 

287SHELVED_OFFLOADED state will not have placement allocations, so it will not 

288consume quota usage for cores and ram. Note that because of this, it will be 

289possible for a request to unshelve a server to be rejected if the user does not 

290have enough quota available to support the cores and ram needed by the server 

291to be unshelved. 

292 

293The ``populate_queued_for_delete`` and ``populate_user_id`` online data 

294migrations must be completed before usage can be counted from placement. Until 

295the data migration is complete, the system will fall back to legacy quota usage 

296counting from cell databases depending on the result of an EXISTS database 

297query during each quota check, if this configuration option is set to True. 

298Operators who want to avoid the performance hit from the EXISTS queries should 

299wait to set this configuration option to True until after they have completed 

300their online data migrations via ``nova-manage db online_data_migrations``. 

301"""), 

302 cfg.StrOpt( 

303 'unified_limits_resource_strategy', 

304 default='require', 

305 choices=[ 

306 ('require', 'Require the resources in ' 

307 '``unified_limits_resource_list`` to have registered limits set ' 

308 'in Keystone'), 

309 ('ignore', 'Ignore the resources in ' 

310 '``unified_limits_resource_list`` if they do not have registered ' 

311 'limits set in Keystone'), 

312 ], 

313 help=""" 

314Specify the semantics of the ``unified_limits_resource_list``. 

315 

316When the quota driver is set to the ``UnifiedLimitsDriver``, resources may be 

317specified to ether require registered limits set in Keystone or ignore if they 

318do not have registered limits set. 

319 

320When set to ``require``, if a resource in ``unified_limits_resource_list`` is 

321requested and has no registered limit set, the quota limit for that resource 

322will be considered to be 0 and all requests to allocate that resource will be 

323rejected for being over quota. 

324 

325When set to ``ignore``, if a resource in ``unified_limits_resource_list`` is 

326requested and has no registered limit set, the quota limit for that resource 

327will be considered to be unlimited and all requests to allocate that resource 

328will be accepted. 

329 

330Related options: 

331 

332* ``unified_limits_resource_list``: This must contain either resources for 

333 which to require registered limits set or resources to ignore if they do not 

334 have registered limits set. It can also be set to an empty list. 

335"""), 

336 cfg.ListOpt( 

337 'unified_limits_resource_list', 

338 item_type=UnifiedLimitsResource(), 

339 default=['servers'], 

340 help=""" 

341Specify a list of resources to require or ignore registered limits. 

342 

343When the quota driver is set to the ``UnifiedLimitsDriver``, require or ignore 

344resources in this list to have registered limits set in Keystone. 

345 

346When ``unified_limits_resource_strategy`` is ``require``, if a resource in this 

347list is requested and has no registered limit set, the quota limit for that 

348resource will be considered to be 0 and all requests to allocate that resource 

349will be rejected for being over quota. 

350 

351When ``unified_limits_resource_strategy`` is ``ignore``, if a resource in this 

352list is requested and has no registered limit set, the quota limit for that 

353resource will be considered to be unlimited and all requests to allocate that 

354resource will be accepted. 

355 

356The list can also be set to an empty list. 

357 

358Valid list item values are: 

359 

360* ``servers`` 

361 

362* ``class:<Placement resource class name>`` 

363 

364* ``server_key_pairs`` 

365 

366* ``server_groups`` 

367 

368* ``server_group_members`` 

369 

370* ``server_metadata_items`` 

371 

372* ``server_injected_files`` 

373 

374* ``server_injected_file_content_bytes`` 

375 

376* ``server_injected_file_path_bytes`` 

377 

378Related options: 

379 

380* ``unified_limits_resource_strategy``: This must be set to ``require`` or 

381 ``ignore`` 

382"""), 

383] 

384 

385 

386def register_opts(conf): 

387 conf.register_group(quota_group) 

388 conf.register_opts(quota_opts, group=quota_group) 

389 

390 

391def list_opts(): 

392 return {quota_group: quota_opts}