def test_copy_volume_to_image(self, has_parent=False): drv = self._smbfs_driver volume = test_utils.create_volume(self._context, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) extra_specs = {'image_service:store_id': 'fake-store'} test_utils.create_volume_type(self._context.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type", extra_specs=extra_specs) fake_image_meta = {'id': 'fake-image-id'} fake_img_format = self._smbfs_driver._DISK_FORMAT_VHDX if has_parent: fake_volume_path = self._FAKE_SNAPSHOT_PATH fake_parent_path = self._FAKE_VOLUME_PATH else: fake_volume_path = self._FAKE_VOLUME_PATH fake_parent_path = None fake_active_image = os.path.basename(fake_volume_path) drv.get_active_image_from_info = mock.Mock( return_value=fake_active_image) drv._local_volume_dir = mock.Mock(return_value=self._FAKE_MNT_POINT) drv.get_volume_format = mock.Mock(return_value=fake_img_format) drv._vhdutils.get_vhd_parent_path.return_value = (fake_parent_path) with mock.patch.object(image_utils, 'upload_volume') as (fake_upload_volume): drv.copy_volume_to_image(mock.sentinel.context, volume, mock.sentinel.image_service, fake_image_meta) if has_parent: fake_temp_image_name = '%s.temp_image.%s.%s' % ( volume.id, fake_image_meta['id'], fake_img_format) fake_temp_image_path = os.path.join(self._FAKE_MNT_POINT, fake_temp_image_name) fake_active_image_path = os.path.join(self._FAKE_MNT_POINT, fake_active_image) upload_path = fake_temp_image_path drv._vhdutils.convert_vhd.assert_called_once_with( fake_active_image_path, fake_temp_image_path) drv._delete.assert_called_once_with(fake_temp_image_path) else: upload_path = fake_volume_path fake_upload_volume.assert_called_once_with( mock.sentinel.context, mock.sentinel.image_service, fake_image_meta, upload_path, fake_img_format, store_id='fake-store')
def test_copy_volume_to_image(self, delete_temp_backing, session, upload_image, create_backing, get_moref, vops, from_provider_loc): fcd_loc = mock.Mock() ds_ref = mock.sentinel.ds_ref fcd_loc.ds_ref.return_value = ds_ref from_provider_loc.return_value = fcd_loc host_ref_val = mock.sentinel.host_ref_val vops.get_connected_hosts.return_value = [host_ref_val] host = mock.sentinel.host get_moref.return_value = host backing = mock.sentinel.backing create_backing.return_value = backing vmdk_file_path = mock.sentinel.vmdk_file_path vops.get_vmdk_path.return_value = vmdk_file_path vops.get_backing_by_uuid.return_value = backing volume = test_utils.create_volume(self._context, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) extra_specs = {'image_service:store_id': 'fake-store'} test_utils.create_volume_type(self._context.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type", extra_specs=extra_specs) image_service = mock.sentinel.image_service image_meta = self._create_image_meta() self._driver.copy_volume_to_image(self._context, volume, image_service, image_meta) from_provider_loc.assert_called_once_with(volume.provider_location) vops.get_connected_hosts.assert_called_once_with(ds_ref) create_backing.assert_called_once_with( volume, host, {vmdk.CREATE_PARAM_DISK_LESS: True}) vops.attach_fcd.assert_called_once_with(backing, fcd_loc) vops.get_vmdk_path.assert_called_once_with(backing) conf = self._driver.configuration upload_image.assert_called_once_with( self._context, conf.vmware_image_transfer_timeout_secs, image_service, image_meta['id'], volume.project_id, session=session, host=conf.vmware_host_ip, port=conf.vmware_host_port, vm=backing, vmdk_file_path=vmdk_file_path, vmdk_size=volume.size * units.Gi, image_name=image_meta['name'], store_id='fake-store', base_image_ref=None) vops.detach_fcd.assert_called_once_with(backing, fcd_loc) delete_temp_backing.assert_called_once_with(backing)
def test_transfer_accept_with_snapshots_invalid(self, mock_notify): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) utils.create_volume_type(self.ctxt.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type") utils.create_snapshot(self.ctxt, volume.id, status='deleting') self.assertRaises(exception.InvalidSnapshot, tx_api.create, self.ctxt, volume.id, 'Description')
def test_transfer_accept_with_snapshots_invalid(self, mock_notify): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) utils.create_volume_type(self.ctxt.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type") utils.create_snapshot(self.ctxt, volume.id, status='deleting') self.assertRaises(exception.InvalidSnapshot, tx_api.create, self.ctxt, volume.id, 'Description')
def test_transfer_accept_with_snapshots(self): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) utils.create_volume_type(self.ctxt.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type") utils.create_snapshot(self.ctxt, volume.id, status='available') with mock.patch('cinder.volume.volume_utils.notify_about_volume_usage' ) as mock_notify: transfer = tx_api.create(self.ctxt, volume.id, 'Description') calls = [ mock.call(self.ctxt, mock.ANY, "transfer.create.start"), mock.call(self.ctxt, mock.ANY, "transfer.create.end") ] mock_notify.assert_has_calls(calls) # The notify_about_volume_usage is called twice at create(). self.assertEqual(2, mock_notify.call_count) # Get volume and snapshot quota before accept self.ctxt.user_id = fake.USER2_ID self.ctxt.project_id = fake.PROJECT2_ID usages = db.quota_usage_get_all_by_project(self.ctxt, self.ctxt.project_id) self.assertEqual(0, usages.get('volumes', {}).get('in_use', 0)) self.assertEqual(0, usages.get('snapshots', {}).get('in_use', 0)) with mock.patch('cinder.volume.volume_utils.notify_about_volume_usage' ) as mock_notify: tx_api.accept(self.ctxt, transfer['id'], transfer['auth_key']) calls = [ mock.call(self.ctxt, mock.ANY, "transfer.accept.start"), mock.call(self.ctxt, mock.ANY, "transfer.accept.end") ] mock_notify.assert_has_calls(calls) # The notify_about_volume_usage is called twice at accept(). self.assertEqual(2, mock_notify.call_count) volume = objects.Volume.get_by_id(self.ctxt, volume.id) self.assertEqual(fake.PROJECT2_ID, volume.project_id) self.assertEqual(fake.USER2_ID, volume.user_id) # Get volume and snapshot quota after accept self.ctxt.user_id = fake.USER2_ID self.ctxt.project_id = fake.PROJECT2_ID usages = db.quota_usage_get_all_by_project(self.ctxt, self.ctxt.project_id) self.assertEqual(1, usages.get('volumes', {}).get('in_use', 0)) self.assertEqual(1, usages.get('snapshots', {}).get('in_use', 0))
def test_delete_cgsnapshot_delete_policy_not_auth(self, mock_delete): vol_type = utils.create_volume_type(context.get_admin_context(), self, name='my_vol_type') consistencygroup = utils.create_group(self.context, group_type_id=fake.GROUP_TYPE_ID, volume_type_ids=[vol_type['id']]) volume_id = utils.create_volume(self.context, volume_type_id=vol_type['id'], group_id=consistencygroup.id)['id'] cgsnapshot = utils.create_group_snapshot( self.context, group_id=consistencygroup.id, group_type_id=fake.GROUP_TYPE_ID, status='available') mock_delete.side_effect = exception.PolicyNotAuthorized( message='PolicyNotAuthorized') req = webob.Request.blank('/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('PolicyNotAuthorized', res_dict['forbidden']['message']) cgsnapshot.destroy() db.volume_destroy(context.get_admin_context(), volume_id) consistencygroup.destroy()
def test_list_replication_targets_group_policy(self, user_id, mock_list_targets): """Test list replication targets for a group policy.""" # FIXME: this is a very fragile approach def fake_list_targets(context, group): context.authorize(group_policies.LIST_REP, target_obj=group) volume_type = test_utils.create_volume_type(self.project_admin_context, name='test_group_policy') group_2 = test_utils.create_group(self.project_admin_context, status=fields.GroupStatus.AVAILABLE, group_type_id=self.group_type.id, volume_type_ids=[volume_type.id]) mock_list_targets.side_effect = fake_list_targets rule_name = group_policies.LIST_REP url = '%s/%s/action' % (self.api_path, group_2.id) req = fake_api.HTTPRequest.blank(url, version=mv.GROUP_REPLICATION) req.method = 'POST' body = {"list_replication_targets": {}} unauthorized_exceptions = [exception.GroupNotFound] self.common_policy_check(user_id, self.authorized_members, self.unauthorized_members, unauthorized_exceptions, rule_name, self.controller.list_replication_targets, req, id=group_2.id, body=body) group_2.destroy()
def test_delete_group_policy(self, user_id): """Test delete group policy.""" volume_type = test_utils.create_volume_type(self.project_admin_context, name='test_group_policy') group_1 = test_utils.create_group(self.project_admin_context, status=fields.GroupStatus.AVAILABLE, group_type_id=self.group_type.id, volume_type_ids=[volume_type.id]) rule_name = group_policies.DELETE_POLICY url = '%s/%s' % (self.api_path, group_1.id) req = fake_api.HTTPRequest.blank(url, version=mv.GROUP_VOLUME) req.method = 'POST' body = {"delete": {"delete-volumes": "false"}} unauthorized_exceptions = [exception.GroupNotFound] self.common_policy_check(user_id, self.authorized_members, self.unauthorized_members, unauthorized_exceptions, rule_name, self.controller.delete_group, req, id=group_1.id, body=body)
def _create_replica_volume_type(self, enable, rep_type=instorage_const.SYNC): # Generate a volume type for volume repliation. if enable: if rep_type == instorage_const.SYNC: spec = { 'replication_enabled': '<is> True', 'replication_type': '<in> sync' } type_name = 'rep_sync' else: spec = { 'replication_enabled': '<is> True', 'replication_type': '<in> async' } type_name = 'rep_async' else: spec = {'replication_enabled': '<is> False'} type_name = "non_rep" db_rep_type = testutils.create_volume_type(self.ctxt, name=type_name, extra_specs=spec) rep_type = volume_types.get_volume_type(self.ctxt, db_rep_type.id) return rep_type
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()
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()
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_delete_policy_not_auth(self, mock_delete): vol_type = utils.create_volume_type(context.get_admin_context(), self, name='my_vol_type') consistencygroup = utils.create_group( self.context, group_type_id=fake.GROUP_TYPE_ID, volume_type_ids=[vol_type['id']]) volume_id = utils.create_volume(self.context, volume_type_id=vol_type['id'], group_id= consistencygroup.id)['id'] cgsnapshot = utils.create_group_snapshot( self.context, group_id=consistencygroup.id, group_type_id=fake.GROUP_TYPE_ID, status='available') mock_delete.side_effect = exception.PolicyNotAuthorized( message='PolicyNotAuthorized') req = webob.Request.blank('/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('PolicyNotAuthorized', res_dict['forbidden']['message']) cgsnapshot.destroy() db.volume_destroy(context.get_admin_context(), volume_id) consistencygroup.destroy()
def test_update_volumes_host(self, mock_volume_get_all, mock_cluster_name, mock_host): vol_type = utils.create_volume_type(self.ctxt, name='test_vol_type') grp = utils.create_group(self.ctxt, group_type_id=fake.GROUP_TYPE_ID, volume_type_ids=[vol_type['id']], availability_zone='nova', status=fields.GroupStatus.CREATING, cluster_name='fake_cluster') vol1 = utils.create_volume( self.ctxt, availability_zone=grp.availability_zone, volume_type_id=fake.VOLUME_TYPE_ID, group_id=grp.id) mock_volume = mock.Mock() mock_volume_get_all.return_value = [mock_volume] group_api = cinder.group.api.API() group_api._update_volumes_host(None, grp) mock_cluster_name.assert_called() mock_host.assert_called() self.assertEqual(grp.host, mock_volume.host) self.assertEqual(grp.cluster_name, mock_volume.cluster_name) mock_volume.save.assert_called_once_with() vol1.destroy() grp.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_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 _create_volume(self): vol_type = test_utils.create_volume_type(self.project_admin_context, name='fake_vol_type', testcase_instance=self) volume = test_utils.create_volume(self.project_member_context, volume_type_id=vol_type.id, testcase_instance=self) return volume
def test_copy_volume_to_image(self, mock_delete_if_exists, mock_upload_volume, mock_tmp_snap): tgt_utils = self._driver._tgt_utils disk_format = 'vhd' fake_image_meta = db_fakes.get_fake_image_meta() fake_volume = test_utils.create_volume( self._context, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) extra_specs = { 'image_service:store_id': 'fake-store' } test_utils.create_volume_type(self._context.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type", extra_specs=extra_specs) fake_img_conv_dir = 'fake_img_conv_dir' self.flags(image_conversion_dir=fake_img_conv_dir) tgt_utils.get_supported_disk_format.return_value = disk_format mock_tmp_snap.return_value.__enter__.return_value = ( mock.sentinel.tmp_snap_name) expected_tmp_vhd_path = os.path.join( fake_img_conv_dir, fake_image_meta['id'] + '.' + disk_format) self._driver.copy_volume_to_image( mock.sentinel.context, fake_volume, mock.sentinel.image_service, fake_image_meta) mock_tmp_snap.assert_called_once_with(fake_volume.name) tgt_utils.export_snapshot.assert_called_once_with( mock.sentinel.tmp_snap_name, expected_tmp_vhd_path) mock_upload_volume.assert_called_once_with( mock.sentinel.context, mock.sentinel.image_service, fake_image_meta, expected_tmp_vhd_path, volume_format='vhd', store_id='fake-store', base_image_ref=None, compress=True, run_as_root=True) mock_delete_if_exists.assert_called_once_with( expected_tmp_vhd_path)
def test_create_group_from_group(self, mock_policy, mock_volume_get_all, mock_rpc_create_group_from_src, mock_group_get, mock_volume_api_create, mock_mapping_create, mock_get_volume_type): vol_type = utils.create_volume_type(self.ctxt, name = 'fake_volume_type') mock_get_volume_type.return_value = vol_type grp = utils.create_group(self.ctxt, group_type_id = fake.GROUP_TYPE_ID, volume_type_ids = [vol_type['id']], availability_zone = 'nova', status = fields.GroupStatus.CREATING) mock_group_get.return_value = grp vol = utils.create_volume( self.ctxt, availability_zone = grp.availability_zone, volume_type_id = fake.VOLUME_TYPE_ID, group_id = grp.id) mock_volume_get_all.return_value = [vol] grp2 = utils.create_group(self.ctxt, group_type_id = fake.GROUP_TYPE_ID, volume_type_ids = [vol_type['id']], availability_zone = 'nova', source_group_id = grp.id, status = fields.GroupStatus.CREATING) vol2 = utils.create_volume( self.ctxt, availability_zone = grp.availability_zone, volume_type_id = vol_type['id'], group_id = grp2.id, source_volid = vol.id) self.group_api._create_group_from_source_group(self.ctxt, grp2, grp.id) mock_volume_api_create.assert_called_once_with( self.ctxt, 1, None, None, availability_zone = grp.availability_zone, source_group = grp, group = grp2, source_volume = vol, volume_type = vol_type) mock_rpc_create_group_from_src.assert_called_once_with( self.ctxt, grp2, None, grp) vol2.destroy() grp2.destroy() vol.destroy() grp.destroy() db.volume_type_destroy(self.ctxt, vol_type['id'])
def test_create_group_from_group(self, mock_policy, mock_volume_get_all, mock_rpc_create_group_from_src, mock_group_get, mock_volume_api_create, mock_mapping_create, mock_get_volume_type): vol_type = utils.create_volume_type(self.ctxt, name = 'fake_volume_type') mock_get_volume_type.return_value = vol_type grp = utils.create_group(self.ctxt, group_type_id = fake.GROUP_TYPE_ID, volume_type_ids = [vol_type['id']], availability_zone = 'nova', status = fields.GroupStatus.CREATING) mock_group_get.return_value = grp vol = utils.create_volume( self.ctxt, availability_zone = grp.availability_zone, volume_type_id = fake.VOLUME_TYPE_ID, group_id = grp.id) mock_volume_get_all.return_value = [vol] grp2 = utils.create_group(self.ctxt, group_type_id = fake.GROUP_TYPE_ID, volume_type_ids = [vol_type['id']], availability_zone = 'nova', source_group_id = grp.id, status = fields.GroupStatus.CREATING) vol2 = utils.create_volume( self.ctxt, availability_zone = grp.availability_zone, volume_type_id = vol_type['id'], group_id = grp2.id, source_volid = vol.id) self.group_api._create_group_from_source_group(self.ctxt, grp2, grp.id) mock_volume_api_create.assert_called_once_with( self.ctxt, 1, None, None, availability_zone = grp.availability_zone, source_group = grp, group = grp2, source_volume = vol, volume_type = vol_type) mock_rpc_create_group_from_src.assert_called_once_with( self.ctxt, grp2, None, grp) vol2.destroy() grp2.destroy() vol.destroy() grp.destroy() db.volume_type_destroy(self.ctxt, vol_type['id'])
def test_copy_volume_to_image(self, volume_get): with mock.patch.object(self.driver, "_rpc_call", self.jsonrpcclient.call): provider_location = "127.0.0.1:3262 RDMA 2016-06.io.spdk:cnode2" volume = test_utils.create_volume( self._context, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at, provider_location=provider_location) extra_specs = {'image_service:store_id': 'fake-store'} test_utils.create_volume_type(self._context.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type", extra_specs=extra_specs) ctxt = context.get_admin_context() volume_get.return_value = volume with mock.patch.object(self.driver.target_driver, "_rpc_call", self.jsonrpcclient.call): self.driver.copy_volume_to_image(ctxt, volume, None, None)
def test_delete_volume_fail_if_not_created(self): """Test that lightos_client fail creating an already exists volume.""" self.driver.do_setup(None) vol_type = test_utils.create_volume_type(self.ctxt, self, name='my_vol_type') volume = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type.id) self.driver.delete_volume(volume) db.volume_destroy(self.ctxt, volume.id)
def test_extend_volume_should_fail_if_volume_does_not_exist(self): self.driver.do_setup(None) vol_type = test_utils.create_volume_type(self.ctxt, self, name='my_vol_type') volume = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type.id) self.assertRaises(exception.VolumeNotFound, self.driver.extend_volume, volume, 6) db.volume_destroy(self.ctxt, volume.id)
def test_transfer_accept_with_snapshots(self, mock_notify): svc = self.start_service('volume', host='test_host') self.addCleanup(svc.stop) tx_api = transfer_api.API() volume = utils.create_volume(self.ctxt, volume_type_id=fake.VOLUME_TYPE_ID, updated_at=self.updated_at) utils.create_volume_type(self.ctxt.elevated(), id=fake.VOLUME_TYPE_ID, name="test_type") utils.create_snapshot(self.ctxt, volume.id, status='available') transfer = tx_api.create(self.ctxt, volume.id, 'Description') # Get volume and snapshot quota before accept self.ctxt.user_id = fake.USER2_ID self.ctxt.project_id = fake.PROJECT2_ID usages = db.quota_usage_get_all_by_project(self.ctxt, self.ctxt.project_id) self.assertEqual(0, usages.get('volumes', {}).get('in_use', 0)) self.assertEqual(0, usages.get('snapshots', {}).get('in_use', 0)) tx_api.accept(self.ctxt, transfer['id'], transfer['auth_key']) volume = objects.Volume.get_by_id(self.ctxt, volume.id) self.assertEqual(fake.PROJECT2_ID, volume.project_id) self.assertEqual(fake.USER2_ID, volume.user_id) calls = [mock.call(self.ctxt, mock.ANY, "transfer.accept.start"), mock.call(self.ctxt, mock.ANY, "transfer.accept.end")] mock_notify.assert_has_calls(calls) # The notify_about_volume_usage is called twice at create(), # and twice at accept(). self.assertEqual(4, mock_notify.call_count) # Get volume and snapshot quota after accept self.ctxt.user_id = fake.USER2_ID self.ctxt.project_id = fake.PROJECT2_ID usages = db.quota_usage_get_all_by_project(self.ctxt, self.ctxt.project_id) self.assertEqual(1, usages.get('volumes', {}).get('in_use', 0)) self.assertEqual(1, usages.get('snapshots', {}).get('in_use', 0))
def _create_snapshot(self, **kwargs): vol_type = test_utils.create_volume_type(self.project_admin_context, name='fake_vol_type', testcase_instance=self) volume = test_utils.create_volume(self.project_member_context, volume_type_id=vol_type.id, testcase_instance=self) snapshot = test_utils.create_snapshot(self.project_member_context, volume_id=volume.id, testcase_instance=self, **kwargs) return snapshot
def _create_group(self, group_status=fields.GroupStatus.AVAILABLE): volume_type = test_utils.create_volume_type(self.project_admin_context, name="test") group = test_utils.create_group(self.project_admin_context, status=group_status, group_type_id=self.group_type.id, volume_type_ids=[volume_type.id]) test_utils.create_volume(self.project_member_context, group_id=group.id, testcase_instance=self, volume_type_id=volume_type.id) return group.id
def setUp(self, enforce_scope=False, enforce_new_defaults=False, *args, **kwargs): super().setUp(enforce_scope, enforce_new_defaults, *args, **kwargs) self.controller = snapshots.SnapshotsController() self.api_path = '/v3/%s/snapshots' % (self.project_id) self.api_version = mv.BASE_VERSION self.vol_type = test_utils.create_volume_type( self.project_admin_context, name='fake_vol_type', testcase_instance=self)
def test_get_volume_specs_compression_True(self): self.driver.do_setup(None) vol_type = test_utils.create_volume_type( self.ctxt, self, extra_specs={'compression': 'True'}, name='my_vol_typ1') vol_type2 = test_utils.create_volume_type( self.ctxt, self, extra_specs={'compression': '<is> True'}, name='my_vol_type2') vol_type3 = test_utils.create_volume_type(self.ctxt, self, name='my_vol_type3') volume1 = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type.id) volume2 = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type2.id) volume3 = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type3.id) compression, _, _ = self.driver._get_volume_specs(volume1) self.assertTrue(compression == "True") compression, _, _ = self.driver._get_volume_specs(volume2) self.assertTrue(compression == "True") compression, _, _ = self.driver._get_volume_specs(volume3) self.assertTrue(compression == "False") db.volume_destroy(self.ctxt, volume1.id) db.volume_destroy(self.ctxt, volume2.id) db.volume_destroy(self.ctxt, volume3.id)
def _create_volume(self, image_metadata=None, **kwargs): vol_type = test_utils.create_volume_type(self.project_admin_context, name='fake_vol_type', testcase_instance=self) volume = test_utils.create_volume(self.project_member_context, volume_type_id=vol_type.id, testcase_instance=self, **kwargs) for (k, v) in (image_metadata.items() if image_metadata else []): db.volume_glance_metadata_create(self.project_admin_context, volume.id, k, v) return volume
def test_extend_volume_should_succeed(self): self.driver.do_setup(None) vol_type = test_utils.create_volume_type(self.ctxt, self, name='my_vol_type') volume = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type.id) self.driver.create_volume(volume) self.driver.extend_volume(volume, 6) self.driver.delete_volume(volume) db.volume_destroy(self.ctxt, volume.id)
def test_terminate_connection_with_hostnqn(self): InitialConnectorMock.nqn = "hostnqn1" InitialConnectorMock.found_discovery_client = True self.driver.do_setup(None) vol_type = test_utils.create_volume_type(self.ctxt, self, name='my_vol_type') volume = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type.id) self.driver.create_volume(volume) self.driver.terminate_connection(volume, get_connector_properties()) self.driver.delete_volume(volume) db.volume_destroy(self.ctxt, volume.id)
def test_create_volume_in_failed_state(self): """Verify scenario of created volume in failed state: Driver is expected to issue a deletion command and raise exception """ def send_cmd_mock(cmd, **kwargs): if cmd == "create_volume": project_name = kwargs["project_name"] volume = { "project_name": project_name, "name": kwargs["name"], "size": kwargs["size"], "n_replicas": kwargs["n_replicas"], "compression": kwargs["compression"], "src_snapshot_name": kwargs["src_snapshot_name"], "acl": { 'values': kwargs.get('acl') }, "state": "Failed", } volume["ETag"] = get_vol_etag(volume) code, new_vol = self.db.create_volume(volume) return (code, new_vol) elif cmd == "delete_volume": return self.db.delete_volume(kwargs["project_name"], kwargs["volume_uuid"]) elif cmd == "get_volume": return self.db.get_volume_by_uuid(kwargs["project_name"], kwargs["volume_uuid"]) elif cmd == "get_volume_by_name": return self.db.get_volume_by_name(kwargs["project_name"], kwargs["volume_name"]) else: raise RuntimeError( f"'{cmd}' is not implemented. kwargs: {kwargs}") self.driver.do_setup(None) self.driver.cluster.send_cmd = send_cmd_mock vol_type = test_utils.create_volume_type(self.ctxt, self, name='my_vol_type') volume = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type.id) self.assertRaises(exception.VolumeBackendAPIException, self.driver.create_volume, volume) proj = self.db.data["projects"][lightos.LIGHTOS_DEFAULT_PROJECT_NAME] actual_volumes = proj["volumes"] self.assertEqual(0, len(actual_volumes)) db.volume_destroy(self.ctxt, volume.id)
def test_create_volume_should_succeed(self): """Test that lightos_client succeed.""" self.driver.do_setup(None) vol_type = test_utils.create_volume_type(self.ctxt, self, name='my_vol_type') volume = test_utils.create_volume(self.ctxt, size=4, volume_type_id=vol_type.id) self.driver.create_volume(volume) self.driver.delete_volume(volume) db.volume_destroy(self.ctxt, volume.id)
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 _create_volume_type( self, ctxt=None, id=fake.VOLUME_TYPE_ID, name='test_volume_type', description='this is a test volume type', extra_specs={"test_key": "test_val"}, testcase_instance=None, **kwargs): """Create a volume type.""" ctxt = ctxt or self.ctxt vol_type = utils.create_volume_type( ctxt, testcase_instance=testcase_instance, id=id, name=name, description=description, extra_specs=extra_specs, **kwargs) return vol_type
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 _create_replica_volume_type(self, enable, rep_type=instorage_const.SYNC): # Generate a volume type for volume repliation. if enable: if rep_type == instorage_const.SYNC: spec = {'replication_enabled': '<is> True', 'replication_type': '<in> sync'} type_name = 'rep_sync' else: spec = {'replication_enabled': '<is> True', 'replication_type': '<in> async'} type_name = 'rep_async' else: spec = {'replication_enabled': '<is> False'} type_name = "non_rep" db_rep_type = testutils.create_volume_type(self.ctxt, name=type_name, extra_specs=spec) rep_type = volume_types.get_volume_type(self.ctxt, db_rep_type.id) return rep_type
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_cast_create_group(self, mock_create_group, mock_get_volume_type_qos_specs): vol_type = utils.create_volume_type(self.ctxt, name='test_vol_type') encryption_key_id = mock.sentinel.encryption_key_id description = mock.sentinel.description name = mock.sentinel.name req_spec = {'volume_type': vol_type, 'encryption_key_id': encryption_key_id, 'description': description, 'name': name} grp_name = "test_group" grp_description = "this is a test group" grp_spec = {'name': grp_name, 'description': grp_description} grp = utils.create_group(self.ctxt, group_type_id=fake.GROUP_TYPE_ID, volume_type_ids=[vol_type.id], availability_zone='nova') grp_filter_properties = mock.sentinel.group_filter_properties filter_properties_list = mock.sentinel.filter_properties_list self.group_api._cast_create_group(self.ctxt, grp, grp_spec, [req_spec], grp_filter_properties, filter_properties_list) mock_get_volume_type_qos_specs.assert_called_once_with(vol_type.id) exp_vol_properties = { 'size': 0, 'user_id': self.ctxt.user_id, 'project_id': self.ctxt.project_id, 'status': 'creating', 'attach_status': 'detached', 'encryption_key_id': encryption_key_id, 'display_description': description, 'display_name': name, 'volume_type_id': vol_type.id, 'group_type_id': grp.group_type_id, 'availability_zone': grp.availability_zone } exp_req_spec = { 'volume_type': vol_type, 'encryption_key_id': encryption_key_id, 'description': description, 'name': name, 'volume_properties': exp_vol_properties, 'qos_specs': None } exp_grp_properties = { 'size': 0, 'user_id': self.ctxt.user_id, 'project_id': self.ctxt.project_id, 'status': 'creating', 'display_description': grp_description, 'display_name': grp_name, 'group_type_id': grp.group_type_id, } exp_grp_spec = { 'name': grp_name, 'description': grp_description, 'volume_properties': exp_grp_properties, 'qos_specs': None } mock_create_group.assert_called_once_with( self.ctxt, grp, group_spec=exp_grp_spec, request_spec_list=[exp_req_spec], group_filter_properties=grp_filter_properties, filter_properties_list=filter_properties_list)
def test_create_group_from_snap(self, mock_volume_get_all, mock_rpc_create_group_from_src, mock_snap_get_all, mock_group_snap_get, mock_volume_api_create, mock_mapping_create, mock_get_volume_type): vol_type = utils.create_volume_type(self.ctxt, name = 'fake_volume_type') mock_get_volume_type.return_value = vol_type grp_snap = utils.create_group_snapshot( self.ctxt, fake.GROUP_ID, group_type_id = fake.GROUP_TYPE_ID, status = fields.GroupStatus.CREATING) mock_group_snap_get.return_value = grp_snap vol1 = utils.create_volume( self.ctxt, availability_zone = 'nova', volume_type_id = vol_type['id'], group_id = fake.GROUP_ID) snap = utils.create_snapshot(self.ctxt, vol1.id, volume_type_id = vol_type['id'], status = fields.GroupStatus.CREATING) mock_snap_get_all.return_value = [snap] name = "test_group" description = "this is a test group" grp = utils.create_group(self.ctxt, group_type_id = fake.GROUP_TYPE_ID, volume_type_ids = [vol_type['id']], availability_zone = 'nova', name = name, description = description, group_snapshot_id = grp_snap.id, status = fields.GroupStatus.CREATING) vol2 = utils.create_volume( self.ctxt, availability_zone = grp.availability_zone, volume_type_id = vol_type['id'], group_id = grp.id, snapshot_id = snap.id) mock_volume_get_all.return_value = [vol2] self.group_api._create_group_from_group_snapshot(self.ctxt, grp, grp_snap.id) mock_volume_api_create.assert_called_once_with( self.ctxt, 1, None, None, availability_zone = grp.availability_zone, group_snapshot = grp_snap, group = grp, snapshot = snap, volume_type = vol_type) mock_rpc_create_group_from_src.assert_called_once_with( self.ctxt, grp, grp_snap) vol2.destroy() grp.destroy() snap.destroy() vol1.destroy() grp_snap.destroy() db.volume_type_destroy(self.ctxt, vol_type['id'])