def setUp(self): super(VolumeMetaDataTest, self).setUp() self.volume_api = volume_api.API() self.mock_object(volume.api.API, 'get', get_volume) self.mock_object(db, 'volume_metadata_get', return_volume_metadata) self.mock_object(db, 'service_get_all', return_value=v2_fakes.fake_service_get_all_by_topic( None, None), autospec=True) self.mock_object(self.volume_api, 'update_volume_metadata') self.ext_mgr = extensions.ExtensionManager() self.ext_mgr.extensions = {} self.volume_controller = volumes.VolumeController(self.ext_mgr) self.controller = volume_metadata.Controller() self.req_id = fake.REQUEST_ID self.url = '/v2/%s/volumes/%s/metadata' % (fake.PROJECT_ID, self.req_id) vol = { "size": 100, "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "zone1:host1", "metadata": {}, "volume_type": self.vt['id'] } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v2/%s/volumes' % fake.PROJECT_ID) self.volume_controller.create(req, body=body)
def setUp(self): super(VolumeMetaDataTest, self).setUp() self.volume_api = volume_api.API() self.mock_object(volume.api.API, 'get', get_volume) self.mock_object(db, 'volume_metadata_get', return_volume_metadata) self.mock_object(db, 'service_get_all', return_value=v2_fakes.fake_service_get_all_by_topic( None, None), autospec=True) self.mock_object(self.volume_api, 'update_volume_metadata') self.ext_mgr = extensions.ExtensionManager() self.ext_mgr.extensions = {} self.volume_controller = volumes.VolumeController(self.ext_mgr) self.controller = volume_metadata.Controller() self.req_id = str(uuid.uuid4()) self.url = '/v2/%s/volumes/%s/metadata' % ( fake.PROJECT_ID, self.req_id) vol = {"size": 100, "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "zone1:host1", "metadata": {}} body = {"volume": vol} req = fakes.HTTPRequest.blank('/v2/volumes') self.volume_controller.create(req, body)
def setUp(self): super(VolumeMetaDataTest, self).setUp() self.volume_api = volume_api.API() self.mock_object(volume.api.API, 'get', get_volume) self.mock_object(db, 'volume_metadata_get', return_volume_metadata) self.patch('cinder.db.service_get_all', autospec=True, return_value=v2_fakes.fake_service_get_all_by_topic( None, None)) self.mock_object(self.volume_api, 'update_volume_metadata', fake_update_volume_metadata) self.ext_mgr = extensions.ExtensionManager() self.ext_mgr.extensions = {} self.patch('cinder.objects.Service.get_minimum_obj_version', return_value=obj_base.OBJ_VERSIONS.get_current()) def _get_minimum_rpc_version_mock(ctxt, binary): binary_map = { 'cinder-backup': backup_rpcapi.BackupAPI, 'cinder-scheduler': scheduler_rpcapi.SchedulerAPI, } return binary_map[binary].RPC_API_VERSION self.patch('cinder.objects.Service.get_minimum_rpc_version', side_effect=_get_minimum_rpc_version_mock) self.volume_controller = volumes.VolumeController(self.ext_mgr) self.controller = volume_metadata.Controller() self.req_id = str(uuid.uuid4()) self.url = '/v3/%s/volumes/%s/metadata' % (fake.PROJECT_ID, self.req_id) vol = { "size": 100, "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "zone1:host1", "metadata": {} } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v2/volumes') self.volume_controller.create(req, body)
def setUp(self): super(VolumeMetaDataTest, self).setUp() self.volume_api = volume_api.API() self.mock_object(volume.api.API, 'get', get_volume) self.mock_object(db, 'volume_metadata_get', return_volume_metadata) self.patch( 'cinder.db.service_get_all', autospec=True, return_value=v2_fakes.fake_service_get_all_by_topic(None, None)) self.mock_object(self.volume_api, 'update_volume_metadata', fake_update_volume_metadata) self.ext_mgr = extensions.ExtensionManager() self.ext_mgr.extensions = {} self.patch( 'cinder.objects.Service.get_minimum_obj_version', return_value=obj_base.OBJ_VERSIONS.get_current()) def _get_minimum_rpc_version_mock(ctxt, binary): binary_map = { 'cinder-backup': backup_rpcapi.BackupAPI, 'cinder-scheduler': scheduler_rpcapi.SchedulerAPI, } return binary_map[binary].RPC_API_VERSION self.patch('cinder.objects.Service.get_minimum_rpc_version', side_effect=_get_minimum_rpc_version_mock) self.volume_controller = volumes.VolumeController(self.ext_mgr) self.controller = volume_metadata.Controller() self.req_id = str(uuid.uuid4()) self.url = '/v3/%s/volumes/%s/metadata' % ( fake.PROJECT_ID, self.req_id) vol = {"size": 100, "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "zone1:host1", "metadata": {}} body = {"volume": vol} req = fakes.HTTPRequest.blank('/v2/volumes') self.volume_controller.create(req, body)
class VolumeApiTest(test.TestCase): def setUp(self): super(VolumeApiTest, self).setUp() self.ext_mgr = extensions.ExtensionManager() self.ext_mgr.extensions = {} fake_image.mock_image_service(self) self.controller = volumes.VolumeController(self.ext_mgr) self.maxDiff = None self.ctxt = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True) def test_volume_create(self): self.mock_object(volume_api.API, 'get', v2_fakes.fake_volume_get) self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_api_create) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) vol = { "size": 100, "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "zone1:host1" } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') res_dict = self.controller.create(req, body) expected = { 'volume': { 'status': 'fakestatus', 'display_description': 'Volume Test Desc', 'availability_zone': 'zone1:host1', 'display_name': 'Volume Test Name', 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'snapshot_id': None, 'source_volid': None, 'metadata': {}, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 100, 'encrypted': False } } self.assertEqual(expected, res_dict) @mock.patch.object(db, 'service_get_all', return_value=v2_fakes.fake_service_get_all_by_topic( None, None), autospec=True) def test_volume_create_with_type(self, mock_service_get): vol_type = db.volume_type_create( context.get_admin_context(), dict(name=CONF.default_volume_type, extra_specs={})) db_vol_type = db.volume_type_get(context.get_admin_context(), vol_type.id) vol = { "size": 100, "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "zone1:host1", "volume_type": "FakeTypeName" } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') # Raise 404 when type name isn't valid self.assertRaises(exc.VolumeTypeNotFoundByName, self.controller.create, req, body) # Use correct volume type name vol.update(dict(volume_type=CONF.default_volume_type)) body.update(dict(volume=vol)) res_dict = self.controller.create(req, body) self.assertIn('id', res_dict['volume']) self.assertEqual(1, len(res_dict)) self.assertEqual(db_vol_type['name'], res_dict['volume']['volume_type']) # Use correct volume type id vol.update(dict(volume_type=db_vol_type['id'])) body.update(dict(volume=vol)) res_dict = self.controller.create(req, body) self.assertIn('id', res_dict['volume']) self.assertEqual(1, len(res_dict)) self.assertEqual(db_vol_type['name'], res_dict['volume']['volume_type']) def test_volume_creation_fails_with_bad_size(self): vol = { "size": '', "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "zone1:host1" } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') self.assertRaises(exc.InvalidInput, self.controller.create, req, body) def test_volume_creation_fails_with_bad_availability_zone(self): vol = { "size": '1', "name": "Volume Test Name", "description": "Volume Test Desc", "availability_zone": "zonen:hostn" } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') self.assertRaises(exc.InvalidAvailabilityZone, self.controller.create, req, body) def test_volume_create_with_image_id(self): self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_api_create) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) self.ext_mgr.extensions = {'os-image-create': 'fake'} test_id = "c905cedb-7281-47e4-8a62-f26bc5fc4c77" vol = { "size": '1', "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "nova", "imageRef": test_id } expected = { 'volume': { 'status': 'fakestatus', 'display_description': 'Volume Test Desc', 'availability_zone': 'nova', 'display_name': 'Volume Test Name', 'encrypted': False, 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'image_id': test_id, 'snapshot_id': None, 'source_volid': None, 'metadata': {}, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 } } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') res_dict = self.controller.create(req, body) self.assertEqual(expected, res_dict) def test_volume_create_with_image_id_is_integer(self): self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create) self.ext_mgr.extensions = {'os-image-create': 'fake'} vol = { "size": '1', "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "cinder", "imageRef": 1234 } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, body) def test_volume_create_with_image_id_not_uuid_format(self): self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create) self.mock_object(fake_image._FakeImageService, "detail", v2_fakes.fake_image_service_detail) self.ext_mgr.extensions = {'os-image-create': 'fake'} vol = { "size": '1', "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "cinder", "imageRef": '12345' } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, body) def test_volume_create_with_image_id_with_empty_string(self): self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create) self.mock_object(fake_image._FakeImageService, "detail", v2_fakes.fake_image_service_detail) self.ext_mgr.extensions = {'os-image-create': 'fake'} vol = { "size": 1, "display_name": "Volume Test Name", "display_description": "Volume Test Desc", "availability_zone": "cinder", "imageRef": '' } body = {"volume": vol} req = fakes.HTTPRequest.blank('/v1/volumes') self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, body) def test_volume_update(self): self.mock_object(volume_api.API, 'get', v2_fakes.fake_volume_api_get) self.mock_object(volume_api.API, "update", v2_fakes.fake_volume_update) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) self.mock_object(db, 'volume_admin_metadata_get', return_value={ 'attached_mode': 'rw', 'readonly': 'False' }) updates = { "display_name": "Updated Test Name", } body = {"volume": updates} req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) self.assertEqual(0, len(self.notifier.notifications)) res_dict = self.controller.update(req, fake.VOLUME_ID, body) expected = { 'volume': { 'status': 'fakestatus', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'Updated Test Name', 'encrypted': False, 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'snapshot_id': None, 'source_volid': None, 'metadata': { 'attached_mode': 'rw', 'readonly': 'False' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 } } self.assertEqual(expected, res_dict) self.assertEqual(2, len(self.notifier.notifications)) def test_volume_update_metadata(self): self.mock_object(volume_api.API, 'get', v2_fakes.fake_volume_api_get) self.mock_object(volume_api.API, "update", v2_fakes.fake_volume_update) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) updates = {"metadata": {"qos_max_iops": '2000'}} body = {"volume": updates} req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) self.assertEqual(0, len(self.notifier.notifications)) res_dict = self.controller.update(req, fake.VOLUME_ID, body) expected = { 'volume': { 'status': 'fakestatus', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'snapshot_id': None, 'source_volid': None, 'metadata': { "qos_max_iops": '2000', "readonly": "False", "attached_mode": "rw" }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 } } self.assertEqual(expected, res_dict) self.assertEqual(2, len(self.notifier.notifications)) def test_volume_update_with_admin_metadata(self): self.mock_object(volume_api.API, "update", v2_fakes.fake_volume_update) volume = v2_fakes.create_fake_volume(fake.VOLUME_ID) del volume['name'] del volume['volume_type'] del volume['volume_type_id'] volume['metadata'] = {'key': 'value'} db.volume_create(context.get_admin_context(), volume) db.volume_admin_metadata_update(context.get_admin_context(), fake.VOLUME_ID, { "readonly": "True", "invisible_key": "invisible_value" }, False) values = { 'volume_id': fake.VOLUME_ID, } attachment = db.volume_attach(context.get_admin_context(), values) db.volume_attached(context.get_admin_context(), attachment['id'], fake.INSTANCE_ID, None, '/') updates = { "display_name": "Updated Test Name", } body = {"volume": updates} req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) self.assertEqual(0, len(self.notifier.notifications)) admin_ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True) req.environ['cinder.context'] = admin_ctx res_dict = self.controller.update(req, fake.VOLUME_ID, body) expected = { 'volume': { 'status': 'in-use', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'Updated Test Name', 'encrypted': False, 'attachments': [{ 'attachment_id': attachment['id'], 'id': fake.VOLUME_ID, 'volume_id': fake.VOLUME_ID, 'server_id': fake.INSTANCE_ID, 'host_name': None, 'device': '/' }], 'multiattach': 'false', 'bootable': 'false', 'volume_type': None, 'snapshot_id': None, 'source_volid': None, 'metadata': { 'key': 'value', 'readonly': 'True' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 } } self.assertEqual(expected, res_dict) self.assertEqual(2, len(self.notifier.notifications)) def test_update_empty_body(self): body = {} req = fakes.HTTPRequest.blank('/v1/volumes/1') self.assertRaises(webob.exc.HTTPUnprocessableEntity, self.controller.update, req, fake.VOLUME_ID, body) def test_update_invalid_body(self): body = {'display_name': 'missing top level volume key'} req = fakes.HTTPRequest.blank('/v1/volumes/1') self.assertRaises(webob.exc.HTTPUnprocessableEntity, self.controller.update, req, fake.VOLUME_ID, body) def test_update_not_found(self): self.mock_object(volume_api.API, "get", v2_fakes.fake_volume_get_notfound) updates = { "name": "Updated Test Name", } body = {"volume": updates} req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.WILL_NOT_BE_FOUND_ID) self.assertRaises(exc.VolumeNotFound, self.controller.update, req, fake.WILL_NOT_BE_FOUND_ID, body) def test_volume_list(self): self.mock_object(volume_api.API, 'get_all', v2_fakes.fake_volume_api_get_all_by_project) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) req = fakes.HTTPRequest.blank('/v1/volumes') res_dict = self.controller.index(req) expected = { 'volumes': [{ 'status': 'fakestatus', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'snapshot_id': None, 'source_volid': None, 'metadata': { 'attached_mode': 'rw', 'readonly': 'False' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 }] } self.assertEqual(expected, res_dict) # Finally test that we cached the returned volumes self.assertEqual(1, len(req.cached_resource())) def test_volume_list_with_admin_metadata(self): volume = v2_fakes.create_fake_volume(fake.VOLUME_ID) del volume['name'] del volume['volume_type'] del volume['volume_type_id'] volume['metadata'] = {'key': 'value'} db.volume_create(context.get_admin_context(), volume) db.volume_admin_metadata_update(context.get_admin_context(), fake.VOLUME_ID, { "readonly": "True", "invisible_key": "invisible_value" }, False) values = { 'volume_id': fake.VOLUME_ID, } attachment = db.volume_attach(context.get_admin_context(), values) db.volume_attached(context.get_admin_context(), attachment['id'], fake.INSTANCE_ID, None, '/') req = fakes.HTTPRequest.blank('/v1/volumes') admin_ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True) req.environ['cinder.context'] = admin_ctx res_dict = self.controller.index(req) expected = { 'volumes': [{ 'status': 'in-use', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [{ 'attachment_id': attachment['id'], 'device': '/', 'server_id': fake.INSTANCE_ID, 'host_name': None, 'id': fake.VOLUME_ID, 'volume_id': fake.VOLUME_ID }], 'multiattach': 'false', 'bootable': 'false', 'volume_type': None, 'snapshot_id': None, 'source_volid': None, 'metadata': { 'key': 'value', 'readonly': 'True' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 }] } self.assertEqual(expected, res_dict) def test_volume_list_detail(self): self.mock_object(volume_api.API, 'get_all', v2_fakes.fake_volume_api_get_all_by_project) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) req = fakes.HTTPRequest.blank('/v1/volumes/detail') res_dict = self.controller.detail(req) expected = { 'volumes': [{ 'status': 'fakestatus', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'snapshot_id': None, 'source_volid': None, 'metadata': { 'attached_mode': 'rw', 'readonly': 'False' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 }] } self.assertEqual(expected, res_dict) # Finally test that we cached the returned volumes self.assertEqual(1, len(req.cached_resource())) def test_volume_list_detail_with_admin_metadata(self): volume = v2_fakes.create_fake_volume(fake.VOLUME_ID) del volume['name'] del volume['volume_type'] del volume['volume_type_id'] volume['metadata'] = {'key': 'value'} db.volume_create(context.get_admin_context(), volume) db.volume_admin_metadata_update(context.get_admin_context(), fake.VOLUME_ID, { "readonly": "True", "invisible_key": "invisible_value" }, False) values = { 'volume_id': fake.VOLUME_ID, } attachment = db.volume_attach(context.get_admin_context(), values) db.volume_attached(context.get_admin_context(), attachment['id'], fake.INSTANCE_ID, None, '/') req = fakes.HTTPRequest.blank('/v1/volumes/detail') admin_ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True) req.environ['cinder.context'] = admin_ctx res_dict = self.controller.index(req) expected = { 'volumes': [{ 'status': 'in-use', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [{ 'attachment_id': attachment['id'], 'device': '/', 'server_id': fake.INSTANCE_ID, 'host_name': None, 'id': fake.VOLUME_ID, 'volume_id': fake.VOLUME_ID }], 'multiattach': 'false', 'bootable': 'false', 'volume_type': None, 'snapshot_id': None, 'source_volid': None, 'metadata': { 'key': 'value', 'readonly': 'True' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 }] } self.assertEqual(expected, res_dict) def test_volume_show(self): self.mock_object(volume_api.API, 'get', v2_fakes.fake_volume_api_get) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) res_dict = self.controller.show(req, fake.VOLUME_ID) expected = { 'volume': { 'status': 'fakestatus', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'snapshot_id': None, 'source_volid': None, 'metadata': { 'attached_mode': 'rw', 'readonly': 'False' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 } } self.assertEqual(expected, res_dict) # Finally test that we cached the returned volume self.assertIsNotNone(req.cached_resource_by_id(fake.VOLUME_ID)) def test_volume_show_no_attachments(self): def fake_volume_get(self, context, volume_id, **kwargs): vol = v2_fakes.create_fake_volume( volume_id, attach_status=fields.VolumeAttachStatus.DETACHED) return fake_volume.fake_volume_obj(context, **vol) def fake_volume_admin_metadata_get(context, volume_id, **kwargs): return v2_fakes.fake_volume_admin_metadata_get( context, volume_id, attach_status=fields.VolumeAttachStatus.DETACHED) self.mock_object(volume_api.API, 'get', fake_volume_get) self.mock_object(db, 'volume_admin_metadata_get', fake_volume_admin_metadata_get) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) res_dict = self.controller.show(req, fake.VOLUME_ID) expected = { 'volume': { 'status': 'fakestatus', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [], 'multiattach': 'false', 'bootable': 'false', 'volume_type': 'vol_type_name', 'snapshot_id': None, 'source_volid': None, 'metadata': { 'readonly': 'False' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 } } self.assertEqual(expected, res_dict) def test_volume_show_no_volume(self): self.mock_object(volume_api.API, "get", v2_fakes.fake_volume_get_notfound) req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.WILL_NOT_BE_FOUND_ID) self.assertRaises(exc.VolumeNotFound, self.controller.show, req, fake.WILL_NOT_BE_FOUND_ID) # Finally test that nothing was cached self.assertIsNone(req.cached_resource_by_id(fake.WILL_NOT_BE_FOUND_ID)) def _create_db_volumes(self, num_volumes): volumes = [ utils.create_volume(self.ctxt, display_name='vol%s' % i) for i in range(num_volumes) ] for vol in volumes: self.addCleanup(db.volume_destroy, self.ctxt, vol.id) volumes.reverse() return volumes def test_volume_detail_limit_offset(self): created_volumes = self._create_db_volumes(2) def volume_detail_limit_offset(is_admin): req = fakes.HTTPRequest.blank( '/v1/volumes/detail?limit=2' '&offset=1', use_admin_context=is_admin) res_dict = self.controller.index(req) volumes = res_dict['volumes'] self.assertEqual(1, len(volumes)) self.assertEqual(created_volumes[1].id, volumes[0]['id']) # admin case volume_detail_limit_offset(is_admin=True) # non_admin case volume_detail_limit_offset(is_admin=False) def test_volume_show_with_admin_metadata(self): volume = v2_fakes.create_fake_volume(fake.VOLUME_ID) del volume['name'] del volume['volume_type'] del volume['volume_type_id'] volume['metadata'] = {'key': 'value'} db.volume_create(context.get_admin_context(), volume) db.volume_admin_metadata_update(context.get_admin_context(), fake.VOLUME_ID, { "readonly": "True", "invisible_key": "invisible_value" }, False) values = { 'volume_id': fake.VOLUME_ID, } attachment = db.volume_attach(context.get_admin_context(), values) db.volume_attached(context.get_admin_context(), attachment['id'], fake.INSTANCE_ID, None, '/') req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) admin_ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True) req.environ['cinder.context'] = admin_ctx res_dict = self.controller.show(req, fake.VOLUME_ID) expected = { 'volume': { 'status': 'in-use', 'display_description': 'displaydesc', 'availability_zone': 'fakeaz', 'display_name': 'displayname', 'encrypted': False, 'attachments': [{ 'attachment_id': attachment['id'], 'device': '/', 'server_id': fake.INSTANCE_ID, 'host_name': None, 'id': fake.VOLUME_ID, 'volume_id': fake.VOLUME_ID }], 'multiattach': 'false', 'bootable': 'false', 'volume_type': None, 'snapshot_id': None, 'source_volid': None, 'metadata': { 'key': 'value', 'readonly': 'True' }, 'id': fake.VOLUME_ID, 'created_at': datetime.datetime(1900, 1, 1, 1, 1, 1, tzinfo=iso8601.iso8601.Utc()), 'size': 1 } } self.assertEqual(expected, res_dict) def test_volume_show_with_encrypted_volume(self): def fake_volume_get(self, context, volume_id, **kwargs): vol = v2_fakes.create_fake_volume(volume_id, encryption_key_id=fake.KEY_ID) return fake_volume.fake_volume_obj(context, **vol) self.mock_object(volume_api.API, 'get', fake_volume_get) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) res_dict = self.controller.show(req, fake.VOLUME_ID) self.assertTrue(res_dict['volume']['encrypted']) def test_volume_show_with_unencrypted_volume(self): self.mock_object(volume_api.API, 'get', v2_fakes.fake_volume_api_get) self.mock_object(db.sqlalchemy.api, '_volume_type_get_full', v2_fakes.fake_volume_type_get) req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) res_dict = self.controller.show(req, fake.VOLUME_ID) self.assertEqual(False, res_dict['volume']['encrypted']) @mock.patch.object(volume_api.API, 'delete', v2_fakes.fake_volume_delete) @mock.patch.object(volume_api.API, 'get', v2_fakes.fake_volume_get) def test_volume_delete(self): req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.VOLUME_ID) resp = self.controller.delete(req, fake.VOLUME_ID) self.assertEqual(http_client.ACCEPTED, resp.status_int) def test_volume_delete_no_volume(self): self.mock_object(volume_api.API, "get", v2_fakes.fake_volume_get_notfound) req = fakes.HTTPRequest.blank('/v1/volumes/%s' % fake.WILL_NOT_BE_FOUND_ID) self.assertRaises(exc.VolumeNotFound, self.controller.delete, req, fake.WILL_NOT_BE_FOUND_ID) def test_admin_list_volumes_limited_to_project(self): self.mock_object(db, 'volume_get_all_by_project', v2_fakes.fake_volume_get_all_by_project) req = fakes.HTTPRequest.blank('/v1/%s/volumes' % fake.PROJECT_ID, use_admin_context=True) res = self.controller.index(req) self.assertIn('volumes', res) self.assertEqual(1, len(res['volumes'])) @mock.patch.object(db, 'volume_get_all', v2_fakes.fake_volume_get_all) @mock.patch.object(db, 'volume_get_all_by_project', v2_fakes.fake_volume_get_all_by_project) def test_admin_list_volumes_all_tenants(self): req = fakes.HTTPRequest.blank('/v1/%s/volumes?all_tenants=1' % fake.PROJECT_ID, use_admin_context=True) res = self.controller.index(req) self.assertIn('volumes', res) self.assertEqual(3, len(res['volumes'])) @mock.patch.object(db, 'volume_get_all', v2_fakes.fake_volume_get_all) @mock.patch.object(db, 'volume_get_all_by_project', v2_fakes.fake_volume_get_all_by_project) @mock.patch.object(volume_api.API, 'get', v2_fakes.fake_volume_get) def test_all_tenants_non_admin_gets_all_tenants(self): req = fakes.HTTPRequest.blank('/v1/%s/volumes?all_tenants=1' % fake.PROJECT_ID) res = self.controller.index(req) self.assertIn('volumes', res) self.assertEqual(1, len(res['volumes'])) @mock.patch.object(db, 'volume_get_all_by_project', v2_fakes.fake_volume_get_all_by_project) @mock.patch.object(volume_api.API, 'get', v2_fakes.fake_volume_get) def test_non_admin_get_by_project(self): req = fakes.HTTPRequest.blank('/v1/%s/volumes' % fake.PROJECT_ID) res = self.controller.index(req) self.assertIn('volumes', res) self.assertEqual(1, len(res['volumes'])) def _unprocessable_volume_create(self, body): req = fakes.HTTPRequest.blank('/v1/%s/volumes' % fake.PROJECT_ID) req.method = 'POST' self.assertRaises(webob.exc.HTTPUnprocessableEntity, self.controller.create, req, body) def test_create_no_body(self): self._unprocessable_volume_create(body=None) def test_create_missing_volume(self): body = {'foo': {'a': 'b'}} self._unprocessable_volume_create(body=body) def test_create_malformed_entity(self): body = {'volume': 'string'} self._unprocessable_volume_create(body=body)