Fix quota usage and reservation display

Fix `openstack quota show --usage` to correctly display resource usage
and reservations by applying proper name normalization for corresponding
sections of data.
Previously, name normalization was applied only for "limits" which is
the root section, leaving 'usage' and 'reservation' sections untouched.

Change-Id: Id14fe894b30a74b9b8d78b00c3d4ff151f8b4210
Closes-bug: #2137636
Signed-off-by: Andriy Kurilin <andr.kurilin@gmail.com>
This commit is contained in:
Andriy Kurilin 2026-01-07 13:26:47 +01:00
parent d1a0ede7db
commit 0a93733293
3 changed files with 83 additions and 14 deletions

View file

@ -797,20 +797,25 @@ and ``server-group-members`` output for a given quota class."""
info.update(volume_quota_info)
info.update(network_quota_info)
# Map the internal quota names to the external ones
# COMPUTE_QUOTAS and NETWORK_QUOTAS share floating-ips,
# secgroup-rules and secgroups as dict value, so when
# neutron is enabled, quotas of these three resources
# in nova will be replaced by neutron's.
for k, v in itertools.chain(
COMPUTE_QUOTAS.items(),
NOVA_NETWORK_QUOTAS.items(),
VOLUME_QUOTAS.items(),
NETWORK_QUOTAS.items(),
):
if not k == v and info.get(k) is not None:
info[v] = info[k]
info.pop(k)
def _normalize_names(section: dict) -> None:
# Map the internal quota names to the external ones
# COMPUTE_QUOTAS and NETWORK_QUOTAS share floating-ips,
# secgroup-rules and secgroups as dict value, so when
# neutron is enabled, quotas of these three resources
# in nova will be replaced by neutron's.
for k, v in itertools.chain(
COMPUTE_QUOTAS.items(),
NOVA_NETWORK_QUOTAS.items(),
VOLUME_QUOTAS.items(),
NETWORK_QUOTAS.items(),
):
if not k == v and section.get(k) is not None:
section[v] = section.pop(k)
_normalize_names(info)
if parsed_args.usage:
_normalize_names(info["reservation"])
_normalize_names(info["usage"])
# Remove the 'id' field since it's not very useful
if 'id' in info:

View file

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
from unittest import mock
from openstack.block_storage.v3 import quota_set as _volume_quota_set
@ -1122,6 +1123,64 @@ class TestQuotaShow(TestQuota):
)
self.assertNotCalled(self.network_client.get_quota_default)
def test_quota_show__with_network_and_usage(self):
# ensure we do not interfere with other tests
self._network_quota_details = copy.deepcopy(
self._network_quota_details
)
# set a couple of resources
self._network_quota_details["floating_ips"].update(
limit=30, reserved=20, used=7
)
self._network_quota_details["security_group_rules"].update(
limit=9, reserved=7, used=5
)
arglist = [
'--network',
'--usage',
self.projects[0].name,
]
verifylist = [
('service', 'network'),
('project', self.projects[0].name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
headers, result_gen = self.cmd.take_action(parsed_args)
self.assertEqual(('Resource', 'Limit', 'In Use', 'Reserved'), headers)
result = sorted(result_gen)
self.assertEqual(
[
('floating-ips', 30, 7, 20),
('health_monitors', 0, 0, 0),
('l7_policies', 0, 0, 0),
('listeners', 0, 0, 0),
('load_balancers', 0, 0, 0),
('networks', 0, 0, 0),
('pools', 0, 0, 0),
('ports', 0, 0, 0),
('rbac_policies', 0, 0, 0),
('routers', 0, 0, 0),
('secgroup-rules', 9, 5, 7),
('secgroups', 0, 0, 0),
('subnet_pools', 0, 0, 0),
('subnets', 0, 0, 0),
],
result,
)
self.compute_client.get_quota_set.assert_not_called()
self.volume_sdk_client.get_quota_set.assert_not_called()
self.network_client.get_quota.assert_called_once_with(
self.projects[0].id,
details=True,
)
self.assertNotCalled(self.network_client.get_quota_default)
def test_quota_show__with_default(self):
arglist = [
'--default',

View file

@ -0,0 +1,5 @@
---
fixes:
- |
Fix ``openstack quota show --usage`` to correctly display resource usage
and reservation.