Move Consistency Groups out of Volumes panel

Notes on enabling consistency groups in devstack:
http://docs.openstack.org/admin-guide/blockstorage-consistency-groups.html

You'll also need to modify the local cinder policy file.

Though that's not actually enough to make it work since
devstack only provides the LVM volume type and CGs don't
work with LVM. You can attempt to create CGs, but they
will error.

Change-Id: I0ab541c81570cd5f67bb7d04c01bc92bc5cc3ab5
Implements: blueprint reorganise-volumes
This commit is contained in:
Richard Jones 2017-02-06 11:22:18 +11:00
parent 921f84a7ce
commit f85e0ffa91
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'