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