Add volume-group table actions for admin panel
This commit allows admin to perform the following table action : 1. manage volumes (Add/remove volumes from group), 2. remove all volumes from group 3. delete group Partially-Implements blueprint cinder-generic-volume-groups Change-Id: I7fcc0dfa8195ecb7914a883fec85c573caa4ae86
This commit is contained in:
24
openstack_dashboard/dashboards/admin/volume_groups/forms.py
Normal file
24
openstack_dashboard/dashboards/admin/volume_groups/forms.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Copyright 2019 NEC Corporation
|
||||||
|
#
|
||||||
|
# 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 openstack_dashboard.dashboards.project.volume_groups \
|
||||||
|
import forms as project_forms
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveVolsForm(project_forms.RemoveVolsForm):
|
||||||
|
failure_url = 'horizon:admin:volume_groups:index'
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteForm(project_forms.DeleteForm):
|
||||||
|
failure_url = 'horizon:admin:volume_groups:index'
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2017 NEC Corporation
|
# Copyright 2019 NEC Corporation
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from openstack_dashboard.dashboards.project.volume_groups \
|
from openstack_dashboard.dashboards.project.volume_groups \
|
||||||
import panel as volume_groups_panel
|
import panel as project_panel
|
||||||
|
|
||||||
|
|
||||||
class VolumeGroups(volume_groups_panel.VolumeGroups):
|
class VolumeGroups(project_panel.VolumeGroups):
|
||||||
policy_rules = (("volume", "context_is_admin"),)
|
policy_rules = (("volume", "context_is_admin"),)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Copyright 2019 NEC Corporation
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@@ -14,10 +16,22 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from horizon import tables
|
from horizon import tables
|
||||||
from openstack_dashboard.dashboards.project.volume_groups \
|
from openstack_dashboard.dashboards.project.volume_groups \
|
||||||
import tables as volume_groups_tables
|
import tables as project_tables
|
||||||
|
|
||||||
|
|
||||||
class GroupsTable(volume_groups_tables.GroupsTable):
|
class DeleteGroup(project_tables.DeleteGroup):
|
||||||
|
url = "horizon:admin:volume_groups:delete"
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveAllVolumes(project_tables.RemoveAllVolumes):
|
||||||
|
url = "horizon:admin:volume_groups:remove_volumes"
|
||||||
|
|
||||||
|
|
||||||
|
class ManageVolumes(project_tables.ManageVolumes):
|
||||||
|
url = "horizon:admin:volume_groups:manage"
|
||||||
|
|
||||||
|
|
||||||
|
class GroupsTable(project_tables.GroupsTable):
|
||||||
# TODO(vishalmanchanda): Add Project Info.column in table
|
# TODO(vishalmanchanda): Add Project Info.column in table
|
||||||
name = tables.WrappingColumn("name_or_id",
|
name = tables.WrappingColumn("name_or_id",
|
||||||
verbose_name=_("Name"),
|
verbose_name=_("Name"),
|
||||||
@@ -27,5 +41,12 @@ class GroupsTable(volume_groups_tables.GroupsTable):
|
|||||||
name = "volume_groups"
|
name = "volume_groups"
|
||||||
verbose_name = _("Volume Groups")
|
verbose_name = _("Volume Groups")
|
||||||
table_actions = (
|
table_actions = (
|
||||||
volume_groups_tables.GroupsFilterAction,
|
project_tables.GroupsFilterAction,
|
||||||
)
|
)
|
||||||
|
row_actions = (
|
||||||
|
ManageVolumes,
|
||||||
|
RemoveAllVolumes,
|
||||||
|
DeleteGroup,
|
||||||
|
)
|
||||||
|
row_class = project_tables.UpdateRow
|
||||||
|
status_columns = ("status",)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Copyright 2019 NEC Corporation
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@@ -13,15 +15,15 @@
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from openstack_dashboard.dashboards.project.volume_groups \
|
from openstack_dashboard.dashboards.project.volume_groups \
|
||||||
import tabs as volume_groups_tabs
|
import tabs as project_tabs
|
||||||
|
|
||||||
|
|
||||||
class OverviewTab(volume_groups_tabs.OverviewTab):
|
class OverviewTab(project_tabs.OverviewTab):
|
||||||
template_name = ("admin/volume_groups/_detail_overview.html")
|
template_name = ("admin/volume_groups/_detail_overview.html")
|
||||||
|
|
||||||
def get_redirect_url(self):
|
def get_redirect_url(self):
|
||||||
return reverse('horizon:admin:volume_groups:index')
|
return reverse('horizon:admin:volume_groups:index')
|
||||||
|
|
||||||
|
|
||||||
class GroupsDetailTabs(volume_groups_tabs.GroupsDetailTabs):
|
class GroupsDetailTabs(project_tabs.GroupsDetailTabs):
|
||||||
tabs = (OverviewTab,)
|
tabs = (OverviewTab,)
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{% extends "horizon/common/_modal_form.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{{ page_title }}{% endblock %}
|
||||||
|
|
||||||
|
{% block modal-body-right %}
|
||||||
|
<p>{% trans "Volume groups can not be deleted if they contain volumes." %}</p>
|
||||||
|
<p>{% trans "Check the "Delete Volumes" box to also delete any volumes associated with this group." %}</p>
|
||||||
|
<p>{% trans "Note that a volume can not be deleted if it is "attached" or has any dependent snapshots." %}</p>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{% extends "horizon/common/_modal_form.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{{ page_title }}{% endblock %}
|
||||||
|
|
||||||
|
{% block modal-body %}
|
||||||
|
<p>{% trans "This action will unassign all volumes that are currently contained in this group." %}</p>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{{ page_title }}{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
{% include 'admin/volumes/volume_groups/_delete.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{{ page_title }}{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
{% include 'admin/volume_groups/_remove_vols.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Copyright 2019 NEC Corporation
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@@ -12,6 +14,8 @@
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
from openstack_dashboard import api
|
from openstack_dashboard import api
|
||||||
from openstack_dashboard.api import cinder
|
from openstack_dashboard.api import cinder
|
||||||
from openstack_dashboard.test import helpers as test
|
from openstack_dashboard.test import helpers as test
|
||||||
@@ -42,6 +46,126 @@ class AdminVolumeGroupTests(test.BaseAdminViewTests):
|
|||||||
self.mock_group_snapshot_list.assert_called_once_with(
|
self.mock_group_snapshot_list.assert_called_once_with(
|
||||||
test.IsHttpRequest())
|
test.IsHttpRequest())
|
||||||
|
|
||||||
|
@test.create_mocks({cinder: ['group_get', 'group_delete']})
|
||||||
|
def test_delete_group(self):
|
||||||
|
group = self.cinder_groups.first()
|
||||||
|
|
||||||
|
self.mock_group_get.return_value = group
|
||||||
|
self.mock_group_delete.return_value = None
|
||||||
|
|
||||||
|
url = reverse('horizon:admin:volume_groups:delete',
|
||||||
|
args=[group.id])
|
||||||
|
res = self.client.post(url)
|
||||||
|
self.assertNoFormErrors(res)
|
||||||
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
|
self.mock_group_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
|
group.id)
|
||||||
|
self.mock_group_delete.assert_called_once_with(test.IsHttpRequest(),
|
||||||
|
group.id,
|
||||||
|
delete_volumes=False)
|
||||||
|
|
||||||
|
@test.create_mocks({cinder: ['group_get', 'group_delete']})
|
||||||
|
def test_delete_group_delete_volumes_flag(self):
|
||||||
|
group = self.cinder_consistencygroups.first()
|
||||||
|
formData = {'delete_volumes': True}
|
||||||
|
|
||||||
|
self.mock_group_get.return_value = group
|
||||||
|
self.mock_group_delete.return_value = None
|
||||||
|
|
||||||
|
url = reverse('horizon:admin:volume_groups:delete',
|
||||||
|
args=[group.id])
|
||||||
|
res = self.client.post(url, formData)
|
||||||
|
self.assertNoFormErrors(res)
|
||||||
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
|
self.mock_group_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
|
group.id)
|
||||||
|
self.mock_group_delete.assert_called_once_with(test.IsHttpRequest(),
|
||||||
|
group.id,
|
||||||
|
delete_volumes=True)
|
||||||
|
|
||||||
|
@test.create_mocks({cinder: ['group_get', 'group_delete']})
|
||||||
|
def test_delete_group_exception(self):
|
||||||
|
group = self.cinder_groups.first()
|
||||||
|
formData = {'delete_volumes': False}
|
||||||
|
|
||||||
|
self.mock_group_get.return_value = group
|
||||||
|
self.mock_group_delete.side_effect = self.exceptions.cinder
|
||||||
|
|
||||||
|
url = reverse('horizon:admin:volume_groups:delete',
|
||||||
|
args=[group.id])
|
||||||
|
res = self.client.post(url, formData)
|
||||||
|
self.assertNoFormErrors(res)
|
||||||
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
|
self.mock_group_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
|
group.id)
|
||||||
|
self.mock_group_delete.assert_called_once_with(test.IsHttpRequest(),
|
||||||
|
group.id,
|
||||||
|
delete_volumes=False)
|
||||||
|
|
||||||
|
def test_update_group_add_vol(self):
|
||||||
|
self._test_update_group_add_remove_vol(add=True)
|
||||||
|
|
||||||
|
def test_update_group_remove_vol(self):
|
||||||
|
self._test_update_group_add_remove_vol(add=False)
|
||||||
|
|
||||||
|
@test.create_mocks({cinder: ['volume_list',
|
||||||
|
'volume_type_list',
|
||||||
|
'group_get',
|
||||||
|
'group_update']})
|
||||||
|
def _test_update_group_add_remove_vol(self, add=True):
|
||||||
|
group = self.cinder_groups.first()
|
||||||
|
volume_types = self.cinder_volume_types.list()
|
||||||
|
volumes = (self.cinder_volumes.list() +
|
||||||
|
self.cinder_group_volumes.list())
|
||||||
|
|
||||||
|
group_voltype_names = [t.name for t in volume_types
|
||||||
|
if t.id in group.volume_types]
|
||||||
|
compat_volumes = [v for v in volumes
|
||||||
|
if v.volume_type in group_voltype_names]
|
||||||
|
compat_volume_ids = [v.id for v in compat_volumes]
|
||||||
|
assigned_volume_ids = [v.id for v in compat_volumes
|
||||||
|
if getattr(v, 'group_id', None)]
|
||||||
|
add_volume_ids = [v.id for v in compat_volumes
|
||||||
|
if v.id not in assigned_volume_ids]
|
||||||
|
|
||||||
|
new_volums = compat_volume_ids if add else []
|
||||||
|
formData = {
|
||||||
|
'default_add_volumes_to_group_role': 'member',
|
||||||
|
'add_volumes_to_group_role_member': new_volums,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mock_volume_list.return_value = volumes
|
||||||
|
self.mock_volume_type_list.return_value = volume_types
|
||||||
|
self.mock_group_get.return_value = group
|
||||||
|
self.mock_group_update.return_value = group
|
||||||
|
|
||||||
|
url = reverse('horizon:admin:volume_groups:manage',
|
||||||
|
args=[group.id])
|
||||||
|
res = self.client.post(url, formData)
|
||||||
|
self.assertNoFormErrors(res)
|
||||||
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
|
self.mock_volume_list, 2,
|
||||||
|
mock.call(test.IsHttpRequest()))
|
||||||
|
self.mock_volume_type_list.assert_called_once_with(
|
||||||
|
test.IsHttpRequest())
|
||||||
|
self.mock_group_get.assert_called_once_with(
|
||||||
|
test.IsHttpRequest(), group.id)
|
||||||
|
if add:
|
||||||
|
self.mock_group_update.assert_called_once_with(
|
||||||
|
test.IsHttpRequest(), group.id,
|
||||||
|
add_volumes=add_volume_ids,
|
||||||
|
remove_volumes=[])
|
||||||
|
else:
|
||||||
|
self.mock_group_update.assert_called_once_with(
|
||||||
|
test.IsHttpRequest(), group.id,
|
||||||
|
add_volumes=[],
|
||||||
|
remove_volumes=assigned_volume_ids)
|
||||||
|
|
||||||
@test.create_mocks({cinder: ['group_get_with_vol_type_names',
|
@test.create_mocks({cinder: ['group_get_with_vol_type_names',
|
||||||
'volume_list',
|
'volume_list',
|
||||||
'group_snapshot_list']})
|
'group_snapshot_list']})
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Copyright 2019 NEC Corporation
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@@ -20,4 +22,13 @@ urlpatterns = [
|
|||||||
url(r'^(?P<group_id>[^/]+)$',
|
url(r'^(?P<group_id>[^/]+)$',
|
||||||
views.DetailView.as_view(),
|
views.DetailView.as_view(),
|
||||||
name='detail'),
|
name='detail'),
|
||||||
|
url(r'^(?P<group_id>[^/]+)/remove_volumese/$',
|
||||||
|
views.RemoveVolumesView.as_view(),
|
||||||
|
name='remove_volumes'),
|
||||||
|
url(r'^(?P<group_id>[^/]+)/delete/$',
|
||||||
|
views.DeleteView.as_view(),
|
||||||
|
name='delete'),
|
||||||
|
url(r'^(?P<group_id>[^/]+)/manage/$',
|
||||||
|
views.ManageView.as_view(),
|
||||||
|
name='manage'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Copyright 2019 NEC Corporation
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@@ -11,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from horizon import exceptions
|
from horizon import exceptions
|
||||||
@@ -19,15 +22,19 @@ from horizon import tables
|
|||||||
from openstack_dashboard import api
|
from openstack_dashboard import api
|
||||||
|
|
||||||
from openstack_dashboard.dashboards.admin.volume_groups \
|
from openstack_dashboard.dashboards.admin.volume_groups \
|
||||||
import tables as volume_group_tables
|
import forms as admin_forms
|
||||||
from openstack_dashboard.dashboards.admin.volume_groups \
|
from openstack_dashboard.dashboards.admin.volume_groups \
|
||||||
import tabs as volume_group_tabs
|
import tables as admin_tables
|
||||||
|
from openstack_dashboard.dashboards.admin.volume_groups \
|
||||||
|
import tabs as admin_tabs
|
||||||
|
from openstack_dashboard.dashboards.admin.volume_groups \
|
||||||
|
import workflows as admin_workflows
|
||||||
from openstack_dashboard.dashboards.project.volume_groups \
|
from openstack_dashboard.dashboards.project.volume_groups \
|
||||||
import views as volume_groups_views
|
import views as project_views
|
||||||
|
|
||||||
|
|
||||||
class IndexView(tables.DataTableView):
|
class IndexView(tables.DataTableView):
|
||||||
table_class = volume_group_tables.GroupsTable
|
table_class = admin_tables.GroupsTable
|
||||||
page_title = _("Groups")
|
page_title = _("Groups")
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
@@ -47,12 +54,30 @@ class IndexView(tables.DataTableView):
|
|||||||
return groups
|
return groups
|
||||||
|
|
||||||
|
|
||||||
class DetailView(volume_groups_views.DetailView):
|
class RemoveVolumesView(project_views.RemoveVolumesView):
|
||||||
tab_group_class = volume_group_tabs.GroupsDetailTabs
|
template_name = 'admin/volume_groups/remove_vols.html'
|
||||||
|
form_class = admin_forms.RemoveVolsForm
|
||||||
|
success_url = reverse_lazy('horizon:admin:volume_groups:index')
|
||||||
|
submit_url = "horizon:admin:volume_groups:remove_volumes"
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteView(project_views.DeleteView):
|
||||||
|
template_name = 'admin/volume_groups/delete.html'
|
||||||
|
form_class = admin_forms.DeleteForm
|
||||||
|
success_url = reverse_lazy('horizon:admin:volume_groups:index')
|
||||||
|
submit_url = "horizon:admin:volume_groups:delete"
|
||||||
|
|
||||||
|
|
||||||
|
class ManageView(project_views.ManageView):
|
||||||
|
workflow_class = admin_workflows.UpdateGroupWorkflow
|
||||||
|
|
||||||
|
|
||||||
|
class DetailView(project_views.DetailView):
|
||||||
|
tab_group_class = admin_tabs.GroupsDetailTabs
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(DetailView, self).get_context_data(**kwargs)
|
context = super(DetailView, self).get_context_data(**kwargs)
|
||||||
table = volume_group_tables.GroupsTable(self.request)
|
table = admin_tables.GroupsTable(self.request)
|
||||||
context["actions"] = table.render_row_actions(context["group"])
|
context["actions"] = table.render_row_actions(context["group"])
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Copyright 2019 NEC Corporation
|
||||||
|
#
|
||||||
|
# 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 openstack_dashboard.dashboards.project.volume_groups \
|
||||||
|
import workflows as project_workflows
|
||||||
|
|
||||||
|
INDEX_URL = "horizon:admin:volume_groups:index"
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateGroupWorkflow(project_workflows.UpdateGroupWorkflow):
|
||||||
|
success_url = INDEX_URL
|
||||||
@@ -58,6 +58,8 @@ class UpdateForm(forms.SelfHandlingForm):
|
|||||||
|
|
||||||
|
|
||||||
class RemoveVolsForm(forms.SelfHandlingForm):
|
class RemoveVolsForm(forms.SelfHandlingForm):
|
||||||
|
failure_url = 'horizon:project:volume_groups:index'
|
||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
group_id = self.initial['group_id']
|
group_id = self.initial['group_id']
|
||||||
name = self.initial['name']
|
name = self.initial['name']
|
||||||
@@ -79,7 +81,7 @@ class RemoveVolsForm(forms.SelfHandlingForm):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
redirect = reverse("horizon:project:volume_groups:index")
|
redirect = reverse(self.failure_url)
|
||||||
exceptions.handle(request,
|
exceptions.handle(request,
|
||||||
_('Errors occurred in removing volumes '
|
_('Errors occurred in removing volumes '
|
||||||
'from group.'),
|
'from group.'),
|
||||||
@@ -89,6 +91,7 @@ class RemoveVolsForm(forms.SelfHandlingForm):
|
|||||||
class DeleteForm(forms.SelfHandlingForm):
|
class DeleteForm(forms.SelfHandlingForm):
|
||||||
delete_volumes = forms.BooleanField(label=_("Delete Volumes"),
|
delete_volumes = forms.BooleanField(label=_("Delete Volumes"),
|
||||||
required=False)
|
required=False)
|
||||||
|
failure_url = 'horizon:project:volume_groups:index'
|
||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
group_id = self.initial['group_id']
|
group_id = self.initial['group_id']
|
||||||
@@ -103,7 +106,7 @@ class DeleteForm(forms.SelfHandlingForm):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
redirect = reverse("horizon:project:volume_groups:index")
|
redirect = reverse(self.failure_url)
|
||||||
exceptions.handle(request, _('Errors occurred in deleting group.'),
|
exceptions.handle(request, _('Errors occurred in deleting group.'),
|
||||||
redirect=redirect)
|
redirect=redirect)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
[:blueprint:`cinder-generic-volume-groups`]
|
||||||
|
Cinder generic groups is now supported for admin panel.
|
||||||
|
Admin is now able to view all groups for differenet users.
|
||||||
Reference in New Issue
Block a user