Merge "Move Consistency Group Snapshots out of Volumes panel"
This commit is contained in:
commit
b7b9e13de6
@ -68,7 +68,7 @@ class CreateCGroupForm(forms.SelfHandlingForm):
|
||||
messages.info(request, message)
|
||||
return cgroup
|
||||
except Exception:
|
||||
redirect = reverse("horizon:project:volumes:index")
|
||||
redirect = reverse("horizon:project:cg_snapshots:index")
|
||||
msg = _('Unable to create consistency '
|
||||
'group "%s" from snapshot.') % data['name']
|
||||
exceptions.handle(request,
|
26
openstack_dashboard/dashboards/project/cg_snapshots/panel.py
Normal file
26
openstack_dashboard/dashboards/project/cg_snapshots/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 CGSnapshots(horizon.Panel):
|
||||
name = _("Consistency Group Snapshots")
|
||||
slug = 'cg_snapshots'
|
||||
permissions = (
|
||||
('openstack.services.volume', 'openstack.services.volumev2'),
|
||||
)
|
||||
policy_rules = (("volume", "consistencygroup:get_all_cgsnapshots"),)
|
@ -23,7 +23,7 @@ from openstack_dashboard import policy
|
||||
class CreateVolumeCGroup(policy.PolicyTargetMixin, tables.LinkAction):
|
||||
name = "create_cgroup"
|
||||
verbose_name = _("Create Consistency Group")
|
||||
url = "horizon:project:volumes:cg_snapshots:create_cgroup"
|
||||
url = "horizon:project:cg_snapshots:create_cgroup"
|
||||
classes = ("ajax-modal",)
|
||||
policy_rules = (("volume", "consistencygroup:create"),)
|
||||
|
||||
@ -90,8 +90,7 @@ class CGSnapshotsTable(tables.DataTable):
|
||||
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link="horizon:project:volumes:"
|
||||
"cg_snapshots:cg_snapshot_detail")
|
||||
link="horizon:project:cg_snapshots:detail")
|
||||
description = tables.Column("description",
|
||||
verbose_name=_("Description"),
|
||||
truncate=40)
|
||||
@ -113,4 +112,6 @@ class CGSnapshotsTable(tables.DataTable):
|
||||
DeleteVolumeCGSnapshot,)
|
||||
row_class = UpdateRow
|
||||
status_columns = ("status",)
|
||||
permissions = ['openstack.services.volume']
|
||||
permissions = [
|
||||
('openstack.services.volume', 'openstack.services.volumev2')
|
||||
]
|
@ -19,14 +19,14 @@ from horizon import tabs
|
||||
class OverviewTab(tabs.Tab):
|
||||
name = _("Overview")
|
||||
slug = "overview"
|
||||
template_name = ("project/volumes/cg_snapshots/_detail_overview.html")
|
||||
template_name = "project/cg_snapshots/_detail_overview.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
cg_snapshot = self.tab_group.kwargs['cg_snapshot']
|
||||
return {"cg_snapshot": cg_snapshot}
|
||||
|
||||
def get_redirect_url(self):
|
||||
return reverse('horizon:project:volumes:cg_snapshots:index')
|
||||
return reverse('horizon:project:cg_snapshots:index')
|
||||
|
||||
|
||||
class CGSnapshotsDetailTabs(tabs.TabGroup):
|
@ -12,16 +12,13 @@
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django import http
|
||||
from django.utils.http import urlunquote
|
||||
from mox3.mox import IsA # noqa
|
||||
|
||||
from openstack_dashboard.api import cinder
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
VOLUME_INDEX_URL = reverse('horizon:project:volumes:index')
|
||||
VOLUME_CG_SNAPSHOTS_TAB_URL = urlunquote(reverse(
|
||||
'horizon:project:volumes:cg_snapshots_tab'))
|
||||
INDEX_URL = reverse('horizon:project:cg_snapshots:index')
|
||||
|
||||
|
||||
class CGroupSnapshotTests(test.TestCase):
|
||||
@ -44,11 +41,11 @@ class CGroupSnapshotTests(test.TestCase):
|
||||
.AndReturn(cgroup)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:project:volumes:cg_snapshots:create_cgroup',
|
||||
url = reverse('horizon:project:cg_snapshots:create_cgroup',
|
||||
args=[cg_snapshot.id])
|
||||
res = self.client.post(url, formData)
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({cinder: ('volume_cg_snapshot_get',
|
||||
'volume_cgroup_create_from_source',)})
|
||||
@ -69,7 +66,7 @@ class CGroupSnapshotTests(test.TestCase):
|
||||
.AndRaise(self.exceptions.cinder)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:project:volumes:cg_snapshots:create_cgroup',
|
||||
url = reverse('horizon:project:cg_snapshots:create_cgroup',
|
||||
args=[cg_snapshot.id])
|
||||
res = self.client.post(url, formData)
|
||||
self.assertNoFormErrors(res)
|
||||
@ -78,7 +75,7 @@ class CGroupSnapshotTests(test.TestCase):
|
||||
self.assertIn('Unable to create consistency group "%s" from snapshot.'
|
||||
% new_cg_name,
|
||||
res.cookies.output().replace('\\', ''))
|
||||
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({cinder: ('volume_cg_snapshot_list',
|
||||
'volume_cg_snapshot_delete',)})
|
||||
@ -93,8 +90,7 @@ class CGroupSnapshotTests(test.TestCase):
|
||||
|
||||
form_data = {'action': 'volume_cg_snapshots__delete_cg_snapshot__%s'
|
||||
% cg_snapshot.id}
|
||||
res = self.client.post(VOLUME_CG_SNAPSHOTS_TAB_URL, form_data,
|
||||
follow=True)
|
||||
res = self.client.post(INDEX_URL, form_data, follow=True)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("Scheduled deletion of Snapshot: %s" % cg_snapshot.name,
|
||||
[m.message for m in res.context['messages']])
|
||||
@ -114,8 +110,7 @@ class CGroupSnapshotTests(test.TestCase):
|
||||
|
||||
form_data = {'action': 'volume_cg_snapshots__delete_cg_snapshot__%s'
|
||||
% cg_snapshot.id}
|
||||
res = self.client.post(VOLUME_CG_SNAPSHOTS_TAB_URL, form_data,
|
||||
follow=True)
|
||||
res = self.client.post(INDEX_URL, form_data, follow=True)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("Unable to delete snapshot: %s" % cg_snapshot.name,
|
||||
[m.message for m in res.context['messages']])
|
||||
@ -143,7 +138,7 @@ class CGroupSnapshotTests(test.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse(
|
||||
'horizon:project:volumes:cg_snapshots:cg_snapshot_detail',
|
||||
'horizon:project:cg_snapshots:cg_snapshot_detail',
|
||||
args=[cg_snapshot.id])
|
||||
res = self.client.get(url)
|
||||
self.assertNoFormErrors(res)
|
||||
@ -159,8 +154,8 @@ class CGroupSnapshotTests(test.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse(
|
||||
'horizon:project:volumes:cg_snapshots:cg_snapshot_detail',
|
||||
'horizon:project:cg_snapshots:cg_snapshot_detail',
|
||||
args=[cg_snapshot.id])
|
||||
res = self.client.get(url)
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
@ -12,9 +12,10 @@
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes.cg_snapshots import views
|
||||
from openstack_dashboard.dashboards.project.cg_snapshots import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.CGSnapshotsView.as_view(), name='index'),
|
||||
url(r'^(?P<cg_snapshot_id>[^/]+)/cg_snapshot_detail/$',
|
||||
views.DetailView.as_view(),
|
||||
name='cg_snapshot_detail'),
|
@ -16,6 +16,7 @@ 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
|
||||
|
||||
@ -23,17 +24,32 @@ from openstack_dashboard import api
|
||||
from openstack_dashboard.api import cinder
|
||||
from openstack_dashboard.usage import quotas
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes \
|
||||
.cg_snapshots import forms as cg_snapshot_forms
|
||||
from openstack_dashboard.dashboards.project.volumes \
|
||||
.cg_snapshots import tables as cg_snapshot_tables
|
||||
from openstack_dashboard.dashboards.project.volumes \
|
||||
.cg_snapshots import tabs as cg_snapshot_tabs
|
||||
from openstack_dashboard.dashboards.project.cg_snapshots \
|
||||
import forms as cg_snapshot_forms
|
||||
from openstack_dashboard.dashboards.project.cg_snapshots \
|
||||
import tables as cg_snapshot_tables
|
||||
from openstack_dashboard.dashboards.project.cg_snapshots \
|
||||
import tabs as cg_snapshot_tabs
|
||||
|
||||
CGROUP_INFO_FIELDS = ("name",
|
||||
"description")
|
||||
|
||||
INDEX_URL = "horizon:project:volumes:index"
|
||||
INDEX_URL = "horizon:project:cg_snapshots:index"
|
||||
|
||||
|
||||
class CGSnapshotsView(tables.DataTableView):
|
||||
table_class = cg_snapshot_tables.CGSnapshotsTable
|
||||
page_title = _("Consistency Group Snapshots")
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
cg_snapshots = api.cinder.volume_cg_snapshot_list(self.request)
|
||||
except Exception:
|
||||
cg_snapshots = []
|
||||
exceptions.handle(self.request, _("Unable to retrieve "
|
||||
"volume consistency group "
|
||||
"snapshots."))
|
||||
return cg_snapshots
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
@ -84,7 +100,7 @@ class DetailView(tabs.TabView):
|
||||
|
||||
@staticmethod
|
||||
def get_redirect_url():
|
||||
return reverse('horizon:project:volumes:index')
|
||||
return reverse(INDEX_URL)
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
cg_snapshot = self.get_data()
|
||||
@ -93,8 +109,8 @@ class DetailView(tabs.TabView):
|
||||
|
||||
class CreateCGroupView(forms.ModalFormView):
|
||||
form_class = cg_snapshot_forms.CreateCGroupForm
|
||||
template_name = 'project/volumes/cg_snapshots/create.html'
|
||||
submit_url = "horizon:project:volumes:cg_snapshots:create_cgroup"
|
||||
template_name = 'project/cg_snapshots/create.html'
|
||||
submit_url = "horizon:project:cg_snapshots:create_cgroup"
|
||||
success_url = reverse_lazy('horizon:project:cgroups:index')
|
||||
page_title = _("Create Volume Consistency Group")
|
||||
|
@ -20,8 +20,8 @@ from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:cgroups:index')
|
||||
VOLUME_CGROUPS_SNAP_TAB_URL = urlunquote(reverse(
|
||||
'horizon:project:volumes:cg_snapshots_tab'))
|
||||
VOLUME_CGROUPS_SNAP_INDEX_URL = urlunquote(reverse(
|
||||
'horizon:project:cg_snapshots:index'))
|
||||
|
||||
|
||||
class ConsistencyGroupTests(test.TestCase):
|
||||
@ -296,7 +296,7 @@ class ConsistencyGroupTests(test.TestCase):
|
||||
args=[cgroup.id])
|
||||
res = self.client.post(url, formData)
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, VOLUME_CGROUPS_SNAP_TAB_URL)
|
||||
self.assertRedirectsNoFollow(res, VOLUME_CGROUPS_SNAP_INDEX_URL)
|
||||
|
||||
@test.create_stubs({cinder: ('volume_cgroup_get',
|
||||
'volume_cgroup_create_from_source',)})
|
||||
|
@ -190,7 +190,7 @@ class CreateSnapshotView(forms.ModalFormView):
|
||||
template_name = 'project/cgroups/create_snapshot.html'
|
||||
submit_label = _("Create Snapshot")
|
||||
submit_url = "horizon:project:cgroups:create_snapshot"
|
||||
success_url = reverse_lazy('horizon:project:volumes:cg_snapshots_tab')
|
||||
success_url = reverse_lazy('horizon:project:cg_snapshots:index')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CreateSnapshotView, self).get_context_data(**kwargs)
|
||||
|
@ -21,10 +21,7 @@ from horizon.tables import PagedTableMixin
|
||||
from horizon import tabs
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes.cg_snapshots \
|
||||
import tables as cg_snapshots_tables
|
||||
from openstack_dashboard.dashboards.project.volumes.volumes \
|
||||
import tables as volume_tables
|
||||
|
||||
@ -122,32 +119,7 @@ class VolumeTab(PagedTableMixin, tabs.TableTab, VolumeTableMixIn):
|
||||
return volumes
|
||||
|
||||
|
||||
class CGSnapshotsTab(tabs.TableTab):
|
||||
table_classes = (cg_snapshots_tables.CGSnapshotsTable,)
|
||||
name = _("Consistency Group Snapshots")
|
||||
slug = "cg_snapshots_tab"
|
||||
template_name = ("horizon/common/_detail_table.html")
|
||||
preload = False
|
||||
|
||||
def allowed(self, request):
|
||||
return policy.check(
|
||||
(("volume", "consistencygroup:get_all_cgsnapshots"),),
|
||||
request
|
||||
)
|
||||
|
||||
def get_volume_cg_snapshots_data(self):
|
||||
try:
|
||||
cg_snapshots = api.cinder.volume_cg_snapshot_list(
|
||||
self.request)
|
||||
except Exception:
|
||||
cg_snapshots = []
|
||||
exceptions.handle(self.request, _("Unable to retrieve "
|
||||
"volume consistency group "
|
||||
"snapshots."))
|
||||
return cg_snapshots
|
||||
|
||||
|
||||
class VolumeAndSnapshotTabs(tabs.TabGroup):
|
||||
slug = "volumes_and_snapshots"
|
||||
tabs = (VolumeTab, CGSnapshotsTab)
|
||||
tabs = (VolumeTab, )
|
||||
sticky = True
|
||||
|
@ -15,8 +15,6 @@
|
||||
from django.conf.urls import include
|
||||
from django.conf.urls import url
|
||||
|
||||
from openstack_dashboard.dashboards.project.volumes.cg_snapshots \
|
||||
import urls as cg_snapshots_urls
|
||||
from openstack_dashboard.dashboards.project.volumes import views
|
||||
from openstack_dashboard.dashboards.project.volumes.volumes \
|
||||
import urls as volume_urls
|
||||
@ -25,12 +23,7 @@ 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__cg_snapshots_tab$',
|
||||
views.IndexView.as_view(), name='cg_snapshots_tab'),
|
||||
url(r'', include(
|
||||
volume_urls,
|
||||
namespace='volumes')),
|
||||
url(r'cg_snapshots/', include(
|
||||
cg_snapshots_urls,
|
||||
namespace='cg_snapshots')),
|
||||
]
|
||||
|
@ -0,0 +1,10 @@
|
||||
# The slug of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'cg_snapshots'
|
||||
# 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.cg_snapshots.panel.CGSnapshots'
|
Loading…
Reference in New Issue
Block a user