
In this patch: - adjusted VersionsController to return only v3 - removed cinder.api.v2.router - adjustments to cinder.tests.unit.api.contrib to use /v3 only - moved cinder.api.v2.snapshot_metadata (and tests) to cinder.api.v3 - moved cinder.api.v2.types (and view, tests) to cinder.api.v3 - updated versions response in api-ref - removed unnecessary config option - updated various sample config files - removed experimental tempest-cinder-v2-api job - updated some docs - updated non-voting rally job config Some cinder.api.v2 modules are left because the v3 classes depend on them, but with the v2 router removed, these are unreachable via the /v2 path. Depends-on: https://review.opendev.org/c/openstack/rally-openstack/+/794891 (changes rally to use Block Storage API v3) Depends-on: https://review.opendev.org/c/openstack/requirements/+/794894 (corrects regression in upper-constraint on Sphinx) Change-Id: I2093d77db9beec7543c7524d2cd273e79dd5fd5d
561 lines
25 KiB
Python
561 lines
25 KiB
Python
# Copyright (C) 2012 - 2014 EMC Corporation.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
"""Tests for cgsnapshot code."""
|
|
|
|
from http import HTTPStatus
|
|
from unittest import mock
|
|
|
|
from oslo_serialization import jsonutils
|
|
import webob
|
|
|
|
from cinder import context
|
|
from cinder import db
|
|
from cinder import exception
|
|
from cinder.group import api as groupAPI
|
|
from cinder import objects
|
|
from cinder.tests.unit.api import fakes
|
|
from cinder.tests.unit import fake_constants as fake
|
|
from cinder.tests.unit import test
|
|
from cinder.tests.unit import utils
|
|
import cinder.volume
|
|
|
|
|
|
class CgsnapshotsAPITestCase(test.TestCase):
|
|
"""Test Case for cgsnapshots API."""
|
|
|
|
def setUp(self):
|
|
super(CgsnapshotsAPITestCase, self).setUp()
|
|
self.volume_api = cinder.volume.API()
|
|
self.context = context.get_admin_context()
|
|
self.context.project_id = fake.PROJECT_ID
|
|
self.context.user_id = fake.USER_ID
|
|
self.user_ctxt = context.RequestContext(
|
|
fake.USER_ID, fake.PROJECT_ID, auth_token=True)
|
|
|
|
def test_show_cgsnapshot(self):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
cgsnapshot = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,)
|
|
snapshot_id = utils.create_snapshot(
|
|
self.context,
|
|
volume_type_id=vol_type['id'],
|
|
volume_id=volume_id,
|
|
group_snapshot_id=cgsnapshot.id)['id']
|
|
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots/%s' % (
|
|
fake.PROJECT_ID, cgsnapshot.id))
|
|
req.method = 'GET'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.OK, res.status_int)
|
|
self.assertEqual('this is a test group snapshot',
|
|
res_dict['cgsnapshot']['description'])
|
|
|
|
self.assertEqual('test_group_snapshot',
|
|
res_dict['cgsnapshot']['name'])
|
|
self.assertEqual('creating', res_dict['cgsnapshot']['status'])
|
|
|
|
db.snapshot_destroy(context.get_admin_context(), snapshot_id)
|
|
cgsnapshot.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
def test_show_cgsnapshot_with_cgsnapshot_NotFound(self):
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots/%s' % (
|
|
fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID))
|
|
req.method = 'GET'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.NOT_FOUND, res.status_int)
|
|
self.assertEqual(HTTPStatus.NOT_FOUND,
|
|
res_dict['itemNotFound']['code'])
|
|
self.assertEqual('GroupSnapshot %s could not be found.' %
|
|
fake.WILL_NOT_BE_FOUND_ID,
|
|
res_dict['itemNotFound']['message'])
|
|
|
|
def test_list_cgsnapshots_json(self):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
cgsnapshot1 = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,)
|
|
cgsnapshot2 = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,)
|
|
cgsnapshot3 = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,)
|
|
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots' % fake.PROJECT_ID)
|
|
req.method = 'GET'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.OK, res.status_int)
|
|
self.assertEqual(cgsnapshot3.id,
|
|
res_dict['cgsnapshots'][0]['id'])
|
|
self.assertEqual('test_group_snapshot',
|
|
res_dict['cgsnapshots'][0]['name'])
|
|
self.assertEqual(cgsnapshot2.id,
|
|
res_dict['cgsnapshots'][1]['id'])
|
|
self.assertEqual('test_group_snapshot',
|
|
res_dict['cgsnapshots'][1]['name'])
|
|
self.assertEqual(cgsnapshot1.id,
|
|
res_dict['cgsnapshots'][2]['id'])
|
|
self.assertEqual('test_group_snapshot',
|
|
res_dict['cgsnapshots'][2]['name'])
|
|
|
|
cgsnapshot3.destroy()
|
|
cgsnapshot2.destroy()
|
|
cgsnapshot1.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
def test_list_cgsnapshots_detail_json(self):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
cgsnapshot1 = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,)
|
|
cgsnapshot2 = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,)
|
|
cgsnapshot3 = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,)
|
|
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots/detail' %
|
|
fake.PROJECT_ID)
|
|
req.method = 'GET'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
req.headers['Accept'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.OK, res.status_int)
|
|
self.assertEqual('this is a test group snapshot',
|
|
res_dict['cgsnapshots'][0]['description'])
|
|
self.assertEqual('test_group_snapshot',
|
|
res_dict['cgsnapshots'][0]['name'])
|
|
self.assertEqual(cgsnapshot3.id,
|
|
res_dict['cgsnapshots'][0]['id'])
|
|
self.assertEqual('creating',
|
|
res_dict['cgsnapshots'][0]['status'])
|
|
|
|
self.assertEqual('this is a test group snapshot',
|
|
res_dict['cgsnapshots'][1]['description'])
|
|
self.assertEqual('test_group_snapshot',
|
|
res_dict['cgsnapshots'][1]['name'])
|
|
self.assertEqual(cgsnapshot2.id,
|
|
res_dict['cgsnapshots'][1]['id'])
|
|
self.assertEqual('creating',
|
|
res_dict['cgsnapshots'][1]['status'])
|
|
|
|
self.assertEqual('this is a test group snapshot',
|
|
res_dict['cgsnapshots'][2]['description'])
|
|
self.assertEqual('test_group_snapshot',
|
|
res_dict['cgsnapshots'][2]['name'])
|
|
self.assertEqual(cgsnapshot1.id,
|
|
res_dict['cgsnapshots'][2]['id'])
|
|
self.assertEqual('creating',
|
|
res_dict['cgsnapshots'][2]['status'])
|
|
|
|
cgsnapshot3.destroy()
|
|
cgsnapshot2.destroy()
|
|
cgsnapshot1.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
@mock.patch(
|
|
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
|
|
def test_create_cgsnapshot_json(self, mock_validate):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
|
|
body = {"cgsnapshot": {"name": "cg1",
|
|
"description":
|
|
"CG Snapshot 1",
|
|
"consistencygroup_id": consistencygroup.id}}
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots' % fake.PROJECT_ID)
|
|
req.method = 'POST'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
req.body = jsonutils.dump_as_bytes(body)
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.ACCEPTED, res.status_int)
|
|
self.assertIn('id', res_dict['cgsnapshot'])
|
|
self.assertTrue(mock_validate.called)
|
|
|
|
cgsnapshot = objects.GroupSnapshot.get_by_id(
|
|
context.get_admin_context(), res_dict['cgsnapshot']['id'])
|
|
cgsnapshot.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
@mock.patch(
|
|
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
|
|
def test_create_cgsnapshot_when_volume_in_error_status(self,
|
|
mock_validate):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=consistencygroup.id,
|
|
status='error')['id']
|
|
|
|
body = {"cgsnapshot": {"name": "cg1",
|
|
"description":
|
|
"CG Snapshot 1",
|
|
"consistencygroup_id": consistencygroup.id}}
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots' % fake.PROJECT_ID)
|
|
req.method = 'POST'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
req.body = jsonutils.dump_as_bytes(body)
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST, res.status_int)
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST,
|
|
res_dict['badRequest']['code'])
|
|
self.assertEqual(
|
|
"Invalid volume: The snapshot cannot be created when the volume "
|
|
"is in error status.",
|
|
res_dict['badRequest']['message']
|
|
)
|
|
self.assertTrue(mock_validate.called)
|
|
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
def test_create_cgsnapshot_with_no_body(self):
|
|
# omit body from the request
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots' % fake.PROJECT_ID)
|
|
req.body = jsonutils.dump_as_bytes(None)
|
|
req.method = 'POST'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
req.headers['Accept'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST, res.status_int)
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST,
|
|
res_dict['badRequest']['code'])
|
|
self.assertEqual("Missing required element 'cgsnapshot' in "
|
|
"request body.",
|
|
res_dict['badRequest']['message'])
|
|
|
|
@mock.patch.object(groupAPI.API, 'create_group_snapshot',
|
|
side_effect=exception.InvalidGroupSnapshot(
|
|
reason='invalid group_snapshot'))
|
|
def test_create_with_invalid_cgsnapshot(self, mock_create_cgsnapshot):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=consistencygroup.id)['id']
|
|
|
|
body = {"cgsnapshot": {"name": "cg1",
|
|
"description":
|
|
"CG Snapshot 1",
|
|
"consistencygroup_id": consistencygroup.id}}
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots' % fake.PROJECT_ID)
|
|
req.body = jsonutils.dump_as_bytes(body)
|
|
req.method = 'POST'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST, res.status_int)
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST,
|
|
res_dict['badRequest']['code'])
|
|
self.assertEqual('Invalid GroupSnapshot: invalid group_snapshot',
|
|
res_dict['badRequest']['message'])
|
|
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
@mock.patch.object(groupAPI.API, 'create_group_snapshot',
|
|
side_effect=exception.GroupSnapshotNotFound(
|
|
group_snapshot_id='invalid_id'))
|
|
def test_create_with_cgsnapshot_not_found(self, mock_create_cgsnapshot):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=consistencygroup.id)['id']
|
|
|
|
body = {"cgsnapshot": {"name": "cg1",
|
|
"description":
|
|
"CG Snapshot 1",
|
|
"consistencygroup_id": consistencygroup.id}}
|
|
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots' % fake.PROJECT_ID)
|
|
req.method = 'POST'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
req.body = jsonutils.dump_as_bytes(body)
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.NOT_FOUND, res.status_int)
|
|
self.assertEqual(HTTPStatus.NOT_FOUND,
|
|
res_dict['itemNotFound']['code'])
|
|
self.assertEqual('GroupSnapshot invalid_id could not be found.',
|
|
res_dict['itemNotFound']['message'])
|
|
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
def test_create_cgsnapshot_from_empty_consistencygroup(self):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
|
|
body = {"cgsnapshot": {"name": "cg1",
|
|
"description":
|
|
"CG Snapshot 1",
|
|
"consistencygroup_id": consistencygroup.id}}
|
|
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots' % fake.PROJECT_ID)
|
|
req.method = 'POST'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
req.body = jsonutils.dump_as_bytes(body)
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST, res.status_int)
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST,
|
|
res_dict['badRequest']['code'])
|
|
self.assertIsNotNone(res_dict['badRequest']['message'])
|
|
|
|
# If failed to create cgsnapshot, its DB object should not be created
|
|
self.assertListEqual(
|
|
[],
|
|
list(objects.GroupSnapshotList.get_all(self.context)))
|
|
consistencygroup.destroy()
|
|
|
|
def test_delete_cgsnapshot_available(self):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
cgsnapshot = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
status='available')
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots/%s' %
|
|
(fake.PROJECT_ID, cgsnapshot.id))
|
|
req.method = 'DELETE'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
|
|
cgsnapshot = objects.GroupSnapshot.get_by_id(self.context,
|
|
cgsnapshot.id)
|
|
self.assertEqual(HTTPStatus.ACCEPTED, res.status_int)
|
|
self.assertEqual('deleting', cgsnapshot.status)
|
|
|
|
cgsnapshot.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
def test_delete_cgsnapshot_available_used_as_source(self):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
cgsnapshot = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
status='available')
|
|
|
|
cg2 = utils.create_consistencygroup(
|
|
self.context, status='creating',
|
|
group_snapshot_id=cgsnapshot.id,
|
|
group_type_id=fake.GROUP_TYPE_ID)
|
|
req = webob.Request.blank('/v3/fake/cgsnapshots/%s' %
|
|
cgsnapshot.id)
|
|
req.method = 'DELETE'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app())
|
|
|
|
cgsnapshot = objects.GroupSnapshot.get_by_id(self.context,
|
|
cgsnapshot.id)
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST, res.status_int)
|
|
self.assertEqual('available', cgsnapshot.status)
|
|
|
|
cgsnapshot.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
cg2.destroy()
|
|
|
|
def test_delete_cgsnapshot_with_cgsnapshot_NotFound(self):
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots/%s' %
|
|
(fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID))
|
|
req.method = 'DELETE'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.NOT_FOUND, res.status_int)
|
|
self.assertEqual(HTTPStatus.NOT_FOUND,
|
|
res_dict['itemNotFound']['code'])
|
|
self.assertEqual('GroupSnapshot %s could not be found.' %
|
|
fake.WILL_NOT_BE_FOUND_ID,
|
|
res_dict['itemNotFound']['message'])
|
|
|
|
def test_delete_cgsnapshot_with_invalid_cgsnapshot(self):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
cgsnapshot = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
status='invalid')
|
|
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots/%s' % (
|
|
fake.PROJECT_ID, cgsnapshot.id))
|
|
req.method = 'DELETE'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST, res.status_int)
|
|
self.assertEqual(HTTPStatus.BAD_REQUEST,
|
|
res_dict['badRequest']['code'])
|
|
self.assertIsNotNone(res_dict['badRequest']['message'])
|
|
|
|
cgsnapshot.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|
|
|
|
@mock.patch('cinder.group.API.delete_group_snapshot')
|
|
def test_delete_cgsnapshot_delete_policy_not_auth(self, mock_delete):
|
|
vol_type = utils.create_volume_type(context.get_admin_context(),
|
|
self, name='my_vol_type')
|
|
consistencygroup = utils.create_group(
|
|
self.context,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
volume_type_ids=[vol_type['id']])
|
|
volume_id = utils.create_volume(self.context,
|
|
volume_type_id=vol_type['id'],
|
|
group_id=
|
|
consistencygroup.id)['id']
|
|
cgsnapshot = utils.create_group_snapshot(
|
|
self.context, group_id=consistencygroup.id,
|
|
group_type_id=fake.GROUP_TYPE_ID,
|
|
status='available')
|
|
mock_delete.side_effect = exception.PolicyNotAuthorized(
|
|
message='PolicyNotAuthorized')
|
|
req = webob.Request.blank('/v3/%s/cgsnapshots/%s' %
|
|
(fake.PROJECT_ID, cgsnapshot.id))
|
|
req.method = 'DELETE'
|
|
req.headers['Content-Type'] = 'application/json'
|
|
res = req.get_response(fakes.wsgi_app(
|
|
fake_auth_context=self.user_ctxt))
|
|
res_dict = jsonutils.loads(res.body)
|
|
self.assertEqual('PolicyNotAuthorized',
|
|
res_dict['forbidden']['message'])
|
|
cgsnapshot.destroy()
|
|
db.volume_destroy(context.get_admin_context(), volume_id)
|
|
consistencygroup.destroy()
|