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
This commit is contained in:
parent
6a8ea3385c
commit
1100169130
@ -493,6 +493,7 @@ by cinder. Currently only the backup service is available.
|
|||||||
Default::
|
Default::
|
||||||
|
|
||||||
{
|
{
|
||||||
|
'enable_router': True,
|
||||||
'enable_distributed_router': False,
|
'enable_distributed_router': False,
|
||||||
'enable_lb': False,
|
'enable_lb': False,
|
||||||
'enable_quotas': 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
|
by Neutron and configure Neutron specific features. The following options are
|
||||||
available.
|
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``:
|
``enable_distributed_router``:
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
@ -24,4 +25,6 @@ class Routers(horizon.Panel):
|
|||||||
slug = 'routers'
|
slug = 'routers'
|
||||||
permissions = ('openstack.services.network',)
|
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)
|
||||||
|
@ -16,6 +16,7 @@ import json
|
|||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django import http
|
from django import http
|
||||||
|
import django.test
|
||||||
|
|
||||||
from mox import IsA # noqa
|
from mox import IsA # noqa
|
||||||
|
|
||||||
@ -34,6 +35,17 @@ class NetworkTopologyTests(test.TestCase):
|
|||||||
'router_list',
|
'router_list',
|
||||||
'port_list')})
|
'port_list')})
|
||||||
def test_json_view(self):
|
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(
|
api.nova.server_list(
|
||||||
IsA(http.HttpRequest)).AndReturn([self.servers.list(), False])
|
IsA(http.HttpRequest)).AndReturn([self.servers.list(), False])
|
||||||
tenant_networks = [net for net in self.networks.list()
|
tenant_networks = [net for net in self.networks.list()
|
||||||
@ -43,17 +55,19 @@ class NetworkTopologyTests(test.TestCase):
|
|||||||
api.neutron.network_list_for_tenant(
|
api.neutron.network_list_for_tenant(
|
||||||
IsA(http.HttpRequest),
|
IsA(http.HttpRequest),
|
||||||
self.tenant.id).AndReturn(tenant_networks)
|
self.tenant.id).AndReturn(tenant_networks)
|
||||||
api.neutron.network_list(
|
if router_enable:
|
||||||
IsA(http.HttpRequest),
|
api.neutron.network_list(
|
||||||
**{'router:external': True}).AndReturn(external_networks)
|
IsA(http.HttpRequest),
|
||||||
|
**{'router:external': True}).AndReturn(external_networks)
|
||||||
|
|
||||||
# router1 : gateway port not in the port list
|
# router1 : gateway port not in the port list
|
||||||
# router2 : no gateway port
|
# router2 : no gateway port
|
||||||
# router3 : gateway port included in port list
|
# router3 : gateway port included in port list
|
||||||
routers = self.routers.list() + self.routers_with_rules.list()
|
routers = self.routers.list() + self.routers_with_rules.list()
|
||||||
api.neutron.router_list(
|
if router_enable:
|
||||||
IsA(http.HttpRequest),
|
api.neutron.router_list(
|
||||||
tenant_id=self.tenant.id).AndReturn(routers)
|
IsA(http.HttpRequest),
|
||||||
|
tenant_id=self.tenant.id).AndReturn(routers)
|
||||||
api.neutron.port_list(
|
api.neutron.port_list(
|
||||||
IsA(http.HttpRequest)).AndReturn(self.ports.list())
|
IsA(http.HttpRequest)).AndReturn(self.ports.list())
|
||||||
|
|
||||||
@ -79,24 +93,29 @@ class NetworkTopologyTests(test.TestCase):
|
|||||||
# rotuers
|
# rotuers
|
||||||
# result_router_urls = [(router['id'], router['url'])
|
# result_router_urls = [(router['id'], router['url'])
|
||||||
# for router in data['routers']]
|
# for router in data['routers']]
|
||||||
expect_router_urls = [
|
if router_enable:
|
||||||
{'id': router.id,
|
expect_router_urls = [
|
||||||
'external_gateway_info':
|
{'id': router.id,
|
||||||
router.external_gateway_info,
|
'external_gateway_info':
|
||||||
'name': router.name,
|
router.external_gateway_info,
|
||||||
'status': router.status,
|
'name': router.name,
|
||||||
'url': '/project/routers/%s/' % router.id}
|
'status': router.status,
|
||||||
for router in routers]
|
'url': '/project/routers/%s/' % router.id}
|
||||||
self.assertEqual(expect_router_urls, data['routers'])
|
for router in routers]
|
||||||
|
self.assertEqual(expect_router_urls, data['routers'])
|
||||||
|
else:
|
||||||
|
self.assertFalse(data['routers'])
|
||||||
|
|
||||||
# networks
|
# networks
|
||||||
expect_net_urls = [{'id': net.id,
|
expect_net_urls = []
|
||||||
'url': None,
|
if router_enable:
|
||||||
'name': net.name,
|
expect_net_urls += [{'id': net.id,
|
||||||
'router:external': net.router__external,
|
'url': None,
|
||||||
'subnets': [{'cidr': subnet.cidr}
|
'name': net.name,
|
||||||
for subnet in net.subnets]}
|
'router:external': net.router__external,
|
||||||
for net in external_networks]
|
'subnets': [{'cidr': subnet.cidr}
|
||||||
|
for subnet in net.subnets]}
|
||||||
|
for net in external_networks]
|
||||||
expect_net_urls += [{'id': net.id,
|
expect_net_urls += [{'id': net.id,
|
||||||
'url': '/project/networks/%s/detail' % net.id,
|
'url': '/project/networks/%s/detail' % net.id,
|
||||||
'name': net.name,
|
'name': net.name,
|
||||||
@ -119,12 +138,13 @@ class NetworkTopologyTests(test.TestCase):
|
|||||||
'status': port.status,
|
'status': port.status,
|
||||||
'url': '/project/networks/ports/%s/detail' % port.id}
|
'url': '/project/networks/ports/%s/detail' % port.id}
|
||||||
for port in self.ports.list()]
|
for port in self.ports.list()]
|
||||||
# fake port for router1 gateway (router1 on ext_net)
|
if router_enable:
|
||||||
router1 = routers[0]
|
# fake port for router1 gateway (router1 on ext_net)
|
||||||
ext_net = external_networks[0]
|
router1 = routers[0]
|
||||||
expect_port_urls.append(
|
ext_net = external_networks[0]
|
||||||
{'id': 'gateway%s' % ext_net.id,
|
expect_port_urls.append(
|
||||||
'device_id': router1.id,
|
{'id': 'gateway%s' % ext_net.id,
|
||||||
'network_id': ext_net.id,
|
'device_id': router1.id,
|
||||||
'fixed_ips': []})
|
'network_id': ext_net.id,
|
||||||
|
'fixed_ips': []})
|
||||||
self.assertEqual(expect_port_urls, data['ports'])
|
self.assertEqual(expect_port_urls, data['ports'])
|
||||||
|
@ -103,17 +103,25 @@ class NetworkTopologyView(TemplateView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(NetworkTopologyView, self).get_context_data(**kwargs)
|
context = super(NetworkTopologyView, self).get_context_data(**kwargs)
|
||||||
|
network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {})
|
||||||
|
|
||||||
context['launch_instance_allowed'] = self._has_permission(
|
context['launch_instance_allowed'] = self._has_permission(
|
||||||
(("compute", "compute:create"),))
|
(("compute", "compute:create"),))
|
||||||
context['create_network_allowed'] = self._has_permission(
|
context['create_network_allowed'] = self._has_permission(
|
||||||
(("network", "create_network"),))
|
(("network", "create_network"),))
|
||||||
context['create_router_allowed'] = self._has_permission(
|
context['create_router_allowed'] = (
|
||||||
(("network", "create_router"),))
|
network_config.get('enable_router', True) and
|
||||||
|
self._has_permission((("network", "create_router"),)))
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class JSONView(View):
|
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):
|
def add_resource_url(self, view, resources):
|
||||||
tenant_id = self.request.user.tenant_id
|
tenant_id = self.request.user.tenant_id
|
||||||
for resource in resources:
|
for resource in resources:
|
||||||
@ -170,32 +178,35 @@ class JSONView(View):
|
|||||||
networks)
|
networks)
|
||||||
|
|
||||||
# Add public networks to the networks list
|
# Add public networks to the networks list
|
||||||
try:
|
if self.is_router_enabled:
|
||||||
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
|
|
||||||
try:
|
try:
|
||||||
subnets = [{'cidr': subnet.cidr}
|
neutron_public_networks = api.neutron.network_list(
|
||||||
for subnet in publicnet.subnets]
|
request,
|
||||||
|
**{'router:external': True})
|
||||||
except Exception:
|
except Exception:
|
||||||
subnets = []
|
neutron_public_networks = []
|
||||||
networks.append({
|
my_network_ids = [net['id'] for net in networks]
|
||||||
'name': publicnet.name,
|
for publicnet in neutron_public_networks:
|
||||||
'id': publicnet.id,
|
if publicnet.id in my_network_ids:
|
||||||
'subnets': subnets,
|
continue
|
||||||
'router:external': publicnet['router:external']})
|
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,
|
return sorted(networks,
|
||||||
key=lambda x: x.get('router:external'),
|
key=lambda x: x.get('router:external'),
|
||||||
reverse=True)
|
reverse=True)
|
||||||
|
|
||||||
def _get_routers(self, request):
|
def _get_routers(self, request):
|
||||||
|
if not self.is_router_enabled:
|
||||||
|
return []
|
||||||
try:
|
try:
|
||||||
neutron_routers = api.neutron.router_list(
|
neutron_routers = api.neutron.router_list(
|
||||||
request,
|
request,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
@ -24,4 +25,6 @@ class Routers(horizon.Panel):
|
|||||||
slug = 'routers'
|
slug = 'routers'
|
||||||
permissions = ('openstack.services.network',)
|
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)
|
||||||
|
@ -178,6 +178,7 @@ OPENSTACK_CINDER_FEATURES = {
|
|||||||
# services provided by neutron. Options currently available are load
|
# services provided by neutron. Options currently available are load
|
||||||
# balancer service, security groups, quotas, VPN service.
|
# balancer service, security groups, quotas, VPN service.
|
||||||
OPENSTACK_NEUTRON_NETWORK = {
|
OPENSTACK_NEUTRON_NETWORK = {
|
||||||
|
'enable_router': True,
|
||||||
'enable_lb': False,
|
'enable_lb': False,
|
||||||
'enable_firewall': False,
|
'enable_firewall': False,
|
||||||
'enable_quotas': True,
|
'enable_quotas': True,
|
||||||
|
@ -104,6 +104,7 @@ OPENSTACK_CINDER_FEATURES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OPENSTACK_NEUTRON_NETWORK = {
|
OPENSTACK_NEUTRON_NETWORK = {
|
||||||
|
'enable_router': True,
|
||||||
'enable_lb': True,
|
'enable_lb': True,
|
||||||
'enable_firewall': True,
|
'enable_firewall': True,
|
||||||
'enable_quotas': False, # Enabled in specific tests only
|
'enable_quotas': False, # Enabled in specific tests only
|
||||||
|
Loading…
Reference in New Issue
Block a user