Skip to content

Commit 6d27b2f

Browse files
committed
Fix networking quota usage show
Quotas details returned from the Neutron service are in different format then quota details returned from Nova and Cinder services. This patch fixes helper function to convert data from Neutron to the same format as data from Nova and Cinder is given. Closes-Bug: #2102513 Change-Id: I18649f6c2ee179b64b7e605f4ea07d4b0c7a1635
1 parent 966aede commit 6d27b2f

3 files changed

Lines changed: 69 additions & 19 deletions

File tree

openstackclient/common/quota.py

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -176,25 +176,37 @@ def get_network_quotas(
176176
default=False,
177177
):
178178
def _network_quota_to_dict(network_quota, detail=False):
179-
if not isinstance(network_quota, dict):
180-
dict_quota = network_quota.to_dict()
181-
else:
182-
dict_quota = network_quota
183-
184-
result = {}
185-
179+
dict_quota = network_quota.to_dict(computed=False)
180+
181+
if not detail:
182+
return dict_quota
183+
184+
# Neutron returns quota details in dict which is in format like:
185+
# {'resource_name': {'in_use': X, 'limit': Y, 'reserved': Z},
186+
# 'resource_name_2': {'in_use': X2, 'limit': Y2, 'reserved': Z2}}
187+
#
188+
# but Nova and Cinder returns quota in different format, like:
189+
# {'resource_name': X,
190+
# 'resource_name_2': X2,
191+
# 'usage': {
192+
# 'resource_name': Y,
193+
# 'resource_name_2': Y2
194+
# },
195+
# 'reserved': {
196+
# 'resource_name': Z,
197+
# 'resource_name_2': Z2
198+
# }}
199+
#
200+
# so we need to make conversion to have data in same format from
201+
# all of the services
202+
result = {"usage": {}, "reservation": {}}
186203
for key, values in dict_quota.items():
187204
if values is None:
188205
continue
189-
190-
# NOTE(slaweq): Neutron returns values with key "used" but Nova for
191-
# example returns same data with key "in_use" instead. Because of
192-
# that we need to convert Neutron key to the same as is returned
193-
# from Nova to make result more consistent
194-
if isinstance(values, dict) and 'used' in values:
195-
values['in_use'] = values.pop("used")
196-
197-
result[key] = values
206+
if isinstance(values, dict):
207+
result[key] = values['limit']
208+
result["reservation"][key] = values['reserved']
209+
result["usage"][key] = values['used']
198210

199211
return result
200212

@@ -756,6 +768,19 @@ def take_action(self, parsed_args):
756768
)
757769

758770
info = {}
771+
if parsed_args.usage:
772+
info["reservation"] = compute_quota_info.pop("reservation", {})
773+
info["reservation"].update(
774+
volume_quota_info.pop("reservation", {})
775+
)
776+
info["reservation"].update(
777+
network_quota_info.pop("reservation", {})
778+
)
779+
780+
info["usage"] = compute_quota_info.pop("usage", {})
781+
info["usage"].update(volume_quota_info.pop("usage", {}))
782+
info["usage"].update(network_quota_info.pop("usage", {}))
783+
759784
info.update(compute_quota_info)
760785
info.update(volume_quota_info)
761786
info.update(network_quota_info)

openstackclient/tests/functional/common/test_quota.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ def test_quota_show_usage_option(self):
250250
row_headers = [str(r) for r in row.keys()]
251251
self.assertEqual(sorted(expected_headers), sorted(row_headers))
252252
resources.append(row['Resource'])
253+
for header in expected_headers[1:]:
254+
self.assertIsInstance(row[header], int)
253255
# Ensure that returned quota has network quota...
254256
self.assertIn("networks", resources)
255257
# ...and compute quota

openstackclient/tests/unit/common/test_quota.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,23 @@ def test_quota_set_with_no_force(self):
955955

956956

957957
class TestQuotaShow(TestQuota):
958+
_network_quota_details = {
959+
'floating_ips': {'limit': 0, 'reserved': 0, 'used': 0},
960+
'health_monitors': {'limit': 0, 'reserved': 0, 'used': 0},
961+
'l7_policies': {'limit': 0, 'reserved': 0, 'used': 0},
962+
'listeners': {'limit': 0, 'reserved': 0, 'used': 0},
963+
'load_balancers': {'limit': 0, 'reserved': 0, 'used': 0},
964+
'networks': {'limit': 0, 'reserved': 0, 'used': 0},
965+
'pools': {'limit': 0, 'reserved': 0, 'used': 0},
966+
'ports': {'limit': 0, 'reserved': 0, 'used': 0},
967+
'rbac_policies': {'limit': 0, 'reserved': 0, 'used': 0},
968+
'routers': {'limit': 0, 'reserved': 0, 'used': 0},
969+
'security_group_rules': {'limit': 0, 'reserved': 0, 'used': 0},
970+
'security_groups': {'limit': 0, 'reserved': 0, 'used': 0},
971+
'subnet_pools': {'limit': 0, 'reserved': 0, 'used': 0},
972+
'subnets': {'limit': 0, 'reserved': 0, 'used': 0},
973+
}
974+
958975
def setUp(self):
959976
super().setUp()
960977

@@ -980,9 +997,15 @@ def setUp(self):
980997
self.default_volume_quotas
981998
)
982999

983-
self.network_client.get_quota.return_value = (
984-
sdk_fakes.generate_fake_resource(_network_quota_set.Quota)
985-
)
1000+
def get_network_quota_mock(*args, **kwargs):
1001+
if kwargs.get("details"):
1002+
return sdk_fakes.generate_fake_resource(
1003+
_network_quota_set.QuotaDetails,
1004+
**self._network_quota_details,
1005+
)
1006+
return sdk_fakes.generate_fake_resource(_network_quota_set.Quota)
1007+
1008+
self.network_client.get_quota.side_effect = get_network_quota_mock
9861009
self.default_network_quotas = sdk_fakes.generate_fake_resource(
9871010
_network_quota_set.QuotaDefault
9881011
)

0 commit comments

Comments
 (0)