From 9ea081ef6ce29b1bfd75b8d6598cc25ef18f1202 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Sat, 9 Aug 2014 06:21:19 +0900 Subject: [PATCH] Display Network panels based on neutron ext-list Neutron features like LBaaS, FWaaS or VPNaaS are provided as extensions in Neutron. This commit changes these features are enabled only when they are included in the extension list from Neutron. It also change the default settings of enable_lb/firewall/vpn to True. The default of these settings were set to False to avoid confusion to users because LB/FW/VPNaaS are optional features in Neutron. By this commit corresponding features in Horizon are enabled dynamically, so it is reasonable to change the default to True. This commit introduces Horizon version of override_settings "update_settings" decorator which allows override an item in dict. Django original override_settings replaces a dict completely, however OpenStack dashboard setting has many dictionary configuration and there are test case where we want to override only one item in a dictionary and keep other items in the dictionary. This version of override_settings allows this. DocImpact Implements blueprint neutron-feature-control-with-ext-list Change-Id: I19424d448c800524de0ee8ac769974272dbb84a0 --- doc/source/topics/settings.rst | 53 ++++++++++++++----- openstack_dashboard/api/neutron.py | 15 +++++- .../dashboards/admin/networks/tests.py | 25 +++++---- .../dashboards/identity/projects/tests.py | 7 ++- .../access_and_security/floating_ips/tests.py | 3 +- .../dashboards/project/firewalls/panel.py | 19 +++++-- .../dashboards/project/instances/tests.py | 28 +++++----- .../dashboards/project/loadbalancers/panel.py | 20 ++++--- .../dashboards/project/networks/tests.py | 33 +++++++----- .../dashboards/project/overview/tests.py | 11 ++-- .../dashboards/project/vpn/panel.py | 17 ++++-- .../local/local_settings.py.example | 6 +-- openstack_dashboard/test/helpers.py | 28 ++++++++++ openstack_dashboard/test/settings.py | 12 +++-- 14 files changed, 194 insertions(+), 83 deletions(-) diff --git a/doc/source/topics/settings.rst b/doc/source/topics/settings.rst index d9d61735a5..6257c984ee 100644 --- a/doc/source/topics/settings.rst +++ b/doc/source/topics/settings.rst @@ -495,10 +495,10 @@ Default:: { 'enable_router': True, 'enable_distributed_router': False, - 'enable_lb': False, + 'enable_lb': True, 'enable_quotas': False, - 'enable_firewall': False, - 'enable_vpn': False, + 'enable_firewall': True, + 'enable_vpn': True, 'profile_support': None, 'supported_provider_types': ["*"], 'segmentation_id_range': None @@ -537,10 +537,20 @@ option appropriately depending on your deployment. .. versionadded:: 2013.1(Grizzly) -Default: ``False`` +(Deprecated) -Enable or disable the load balancer panel. This option should be enabled only -when your Neutron deployment supports LBaaS. +Default: ``True`` + +Enables the load balancer panel. load balancer panel will be enabled +when this option is True and your Neutron deployment supports +LBaaS. If you want to disable load balancer panel even when your +Neutron supports LBaaS, set it to False. + +This option is now marked as "deprecated" and will be removed in +Kilo or later release. The load balancer panel is now enabled only +when LBaaS feature is available in Neutron and this option is no +longer needed. We suggest not to use this option to disable the +load balancer panel from now on. ``supported_provider_types``: @@ -581,17 +591,36 @@ and quota_driver should be DbQuotaDriver (default config). ``enable_firewall``: -Default: ``False`` +(Deprecated) -Enables the firewall panel. This option should be enabled when your Neutron -deployment supports LBaaS. +Default: ``True`` + +Enables the firewall panel. firewall panel will be enabled when this +option is True and your Neutron deployment supports FWaaS. If you want +to disable firewall panel even when your Neutron supports FWaaS, set +it to False. + +This option is now marked as "deprecated" and will be removed in +Kilo or later release. The firewall panel is now enabled only +when FWaaS feature is available in Neutron and this option is no +longer needed. We suggest not to use this option to disable the +firewall panel from now on. ``enable_vpn``: -Default: ``False`` +(Deprecated) -Enables the VPN panel. This option should be enabled when your Neutron -deployment supports VPNaaS. +Default: ``True`` + +Enables the VPN panel. VPN panel will be enabled when this option is True +and your Neutron deployment supports VPNaaS. If you want to disable +VPN panel even when your Neutron supports VPNaaS, set it to False. + +This option is now marked as "deprecated" and will be removed in +Kilo or later release. The VPN panel is now enabled only +when VPNaaS feature is available in Neutron and this option is no +longer needed. We suggest not to use this option to disable the +VPN panel from now on. ``profile_support``: diff --git a/openstack_dashboard/api/neutron.py b/openstack_dashboard/api/neutron.py index 06b1782fb4..6744df5266 100644 --- a/openstack_dashboard/api/neutron.py +++ b/openstack_dashboard/api/neutron.py @@ -882,10 +882,21 @@ def is_extension_supported(request, extension_alias): return False +def is_enabled_by_config(name, default=True): + network_config = (getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) or + getattr(settings, 'OPENSTACK_QUANTUM_NETWORK', {})) + return network_config.get(name, default) + + +@memoized +def is_service_enabled(request, config_name, ext_name): + return (is_enabled_by_config(config_name) and + is_extension_supported(request, ext_name)) + + @memoized def is_quotas_extension_supported(request): - network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) - if (network_config.get('enable_quotas', False) and + if (is_enabled_by_config('enable_quotas', False) and is_extension_supported(request, 'quotas')): return True else: diff --git a/openstack_dashboard/dashboards/admin/networks/tests.py b/openstack_dashboard/dashboards/admin/networks/tests.py index 603b16ff5c..b7f5c930bc 100644 --- a/openstack_dashboard/dashboards/admin/networks/tests.py +++ b/openstack_dashboard/dashboards/admin/networks/tests.py @@ -14,7 +14,6 @@ from django.core.urlresolvers import reverse from django import http -from django.test.utils import override_settings from horizon.workflows import views @@ -263,7 +262,8 @@ class NetworkTests(test.BaseAdminViewTests): self.assertTemplateUsed(res, 'admin/networks/create.html') - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_get_with_profile(self): self.test_network_create_get(test_with_profile=True) @@ -311,7 +311,8 @@ class NetworkTests(test.BaseAdminViewTests): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_post_with_profile(self): self.test_network_create_post(test_with_profile=True) @@ -359,7 +360,8 @@ class NetworkTests(test.BaseAdminViewTests): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_post_network_exception_with_profile(self): self.test_network_create_post_network_exception( test_with_profile=True) @@ -420,8 +422,9 @@ class NetworkTests(test.BaseAdminViewTests): @test.create_stubs({api.neutron: ('list_extensions',), api.keystone: ('tenant_list',)}) - @override_settings(OPENSTACK_NEUTRON_NETWORK={ - 'segmentation_id_range': {'vxlan': [10, 20]}}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={ + 'segmentation_id_range': {'vxlan': [10, 20]}}) def test_network_create_vxlan_segmentation_id_custom(self): tenants = self.tenants.list() tenant_id = self.tenants.first().id @@ -449,8 +452,9 @@ class NetworkTests(test.BaseAdminViewTests): @test.create_stubs({api.neutron: ('list_extensions',), api.keystone: ('tenant_list',)}) - @override_settings(OPENSTACK_NEUTRON_NETWORK={ - 'supported_provider_types': []}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={ + 'supported_provider_types': []}) def test_network_create_no_provider_types(self): tenants = self.tenants.list() extensions = self.api_extensions.list() @@ -469,8 +473,9 @@ class NetworkTests(test.BaseAdminViewTests): @test.create_stubs({api.neutron: ('list_extensions',), api.keystone: ('tenant_list',)}) - @override_settings(OPENSTACK_NEUTRON_NETWORK={ - 'supported_provider_types': ['local', 'flat', 'gre']}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={ + 'supported_provider_types': ['local', 'flat', 'gre']}) def test_network_create_unsupported_provider_types(self): tenants = self.tenants.list() extensions = self.api_extensions.list() diff --git a/openstack_dashboard/dashboards/identity/projects/tests.py b/openstack_dashboard/dashboards/identity/projects/tests.py index dd2846b14f..bd1a3f3d81 100644 --- a/openstack_dashboard/dashboards/identity/projects/tests.py +++ b/openstack_dashboard/dashboards/identity/projects/tests.py @@ -20,7 +20,6 @@ import os import django from django.core.urlresolvers import reverse from django import http -from django.test.utils import override_settings from django.utils import timezone from django.utils import unittest @@ -233,7 +232,7 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests): api.neutron: ('is_extension_supported', 'tenant_quota_get'), quotas: ('get_default_quota_data',)}) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_add_project_get_with_neutron(self): quota = self.quotas.first() neutron_quotas = self.neutron_quotas.first() @@ -376,7 +375,7 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests): @test.create_stubs({api.neutron: ('is_extension_supported', 'tenant_quota_update')}) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_add_project_post_with_neutron(self): quota_data = self.neutron_quotas.first() neutron_updated_quota = dict([(key, quota_data.get(key).limit) @@ -1058,7 +1057,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests): @test.create_stubs({api.neutron: ('is_extension_supported', 'tenant_quota_get', 'tenant_quota_update')}) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_update_project_save_with_neutron(self): quota_data = self.neutron_quotas.first() neutron_updated_quota = dict([(key, quota_data.get(key).limit) diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py index e43618fecb..97ce4e2631 100644 --- a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py +++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py @@ -19,7 +19,6 @@ from django.core.urlresolvers import reverse from django import http -from django.test.utils import override_settings from mox import IsA # noqa @@ -190,7 +189,7 @@ class FloatingIpNeutronViewTests(FloatingIpViewTests): 'tenant_floating_ip_list'), api.neutron: ('is_extension_supported', 'tenant_quota_get')}) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_correct_quotas_displayed(self): servers = [s for s in self.servers.list() if s.tenant_id == self.request.user.tenant_id] diff --git a/openstack_dashboard/dashboards/project/firewalls/panel.py b/openstack_dashboard/dashboards/project/firewalls/panel.py index 831871652e..e8a4e6b2c6 100644 --- a/openstack_dashboard/dashboards/project/firewalls/panel.py +++ b/openstack_dashboard/dashboards/project/firewalls/panel.py @@ -10,11 +10,11 @@ # License for the specific language governing permissions and limitations # under the License. -from django.conf import settings from django.utils.translation import ugettext_lazy as _ import horizon +from openstack_dashboard.api import neutron from openstack_dashboard.dashboards.project import dashboard @@ -23,8 +23,17 @@ class Firewall(horizon.Panel): slug = "firewalls" permissions = ('openstack.services.network',) + def can_access(self, context): + request = context['request'] + if not request.user.has_perms(self.permissions): + return False + if not neutron.is_service_enabled(request, + config_name='enable_firewall', + ext_name='fwaas'): + return False + if not super(Firewall, self).can_access(context): + return False + return True -if getattr(settings, - 'OPENSTACK_NEUTRON_NETWORK', - {}).get('enable_firewall', False): - dashboard.Project.register(Firewall) + +dashboard.Project.register(Firewall) diff --git a/openstack_dashboard/dashboards/project/instances/tests.py b/openstack_dashboard/dashboards/project/instances/tests.py index 7df4a9891f..684a4e6230 100644 --- a/openstack_dashboard/dashboards/project/instances/tests.py +++ b/openstack_dashboard/dashboards/project/instances/tests.py @@ -1359,7 +1359,7 @@ class InstanceTests(helpers.TestCase): def test_launch_instance_get_with_only_one_network(self): self.test_launch_instance_get(only_one_network=True) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_instance_get_with_profile(self): self.test_launch_instance_get(test_with_profile=True) @@ -1448,7 +1448,7 @@ class InstanceTests(helpers.TestCase): for volume in bootable_volumes: self.assertTrue(volume in volume_sources_ids) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_instance_get_bootable_volumes_with_profile(self): self.test_launch_instance_get_bootable_volumes(test_with_profile=True) @@ -1574,7 +1574,7 @@ class InstanceTests(helpers.TestCase): def test_launch_instance_post_no_disk_config_supported(self): self.test_launch_instance_post(disk_config=False) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_instance_post_with_profile(self): self.test_launch_instance_post(test_with_profile=True) @@ -1696,7 +1696,7 @@ class InstanceTests(helpers.TestCase): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_instance_post_boot_from_volume_with_profile(self): self.test_launch_instance_post_boot_from_volume(test_with_profile=True) @@ -1823,7 +1823,7 @@ class InstanceTests(helpers.TestCase): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_lnch_inst_post_no_images_avail_boot_from_vol_with_profile(self): self.test_launch_instance_post_no_images_available_boot_from_volume( @@ -1916,7 +1916,7 @@ class InstanceTests(helpers.TestCase): self.assertFormErrors(res, 1, "You must select an image.") self.assertTemplateUsed(res, views.WorkflowView.template_name) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_instance_post_no_images_available_with_profile(self): self.test_launch_instance_post_no_images_available( @@ -1984,7 +1984,7 @@ class InstanceTests(helpers.TestCase): self.assertTemplateUsed(res, views.WorkflowView.template_name) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_flavorlist_error_with_profile(self): self.test_launch_flavorlist_error(test_with_profile=True) @@ -2103,7 +2103,7 @@ class InstanceTests(helpers.TestCase): self.assertRedirectsNoFollow(res, INDEX_URL) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_form_keystone_exception_with_profile(self): self.test_launch_form_keystone_exception(test_with_profile=True) @@ -2318,7 +2318,7 @@ class InstanceTests(helpers.TestCase): def test_launch_form_ram_cores_count_error(self): self._test_launch_form_count_error('both', 1, test_with_profile=False) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_form_instance_count_error_with_profile(self): self.test_launch_form_instance_count_error(test_with_profile=True) @@ -2437,13 +2437,13 @@ class InstanceTests(helpers.TestCase): self._test_launch_form_instance_requirement_error(image, flavor, test_with_profile) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_form_instance_requirement_error_disk_with_profile(self): self.test_launch_form_instance_requirement_error_disk( test_with_profile=True) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_form_instance_requirement_error_ram_with_profile(self): self.test_launch_form_instance_requirement_error_ram( @@ -2557,13 +2557,13 @@ class InstanceTests(helpers.TestCase): self._test_launch_form_instance_volume_size(image, 1.5, msg, test_with_profile) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_form_instance_volume_size_error_with_profile(self): self.test_launch_form_instance_volume_size_error( test_with_profile=True) - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_launch_form_instance_non_int_volume_size_with_profile(self): self.test_launch_form_instance_non_int_volume_size( @@ -2723,7 +2723,7 @@ class InstanceTests(helpers.TestCase): html=True, msg_prefix="The default key pair was not selected.") - @django.test.utils.override_settings( + @helpers.update_settings( OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_select_default_keypair_if_only_one_with_profile(self): self.test_select_default_keypair_if_only_one(test_with_profile=True) diff --git a/openstack_dashboard/dashboards/project/loadbalancers/panel.py b/openstack_dashboard/dashboards/project/loadbalancers/panel.py index fc7f3c6c6b..af24570fa0 100644 --- a/openstack_dashboard/dashboards/project/loadbalancers/panel.py +++ b/openstack_dashboard/dashboards/project/loadbalancers/panel.py @@ -10,11 +10,11 @@ # License for the specific language governing permissions and limitations # under the License. -from django.conf import settings from django.utils.translation import ugettext_lazy as _ import horizon +from openstack_dashboard.api import neutron from openstack_dashboard.dashboards.project import dashboard @@ -23,11 +23,17 @@ class LoadBalancer(horizon.Panel): slug = "loadbalancers" permissions = ('openstack.services.network',) + def can_access(self, context): + request = context['request'] + if not request.user.has_perms(self.permissions): + return False + if not neutron.is_service_enabled(request, + config_name='enable_lb', + ext_name='lbaas'): + return False + if not super(LoadBalancer, self).can_access(context): + return False + return True -network_config = ( - getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) or - getattr(settings, 'OPENSTACK_QUANTUM_NETWORK', {}) -) -if network_config.get('enable_lb'): - dashboard.Project.register(LoadBalancer) +dashboard.Project.register(LoadBalancer) diff --git a/openstack_dashboard/dashboards/project/networks/tests.py b/openstack_dashboard/dashboards/project/networks/tests.py index 81d73838bf..c4c4830c72 100644 --- a/openstack_dashboard/dashboards/project/networks/tests.py +++ b/openstack_dashboard/dashboards/project/networks/tests.py @@ -14,7 +14,6 @@ from django.core.urlresolvers import reverse from django import http -from django.test.utils import override_settings from django.utils.html import escape from horizon.workflows import views @@ -291,7 +290,8 @@ class NetworkTests(test.TestCase): ''] self.assertQuerysetEqual(workflow.steps, expected_objs) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_get_with_profile(self): self.test_network_create_get(test_with_profile=True) @@ -325,7 +325,8 @@ class NetworkTests(test.TestCase): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_post_with_profile(self): self.test_network_create_post(test_with_profile=True) @@ -372,11 +373,12 @@ class NetworkTests(test.TestCase): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_post_with_subnet_w_profile(self): self.test_network_create_post_with_subnet(test_with_profile=True) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_ipv6': False}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_ipv6': False}) def test_create_network_with_ipv6_disabled(self): self.test_network_create_post_with_subnet(test_with_ipv6=False) @@ -410,7 +412,8 @@ class NetworkTests(test.TestCase): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_post_nw_exception_w_profile(self): self.test_network_create_post_network_exception( test_with_profile=True) @@ -447,7 +450,8 @@ class NetworkTests(test.TestCase): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_nw_create_post_w_subnet_nw_exception_w_profile(self): self.test_network_create_post_with_subnet_network_exception( test_with_profile=True) @@ -496,7 +500,8 @@ class NetworkTests(test.TestCase): self.assertNoFormErrors(res) self.assertRedirectsNoFollow(res, INDEX_URL) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_nw_create_post_w_subnet_subnet_exception_w_profile(self): self.test_network_create_post_with_subnet_subnet_exception( test_with_profile=True) @@ -526,7 +531,8 @@ class NetworkTests(test.TestCase): self.assertContains(res, escape('Specify "Network Address" or ' 'clear "Create Subnet" checkbox.')) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_nw_create_post_w_subnet_no_cidr_w_profile(self): self.test_network_create_post_with_subnet_nocidr( test_with_profile=True) @@ -558,7 +564,8 @@ class NetworkTests(test.TestCase): expected_msg = "The subnet in the Network Address is too small (/32)." self.assertContains(res, expected_msg) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_nw_create_post_w_subnet_cidr_without_mask_w_profile(self): self.test_network_create_post_with_subnet_cidr_without_mask( test_with_profile=True) @@ -592,7 +599,8 @@ class NetworkTests(test.TestCase): expected_msg = 'Network Address and IP version are inconsistent.' self.assertContains(res, expected_msg) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_post_with_subnet_cidr_inconsistent_w_profile(self): self.test_network_create_post_with_subnet_cidr_inconsistent( test_with_profile=True) @@ -625,7 +633,8 @@ class NetworkTests(test.TestCase): self.assertContains(res, 'Gateway IP and IP version are inconsistent.') - @override_settings(OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) + @test.update_settings( + OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'}) def test_network_create_post_with_subnet_gw_inconsistent_w_profile(self): self.test_network_create_post_with_subnet_gw_inconsistent( test_with_profile=True) diff --git a/openstack_dashboard/dashboards/project/overview/tests.py b/openstack_dashboard/dashboards/project/overview/tests.py index de0aa1968f..ed487c04c0 100644 --- a/openstack_dashboard/dashboards/project/overview/tests.py +++ b/openstack_dashboard/dashboards/project/overview/tests.py @@ -20,7 +20,6 @@ import datetime from django.core.urlresolvers import reverse from django import http -from django.test.utils import override_settings from django.utils import timezone from mox import IsA # noqa @@ -273,15 +272,15 @@ class UsageViewTests(test.TestCase): self.assertTemplateUsed(res, 'project/overview/usage.html') self.assertTrue(isinstance(res.context['usage'], usage.ProjectUsage)) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_usage_with_neutron(self): self._test_usage_with_neutron(neutron_sg_enabled=True) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_usage_with_neutron_nova_security_group(self): self._test_usage_with_neutron(neutron_sg_enabled=False) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_usage_with_neutron_floating_ip_disabled(self): self._test_usage_with_neutron(neutron_fip_enabled=False) @@ -344,7 +343,7 @@ class UsageViewTests(test.TestCase): max_security_groups = res_limits['maxSecurityGroups'] self.assertEqual(max_security_groups, max_sg_expected) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_usage_with_neutron_quotas_ext_error(self): self._test_usage_with_neutron_prepare() api.neutron.is_extension_supported( @@ -353,7 +352,7 @@ class UsageViewTests(test.TestCase): self._test_usage_with_neutron_check(max_fip_expected=float("inf"), max_sg_expected=float("inf")) - @override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) + @test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True}) def test_usage_with_neutron_sg_ext_error(self): self._test_usage_with_neutron_prepare() api.neutron.is_extension_supported( diff --git a/openstack_dashboard/dashboards/project/vpn/panel.py b/openstack_dashboard/dashboards/project/vpn/panel.py index 38daac3dba..1f33a0b90a 100644 --- a/openstack_dashboard/dashboards/project/vpn/panel.py +++ b/openstack_dashboard/dashboards/project/vpn/panel.py @@ -14,11 +14,11 @@ # # @author: Tatiana Mazur -from django.conf import settings from django.utils.translation import ugettext_lazy as _ import horizon +from openstack_dashboard.api import neutron from openstack_dashboard.dashboards.project import dashboard @@ -27,6 +27,17 @@ class VPN(horizon.Panel): slug = 'vpn' permissions = ('openstack.services.network',) + def can_access(self, context): + request = context['request'] + if not request.user.has_perms(self.permissions): + return False + if not neutron.is_service_enabled(request, + config_name='enable_vpn', + ext_name='vpnaas'): + return False + if not super(VPN, self).can_access(context): + return False + return True -if getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}).get('enable_vpn', False): - dashboard.Project.register(VPN) + +dashboard.Project.register(VPN) diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example index f748dc84ea..c1c5ea55e8 100644 --- a/openstack_dashboard/local/local_settings.py.example +++ b/openstack_dashboard/local/local_settings.py.example @@ -179,12 +179,12 @@ OPENSTACK_CINDER_FEATURES = { # balancer service, security groups, quotas, VPN service. OPENSTACK_NEUTRON_NETWORK = { 'enable_router': True, - 'enable_lb': False, - 'enable_firewall': False, 'enable_quotas': True, - 'enable_vpn': False, 'enable_ipv6': True, 'enable_distributed_router': True, + 'enable_lb': True, + 'enable_firewall': True, + 'enable_vpn': True, # The profile_support option is used to detect if an external router can be # configured via the dashboard. When using specific plugins the # profile_support can be turned on if needed. diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py index 6d65ef0d37..20498022dc 100644 --- a/openstack_dashboard/test/helpers.py +++ b/openstack_dashboard/test/helpers.py @@ -16,6 +16,8 @@ # License for the specific language governing permissions and limitations # under the License. +import collections +import copy from functools import wraps # noqa import os @@ -28,6 +30,7 @@ from django.core.handlers import wsgi from django.core import urlresolvers from django import http from django.test.client import RequestFactory # noqa +from django.test import utils as django_test_utils from django.utils.importlib import import_module # noqa from django.utils import unittest import glanceclient @@ -488,3 +491,28 @@ class PluginTestCase(TestCase): urlresolvers.clear_url_caches() reload(import_module(settings.ROOT_URLCONF)) base.Horizon._urls() + + +class update_settings(django_test_utils.override_settings): + """override_settings which allows override an item in dict. + + django original override_settings replaces a dict completely, + however OpenStack dashboard setting has many dictionary configuration + and there are test case where we want to override only one item in + a dictionary and keep other items in the dictionary. + This version of override_settings allows this if keep_dict is True. + + If keep_dict False is specified, the original behavior of + Django override_settings is used. + """ + + def __init__(self, keep_dict=True, **kwargs): + if keep_dict: + for key, new_value in kwargs.items(): + value = getattr(settings, key, None) + if (isinstance(new_value, collections.Mapping) and + isinstance(value, collections.Mapping)): + copied = copy.copy(value) + copied.update(new_value) + kwargs[key] = copied + super(update_settings, self).__init__(**kwargs) diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py index 63f92d550b..7db494e03a 100644 --- a/openstack_dashboard/test/settings.py +++ b/openstack_dashboard/test/settings.py @@ -105,10 +105,16 @@ OPENSTACK_CINDER_FEATURES = { OPENSTACK_NEUTRON_NETWORK = { 'enable_router': True, - 'enable_lb': True, - 'enable_firewall': True, 'enable_quotas': False, # Enabled in specific tests only - 'enable_vpn': True, + # Parameters below (enable_lb, enable_firewall, enable_vpn) + # control if these panels are displayed or not, + # i.e. they only affect the navigation menu. + # These panels are registered even if enable_XXX is False, + # so we don't need to set them to True in most unit tests + # to avoid stubbing neutron extension check calls. + 'enable_lb': False, + 'enable_firewall': False, + 'enable_vpn': False, 'profile_support': None, 'enable_distributed_router': False, # 'profile_support': 'cisco'