Move Volume Backups out of tabbed panel
Notes on enabling backup: https://github.com/coolsvap/devstack-cinder-backup Change-Id: Ie6bcfad30d04ee35c75d693f5637197297ca84ef Implements: blueprint reorganise-volumes
This commit is contained in:
parent
d7e1adeca0
commit
921f84a7ce
@ -74,7 +74,7 @@ class RestoreBackupForm(forms.SelfHandlingForm):
|
||||
volumes = api.cinder.volume_list(request)
|
||||
except Exception:
|
||||
msg = _('Unable to lookup volume or backup information.')
|
||||
redirect = reverse('horizon:project:volumes:index')
|
||||
redirect = reverse('horizon:project:backups:index')
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
raise exceptions.Http302(redirect)
|
||||
|
||||
@ -104,5 +104,5 @@ class RestoreBackupForm(forms.SelfHandlingForm):
|
||||
return restore
|
||||
except Exception:
|
||||
msg = _('Unable to restore backup.')
|
||||
redirect = reverse('horizon:project:volumes:index')
|
||||
redirect = reverse('horizon:project:backups:index')
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
26
openstack_dashboard/dashboards/project/backups/panel.py
Normal file
26
openstack_dashboard/dashboards/project/backups/panel.py
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright 2017 Rackspace, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
|
||||
class Backups(horizon.Panel):
|
||||
name = _("Backups")
|
||||
slug = 'backups'
|
||||
permissions = (
|
||||
('openstack.services.volume', 'openstack.services.volumev2'),
|
||||
)
|
||||
policy_rules = (("volume", "backup:get_all"),)
|
@ -86,7 +86,7 @@ class RestoreBackup(tables.LinkAction):
|
||||
backup_id = datum.id
|
||||
backup_name = datum.name
|
||||
volume_id = getattr(datum, 'volume_id', None)
|
||||
url = reverse("horizon:project:volumes:backups:restore",
|
||||
url = reverse("horizon:project:backups:restore",
|
||||
args=(backup_id,))
|
||||
url += '?%s' % http.urlencode({'backup_name': backup_name,
|
||||
'volume_id': volume_id})
|
||||
@ -133,7 +133,7 @@ class BackupsTable(tables.DataTable):
|
||||
)
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link="horizon:project:volumes:backups:detail")
|
||||
link="horizon:project:backups:detail")
|
||||
description = tables.Column("description",
|
||||
verbose_name=_("Description"),
|
||||
truncate=40)
|
@ -23,8 +23,7 @@ from openstack_dashboard.api import cinder
|
||||
class BackupOverviewTab(tabs.Tab):
|
||||
name = _("Overview")
|
||||
slug = "overview"
|
||||
template_name = ("project/volumes/backups/"
|
||||
"_detail_overview.html")
|
||||
template_name = "project/backups/_detail_overview.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
try:
|
||||
@ -36,7 +35,7 @@ class BackupOverviewTab(tabs.Tab):
|
||||
return {'backup': backup,
|
||||
'volume': volume}
|
||||
except Exception:
|
||||
redirect = reverse('horizon:project:volumes:index')
|
||||
redirect = reverse('horizon:project:backups:index')
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve backup details.'),
|
||||
redirect=redirect)
|
@ -10,21 +10,108 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django import http
|
||||
from django.test.utils import override_settings
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.http import urlunquote
|
||||
from mox3.mox import IsA # noqa
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.backups \
|
||||
import tables as backup_tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:volumes:index')
|
||||
VOLUME_BACKUPS_TAB_URL = reverse('horizon:project:volumes:backups_tab')
|
||||
INDEX_URL = reverse('horizon:project:backups:index')
|
||||
|
||||
|
||||
class VolumeBackupsViewTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.cinder: ('tenant_absolute_limits',
|
||||
'volume_backup_list_paged',
|
||||
'volume_list'),
|
||||
api.nova: ('server_list',)})
|
||||
def _test_backups_index_paginated(self, marker, sort_dir, backups, url,
|
||||
has_more, has_prev):
|
||||
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(urlunquote(url))
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertTemplateUsed(res, 'horizon/common/_data_table_view.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 = INDEX_URL
|
||||
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 = base_url + "?%s=%s" % (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 = base_url + "?%s=%s" % (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 = INDEX_URL
|
||||
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 = base_url + "?%s=%s" % (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 = base_url + "?%s=%s" % (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)
|
||||
|
||||
@test.create_stubs({api.cinder: ('volume_backup_create',)})
|
||||
def test_create_backup_post(self):
|
||||
volume = self.volumes.first()
|
||||
@ -50,10 +137,9 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertMessageCount(error=0, warning=0)
|
||||
self.assertRedirectsNoFollow(res, VOLUME_BACKUPS_TAB_URL)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.cinder: ('volume_list',
|
||||
'volume_backup_supported',
|
||||
'volume_backup_list_paged',
|
||||
'volume_backup_delete')})
|
||||
def test_delete_volume_backup(self):
|
||||
@ -61,8 +147,6 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
volumes = self.cinder_volumes.list()
|
||||
backup = self.cinder_volume_backups.first()
|
||||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)). \
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.cinder.volume_backup_list_paged(
|
||||
IsA(http.HttpRequest), marker=None, sort_dir='desc',
|
||||
paginate=True).AndReturn([vol_backups, False, False])
|
||||
@ -74,12 +158,9 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
|
||||
formData = {'action':
|
||||
'volume_backups__delete__%s' % backup.id}
|
||||
res = self.client.post(INDEX_URL +
|
||||
"?tab=volumes_and_snapshots__backups_tab",
|
||||
formData)
|
||||
res = self.client.post(INDEX_URL, formData)
|
||||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL +
|
||||
"?tab=volumes_and_snapshots__backups_tab")
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
self.assertMessageCount(success=1)
|
||||
|
||||
@test.create_stubs({api.cinder: ('volume_backup_get', 'volume_get')})
|
||||
@ -93,7 +174,7 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
AndReturn(volume)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:project:volumes:backups:detail',
|
||||
url = reverse('horizon:project:backups:detail',
|
||||
args=[backup.id])
|
||||
res = self.client.get(url)
|
||||
|
||||
@ -109,7 +190,7 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
AndRaise(self.exceptions.cinder)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:project:volumes:backups:detail',
|
||||
url = reverse('horizon:project:backups:detail',
|
||||
args=[backup.id])
|
||||
res = self.client.get(url)
|
||||
|
||||
@ -128,7 +209,7 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
AndRaise(self.exceptions.cinder)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:project:volumes:backups:detail',
|
||||
url = reverse('horizon:project:backups:detail',
|
||||
args=[backup.id])
|
||||
res = self.client.get(url)
|
||||
|
||||
@ -153,7 +234,7 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
'backup_id': backup.id,
|
||||
'backup_name': backup.name,
|
||||
'volume_id': backup.volume_id}
|
||||
url = reverse('horizon:project:volumes:backups:restore',
|
||||
url = reverse('horizon:project:backups:restore',
|
||||
args=[backup.id])
|
||||
url += '?%s' % urlencode({'backup_name': backup.name,
|
||||
'volume_id': backup.volume_id})
|
||||
@ -161,4 +242,5 @@ class VolumeBackupsViewTests(test.TestCase):
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertMessageCount(info=1)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
self.assertRedirectsNoFollow(res,
|
||||
reverse('horizon:project:volumes:index'))
|
@ -12,10 +12,11 @@
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes.backups import views
|
||||
from openstack_dashboard.dashboards.project.backups import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.BackupsView.as_view(), name='index'),
|
||||
url(r'^(?P<backup_id>[^/]+)/$',
|
||||
views.BackupDetailView.as_view(),
|
||||
name='detail'),
|
@ -16,24 +16,53 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.volumes.backups \
|
||||
from openstack_dashboard.dashboards.project.backups \
|
||||
import forms as backup_forms
|
||||
from openstack_dashboard.dashboards.project.volumes.backups \
|
||||
from openstack_dashboard.dashboards.project.backups \
|
||||
import tables as backup_tables
|
||||
from openstack_dashboard.dashboards.project.volumes.backups \
|
||||
from openstack_dashboard.dashboards.project.backups \
|
||||
import tabs as backup_tabs
|
||||
from openstack_dashboard.dashboards.project.volumes \
|
||||
import tabs as volume_tabs
|
||||
|
||||
|
||||
class BackupsView(tables.DataTableView, tables.PagedTableMixin,
|
||||
volume_tabs.VolumeTableMixIn):
|
||||
table_class = backup_tables.BackupsTable
|
||||
page_title = _("Volume Backups")
|
||||
|
||||
def allowed(self, request):
|
||||
return api.cinder.volume_backup_supported(self.request)
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
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:
|
||||
backup.volume = volumes.get(backup.volume_id)
|
||||
except Exception:
|
||||
backups = []
|
||||
exceptions.handle(self.request, _("Unable to retrieve "
|
||||
"volume backups."))
|
||||
return backups
|
||||
|
||||
|
||||
class CreateBackupView(forms.ModalFormView):
|
||||
form_class = backup_forms.CreateBackupForm
|
||||
template_name = 'project/volumes/backups/create_backup.html'
|
||||
template_name = 'project/backups/create_backup.html'
|
||||
submit_label = _("Create Volume Backup")
|
||||
submit_url = "horizon:project:volumes:volumes:create_backup"
|
||||
success_url = reverse_lazy("horizon:project:volumes:backups_tab")
|
||||
success_url = reverse_lazy("horizon:project:backups:index")
|
||||
page_title = _("Create Volume Backup")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@ -79,14 +108,14 @@ class BackupDetailView(tabs.TabView):
|
||||
|
||||
@staticmethod
|
||||
def get_redirect_url():
|
||||
return reverse('horizon:project:volumes:index')
|
||||
return reverse('horizon:project:backups:index')
|
||||
|
||||
|
||||
class RestoreBackupView(forms.ModalFormView):
|
||||
form_class = backup_forms.RestoreBackupForm
|
||||
template_name = 'project/volumes/backups/restore_backup.html'
|
||||
template_name = 'project/backups/restore_backup.html'
|
||||
submit_label = _("Restore Backup to Volume")
|
||||
submit_url = "horizon:project:volumes:backups:restore"
|
||||
submit_url = "horizon:project:backups:restore"
|
||||
success_url = reverse_lazy('horizon:project:volumes:index')
|
||||
page_title = _("Restore Volume Backup")
|
||||
|
@ -23,8 +23,6 @@ from horizon import tabs
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes.backups \
|
||||
import tables as backups_tables
|
||||
from openstack_dashboard.dashboards.project.volumes.cg_snapshots \
|
||||
import tables as cg_snapshots_tables
|
||||
from openstack_dashboard.dashboards.project.volumes.cgroups \
|
||||
@ -126,34 +124,6 @@ class VolumeTab(PagedTableMixin, tabs.TableTab, VolumeTableMixIn):
|
||||
return volumes
|
||||
|
||||
|
||||
class BackupsTab(PagedTableMixin, tabs.TableTab, VolumeTableMixIn):
|
||||
table_classes = (backups_tables.BackupsTable,)
|
||||
name = _("Volume Backups")
|
||||
slug = "backups_tab"
|
||||
template_name = ("horizon/common/_detail_table.html")
|
||||
preload = False
|
||||
|
||||
def allowed(self, request):
|
||||
return api.cinder.volume_backup_supported(self.request)
|
||||
|
||||
def get_volume_backups_data(self):
|
||||
try:
|
||||
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:
|
||||
backup.volume = volumes.get(backup.volume_id)
|
||||
except Exception:
|
||||
backups = []
|
||||
exceptions.handle(self.request, _("Unable to retrieve "
|
||||
"volume backups."))
|
||||
return backups
|
||||
|
||||
|
||||
class CGroupsTab(tabs.TableTab):
|
||||
table_classes = (cgroup_tables.VolumeCGroupsTable,)
|
||||
name = _("Consistency Groups")
|
||||
@ -206,5 +176,5 @@ class CGSnapshotsTab(tabs.TableTab):
|
||||
|
||||
class VolumeAndSnapshotTabs(tabs.TabGroup):
|
||||
slug = "volumes_and_snapshots"
|
||||
tabs = (VolumeTab, BackupsTab, CGroupsTab, CGSnapshotsTab)
|
||||
tabs = (VolumeTab, CGroupsTab, CGSnapshotsTab)
|
||||
sticky = True
|
||||
|
@ -23,16 +23,12 @@ from django.utils.http import urlunquote
|
||||
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.volumes \
|
||||
import tables as volume_tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:volumes:index')
|
||||
VOLUME_BACKUPS_TAB_URL = urlunquote(reverse(
|
||||
'horizon:project:volumes:backups_tab'))
|
||||
|
||||
|
||||
class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
|
||||
@ -44,8 +40,7 @@ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
|
||||
'volume_backup_list_paged',
|
||||
),
|
||||
api.nova: ('server_list',)})
|
||||
def _test_index(self, backup_supported=True, instanceless_volumes=False):
|
||||
vol_backups = self.cinder_volume_backups.list()
|
||||
def test_index(self, instanceless_volumes=False):
|
||||
vol_snaps = self.cinder_volume_snapshots.list()
|
||||
volumes = self.cinder_volumes.list()
|
||||
if instanceless_volumes:
|
||||
@ -53,7 +48,7 @@ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
|
||||
volume.attachments = []
|
||||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)).\
|
||||
MultipleTimes().AndReturn(backup_supported)
|
||||
MultipleTimes().AndReturn(False)
|
||||
api.cinder.volume_list_paged(
|
||||
IsA(http.HttpRequest), marker=None, search_opts=None,
|
||||
sort_dir='desc', paginate=True).\
|
||||
@ -65,11 +60,6 @@ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
|
||||
api.cinder.volume_snapshot_list(IsA(http.HttpRequest)).\
|
||||
AndReturn(vol_snaps)
|
||||
|
||||
if backup_supported:
|
||||
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'])
|
||||
self.mox.ReplayAll()
|
||||
@ -78,18 +68,8 @@ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertTemplateUsed(res, 'project/volumes/index.html')
|
||||
|
||||
if backup_supported:
|
||||
res = self.client.get(VOLUME_BACKUPS_TAB_URL)
|
||||
self.assertTemplateUsed(res, 'project/volumes/index.html')
|
||||
|
||||
def test_index_backup_supported(self):
|
||||
self._test_index(backup_supported=True)
|
||||
|
||||
def test_index_backup_not_supported(self):
|
||||
self._test_index(backup_supported=False)
|
||||
|
||||
def test_index_no_volume_attachments(self):
|
||||
self._test_index(instanceless_volumes=True)
|
||||
self.test_index(instanceless_volumes=True)
|
||||
|
||||
@test.create_stubs({api.cinder: ('tenant_absolute_limits',
|
||||
'volume_list_paged',
|
||||
@ -193,92 +173,3 @@ class VolumeAndSnapshotsAndBackupsTests(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_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(urlunquote(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)
|
||||
|
@ -15,8 +15,6 @@
|
||||
from django.conf.urls import include
|
||||
from django.conf.urls import url
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes.backups \
|
||||
import urls as backups_urls
|
||||
from openstack_dashboard.dashboards.project.volumes.cg_snapshots \
|
||||
import urls as cg_snapshots_urls
|
||||
from openstack_dashboard.dashboards.project.volumes.cgroups \
|
||||
@ -29,8 +27,6 @@ urlpatterns = [
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'^\?tab=volumes_and_snapshots__volumes_tab$',
|
||||
views.IndexView.as_view(), name='volumes_tab'),
|
||||
url(r'^\?tab=volumes_and_snapshots__backups_tab$',
|
||||
views.IndexView.as_view(), name='backups_tab'),
|
||||
url(r'^\?tab=volumes_and_snapshots__cgroups_tab$',
|
||||
views.IndexView.as_view(), name='cgroups_tab'),
|
||||
url(r'^\?tab=volumes_and_snapshots__cg_snapshots_tab$',
|
||||
@ -38,9 +34,6 @@ urlpatterns = [
|
||||
url(r'', include(
|
||||
volume_urls,
|
||||
namespace='volumes')),
|
||||
url(r'backups/', include(
|
||||
backups_urls,
|
||||
namespace='backups')),
|
||||
url(r'cgroups/', include(
|
||||
cgroup_urls,
|
||||
namespace='cgroups')),
|
||||
|
@ -16,7 +16,7 @@ from django.conf.urls import url
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes \
|
||||
.volumes import views
|
||||
from openstack_dashboard.dashboards.project.volumes.backups \
|
||||
from openstack_dashboard.dashboards.project.backups \
|
||||
import views as backup_views
|
||||
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
# The slug of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'backups'
|
||||
# The slug of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'project'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'volumes'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = 'openstack_dashboard.dashboards.project.backups.panel.Backups'
|
Loading…
Reference in New Issue
Block a user