Merge "Move Consistency Groups out of Volumes panel"

This commit is contained in:
Jenkins 2017-03-06 15:14:26 +00:00 committed by Gerrit Code Review
commit 8a2da91ff9
28 changed files with 131 additions and 114 deletions

View File

@ -95,16 +95,16 @@
"snapshot_extension:snapshot_manage": "rule:admin_api",
"snapshot_extension:snapshot_unmanage": "rule:admin_api",
"consistencygroup:create" : "group:nobody",
"consistencygroup:delete": "group:nobody",
"consistencygroup:update": "group:nobody",
"consistencygroup:get": "group:nobody",
"consistencygroup:get_all": "group:nobody",
"consistencygroup:create" : "",
"consistencygroup:delete": "",
"consistencygroup:update": "",
"consistencygroup:get": "",
"consistencygroup:get_all": "",
"consistencygroup:create_cgsnapshot" : "group:nobody",
"consistencygroup:delete_cgsnapshot": "group:nobody",
"consistencygroup:get_cgsnapshot": "group:nobody",
"consistencygroup:get_all_cgsnapshots": "group:nobody",
"consistencygroup:create_cgsnapshot" : "",
"consistencygroup:delete_cgsnapshot": "",
"consistencygroup:get_cgsnapshot": "",
"consistencygroup:get_all_cgsnapshots": "",
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
"message:delete": "rule:admin_or_owner",

View File

@ -54,7 +54,7 @@ class UpdateForm(forms.SelfHandlingForm):
messages.info(request, message)
return True
except Exception:
redirect = reverse("horizon:project:volumes:index")
redirect = reverse("horizon:project:cgroups:index")
exceptions.handle(request,
_('Unable to update volume consistency group.'),
redirect=redirect)
@ -85,7 +85,7 @@ class RemoveVolsForm(forms.SelfHandlingForm):
return True
except Exception:
redirect = reverse("horizon:project:volumes:index")
redirect = reverse("horizon:project:groups:index")
exceptions.handle(request, _('Errors occurred in removing volumes '
'from consistency group.'),
redirect=redirect)
@ -110,7 +110,7 @@ class DeleteForm(forms.SelfHandlingForm):
return True
except Exception:
redirect = reverse("horizon:project:volumes:index")
redirect = reverse("horizon:project:cgroups:index")
exceptions.handle(request, _('Errors occurred in deleting '
'consistency group.'),
redirect=redirect)
@ -143,7 +143,7 @@ class CreateSnapshotForm(forms.SelfHandlingForm):
messages.info(request, message)
return snapshot
except Exception as e:
redirect = reverse("horizon:project:volumes:index")
redirect = reverse("horizon:project:cgroups:index")
msg = _('Unable to create consistency group snapshot.')
if e.code == 413:
msg = _('Requested snapshot would exceed the allowed quota.')
@ -204,7 +204,7 @@ class CloneCGroupForm(forms.SelfHandlingForm):
messages.info(request, message)
return cgroup
except Exception:
redirect = reverse("horizon:project:volumes:index")
redirect = reverse("horizon:project:cgroups:index")
msg = _('Unable to clone consistency group.')
search_opts = {'consistentcygroup_id': data['cgroup_id']}

View 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 CGroups(horizon.Panel):
name = _("Consistency Groups")
slug = 'cgroups'
permissions = (
('openstack.services.volume', 'openstack.services.volumev2'),
)
policy_rules = (("volume", "consistencygroup:get_all"),)

View File

@ -23,7 +23,7 @@ from openstack_dashboard import policy
class CreateVolumeCGroup(policy.PolicyTargetMixin, tables.LinkAction):
name = "create"
verbose_name = _("Create Consistency Group")
url = "horizon:project:volumes:cgroups:create"
url = "horizon:project:cgroups:create"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("volume", "consistencygroup:create"),)
@ -32,7 +32,7 @@ class CreateVolumeCGroup(policy.PolicyTargetMixin, tables.LinkAction):
class DeleteVolumeCGroup(policy.PolicyTargetMixin, tables.LinkAction):
name = "deletecg"
verbose_name = _("Delete Consistency Group")
url = "horizon:project:volumes:cgroups:delete"
url = "horizon:project:cgroups:delete"
classes = ("ajax-modal", "btn-danger")
policy_rules = (("volume", "consistencygroup:delete"), )
@ -40,7 +40,7 @@ class DeleteVolumeCGroup(policy.PolicyTargetMixin, tables.LinkAction):
class RemoveAllVolumes(policy.PolicyTargetMixin, tables.LinkAction):
name = "remove_vols"
verbose_name = _("Remove Volumes from Consistency Group")
url = "horizon:project:volumes:cgroups:remove_volumes"
url = "horizon:project:cgroups:remove_volumes"
classes = ("ajax-modal",)
policy_rules = (("volume", "consistencygroup:update"), )
@ -48,7 +48,7 @@ class RemoveAllVolumes(policy.PolicyTargetMixin, tables.LinkAction):
class EditVolumeCGroup(policy.PolicyTargetMixin, tables.LinkAction):
name = "edit"
verbose_name = _("Edit Consistency Group")
url = "horizon:project:volumes:cgroups:update"
url = "horizon:project:cgroups:update"
classes = ("ajax-modal",)
policy_rules = (("volume", "consistencygroup:update"),)
@ -56,7 +56,7 @@ class EditVolumeCGroup(policy.PolicyTargetMixin, tables.LinkAction):
class ManageVolumes(policy.PolicyTargetMixin, tables.LinkAction):
name = "manage"
verbose_name = _("Manage Volumes")
url = "horizon:project:volumes:cgroups:manage"
url = "horizon:project:cgroups:manage"
classes = ("ajax-modal",)
policy_rules = (("volume", "consistencygroup:update"),)
@ -70,7 +70,7 @@ class ManageVolumes(policy.PolicyTargetMixin, tables.LinkAction):
class CreateSnapshot(policy.PolicyTargetMixin, tables.LinkAction):
name = "create_snapshot"
verbose_name = _("Create Snapshot")
url = "horizon:project:volumes:cgroups:create_snapshot"
url = "horizon:project:cgroups:create_snapshot"
classes = ("ajax-modal",)
policy_rules = (("volume", "consistencygroup:create_cgsnapshot"),)
@ -84,7 +84,7 @@ class CreateSnapshot(policy.PolicyTargetMixin, tables.LinkAction):
class CloneCGroup(policy.PolicyTargetMixin, tables.LinkAction):
name = "clone_cgroup"
verbose_name = _("Clone Consistency Group")
url = "horizon:project:volumes:cgroups:clone_cgroup"
url = "horizon:project:cgroups:clone_cgroup"
classes = ("ajax-modal",)
policy_rules = (("volume", "consistencygroup:create"),)
@ -142,7 +142,7 @@ class VolumeCGroupsTable(tables.DataTable):
name = tables.WrappingColumn("name",
verbose_name=_("Name"),
link="horizon:project:volumes:cgroups:detail")
link="horizon:project:cgroups:detail")
description = tables.Column("description",
verbose_name=_("Description"),
truncate=40)

View File

@ -19,14 +19,14 @@ from horizon import tabs
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("project/volumes/cgroups/_detail_overview.html")
template_name = ("project/cgroups/_detail_overview.html")
def get_context_data(self, request):
cgroup = self.tab_group.kwargs['cgroup']
return {"cgroup": cgroup}
def get_redirect_url(self):
return reverse('horizon:project:volumes:index')
return reverse('horizon:project:cgroups:index')
class CGroupsDetailTabs(tabs.TabGroup):

View File

@ -19,9 +19,7 @@ from openstack_dashboard.api import cinder
from openstack_dashboard.test import helpers as test
VOLUME_INDEX_URL = reverse('horizon:project:volumes:index')
VOLUME_CGROUPS_TAB_URL = urlunquote(reverse(
'horizon:project:volumes:cgroups_tab'))
INDEX_URL = reverse('horizon:project:cgroups:index')
VOLUME_CGROUPS_SNAP_TAB_URL = urlunquote(reverse(
'horizon:project:volumes:cg_snapshots_tab'))
@ -62,10 +60,10 @@ class ConsistencyGroupTests(test.TestCase):
.AndReturn(cgroup)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:create')
url = reverse('horizon:project:cgroups:create')
res = self.client.post(url, formData)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)
self.assertRedirectsNoFollow(res, INDEX_URL)
@test.create_stubs({cinder: ('extension_supported',
'availability_zone_list',
@ -101,10 +99,10 @@ class ConsistencyGroupTests(test.TestCase):
.AndRaise(self.exceptions.cinder)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:create')
url = reverse('horizon:project:cgroups:create')
res = self.client.post(url, formData)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)
self.assertRedirectsNoFollow(res, INDEX_URL)
self.assertIn("Unable to create consistency group.",
res.cookies.output())
@ -119,11 +117,11 @@ class ConsistencyGroupTests(test.TestCase):
force=False)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:delete',
url = reverse('horizon:project:cgroups:delete',
args=[cgroup.id])
res = self.client.post(url)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)
self.assertRedirectsNoFollow(res, INDEX_URL)
@test.create_stubs({cinder: ('volume_cgroup_get',
'volume_cgroup_delete')})
@ -137,11 +135,11 @@ class ConsistencyGroupTests(test.TestCase):
force=True)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:delete',
url = reverse('horizon:project:cgroups:delete',
args=[cgroup.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_cgroup_get',
'volume_cgroup_delete')})
@ -157,11 +155,11 @@ class ConsistencyGroupTests(test.TestCase):
AndRaise(self.exceptions.cinder)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:delete',
url = reverse('horizon:project:cgroups:delete',
args=[cgroup.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_cgroup_update',
'volume_cgroup_get')})
@ -183,11 +181,11 @@ class ConsistencyGroupTests(test.TestCase):
.AndReturn(cgroup)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:update',
url = reverse('horizon:project:cgroups:update',
args=[cgroup.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_cgroup_update',
'volume_cgroup_get')})
@ -209,11 +207,11 @@ class ConsistencyGroupTests(test.TestCase):
.AndReturn(cgroup)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:update',
url = reverse('horizon:project:cgroups:update',
args=[cgroup.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_cgroup_update',
'volume_cgroup_get')})
@ -233,11 +231,11 @@ class ConsistencyGroupTests(test.TestCase):
.AndReturn(cgroup)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:update',
url = reverse('horizon:project:cgroups:update',
args=[cgroup.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_cgroup_update',
'volume_cgroup_get')})
@ -257,11 +255,11 @@ class ConsistencyGroupTests(test.TestCase):
.AndRaise(self.exceptions.cinder)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:update',
url = reverse('horizon:project:cgroups:update',
args=[cgroup.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_cgroup_get',)})
def test_detail_view_with_exception(self):
@ -272,11 +270,11 @@ class ConsistencyGroupTests(test.TestCase):
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:detail',
url = reverse('horizon:project:cgroups:detail',
args=[cgroup.id])
res = self.client.get(url)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)
self.assertRedirectsNoFollow(res, INDEX_URL)
@test.create_stubs({cinder: ('volume_cg_snapshot_create',)})
def test_create_snapshot(self):
@ -294,7 +292,7 @@ class ConsistencyGroupTests(test.TestCase):
.AndReturn(cg_snapshot)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:create_snapshot',
url = reverse('horizon:project:cgroups:create_snapshot',
args=[cgroup.id])
res = self.client.post(url, formData)
self.assertNoFormErrors(res)
@ -315,8 +313,8 @@ class ConsistencyGroupTests(test.TestCase):
.AndReturn(cgroup)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:cgroups:clone_cgroup',
url = reverse('horizon:project:cgroups:clone_cgroup',
args=[cgroup.id])
res = self.client.post(url, formData)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, VOLUME_CGROUPS_TAB_URL)
self.assertRedirectsNoFollow(res, INDEX_URL)

View File

@ -12,10 +12,11 @@
from django.conf.urls import url
from openstack_dashboard.dashboards.project.volumes.cgroups import views
from openstack_dashboard.dashboards.project.cgroups import views
urlpatterns = [
url(r'^$', views.CGroupsView.as_view(), name='index'),
url(r'^create/$',
views.CreateView.as_view(),
name='create'),

View File

@ -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
from horizon import workflows
@ -24,33 +25,49 @@ from openstack_dashboard import api
from openstack_dashboard.api import cinder
from openstack_dashboard.usage import quotas
from openstack_dashboard.dashboards.project.volumes \
.cgroups import workflows as vol_cgroup_workflows
from openstack_dashboard.dashboards.project.volumes \
.cgroups import forms as vol_cgroup_forms
from openstack_dashboard.dashboards.project.volumes \
.cgroups import tables as vol_cgroup_tables
from openstack_dashboard.dashboards.project.volumes \
.cgroups import tabs as vol_cgroup_tabs
from openstack_dashboard.dashboards.project.cgroups \
import forms as vol_cgroup_forms
from openstack_dashboard.dashboards.project.cgroups \
import tables as vol_cgroup_tables
from openstack_dashboard.dashboards.project.cgroups \
import tabs as vol_cgroup_tabs
from openstack_dashboard.dashboards.project.cgroups \
import workflows as vol_cgroup_workflows
CGROUP_INFO_FIELDS = ("name",
"description")
INDEX_URL = "horizon:project:volumes:index"
INDEX_URL = "horizon:project:cgroups:index"
class CGroupsView(tables.DataTableView):
table_class = vol_cgroup_tables.VolumeCGroupsTable
page_title = _("Consistency Groups")
def get_data(self):
try:
cgroups = api.cinder.volume_cgroup_list_with_vol_type_names(
self.request)
except Exception:
cgroups = []
exceptions.handle(self.request, _("Unable to retrieve "
"volume consistency groups."))
return cgroups
class CreateView(workflows.WorkflowView):
workflow_class = vol_cgroup_workflows.CreateCGroupWorkflow
template_name = 'project/volumes/cgroups/create.html'
template_name = 'project/cgroups/create.html'
page_title = _("Create Volume Consistency Group")
class UpdateView(forms.ModalFormView):
template_name = 'project/volumes/cgroups/update.html'
template_name = 'project/cgroups/update.html'
page_title = _("Edit Consistency Group")
form_class = vol_cgroup_forms.UpdateForm
success_url = reverse_lazy('horizon:project:volumes:index')
submit_url = "horizon:project:volumes:cgroups:update"
success_url = reverse_lazy('horizon:project:cgroups:index')
submit_url = "horizon:project:cgroups:update"
def get_initial(self):
cgroup = self.get_object()
@ -78,11 +95,11 @@ class UpdateView(forms.ModalFormView):
class RemoveVolumesView(forms.ModalFormView):
template_name = 'project/volumes/cgroups/remove_vols.html'
template_name = 'project/cgroups/remove_vols.html'
page_title = _("Remove Volumes from Consistency Group")
form_class = vol_cgroup_forms.RemoveVolsForm
success_url = reverse_lazy('horizon:project:volumes:index')
submit_url = "horizon:project:volumes:cgroups:remove_volumes"
success_url = reverse_lazy('horizon:project:cgroups:index')
submit_url = "horizon:project:cgroups:remove_volumes"
def get_initial(self):
cgroup = self.get_object()
@ -109,11 +126,11 @@ class RemoveVolumesView(forms.ModalFormView):
class DeleteView(forms.ModalFormView):
template_name = 'project/volumes/cgroups/delete.html'
template_name = 'project/cgroups/delete.html'
page_title = _("Delete Consistency Group")
form_class = vol_cgroup_forms.DeleteForm
success_url = reverse_lazy('horizon:project:volumes:index')
submit_url = "horizon:project:volumes:cgroups:delete"
success_url = reverse_lazy('horizon:project:cgroups:index')
submit_url = "horizon:project:cgroups:delete"
submit_label = page_title
def get_initial(self):
@ -170,9 +187,9 @@ class ManageView(workflows.WorkflowView):
class CreateSnapshotView(forms.ModalFormView):
form_class = vol_cgroup_forms.CreateSnapshotForm
page_title = _("Create Consistency Group Snapshot")
template_name = 'project/volumes/cgroups/create_snapshot.html'
template_name = 'project/cgroups/create_snapshot.html'
submit_label = _("Create Snapshot")
submit_url = "horizon:project:volumes:cgroups:create_snapshot"
submit_url = "horizon:project:cgroups:create_snapshot"
success_url = reverse_lazy('horizon:project:volumes:cg_snapshots_tab')
def get_context_data(self, **kwargs):
@ -212,10 +229,10 @@ class CreateSnapshotView(forms.ModalFormView):
class CloneCGroupView(forms.ModalFormView):
form_class = vol_cgroup_forms.CloneCGroupForm
page_title = _("Clone Consistency Group")
template_name = 'project/volumes/cgroups/clone_cgroup.html'
template_name = 'project/cgroups/clone_cgroup.html'
submit_label = _("Clone Consistency Group")
submit_url = "horizon:project:volumes:cgroups:clone_cgroup"
success_url = reverse_lazy('horizon:project:volumes:cgroups_tab')
submit_url = "horizon:project:cgroups:clone_cgroup"
success_url = reverse_lazy('horizon:project:cgroups:index')
def get_context_data(self, **kwargs):
context = super(CloneCGroupView, self).get_context_data(**kwargs)
@ -296,7 +313,7 @@ class DetailView(tabs.TabView):
@staticmethod
def get_redirect_url():
return reverse('horizon:project:volumes:index')
return reverse('horizon:project:cgroups:index')
def get_tabs(self, request, *args, **kwargs):
cgroup = self.get_data()

View File

@ -20,7 +20,7 @@ from horizon import workflows
from openstack_dashboard import api
from openstack_dashboard.api import cinder
INDEX_URL = "horizon:project:volumes:index"
INDEX_URL = "horizon:project:cgroups:index"
CGROUP_VOLUME_MEMBER_SLUG = "update_members"

View File

@ -95,7 +95,7 @@ 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"
success_url = reverse_lazy('horizon:project:volumes:cgroups_tab')
success_url = reverse_lazy('horizon:project:cgroups:index')
page_title = _("Create Volume Consistency Group")
def get_context_data(self, **kwargs):

View File

@ -25,8 +25,6 @@ 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.cgroups \
import tables as cgroup_tables
from openstack_dashboard.dashboards.project.volumes.volumes \
import tables as volume_tables
@ -124,31 +122,6 @@ class VolumeTab(PagedTableMixin, tabs.TableTab, VolumeTableMixIn):
return volumes
class CGroupsTab(tabs.TableTab):
table_classes = (cgroup_tables.VolumeCGroupsTable,)
name = _("Consistency Groups")
slug = "cgroups_tab"
template_name = ("horizon/common/_detail_table.html")
preload = False
def allowed(self, request):
return policy.check(
(("volume", "consistencygroup:get_all"),),
request
)
def get_volume_cgroups_data(self):
try:
cgroups = api.cinder.volume_cgroup_list_with_vol_type_names(
self.request)
except Exception:
cgroups = []
exceptions.handle(self.request, _("Unable to retrieve "
"volume consistency groups."))
return cgroups
class CGSnapshotsTab(tabs.TableTab):
table_classes = (cg_snapshots_tables.CGSnapshotsTable,)
name = _("Consistency Group Snapshots")
@ -176,5 +149,5 @@ class CGSnapshotsTab(tabs.TableTab):
class VolumeAndSnapshotTabs(tabs.TabGroup):
slug = "volumes_and_snapshots"
tabs = (VolumeTab, CGroupsTab, CGSnapshotsTab)
tabs = (VolumeTab, CGSnapshotsTab)
sticky = True

View File

@ -14,7 +14,7 @@
<dd>{{ cg_snapshot.status|capfirst }}</dd>
<dt>{% trans "Consistency Group" %}</dt>
<dd>
<a href="{% url 'horizon:project:volumes:cgroups:detail' cg_snapshot.consistencygroup_id %}">
<a href="{% url 'horizon:project:cgroups:detail' cg_snapshot.consistencygroup_id %}">
{% if cg_snapshot.cg_name %}
{{ cg_snapshot.cg_name }}
{% else %}

View File

@ -17,8 +17,6 @@ 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.cgroups \
import urls as cgroup_urls
from openstack_dashboard.dashboards.project.volumes import views
from openstack_dashboard.dashboards.project.volumes.volumes \
import urls as volume_urls
@ -27,16 +25,11 @@ 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__cgroups_tab$',
views.IndexView.as_view(), name='cgroups_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'cgroups/', include(
cgroup_urls,
namespace='cgroups')),
url(r'cg_snapshots/', include(
cg_snapshots_urls,
namespace='cg_snapshots')),

View File

@ -0,0 +1,9 @@
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'cgroups'
# 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.cgroups.panel.CGroups'