diff --git a/cinder/group/api.py b/cinder/group/api.py index 79d473be9..4320698a5 100644 --- a/cinder/group/api.py +++ b/cinder/group/api.py @@ -517,6 +517,12 @@ class API(base.Base): "but current status is: %s") % group.status raise exception.InvalidGroup(reason=msg) + # NOTE(tommylikehu): Admin context is required to load group snapshots. + with group.obj_as_admin(): + if group.group_snapshots: + raise exception.InvalidGroup( + reason=_("Group has existing snapshots.")) + volumes = self.db.volume_get_all_by_generic_group(context.elevated(), group.id) if volumes and not delete_volumes: diff --git a/cinder/tests/unit/api/v3/test_groups.py b/cinder/tests/unit/api/v3/test_groups.py index 036d2e692..2e98c2408 100644 --- a/cinder/tests/unit/api/v3/test_groups.py +++ b/cinder/tests/unit/api/v3/test_groups.py @@ -654,6 +654,29 @@ class GroupsAPITestCase(test.TestCase): self.controller.delete_group, req, self.group1.id, body) + def test_delete_group_with_group_snapshot(self): + self.group1.status = fields.GroupStatus.AVAILABLE + self.group1.save() + g_snapshot = utils.create_group_snapshot(self.ctxt, self.group1.id) + + req = fakes.HTTPRequest.blank('/v3/%s/groups/%s/action' % + (fake.PROJECT_ID, self.group1.id), + version=GROUP_MICRO_VERSION) + body = {"delete": {"delete-volumes": True}} + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.delete_group, + req, self.group1.id, body) + + g_snapshot.destroy() + + res_dict = self.controller.delete_group( + req, self.group1.id, body) + + group = objects.Group.get_by_id( + self.ctxt, self.group1.id) + self.assertEqual(http_client.ACCEPTED, res_dict.status_int) + self.assertEqual(fields.GroupStatus.DELETING, group.status) + def test_delete_group_delete_volumes(self): self.group1.status = fields.GroupStatus.AVAILABLE self.group1.save() diff --git a/cinder/tests/unit/group/test_groups_api.py b/cinder/tests/unit/group/test_groups_api.py index ab6155822..07b13e050 100644 --- a/cinder/tests/unit/group/test_groups_api.py +++ b/cinder/tests/unit/group/test_groups_api.py @@ -114,6 +114,7 @@ class GroupAPITestCase(test.TestCase): ret_group.host = "test_host@fakedrv#fakepool" ret_group.status = fields.GroupStatus.AVAILABLE ret_group.assert_not_frozen = mock.Mock(return_value=True) + ret_group.group_snapshots = [] self.group_api.delete(self.ctxt, ret_group, delete_volumes=True) mock_volume_get_all.assert_called_once_with(mock.ANY, ret_group.id) mock_volumes_update.assert_called_once_with(self.ctxt, []) diff --git a/releasenotes/notes/bug-1705375-prohibit-group-deletion-if-groupsnapshot-exists.yaml b/releasenotes/notes/bug-1705375-prohibit-group-deletion-if-groupsnapshot-exists.yaml new file mode 100644 index 000000000..468a54579 --- /dev/null +++ b/releasenotes/notes/bug-1705375-prohibit-group-deletion-if-groupsnapshot-exists.yaml @@ -0,0 +1,3 @@ +--- +fixes: + - Prohibit the deletion of group if group snapshot exists.