From 11001691308b633abf6cac378ae926677ad0d903 Mon Sep 17 00:00:00 2001 From: Akihiro Motoki Date: Sat, 9 Aug 2014 09:45:56 +0900 Subject: [PATCH] Add a config option to disable Router panel Neutron setup allows operators not to enable Router feautre (by not using Router service plugin in neutron.conf) and some Neutron plugin does not support Router feature. According to bug 1350639 there is also a case where operators want to disable Router panel from their policy. It seems nice we have a option to control Router panel. This commit add a new option 'enable_router' to OPENSTACK_NEUTRON_NETWORK. The default is True since router feature is enabled in most deployments and it is the current default behavior of Horizon. If this option is False, Router panel will disappear. blueprint hide-router-panel-by-config Partial-Bug: #1292022 Closes-Bug: #1350639 Change-Id: If90517bd35c5b18173c54c14a1ba229f97ba4797 --- doc/source/topics/settings.rst | 11 +++ .../dashboards/admin/routers/panel.py | 5 +- .../project/network_topology/tests.py | 80 ++++++++++++------- .../project/network_topology/views.py | 51 +++++++----- .../dashboards/project/routers/panel.py | 5 +- .../local/local_settings.py.example | 1 + openstack_dashboard/test/settings.py | 1 + 7 files changed, 102 insertions(+), 52 deletions(-) diff --git a/doc/source/topics/settings.rst b/doc/source/topics/settings.rst index c526c868da..397cf5c683 100644 --- a/doc/source/topics/settings.rst +++ b/doc/source/topics/settings.rst @@ -493,6 +493,7 @@ by cinder. Currently only the backup service is available. Default:: { + 'enable_router': True, 'enable_distributed_router': False, 'enable_lb': False, 'enable_quotas': False, @@ -507,6 +508,16 @@ A dictionary of settings which can be used to enable optional services provided by Neutron and configure Neutron specific features. The following options are available. +``enable_router``: + +.. versionadded:: 2014.2(Juno) + +Default: ``True`` + +Enable (True) or disable (False) the router panel. If your neutron +has no support for Layer-3 router features, or you do no not wish to +provide the Layer-3 features through the Dashboard, this should be set to +``False``. ``enable_distributed_router``: diff --git a/openstack_dashboard/dashboards/admin/routers/panel.py b/openstack_dashboard/dashboards/admin/routers/panel.py index da039c7515..5a52cb8db5 100644 --- a/openstack_dashboard/dashboards/admin/routers/panel.py +++ b/openstack_dashboard/dashboards/admin/routers/panel.py @@ -12,6 +12,7 @@ # 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 @@ -24,4 +25,6 @@ class Routers(horizon.Panel): slug = 'routers' permissions = ('openstack.services.network',) -dashboard.Admin.register(Routers) +network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) +if network_config.get('enable_router', True): + dashboard.Admin.register(Routers) diff --git a/openstack_dashboard/dashboards/project/network_topology/tests.py b/openstack_dashboard/dashboards/project/network_topology/tests.py index 86535b43fa..17ed550cdb 100644 --- a/openstack_dashboard/dashboards/project/network_topology/tests.py +++ b/openstack_dashboard/dashboards/project/network_topology/tests.py @@ -16,6 +16,7 @@ import json from django.core.urlresolvers import reverse from django import http +import django.test from mox import IsA # noqa @@ -34,6 +35,17 @@ class NetworkTopologyTests(test.TestCase): 'router_list', 'port_list')}) def test_json_view(self): + self._test_json_view() + + @django.test.utils.override_settings( + OPENSTACK_NEUTRON_NETWORK={'enable_router': False}) + @test.create_stubs({api.nova: ('server_list',), + api.neutron: ('network_list_for_tenant', + 'port_list')}) + def test_json_view_router_disabled(self): + self._test_json_view(router_enable=False) + + def _test_json_view(self, router_enable=True): api.nova.server_list( IsA(http.HttpRequest)).AndReturn([self.servers.list(), False]) tenant_networks = [net for net in self.networks.list() @@ -43,17 +55,19 @@ class NetworkTopologyTests(test.TestCase): api.neutron.network_list_for_tenant( IsA(http.HttpRequest), self.tenant.id).AndReturn(tenant_networks) - api.neutron.network_list( - IsA(http.HttpRequest), - **{'router:external': True}).AndReturn(external_networks) + if router_enable: + api.neutron.network_list( + IsA(http.HttpRequest), + **{'router:external': True}).AndReturn(external_networks) # router1 : gateway port not in the port list # router2 : no gateway port # router3 : gateway port included in port list routers = self.routers.list() + self.routers_with_rules.list() - api.neutron.router_list( - IsA(http.HttpRequest), - tenant_id=self.tenant.id).AndReturn(routers) + if router_enable: + api.neutron.router_list( + IsA(http.HttpRequest), + tenant_id=self.tenant.id).AndReturn(routers) api.neutron.port_list( IsA(http.HttpRequest)).AndReturn(self.ports.list()) @@ -79,24 +93,29 @@ class NetworkTopologyTests(test.TestCase): # rotuers # result_router_urls = [(router['id'], router['url']) # for router in data['routers']] - expect_router_urls = [ - {'id': router.id, - 'external_gateway_info': - router.external_gateway_info, - 'name': router.name, - 'status': router.status, - 'url': '/project/routers/%s/' % router.id} - for router in routers] - self.assertEqual(expect_router_urls, data['routers']) + if router_enable: + expect_router_urls = [ + {'id': router.id, + 'external_gateway_info': + router.external_gateway_info, + 'name': router.name, + 'status': router.status, + 'url': '/project/routers/%s/' % router.id} + for router in routers] + self.assertEqual(expect_router_urls, data['routers']) + else: + self.assertFalse(data['routers']) # networks - expect_net_urls = [{'id': net.id, - 'url': None, - 'name': net.name, - 'router:external': net.router__external, - 'subnets': [{'cidr': subnet.cidr} - for subnet in net.subnets]} - for net in external_networks] + expect_net_urls = [] + if router_enable: + expect_net_urls += [{'id': net.id, + 'url': None, + 'name': net.name, + 'router:external': net.router__external, + 'subnets': [{'cidr': subnet.cidr} + for subnet in net.subnets]} + for net in external_networks] expect_net_urls += [{'id': net.id, 'url': '/project/networks/%s/detail' % net.id, 'name': net.name, @@ -119,12 +138,13 @@ class NetworkTopologyTests(test.TestCase): 'status': port.status, 'url': '/project/networks/ports/%s/detail' % port.id} for port in self.ports.list()] - # fake port for router1 gateway (router1 on ext_net) - router1 = routers[0] - ext_net = external_networks[0] - expect_port_urls.append( - {'id': 'gateway%s' % ext_net.id, - 'device_id': router1.id, - 'network_id': ext_net.id, - 'fixed_ips': []}) + if router_enable: + # fake port for router1 gateway (router1 on ext_net) + router1 = routers[0] + ext_net = external_networks[0] + expect_port_urls.append( + {'id': 'gateway%s' % ext_net.id, + 'device_id': router1.id, + 'network_id': ext_net.id, + 'fixed_ips': []}) self.assertEqual(expect_port_urls, data['ports']) diff --git a/openstack_dashboard/dashboards/project/network_topology/views.py b/openstack_dashboard/dashboards/project/network_topology/views.py index 29cf44f8af..07d05d9ed4 100644 --- a/openstack_dashboard/dashboards/project/network_topology/views.py +++ b/openstack_dashboard/dashboards/project/network_topology/views.py @@ -103,17 +103,25 @@ class NetworkTopologyView(TemplateView): def get_context_data(self, **kwargs): context = super(NetworkTopologyView, self).get_context_data(**kwargs) + network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) context['launch_instance_allowed'] = self._has_permission( (("compute", "compute:create"),)) context['create_network_allowed'] = self._has_permission( (("network", "create_network"),)) - context['create_router_allowed'] = self._has_permission( - (("network", "create_router"),)) + context['create_router_allowed'] = ( + network_config.get('enable_router', True) and + self._has_permission((("network", "create_router"),))) return context class JSONView(View): + + @property + def is_router_enabled(self): + network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) + return network_config.get('enable_router', True) + def add_resource_url(self, view, resources): tenant_id = self.request.user.tenant_id for resource in resources: @@ -170,32 +178,35 @@ class JSONView(View): networks) # Add public networks to the networks list - try: - neutron_public_networks = api.neutron.network_list( - request, - **{'router:external': True}) - except Exception: - neutron_public_networks = [] - my_network_ids = [net['id'] for net in networks] - for publicnet in neutron_public_networks: - if publicnet.id in my_network_ids: - continue + if self.is_router_enabled: try: - subnets = [{'cidr': subnet.cidr} - for subnet in publicnet.subnets] + neutron_public_networks = api.neutron.network_list( + request, + **{'router:external': True}) except Exception: - subnets = [] - networks.append({ - 'name': publicnet.name, - 'id': publicnet.id, - 'subnets': subnets, - 'router:external': publicnet['router:external']}) + neutron_public_networks = [] + my_network_ids = [net['id'] for net in networks] + for publicnet in neutron_public_networks: + if publicnet.id in my_network_ids: + continue + try: + subnets = [{'cidr': subnet.cidr} + for subnet in publicnet.subnets] + except Exception: + subnets = [] + networks.append({ + 'name': publicnet.name, + 'id': publicnet.id, + 'subnets': subnets, + 'router:external': publicnet['router:external']}) return sorted(networks, key=lambda x: x.get('router:external'), reverse=True) def _get_routers(self, request): + if not self.is_router_enabled: + return [] try: neutron_routers = api.neutron.router_list( request, diff --git a/openstack_dashboard/dashboards/project/routers/panel.py b/openstack_dashboard/dashboards/project/routers/panel.py index c533676ed5..e2ea70e537 100644 --- a/openstack_dashboard/dashboards/project/routers/panel.py +++ b/openstack_dashboard/dashboards/project/routers/panel.py @@ -12,6 +12,7 @@ # 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 @@ -24,4 +25,6 @@ class Routers(horizon.Panel): slug = 'routers' permissions = ('openstack.services.network',) -dashboard.Project.register(Routers) +network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {}) +if network_config.get('enable_router', True): + dashboard.Project.register(Routers) diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example index cf3959e003..f748dc84ea 100644 --- a/openstack_dashboard/local/local_settings.py.example +++ b/openstack_dashboard/local/local_settings.py.example @@ -178,6 +178,7 @@ OPENSTACK_CINDER_FEATURES = { # services provided by neutron. Options currently available are load # balancer service, security groups, quotas, VPN service. OPENSTACK_NEUTRON_NETWORK = { + 'enable_router': True, 'enable_lb': False, 'enable_firewall': False, 'enable_quotas': True, diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py index 4a7ad403d1..63f92d550b 100644 --- a/openstack_dashboard/test/settings.py +++ b/openstack_dashboard/test/settings.py @@ -104,6 +104,7 @@ OPENSTACK_CINDER_FEATURES = { } OPENSTACK_NEUTRON_NETWORK = { + 'enable_router': True, 'enable_lb': True, 'enable_firewall': True, 'enable_quotas': False, # Enabled in specific tests only