diff options
author | Jenkins <jenkins@review.openstack.org> | 2014-04-29 16:01:45 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2014-04-29 16:01:45 +0000 |
commit | d933ad09a271f0a4215b2dfd393e110cdc69fcf5 (patch) | |
tree | a81bc5494ea78331b640e111d3e3b13271d50e60 | |
parent | cd1de75ee2a8c246d5564e96ccc48185816c2290 (diff) | |
parent | f3557786e2a9f026a16d2fd3b8fa9243bc4c70a9 (diff) | |
download | horizon-d933ad09a271f0a4215b2dfd393e110cdc69fcf5.tar.gz |
Merge "Get instance networking information from Neutron" into stable/havana
-rw-r--r-- | openstack_dashboard/api/network.py | 12 | ||||
-rw-r--r-- | openstack_dashboard/api/neutron.py | 89 | ||||
-rw-r--r-- | openstack_dashboard/dashboards/admin/instances/tests.py | 26 | ||||
-rw-r--r-- | openstack_dashboard/dashboards/admin/instances/views.py | 8 | ||||
-rw-r--r-- | openstack_dashboard/dashboards/project/instances/tests.py | 184 | ||||
-rw-r--r-- | openstack_dashboard/dashboards/project/instances/views.py | 20 |
6 files changed, 271 insertions, 68 deletions
diff --git a/openstack_dashboard/api/network.py b/openstack_dashboard/api/network.py index 7ab233c5c..ea76d4172 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 4443c9b13..c09a6743b 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 6beb8fad7..9236b4eca 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 3397f2599..4bc6beec5 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 8d5645578..b2b066ff4 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)) @@ -1833,18 +1898,21 @@ class InstanceTests(test.TestCase): @test.create_stubs({api.network: ('floating_ip_target_get_by_instance', 'tenant_floating_ip_list', - 'floating_ip_disassociate',), + 'floating_ip_disassociate', + 'servers_update_addresses',), api.glance: ('image_list_detailed',), 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 4826d8a69..cebc5c0d5 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): |