Move Floating IPs from Access & Security to panel
This patch makes the Floating IPs tab in Access & Security its own panel under Project > Network Change-Id: Ibb83ae5a0448d2824c10f867e620cec8219b7b72 Implements: blueprint reorganise-access-and-security
This commit is contained in:
parent
4f654e30c3
commit
99849ad88f
@ -23,9 +23,9 @@ from horizon import messages
|
||||
from horizon import tables
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.floating_ips \
|
||||
import tables as project_tables
|
||||
from openstack_dashboard import policy
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
floating_ips import tables as project_tables
|
||||
from openstack_dashboard.utils import filters
|
||||
|
||||
|
||||
|
@ -32,8 +32,8 @@ from openstack_dashboard.dashboards.admin.floating_ips \
|
||||
import forms as fip_forms
|
||||
from openstack_dashboard.dashboards.admin.floating_ips \
|
||||
import tables as fip_tables
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
floating_ips import tables as project_tables
|
||||
from openstack_dashboard.dashboards.project.floating_ips \
|
||||
import tables as project_tables
|
||||
|
||||
|
||||
def get_floatingip_pools(request):
|
||||
|
@ -25,10 +25,6 @@ from horizon import tabs
|
||||
from neutronclient.common import exceptions as neutron_exc
|
||||
|
||||
from openstack_dashboard.api import network
|
||||
from openstack_dashboard.api import nova
|
||||
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
floating_ips.tables import FloatingIPsTable
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
security_groups.tables import SecurityGroupsTable
|
||||
|
||||
@ -53,60 +49,7 @@ class SecurityGroupsTab(tabs.TableTab):
|
||||
return sorted(security_groups, key=lambda group: group.name)
|
||||
|
||||
|
||||
class FloatingIPsTab(tabs.TableTab):
|
||||
table_classes = (FloatingIPsTable,)
|
||||
name = _("Floating IPs")
|
||||
slug = "floating_ips_tab"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
permissions = ('openstack.services.compute',)
|
||||
|
||||
def get_floating_ips_data(self):
|
||||
try:
|
||||
floating_ips = network.tenant_floating_ip_list(self.request)
|
||||
except neutron_exc.ConnectionFailed:
|
||||
floating_ips = []
|
||||
exceptions.handle(self.request)
|
||||
except Exception:
|
||||
floating_ips = []
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve floating IP addresses.'))
|
||||
|
||||
try:
|
||||
floating_ip_pools = network.floating_ip_pools_list(self.request)
|
||||
except neutron_exc.ConnectionFailed:
|
||||
floating_ip_pools = []
|
||||
exceptions.handle(self.request)
|
||||
except Exception:
|
||||
floating_ip_pools = []
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve floating IP pools.'))
|
||||
pool_dict = dict([(obj.id, obj.name) for obj in floating_ip_pools])
|
||||
|
||||
attached_instance_ids = [ip.instance_id for ip in floating_ips
|
||||
if ip.instance_id is not None]
|
||||
if attached_instance_ids:
|
||||
instances = []
|
||||
try:
|
||||
# TODO(tsufiev): we should pass attached_instance_ids to
|
||||
# nova.server_list as soon as Nova API allows for this
|
||||
instances, has_more = nova.server_list(self.request)
|
||||
except Exception:
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve instance list.'))
|
||||
|
||||
instances_dict = dict([(obj.id, obj.name) for obj in instances])
|
||||
|
||||
for ip in floating_ips:
|
||||
ip.instance_name = instances_dict.get(ip.instance_id)
|
||||
ip.pool_name = pool_dict.get(ip.pool, ip.pool)
|
||||
|
||||
return floating_ips
|
||||
|
||||
def allowed(self, request):
|
||||
return network.floating_ip_supported(request)
|
||||
|
||||
|
||||
class AccessAndSecurityTabs(tabs.TabGroup):
|
||||
slug = "access_security_tabs"
|
||||
tabs = (SecurityGroupsTab, FloatingIPsTab)
|
||||
tabs = (SecurityGroupsTab,)
|
||||
sticky = True
|
||||
|
@ -1,7 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Allocate Floating IP" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/access_and_security/floating_ips/_allocate.html' %}
|
||||
{% endblock %}
|
@ -23,7 +23,6 @@ from django import http
|
||||
from mox3.mox import IsA # noqa
|
||||
import six
|
||||
|
||||
from horizon.workflows import views
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.test import helpers as test
|
||||
from openstack_dashboard.usage import quotas
|
||||
@ -35,32 +34,14 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
def setUp(self):
|
||||
super(AccessAndSecurityTests, self).setUp()
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'floating_ip_pools_list',
|
||||
'security_group_list',),
|
||||
api.nova: ('server_list',),
|
||||
@test.create_stubs({api.network: ('security_group_list',),
|
||||
api.base: ('is_service_enabled',),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def _test_index(self, instanceless_ips=False):
|
||||
def _test_index(self):
|
||||
sec_groups = self.security_groups.list()
|
||||
floating_ips = self.floating_ips.list()
|
||||
floating_pools = self.pools.list()
|
||||
if instanceless_ips:
|
||||
for fip in floating_ips:
|
||||
fip.instance_id = None
|
||||
quota_data = self.quota_usages.first()
|
||||
quota_data['security_groups']['available'] = 10
|
||||
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
if not instanceless_ips:
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.floating_ip_pools_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_pools)
|
||||
api.network.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(sec_groups)
|
||||
quotas.tenant_quota_usages(IsA(http.HttpRequest)).MultipleTimes() \
|
||||
@ -74,8 +55,6 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
res = self.client.get(INDEX_URL)
|
||||
|
||||
self.assertTemplateUsed(res, 'project/access_and_security/index.html')
|
||||
self.assertItemsEqual(res.context['floating_ips_table'].data,
|
||||
floating_ips)
|
||||
|
||||
# Security groups
|
||||
sec_groups_from_ctx = res.context['security_groups_table'].data
|
||||
@ -93,81 +72,22 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
def test_index(self):
|
||||
self._test_index()
|
||||
|
||||
def test_index_with_instanceless_fips(self):
|
||||
self._test_index(instanceless_ips=True)
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_target_list',
|
||||
'tenant_floating_ip_list',)})
|
||||
def test_association(self):
|
||||
servers = [api.nova.Server(s, self.request)
|
||||
for s in self.servers.list()]
|
||||
# Add duplicate instance name to test instance name with [ID]
|
||||
# Change id and private IP
|
||||
server3 = api.nova.Server(self.servers.first(), self.request)
|
||||
server3.id = 101
|
||||
server3.addresses = deepcopy(server3.addresses)
|
||||
server3.addresses['private'][0]['addr'] = "10.0.0.5"
|
||||
servers.append(server3)
|
||||
|
||||
targets = [api.nova.FloatingIpTarget(s) for s in servers]
|
||||
|
||||
api.network.tenant_floating_ip_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.network.floating_ip_target_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(targets)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse("horizon:project:access_and_security:"
|
||||
"floating_ips:associate"))
|
||||
|
||||
self.assertTemplateUsed(res, views.WorkflowView.template_name)
|
||||
self.assertContains(res, '<option value="1">server_1 (1)</option>')
|
||||
self.assertContains(res, '<option value="101">server_1 (101)</option>')
|
||||
self.assertContains(res, '<option value="2">server_2 (2)</option>')
|
||||
|
||||
|
||||
class AccessAndSecurityNeutronProxyTests(AccessAndSecurityTests):
|
||||
def setUp(self):
|
||||
super(AccessAndSecurityNeutronProxyTests, self).setUp()
|
||||
self.floating_ips = self.floating_ips_uuid
|
||||
|
||||
|
||||
class SecurityGroupTabTests(test.TestCase):
|
||||
def setUp(self):
|
||||
super(SecurityGroupTabTests, self).setUp()
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
'floating_ip_pools_list',),
|
||||
api.nova: ('server_list',),
|
||||
@test.create_stubs({api.network: ('security_group_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
api.base: ('is_service_enabled',)})
|
||||
def test_create_button_attributes(self):
|
||||
floating_ips = self.floating_ips.list()
|
||||
floating_pools = self.pools.list()
|
||||
sec_groups = self.security_groups.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
quota_data['security_groups']['available'] = 10
|
||||
|
||||
api.network.floating_ip_supported(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.floating_ip_pools_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_pools)
|
||||
api.network.security_group_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(sec_groups)
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)).MultipleTimes() \
|
||||
.AndReturn(quota_data)
|
||||
@ -195,36 +115,18 @@ class SecurityGroupTabTests(test.TestCase):
|
||||
url = 'horizon:project:access_and_security:security_groups:create'
|
||||
self.assertEqual(url, create_action.url)
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
'floating_ip_pools_list',),
|
||||
api.nova: ('server_list',),
|
||||
@test.create_stubs({api.network: ('security_group_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
api.base: ('is_service_enabled',)})
|
||||
def _test_create_button_disabled_when_quota_exceeded(self,
|
||||
network_enabled):
|
||||
floating_ips = self.floating_ips.list()
|
||||
floating_pools = self.pools.list()
|
||||
sec_groups = self.security_groups.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
quota_data['security_groups']['available'] = 0
|
||||
|
||||
api.network.floating_ip_supported(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.floating_ip_pools_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_pools)
|
||||
api.network.security_group_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(sec_groups)
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)).MultipleTimes() \
|
||||
.AndReturn(quota_data)
|
||||
|
@ -19,8 +19,6 @@
|
||||
from django.conf.urls import include
|
||||
from django.conf.urls import url
|
||||
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
floating_ips import urls as fip_urls
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
security_groups import urls as sec_group_urls
|
||||
from openstack_dashboard.dashboards.project.access_and_security import views
|
||||
@ -28,7 +26,6 @@ from openstack_dashboard.dashboards.project.access_and_security import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'floating_ips/', include(fip_urls, namespace='floating_ips')),
|
||||
url(r'security_groups/',
|
||||
include(sec_group_urls, namespace='security_groups')),
|
||||
]
|
||||
|
27
openstack_dashboard/dashboards/project/floating_ips/panel.py
Normal file
27
openstack_dashboard/dashboards/project/floating_ips/panel.py
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright 2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# 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
|
||||
|
||||
|
||||
class FloatingIps(horizon.Panel):
|
||||
name = _("Floating IPs")
|
||||
slug = 'floating_ips'
|
||||
|
||||
@staticmethod
|
||||
def can_register():
|
||||
network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {})
|
||||
return network_config.get('enable_router', True)
|
@ -41,10 +41,10 @@ class AllocateIP(tables.LinkAction):
|
||||
verbose_name = _("Allocate IP To Project")
|
||||
classes = ("ajax-modal",)
|
||||
icon = "link"
|
||||
url = "horizon:project:access_and_security:floating_ips:allocate"
|
||||
url = "horizon:project:floating_ips:allocate"
|
||||
|
||||
def single(self, data_table, request, *args):
|
||||
return shortcuts.redirect('horizon:project:access_and_security:index')
|
||||
return shortcuts.redirect('horizon:project:floating_ips:index')
|
||||
|
||||
def allowed(self, request, fip=None):
|
||||
usages = quotas.tenant_quota_usages(request)
|
||||
@ -106,7 +106,7 @@ class ReleaseIPs(tables.BatchAction):
|
||||
class AssociateIP(tables.LinkAction):
|
||||
name = "associate"
|
||||
verbose_name = _("Associate")
|
||||
url = "horizon:project:access_and_security:floating_ips:associate"
|
||||
url = "horizon:project:floating_ips:associate"
|
||||
classes = ("ajax-modal",)
|
||||
icon = "link"
|
||||
|
||||
@ -152,7 +152,7 @@ class DisassociateIP(tables.Action):
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Unable to disassociate floating IP.'))
|
||||
return shortcuts.redirect('horizon:project:access_and_security:index')
|
||||
return shortcuts.redirect('horizon:project:floating_ips:index')
|
||||
|
||||
|
||||
def get_instance_info(fip):
|
@ -0,0 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/floating_ips/_allocate.html' %}
|
||||
{% endblock %}
|
@ -31,8 +31,8 @@ from openstack_dashboard.usage import quotas
|
||||
from horizon.workflows import views
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:access_and_security:index')
|
||||
NAMESPACE = "horizon:project:access_and_security:floating_ips"
|
||||
INDEX_URL = reverse('horizon:project:floating_ips:index')
|
||||
NAMESPACE = "horizon:project:floating_ips"
|
||||
|
||||
|
||||
class FloatingIpViewTests(test.TestCase):
|
||||
@ -167,7 +167,6 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.nova: ('server_list',),
|
||||
api.network: ('floating_ip_disassociate',
|
||||
'floating_ip_supported',
|
||||
'tenant_floating_ip_get',
|
||||
'tenant_floating_ip_list',),
|
||||
api.neutron: ('is_extension_supported',)})
|
||||
@ -176,8 +175,6 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
@ -194,7 +191,6 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.nova: ('server_list',),
|
||||
api.network: ('floating_ip_disassociate',
|
||||
'floating_ip_supported',
|
||||
'tenant_floating_ip_get',
|
||||
'tenant_floating_ip_list',),
|
||||
api.neutron: ('is_extension_supported',)})
|
||||
@ -203,8 +199,6 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
@ -220,9 +214,7 @@ class FloatingIpViewTests(test.TestCase):
|
||||
res = self.client.post(INDEX_URL, {"action": action})
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
@test.create_stubs({api.network: ('tenant_floating_ip_list',
|
||||
'floating_ip_pools_list',),
|
||||
api.nova: ('server_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
@ -232,17 +224,10 @@ class FloatingIpViewTests(test.TestCase):
|
||||
floating_pools = self.pools.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
quota_data['floating_ips']['available'] = 10
|
||||
sec_groups = self.security_groups.list()
|
||||
|
||||
api.network.floating_ip_supported(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.security_group_list(
|
||||
IsA(http.HttpRequest)).MultipleTimes()\
|
||||
.AndReturn(sec_groups)
|
||||
api.network.floating_ip_pools_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_pools)
|
||||
@ -252,7 +237,6 @@ class FloatingIpViewTests(test.TestCase):
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)).MultipleTimes() \
|
||||
.AndReturn(quota_data)
|
||||
|
||||
api.base.is_service_enabled(
|
||||
IsA(http.HttpRequest),
|
||||
'network').MultipleTimes() \
|
||||
@ -260,8 +244,7 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(INDEX_URL +
|
||||
"?tab=access_security_tabs__floating_ips_tab")
|
||||
res = self.client.get(INDEX_URL)
|
||||
|
||||
allocate_action = self.getAndAssertTableAction(res, 'floating_ips',
|
||||
'allocate')
|
||||
@ -270,12 +253,10 @@ class FloatingIpViewTests(test.TestCase):
|
||||
six.text_type(allocate_action.verbose_name))
|
||||
self.assertIsNone(allocate_action.policy_rules)
|
||||
|
||||
url = 'horizon:project:access_and_security:floating_ips:allocate'
|
||||
url = 'horizon:project:floating_ips:allocate'
|
||||
self.assertEqual(url, allocate_action.url)
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
@test.create_stubs({api.network: ('tenant_floating_ip_list',
|
||||
'floating_ip_pools_list',),
|
||||
api.nova: ('server_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
@ -285,17 +266,10 @@ class FloatingIpViewTests(test.TestCase):
|
||||
floating_pools = self.pools.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
quota_data['floating_ips']['available'] = 0
|
||||
sec_groups = self.security_groups.list()
|
||||
|
||||
api.network.floating_ip_supported(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.security_group_list(
|
||||
IsA(http.HttpRequest)).MultipleTimes()\
|
||||
.AndReturn(sec_groups)
|
||||
api.network.floating_ip_pools_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_pools)
|
||||
@ -305,7 +279,6 @@ class FloatingIpViewTests(test.TestCase):
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)).MultipleTimes() \
|
||||
.AndReturn(quota_data)
|
||||
|
||||
api.base.is_service_enabled(
|
||||
IsA(http.HttpRequest),
|
||||
'network').MultipleTimes() \
|
||||
@ -313,8 +286,7 @@ class FloatingIpViewTests(test.TestCase):
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(INDEX_URL +
|
||||
"?tab=access_security_tabs__floating_ips_tab")
|
||||
res = self.client.get(INDEX_URL)
|
||||
|
||||
allocate_action = self.getAndAssertTableAction(res, 'floating_ips',
|
||||
'allocate')
|
@ -18,11 +18,10 @@
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
floating_ips import views
|
||||
|
||||
from openstack_dashboard.dashboards.project.floating_ips import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'^associate/$', views.AssociateView.as_view(), name='associate'),
|
||||
url(r'^allocate/$', views.AllocateView.as_view(), name='allocate'),
|
||||
]
|
@ -28,15 +28,18 @@ from neutronclient.common import exceptions as neutron_exc
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
from horizon import workflows
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.usage import quotas
|
||||
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
floating_ips import forms as project_forms
|
||||
from openstack_dashboard.dashboards.project.access_and_security.\
|
||||
floating_ips import workflows as project_workflows
|
||||
from openstack_dashboard.dashboards.project.floating_ips \
|
||||
import forms as project_forms
|
||||
from openstack_dashboard.dashboards.project.floating_ips \
|
||||
import tables as project_tables
|
||||
from openstack_dashboard.dashboards.project.floating_ips \
|
||||
import workflows as project_workflows
|
||||
|
||||
|
||||
class AssociateView(workflows.WorkflowView):
|
||||
@ -47,11 +50,10 @@ class AllocateView(forms.ModalFormView):
|
||||
form_class = project_forms.FloatingIpAllocate
|
||||
form_id = "associate_floating_ip_form"
|
||||
page_title = _("Allocate Floating IP")
|
||||
template_name = 'project/access_and_security/floating_ips/allocate.html'
|
||||
template_name = 'project/floating_ips/allocate.html'
|
||||
submit_label = _("Allocate IP")
|
||||
submit_url = reverse_lazy(
|
||||
"horizon:project:access_and_security:floating_ips:allocate")
|
||||
success_url = reverse_lazy('horizon:project:access_and_security:index')
|
||||
submit_url = reverse_lazy("horizon:project:floating_ips:allocate")
|
||||
success_url = reverse_lazy('horizon:project:floating_ips:index')
|
||||
|
||||
def get_object_display(self, obj):
|
||||
return obj.ip
|
||||
@ -78,3 +80,51 @@ class AllocateView(forms.ModalFormView):
|
||||
if not pool_list:
|
||||
pool_list = [(None, _("No floating IP pools available"))]
|
||||
return {'pool_list': pool_list}
|
||||
|
||||
|
||||
class IndexView(tables.DataTableView):
|
||||
table_class = project_tables.FloatingIPsTable
|
||||
page_title = _("Floating IPs")
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
floating_ips = api.network.tenant_floating_ip_list(self.request)
|
||||
except neutron_exc.ConnectionFailed:
|
||||
floating_ips = []
|
||||
exceptions.handle(self.request)
|
||||
except Exception:
|
||||
floating_ips = []
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve floating IP addresses.'))
|
||||
|
||||
try:
|
||||
floating_ip_pools = \
|
||||
api.network.floating_ip_pools_list(self.request)
|
||||
except neutron_exc.ConnectionFailed:
|
||||
floating_ip_pools = []
|
||||
exceptions.handle(self.request)
|
||||
except Exception:
|
||||
floating_ip_pools = []
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve floating IP pools.'))
|
||||
pool_dict = dict([(obj.id, obj.name) for obj in floating_ip_pools])
|
||||
|
||||
attached_instance_ids = [ip.instance_id for ip in floating_ips
|
||||
if ip.instance_id is not None]
|
||||
if attached_instance_ids:
|
||||
instances = []
|
||||
try:
|
||||
# TODO(tsufiev): we should pass attached_instance_ids to
|
||||
# nova.server_list as soon as Nova API allows for this
|
||||
instances, has_more = api.nova.server_list(self.request)
|
||||
except Exception:
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve instance list.'))
|
||||
|
||||
instances_dict = dict([(obj.id, obj.name) for obj in instances])
|
||||
|
||||
for ip in floating_ips:
|
||||
ip.instance_name = instances_dict.get(ip.instance_id)
|
||||
ip.pool_name = pool_dict.get(ip.pool, ip.pool)
|
||||
|
||||
return floating_ips
|
@ -26,7 +26,7 @@ from openstack_dashboard import api
|
||||
from openstack_dashboard.utils import filters
|
||||
|
||||
|
||||
ALLOCATE_URL = "horizon:project:access_and_security:floating_ips:allocate"
|
||||
ALLOCATE_URL = "horizon:project:floating_ips:allocate"
|
||||
|
||||
|
||||
class AssociateIPAction(workflows.Action):
|
||||
@ -72,7 +72,7 @@ class AssociateIPAction(workflows.Action):
|
||||
|
||||
def populate_ip_id_choices(self, request, context):
|
||||
ips = []
|
||||
redirect = reverse('horizon:project:access_and_security:index')
|
||||
redirect = reverse('horizon:project:floating_ips:index')
|
||||
try:
|
||||
ips = api.network.tenant_floating_ip_list(self.request)
|
||||
except neutron_exc.ConnectionFailed:
|
||||
@ -95,7 +95,7 @@ class AssociateIPAction(workflows.Action):
|
||||
try:
|
||||
targets = api.network.floating_ip_target_list(self.request)
|
||||
except Exception:
|
||||
redirect = reverse('horizon:project:access_and_security:index')
|
||||
redirect = reverse('horizon:project:floating_ips:index')
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve instance list.'),
|
||||
redirect=redirect)
|
||||
@ -146,7 +146,7 @@ class IPAssociationWorkflow(workflows.Workflow):
|
||||
finalize_button_name = _("Associate")
|
||||
success_message = _('IP address %s associated.')
|
||||
failure_message = _('Unable to associate IP address %s.')
|
||||
success_url = "horizon:project:access_and_security:index"
|
||||
success_url = "horizon:project:floating_ips:index"
|
||||
default_steps = (AssociateIP,)
|
||||
|
||||
def format_status_message(self, message):
|
@ -36,8 +36,7 @@ from horizon.templatetags import sizeformat
|
||||
from horizon.utils import filters
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.access_and_security.floating_ips \
|
||||
import workflows
|
||||
from openstack_dashboard.dashboards.project.floating_ips import workflows
|
||||
from openstack_dashboard.dashboards.project.instances import tabs
|
||||
from openstack_dashboard.dashboards.project.instances.workflows \
|
||||
import resize_instance
|
||||
@ -617,7 +616,7 @@ class DecryptInstancePassword(tables.LinkAction):
|
||||
class AssociateIP(policy.PolicyTargetMixin, tables.LinkAction):
|
||||
name = "associate"
|
||||
verbose_name = _("Associate Floating IP")
|
||||
url = "horizon:project:access_and_security:floating_ips:associate"
|
||||
url = "horizon:project:floating_ips:associate"
|
||||
classes = ("ajax-modal",)
|
||||
icon = "link"
|
||||
policy_rules = (("compute", "network:associate_floating_ip"),)
|
||||
|
@ -0,0 +1,6 @@
|
||||
PANEL_DASHBOARD = 'project'
|
||||
PANEL_GROUP = 'network'
|
||||
PANEL = 'floating_ips'
|
||||
|
||||
ADD_PANEL = \
|
||||
'openstack_dashboard.dashboards.project.floating_ips.panel.FloatingIps'
|
Loading…
Reference in New Issue
Block a user