Browse Source

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
tags/11.0.0.0rc1
Rob Cresswell 2 years ago
parent
commit
99849ad88f

+ 2
- 2
openstack_dashboard/dashboards/admin/floating_ips/tables.py View File

@@ -23,9 +23,9 @@ from horizon import messages
23 23
 from horizon import tables
24 24
 
25 25
 from openstack_dashboard import api
26
+from openstack_dashboard.dashboards.project.floating_ips \
27
+    import tables as project_tables
26 28
 from openstack_dashboard import policy
27
-from openstack_dashboard.dashboards.project.access_and_security.\
28
-    floating_ips import tables as project_tables
29 29
 from openstack_dashboard.utils import filters
30 30
 
31 31
 

+ 2
- 2
openstack_dashboard/dashboards/admin/floating_ips/views.py View File

@@ -32,8 +32,8 @@ from openstack_dashboard.dashboards.admin.floating_ips \
32 32
     import forms as fip_forms
33 33
 from openstack_dashboard.dashboards.admin.floating_ips \
34 34
     import tables as fip_tables
35
-from openstack_dashboard.dashboards.project.access_and_security.\
36
-    floating_ips import tables as project_tables
35
+from openstack_dashboard.dashboards.project.floating_ips \
36
+    import tables as project_tables
37 37
 
38 38
 
39 39
 def get_floatingip_pools(request):

+ 1
- 58
openstack_dashboard/dashboards/project/access_and_security/tabs.py View File

@@ -25,10 +25,6 @@ from horizon import tabs
25 25
 from neutronclient.common import exceptions as neutron_exc
26 26
 
27 27
 from openstack_dashboard.api import network
28
-from openstack_dashboard.api import nova
29
-
30
-from openstack_dashboard.dashboards.project.access_and_security.\
31
-    floating_ips.tables import FloatingIPsTable
32 28
 from openstack_dashboard.dashboards.project.access_and_security.\
33 29
     security_groups.tables import SecurityGroupsTable
34 30
 
@@ -53,60 +49,7 @@ class SecurityGroupsTab(tabs.TableTab):
53 49
         return sorted(security_groups, key=lambda group: group.name)
54 50
 
55 51
 
56
-class FloatingIPsTab(tabs.TableTab):
57
-    table_classes = (FloatingIPsTable,)
58
-    name = _("Floating IPs")
59
-    slug = "floating_ips_tab"
60
-    template_name = "horizon/common/_detail_table.html"
61
-    permissions = ('openstack.services.compute',)
62
-
63
-    def get_floating_ips_data(self):
64
-        try:
65
-            floating_ips = network.tenant_floating_ip_list(self.request)
66
-        except neutron_exc.ConnectionFailed:
67
-            floating_ips = []
68
-            exceptions.handle(self.request)
69
-        except Exception:
70
-            floating_ips = []
71
-            exceptions.handle(self.request,
72
-                              _('Unable to retrieve floating IP addresses.'))
73
-
74
-        try:
75
-            floating_ip_pools = network.floating_ip_pools_list(self.request)
76
-        except neutron_exc.ConnectionFailed:
77
-            floating_ip_pools = []
78
-            exceptions.handle(self.request)
79
-        except Exception:
80
-            floating_ip_pools = []
81
-            exceptions.handle(self.request,
82
-                              _('Unable to retrieve floating IP pools.'))
83
-        pool_dict = dict([(obj.id, obj.name) for obj in floating_ip_pools])
84
-
85
-        attached_instance_ids = [ip.instance_id for ip in floating_ips
86
-                                 if ip.instance_id is not None]
87
-        if attached_instance_ids:
88
-            instances = []
89
-            try:
90
-                # TODO(tsufiev): we should pass attached_instance_ids to
91
-                # nova.server_list as soon as Nova API allows for this
92
-                instances, has_more = nova.server_list(self.request)
93
-            except Exception:
94
-                exceptions.handle(self.request,
95
-                                  _('Unable to retrieve instance list.'))
96
-
97
-            instances_dict = dict([(obj.id, obj.name) for obj in instances])
98
-
99
-            for ip in floating_ips:
100
-                ip.instance_name = instances_dict.get(ip.instance_id)
101
-                ip.pool_name = pool_dict.get(ip.pool, ip.pool)
102
-
103
-        return floating_ips
104
-
105
-    def allowed(self, request):
106
-        return network.floating_ip_supported(request)
107
-
108
-
109 52
 class AccessAndSecurityTabs(tabs.TabGroup):
110 53
     slug = "access_security_tabs"
111
-    tabs = (SecurityGroupsTab, FloatingIPsTab)
54
+    tabs = (SecurityGroupsTab,)
112 55
     sticky = True

+ 0
- 7
openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html View File

@@ -1,7 +0,0 @@
1
-{% extends 'base.html' %}
2
-{% load i18n %}
3
-{% block title %}{% trans "Allocate Floating IP" %}{% endblock %}
4
-
5
-{% block main %}
6
-  {% include 'project/access_and_security/floating_ips/_allocate.html' %}
7
-{% endblock %}

+ 4
- 102
openstack_dashboard/dashboards/project/access_and_security/tests.py View File

@@ -23,7 +23,6 @@ from django import http
23 23
 from mox3.mox import IsA  # noqa
24 24
 import six
25 25
 
26
-from horizon.workflows import views
27 26
 from openstack_dashboard import api
28 27
 from openstack_dashboard.test import helpers as test
29 28
 from openstack_dashboard.usage import quotas
@@ -35,32 +34,14 @@ class AccessAndSecurityTests(test.TestCase):
35 34
     def setUp(self):
36 35
         super(AccessAndSecurityTests, self).setUp()
37 36
 
38
-    @test.create_stubs({api.network: ('floating_ip_supported',
39
-                                      'tenant_floating_ip_list',
40
-                                      'floating_ip_pools_list',
41
-                                      'security_group_list',),
42
-                        api.nova: ('server_list',),
37
+    @test.create_stubs({api.network: ('security_group_list',),
43 38
                         api.base: ('is_service_enabled',),
44 39
                         quotas: ('tenant_quota_usages',)})
45
-    def _test_index(self, instanceless_ips=False):
40
+    def _test_index(self):
46 41
         sec_groups = self.security_groups.list()
47
-        floating_ips = self.floating_ips.list()
48
-        floating_pools = self.pools.list()
49
-        if instanceless_ips:
50
-            for fip in floating_ips:
51
-                fip.instance_id = None
52 42
         quota_data = self.quota_usages.first()
53 43
         quota_data['security_groups']['available'] = 10
54 44
 
55
-        api.network.floating_ip_supported(IsA(http.HttpRequest)) \
56
-            .AndReturn(True)
57
-        if not instanceless_ips:
58
-            api.nova.server_list(IsA(http.HttpRequest)) \
59
-                .AndReturn([self.servers.list(), False])
60
-        api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
61
-            .AndReturn(floating_ips)
62
-        api.network.floating_ip_pools_list(IsA(http.HttpRequest)) \
63
-            .AndReturn(floating_pools)
64 45
         api.network.security_group_list(IsA(http.HttpRequest)) \
65 46
             .AndReturn(sec_groups)
66 47
         quotas.tenant_quota_usages(IsA(http.HttpRequest)).MultipleTimes() \
@@ -74,8 +55,6 @@ class AccessAndSecurityTests(test.TestCase):
74 55
         res = self.client.get(INDEX_URL)
75 56
 
76 57
         self.assertTemplateUsed(res, 'project/access_and_security/index.html')
77
-        self.assertItemsEqual(res.context['floating_ips_table'].data,
78
-                              floating_ips)
79 58
 
80 59
         # Security groups
81 60
         sec_groups_from_ctx = res.context['security_groups_table'].data
@@ -93,81 +72,22 @@ class AccessAndSecurityTests(test.TestCase):
93 72
     def test_index(self):
94 73
         self._test_index()
95 74
 
96
-    def test_index_with_instanceless_fips(self):
97
-        self._test_index(instanceless_ips=True)
98
-
99
-    @test.create_stubs({api.network: ('floating_ip_target_list',
100
-                                      'tenant_floating_ip_list',)})
101
-    def test_association(self):
102
-        servers = [api.nova.Server(s, self.request)
103
-                   for s in self.servers.list()]
104
-        # Add duplicate instance name to test instance name with [ID]
105
-        # Change id and private IP
106
-        server3 = api.nova.Server(self.servers.first(), self.request)
107
-        server3.id = 101
108
-        server3.addresses = deepcopy(server3.addresses)
109
-        server3.addresses['private'][0]['addr'] = "10.0.0.5"
110
-        servers.append(server3)
111
-
112
-        targets = [api.nova.FloatingIpTarget(s) for s in servers]
113
-
114
-        api.network.tenant_floating_ip_list(
115
-            IsA(http.HttpRequest)) \
116
-            .AndReturn(self.floating_ips.list())
117
-        api.network.floating_ip_target_list(
118
-            IsA(http.HttpRequest)) \
119
-            .AndReturn(targets)
120
-
121
-        self.mox.ReplayAll()
122
-
123
-        res = self.client.get(reverse("horizon:project:access_and_security:"
124
-                                      "floating_ips:associate"))
125
-
126
-        self.assertTemplateUsed(res, views.WorkflowView.template_name)
127
-        self.assertContains(res, '<option value="1">server_1 (1)</option>')
128
-        self.assertContains(res, '<option value="101">server_1 (101)</option>')
129
-        self.assertContains(res, '<option value="2">server_2 (2)</option>')
130
-
131
-
132
-class AccessAndSecurityNeutronProxyTests(AccessAndSecurityTests):
133
-    def setUp(self):
134
-        super(AccessAndSecurityNeutronProxyTests, self).setUp()
135
-        self.floating_ips = self.floating_ips_uuid
136
-
137 75
 
138 76
 class SecurityGroupTabTests(test.TestCase):
139 77
     def setUp(self):
140 78
         super(SecurityGroupTabTests, self).setUp()
141 79
 
142
-    @test.create_stubs({api.network: ('floating_ip_supported',
143
-                                      'tenant_floating_ip_list',
144
-                                      'security_group_list',
145
-                                      'floating_ip_pools_list',),
146
-                        api.nova: ('server_list',),
80
+    @test.create_stubs({api.network: ('security_group_list',),
147 81
                         quotas: ('tenant_quota_usages',),
148 82
                         api.base: ('is_service_enabled',)})
149 83
     def test_create_button_attributes(self):
150
-        floating_ips = self.floating_ips.list()
151
-        floating_pools = self.pools.list()
152 84
         sec_groups = self.security_groups.list()
153 85
         quota_data = self.quota_usages.first()
154 86
         quota_data['security_groups']['available'] = 10
155 87
 
156
-        api.network.floating_ip_supported(
157
-            IsA(http.HttpRequest)) \
158
-            .AndReturn(True)
159
-        api.network.tenant_floating_ip_list(
160
-            IsA(http.HttpRequest)) \
161
-            .AndReturn(floating_ips)
162
-        api.network.floating_ip_pools_list(
163
-            IsA(http.HttpRequest)) \
164
-            .AndReturn(floating_pools)
165 88
         api.network.security_group_list(
166 89
             IsA(http.HttpRequest)) \
167 90
             .AndReturn(sec_groups)
168
-        api.nova.server_list(
169
-            IsA(http.HttpRequest)) \
170
-            .AndReturn([self.servers.list(), False])
171 91
         quotas.tenant_quota_usages(
172 92
             IsA(http.HttpRequest)).MultipleTimes() \
173 93
             .AndReturn(quota_data)
@@ -195,36 +115,18 @@ class SecurityGroupTabTests(test.TestCase):
195 115
         url = 'horizon:project:access_and_security:security_groups:create'
196 116
         self.assertEqual(url, create_action.url)
197 117
 
198
-    @test.create_stubs({api.network: ('floating_ip_supported',
199
-                                      'tenant_floating_ip_list',
200
-                                      'security_group_list',
201
-                                      'floating_ip_pools_list',),
202
-                        api.nova: ('server_list',),
118
+    @test.create_stubs({api.network: ('security_group_list',),
203 119
                         quotas: ('tenant_quota_usages',),
204 120
                         api.base: ('is_service_enabled',)})
205 121
     def _test_create_button_disabled_when_quota_exceeded(self,
206 122
                                                          network_enabled):
207
-        floating_ips = self.floating_ips.list()
208
-        floating_pools = self.pools.list()
209 123
         sec_groups = self.security_groups.list()
210 124
         quota_data = self.quota_usages.first()
211 125
         quota_data['security_groups']['available'] = 0
212 126
 
213
-        api.network.floating_ip_supported(
214
-            IsA(http.HttpRequest)) \
215
-            .AndReturn(True)
216
-        api.network.tenant_floating_ip_list(
217
-            IsA(http.HttpRequest)) \
218
-            .AndReturn(floating_ips)
219
-        api.network.floating_ip_pools_list(
220
-            IsA(http.HttpRequest)) \
221
-            .AndReturn(floating_pools)
222 127
         api.network.security_group_list(
223 128
             IsA(http.HttpRequest)) \
224 129
             .AndReturn(sec_groups)
225
-        api.nova.server_list(
226
-            IsA(http.HttpRequest)) \
227
-            .AndReturn([self.servers.list(), False])
228 130
         quotas.tenant_quota_usages(
229 131
             IsA(http.HttpRequest)).MultipleTimes() \
230 132
             .AndReturn(quota_data)

+ 0
- 3
openstack_dashboard/dashboards/project/access_and_security/urls.py View File

@@ -19,8 +19,6 @@
19 19
 from django.conf.urls import include
20 20
 from django.conf.urls import url
21 21
 
22
-from openstack_dashboard.dashboards.project.access_and_security.\
23
-    floating_ips import urls as fip_urls
24 22
 from openstack_dashboard.dashboards.project.access_and_security.\
25 23
     security_groups import urls as sec_group_urls
26 24
 from openstack_dashboard.dashboards.project.access_and_security import views
@@ -28,7 +26,6 @@ from openstack_dashboard.dashboards.project.access_and_security import views
28 26
 
29 27
 urlpatterns = [
30 28
     url(r'^$', views.IndexView.as_view(), name='index'),
31
-    url(r'floating_ips/', include(fip_urls, namespace='floating_ips')),
32 29
     url(r'security_groups/',
33 30
         include(sec_group_urls, namespace='security_groups')),
34 31
 ]

openstack_dashboard/dashboards/project/access_and_security/floating_ips/__init__.py → openstack_dashboard/dashboards/project/floating_ips/__init__.py View File


openstack_dashboard/dashboards/project/access_and_security/floating_ips/forms.py → openstack_dashboard/dashboards/project/floating_ips/forms.py View File


+ 27
- 0
openstack_dashboard/dashboards/project/floating_ips/panel.py View File

@@ -0,0 +1,27 @@
1
+# Copyright 2017 Cisco Systems, Inc.
2
+#
3
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+#    not use this file except in compliance with the License. You may obtain
5
+#    a copy of the License at
6
+#
7
+#         http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+#    Unless required by applicable law or agreed to in writing, software
10
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+#    License for the specific language governing permissions and limitations
13
+#    under the License.
14
+
15
+from django.conf import settings
16
+from django.utils.translation import ugettext_lazy as _
17
+import horizon
18
+
19
+
20
+class FloatingIps(horizon.Panel):
21
+    name = _("Floating IPs")
22
+    slug = 'floating_ips'
23
+
24
+    @staticmethod
25
+    def can_register():
26
+        network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {})
27
+        return network_config.get('enable_router', True)

openstack_dashboard/dashboards/project/access_and_security/floating_ips/tables.py → openstack_dashboard/dashboards/project/floating_ips/tables.py View File

@@ -41,10 +41,10 @@ class AllocateIP(tables.LinkAction):
41 41
     verbose_name = _("Allocate IP To Project")
42 42
     classes = ("ajax-modal",)
43 43
     icon = "link"
44
-    url = "horizon:project:access_and_security:floating_ips:allocate"
44
+    url = "horizon:project:floating_ips:allocate"
45 45
 
46 46
     def single(self, data_table, request, *args):
47
-        return shortcuts.redirect('horizon:project:access_and_security:index')
47
+        return shortcuts.redirect('horizon:project:floating_ips:index')
48 48
 
49 49
     def allowed(self, request, fip=None):
50 50
         usages = quotas.tenant_quota_usages(request)
@@ -106,7 +106,7 @@ class ReleaseIPs(tables.BatchAction):
106 106
 class AssociateIP(tables.LinkAction):
107 107
     name = "associate"
108 108
     verbose_name = _("Associate")
109
-    url = "horizon:project:access_and_security:floating_ips:associate"
109
+    url = "horizon:project:floating_ips:associate"
110 110
     classes = ("ajax-modal",)
111 111
     icon = "link"
112 112
 
@@ -152,7 +152,7 @@ class DisassociateIP(tables.Action):
152 152
         except Exception:
153 153
             exceptions.handle(request,
154 154
                               _('Unable to disassociate floating IP.'))
155
-        return shortcuts.redirect('horizon:project:access_and_security:index')
155
+        return shortcuts.redirect('horizon:project:floating_ips:index')
156 156
 
157 157
 
158 158
 def get_instance_info(fip):

openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html → openstack_dashboard/dashboards/project/floating_ips/templates/floating_ips/_allocate.html View File


+ 6
- 0
openstack_dashboard/dashboards/project/floating_ips/templates/floating_ips/allocate.html View File

@@ -0,0 +1,6 @@
1
+{% extends 'base.html' %}
2
+{% load i18n %}
3
+
4
+{% block main %}
5
+  {% include 'project/floating_ips/_allocate.html' %}
6
+{% endblock %}

openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py → openstack_dashboard/dashboards/project/floating_ips/tests.py View File

@@ -31,8 +31,8 @@ from openstack_dashboard.usage import quotas
31 31
 from horizon.workflows import views
32 32
 
33 33
 
34
-INDEX_URL = reverse('horizon:project:access_and_security:index')
35
-NAMESPACE = "horizon:project:access_and_security:floating_ips"
34
+INDEX_URL = reverse('horizon:project:floating_ips:index')
35
+NAMESPACE = "horizon:project:floating_ips"
36 36
 
37 37
 
38 38
 class FloatingIpViewTests(test.TestCase):
@@ -167,7 +167,6 @@ class FloatingIpViewTests(test.TestCase):
167 167
 
168 168
     @test.create_stubs({api.nova: ('server_list',),
169 169
                         api.network: ('floating_ip_disassociate',
170
-                                      'floating_ip_supported',
171 170
                                       'tenant_floating_ip_get',
172 171
                                       'tenant_floating_ip_list',),
173 172
                         api.neutron: ('is_extension_supported',)})
@@ -176,8 +175,6 @@ class FloatingIpViewTests(test.TestCase):
176 175
 
177 176
         api.nova.server_list(IsA(http.HttpRequest)) \
178 177
             .AndReturn([self.servers.list(), False])
179
-        api.network.floating_ip_supported(IsA(http.HttpRequest)) \
180
-            .AndReturn(True)
181 178
         api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
182 179
             .AndReturn(self.floating_ips.list())
183 180
         api.neutron.is_extension_supported(IsA(http.HttpRequest),
@@ -194,7 +191,6 @@ class FloatingIpViewTests(test.TestCase):
194 191
 
195 192
     @test.create_stubs({api.nova: ('server_list',),
196 193
                         api.network: ('floating_ip_disassociate',
197
-                                      'floating_ip_supported',
198 194
                                       'tenant_floating_ip_get',
199 195
                                       'tenant_floating_ip_list',),
200 196
                         api.neutron: ('is_extension_supported',)})
@@ -203,8 +199,6 @@ class FloatingIpViewTests(test.TestCase):
203 199
 
204 200
         api.nova.server_list(IsA(http.HttpRequest)) \
205 201
             .AndReturn([self.servers.list(), False])
206
-        api.network.floating_ip_supported(IsA(http.HttpRequest)) \
207
-            .AndReturn(True)
208 202
         api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
209 203
             .AndReturn(self.floating_ips.list())
210 204
         api.neutron.is_extension_supported(IsA(http.HttpRequest),
@@ -220,9 +214,7 @@ class FloatingIpViewTests(test.TestCase):
220 214
         res = self.client.post(INDEX_URL, {"action": action})
221 215
         self.assertRedirectsNoFollow(res, INDEX_URL)
222 216
 
223
-    @test.create_stubs({api.network: ('floating_ip_supported',
224
-                                      'tenant_floating_ip_list',
225
-                                      'security_group_list',
217
+    @test.create_stubs({api.network: ('tenant_floating_ip_list',
226 218
                                       'floating_ip_pools_list',),
227 219
                         api.nova: ('server_list',),
228 220
                         quotas: ('tenant_quota_usages',),
@@ -232,17 +224,10 @@ class FloatingIpViewTests(test.TestCase):
232 224
         floating_pools = self.pools.list()
233 225
         quota_data = self.quota_usages.first()
234 226
         quota_data['floating_ips']['available'] = 10
235
-        sec_groups = self.security_groups.list()
236 227
 
237
-        api.network.floating_ip_supported(
238
-            IsA(http.HttpRequest)) \
239
-            .AndReturn(True)
240 228
         api.network.tenant_floating_ip_list(
241 229
             IsA(http.HttpRequest)) \
242 230
             .AndReturn(floating_ips)
243
-        api.network.security_group_list(
244
-            IsA(http.HttpRequest)).MultipleTimes()\
245
-            .AndReturn(sec_groups)
246 231
         api.network.floating_ip_pools_list(
247 232
             IsA(http.HttpRequest)) \
248 233
             .AndReturn(floating_pools)
@@ -252,7 +237,6 @@ class FloatingIpViewTests(test.TestCase):
252 237
         quotas.tenant_quota_usages(
253 238
             IsA(http.HttpRequest)).MultipleTimes() \
254 239
             .AndReturn(quota_data)
255
-
256 240
         api.base.is_service_enabled(
257 241
             IsA(http.HttpRequest),
258 242
             'network').MultipleTimes() \
@@ -260,8 +244,7 @@ class FloatingIpViewTests(test.TestCase):
260 244
 
261 245
         self.mox.ReplayAll()
262 246
 
263
-        res = self.client.get(INDEX_URL +
264
-                              "?tab=access_security_tabs__floating_ips_tab")
247
+        res = self.client.get(INDEX_URL)
265 248
 
266 249
         allocate_action = self.getAndAssertTableAction(res, 'floating_ips',
267 250
                                                        'allocate')
@@ -270,12 +253,10 @@ class FloatingIpViewTests(test.TestCase):
270 253
                          six.text_type(allocate_action.verbose_name))
271 254
         self.assertIsNone(allocate_action.policy_rules)
272 255
 
273
-        url = 'horizon:project:access_and_security:floating_ips:allocate'
256
+        url = 'horizon:project:floating_ips:allocate'
274 257
         self.assertEqual(url, allocate_action.url)
275 258
 
276
-    @test.create_stubs({api.network: ('floating_ip_supported',
277
-                                      'tenant_floating_ip_list',
278
-                                      'security_group_list',
259
+    @test.create_stubs({api.network: ('tenant_floating_ip_list',
279 260
                                       'floating_ip_pools_list',),
280 261
                         api.nova: ('server_list',),
281 262
                         quotas: ('tenant_quota_usages',),
@@ -285,17 +266,10 @@ class FloatingIpViewTests(test.TestCase):
285 266
         floating_pools = self.pools.list()
286 267
         quota_data = self.quota_usages.first()
287 268
         quota_data['floating_ips']['available'] = 0
288
-        sec_groups = self.security_groups.list()
289 269
 
290
-        api.network.floating_ip_supported(
291
-            IsA(http.HttpRequest)) \
292
-            .AndReturn(True)
293 270
         api.network.tenant_floating_ip_list(
294 271
             IsA(http.HttpRequest)) \
295 272
             .AndReturn(floating_ips)
296
-        api.network.security_group_list(
297
-            IsA(http.HttpRequest)).MultipleTimes()\
298
-            .AndReturn(sec_groups)
299 273
         api.network.floating_ip_pools_list(
300 274
             IsA(http.HttpRequest)) \
301 275
             .AndReturn(floating_pools)
@@ -305,7 +279,6 @@ class FloatingIpViewTests(test.TestCase):
305 279
         quotas.tenant_quota_usages(
306 280
             IsA(http.HttpRequest)).MultipleTimes() \
307 281
             .AndReturn(quota_data)
308
-
309 282
         api.base.is_service_enabled(
310 283
             IsA(http.HttpRequest),
311 284
             'network').MultipleTimes() \
@@ -313,8 +286,7 @@ class FloatingIpViewTests(test.TestCase):
313 286
 
314 287
         self.mox.ReplayAll()
315 288
 
316
-        res = self.client.get(INDEX_URL +
317
-                              "?tab=access_security_tabs__floating_ips_tab")
289
+        res = self.client.get(INDEX_URL)
318 290
 
319 291
         allocate_action = self.getAndAssertTableAction(res, 'floating_ips',
320 292
                                                        'allocate')

openstack_dashboard/dashboards/project/access_and_security/floating_ips/urls.py → openstack_dashboard/dashboards/project/floating_ips/urls.py View File

@@ -18,11 +18,10 @@
18 18
 
19 19
 from django.conf.urls import url
20 20
 
21
-from openstack_dashboard.dashboards.project.access_and_security.\
22
-    floating_ips import views
23
-
21
+from openstack_dashboard.dashboards.project.floating_ips import views
24 22
 
25 23
 urlpatterns = [
24
+    url(r'^$', views.IndexView.as_view(), name='index'),
26 25
     url(r'^associate/$', views.AssociateView.as_view(), name='associate'),
27 26
     url(r'^allocate/$', views.AllocateView.as_view(), name='allocate'),
28 27
 ]

openstack_dashboard/dashboards/project/access_and_security/floating_ips/views.py → openstack_dashboard/dashboards/project/floating_ips/views.py View File

@@ -28,15 +28,18 @@ from neutronclient.common import exceptions as neutron_exc
28 28
 
29 29
 from horizon import exceptions
30 30
 from horizon import forms
31
+from horizon import tables
31 32
 from horizon import workflows
32 33
 
33 34
 from openstack_dashboard import api
34 35
 from openstack_dashboard.usage import quotas
35 36
 
36
-from openstack_dashboard.dashboards.project.access_and_security.\
37
-    floating_ips import forms as project_forms
38
-from openstack_dashboard.dashboards.project.access_and_security.\
39
-    floating_ips import workflows as project_workflows
37
+from openstack_dashboard.dashboards.project.floating_ips \
38
+    import forms as project_forms
39
+from openstack_dashboard.dashboards.project.floating_ips \
40
+    import tables as project_tables
41
+from openstack_dashboard.dashboards.project.floating_ips \
42
+    import workflows as project_workflows
40 43
 
41 44
 
42 45
 class AssociateView(workflows.WorkflowView):
@@ -47,11 +50,10 @@ class AllocateView(forms.ModalFormView):
47 50
     form_class = project_forms.FloatingIpAllocate
48 51
     form_id = "associate_floating_ip_form"
49 52
     page_title = _("Allocate Floating IP")
50
-    template_name = 'project/access_and_security/floating_ips/allocate.html'
53
+    template_name = 'project/floating_ips/allocate.html'
51 54
     submit_label = _("Allocate IP")
52
-    submit_url = reverse_lazy(
53
-        "horizon:project:access_and_security:floating_ips:allocate")
54
-    success_url = reverse_lazy('horizon:project:access_and_security:index')
55
+    submit_url = reverse_lazy("horizon:project:floating_ips:allocate")
56
+    success_url = reverse_lazy('horizon:project:floating_ips:index')
55 57
 
56 58
     def get_object_display(self, obj):
57 59
         return obj.ip
@@ -78,3 +80,51 @@ class AllocateView(forms.ModalFormView):
78 80
         if not pool_list:
79 81
             pool_list = [(None, _("No floating IP pools available"))]
80 82
         return {'pool_list': pool_list}
83
+
84
+
85
+class IndexView(tables.DataTableView):
86
+    table_class = project_tables.FloatingIPsTable
87
+    page_title = _("Floating IPs")
88
+
89
+    def get_data(self):
90
+        try:
91
+            floating_ips = api.network.tenant_floating_ip_list(self.request)
92
+        except neutron_exc.ConnectionFailed:
93
+            floating_ips = []
94
+            exceptions.handle(self.request)
95
+        except Exception:
96
+            floating_ips = []
97
+            exceptions.handle(self.request,
98
+                              _('Unable to retrieve floating IP addresses.'))
99
+
100
+        try:
101
+            floating_ip_pools = \
102
+                api.network.floating_ip_pools_list(self.request)
103
+        except neutron_exc.ConnectionFailed:
104
+            floating_ip_pools = []
105
+            exceptions.handle(self.request)
106
+        except Exception:
107
+            floating_ip_pools = []
108
+            exceptions.handle(self.request,
109
+                              _('Unable to retrieve floating IP pools.'))
110
+        pool_dict = dict([(obj.id, obj.name) for obj in floating_ip_pools])
111
+
112
+        attached_instance_ids = [ip.instance_id for ip in floating_ips
113
+                                 if ip.instance_id is not None]
114
+        if attached_instance_ids:
115
+            instances = []
116
+            try:
117
+                # TODO(tsufiev): we should pass attached_instance_ids to
118
+                # nova.server_list as soon as Nova API allows for this
119
+                instances, has_more = api.nova.server_list(self.request)
120
+            except Exception:
121
+                exceptions.handle(self.request,
122
+                                  _('Unable to retrieve instance list.'))
123
+
124
+            instances_dict = dict([(obj.id, obj.name) for obj in instances])
125
+
126
+            for ip in floating_ips:
127
+                ip.instance_name = instances_dict.get(ip.instance_id)
128
+                ip.pool_name = pool_dict.get(ip.pool, ip.pool)
129
+
130
+        return floating_ips

openstack_dashboard/dashboards/project/access_and_security/floating_ips/workflows.py → openstack_dashboard/dashboards/project/floating_ips/workflows.py View File

@@ -26,7 +26,7 @@ from openstack_dashboard import api
26 26
 from openstack_dashboard.utils import filters
27 27
 
28 28
 
29
-ALLOCATE_URL = "horizon:project:access_and_security:floating_ips:allocate"
29
+ALLOCATE_URL = "horizon:project:floating_ips:allocate"
30 30
 
31 31
 
32 32
 class AssociateIPAction(workflows.Action):
@@ -72,7 +72,7 @@ class AssociateIPAction(workflows.Action):
72 72
 
73 73
     def populate_ip_id_choices(self, request, context):
74 74
         ips = []
75
-        redirect = reverse('horizon:project:access_and_security:index')
75
+        redirect = reverse('horizon:project:floating_ips:index')
76 76
         try:
77 77
             ips = api.network.tenant_floating_ip_list(self.request)
78 78
         except neutron_exc.ConnectionFailed:
@@ -95,7 +95,7 @@ class AssociateIPAction(workflows.Action):
95 95
         try:
96 96
             targets = api.network.floating_ip_target_list(self.request)
97 97
         except Exception:
98
-            redirect = reverse('horizon:project:access_and_security:index')
98
+            redirect = reverse('horizon:project:floating_ips:index')
99 99
             exceptions.handle(self.request,
100 100
                               _('Unable to retrieve instance list.'),
101 101
                               redirect=redirect)
@@ -146,7 +146,7 @@ class IPAssociationWorkflow(workflows.Workflow):
146 146
     finalize_button_name = _("Associate")
147 147
     success_message = _('IP address %s associated.')
148 148
     failure_message = _('Unable to associate IP address %s.')
149
-    success_url = "horizon:project:access_and_security:index"
149
+    success_url = "horizon:project:floating_ips:index"
150 150
     default_steps = (AssociateIP,)
151 151
 
152 152
     def format_status_message(self, message):

+ 2
- 3
openstack_dashboard/dashboards/project/instances/tables.py View File

@@ -36,8 +36,7 @@ from horizon.templatetags import sizeformat
36 36
 from horizon.utils import filters
37 37
 
38 38
 from openstack_dashboard import api
39
-from openstack_dashboard.dashboards.project.access_and_security.floating_ips \
40
-    import workflows
39
+from openstack_dashboard.dashboards.project.floating_ips import workflows
41 40
 from openstack_dashboard.dashboards.project.instances import tabs
42 41
 from openstack_dashboard.dashboards.project.instances.workflows \
43 42
     import resize_instance
@@ -617,7 +616,7 @@ class DecryptInstancePassword(tables.LinkAction):
617 616
 class AssociateIP(policy.PolicyTargetMixin, tables.LinkAction):
618 617
     name = "associate"
619 618
     verbose_name = _("Associate Floating IP")
620
-    url = "horizon:project:access_and_security:floating_ips:associate"
619
+    url = "horizon:project:floating_ips:associate"
621 620
     classes = ("ajax-modal",)
622 621
     icon = "link"
623 622
     policy_rules = (("compute", "network:associate_floating_ip"),)

+ 6
- 0
openstack_dashboard/enabled/_1490_project_floating_ips_panel.py View File

@@ -0,0 +1,6 @@
1
+PANEL_DASHBOARD = 'project'
2
+PANEL_GROUP = 'network'
3
+PANEL = 'floating_ips'
4
+
5
+ADD_PANEL = \
6
+    'openstack_dashboard.dashboards.project.floating_ips.panel.FloatingIps'

Loading…
Cancel
Save