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.