components/openstack/horizon/patches/12-launchpad-1265032.patch
branchs11u2-sru
changeset 4156 4b1def16fe9b
parent 4146 097063f324c0
child 4157 92532a6159e7
--- a/components/openstack/horizon/patches/12-launchpad-1265032.patch	Thu Apr 16 01:36:32 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,868 +0,0 @@
-Upstream patch to fix launchpad bug 1265032.  This fix is available in
-Icehouse 2014.1 but not yet available in Havana.
-
-From f3557786e2a9f026a16d2fd3b8fa9243bc4c70a9 Mon Sep 17 00:00:00 2001
-From: Assaf Muller <[email protected]>
-Date: Sun, 29 Dec 2013 16:44:46 +0200
-Subject: Get instance networking information from Neutron
-
-project/instances, admin/instances and the instance details page
-all get networking information from Nova. However, with Neutron
-enabled, floating IP associations are done direcly with Neutron,
-meaning that Nova's DB will fall out of sync and thus the GUI
-won't reflect successful floating IP associations until Nova
-polls Neutron again and updates its DB. The polling can take
-up to several minutes to complete for consecutive floating IP
-operations.
-
-The solution is to update instances' networking information from
-Neutron immediately after the call to list Nova instances.
-
-Conflicts:
-	openstack_dashboard/dashboards/project/instances/tests.py
-	openstack_dashboard/dashboards/project/instances/views.py
-
-Closes-Bug: #1265032
-Change-Id: I0382fa9a4a9fff21e7b4d05cd3b76783f826735f
-(cherry picked from commit 715d6b822838009530b7792cd7749164ae3fc663)
-
-diff --git a/openstack_dashboard/api/network.py b/openstack_dashboard/api/network.py
-index 7ab233c..ea76d41 100644
---- a/openstack_dashboard/api/network.py
-+++ b/openstack_dashboard/api/network.py
-@@ -132,3 +132,15 @@ def server_update_security_groups(request, instance_id,
- 
- def security_group_backend(request):
-     return NetworkClient(request).secgroups.backend
-+
-+
-+def servers_update_addresses(request, servers):
-+    """Retrieve servers networking information from Neutron if enabled.
-+
-+       Should be used when up to date networking information is required,
-+       and Nova's networking info caching mechanism is not fast enough.
-+
-+    """
-+    neutron_enabled = base.is_service_enabled(request, 'network')
-+    if neutron_enabled:
-+        neutron.servers_update_addresses(request, servers)
-diff --git a/openstack_dashboard/api/neutron.py b/openstack_dashboard/api/neutron.py
-index 4443c9b..c09a674 100644
---- a/openstack_dashboard/api/neutron.py
-+++ b/openstack_dashboard/api/neutron.py
-@@ -21,12 +21,15 @@
- 
- from __future__ import absolute_import
- 
-+import collections
- import logging
-+import netaddr
- 
- from django.conf import settings  # noqa
- from django.utils.datastructures import SortedDict  # noqa
- from django.utils.translation import ugettext_lazy as _  # noqa
- 
-+from horizon import messages
- from horizon.utils.memoized import memoized  # noqa
- 
- from openstack_dashboard.api import base
-@@ -321,12 +324,12 @@ class FloatingIpManager(network_base.FloatingIpManager):
-         return [FloatingIpPool(pool) for pool
-                 in self.client.list_networks(**search_opts).get('networks')]
- 
--    def list(self):
-+    def list(self, **search_opts):
-         tenant_id = self.request.user.tenant_id
-         # In Neutron, list_floatingips returns Floating IPs from all tenants
-         # when the API is called with admin role, so we need to filter them
-         # with tenant_id.
--        fips = self.client.list_floatingips(tenant_id=tenant_id)
-+        fips = self.client.list_floatingips(tenant_id=tenant_id, **search_opts)
-         fips = fips.get('floatingips')
-         # Get port list to add instance_id to floating IP list
-         # instance_id is stored in device_id attribute
-@@ -727,6 +730,88 @@ def provider_list(request):
-     return providers['service_providers']
- 
- 
-+def servers_update_addresses(request, servers):
-+    """Retrieve servers networking information from Neutron if enabled.
-+
-+       Should be used when up to date networking information is required,
-+       and Nova's networking info caching mechanism is not fast enough.
-+    """
-+
-+    # Get all (filtered for relevant servers) information from Neutron
-+    try:
-+        ports = port_list(request,
-+                          device_id=[instance.id for instance in servers])
-+        floating_ips = FloatingIpManager(request).list(
-+            port_id=[port.id for port in ports])
-+        networks = network_list(request,
-+                                id=[port.network_id for port in ports])
-+    except Exception:
-+        error_message = _('Unable to connect to Neutron.')
-+        LOG.error(error_message)
-+        messages.error(request, error_message)
-+        return
-+
-+    # Map instance to its ports
-+    instances_ports = collections.defaultdict(list)
-+    for port in ports:
-+        instances_ports[port.device_id].append(port)
-+
-+    # Map port to its floating ips
-+    ports_floating_ips = collections.defaultdict(list)
-+    for fip in floating_ips:
-+        ports_floating_ips[fip.port_id].append(fip)
-+
-+    # Map network id to its name
-+    network_names = dict(((network.id, network.name) for network in networks))
-+
-+    for server in servers:
-+        try:
-+            addresses = _server_get_addresses(
-+                request,
-+                server,
-+                instances_ports,
-+                ports_floating_ips,
-+                network_names)
-+        except Exception as e:
-+            LOG.error(e)
-+        else:
-+            server.addresses = addresses
-+
-+
-+def _server_get_addresses(request, server, ports, floating_ips, network_names):
-+    def _format_address(mac, ip, type):
-+        try:
-+            version = netaddr.IPAddress(ip).version
-+        except Exception as e:
-+            error_message = _('Unable to parse IP address %s.') % ip
-+            LOG.error(error_message)
-+            messages.error(request, error_message)
-+            raise e
-+        return {u'OS-EXT-IPS-MAC:mac_addr': mac,
-+                u'version': version,
-+                u'addr': ip,
-+                u'OS-EXT-IPS:type': type}
-+
-+    addresses = collections.defaultdict(list)
-+    instance_ports = ports.get(server.id, [])
-+    for port in instance_ports:
-+        network_name = network_names.get(port.network_id)
-+        if network_name is not None:
-+            for fixed_ip in port.fixed_ips:
-+                addresses[network_name].append(
-+                    _format_address(port.mac_address,
-+                                    fixed_ip['ip_address'],
-+                                    u'fixed'))
-+            port_fips = floating_ips.get(port.id, [])
-+            for fip in port_fips:
-+                addresses[network_name].append(
-+                    _format_address(port.mac_address,
-+                                    fip.floating_ip_address,
-+                                    u'floating'))
-+
-+    return dict(addresses)
-+
-+
- @memoized
- def list_extensions(request):
-     extensions_list = neutronclient(request).list_extensions()
-diff --git a/openstack_dashboard/dashboards/admin/instances/tests.py b/openstack_dashboard/dashboards/admin/instances/tests.py
-index 6beb8fa..9236b4e 100644
---- a/openstack_dashboard/dashboards/admin/instances/tests.py
-+++ b/openstack_dashboard/dashboards/admin/instances/tests.py
-@@ -20,6 +20,7 @@ from django.core.urlresolvers import reverse  # noqa
- from django import http
- from django.utils.datastructures import SortedDict  # noqa
- 
-+from mox import IgnoreArg  # noqa
- from mox import IsA  # noqa
- 
- from openstack_dashboard import api
-@@ -29,7 +30,8 @@ from openstack_dashboard.test import helpers as test
- class InstanceViewTest(test.BaseAdminViewTests):
-     @test.create_stubs({api.nova: ('flavor_list', 'server_list',
-                                    'extension_supported',),
--                        api.keystone: ('tenant_list',)})
-+                        api.keystone: ('tenant_list',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_index(self):
-         servers = self.servers.list()
-         flavors = self.flavors.list()
-@@ -42,6 +44,7 @@ class InstanceViewTest(test.BaseAdminViewTests):
-         api.nova.server_list(IsA(http.HttpRequest),
-                              all_tenants=True, search_opts=search_opts) \
-                                 .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
-         self.mox.ReplayAll()
- 
-@@ -52,7 +55,8 @@ class InstanceViewTest(test.BaseAdminViewTests):
- 
-     @test.create_stubs({api.nova: ('flavor_list', 'flavor_get',
-                                     'server_list', 'extension_supported',),
--                        api.keystone: ('tenant_list',)})
-+                        api.keystone: ('tenant_list',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_index_flavor_list_exception(self):
-         servers = self.servers.list()
-         tenants = self.tenants.list()
-@@ -63,6 +67,7 @@ class InstanceViewTest(test.BaseAdminViewTests):
-         api.nova.server_list(IsA(http.HttpRequest),
-                              all_tenants=True, search_opts=search_opts) \
-                                 .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
-             .MultipleTimes().AndReturn(True)
-         api.nova.flavor_list(IsA(http.HttpRequest)). \
-@@ -82,7 +87,8 @@ class InstanceViewTest(test.BaseAdminViewTests):
- 
-     @test.create_stubs({api.nova: ('flavor_list', 'flavor_get',
-                                     'server_list', 'extension_supported', ),
--                        api.keystone: ('tenant_list',)})
-+                        api.keystone: ('tenant_list',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_index_flavor_get_exception(self):
-         servers = self.servers.list()
-         flavors = self.flavors.list()
-@@ -96,6 +102,7 @@ class InstanceViewTest(test.BaseAdminViewTests):
-         api.nova.server_list(IsA(http.HttpRequest),
-                              all_tenants=True, search_opts=search_opts) \
-                                 .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
-             .MultipleTimes().AndReturn(True)
-         api.nova.flavor_list(IsA(http.HttpRequest)). \
-@@ -162,14 +169,17 @@ class InstanceViewTest(test.BaseAdminViewTests):
- 
-     @test.create_stubs({api.nova: ('flavor_list', 'server_list',
-                                    'extension_supported', ),
--                        api.keystone: ('tenant_list',)})
-+                        api.keystone: ('tenant_list',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_index_options_before_migrate(self):
-+        servers = self.servers.list()
-         api.keystone.tenant_list(IsA(http.HttpRequest)).\
-             AndReturn([self.tenants.list(), False])
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest),
-                              all_tenants=True, search_opts=search_opts) \
--                                .AndReturn([self.servers.list(), False])
-+                                .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
-             .MultipleTimes().AndReturn(True)
-         api.nova.flavor_list(IsA(http.HttpRequest)).\
-@@ -183,7 +193,8 @@ class InstanceViewTest(test.BaseAdminViewTests):
- 
-     @test.create_stubs({api.nova: ('flavor_list', 'server_list',
-                                    'extension_supported', ),
--                        api.keystone: ('tenant_list',)})
-+                        api.keystone: ('tenant_list',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_index_options_after_migrate(self):
-         servers = self.servers.list()
-         server1 = servers[0]
-@@ -197,7 +208,8 @@ class InstanceViewTest(test.BaseAdminViewTests):
-             .MultipleTimes().AndReturn(True)
-         api.nova.server_list(IsA(http.HttpRequest),
-                              all_tenants=True, search_opts=search_opts) \
--                                .AndReturn([self.servers.list(), False])
-+                                .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IsA(http.HttpRequest)).\
-                              AndReturn(self.flavors.list())
-         self.mox.ReplayAll()
-diff --git a/openstack_dashboard/dashboards/admin/instances/views.py b/openstack_dashboard/dashboards/admin/instances/views.py
-index 3397f25..4bc6bee 100644
---- a/openstack_dashboard/dashboards/admin/instances/views.py
-+++ b/openstack_dashboard/dashboards/admin/instances/views.py
-@@ -74,6 +74,14 @@ class AdminIndexView(tables.DataTableView):
-             exceptions.handle(self.request,
-                               _('Unable to retrieve instance list.'))
-         if instances:
-+            try:
-+                api.network.servers_update_addresses(self.request, instances)
-+            except Exception:
-+                exceptions.handle(
-+                    self.request,
-+                    message=_('Unable to retrieve IP addresses from Neutron.'),
-+                    ignore=True)
-+
-             # Gather our flavors to correlate against IDs
-             try:
-                 flavors = api.nova.flavor_list(self.request)
-diff --git a/openstack_dashboard/dashboards/project/instances/tests.py b/openstack_dashboard/dashboards/project/instances/tests.py
-index 8d56455..b2b066f 100644
---- a/openstack_dashboard/dashboards/project/instances/tests.py
-+++ b/openstack_dashboard/dashboards/project/instances/tests.py
-@@ -52,9 +52,11 @@ class InstanceTests(test.TestCase):
-                                    'extension_supported',),
-                         api.glance: ('image_list_detailed',),
-                         api.network:
--                            ('floating_ip_simple_associate_supported',),
-+                            ('floating_ip_simple_associate_supported',
-+                             'servers_update_addresses',),
-                         })
-     def test_index(self):
-+        servers = self.servers.list()
-         api.nova.extension_supported('AdminActions',
-                                      IsA(http.HttpRequest)) \
-             .MultipleTimes().AndReturn(True)
-@@ -64,7 +66,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
-            .MultipleTimes().AndReturn(self.limits['absolute'])
-         api.network.floating_ip_simple_associate_supported(
-@@ -104,7 +107,8 @@ class InstanceTests(test.TestCase):
-                                    'extension_supported',),
-                         api.glance: ('image_list_detailed',),
-                         api.network:
--                            ('floating_ip_simple_associate_supported',),
-+                            ('floating_ip_simple_associate_supported',
-+                             'servers_update_addresses',),
-                         })
-     def test_index_flavor_list_exception(self):
-         servers = self.servers.list()
-@@ -116,6 +120,7 @@ class InstanceTests(test.TestCase):
-             .MultipleTimes().AndReturn(True)
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
-             .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IsA(http.HttpRequest)) \
-             .AndRaise(self.exceptions.nova)
-         api.glance.image_list_detailed(IgnoreArg()) \
-@@ -144,7 +149,8 @@ class InstanceTests(test.TestCase):
-                                    'extension_supported',),
-                         api.glance: ('image_list_detailed',),
-                         api.network:
--                            ('floating_ip_simple_associate_supported',),
-+                            ('floating_ip_simple_associate_supported',
-+                             'servers_update_addresses',),
-                         })
-     def test_index_flavor_get_exception(self):
-         servers = self.servers.list()
-@@ -160,6 +166,7 @@ class InstanceTests(test.TestCase):
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
-             .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
-         api.glance.image_list_detailed(IgnoreArg()) \
-             .AndReturn((self.images.list(), False))
-@@ -187,7 +194,8 @@ class InstanceTests(test.TestCase):
-                                    'extension_supported',),
-                         api.glance: ('image_list_detailed',),
-                         api.network:
--                            ('floating_ip_simple_associate_supported',),
-+                            ('floating_ip_simple_associate_supported',
-+                             'servers_update_addresses',),
-                         })
-     def test_index_with_instance_booted_from_volume(self):
-         volume_server = self.servers.first()
-@@ -206,6 +214,7 @@ class InstanceTests(test.TestCase):
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
-             .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
-            .MultipleTimes().AndReturn(self.limits['absolute'])
-         api.network.floating_ip_simple_associate_supported(
-@@ -223,18 +232,20 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ('server_list',
-                                    'flavor_list',
-                                    'server_delete',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_terminate_instance(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
-         api.glance.image_list_detailed(IgnoreArg()) \
-             .AndReturn((self.images.list(), False))
-         api.nova.server_delete(IsA(http.HttpRequest), server.id)
--
-         self.mox.ReplayAll()
- 
-         formData = {'action': 'instances__terminate__%s' % server.id}
-@@ -245,13 +256,16 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ('server_list',
-                                    'flavor_list',
-                                    'server_delete',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_terminate_instance_exception(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
-         api.glance.image_list_detailed(IgnoreArg()) \
-             .AndReturn((self.images.list(), False))
-@@ -269,9 +283,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_pause_instance(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         api.nova.extension_supported('AdminActions',
-                                      IsA(http.HttpRequest)) \
-@@ -282,7 +298,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_pause(IsA(http.HttpRequest), server.id)
- 
-         self.mox.ReplayAll()
-@@ -296,9 +313,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_pause_instance_exception(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         api.nova.extension_supported('AdminActions',
-                                      IsA(http.HttpRequest)) \
-@@ -309,7 +328,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_pause(IsA(http.HttpRequest), server.id) \
-                         .AndRaise(self.exceptions.nova)
- 
-@@ -324,9 +344,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_unpause_instance(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
-         server.status = "PAUSED"
-         api.nova.extension_supported('AdminActions',
-                                      IsA(http.HttpRequest)) \
-@@ -337,7 +359,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_unpause(IsA(http.HttpRequest), server.id)
- 
-         self.mox.ReplayAll()
-@@ -351,9 +374,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_unpause_instance_exception(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
-         server.status = "PAUSED"
- 
-         api.nova.extension_supported('AdminActions',
-@@ -365,7 +390,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_unpause(IsA(http.HttpRequest), server.id) \
-                           .AndRaise(self.exceptions.nova)
- 
-@@ -379,16 +405,19 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ('server_reboot',
-                                    'server_list',
-                                    'flavor_list',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_reboot_instance(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
-         api.nova.flavor_list(IsA(http.HttpRequest)) \
-             .AndReturn(self.flavors.list())
-         api.glance.image_list_detailed(IgnoreArg()) \
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_reboot(IsA(http.HttpRequest), server.id,
-                                soft_reboot=False)
- 
-@@ -402,9 +431,11 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ('server_reboot',
-                                    'server_list',
-                                    'flavor_list',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_reboot_instance_exception(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         api.nova.flavor_list(IsA(http.HttpRequest)) \
-             .AndReturn(self.flavors.list())
-@@ -412,7 +443,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_reboot(IsA(http.HttpRequest), server.id,
-                                soft_reboot=False) \
-             .AndRaise(self.exceptions.nova)
-@@ -427,9 +459,11 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ('server_reboot',
-                                    'server_list',
-                                    'flavor_list',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_soft_reboot_instance(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         api.nova.flavor_list(IsA(http.HttpRequest)) \
-             .AndReturn(self.flavors.list())
-@@ -437,7 +471,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_reboot(IsA(http.HttpRequest), server.id,
-                                soft_reboot=True)
- 
-@@ -452,9 +487,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_suspend_instance(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         api.nova.extension_supported('AdminActions',
-                                      IsA(http.HttpRequest)) \
-@@ -465,7 +502,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_suspend(IsA(http.HttpRequest), unicode(server.id))
- 
-         self.mox.ReplayAll()
-@@ -479,9 +517,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_suspend_instance_exception(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
- 
-         api.nova.extension_supported('AdminActions',
-                                      IsA(http.HttpRequest)) \
-@@ -492,7 +532,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_suspend(IsA(http.HttpRequest), unicode(server.id)) \
-             .AndRaise(self.exceptions.nova)
- 
-@@ -507,9 +548,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_resume_instance(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
-         server.status = "SUSPENDED"
- 
-         api.nova.extension_supported('AdminActions',
-@@ -521,7 +564,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_resume(IsA(http.HttpRequest), unicode(server.id))
- 
-         self.mox.ReplayAll()
-@@ -535,9 +579,11 @@ class InstanceTests(test.TestCase):
-                                    'server_list',
-                                    'flavor_list',
-                                    'extension_supported',),
--                        api.glance: ('image_list_detailed',)})
-+                        api.glance: ('image_list_detailed',),
-+                        api.network: ('servers_update_addresses',)})
-     def test_resume_instance_exception(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
-         server.status = "SUSPENDED"
- 
-         api.nova.extension_supported('AdminActions',
-@@ -549,7 +595,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.server_resume(IsA(http.HttpRequest),
-                                unicode(server.id)) \
-             .AndRaise(self.exceptions.nova)
-@@ -564,12 +611,15 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ("server_get",
-                                    "instance_volumes_list",
-                                    "flavor_get"),
--                        api.network: ("server_security_groups",)})
-+                        api.network: ("server_security_groups",
-+                                      "servers_update_addresses")})
-     def test_instance_details_volumes(self):
-         server = self.servers.first()
-         volumes = [self.volumes.list()[1]]
- 
-         api.nova.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
-+        api.network.servers_update_addresses(IsA(http.HttpRequest),
-+                                             IgnoreArg())
-         api.nova.instance_volumes_list(IsA(http.HttpRequest),
-                                        server.id).AndReturn(volumes)
-         api.nova.flavor_get(IsA(http.HttpRequest), server.flavor['id']) \
-@@ -588,12 +638,15 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ("server_get",
-                                    "instance_volumes_list",
-                                    "flavor_get"),
--                        api.network: ("server_security_groups",)})
-+                        api.network: ("server_security_groups",
-+                                      "servers_update_addresses")})
-     def test_instance_details_volume_sorting(self):
-         server = self.servers.first()
-         volumes = self.volumes.list()[1:3]
- 
-         api.nova.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
-+        api.network.servers_update_addresses(IsA(http.HttpRequest),
-+                                             IgnoreArg())
-         api.nova.instance_volumes_list(IsA(http.HttpRequest),
-                                        server.id).AndReturn(volumes)
-         api.nova.flavor_get(IsA(http.HttpRequest), server.flavor['id']) \
-@@ -616,11 +669,14 @@ class InstanceTests(test.TestCase):
-     @test.create_stubs({api.nova: ("server_get",
-                                    "instance_volumes_list",
-                                    "flavor_get"),
--                        api.network: ("server_security_groups",)})
-+                        api.network: ("server_security_groups",
-+                                      "servers_update_addresses")})
-     def test_instance_details_metadata(self):
-         server = self.servers.first()
- 
-         api.nova.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
-+        api.network.servers_update_addresses(IsA(http.HttpRequest),
-+                                             IgnoreArg())
-         api.nova.instance_volumes_list(IsA(http.HttpRequest),
-                                        server.id).AndReturn([])
-         api.nova.flavor_get(IsA(http.HttpRequest), server.flavor['id']) \
-@@ -1668,9 +1724,11 @@ class InstanceTests(test.TestCase):
-                                    'extension_supported',),
-                         api.glance: ('image_list_detailed',),
-                         api.network:
--                            ('floating_ip_simple_associate_supported',),
-+                            ('floating_ip_simple_associate_supported',
-+                             'servers_update_addresses',),
-                         })
-     def test_launch_button_disabled_when_quota_exceeded(self):
-+        servers = self.servers.list()
-         limits = self.limits['absolute']
-         limits['totalInstancesUsed'] = limits['maxTotalInstances']
- 
-@@ -1683,7 +1741,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
-             .MultipleTimes().AndReturn(limits)
-         api.network.floating_ip_simple_associate_supported(
-@@ -1709,9 +1768,11 @@ class InstanceTests(test.TestCase):
-                                    'extension_supported',),
-                         api.glance: ('image_list_detailed',),
-                         api.network:
--                            ('floating_ip_simple_associate_supported',),
-+                            ('floating_ip_simple_associate_supported',
-+                             'servers_update_addresses',),
-                         })
-     def test_index_options_after_migrate(self):
-+        servers = self.servers.list()
-         server = self.servers.first()
-         server.status = "VERIFY_RESIZE"
-         api.nova.extension_supported('AdminActions',
-@@ -1723,7 +1784,8 @@ class InstanceTests(test.TestCase):
-             .AndReturn((self.images.list(), False))
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
-            .MultipleTimes().AndReturn(self.limits['absolute'])
-         api.network.floating_ip_simple_associate_supported(
-@@ -1802,17 +1864,20 @@ class InstanceTests(test.TestCase):
- 
-     @test.create_stubs({api.network: ('floating_ip_target_get_by_instance',
-                                       'tenant_floating_ip_allocate',
--                                      'floating_ip_associate'),
-+                                      'floating_ip_associate',
-+                                      'servers_update_addresses',),
-                         api.glance: ('image_list_detailed',),
-                         api.nova: ('server_list',
-                                    'flavor_list')})
-     def test_associate_floating_ip(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
-         fip = self.q_floating_ips.first()
- 
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
-         api.glance.image_list_detailed(IgnoreArg()) \
-             .AndReturn((self.images.list(), False))
-@@ -1839,13 +1905,15 @@ class InstanceTests(test.TestCase):
- 
-                         api.nova: ('server_list',
-                                    'flavor_list')})
-     def test_disassociate_floating_ip(self):
--        server = self.servers.first()
-+        servers = self.servers.list()
-+        server = servers[0]
-         fip = self.q_floating_ips.first()
-         fip.port_id = server.id
- 
-         search_opts = {'marker': None, 'paginate': True}
-         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
--            .AndReturn([self.servers.list(), False])
-+            .AndReturn([servers, False])
-+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
-         api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
-         api.glance.image_list_detailed(IgnoreArg()) \
-             .AndReturn((self.images.list(), False))
-diff --git a/openstack_dashboard/dashboards/project/instances/views.py b/openstack_dashboard/dashboards/project/instances/views.py
-index 4826d8a..cebc5c0 100644
---- a/openstack_dashboard/dashboards/project/instances/views.py
-+++ b/openstack_dashboard/dashboards/project/instances/views.py
-@@ -66,9 +66,18 @@ class IndexView(tables.DataTableView):
-             instances = []
-             exceptions.handle(self.request,
-                               _('Unable to retrieve instances.'))
--        # Gather our flavors and images and correlate our instances to them
-+
-         if instances:
-             try:
-+                api.network.servers_update_addresses(self.request, instances)
-+            except Exception:
-+                exceptions.handle(
-+                    self.request,
-+                    message=_('Unable to retrieve IP addresses from Neutron.'),
-+                    ignore=True)
-+
-+            # Gather our flavors and images and correlate our instances to them
-+            try:
-                 flavors = api.nova.flavor_list(self.request)
-             except Exception:
-                 flavors = []
-@@ -233,6 +242,15 @@ class DetailView(tabs.TabView):
-                                     'instance "%s".') % instance_id,
-                                     redirect=redirect)
-             self._instance = instance
-+
-+            try:
-+                api.network.servers_update_addresses(self.request, [instance])
-+            except Exception:
-+                exceptions.handle(
-+                    self.request,
-+                    _('Unable to retrieve IP addresses from Neutron for '
-+                      'instance "%s".') % instance_id, ignore=True)
-+
-         return self._instance
- 
-     def get_tabs(self, request, *args, **kwargs):
--- 
-cgit v0.10.1
-