Пример #1
0
 def delete_group_snapshot(self, context, group_snapshot, snapshots):
     """Deletes a group_snapshot."""
     # let generic volume group support handle non-cgsnapshots
     if not vol_utils.is_group_a_cg_snapshot_type(group_snapshot):
         raise NotImplementedError()
     cgsnap_name = self._make_group_snapshot_name(group_snapshot)
     infinidat_cgsnap = self._system.cons_groups.safe_get(name=cgsnap_name)
     if infinidat_cgsnap is not None:
         if not infinidat_cgsnap.is_snapgroup():
             msg = _('Group "%s" is not a snapshot group') % cgsnap_name
             LOG.error(msg)
             raise exception.InvalidGroupSnapshot(message=msg)
         infinidat_cgsnap.safe_delete()
     for snapshot in snapshots:
         self.delete_snapshot(snapshot)
     return None, None
Пример #2
0
class GroupSnapshotsAPITestCase(test.TestCase):
    """Test Case for group_snapshots API."""
    def setUp(self):
        super(GroupSnapshotsAPITestCase, self).setUp()
        self.controller = v3_group_snapshots.GroupSnapshotsController()
        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)
        self.group = utils.create_group(self.context,
                                        group_type_id=fake.GROUP_TYPE_ID,
                                        volume_type_ids=[fake.VOLUME_TYPE_ID])
        self.volume = utils.create_volume(self.context,
                                          group_id=self.group.id,
                                          volume_type_id=fake.VOLUME_TYPE_ID)
        self.g_snapshots_array = [
            utils.create_group_snapshot(self.context,
                                        group_id=self.group.id,
                                        group_type_id=self.group.group_type_id)
            for _ in range(3)
        ]
        self.addCleanup(self._cleanup)

    def _cleanup(self):
        for snapshot in self.g_snapshots_array:
            snapshot.destroy()
        self.volume.destroy()
        self.group.destroy()

    def test_show_group_snapshot(self):
        group_snapshot = utils.create_group_snapshot(self.context,
                                                     group_id=self.group.id)
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=mv.GROUP_SNAPSHOTS)
        res_dict = self.controller.show(req, group_snapshot.id)

        self.assertEqual(1, len(res_dict))
        self.assertEqual('this is a test group snapshot',
                         res_dict['group_snapshot']['description'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshot']['name'])
        self.assertEqual(fields.GroupSnapshotStatus.CREATING,
                         res_dict['group_snapshot']['status'])

        group_snapshot.destroy()

    @ddt.data(True, False)
    def test_list_group_snapshots_with_limit(self, is_detail):

        url = '/v3/%s/group_snapshots?limit=1' % fake.PROJECT_ID
        if is_detail:
            url = '/v3/%s/group_snapshots/detail?limit=1' % fake.PROJECT_ID
        req = fakes.HTTPRequest.blank(url,
                                      version=mv.GROUP_SNAPSHOT_PAGINATION)
        if is_detail:
            res_dict = self.controller.detail(req)
        else:
            res_dict = self.controller.index(req)

        self.assertEqual(2, len(res_dict))
        self.assertEqual(1, len(res_dict['group_snapshots']))
        self.assertEqual(self.g_snapshots_array[2].id,
                         res_dict['group_snapshots'][0]['id'])
        next_link = ('http://localhost/v3/%s/group_snapshots?limit='
                     '1&marker=%s' %
                     (fake.PROJECT_ID, res_dict['group_snapshots'][0]['id']))
        self.assertEqual(next_link,
                         res_dict['group_snapshot_links'][0]['href'])
        if is_detail:
            self.assertIn('description', res_dict['group_snapshots'][0].keys())
        else:
            self.assertNotIn('description',
                             res_dict['group_snapshots'][0].keys())

    @ddt.data(True, False)
    def test_list_group_snapshot_with_offset(self, is_detail):
        url = '/v3/%s/group_snapshots?offset=1' % fake.PROJECT_ID
        if is_detail:
            url = '/v3/%s/group_snapshots/detail?offset=1' % fake.PROJECT_ID
        req = fakes.HTTPRequest.blank(url,
                                      version=mv.GROUP_SNAPSHOT_PAGINATION)
        if is_detail:
            res_dict = self.controller.detail(req)
        else:
            res_dict = self.controller.index(req)
        self.assertEqual(1, len(res_dict))
        self.assertEqual(2, len(res_dict['group_snapshots']))
        self.assertEqual(self.g_snapshots_array[1].id,
                         res_dict['group_snapshots'][0]['id'])
        self.assertEqual(self.g_snapshots_array[0].id,
                         res_dict['group_snapshots'][1]['id'])
        if is_detail:
            self.assertIn('description', res_dict['group_snapshots'][0].keys())
        else:
            self.assertNotIn('description',
                             res_dict['group_snapshots'][0].keys())

    @ddt.data(True, False)
    def test_list_group_snapshot_with_offset_out_of_range(self, is_detail):
        url = ('/v3/%s/group_snapshots?offset=234523423455454' %
               fake.PROJECT_ID)
        if is_detail:
            url = ('/v3/%s/group_snapshots/detail?offset=234523423455454' %
                   fake.PROJECT_ID)
        req = fakes.HTTPRequest.blank(url,
                                      version=mv.GROUP_SNAPSHOT_PAGINATION)
        if is_detail:
            self.assertRaises(webob.exc.HTTPBadRequest, self.controller.detail,
                              req)
        else:
            self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index,
                              req)

    @ddt.data(False, True)
    def test_list_group_snapshot_with_limit_and_offset(self, is_detail):
        group_snapshot = utils.create_group_snapshot(
            self.context,
            group_id=self.group.id,
            group_type_id=self.group.group_type_id)
        url = '/v3/%s/group_snapshots?limit=2&offset=1' % fake.PROJECT_ID
        if is_detail:
            url = ('/v3/%s/group_snapshots/detail?limit=2&offset=1' %
                   fake.PROJECT_ID)
        req = fakes.HTTPRequest.blank(url,
                                      version=mv.GROUP_SNAPSHOT_PAGINATION)
        if is_detail:
            res_dict = self.controller.detail(req)
        else:
            res_dict = self.controller.index(req)

        self.assertEqual(2, len(res_dict))
        self.assertEqual(2, len(res_dict['group_snapshots']))
        self.assertEqual(self.g_snapshots_array[2].id,
                         res_dict['group_snapshots'][0]['id'])
        self.assertEqual(self.g_snapshots_array[1].id,
                         res_dict['group_snapshots'][1]['id'])
        self.assertIsNotNone(res_dict['group_snapshot_links'][0]['href'])
        if is_detail:
            self.assertIn('description', res_dict['group_snapshots'][0].keys())
        else:
            self.assertNotIn('description',
                             res_dict['group_snapshots'][0].keys())
        group_snapshot.destroy()

    @ddt.data(mv.get_prior_version(mv.RESOURCE_FILTER), mv.RESOURCE_FILTER,
              mv.LIKE_FILTER)
    @mock.patch('cinder.api.common.reject_invalid_filters')
    def test_group_snapshot_list_with_general_filter(self, version,
                                                     mock_update):
        url = '/v3/%s/group_snapshots' % fake.PROJECT_ID
        req = fakes.HTTPRequest.blank(url,
                                      version=version,
                                      use_admin_context=False)
        self.controller.index(req)

        if version != mv.get_prior_version(mv.RESOURCE_FILTER):
            support_like = True if version == mv.LIKE_FILTER else False
            mock_update.assert_called_once_with(req.environ['cinder.context'],
                                                mock.ANY, 'group_snapshot',
                                                support_like)

    @ddt.data(False, True)
    def test_list_group_snapshot_with_filter(self, is_detail):
        url = ('/v3/%s/group_snapshots?'
               'all_tenants=True&id=%s') % (fake.PROJECT_ID,
                                            self.g_snapshots_array[0].id)
        if is_detail:
            url = ('/v3/%s/group_snapshots/detail?'
                   'all_tenants=True&id=%s') % (fake.PROJECT_ID,
                                                self.g_snapshots_array[0].id)
        req = fakes.HTTPRequest.blank(url,
                                      version=mv.GROUP_SNAPSHOT_PAGINATION,
                                      use_admin_context=True)
        if is_detail:
            res_dict = self.controller.detail(req)
        else:
            res_dict = self.controller.index(req)

        self.assertEqual(1, len(res_dict))
        self.assertEqual(1, len(res_dict['group_snapshots']))
        self.assertEqual(self.g_snapshots_array[0].id,
                         res_dict['group_snapshots'][0]['id'])
        if is_detail:
            self.assertIn('description', res_dict['group_snapshots'][0].keys())
        else:
            self.assertNotIn('description',
                             res_dict['group_snapshots'][0].keys())

    @ddt.data(
        {
            'is_detail': True,
            'version': mv.GROUP_SNAPSHOTS
        },
        {
            'is_detail': False,
            'version': mv.GROUP_SNAPSHOTS
        },
        {
            'is_detail': True,
            'version': mv.POOL_FILTER
        },
        {
            'is_detail': False,
            'version': mv.POOL_FILTER
        },
    )
    @ddt.unpack
    def test_list_group_snapshot_with_filter_previous_version(
            self, is_detail, version):
        url = ('/v3/%s/group_snapshots?'
               'all_tenants=True&id=%s') % (fake.PROJECT_ID,
                                            self.g_snapshots_array[0].id)
        if is_detail:
            url = ('/v3/%s/group_snapshots/detail?'
                   'all_tenants=True&id=%s') % (fake.PROJECT_ID,
                                                self.g_snapshots_array[0].id)
        req = fakes.HTTPRequest.blank(url,
                                      version=version,
                                      use_admin_context=True)

        if is_detail:
            res_dict = self.controller.detail(req)
        else:
            res_dict = self.controller.index(req)

        self.assertEqual(1, len(res_dict))
        self.assertEqual(3, len(res_dict['group_snapshots']))

    @ddt.data(False, True)
    def test_list_group_snapshot_with_sort(self, is_detail):
        url = '/v3/%s/group_snapshots?sort=id:asc' % fake.PROJECT_ID
        if is_detail:
            url = ('/v3/%s/group_snapshots/detail?sort=id:asc' %
                   fake.PROJECT_ID)
        req = fakes.HTTPRequest.blank(url,
                                      version=mv.GROUP_SNAPSHOT_PAGINATION)
        expect_result = [snapshot.id for snapshot in self.g_snapshots_array]
        expect_result.sort()
        if is_detail:
            res_dict = self.controller.detail(req)
        else:
            res_dict = self.controller.index(req)
        self.assertEqual(1, len(res_dict))
        self.assertEqual(3, len(res_dict['group_snapshots']))
        self.assertEqual(expect_result[0],
                         res_dict['group_snapshots'][0]['id'])
        self.assertEqual(expect_result[1],
                         res_dict['group_snapshots'][1]['id'])
        self.assertEqual(expect_result[2],
                         res_dict['group_snapshots'][2]['id'])
        if is_detail:
            self.assertIn('description', res_dict['group_snapshots'][0].keys())
        else:
            self.assertNotIn('description',
                             res_dict['group_snapshots'][0].keys())

    def test_show_group_snapshot_with_group_snapshot_not_found(self):
        req = fakes.HTTPRequest.blank(
            '/v3/%s/group_snapshots/%s' %
            (fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID),
            version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(exception.GroupSnapshotNotFound,
                          self.controller.show, req, fake.WILL_NOT_BE_FOUND_ID)

    @ddt.data(True, False)
    def test_list_group_snapshots_json(self, is_detail):
        if is_detail:
            request_url = '/v3/%s/group_snapshots/detail'
        else:
            request_url = '/v3/%s/group_snapshots'
        req = fakes.HTTPRequest.blank(request_url % fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)
        if is_detail:
            res_dict = self.controller.detail(req)
        else:
            res_dict = self.controller.index(req)

        self.assertEqual(1, len(res_dict))
        self.assertEqual(3, len(res_dict['group_snapshots']))
        for index, snapshot in enumerate(self.g_snapshots_array):
            self.assertEqual(snapshot.id,
                             res_dict['group_snapshots'][2 - index]['id'])
            self.assertIsNotNone(res_dict['group_snapshots'][2 -
                                                             index]['name'])
            if is_detail:
                self.assertIn('description',
                              res_dict['group_snapshots'][2 - index].keys())
            else:
                self.assertNotIn('description',
                                 res_dict['group_snapshots'][2 - index].keys())

    @mock.patch('cinder.db.volume_type_get')
    @mock.patch('cinder.quota.VolumeTypeQuotaEngine.reserve')
    def test_create_group_snapshot_json(self, mock_quota, mock_vol_type):
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": self.group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)
        res_dict = self.controller.create(req, body=body)

        self.assertEqual(1, len(res_dict))
        self.assertIn('id', res_dict['group_snapshot'])
        group_snapshot = objects.GroupSnapshot.get_by_id(
            context.get_admin_context(), res_dict['group_snapshot']['id'])
        group_snapshot.destroy()

    @mock.patch('cinder.db.volume_type_get')
    def test_create_group_snapshot_when_volume_in_error_status(
            self, mock_vol_type):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            status='error',
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(webob.exc.HTTPBadRequest,
                          self.controller.create,
                          req,
                          body=body)

        group.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_create_group_snapshot_with_no_body(self):
        # omit body from the request
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(exception.ValidationError,
                          self.controller.create,
                          req,
                          body=None)

    def test_create_group_snapshot_with_empty_body(self):
        # empty body in the request
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)
        body = {"group_snapshot": {}}
        self.assertRaises(exception.ValidationError,
                          self.controller.create,
                          req,
                          body=body)

    @mock.patch.object(group_api.API,
                       'create_group_snapshot',
                       side_effect=exception.InvalidGroupSnapshot(
                           reason='Invalid group snapshot'))
    def test_create_with_invalid_group_snapshot(self, mock_create_group_snap):
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": self.group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(webob.exc.HTTPBadRequest,
                          self.controller.create,
                          req,
                          body=body)

    @mock.patch.object(group_api.API,
                       'create_group_snapshot',
                       side_effect=exception.GroupSnapshotNotFound(
                           group_snapshot_id='invalid_id'))
    def test_create_with_group_snapshot_not_found(self, mock_create_grp_snap):
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": self.group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(exception.GroupSnapshotNotFound,
                          self.controller.create,
                          req,
                          body=body)

    def test_create_group_snapshot_from_empty_group(self):
        empty_group = utils.create_group(self.context,
                                         group_type_id=fake.GROUP_TYPE_ID,
                                         volume_type_ids=[fake.VOLUME_TYPE_ID])
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": empty_group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=mv.GROUP_SNAPSHOTS)

        self.assertRaises(webob.exc.HTTPBadRequest,
                          self.controller.create,
                          req,
                          body=body)
        empty_group.destroy()

    def test_delete_group_snapshot_available(self):
        group_snapshot = utils.create_group_snapshot(
            self.context,
            group_id=self.group.id,
            status=fields.GroupSnapshotStatus.AVAILABLE)
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=mv.GROUP_SNAPSHOTS)
        res_dict = self.controller.delete(req, group_snapshot.id)

        group_snapshot = objects.GroupSnapshot.get_by_id(
            self.context, group_snapshot.id)
        self.assertEqual(http_client.ACCEPTED, res_dict.status_int)
        self.assertEqual(fields.GroupSnapshotStatus.DELETING,
                         group_snapshot.status)

        group_snapshot.destroy()

    def test_delete_group_snapshot_available_used_as_source(self):
        group_snapshot = utils.create_group_snapshot(
            self.context,
            group_id=self.group.id,
            status=fields.GroupSnapshotStatus.AVAILABLE)

        group2 = utils.create_group(
            self.context,
            status='creating',
            group_snapshot_id=group_snapshot.id,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
                          req, group_snapshot.id)

        group_snapshot.destroy()
        group2.destroy()

    def test_delete_group_snapshot_with_group_snapshot_NotFound(self):
        req = fakes.HTTPRequest.blank(
            '/v3/%s/group_snapshots/%s' %
            (fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID),
            version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(exception.GroupSnapshotNotFound,
                          self.controller.delete, req,
                          fake.WILL_NOT_BE_FOUND_ID)

    def test_delete_group_snapshot_with_invalid_group_snapshot(self):
        group_snapshot = utils.create_group_snapshot(self.context,
                                                     group_id=self.group.id,
                                                     status='invalid')
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=mv.GROUP_SNAPSHOTS)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
                          req, group_snapshot.id)

        group_snapshot.destroy()

    @ddt.data(
        (mv.GROUP_TYPE, 'fake_snapshot_001',
         fields.GroupSnapshotStatus.AVAILABLE,
         exception.VersionNotFoundForAPIMethod),
        (mv.get_prior_version(mv.GROUP_SNAPSHOT_RESET_STATUS),
         'fake_snapshot_001', fields.GroupSnapshotStatus.AVAILABLE,
         exception.VersionNotFoundForAPIMethod),
        (mv.GROUP_SNAPSHOT_RESET_STATUS, 'fake_snapshot_001',
         fields.GroupSnapshotStatus.AVAILABLE, exception.GroupSnapshotNotFound)
    )
    @ddt.unpack
    def test_reset_group_snapshot_status_illegal(self, version,
                                                 group_snapshot_id, status,
                                                 exceptions):
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s/action' %
                                      (fake.PROJECT_ID, group_snapshot_id),
                                      version=version)
        body = {"reset_status": {"status": status}}
        self.assertRaises(exceptions,
                          self.controller.reset_status,
                          req,
                          group_snapshot_id,
                          body=body)

    def test_reset_group_snapshot_status_invalid_status(self):
        group_snapshot = utils.create_group_snapshot(
            self.context,
            group_id=self.group.id,
            status=fields.GroupSnapshotStatus.CREATING)
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s/action' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=mv.GROUP_SNAPSHOT_RESET_STATUS)
        body = {"reset_status": {"status": "invalid_test_status"}}
        self.assertRaises(exception.InvalidGroupSnapshotStatus,
                          self.controller.reset_status,
                          req,
                          group_snapshot.id,
                          body=body)
        group_snapshot.destroy()

    def test_reset_group_snapshot_status(self):
        group_snapshot = utils.create_group_snapshot(
            self.context,
            group_id=self.group.id,
            status=fields.GroupSnapshotStatus.CREATING)
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s/action' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=mv.GROUP_SNAPSHOT_RESET_STATUS)
        body = {
            "reset_status": {
                "status": fields.GroupSnapshotStatus.AVAILABLE
            }
        }
        response = self.controller.reset_status(req,
                                                group_snapshot.id,
                                                body=body)

        g_snapshot = objects.GroupSnapshot.get_by_id(self.context,
                                                     group_snapshot.id)
        self.assertEqual(http_client.ACCEPTED, response.status_int)
        self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE,
                         g_snapshot.status)
        group_snapshot.destroy()
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('/v2/%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(http_client.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('/v2/%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(http_client.NOT_FOUND, res.status_int)
        self.assertEqual(http_client.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('/v2/%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(http_client.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('/v2/%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(http_client.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('/v2/%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(http_client.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('/v2/%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(http_client.BAD_REQUEST, res.status_int)
        self.assertEqual(http_client.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('/v2/%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(http_client.BAD_REQUEST, res.status_int)
        self.assertEqual(http_client.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('/v2/%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(http_client.BAD_REQUEST, res.status_int)
        self.assertEqual(http_client.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('/v2/%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(http_client.NOT_FOUND, res.status_int)
        self.assertEqual(http_client.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('/v2/%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(http_client.BAD_REQUEST, res.status_int)
        self.assertEqual(http_client.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('/v2/%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(http_client.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('/v2/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(http_client.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('/v2/%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(http_client.NOT_FOUND, res.status_int)
        self.assertEqual(http_client.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('/v2/%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(http_client.BAD_REQUEST, res.status_int)
        self.assertEqual(http_client.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()
Пример #4
0
class GroupSnapshotsAPITestCase(test.TestCase):
    """Test Case for group_snapshots API."""
    def setUp(self):
        super(GroupSnapshotsAPITestCase, self).setUp()
        self.controller = v3_group_snapshots.GroupSnapshotsController()
        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_group_snapshot(self):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        group_snapshot = utils.create_group_snapshot(self.context,
                                                     group_id=group.id)
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=GROUP_MICRO_VERSION)
        res_dict = self.controller.show(req, group_snapshot.id)

        self.assertEqual(1, len(res_dict))
        self.assertEqual('this is a test group snapshot',
                         res_dict['group_snapshot']['description'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshot']['name'])
        self.assertEqual('creating', res_dict['group_snapshot']['status'])

        group_snapshot.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)
        group.destroy()

    def test_show_group_snapshot_with_group_snapshot_NotFound(self):
        req = fakes.HTTPRequest.blank(
            '/v3/%s/group_snapshots/%s' %
            (fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID),
            version=GROUP_MICRO_VERSION)
        self.assertRaises(exception.GroupSnapshotNotFound,
                          self.controller.show, req, fake.WILL_NOT_BE_FOUND_ID)

    def test_list_group_snapshots_json(self):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        group_snapshot1 = utils.create_group_snapshot(self.context,
                                                      group_id=group.id)
        group_snapshot2 = utils.create_group_snapshot(self.context,
                                                      group_id=group.id)
        group_snapshot3 = utils.create_group_snapshot(self.context,
                                                      group_id=group.id)

        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        res_dict = self.controller.index(req)

        self.assertEqual(1, len(res_dict))
        self.assertEqual(group_snapshot1.id,
                         res_dict['group_snapshots'][0]['id'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshots'][0]['name'])
        self.assertEqual(group_snapshot2.id,
                         res_dict['group_snapshots'][1]['id'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshots'][1]['name'])
        self.assertEqual(group_snapshot3.id,
                         res_dict['group_snapshots'][2]['id'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshots'][2]['name'])

        group_snapshot3.destroy()
        group_snapshot2.destroy()
        group_snapshot1.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)
        group.destroy()

    def test_list_group_snapshots_detail_json(self):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        group_snapshot1 = utils.create_group_snapshot(self.context,
                                                      group_id=group.id)
        group_snapshot2 = utils.create_group_snapshot(self.context,
                                                      group_id=group.id)
        group_snapshot3 = utils.create_group_snapshot(self.context,
                                                      group_id=group.id)

        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/detail' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        res_dict = self.controller.detail(req)

        self.assertEqual(1, len(res_dict))
        self.assertEqual(3, len(res_dict['group_snapshots']))
        self.assertEqual('this is a test group snapshot',
                         res_dict['group_snapshots'][0]['description'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshots'][0]['name'])
        self.assertEqual(group_snapshot1.id,
                         res_dict['group_snapshots'][0]['id'])
        self.assertEqual('creating', res_dict['group_snapshots'][0]['status'])

        self.assertEqual('this is a test group snapshot',
                         res_dict['group_snapshots'][1]['description'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshots'][1]['name'])
        self.assertEqual(group_snapshot2.id,
                         res_dict['group_snapshots'][1]['id'])
        self.assertEqual('creating', res_dict['group_snapshots'][1]['status'])

        self.assertEqual('this is a test group snapshot',
                         res_dict['group_snapshots'][2]['description'])
        self.assertEqual('test_group_snapshot',
                         res_dict['group_snapshots'][2]['name'])
        self.assertEqual(group_snapshot3.id,
                         res_dict['group_snapshots'][2]['id'])
        self.assertEqual('creating', res_dict['group_snapshots'][2]['status'])

        group_snapshot3.destroy()
        group_snapshot2.destroy()
        group_snapshot1.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)
        group.destroy()

    @mock.patch(
        'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
    @mock.patch('cinder.db.volume_type_get')
    @mock.patch('cinder.quota.VolumeTypeQuotaEngine.reserve')
    def test_create_group_snapshot_json(self, mock_quota, mock_vol_type,
                                        mock_validate):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        res_dict = self.controller.create(req, body)

        self.assertEqual(1, len(res_dict))
        self.assertIn('id', res_dict['group_snapshot'])
        self.assertTrue(mock_validate.called)

        group.destroy()
        group_snapshot = objects.GroupSnapshot.get_by_id(
            context.get_admin_context(), res_dict['group_snapshot']['id'])
        db.volume_destroy(context.get_admin_context(), volume_id)
        group_snapshot.destroy()

    @mock.patch(
        'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
    @mock.patch('cinder.db.volume_type_get')
    def test_create_group_snapshot_when_volume_in_error_status(
            self, mock_vol_type, mock_validate):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            status='error',
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
                          req, body)
        self.assertTrue(mock_validate.called)

        group.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_create_group_snapshot_with_no_body(self):
        # omit body from the request
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
                          req, None)

    @mock.patch.object(group_api.API,
                       'create_group_snapshot',
                       side_effect=exception.InvalidGroupSnapshot(
                           reason='Invalid group snapshot'))
    def test_create_with_invalid_group_snapshot(self, mock_create_group_snap):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            status='error',
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
                          req, body)

        group.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)

    @mock.patch.object(group_api.API,
                       'create_group_snapshot',
                       side_effect=exception.GroupSnapshotNotFound(
                           group_snapshot_id='invalid_id'))
    def test_create_with_group_snapshot_not_found(self, mock_create_grp_snap):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            status='error',
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        self.assertRaises(exception.GroupSnapshotNotFound,
                          self.controller.create, req, body)

        group.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_create_group_snapshot_from_empty_group(self):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        body = {
            "group_snapshot": {
                "name": "group_snapshot1",
                "description": "Group Snapshot 1",
                "group_id": group.id
            }
        }
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots' %
                                      fake.PROJECT_ID,
                                      version=GROUP_MICRO_VERSION)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
                          req, body)

        group.destroy()

    def test_delete_group_snapshot_available(self):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        group_snapshot = utils.create_group_snapshot(self.context,
                                                     group_id=group.id,
                                                     status='available')
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=GROUP_MICRO_VERSION)
        res_dict = self.controller.delete(req, group_snapshot.id)

        group_snapshot = objects.GroupSnapshot.get_by_id(
            self.context, group_snapshot.id)
        self.assertEqual(202, res_dict.status_int)
        self.assertEqual('deleting', group_snapshot.status)

        group_snapshot.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)
        group.destroy()

    def test_delete_group_snapshot_available_used_as_source(self):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        group_snapshot = utils.create_group_snapshot(self.context,
                                                     group_id=group.id,
                                                     status='available')

        group2 = utils.create_group(
            self.context,
            status='creating',
            group_snapshot_id=group_snapshot.id,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=GROUP_MICRO_VERSION)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
                          req, group_snapshot.id)

        group_snapshot.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)
        group.destroy()
        group2.destroy()

    def test_delete_group_snapshot_with_group_snapshot_NotFound(self):
        req = fakes.HTTPRequest.blank(
            '/v3/%s/group_snapshots/%s' %
            (fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID),
            version=GROUP_MICRO_VERSION)
        self.assertRaises(exception.GroupSnapshotNotFound,
                          self.controller.delete, req,
                          fake.WILL_NOT_BE_FOUND_ID)

    def test_delete_group_snapshot_with_Invalid_group_snapshot(self):
        group = utils.create_group(
            self.context,
            group_type_id=fake.GROUP_TYPE_ID,
            volume_type_ids=[fake.VOLUME_TYPE_ID],
        )
        volume_id = utils.create_volume(
            self.context,
            group_id=group.id,
            volume_type_id=fake.VOLUME_TYPE_ID)['id']
        group_snapshot = utils.create_group_snapshot(self.context,
                                                     group_id=group.id,
                                                     status='invalid')
        req = fakes.HTTPRequest.blank('/v3/%s/group_snapshots/%s' %
                                      (fake.PROJECT_ID, group_snapshot.id),
                                      version=GROUP_MICRO_VERSION)
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.delete,
                          req, group_snapshot.id)

        group_snapshot.destroy()
        db.volume_destroy(context.get_admin_context(), volume_id)
        group.destroy()