Server-side filtering for Instances (Project/Admin)
New Filters: - UUID - Flavor Name - Image Name - Availability Zone - Key Name - IPv4 Address - IPv6 - vCPUs - Changes-since. Affected views: Project->Instances and Admin->Instances Implements blueprint: server-side-filtering Change-Id: I3b07674fc1083607cae5d1db5a691827bde46d7c
This commit is contained in:
parent
110175a549
commit
460a53f96d
|
@ -101,14 +101,11 @@ class AdminInstanceFilterAction(tables.FilterAction):
|
||||||
# session property used for persisting the filter.
|
# session property used for persisting the filter.
|
||||||
name = "filter_admin_instances"
|
name = "filter_admin_instances"
|
||||||
filter_type = "server"
|
filter_type = "server"
|
||||||
filter_choices = (('project', _("Project ="), True),
|
filter_choices = (
|
||||||
('host', _("Host ="), True),
|
('project', _("Project Name ="), True),
|
||||||
('name', _("Name ="), True),
|
('tenant_id', _("Project ID ="), True),
|
||||||
('ip', _("IPv4 Address ="), True),
|
('host', _("Host Name ="), True),
|
||||||
('ip6', _("IPv6 Address ="), True),
|
) + project_tables.INSTANCE_FILTER_CHOICES
|
||||||
('status', _("Status ="), True),
|
|
||||||
('image', _("Image ID ="), True),
|
|
||||||
('flavor', _("Flavor ID ="), True))
|
|
||||||
|
|
||||||
|
|
||||||
class AdminInstancesTable(tables.DataTable):
|
class AdminInstancesTable(tables.DataTable):
|
||||||
|
|
|
@ -29,14 +29,17 @@ INDEX_URL = reverse('horizon:admin:instances:index')
|
||||||
|
|
||||||
|
|
||||||
class InstanceViewTest(test.BaseAdminViewTests):
|
class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
@test.create_stubs({api.nova: ('flavor_list', 'server_list',
|
@test.create_stubs({
|
||||||
'extension_supported',),
|
api.nova: ('flavor_list', 'server_list', 'extension_supported',),
|
||||||
api.keystone: ('tenant_list',),
|
api.keystone: ('tenant_list',),
|
||||||
api.network: ('servers_update_addresses',)})
|
api.network: ('servers_update_addresses',),
|
||||||
|
api.glance: ('image_list_detailed',),
|
||||||
|
})
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
servers = self.servers.list()
|
servers = self.servers.list()
|
||||||
flavors = self.flavors.list()
|
flavors = self.flavors.list()
|
||||||
tenants = self.tenants.list()
|
tenants = self.tenants.list()
|
||||||
|
images = self.images.list()
|
||||||
api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
|
api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
|
||||||
.MultipleTimes().AndReturn(True)
|
.MultipleTimes().AndReturn(True)
|
||||||
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
|
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
|
||||||
|
@ -44,12 +47,14 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
api.keystone.tenant_list(IsA(http.HttpRequest)).\
|
api.keystone.tenant_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn([tenants, False])
|
AndReturn([tenants, False])
|
||||||
search_opts = {'marker': None, 'paginate': True}
|
search_opts = {'marker': None, 'paginate': True}
|
||||||
|
api.glance.image_list_detailed(IsA(http.HttpRequest))\
|
||||||
|
.AndReturn(images)
|
||||||
|
api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True, search_opts=search_opts) \
|
all_tenants=True, search_opts=search_opts) \
|
||||||
.AndReturn([servers, False])
|
.AndReturn([servers, False])
|
||||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers,
|
api.network.servers_update_addresses(IsA(http.HttpRequest), servers,
|
||||||
all_tenants=True)
|
all_tenants=True)
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.get(INDEX_URL)
|
res = self.client.get(INDEX_URL)
|
||||||
|
@ -57,16 +62,18 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
instances = res.context['table'].data
|
instances = res.context['table'].data
|
||||||
self.assertItemsEqual(instances, servers)
|
self.assertItemsEqual(instances, servers)
|
||||||
|
|
||||||
@test.create_stubs({api.nova: ('flavor_list', 'flavor_get',
|
@test.create_stubs({
|
||||||
'server_list', 'extension_supported',),
|
api.nova: ('flavor_list', 'flavor_get', 'server_list',
|
||||||
api.keystone: ('tenant_list',),
|
'extension_supported',),
|
||||||
api.network: ('servers_update_addresses',)})
|
api.keystone: ('tenant_list',),
|
||||||
|
api.network: ('servers_update_addresses',),
|
||||||
|
api.glance: ('image_list_detailed',),
|
||||||
|
})
|
||||||
def test_index_flavor_list_exception(self):
|
def test_index_flavor_list_exception(self):
|
||||||
servers = self.servers.list()
|
servers = self.servers.list()
|
||||||
tenants = self.tenants.list()
|
tenants = self.tenants.list()
|
||||||
flavors = self.flavors.list()
|
flavors = self.flavors.list()
|
||||||
full_flavors = OrderedDict([(f.id, f) for f in flavors])
|
full_flavors = OrderedDict([(f.id, f) for f in flavors])
|
||||||
|
|
||||||
search_opts = {'marker': None, 'paginate': True}
|
search_opts = {'marker': None, 'paginate': True}
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True, search_opts=search_opts) \
|
all_tenants=True, search_opts=search_opts) \
|
||||||
|
@ -92,19 +99,26 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
instances = res.context['table'].data
|
instances = res.context['table'].data
|
||||||
self.assertItemsEqual(instances, servers)
|
self.assertItemsEqual(instances, servers)
|
||||||
|
|
||||||
@test.create_stubs({api.nova: ('flavor_list', 'flavor_get',
|
@test.create_stubs({
|
||||||
'server_list', 'extension_supported', ),
|
api.nova: ('flavor_list', 'flavor_get', 'server_list',
|
||||||
api.keystone: ('tenant_list',),
|
'extension_supported',),
|
||||||
api.network: ('servers_update_addresses',)})
|
api.keystone: ('tenant_list',),
|
||||||
|
api.network: ('servers_update_addresses',),
|
||||||
|
api.glance: ('image_list_detailed',),
|
||||||
|
})
|
||||||
def test_index_flavor_get_exception(self):
|
def test_index_flavor_get_exception(self):
|
||||||
servers = self.servers.list()
|
servers = self.servers.list()
|
||||||
flavors = self.flavors.list()
|
flavors = self.flavors.list()
|
||||||
|
images = self.images.list()
|
||||||
tenants = self.tenants.list()
|
tenants = self.tenants.list()
|
||||||
# UUIDs generated using indexes are unlikely to match
|
# UUIDs generated using indexes are unlikely to match
|
||||||
# any of existing flavor ids and are guaranteed to be deterministic.
|
# any of existing flavor ids and are guaranteed to be deterministic.
|
||||||
for i, server in enumerate(servers):
|
for i, server in enumerate(servers):
|
||||||
server.flavor['id'] = str(uuid.UUID(int=i))
|
server.flavor['id'] = str(uuid.UUID(int=i))
|
||||||
|
|
||||||
|
api.glance.image_list_detailed(IsA(http.HttpRequest))\
|
||||||
|
.AndReturn(images)
|
||||||
|
api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
|
||||||
search_opts = {'marker': None, 'paginate': True}
|
search_opts = {'marker': None, 'paginate': True}
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True, search_opts=search_opts) \
|
all_tenants=True, search_opts=search_opts) \
|
||||||
|
@ -115,8 +129,6 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
.MultipleTimes().AndReturn(True)
|
.MultipleTimes().AndReturn(True)
|
||||||
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
|
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
|
||||||
.MultipleTimes().AndReturn(True)
|
.MultipleTimes().AndReturn(True)
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)). \
|
|
||||||
AndReturn(flavors)
|
|
||||||
api.keystone.tenant_list(IsA(http.HttpRequest)).\
|
api.keystone.tenant_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn([tenants, False])
|
AndReturn([tenants, False])
|
||||||
for server in servers:
|
for server in servers:
|
||||||
|
@ -133,10 +145,14 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
self.assertMessageCount(res, error=1)
|
self.assertMessageCount(res, error=1)
|
||||||
self.assertItemsEqual(instances, servers)
|
self.assertItemsEqual(instances, servers)
|
||||||
|
|
||||||
@test.create_stubs({api.nova: ('server_list',),
|
@test.create_stubs({
|
||||||
api.keystone: ('tenant_list',)})
|
api.nova: ('server_list', 'flavor_list',),
|
||||||
|
api.keystone: ('tenant_list',),
|
||||||
|
api.glance: ('image_list_detailed',),
|
||||||
|
})
|
||||||
def test_index_server_list_exception(self):
|
def test_index_server_list_exception(self):
|
||||||
tenants = self.tenants.list()
|
tenants = self.tenants.list()
|
||||||
|
|
||||||
search_opts = {'marker': None, 'paginate': True}
|
search_opts = {'marker': None, 'paginate': True}
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True, search_opts=search_opts) \
|
all_tenants=True, search_opts=search_opts) \
|
||||||
|
@ -188,14 +204,21 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
self.assertContains(res, "Active", 1, 200)
|
self.assertContains(res, "Active", 1, 200)
|
||||||
self.assertContains(res, "Running", 1, 200)
|
self.assertContains(res, "Running", 1, 200)
|
||||||
|
|
||||||
@test.create_stubs({api.nova: ('flavor_list', 'server_list',
|
@test.create_stubs({
|
||||||
'extension_supported', ),
|
api.nova: ('flavor_list', 'server_list', 'extension_supported', ),
|
||||||
api.keystone: ('tenant_list',),
|
api.keystone: ('tenant_list',),
|
||||||
api.network: ('servers_update_addresses',)})
|
api.network: ('servers_update_addresses',),
|
||||||
|
api.glance: ('image_list_detailed',),
|
||||||
|
})
|
||||||
def test_index_options_before_migrate(self):
|
def test_index_options_before_migrate(self):
|
||||||
servers = self.servers.list()
|
servers = self.servers.list()
|
||||||
|
images = self.images.list()
|
||||||
|
flavors = self.flavors.list()
|
||||||
api.keystone.tenant_list(IsA(http.HttpRequest)).\
|
api.keystone.tenant_list(IsA(http.HttpRequest)).\
|
||||||
AndReturn([self.tenants.list(), False])
|
AndReturn([self.tenants.list(), False])
|
||||||
|
api.glance.image_list_detailed(IsA(http.HttpRequest)) \
|
||||||
|
.AndReturn(images)
|
||||||
|
api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
|
||||||
search_opts = {'marker': None, 'paginate': True}
|
search_opts = {'marker': None, 'paginate': True}
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True, search_opts=search_opts) \
|
all_tenants=True, search_opts=search_opts) \
|
||||||
|
@ -206,8 +229,6 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
.MultipleTimes().AndReturn(True)
|
.MultipleTimes().AndReturn(True)
|
||||||
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
|
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
|
||||||
.MultipleTimes().AndReturn(True)
|
.MultipleTimes().AndReturn(True)
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.flavors.list())
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.get(INDEX_URL)
|
res = self.client.get(INDEX_URL)
|
||||||
|
@ -215,18 +236,25 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
self.assertNotContains(res, "instances__confirm")
|
self.assertNotContains(res, "instances__confirm")
|
||||||
self.assertNotContains(res, "instances__revert")
|
self.assertNotContains(res, "instances__revert")
|
||||||
|
|
||||||
@test.create_stubs({api.nova: ('flavor_list', 'server_list',
|
@test.create_stubs({
|
||||||
'extension_supported', ),
|
api.nova: ('flavor_list', 'server_list', 'extension_supported',),
|
||||||
api.keystone: ('tenant_list',),
|
api.keystone: ('tenant_list',),
|
||||||
api.network: ('servers_update_addresses',)})
|
api.network: ('servers_update_addresses',),
|
||||||
|
api.glance: ('image_list_detailed',),
|
||||||
|
})
|
||||||
def test_index_options_after_migrate(self):
|
def test_index_options_after_migrate(self):
|
||||||
servers = self.servers.list()
|
servers = self.servers.list()
|
||||||
server1 = servers[0]
|
server1 = servers[0]
|
||||||
server1.status = "VERIFY_RESIZE"
|
server1.status = "VERIFY_RESIZE"
|
||||||
server2 = servers[2]
|
server2 = servers[2]
|
||||||
server2.status = "VERIFY_RESIZE"
|
server2.status = "VERIFY_RESIZE"
|
||||||
|
images = self.images.list()
|
||||||
|
flavors = self.flavors.list()
|
||||||
api.keystone.tenant_list(IsA(http.HttpRequest)) \
|
api.keystone.tenant_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn([self.tenants.list(), False])
|
.AndReturn([self.tenants.list(), False])
|
||||||
|
api.glance.image_list_detailed(IsA(http.HttpRequest)) \
|
||||||
|
.AndReturn(images)
|
||||||
|
api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
|
||||||
search_opts = {'marker': None, 'paginate': True}
|
search_opts = {'marker': None, 'paginate': True}
|
||||||
api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
|
api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
|
||||||
.MultipleTimes().AndReturn(True)
|
.MultipleTimes().AndReturn(True)
|
||||||
|
@ -237,8 +265,6 @@ class InstanceViewTest(test.BaseAdminViewTests):
|
||||||
.AndReturn([servers, False])
|
.AndReturn([servers, False])
|
||||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers,
|
api.network.servers_update_addresses(IsA(http.HttpRequest), servers,
|
||||||
all_tenants=True)
|
all_tenants=True)
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)).\
|
|
||||||
AndReturn(self.flavors.list())
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.get(INDEX_URL)
|
res = self.client.get(INDEX_URL)
|
||||||
|
|
|
@ -30,6 +30,7 @@ from horizon import tables
|
||||||
from horizon.utils import memoized
|
from horizon.utils import memoized
|
||||||
|
|
||||||
from openstack_dashboard import api
|
from openstack_dashboard import api
|
||||||
|
|
||||||
from openstack_dashboard.dashboards.admin.instances \
|
from openstack_dashboard.dashboards.admin.instances \
|
||||||
import forms as project_forms
|
import forms as project_forms
|
||||||
from openstack_dashboard.dashboards.admin.instances \
|
from openstack_dashboard.dashboards.admin.instances \
|
||||||
|
@ -59,6 +60,11 @@ def rdp(args, **kvargs):
|
||||||
return views.rdp(args, **kvargs)
|
return views.rdp(args, **kvargs)
|
||||||
|
|
||||||
|
|
||||||
|
# re-use get_resource_id_by_name from project.instances.views
|
||||||
|
def swap_filter(resources, filters, fake_field, real_field):
|
||||||
|
return views.swap_filter(resources, filters, fake_field, real_field)
|
||||||
|
|
||||||
|
|
||||||
class AdminUpdateView(views.UpdateView):
|
class AdminUpdateView(views.UpdateView):
|
||||||
workflow_class = update_instance.AdminUpdateInstance
|
workflow_class = update_instance.AdminUpdateInstance
|
||||||
success_url = reverse_lazy("horizon:admin:instances:index")
|
success_url = reverse_lazy("horizon:admin:instances:index")
|
||||||
|
@ -102,15 +108,32 @@ class AdminIndexView(tables.DataTableView):
|
||||||
msg = _('Unable to retrieve instance project information.')
|
msg = _('Unable to retrieve instance project information.')
|
||||||
exceptions.handle(self.request, msg)
|
exceptions.handle(self.request, msg)
|
||||||
|
|
||||||
if 'project' in search_opts:
|
# Gather our images to correlate againts IDs
|
||||||
ten_filter_ids = [t.id for t in tenants
|
try:
|
||||||
if t.name == search_opts['project']]
|
images = api.glance.image_list_detailed(self.request)[0]
|
||||||
del search_opts['project']
|
except Exception:
|
||||||
if len(ten_filter_ids) > 0:
|
images = []
|
||||||
search_opts['tenant_id'] = ten_filter_ids[0]
|
msg = _("Unable to retrieve image list.")
|
||||||
else:
|
|
||||||
|
# Gather our flavors to correlate against IDs
|
||||||
|
try:
|
||||||
|
flavors = api.nova.flavor_list(self.request)
|
||||||
|
except Exception:
|
||||||
|
# If fails to retrieve flavor list, creates an empty list.
|
||||||
|
flavors = []
|
||||||
|
|
||||||
|
if 'project' in search_opts and \
|
||||||
|
not swap_filter(tenants, search_opts, 'project', 'tenant_id'):
|
||||||
self._more = False
|
self._more = False
|
||||||
return []
|
return instances
|
||||||
|
elif 'image_name' in search_opts and \
|
||||||
|
not swap_filter(images, search_opts, 'image_name', 'image'):
|
||||||
|
self._more = False
|
||||||
|
return instances
|
||||||
|
elif "flavor_name" in search_opts and \
|
||||||
|
not swap_filter(flavors, search_opts, 'flavor_name', 'flavor'):
|
||||||
|
self._more = False
|
||||||
|
return instances
|
||||||
|
|
||||||
try:
|
try:
|
||||||
instances, self._more = api.nova.server_list(
|
instances, self._more = api.nova.server_list(
|
||||||
|
@ -131,13 +154,6 @@ class AdminIndexView(tables.DataTableView):
|
||||||
message=_('Unable to retrieve IP addresses from Neutron.'),
|
message=_('Unable to retrieve IP addresses from Neutron.'),
|
||||||
ignore=True)
|
ignore=True)
|
||||||
|
|
||||||
# Gather our flavors to correlate against IDs
|
|
||||||
try:
|
|
||||||
flavors = api.nova.flavor_list(self.request)
|
|
||||||
except Exception:
|
|
||||||
# If fails to retrieve flavor list, creates an empty list.
|
|
||||||
flavors = []
|
|
||||||
|
|
||||||
full_flavors = OrderedDict([(f.id, f) for f in flavors])
|
full_flavors = OrderedDict([(f.id, f) for f in flavors])
|
||||||
tenant_dict = OrderedDict([(t.id, t) for t in tenants])
|
tenant_dict = OrderedDict([(t.id, t) for t in tenants])
|
||||||
# Loop through instances to get flavor and tenant info.
|
# Loop through instances to get flavor and tenant info.
|
||||||
|
|
|
@ -1171,13 +1171,27 @@ POWER_DISPLAY_CHOICES = (
|
||||||
("BUILDING", pgettext_lazy("Power state of an Instance", u"Building")),
|
("BUILDING", pgettext_lazy("Power state of an Instance", u"Building")),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
INSTANCE_FILTER_CHOICES = (
|
||||||
|
('uuid', _("Instance ID ="), True),
|
||||||
|
('name', _("Instance Name"), True),
|
||||||
|
('image', _("Image ID ="), True),
|
||||||
|
('image_name', _("Image Name ="), True),
|
||||||
|
('ip', _("IPv4 Address"), True),
|
||||||
|
('ip6', _("IPv6 Address"), True),
|
||||||
|
('flavor', _("Flavor ID ="), True),
|
||||||
|
('flavor_name', _("Flavor Name ="), True),
|
||||||
|
('key_name', _("Key Pair Name"), True),
|
||||||
|
('status', _("Status ="), True),
|
||||||
|
('availability_zone', _("Availability Zone"), True),
|
||||||
|
('changes-since', _("Changes Since"), True,
|
||||||
|
_("Filter by an ISO 8061 formatted time, e.g. 2016-06-14T06:27:59Z")),
|
||||||
|
('vcpus', _("vCPUs ="), True),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class InstancesFilterAction(tables.FilterAction):
|
class InstancesFilterAction(tables.FilterAction):
|
||||||
filter_type = "server"
|
filter_type = "server"
|
||||||
filter_choices = (('name', _("Instance Name ="), True),
|
filter_choices = INSTANCE_FILTER_CHOICES
|
||||||
('status', _("Status ="), True),
|
|
||||||
('image', _("Image ID ="), True),
|
|
||||||
('flavor', _("Flavor ID ="), True))
|
|
||||||
|
|
||||||
|
|
||||||
class InstancesTable(tables.DataTable):
|
class InstancesTable(tables.DataTable):
|
||||||
|
|
|
@ -106,10 +106,18 @@ class InstanceTests(helpers.TestCase):
|
||||||
self.assertItemsEqual(instances, self.servers.list())
|
self.assertItemsEqual(instances, self.servers.list())
|
||||||
self.assertNotContains(res, "Launch Instance (Quota exceeded)")
|
self.assertNotContains(res, "Launch Instance (Quota exceeded)")
|
||||||
|
|
||||||
@helpers.create_stubs({api.nova: ('server_list',
|
@helpers.create_stubs({
|
||||||
'tenant_absolute_limits',)})
|
api.nova: ('server_list', 'tenant_absolute_limits', 'flavor_list'),
|
||||||
|
api.glance: ('image_list_detailed',),
|
||||||
|
})
|
||||||
def test_index_server_list_exception(self):
|
def test_index_server_list_exception(self):
|
||||||
search_opts = {'marker': None, 'paginate': True}
|
search_opts = {'marker': None, 'paginate': True}
|
||||||
|
flavors = self.flavors.list()
|
||||||
|
images = self.images.list()
|
||||||
|
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||||
|
.AndReturn(flavors)
|
||||||
|
api.glance.image_list_detailed(IsA(http.HttpRequest)) \
|
||||||
|
.AndReturn(images)
|
||||||
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
|
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
|
||||||
.AndRaise(self.exceptions.nova)
|
.AndRaise(self.exceptions.nova)
|
||||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||||
|
|
|
@ -64,9 +64,35 @@ class IndexView(tables.DataTableView):
|
||||||
return self._more
|
return self._more
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
|
instances = []
|
||||||
marker = self.request.GET.get(
|
marker = self.request.GET.get(
|
||||||
project_tables.InstancesTable._meta.pagination_param, None)
|
project_tables.InstancesTable._meta.pagination_param, None)
|
||||||
|
|
||||||
search_opts = self.get_filters({'marker': marker, 'paginate': True})
|
search_opts = self.get_filters({'marker': marker, 'paginate': True})
|
||||||
|
|
||||||
|
# Gather our flavors and images and correlate our instances to them
|
||||||
|
try:
|
||||||
|
flavors = api.nova.flavor_list(self.request)
|
||||||
|
except Exception:
|
||||||
|
flavors = []
|
||||||
|
exceptions.handle(self.request, ignore=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# TODO(gabriel): Handle pagination.
|
||||||
|
images = api.glance.image_list_detailed(self.request)[0]
|
||||||
|
except Exception:
|
||||||
|
images = []
|
||||||
|
exceptions.handle(self.request, ignore=True)
|
||||||
|
|
||||||
|
if 'image_name' in search_opts and \
|
||||||
|
not swap_filter(images, search_opts, 'image_name', 'image'):
|
||||||
|
self._more = False
|
||||||
|
return instances
|
||||||
|
elif 'flavor_name' in search_opts and \
|
||||||
|
not swap_filter(flavors, search_opts, 'flavor_name', 'flavor'):
|
||||||
|
self._more = False
|
||||||
|
return instances
|
||||||
|
|
||||||
# Gather our instances
|
# Gather our instances
|
||||||
try:
|
try:
|
||||||
instances, self._more = api.nova.server_list(
|
instances, self._more = api.nova.server_list(
|
||||||
|
@ -86,22 +112,6 @@ class IndexView(tables.DataTableView):
|
||||||
self.request,
|
self.request,
|
||||||
message=_('Unable to retrieve IP addresses from Neutron.'),
|
message=_('Unable to retrieve IP addresses from Neutron.'),
|
||||||
ignore=True)
|
ignore=True)
|
||||||
|
|
||||||
# Gather our flavors and images and correlate our instances to them
|
|
||||||
try:
|
|
||||||
flavors = api.nova.flavor_list(self.request)
|
|
||||||
except Exception:
|
|
||||||
flavors = []
|
|
||||||
exceptions.handle(self.request, ignore=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# TODO(gabriel): Handle pagination.
|
|
||||||
images, more, prev = api.glance.image_list_detailed(
|
|
||||||
self.request)
|
|
||||||
except Exception:
|
|
||||||
images = []
|
|
||||||
exceptions.handle(self.request, ignore=True)
|
|
||||||
|
|
||||||
full_flavors = OrderedDict([(str(flavor.id), flavor)
|
full_flavors = OrderedDict([(str(flavor.id), flavor)
|
||||||
for flavor in flavors])
|
for flavor in flavors])
|
||||||
image_map = OrderedDict([(str(image.id), image)
|
image_map = OrderedDict([(str(image.id), image)
|
||||||
|
@ -114,7 +124,6 @@ class IndexView(tables.DataTableView):
|
||||||
if isinstance(instance.image, dict):
|
if isinstance(instance.image, dict):
|
||||||
if instance.image.get('id') in image_map:
|
if instance.image.get('id') in image_map:
|
||||||
instance.image = image_map[instance.image['id']]
|
instance.image = image_map[instance.image['id']]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
flavor_id = instance.flavor["id"]
|
flavor_id = instance.flavor["id"]
|
||||||
if flavor_id in full_flavors:
|
if flavor_id in full_flavors:
|
||||||
|
@ -131,6 +140,16 @@ class IndexView(tables.DataTableView):
|
||||||
return instances
|
return instances
|
||||||
|
|
||||||
|
|
||||||
|
def swap_filter(resources, filters, fake_field, real_field):
|
||||||
|
if fake_field in filters:
|
||||||
|
filter_string = filters[fake_field]
|
||||||
|
for resource in resources:
|
||||||
|
if resource.name.lower() == filter_string.lower():
|
||||||
|
filters[real_field] = resource.id
|
||||||
|
del filters[fake_field]
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class LaunchInstanceView(workflows.WorkflowView):
|
class LaunchInstanceView(workflows.WorkflowView):
|
||||||
workflow_class = project_workflows.LaunchInstance
|
workflow_class = project_workflows.LaunchInstance
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue