From 22741aaa3eb36a98e5c599833655e0274f58e544 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Mon, 26 Oct 2020 16:53:55 +0900 Subject: [PATCH] Drop the legacy way to retrieve neutron quotas and usages quota_details neutron API extension was implemented since Pike and the enough migration period has passed. We have not received any negative feedback on the removal of the legacy way since its deprecation in Ussuri release. Change-Id: Ia249e83a7d40af873d6509c932b11cb9bb7a9497 --- .../test/unit/usage/test_quotas.py | 156 +----------------- openstack_dashboard/usage/quotas.py | 81 +-------- ...neutron-quota-legacy-1efd1f1924ae3489.yaml | 7 + 3 files changed, 15 insertions(+), 229 deletions(-) create mode 100644 releasenotes/notes/drop-neutron-quota-legacy-1efd1f1924ae3489.yaml diff --git a/openstack_dashboard/test/unit/usage/test_quotas.py b/openstack_dashboard/test/unit/usage/test_quotas.py index d663525ec1..3538b8a8d6 100644 --- a/openstack_dashboard/test/unit/usage/test_quotas.py +++ b/openstack_dashboard/test/unit/usage/test_quotas.py @@ -432,23 +432,6 @@ class QuotaTests(test.APITestCase): else: self.mock_cinder_tenant_absolute_limits.assert_not_called() - def test_tenant_quota_usages_neutron_with_target_network_resources(self): - self._test_tenant_quota_usages_neutron_with_target( - targets=('network', 'subnet', 'router',)) - - def test_tenant_quota_usages_neutron_with_target_security_groups(self): - self._test_tenant_quota_usages_neutron_with_target( - targets=('security_group',)) - - def test_tenant_quota_usages_neutron_with_target_floating_ips(self): - self._test_tenant_quota_usages_neutron_with_target( - targets=('floatingip',)) - - def test_tenant_quota_usages_neutron_with_target_security_group_rule(self): - self._test_tenant_quota_usages_neutron_with_target( - targets=('security_group_rule',) - ) - def _list_security_group_rules(self): security_groups = self.security_groups.list() security_group_rules = [] @@ -464,7 +447,7 @@ class QuotaTests(test.APITestCase): api.neutron: ('is_extension_supported', 'is_quotas_extension_supported', 'tenant_quota_detail_get')}) - def test_tenant_quota_usages_non_legacy(self): + def test_tenant_quota_usages_network(self): self._mock_service_enabled(network_enabled=True) self.mock_is_extension_supported.return_value = True self.mock_is_quotas_extension_supported.return_value = True @@ -517,149 +500,14 @@ class QuotaTests(test.APITestCase): # as _mock_service_enabled() requires it, but it is never called here. self.mock_is_volume_service_enabled.assert_not_called() self.mock_is_extension_supported.assert_has_calls([ - # network - mock.call(test.IsHttpRequest(), 'quota_details'), - # subnet - mock.call(test.IsHttpRequest(), 'quota_details'), - # port - mock.call(test.IsHttpRequest(), 'quota_details'), - # router mock.call(test.IsHttpRequest(), 'router'), - mock.call(test.IsHttpRequest(), 'quota_details'), - # floating IP - mock.call(test.IsHttpRequest(), 'quota_details'), - # security group mock.call(test.IsHttpRequest(), 'security-group'), - mock.call(test.IsHttpRequest(), 'quota_details'), - # security group rule mock.call(test.IsHttpRequest(), 'security-group'), - mock.call(test.IsHttpRequest(), 'quota_details'), ]) - self.assertEqual(10, self.mock_is_extension_supported.call_count) + self.assertEqual(3, self.mock_is_extension_supported.call_count) self.assert_mock_multiple_calls_with_same_arguments( self.mock_is_quotas_extension_supported, len(test_data), mock.call(test.IsHttpRequest())) self.assert_mock_multiple_calls_with_same_arguments( self.mock_tenant_quota_detail_get, len(test_data), mock.call(test.IsHttpRequest(), self.request.user.tenant_id)) - - @test.create_mocks({api.base: ('is_service_enabled',), - cinder: ('is_volume_service_enabled',), - api.neutron: ('floating_ip_supported', - 'tenant_floating_ip_list', - 'security_group_list', - 'is_extension_supported', - 'is_router_enabled', - 'is_quotas_extension_supported', - 'tenant_quota_get', - 'network_list', - 'subnet_list', - 'router_list')}) - def _test_tenant_quota_usages_neutron_with_target(self, targets): - self._mock_service_enabled(network_enabled=True) - if 'security_group' in targets or 'security_group_rule' in targets: - self.mock_is_extension_supported.side_effect = [True, False] - else: - self.mock_is_extension_supported.side_effect = [False] - self.mock_is_router_enabled.return_value = True - self.mock_is_quotas_extension_supported.return_value = True - self.mock_tenant_quota_get.return_value = self.neutron_quotas.first() - - if 'network' in targets: - self.mock_network_list.return_value = self.networks.list() - if 'subnet' in targets: - self.mock_subnet_list.return_value = self.subnets.list() - if 'router' in targets: - self.mock_router_list.return_value = self.routers.list() - if 'floatingip' in targets: - self.mock_tenant_floating_ip_list.return_value = \ - self.floating_ips.list() - if 'security_group' in targets or 'security_group_rule' in targets: - self.mock_security_group_list.return_value = \ - self.security_groups.list() - - quota_usages = quotas.tenant_quota_usages(self.request, - targets=targets) - - network_used = len(self.networks.list()) - subnet_used = len(self.subnets.list()) - router_used = len(self.routers.list()) - fip_used = len(self.floating_ips.list()) - - security_groups = self.security_groups.list() - sg_used = len(security_groups) - sgr_used = sum(map( - lambda group: len(group.security_group_rules), - security_groups - )) - - expected = { - 'network': {'used': network_used, 'quota': 10, - 'available': 10 - network_used}, - 'subnet': {'used': subnet_used, 'quota': 10, - 'available': 10 - subnet_used}, - 'router': {'used': router_used, 'quota': 10, - 'available': 10 - router_used}, - 'security_group': {'used': sg_used, 'quota': 20, - 'available': 20 - sg_used}, - 'security_group_rule': { - 'quota': 100, 'used': sgr_used, 'available': 100 - sgr_used - }, - 'floatingip': {'used': fip_used, 'quota': 50, - 'available': 50 - fip_used}, - } - expected = dict((k, v) for k, v in expected.items() if k in targets) - - # Compare internal structure of usages to expected. - self.assertEqual(expected, quota_usages.usages) - # Compare available resources - self.assertAvailableQuotasEqual(expected, quota_usages.usages) - - self._check_service_enabled({'network': 1}) - - if 'security_group' in targets or 'security_group_rule' in targets: - self.mock_is_extension_supported.assert_has_calls([ - mock.call(test.IsHttpRequest(), 'security-group'), - mock.call(test.IsHttpRequest(), 'quota_details'), - ]) - self.assertEqual(2, self.mock_is_extension_supported.call_count) - else: - self.mock_is_extension_supported.assert_called_once_with( - test.IsHttpRequest(), 'quota_details') - if 'floatingip' in targets or 'router' in targets: - self.mock_is_router_enabled.assert_called_once_with( - test.IsHttpRequest()) - else: - self.mock_is_router_enabled.assert_not_called() - self.mock_is_quotas_extension_supported.assert_called_once_with( - test.IsHttpRequest()) - self.mock_tenant_quota_get.assert_called_once_with( - test.IsHttpRequest(), '1') - if 'network' in targets: - self.mock_network_list.assert_called_once_with( - test.IsHttpRequest(), - tenant_id=self.request.user.tenant_id) - else: - self.mock_network_list.assert_not_called() - if 'subnet' in targets: - self.mock_subnet_list.assert_called_once_with( - test.IsHttpRequest(), - tenant_id=self.request.user.tenant_id) - else: - self.mock_subnet_list.assert_not_called() - if 'router' in targets: - self.mock_router_list.assert_called_once_with( - test.IsHttpRequest(), - tenant_id=self.request.user.tenant_id) - else: - self.mock_router_list.assert_not_called() - if 'floatingip' in targets: - self.mock_tenant_floating_ip_list.assert_called_once_with( - test.IsHttpRequest()) - else: - self.mock_tenant_floating_ip_list.assert_not_called() - if 'security_group' in targets or 'security_group_rule' in targets: - self.mock_security_group_list.assert_called_once_with( - test.IsHttpRequest()) - else: - self.mock_security_group_list.assert_not_called() diff --git a/openstack_dashboard/usage/quotas.py b/openstack_dashboard/usage/quotas.py index 7986abce96..6f4e32e2fe 100644 --- a/openstack_dashboard/usage/quotas.py +++ b/openstack_dashboard/usage/quotas.py @@ -13,7 +13,6 @@ from collections import defaultdict import itertools import logging -import warnings from django.utils.translation import ugettext_lazy as _ @@ -337,81 +336,13 @@ def _get_tenant_network_usages(request, usages, disabled_quotas, tenant_id): if not enabled_quotas: return - if neutron.is_extension_supported(request, 'quota_details'): - details = neutron.tenant_quota_detail_get(request, tenant_id) - for quota_name in NEUTRON_QUOTA_FIELDS: - if quota_name in disabled_quotas: - continue - detail = details[quota_name] - usages.add_quota(base.Quota(quota_name, detail['limit'])) - usages.tally(quota_name, detail['used'] + detail['reserved']) - else: - _get_tenant_network_usages_legacy( - request, usages, disabled_quotas, tenant_id) - - -def _get_neutron_quota_data(request, qs, disabled_quotas, tenant_id): - tenant_id = tenant_id or request.user.tenant_id - neutron_quotas = neutron.tenant_quota_get(request, tenant_id) - + details = neutron.tenant_quota_detail_get(request, tenant_id) for quota_name in NEUTRON_QUOTA_FIELDS: - if quota_name not in disabled_quotas: - quota_data = neutron_quotas.get(quota_name).limit - qs.add(base.QuotaSet({quota_name: quota_data})) - - return qs - - -# TODO(amotoki): Deprecated in Ussuri. Drop this in Victoria release or later. -def _get_tenant_network_usages_legacy(request, usages, disabled_quotas, - tenant_id): - warnings.warn( - "The legacy way to retrieve neutron resource usage is deprecated " - "in Ussuri release. Horizon will depend on 'quota_details' " - "neutron extension added in Pike release in future.", - DeprecationWarning) - qs = base.QuotaSet() - _get_neutron_quota_data(request, qs, disabled_quotas, tenant_id) - for quota in qs: - usages.add_quota(quota) - - resource_lister = { - 'network': (neutron.network_list, {'tenant_id': tenant_id}), - 'subnet': (neutron.subnet_list, {'tenant_id': tenant_id}), - 'port': (neutron.port_list, {'tenant_id': tenant_id}), - 'router': (neutron.router_list, {'tenant_id': tenant_id}), - 'floatingip': (neutron.tenant_floating_ip_list, {}), - } - - for quota_name, lister_info in resource_lister.items(): - if quota_name not in disabled_quotas: - lister = lister_info[0] - kwargs = lister_info[1] - try: - resources = lister(request, **kwargs) - except Exception: - resources = [] - usages.tally(quota_name, len(resources)) - - # Security groups have to be processed separately so that rules may be - # processed in the same api call and in a single pass - add_sg = 'security_group' not in disabled_quotas - add_sgr = 'security_group_rule' not in disabled_quotas - - if add_sg or add_sgr: - try: - security_groups = neutron.security_group_list(request) - num_rules = sum(len(group['security_group_rules']) - for group in security_groups) - except Exception: - security_groups = [] - num_rules = 0 - - if add_sg: - usages.tally('security_group', len(security_groups)) - - if add_sgr: - usages.tally('security_group_rule', num_rules) + if quota_name in disabled_quotas: + continue + detail = details[quota_name] + usages.add_quota(base.Quota(quota_name, detail['limit'])) + usages.tally(quota_name, detail['used'] + detail['reserved']) @profiler.trace diff --git a/releasenotes/notes/drop-neutron-quota-legacy-1efd1f1924ae3489.yaml b/releasenotes/notes/drop-neutron-quota-legacy-1efd1f1924ae3489.yaml new file mode 100644 index 0000000000..911ce3897d --- /dev/null +++ b/releasenotes/notes/drop-neutron-quota-legacy-1efd1f1924ae3489.yaml @@ -0,0 +1,7 @@ +--- +upgrade: + - | + The legacy way to retrive neutron resource usages was dropped and + horizon now assumes the ``quota_details`` neutron API extension + implemented in Pike release (over three years ago), so we expect + this is available in all Wallaby neutron deployments.