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. Closes-Bug: #1265032 Change-Id: I0382fa9a4a9fff21e7b4d05cd3b76783f826735f
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -732,6 +735,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()
|
||||
|
||||
@@ -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
|
||||
@@ -32,7 +33,8 @@ INDEX_URL = reverse('horizon:admin:instances:index')
|
||||
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()
|
||||
@@ -45,6 +47,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()
|
||||
|
||||
@@ -55,7 +58,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()
|
||||
@@ -66,6 +70,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)). \
|
||||
@@ -85,7 +90,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()
|
||||
@@ -99,6 +105,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)). \
|
||||
@@ -165,14 +172,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)).\
|
||||
@@ -186,7 +196,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]
|
||||
@@ -200,7 +211,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()
|
||||
|
||||
@@ -80,6 +80,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)
|
||||
|
||||
@@ -54,9 +54,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)
|
||||
@@ -66,7 +68,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(
|
||||
@@ -106,7 +109,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()
|
||||
@@ -118,6 +122,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()) \
|
||||
@@ -146,7 +151,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()
|
||||
@@ -162,6 +168,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))
|
||||
@@ -189,7 +196,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()
|
||||
@@ -208,6 +216,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(
|
||||
@@ -225,18 +234,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}
|
||||
@@ -247,13 +258,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))
|
||||
@@ -271,9 +285,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)) \
|
||||
@@ -284,7 +300,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()
|
||||
@@ -298,9 +315,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)) \
|
||||
@@ -311,7 +330,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)
|
||||
|
||||
@@ -326,9 +346,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)) \
|
||||
@@ -339,7 +361,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()
|
||||
@@ -353,9 +376,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',
|
||||
@@ -367,7 +392,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)
|
||||
|
||||
@@ -381,16 +407,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)
|
||||
|
||||
@@ -404,9 +433,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())
|
||||
@@ -414,7 +445,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)
|
||||
@@ -429,9 +461,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())
|
||||
@@ -439,7 +473,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)
|
||||
|
||||
@@ -454,9 +489,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)) \
|
||||
@@ -467,7 +504,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()
|
||||
@@ -481,9 +519,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)) \
|
||||
@@ -494,7 +534,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)
|
||||
|
||||
@@ -509,9 +550,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',
|
||||
@@ -523,7 +566,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()
|
||||
@@ -537,9 +581,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',
|
||||
@@ -551,7 +597,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)
|
||||
@@ -566,12 +613,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']) \
|
||||
@@ -590,12 +640,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']) \
|
||||
@@ -618,11 +671,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']) \
|
||||
@@ -650,7 +706,8 @@ 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_fault(self):
|
||||
server = self.servers.first()
|
||||
|
||||
@@ -666,6 +723,8 @@ class InstanceTests(test.TestCase):
|
||||
"created": "2013-10-07T00:08:32Z"}
|
||||
|
||||
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']) \
|
||||
@@ -1781,9 +1840,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']
|
||||
|
||||
@@ -1796,7 +1857,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(
|
||||
@@ -1822,9 +1884,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',
|
||||
@@ -1836,7 +1900,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(
|
||||
@@ -1915,17 +1980,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))
|
||||
@@ -1946,18 +2014,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))
|
||||
|
||||
@@ -67,8 +67,17 @@ 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:
|
||||
@@ -233,6 +242,13 @@ class DetailView(tabs.TabView):
|
||||
_('Unable to retrieve details for '
|
||||
'instance "%s".') % instance_id,
|
||||
redirect=redirect)
|
||||
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 instance
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user