Add pagination to volume snapshots and backups pages
Do it for both Project (both Snapshots and Backups tabs) and Admin (only Snapshots tab) dashboards. To test: set 'Items Per Page' in the UI Settings page to a low number. Change-Id: I9b16cf31c726055da0afad347e033f3918af3049 Closes-Bug: #1499664
This commit is contained in:
parent
abad2d3af4
commit
f90b374ad7
|
@ -202,6 +202,23 @@ def volume_list(request, search_opts=None, marker=None, sort_dir="desc"):
|
|||
return volumes
|
||||
|
||||
|
||||
def update_pagination(entities, page_size, marker, sort_dir):
|
||||
has_more_data, has_prev_data = False, False
|
||||
if len(entities) > page_size:
|
||||
has_more_data = True
|
||||
entities.pop()
|
||||
if marker is not None:
|
||||
has_prev_data = True
|
||||
# first page condition when reached via prev back
|
||||
elif sort_dir == 'asc' and marker is not None:
|
||||
has_more_data = True
|
||||
# last page condition
|
||||
elif marker is not None:
|
||||
has_prev_data = True
|
||||
|
||||
return entities, has_more_data, has_prev_data
|
||||
|
||||
|
||||
def volume_list_paged(request, search_opts=None, marker=None, paginate=False,
|
||||
sort_dir="desc"):
|
||||
"""To see all volumes in the cloud as an admin you can pass in a special
|
||||
|
@ -231,17 +248,8 @@ def volume_list_paged(request, search_opts=None, marker=None, paginate=False,
|
|||
sort=sort):
|
||||
v.transfer = transfers.get(v.id)
|
||||
volumes.append(Volume(v))
|
||||
if len(volumes) > page_size:
|
||||
has_more_data = True
|
||||
volumes.pop()
|
||||
if marker is not None:
|
||||
has_prev_data = True
|
||||
# first page condition when reached via prev back
|
||||
elif sort_dir == 'asc' and marker is not None:
|
||||
has_more_data = True
|
||||
# last page condition
|
||||
elif marker is not None:
|
||||
has_prev_data = True
|
||||
volumes, has_more_data, has_prev_data = update_pagination(
|
||||
volumes, page_size, marker, sort_dir)
|
||||
else:
|
||||
for v in c_client.volumes.list(search_opts=search_opts):
|
||||
v.transfer = transfers.get(v.id)
|
||||
|
@ -346,11 +354,40 @@ def volume_snapshot_get(request, snapshot_id):
|
|||
|
||||
|
||||
def volume_snapshot_list(request, search_opts=None):
|
||||
snapshots, _, __ = volume_snapshot_list_paged(request,
|
||||
search_opts=search_opts,
|
||||
paginate=False)
|
||||
return snapshots
|
||||
|
||||
|
||||
def volume_snapshot_list_paged(request, search_opts=None, marker=None,
|
||||
paginate=False, sort_dir="desc"):
|
||||
has_more_data = False
|
||||
has_prev_data = False
|
||||
snapshots = []
|
||||
c_client = cinderclient(request)
|
||||
if c_client is None:
|
||||
return []
|
||||
return [VolumeSnapshot(s) for s in c_client.volume_snapshots.list(
|
||||
search_opts=search_opts)]
|
||||
return snapshots, has_more_data, has_more_data
|
||||
|
||||
if VERSIONS.active > 1 and paginate:
|
||||
page_size = utils.get_page_size(request)
|
||||
# sort_key and sort_dir deprecated in kilo, use sort
|
||||
# if pagination is true, we use a single sort parameter
|
||||
# by default, it is "created_at"
|
||||
sort = 'created_at:' + sort_dir
|
||||
for s in c_client.volume_snapshots.list(search_opts=search_opts,
|
||||
limit=page_size + 1,
|
||||
marker=marker,
|
||||
sort=sort):
|
||||
snapshots.append(VolumeSnapshot(s))
|
||||
|
||||
snapshots, has_more_data, has_prev_data = update_pagination(
|
||||
snapshots, page_size, marker, sort_dir)
|
||||
else:
|
||||
for s in c_client.volume_snapshots.list(search_opts=search_opts):
|
||||
snapshots.append(VolumeSnapshot(s))
|
||||
|
||||
return snapshots, has_more_data, has_prev_data
|
||||
|
||||
|
||||
def volume_snapshot_create(request, volume_id, name,
|
||||
|
@ -399,10 +436,38 @@ def volume_backup_get(request, backup_id):
|
|||
|
||||
|
||||
def volume_backup_list(request):
|
||||
backups, _, __ = volume_backup_list_paged(request, paginate=False)
|
||||
return backups
|
||||
|
||||
|
||||
def volume_backup_list_paged(request, marker=None, paginate=False,
|
||||
sort_dir="desc"):
|
||||
has_more_data = False
|
||||
has_prev_data = False
|
||||
backups = []
|
||||
|
||||
c_client = cinderclient(request)
|
||||
if c_client is None:
|
||||
return []
|
||||
return [VolumeBackup(b) for b in c_client.backups.list()]
|
||||
return backups, has_more_data, has_prev_data
|
||||
|
||||
if VERSIONS.active > 1 and paginate:
|
||||
page_size = utils.get_page_size(request)
|
||||
# sort_key and sort_dir deprecated in kilo, use sort
|
||||
# if pagination is true, we use a single sort parameter
|
||||
# by default, it is "created_at"
|
||||
sort = 'created_at:' + sort_dir
|
||||
for b in c_client.backups.list(limit=page_size + 1,
|
||||
marker=marker,
|
||||
sort=sort):
|
||||
backups.append(VolumeBackup(b))
|
||||
|
||||
backups, has_more_data, has_prev_data = update_pagination(
|
||||
backups, page_size, marker, sort_dir)
|
||||
else:
|
||||
for b in c_client.backups.list():
|
||||
backups.append(VolumeBackup(b))
|
||||
|
||||
return backups, has_more_data, has_prev_data
|
||||
|
||||
|
||||
def volume_backup_create(request,
|
||||
|
|
|
@ -67,6 +67,8 @@ class VolumeSnapshotsTable(volumes_tables.VolumesTableBase):
|
|||
class Meta(object):
|
||||
name = "volume_snapshots"
|
||||
verbose_name = _("Volume Snapshots")
|
||||
pagination_param = 'snapshot_marker'
|
||||
prev_pagination_param = 'prev_snapshot_marker'
|
||||
table_actions = (snapshots_tables.VolumeSnapshotsFilterAction,
|
||||
snapshots_tables.DeleteVolumeSnapshot,)
|
||||
row_actions = (snapshots_tables.DeleteVolumeSnapshot,
|
||||
|
|
|
@ -30,7 +30,8 @@ from openstack_dashboard.dashboards.project.volumes \
|
|||
import tabs as volumes_tabs
|
||||
|
||||
|
||||
class VolumeTab(tabs.TableTab, volumes_tabs.VolumeTableMixIn):
|
||||
class VolumeTab(volumes_tabs.PagedTableMixin, tabs.TableTab,
|
||||
volumes_tabs.VolumeTableMixIn):
|
||||
table_classes = (volumes_tables.VolumesTable,)
|
||||
name = _("Volumes")
|
||||
slug = "volumes_tab"
|
||||
|
@ -61,12 +62,6 @@ class VolumeTab(tabs.TableTab, volumes_tabs.VolumeTableMixIn):
|
|||
|
||||
return volumes
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev_data
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more_data
|
||||
|
||||
|
||||
class VolumeTypesTab(tabs.TableTab, volumes_tabs.VolumeTableMixIn):
|
||||
table_classes = (volume_types_tables.VolumeTypesTable,
|
||||
|
@ -116,7 +111,7 @@ class VolumeTypesTab(tabs.TableTab, volumes_tabs.VolumeTableMixIn):
|
|||
return qos_specs
|
||||
|
||||
|
||||
class SnapshotTab(tabs.TableTab):
|
||||
class SnapshotTab(volumes_tabs.PagedTableMixin, tabs.TableTab):
|
||||
table_classes = (snapshots_tables.VolumeSnapshotsTable,)
|
||||
name = _("Volume Snapshots")
|
||||
slug = "snapshots_tab"
|
||||
|
@ -126,9 +121,11 @@ class SnapshotTab(tabs.TableTab):
|
|||
def get_volume_snapshots_data(self):
|
||||
if api.base.is_service_enabled(self.request, 'volume'):
|
||||
try:
|
||||
snapshots = cinder.volume_snapshot_list(
|
||||
self.request,
|
||||
search_opts={'all_tenants': True})
|
||||
marker, sort_dir = self._get_marker()
|
||||
snapshots, self._has_more_data, self._has_prev_data = \
|
||||
cinder.volume_snapshot_list_paged(
|
||||
self.request, paginate=True, marker=marker,
|
||||
sort_dir=sort_dir, search_opts={'all_tenants': True})
|
||||
volumes = cinder.volume_list(
|
||||
self.request,
|
||||
search_opts={'all_tenants': True})
|
||||
|
|
|
@ -21,6 +21,8 @@ from mox3.mox import IsA # noqa
|
|||
from openstack_dashboard import api
|
||||
from openstack_dashboard.api import cinder
|
||||
from openstack_dashboard.api import keystone
|
||||
from openstack_dashboard.dashboards.project.volumes.snapshots \
|
||||
import tables as snapshot_tables
|
||||
from openstack_dashboard.dashboards.project.volumes.volumes \
|
||||
import tables as volume_tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
@ -174,12 +176,13 @@ class VolumeTests(test.BaseAdminViewTests):
|
|||
self.assertItemsEqual(qos_specs, self.cinder_qos_specs.list())
|
||||
|
||||
@test.create_stubs({cinder: ('volume_list',
|
||||
'volume_snapshot_list',),
|
||||
'volume_snapshot_list_paged',),
|
||||
keystone: ('tenant_list',)})
|
||||
def test_snapshots_tab(self):
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest), search_opts={
|
||||
'all_tenants': True}). \
|
||||
AndReturn(self.cinder_volume_snapshots.list())
|
||||
cinder.volume_snapshot_list_paged(
|
||||
IsA(http.HttpRequest), paginate=True, marker=None, sort_dir='desc',
|
||||
search_opts={'all_tenants': True},).AndReturn(
|
||||
[self.cinder_volume_snapshots.list(), False, False])
|
||||
cinder.volume_list(IsA(http.HttpRequest), search_opts={
|
||||
'all_tenants': True}).\
|
||||
AndReturn(self.cinder_volumes.list())
|
||||
|
@ -193,3 +196,90 @@ class VolumeTests(test.BaseAdminViewTests):
|
|||
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, self.cinder_volume_snapshots.list())
|
||||
|
||||
@test.create_stubs({cinder: ('volume_list',
|
||||
'volume_snapshot_list_paged',),
|
||||
keystone: ('tenant_list',)})
|
||||
def _test_snapshots_index_paginated(self, marker, sort_dir, snapshots, url,
|
||||
has_more, has_prev):
|
||||
cinder.volume_snapshot_list_paged(
|
||||
IsA(http.HttpRequest), paginate=True, marker=marker,
|
||||
sort_dir=sort_dir, search_opts={'all_tenants': True}) \
|
||||
.AndReturn([snapshots, has_more, has_prev])
|
||||
cinder.volume_list(IsA(http.HttpRequest), search_opts={
|
||||
'all_tenants': True}).\
|
||||
AndReturn(self.cinder_volumes.list())
|
||||
keystone.tenant_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.tenants.list(), False])
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(url)
|
||||
|
||||
self.assertTemplateUsed(res, 'admin/volumes/index.html')
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
self.mox.UnsetStubs()
|
||||
return res
|
||||
|
||||
@override_settings(API_RESULT_PAGE_SIZE=1)
|
||||
def test_snapshots_index_paginated(self):
|
||||
size = settings.API_RESULT_PAGE_SIZE
|
||||
mox_snapshots = self.cinder_volume_snapshots.list()
|
||||
base_url = reverse('horizon:admin:volumes:snapshots_tab')
|
||||
next = snapshot_tables.VolumeSnapshotsTable._meta.pagination_param
|
||||
|
||||
# get first page
|
||||
expected_snapshots = mox_snapshots[:size]
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=None, sort_dir="desc", snapshots=expected_snapshots,
|
||||
url=base_url, has_more=True, has_prev=False)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
# get second page
|
||||
expected_snapshots = mox_snapshots[size:2 * size]
|
||||
marker = expected_snapshots[0].id
|
||||
url = "&".join([base_url, "=".join([next, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="desc", snapshots=expected_snapshots,
|
||||
url=url, has_more=True, has_prev=True)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
# get last page
|
||||
expected_snapshots = mox_snapshots[-size:]
|
||||
marker = expected_snapshots[0].id
|
||||
url = "&".join([base_url, "=".join([next, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="desc", snapshots=expected_snapshots,
|
||||
url=url, has_more=False, has_prev=True)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
@override_settings(API_RESULT_PAGE_SIZE=1)
|
||||
def test_snapshots_index_paginated_prev(self):
|
||||
size = settings.API_RESULT_PAGE_SIZE
|
||||
max_snapshots = self.cinder_volume_snapshots.list()
|
||||
base_url = reverse('horizon:admin:volumes:snapshots_tab')
|
||||
prev = snapshot_tables.VolumeSnapshotsTable._meta.prev_pagination_param
|
||||
|
||||
# prev from some page
|
||||
expected_snapshots = max_snapshots[size:2 * size]
|
||||
marker = max_snapshots[0].id
|
||||
url = "&".join([base_url, "=".join([prev, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="asc", snapshots=expected_snapshots,
|
||||
url=url, has_more=False, has_prev=True)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
# back to first page
|
||||
expected_snapshots = max_snapshots[:size]
|
||||
marker = max_snapshots[0].id
|
||||
url = "&".join([base_url, "=".join([prev, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="asc", snapshots=expected_snapshots,
|
||||
url=url, has_more=True, has_prev=False)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
|
|
@ -139,6 +139,8 @@ class BackupsTable(tables.DataTable):
|
|||
class Meta(object):
|
||||
name = "volume_backups"
|
||||
verbose_name = _("Volume Backups")
|
||||
pagination_param = 'backup_marker'
|
||||
prev_pagination_param = 'prev_backup_marker'
|
||||
status_columns = ("status",)
|
||||
row_class = UpdateRow
|
||||
table_actions = (DeleteBackup,)
|
||||
|
|
|
@ -54,7 +54,7 @@ class VolumeBackupsViewTests(test.TestCase):
|
|||
|
||||
@test.create_stubs({api.cinder: ('volume_list',
|
||||
'volume_backup_supported',
|
||||
'volume_backup_list',
|
||||
'volume_backup_list_paged',
|
||||
'volume_backup_delete')})
|
||||
def test_delete_volume_backup(self):
|
||||
vol_backups = self.cinder_volume_backups.list()
|
||||
|
@ -63,14 +63,16 @@ class VolumeBackupsViewTests(test.TestCase):
|
|||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)). \
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.cinder.volume_backup_list(IsA(http.HttpRequest)). \
|
||||
AndReturn(vol_backups)
|
||||
api.cinder.volume_backup_list_paged(
|
||||
IsA(http.HttpRequest), marker=None, sort_dir='desc',
|
||||
paginate=True).AndReturn([vol_backups, False, False])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)). \
|
||||
AndReturn(volumes)
|
||||
api.cinder.volume_backup_delete(IsA(http.HttpRequest), backup.id)
|
||||
|
||||
api.cinder.volume_backup_list(IsA(http.HttpRequest)). \
|
||||
AndReturn(vol_backups)
|
||||
api.cinder.volume_backup_list_paged(
|
||||
IsA(http.HttpRequest), marker=None, sort_dir='desc',
|
||||
paginate=True).AndReturn([vol_backups, False, False])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)). \
|
||||
AndReturn(volumes)
|
||||
self.mox.ReplayAll()
|
||||
|
|
|
@ -154,6 +154,8 @@ class VolumeSnapshotsTable(volume_tables.VolumesTableBase):
|
|||
class Meta(object):
|
||||
name = "volume_snapshots"
|
||||
verbose_name = _("Volume Snapshots")
|
||||
pagination_param = 'snapshot_marker'
|
||||
prev_pagination_param = 'prev_snapshot_marker'
|
||||
table_actions = (VolumeSnapshotsFilterAction, DeleteVolumeSnapshot,)
|
||||
row_actions = (CreateVolumeFromSnapshot, LaunchSnapshot,
|
||||
EditVolumeSnapshot, DeleteVolumeSnapshot)
|
||||
|
|
|
@ -105,7 +105,7 @@ class VolumeSnapshotsViewTests(test.TestCase):
|
|||
res = self.client.post(url, formData)
|
||||
self.assertRedirectsNoFollow(res, VOLUME_SNAPSHOTS_TAB_URL)
|
||||
|
||||
@test.create_stubs({api.cinder: ('volume_snapshot_list',
|
||||
@test.create_stubs({api.cinder: ('volume_snapshot_list_paged',
|
||||
'volume_list',
|
||||
'volume_backup_supported',
|
||||
'volume_snapshot_delete')})
|
||||
|
@ -116,14 +116,16 @@ class VolumeSnapshotsViewTests(test.TestCase):
|
|||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)). \
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.cinder.volume_snapshot_list(IsA(http.HttpRequest)). \
|
||||
AndReturn(vol_snapshots)
|
||||
api.cinder.volume_snapshot_list_paged(
|
||||
IsA(http.HttpRequest), paginate=True, marker=None,
|
||||
sort_dir='desc').AndReturn([vol_snapshots, False, False])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)). \
|
||||
AndReturn(volumes)
|
||||
|
||||
api.cinder.volume_snapshot_delete(IsA(http.HttpRequest), snapshot.id)
|
||||
api.cinder.volume_snapshot_list(IsA(http.HttpRequest)). \
|
||||
AndReturn([])
|
||||
api.cinder.volume_snapshot_list_paged(
|
||||
IsA(http.HttpRequest), paginate=True, marker=None,
|
||||
sort_dir='desc').AndReturn([[], False, False])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)). \
|
||||
AndReturn(volumes)
|
||||
self.mox.ReplayAll()
|
||||
|
|
|
@ -89,20 +89,32 @@ class VolumeTableMixIn(object):
|
|||
server_id = att.get('server_id', None)
|
||||
att['instance'] = instances.get(server_id, None)
|
||||
|
||||
|
||||
class PagedTableMixin(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PagedTableMixin, self).__init__(*args, **kwargs)
|
||||
self._has_prev_data = False
|
||||
self._has_more_data = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev_data
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more_data
|
||||
|
||||
def _get_marker(self):
|
||||
prev_marker = self.request.GET.get(
|
||||
volume_tables.VolumesTable._meta.prev_pagination_param, None)
|
||||
meta = self.table_classes[0]._meta
|
||||
prev_marker = self.request.GET.get(meta.prev_pagination_param, None)
|
||||
if prev_marker:
|
||||
return prev_marker, "asc"
|
||||
else:
|
||||
marker = self.request.GET.get(
|
||||
volume_tables.VolumesTable._meta.pagination_param, None)
|
||||
marker = self.request.GET.get(meta.pagination_param, None)
|
||||
if marker:
|
||||
return marker, "desc"
|
||||
return None, "desc"
|
||||
|
||||
|
||||
class VolumeTab(tabs.TableTab, VolumeTableMixIn):
|
||||
class VolumeTab(PagedTableMixin, tabs.TableTab, VolumeTableMixIn):
|
||||
table_classes = (volume_tables.VolumesTable,)
|
||||
name = _("Volumes")
|
||||
slug = "volumes_tab"
|
||||
|
@ -117,14 +129,8 @@ class VolumeTab(tabs.TableTab, VolumeTableMixIn):
|
|||
volumes, instances, volume_ids_with_snapshots)
|
||||
return volumes
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev_data
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more_data
|
||||
|
||||
|
||||
class SnapshotTab(tabs.TableTab):
|
||||
class SnapshotTab(PagedTableMixin, tabs.TableTab):
|
||||
table_classes = (vol_snapshot_tables.VolumeSnapshotsTable,)
|
||||
name = _("Volume Snapshots")
|
||||
slug = "snapshots_tab"
|
||||
|
@ -133,7 +139,11 @@ class SnapshotTab(tabs.TableTab):
|
|||
|
||||
def get_volume_snapshots_data(self):
|
||||
try:
|
||||
snapshots = api.cinder.volume_snapshot_list(self.request)
|
||||
marker, sort_dir = self._get_marker()
|
||||
snapshots, self._has_more_data, self._has_prev_data = \
|
||||
api.cinder.volume_snapshot_list_paged(
|
||||
self.request, paginate=True, marker=marker,
|
||||
sort_dir=sort_dir)
|
||||
volumes = api.cinder.volume_list(self.request)
|
||||
volumes = dict((v.id, v) for v in volumes)
|
||||
except Exception:
|
||||
|
@ -149,7 +159,7 @@ class SnapshotTab(tabs.TableTab):
|
|||
return snapshots
|
||||
|
||||
|
||||
class BackupsTab(tabs.TableTab, VolumeTableMixIn):
|
||||
class BackupsTab(PagedTableMixin, tabs.TableTab, VolumeTableMixIn):
|
||||
table_classes = (backups_tables.BackupsTable,)
|
||||
name = _("Volume Backups")
|
||||
slug = "backups_tab"
|
||||
|
@ -161,7 +171,11 @@ class BackupsTab(tabs.TableTab, VolumeTableMixIn):
|
|||
|
||||
def get_volume_backups_data(self):
|
||||
try:
|
||||
backups = api.cinder.volume_backup_list(self.request)
|
||||
marker, sort_dir = self._get_marker()
|
||||
backups, self._has_more_data, self._has_prev_data = \
|
||||
api.cinder.volume_backup_list_paged(
|
||||
self.request, marker=marker, sort_dir=sort_dir,
|
||||
paginate=True)
|
||||
volumes = api.cinder.volume_list(self.request)
|
||||
volumes = dict((v.id, v) for v in volumes)
|
||||
for backup in backups:
|
||||
|
|
|
@ -20,6 +20,10 @@ from django.test.utils import override_settings
|
|||
from mox3.mox import IsA # noqa
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.volumes.backups \
|
||||
import tables as backup_tables
|
||||
from openstack_dashboard.dashboards.project.volumes.snapshots \
|
||||
import tables as snapshot_tables
|
||||
from openstack_dashboard.dashboards.project.volumes.volumes \
|
||||
import tables as volume_tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
@ -30,13 +34,14 @@ VOLUME_SNAPSHOTS_TAB_URL = reverse('horizon:project:volumes:snapshots_tab')
|
|||
VOLUME_BACKUPS_TAB_URL = reverse('horizon:project:volumes:backups_tab')
|
||||
|
||||
|
||||
class VolumeAndSnapshotsTests(test.TestCase):
|
||||
class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
|
||||
@test.create_stubs({api.cinder: ('tenant_absolute_limits',
|
||||
'volume_list',
|
||||
'volume_list_paged',
|
||||
'volume_snapshot_list',
|
||||
'volume_snapshot_list_paged',
|
||||
'volume_backup_supported',
|
||||
'volume_backup_list',
|
||||
'volume_backup_list_paged',
|
||||
),
|
||||
api.nova: ('server_list',)})
|
||||
def _test_index(self, backup_supported=True):
|
||||
|
@ -46,20 +51,23 @@ class VolumeAndSnapshotsTests(test.TestCase):
|
|||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)).\
|
||||
MultipleTimes().AndReturn(backup_supported)
|
||||
api.cinder.volume_list_paged(IsA(http.HttpRequest), marker=None,
|
||||
sort_dir='desc', search_opts=None,
|
||||
paginate=True).\
|
||||
api.cinder.volume_list_paged(
|
||||
IsA(http.HttpRequest), marker=None, search_opts=None,
|
||||
sort_dir='desc', paginate=True).\
|
||||
AndReturn([volumes, False, False])
|
||||
api.nova.server_list(IsA(http.HttpRequest), search_opts=None).\
|
||||
AndReturn([self.servers.list(), False])
|
||||
api.cinder.volume_snapshot_list(
|
||||
IsA(http.HttpRequest), search_opts=None).AndReturn(vol_snaps)
|
||||
api.cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
||||
AndReturn(vol_snaps)
|
||||
|
||||
api.cinder.volume_snapshot_list_paged(
|
||||
IsA(http.HttpRequest), paginate=True, marker=None,
|
||||
sort_dir='desc').AndReturn([vol_snaps, False, False])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)).AndReturn(volumes)
|
||||
if backup_supported:
|
||||
api.cinder.volume_backup_list(IsA(http.HttpRequest)).\
|
||||
AndReturn(vol_backups)
|
||||
api.cinder.volume_backup_list_paged(
|
||||
IsA(http.HttpRequest), marker=None, sort_dir='desc',
|
||||
paginate=True).AndReturn([vol_backups, False, False])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)).AndReturn(volumes)
|
||||
api.cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
|
||||
MultipleTimes().AndReturn(self.cinder_limits['absolute'])
|
||||
|
@ -175,3 +183,181 @@ class VolumeAndSnapshotsTests(test.TestCase):
|
|||
has_more=True, has_prev=False)
|
||||
volumes = res.context['volumes_table'].data
|
||||
self.assertItemsEqual(volumes, expected_volumes)
|
||||
|
||||
@test.create_stubs({api.cinder: ('tenant_absolute_limits',
|
||||
'volume_snapshot_list_paged',
|
||||
'volume_list',
|
||||
'volume_backup_supported',
|
||||
),
|
||||
api.nova: ('server_list',)})
|
||||
def _test_snapshots_index_paginated(self, marker, sort_dir, snapshots, url,
|
||||
has_more, has_prev):
|
||||
backup_supported = True
|
||||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)).\
|
||||
MultipleTimes().AndReturn(backup_supported)
|
||||
api.cinder.volume_snapshot_list_paged(
|
||||
IsA(http.HttpRequest), marker=marker, sort_dir=sort_dir,
|
||||
paginate=True).AndReturn([snapshots, has_more, has_prev])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)).AndReturn(
|
||||
self.cinder_volumes.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertTemplateUsed(res, 'project/volumes/index.html')
|
||||
|
||||
self.mox.UnsetStubs()
|
||||
return res
|
||||
|
||||
@override_settings(API_RESULT_PAGE_SIZE=1)
|
||||
def test_snapshots_index_paginated(self):
|
||||
mox_snapshots = self.cinder_volume_snapshots.list()
|
||||
size = settings.API_RESULT_PAGE_SIZE
|
||||
base_url = reverse('horizon:project:volumes:snapshots_tab')
|
||||
next = snapshot_tables.VolumeSnapshotsTable._meta.pagination_param
|
||||
|
||||
# get first page
|
||||
expected_snapshots = mox_snapshots[:size]
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=None, sort_dir="desc", snapshots=expected_snapshots,
|
||||
url=base_url, has_more=True, has_prev=False)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
# get second page
|
||||
expected_snapshots = mox_snapshots[size:2 * size]
|
||||
marker = expected_snapshots[0].id
|
||||
|
||||
url = "&".join([base_url, "=".join([next, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="desc", snapshots=expected_snapshots,
|
||||
url=url, has_more=True, has_prev=True)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
# get last page
|
||||
expected_snapshots = mox_snapshots[-size:]
|
||||
marker = expected_snapshots[0].id
|
||||
url = "&".join([base_url, "=".join([next, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="desc", snapshots=expected_snapshots,
|
||||
url=url, has_more=False, has_prev=True)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
@override_settings(API_RESULT_PAGE_SIZE=1)
|
||||
def test_snapshots_index_paginated_prev_page(self):
|
||||
mox_snapshots = self.cinder_volume_snapshots.list()
|
||||
size = settings.API_RESULT_PAGE_SIZE
|
||||
base_url = reverse('horizon:project:volumes:snapshots_tab')
|
||||
prev = snapshot_tables.VolumeSnapshotsTable._meta.prev_pagination_param
|
||||
|
||||
# prev from some page
|
||||
expected_snapshots = mox_snapshots[size:2 * size]
|
||||
marker = expected_snapshots[0].id
|
||||
url = "&".join([base_url, "=".join([prev, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="asc", snapshots=expected_snapshots,
|
||||
url=url, has_more=True, has_prev=True)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
# back to first page
|
||||
expected_snapshots = mox_snapshots[:size]
|
||||
marker = expected_snapshots[0].id
|
||||
url = "&".join([base_url, "=".join([prev, marker])])
|
||||
res = self._test_snapshots_index_paginated(
|
||||
marker=marker, sort_dir="asc", snapshots=expected_snapshots,
|
||||
url=url, has_more=True, has_prev=False)
|
||||
snapshots = res.context['volume_snapshots_table'].data
|
||||
self.assertItemsEqual(snapshots, expected_snapshots)
|
||||
|
||||
@test.create_stubs({api.cinder: ('tenant_absolute_limits',
|
||||
'volume_backup_list_paged',
|
||||
'volume_list',
|
||||
'volume_backup_supported',
|
||||
),
|
||||
api.nova: ('server_list',)})
|
||||
def _test_backups_index_paginated(self, marker, sort_dir, backups, url,
|
||||
has_more, has_prev):
|
||||
backup_supported = True
|
||||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)).\
|
||||
MultipleTimes().AndReturn(backup_supported)
|
||||
api.cinder.volume_backup_list_paged(
|
||||
IsA(http.HttpRequest), marker=marker, sort_dir=sort_dir,
|
||||
paginate=True).AndReturn([backups, has_more, has_prev])
|
||||
api.cinder.volume_list(IsA(http.HttpRequest)).AndReturn(
|
||||
self.cinder_volumes.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertTemplateUsed(res, 'project/volumes/index.html')
|
||||
|
||||
self.mox.UnsetStubs()
|
||||
return res
|
||||
|
||||
@override_settings(API_RESULT_PAGE_SIZE=1)
|
||||
def test_backups_index_paginated(self):
|
||||
mox_backups = self.cinder_volume_backups.list()
|
||||
size = settings.API_RESULT_PAGE_SIZE
|
||||
base_url = reverse('horizon:project:volumes:backups_tab')
|
||||
next = backup_tables.BackupsTable._meta.pagination_param
|
||||
|
||||
# get first page
|
||||
expected_backups = mox_backups[:size]
|
||||
res = self._test_backups_index_paginated(
|
||||
marker=None, sort_dir="desc", backups=expected_backups,
|
||||
url=base_url, has_more=True, has_prev=False)
|
||||
backups = res.context['volume_backups_table'].data
|
||||
self.assertItemsEqual(backups, expected_backups)
|
||||
|
||||
# get second page
|
||||
expected_backups = mox_backups[size:2 * size]
|
||||
marker = expected_backups[0].id
|
||||
|
||||
url = "&".join([base_url, "=".join([next, marker])])
|
||||
res = self._test_backups_index_paginated(
|
||||
marker=marker, sort_dir="desc", backups=expected_backups, url=url,
|
||||
has_more=True, has_prev=True)
|
||||
backups = res.context['volume_backups_table'].data
|
||||
self.assertItemsEqual(backups, expected_backups)
|
||||
|
||||
# get last page
|
||||
expected_backups = mox_backups[-size:]
|
||||
marker = expected_backups[0].id
|
||||
url = "&".join([base_url, "=".join([next, marker])])
|
||||
res = self._test_backups_index_paginated(
|
||||
marker=marker, sort_dir="desc", backups=expected_backups, url=url,
|
||||
has_more=False, has_prev=True)
|
||||
backups = res.context['volume_backups_table'].data
|
||||
self.assertItemsEqual(backups, expected_backups)
|
||||
|
||||
@override_settings(API_RESULT_PAGE_SIZE=1)
|
||||
def test_backups_index_paginated_prev_page(self):
|
||||
mox_backups = self.cinder_volume_backups.list()
|
||||
size = settings.API_RESULT_PAGE_SIZE
|
||||
base_url = reverse('horizon:project:volumes:backups_tab')
|
||||
prev = backup_tables.BackupsTable._meta.prev_pagination_param
|
||||
|
||||
# prev from some page
|
||||
expected_backups = mox_backups[size:2 * size]
|
||||
marker = expected_backups[0].id
|
||||
url = "&".join([base_url, "=".join([prev, marker])])
|
||||
res = self._test_backups_index_paginated(
|
||||
marker=marker, sort_dir="asc", backups=expected_backups, url=url,
|
||||
has_more=True, has_prev=True)
|
||||
backups = res.context['volume_backups_table'].data
|
||||
self.assertItemsEqual(backups, expected_backups)
|
||||
|
||||
# back to first page
|
||||
expected_backups = mox_backups[:size]
|
||||
marker = expected_backups[0].id
|
||||
url = "&".join([base_url, "=".join([prev, marker])])
|
||||
res = self._test_backups_index_paginated(
|
||||
marker=marker, sort_dir="asc", backups=expected_backups, url=url,
|
||||
has_more=True, has_prev=False)
|
||||
backups = res.context['volume_backups_table'].data
|
||||
self.assertItemsEqual(backups, expected_backups)
|
||||
|
|
|
@ -185,12 +185,21 @@ def data(TEST):
|
|||
'size': 80,
|
||||
'status': 'available',
|
||||
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||
snapshot3 = vol_snaps.Snapshot(
|
||||
vol_snaps.SnapshotManager(None),
|
||||
{'id': 'c9d0881a-4c0b-4158-a212-ad27e11c2b0e',
|
||||
'name': '',
|
||||
'description': 'v2 volume snapshot description 2',
|
||||
'size': 80,
|
||||
'status': 'available',
|
||||
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||
|
||||
snapshot.bootable = 'true'
|
||||
snapshot2.bootable = 'true'
|
||||
|
||||
TEST.cinder_volume_snapshots.add(api.cinder.VolumeSnapshot(snapshot))
|
||||
TEST.cinder_volume_snapshots.add(api.cinder.VolumeSnapshot(snapshot2))
|
||||
TEST.cinder_volume_snapshots.add(api.cinder.VolumeSnapshot(snapshot3))
|
||||
TEST.cinder_volume_snapshots.first()._volume = volume
|
||||
|
||||
# Volume Type Encryption
|
||||
|
@ -233,8 +242,19 @@ def data(TEST):
|
|||
'container_name': 'volumebackups',
|
||||
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||
|
||||
volume_backup3 = vol_backups.VolumeBackup(
|
||||
vol_backups.VolumeBackupManager(None),
|
||||
{'id': 'c321cbb8-3f99-4c3f-a2ef-3edbec842e53',
|
||||
'name': 'backup3',
|
||||
'description': 'volume backup 3',
|
||||
'size': 20,
|
||||
'status': 'available',
|
||||
'container_name': 'volumebackups',
|
||||
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||
|
||||
TEST.cinder_volume_backups.add(volume_backup1)
|
||||
TEST.cinder_volume_backups.add(volume_backup2)
|
||||
TEST.cinder_volume_backups.add(volume_backup3)
|
||||
|
||||
# Volume Encryption
|
||||
vol_enc_metadata1 = volumes.Volume(
|
||||
|
|
Loading…
Reference in New Issue