summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-04-29 16:01:45 +0000
committerGerrit Code Review <review@openstack.org>2014-04-29 16:01:45 +0000
commitd933ad09a271f0a4215b2dfd393e110cdc69fcf5 (patch)
treea81bc5494ea78331b640e111d3e3b13271d50e60
parentcd1de75ee2a8c246d5564e96ccc48185816c2290 (diff)
parentf3557786e2a9f026a16d2fd3b8fa9243bc4c70a9 (diff)
downloadhorizon-d933ad09a271f0a4215b2dfd393e110cdc69fcf5.tar.gz
Merge "Get instance networking information from Neutron" into stable/havana
-rw-r--r--openstack_dashboard/api/network.py12
-rw-r--r--openstack_dashboard/api/neutron.py89
-rw-r--r--openstack_dashboard/dashboards/admin/instances/tests.py26
-rw-r--r--openstack_dashboard/dashboards/admin/instances/views.py8
-rw-r--r--openstack_dashboard/dashboards/project/instances/tests.py184
-rw-r--r--openstack_dashboard/dashboards/project/instances/views.py20
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):