Use server filter mode for flavors tables
Horizon uses naive filtering for admin flavors, which doesn't work well
with pagination. Nova API supports flavors filtering, so this patch
replaces the existing filtering with server side filtering.
Change-Id: Icdfc414c4f77bb9fda65b21f509b9f1d453ea7df
Signed-off-by: Tatiana Ovchinnikova <t.v.ovtchinnikova@gmail.com>
(cherry picked from commit 5acdc88861)
This commit is contained in:
@@ -259,7 +259,7 @@ def flavor_get(request, flavor_id, get_extras=False):
|
||||
|
||||
@profiler.trace
|
||||
@memoized.memoized
|
||||
def flavor_list(request, is_public=True, get_extras=False):
|
||||
def flavor_list(request, is_public=None, get_extras=False):
|
||||
"""Get the list of available instance sizes (flavors)."""
|
||||
flavors = _nova.novaclient(request).flavors.list(is_public=is_public)
|
||||
if get_extras:
|
||||
@@ -292,9 +292,9 @@ def update_pagination(entities, page_size, marker, reversed_order=False):
|
||||
|
||||
@profiler.trace
|
||||
@memoized.memoized
|
||||
def flavor_list_paged(request, is_public=True, get_extras=False, marker=None,
|
||||
paginate=False, sort_key="name", sort_dir="desc",
|
||||
reversed_order=False):
|
||||
def flavor_list_paged(request, is_public=None, min_disk=None, min_ram=None,
|
||||
get_extras=False, marker=None, paginate=False,
|
||||
sort_key="name", sort_dir="desc", reversed_order=False):
|
||||
"""Get the list of available instance sizes (flavors)."""
|
||||
has_more_data = False
|
||||
has_prev_data = False
|
||||
@@ -304,6 +304,8 @@ def flavor_list_paged(request, is_public=True, get_extras=False, marker=None,
|
||||
sort_dir = 'desc' if sort_dir == 'asc' else 'asc'
|
||||
page_size = utils.get_page_size(request)
|
||||
flavors = _nova.novaclient(request).flavors.list(is_public=is_public,
|
||||
min_disk=min_disk,
|
||||
min_ram=min_ram,
|
||||
marker=marker,
|
||||
limit=page_size + 1,
|
||||
sort_key=sort_key,
|
||||
|
||||
@@ -105,14 +105,13 @@ class ModifyAccess(tables.LinkAction):
|
||||
|
||||
|
||||
class FlavorFilterAction(tables.FilterAction):
|
||||
def filter(self, table, flavors, filter_string):
|
||||
"""Really naive case-insensitive search."""
|
||||
q = filter_string.lower()
|
||||
|
||||
def comp(flavor):
|
||||
return q in flavor.name.lower()
|
||||
|
||||
return filter(comp, flavors)
|
||||
name = 'flavors_filter'
|
||||
filter_type = 'server'
|
||||
filter_choices = (
|
||||
('is_public', _('Is Public ='), True),
|
||||
('min_disk', _('Minimum Root Disk (GB) ='), True),
|
||||
('min_ram', _('Minimum RAM (MB) ='), True),
|
||||
)
|
||||
|
||||
|
||||
def get_size(flavor):
|
||||
|
||||
@@ -38,8 +38,9 @@ class FlavorsViewTests(test.BaseAdminViewTests):
|
||||
self.assertCountEqual(res.context['table'].data, self.flavors.list())
|
||||
|
||||
self.mock_flavor_list_paged.assert_called_once_with(
|
||||
test.IsHttpRequest(), None, marker=None, paginate=True,
|
||||
sort_dir='asc', sort_key='name', reversed_order=False)
|
||||
test.IsHttpRequest(), is_public=None, min_disk=None, min_ram=None,
|
||||
marker=None, paginate=True, sort_dir='asc', sort_key='name',
|
||||
reversed_order=False)
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_get_keys, 4, mock.call())
|
||||
|
||||
@@ -76,15 +77,18 @@ class FlavorsViewTests(test.BaseAdminViewTests):
|
||||
self.flavors.list()[2:4])
|
||||
|
||||
self.mock_flavor_list_paged.assert_has_calls([
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=None, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=False),
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=None, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=False),
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=flavors_list[2].id, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=False),
|
||||
@@ -137,19 +141,23 @@ class FlavorsViewTests(test.BaseAdminViewTests):
|
||||
self.flavors.list()[:2])
|
||||
|
||||
self.mock_flavor_list_paged.assert_has_calls([
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=None, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=False),
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=None, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=False),
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=flavors_list[2].id, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=False),
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=flavors_list[2].id, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=True),
|
||||
@@ -185,11 +193,13 @@ class FlavorsViewTests(test.BaseAdminViewTests):
|
||||
self.assertContains(res, form_action, count=1)
|
||||
|
||||
self.mock_flavor_list_paged.assert_has_calls([
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=None, paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
reversed_order=False),
|
||||
mock.call(test.IsHttpRequest(), None,
|
||||
mock.call(test.IsHttpRequest(), is_public=None,
|
||||
min_disk=None, min_ram=None,
|
||||
marker=flavors_list[page_size - 1].id,
|
||||
paginate=True,
|
||||
sort_dir='asc', sort_key='name',
|
||||
|
||||
@@ -38,6 +38,8 @@ class IndexView(tables.DataTableView):
|
||||
table_class = project_tables.FlavorsTable
|
||||
page_title = _("Flavors")
|
||||
|
||||
FILTERS_MAPPING = {'is_public': {_('yes'): True, _('no'): False}}
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._prev
|
||||
|
||||
@@ -46,6 +48,11 @@ class IndexView(tables.DataTableView):
|
||||
|
||||
def get_data(self):
|
||||
request = self.request
|
||||
filters = self.get_filters(filters_map=self.FILTERS_MAPPING)
|
||||
is_public = filters.get("is_public")
|
||||
min_disk = filters.get("min_disk")
|
||||
min_ram = filters.get("min_ram")
|
||||
|
||||
prev_marker = request.GET.get(
|
||||
project_tables.FlavorsTable._meta.prev_pagination_param, None)
|
||||
|
||||
@@ -60,11 +67,14 @@ class IndexView(tables.DataTableView):
|
||||
# Removing the pagination params and adding "is_public=None"
|
||||
# will return all flavors.
|
||||
flavors, self._more, self._prev = api.nova.flavor_list_paged(
|
||||
request, None,
|
||||
request,
|
||||
is_public=is_public,
|
||||
marker=marker,
|
||||
paginate=True,
|
||||
sort_dir='asc',
|
||||
sort_key='name',
|
||||
min_disk=min_disk,
|
||||
min_ram=min_ram,
|
||||
reversed_order=reversed_order)
|
||||
except Exception:
|
||||
self._prev = self._more = False
|
||||
|
||||
@@ -491,7 +491,7 @@ class ComputeApiTests(test.APIMockTestCase):
|
||||
api_flavors = api.nova.flavor_list(self.request)
|
||||
|
||||
self.assertEqual(len(flavors), len(api_flavors))
|
||||
novaclient.flavors.list.assert_called_once_with(is_public=True)
|
||||
novaclient.flavors.list.assert_called_once_with(is_public=None)
|
||||
|
||||
@mock.patch.object(api._nova, 'novaclient')
|
||||
def test_flavor_get_no_extras(self, mock_novaclient):
|
||||
@@ -514,7 +514,7 @@ class ComputeApiTests(test.APIMockTestCase):
|
||||
novaclient.flavors.list.return_value = flavors
|
||||
|
||||
api_flavors, has_more, has_prev = api.nova.flavor_list_paged(
|
||||
self.request, True, False, None, paginate=paginate,
|
||||
self.request, None, None, None, paginate=paginate,
|
||||
reversed_order=reversed_order)
|
||||
|
||||
for flavor in api_flavors:
|
||||
@@ -523,11 +523,11 @@ class ComputeApiTests(test.APIMockTestCase):
|
||||
self.assertFalse(has_prev)
|
||||
if paginate:
|
||||
novaclient.flavors.list.assert_called_once_with(
|
||||
is_public=True, marker=None, limit=page_size + 1,
|
||||
sort_key='name', sort_dir=order)
|
||||
is_public=None, min_disk=None, min_ram=None, marker=None,
|
||||
limit=page_size + 1, sort_key='name', sort_dir=order)
|
||||
else:
|
||||
novaclient.flavors.list.assert_called_once_with(
|
||||
is_public=True)
|
||||
is_public=None)
|
||||
|
||||
@override_settings(API_RESULT_PAGE_SIZE=1)
|
||||
@mock.patch.object(api._nova, 'novaclient')
|
||||
@@ -541,7 +541,9 @@ class ComputeApiTests(test.APIMockTestCase):
|
||||
api_flavors, has_more, has_prev = api.nova\
|
||||
.flavor_list_paged(
|
||||
self.request,
|
||||
True,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
marker,
|
||||
paginate=True)
|
||||
@@ -552,8 +554,8 @@ class ComputeApiTests(test.APIMockTestCase):
|
||||
self.assertTrue(has_more)
|
||||
self.assertTrue(has_prev)
|
||||
novaclient.flavors.list.assert_called_once_with(
|
||||
is_public=True, marker=marker, limit=page_size + 1,
|
||||
sort_key='name', sort_dir='desc')
|
||||
is_public=None, min_disk=None, min_ram=None, marker=marker,
|
||||
limit=page_size + 1, sort_key='name', sort_dir='desc')
|
||||
|
||||
def test_flavor_list_paged_default_order(self):
|
||||
self._test_flavor_list_paged()
|
||||
|
||||
Reference in New Issue
Block a user