Skip to content

Commit d42fe46

Browse files
committed
Follow up for unified limits: PCPU and documentation
This addresses comments from code review to add handling of PCPU during the migration/copy of limits from the Nova database to Keystone. In legacy quotas, there is no settable quota limit for PCPU, so the limit for VCPU is used for PCPU. With unified limits, PCPU will have its own quota limit, so for the automated migration command, we will simply create a dedicated limit for PCPU that is the same value as the limit for VCPU. On the docs side, this adds more detail about the token authorization settings needed to use the nova-manage limits migrate_to_unified_limits CLI command and documents more OSC limit commands like show and delete. Related to blueprint unified-limits-nova-tool-and-docs Change-Id: Ifdb1691d7b25d28216d26479418ea323476fee1a
1 parent 8f0817f commit d42fe46

File tree

5 files changed

+173
-18
lines changed

5 files changed

+173
-18
lines changed

doc/source/admin/unified-limits.rst

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ To list all default quotas for a project, run:
135135

136136
This lists default quotas for all services and not just nova.
137137

138+
To show details about a default limit, run:
139+
140+
.. code-block:: console
141+
142+
$ openstack registered limit show <registered-limit-id>
143+
138144
To create a default quota limit, run:
139145

140146
.. code-block:: console
@@ -149,12 +155,18 @@ To create a default quota limit, run:
149155

150156
.. _Keystone tokens documentation: https://docs.openstack.org/keystone/latest/admin/tokens-overview.html#operation_create_system_token
151157

152-
To update a default value, run:
158+
To update a default quota value, run:
153159

154160
.. code-block:: console
155161
156162
$ openstack registered limit set --default-limit <value> <registered-limit-id>
157163
164+
To delete a default quota limit, run:
165+
166+
.. code-block:: console
167+
168+
$ openstack registered limit delete <registered-limit-id> [<registered-limit-id> ...]
169+
158170
View and update quota values for a project
159171
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
160172

@@ -175,18 +187,36 @@ token and run:
175187
176188
$ openstack limit list
177189
190+
To show details about a quota limit, run:
191+
192+
.. code-block:: console
193+
194+
$ openstack limit show <limit-id>
195+
196+
To create a quota limit for a project, run:
197+
198+
.. code-block:: console
199+
200+
$ openstack limit create --service nova --project <project> --resource-limit <value> <resource-name>
201+
178202
To update quotas for a project, run:
179203

180204
.. code-block:: console
181205
182206
$ openstack limit set --resource-limit <value> <limit-id>
183207
208+
To delete quotas for a project, run:
209+
210+
.. code-block:: console
211+
212+
$ openstack limit delete <limit-id> [<limit-id> ...]
213+
184214
185215
Migration to unified limits quotas
186216
----------------------------------
187217

188-
There is a `nova-manage limits migrate_to_unified_limits`_ command available
189-
to help with moving from legacy Nova database quotas to Keystone unified limits
218+
There is a `nova-manage limits migrate_to_unified_limits`_ command available to
219+
help with moving from legacy Nova database quotas to Keystone unified limits
190220
quotas. The command will read quota limits from the Nova database and call the
191221
Keystone API to create the corresponding unified limits. Per-user quota limits
192222
will **not** be copied into Keystone because per-user quotas are not supported

doc/source/cli/nova-manage.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,46 @@ This command is useful for operators to migrate from legacy quotas to unified
17781778
limits. Limits are migrated by copying them from the Nova database to Keystone
17791779
by creating them using the Keystone API.
17801780

1781+
The Nova configuration file used by ``nova-manage`` must have a ``[keystone]``
1782+
section that contains authentication settings in order for the Keystone API
1783+
calls to succeed. As an example:
1784+
1785+
.. code-block:: ini
1786+
1787+
[keystone]
1788+
region_name = RegionOne
1789+
user_domain_name = Default
1790+
auth_url = http://127.0.0.1/identity
1791+
auth_type = password
1792+
username = admin
1793+
password = <password>
1794+
system_scope = all
1795+
1796+
By default `Keystone policy configuration`_, access to create, update, and
1797+
delete in the `unified limits API`_ is restricted to callers with
1798+
`system-scoped authorization tokens`_. The ``system_scope = all`` setting
1799+
indicates the scope for system operations. You will need to ensure that the
1800+
user configured under ``[keystone]`` has the necessary role and scope.
1801+
1802+
.. warning::
1803+
1804+
The ``limits migrate_to_unified_limits`` command will create limits only
1805+
for resources that exist in the legacy quota system and any resource that
1806+
does not have a unified limit in Keystone will use a quota limit of **0**.
1807+
1808+
For resource classes that are allocated by the placement service and have no
1809+
default limit set, you will need to create default limits manually. The most
1810+
common example is class:DISK_GB. All Nova API requests that need to allocate
1811+
DISK_GB will fail quota enforcement until a default limit for it is set in
1812+
Keystone.
1813+
1814+
See the :doc:`unified limits documentation
1815+
</admin/unified-limits>` about creating limits using the OpenStackClient.
1816+
1817+
.. _Keystone policy configuration: https://docs.openstack.org/keystone/latest/configuration/policy.html
1818+
.. _unified limits API: https://docs.openstack.org/api-ref/identity/v3/index.html#unified-limits
1819+
.. _system-scoped authorization tokens: https://docs.openstack.org/keystone/latest/admin/tokens-overview.html#system-scoped-tokens
1820+
17811821
.. versionadded:: 28.0.0 (2023.2 Bobcat)
17821822

17831823
.. rubric:: Options

doc/source/user/unified-limits.rst

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,21 @@ API`_.
2020
Types of quota
2121
--------------
2222

23+
Unified limit resource names for resources that are tracked as `resource
24+
classes`_ in the placement service follow the naming pattern of the ``class:``
25+
prefix followed by the name of the resource class. For example: class:VCPU,
26+
class:PCPU, class:MEMORY_MB, class:DISK_GB, class:VGPU.
27+
2328
.. list-table::
2429
:header-rows: 1
2530
:widths: 10 40
2631

2732
* - Quota name
2833
- Description
2934
* - class:VCPU
30-
- Number of instance cores (VCPUs) allowed per project.
35+
- Number of shared CPU cores (VCPUs) allowed per project.
36+
* - class:PCPU
37+
- Number of dedicated CPU cores (PCPUs) allowed per project.
3138
* - servers
3239
- Number of instances allowed per project.
3340
* - server_key_pairs
@@ -42,9 +49,11 @@ Types of quota
4249
- Number of servers per server group.
4350
* - class:DISK_GB
4451
- Gigabytes of instance disk allowed per project.
45-
* - class:<any resource in the placement service>
46-
- Any resource in the placement service that is allocated by Nova can have
47-
a quota limit specified for it. Example: class:VGPU.
52+
* - class:<any resource class in the placement service>
53+
- Any resource class in the placement service that is allocated by Nova
54+
can have a quota limit specified for it. Example: class:VGPU.
55+
56+
.. _resource classes: https://docs.openstack.org/os-resource-classes/latest
4857

4958
The following quotas were previously available but were removed in microversion
5059
2.36 as they proxied information available from the networking service.
@@ -125,6 +134,28 @@ For example:
125134
| 17c4552c5aad4afca4813f37530fc897 | 8b22bf8a66fa4524a522b2a21865bbf2 | server_group_members | 10 | None | None |
126135
+----------------------------------+----------------------------------+------------------------------------+---------------+-------------+-----------+
127136
137+
To show details about a default limit, run:
138+
139+
.. code-block:: console
140+
141+
$ openstack registered limit show <registered-limit-id>
142+
143+
For example:
144+
145+
.. code-block:: console
146+
147+
$ openstack registered limit show 8a658096236549788e61f4fcbd5a4a12
148+
+---------------+----------------------------------+
149+
| Field | Value |
150+
+---------------+----------------------------------+
151+
| default_limit | 20 |
152+
| description | None |
153+
| id | 8a658096236549788e61f4fcbd5a4a12 |
154+
| region_id | None |
155+
| resource_name | class:VCPU |
156+
| service_id | 8b22bf8a66fa4524a522b2a21865bbf2 |
157+
+---------------+----------------------------------+
158+
128159
To list the currently set quota values for your project, run:
129160

130161
.. code-block:: console
@@ -141,3 +172,27 @@ For example:
141172
+----------------------------------+----------------------------------+----------------------------------+---------------+----------------+-------------+-----------+
142173
| 8b3364b2241e4090aaaa49355c7a5b56 | 5cd3281595a9497ba87209701cd9f3f2 | 8b22bf8a66fa4524a522b2a21865bbf2 | class:VCPU | 5 | None | None |
143174
+----------------------------------+----------------------------------+----------------------------------+---------------+----------------+-------------+-----------+
175+
176+
To show details about a quota limimt, run:
177+
178+
.. code-block:: console
179+
180+
$ openstack limit show <limit-id>
181+
182+
For example:
183+
184+
.. code-block:: console
185+
186+
$ openstack limit show 8b3364b2241e4090aaaa49355c7a5b56
187+
+----------------+----------------------------------+
188+
| Field | Value |
189+
+----------------+----------------------------------+
190+
| description | None |
191+
| domain_id | None |
192+
| id | 8b3364b2241e4090aaaa49355c7a5b56 |
193+
| project_id | 5cd3281595a9497ba87209701cd9f3f2 |
194+
| region_id | None |
195+
| resource_limit | 5 |
196+
| resource_name | class:VCPU |
197+
| service_id | 8b22bf8a66fa4524a522b2a21865bbf2 |
198+
+----------------+----------------------------------+

nova/cmd/manage.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3384,6 +3384,17 @@ def _create_unified_limits(self, ctxt, legacy_defaults, project_id,
33843384
zip(unified_to_legacy_names.values(),
33853385
unified_to_legacy_names.keys()))
33863386

3387+
# Handle the special case of PCPU. With legacy quotas, there is no
3388+
# dedicated quota limit for PCPUs, so they share the quota limit for
3389+
# VCPUs: 'cores'. With unified limits, class:PCPU has its own dedicated
3390+
# quota limit, so we will just mirror the limit for class:VCPU and
3391+
# create a limit with the same value for class:PCPU.
3392+
if 'cores' in legacy_defaults:
3393+
# Just make up a dummy legacy resource 'pcores' for this.
3394+
legacy_defaults['pcores'] = legacy_defaults['cores']
3395+
unified_to_legacy_names['class:PCPU'] = 'pcores'
3396+
legacy_to_unified_names['pcores'] = 'class:PCPU'
3397+
33873398
# For auth, a section for [keystone] is required in the config:
33883399
#
33893400
# [keystone]
@@ -3448,6 +3459,11 @@ def _create_unified_limits(self, ctxt, legacy_defaults, project_id,
34483459
msg = f'Found project limits in the database: {legacy_projects} ...'
34493460
output(_(msg))
34503461

3462+
# Handle the special case of PCPU again for project limits.
3463+
if 'cores' in legacy_projects:
3464+
# Just make up a dummy legacy resource 'pcores' for this.
3465+
legacy_projects['pcores'] = legacy_projects['cores']
3466+
34513467
# Retrieve existing limits from Keystone.
34523468
project_limits = keystone_api.limits(
34533469
project_id=project_id, region_id=region_id)

nova/tests/functional/test_nova_manage.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,9 +2443,10 @@ def test_migrate_to_unified_limits_unexpected_error(self, mock_sdk):
24432443
mock_sdk.return_value.create_limit.side_effect = (
24442444
test.TestingException('oops!'))
24452445

2446-
# Create a couple of project limits.
2446+
# Create a few project limits.
24472447
objects.Quotas.create_limit(self.ctxt, uuids.project, 'ram', 8192)
24482448
objects.Quotas.create_limit(self.ctxt, uuids.project, 'instances', 25)
2449+
objects.Quotas.create_limit(self.ctxt, uuids.project, 'cores', 22)
24492450

24502451
return_code = self.cli.migrate_to_unified_limits(
24512452
project_id=uuids.project, verbose=True)
@@ -2458,10 +2459,16 @@ def test_migrate_to_unified_limits_unexpected_error(self, mock_sdk):
24582459
# cores, ram, metadata_items, injected_files,
24592460
# injected_file_content_bytes, injected_file_path_length, key_pairs,
24602461
# server_groups, and server_group_members.
2462+
#
2463+
# And there is 1 default limit value automatically generated for PCPU
2464+
# based on 'cores'.
24612465
self.assertEqual(
2462-
10, mock_sdk.return_value.create_registered_limit.call_count)
2466+
11, mock_sdk.return_value.create_registered_limit.call_count)
24632467

2464-
self.assertEqual(2, mock_sdk.return_value.create_limit.call_count)
2468+
# We expect that we attempted to create 4 project limits:
2469+
# class:MEMORY_MB, servers, and class:VCPU = 3 + special case
2470+
# class:PCPU = 4.
2471+
self.assertEqual(4, mock_sdk.return_value.create_limit.call_count)
24652472

24662473
def test_migrate_to_unified_limits_already_exists(self):
24672474
# Create a couple of unified limits to already exist.
@@ -2478,15 +2485,18 @@ def test_migrate_to_unified_limits_already_exists(self):
24782485
self.cli.migrate_to_unified_limits(
24792486
project_id=uuids.project, verbose=True)
24802487

2481-
# There are 10 default limit values in the config options, so because a
2482-
# limit for 'servers' already exists, we should have only created 9.
2488+
# There are 10 default limit values in the config options +
2489+
# 1 special case for PCPU which will be added based on VCPU = 11.
2490+
# Because a limit for 'servers' already exists, we should have only
2491+
# created 10.
24832492
mock_sdk = self.ul_api.mock_sdk_adapter
24842493
self.assertEqual(
2485-
9, mock_sdk.create_registered_limit.call_count)
2494+
10, mock_sdk.create_registered_limit.call_count)
24862495

24872496
# There already exists a project limit for 'class:VCPU', so we should
2488-
# have created only 1 project limit.
2489-
self.assertEqual(1, mock_sdk.create_limit.call_count)
2497+
# have created only 2 project limits. One for 'servers' and one for
2498+
# special case 'class:PCPU' generated from VCPU.
2499+
self.assertEqual(2, mock_sdk.create_limit.call_count)
24902500

24912501
def test_migrate_to_unified_limits(self):
24922502
# Set some defaults using the config options.
@@ -2534,10 +2544,14 @@ def test_migrate_to_unified_limits(self):
25342544
self.cli.migrate_to_unified_limits(
25352545
project_id=uuids.project, verbose=True)
25362546

2537-
# There should be 10 registered (default) limits now.
2547+
# There are 10 default limit values in the config options +
2548+
# 1 special case for PCPU which will be added based on VCPU = 11.
2549+
#
2550+
# There should be 11 registered (default) limits now.
25382551
expected_registered_limits = {
25392552
'servers': 5,
25402553
'class:VCPU': 10,
2554+
'class:PCPU': 10,
25412555
'class:MEMORY_MB': 4096,
25422556
'server_metadata_items': 64,
25432557
'server_injected_files': 3,
@@ -2549,7 +2563,7 @@ def test_migrate_to_unified_limits(self):
25492563
}
25502564

25512565
registered_limits = self.ul_api.registered_limits()
2552-
self.assertEqual(10, len(registered_limits))
2566+
self.assertEqual(11, len(registered_limits))
25532567
for rl in registered_limits:
25542568
self.assertEqual(
25552569
expected_registered_limits[rl.resource_name], rl.default_limit)
@@ -2581,7 +2595,7 @@ def test_migrate_to_unified_limits(self):
25812595

25822596
region_registered_limits = self.ul_api.registered_limits(
25832597
region_id=uuids.region)
2584-
self.assertEqual(10, len(region_registered_limits))
2598+
self.assertEqual(11, len(region_registered_limits))
25852599
for rl in region_registered_limits:
25862600
self.assertEqual(
25872601
expected_registered_limits[rl.resource_name], rl.default_limit)

0 commit comments

Comments
 (0)