class GPFSDriverTestCase(test.TestCase): driver_name = "cinder.volume.drivers.gpfs.GPFSDriver" context = context.get_admin_context() def _execute_wrapper(self, cmd, *args, **kwargs): try: kwargs.pop('run_as_root') except KeyError: pass return utils.execute(cmd, *args, **kwargs) def setUp(self): super(GPFSDriverTestCase, self).setUp() self.volumes_path = tempfile.mkdtemp(prefix="gpfs_") self.images_dir = '%s/images' % self.volumes_path if not os.path.exists(self.volumes_path): os.mkdir(self.volumes_path) if not os.path.exists(self.images_dir): os.mkdir(self.images_dir) self.image_id = '70a599e0-31e7-49b7-b260-868f441e862b' self.driver = GPFSDriver(configuration=conf.Configuration(None)) self.driver.set_execute(self._execute_wrapper) self.flags(volume_driver=self.driver_name, gpfs_mount_point_base=self.volumes_path) self.volume = importutils.import_object(CONF.volume_manager) self.volume.driver.set_execute(self._execute_wrapper) self.volume.driver.set_initialized() self.volume.stats = dict(allocated_capacity_gb=0) self.stubs.Set(GPFSDriver, '_create_gpfs_snap', self._fake_gpfs_snap) self.stubs.Set(GPFSDriver, '_create_gpfs_copy', self._fake_gpfs_copy) self.stubs.Set(GPFSDriver, '_gpfs_redirect', self._fake_gpfs_redirect) self.stubs.Set(GPFSDriver, '_is_gpfs_parent_file', self._fake_is_gpfs_parent) self.stubs.Set(GPFSDriver, '_is_gpfs_path', self._fake_is_gpfs_path) self.stubs.Set(GPFSDriver, '_delete_gpfs_file', self._fake_delete_gpfs_file) self.stubs.Set(GPFSDriver, '_create_sparse_file', self._fake_create_sparse_file) self.stubs.Set(GPFSDriver, '_allocate_file_blocks', self._fake_allocate_file_blocks) self.stubs.Set(GPFSDriver, '_get_available_capacity', self._fake_get_available_capacity) self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_qcow2_image_info) self.stubs.Set(image_utils, 'convert_image', self._fake_convert_image) self.stubs.Set(image_utils, 'resize_image', self._fake_qemu_image_resize) self.context = context.get_admin_context() self.context.user_id = 'fake' self.context.project_id = 'fake' CONF.gpfs_images_dir = self.images_dir def tearDown(self): try: os.rmdir(self.images_dir) os.rmdir(self.volumes_path) except OSError: pass super(GPFSDriverTestCase, self).tearDown() def test_create_delete_volume_full_backing_file(self): """Create and delete vol with full creation method.""" CONF.gpfs_sparse_volumes = False vol = test_utils.create_volume(self.context, host=CONF.host) volume_id = vol['id'] self.assertTrue(os.path.exists(self.volumes_path)) self.volume.create_volume(self.context, volume_id) path = self.volumes_path + '/' + vol['name'] self.assertTrue(os.path.exists(path)) self.volume.delete_volume(self.context, volume_id) self.assertFalse(os.path.exists(path)) def test_create_delete_volume_sparse_backing_file(self): """Create and delete vol with default sparse creation method.""" CONF.gpfs_sparse_volumes = True vol = test_utils.create_volume(self.context, host=CONF.host) volume_id = vol['id'] self.assertTrue(os.path.exists(self.volumes_path)) self.volume.create_volume(self.context, volume_id) path = self.volumes_path + '/' + vol['name'] self.assertTrue(os.path.exists(path)) self.volume.delete_volume(self.context, volume_id) self.assertFalse(os.path.exists(path)) def test_create_volume_with_attributes(self): self.stubs.Set(GPFSDriver, '_gpfs_change_attributes', self._fake_gpfs_change_attributes) attributes = {'dio': 'yes', 'data_pool_name': 'ssd_pool', 'replicas': '2', 'write_affinity_depth': '1', 'block_group_factor': '1', 'write_affinity_failure-group': '1,1,1:2;2,1,1:2;2,0,3:4'} vol = test_utils.create_volume(self.context, host=CONF.host, metadata=attributes) volume_id = vol['id'] self.assertTrue(os.path.exists(self.volumes_path)) self.volume.create_volume(self.context, volume_id) path = self.volumes_path + '/' + vol['name'] self.assertTrue(os.path.exists(path)) self.volume.delete_volume(self.context, volume_id) self.assertFalse(os.path.exists(path)) def test_migrate_volume(self): """Test volume migration done by driver.""" loc = 'GPFSDriver:cindertest:openstack' cap = {'location_info': loc} host = {'host': 'foo', 'capabilities': cap} volume = test_utils.create_volume(self.context, host=CONF.host) self.driver.create_volume(volume) self.driver.migrate_volume(self.context, volume, host) self.driver.delete_volume(volume) def _create_snapshot(self, volume_id, size='0'): """Create a snapshot object.""" snap = {} snap['volume_size'] = size snap['user_id'] = 'fake' snap['project_id'] = 'fake' snap['volume_id'] = volume_id snap['status'] = "creating" return db.snapshot_create(context.get_admin_context(), snap) def test_create_delete_snapshot(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) snapCount = len(db.snapshot_get_all_for_volume(self.context, volume_src['id'])) self.assertEqual(snapCount, 0) snapshot = self._create_snapshot(volume_src['id']) snapshot_id = snapshot['id'] self.volume.create_snapshot(self.context, volume_src['id'], snapshot_id) self.assertTrue(os.path.exists(os.path.join(self.volumes_path, snapshot['name']))) snapCount = len(db.snapshot_get_all_for_volume(self.context, volume_src['id'])) self.assertEqual(snapCount, 1) self.volume.delete_snapshot(self.context, snapshot_id) self.volume.delete_volume(self.context, volume_src['id']) self.assertFalse(os.path.exists(os.path.join(self.volumes_path, snapshot['name']))) snapCount = len(db.snapshot_get_all_for_volume(self.context, volume_src['id'])) self.assertEqual(snapCount, 0) def test_create_volume_from_snapshot(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) snapshot = self._create_snapshot(volume_src['id']) snapshot_id = snapshot['id'] self.volume.create_snapshot(self.context, volume_src['id'], snapshot_id) self.assertTrue(os.path.exists(os.path.join(self.volumes_path, snapshot['name']))) volume_dst = test_utils.create_volume(self.context, host=CONF.host, snapshot_id=snapshot_id) self.volume.create_volume(self.context, volume_dst['id'], snapshot_id) self.assertEqual(volume_dst['id'], db.volume_get( context.get_admin_context(), volume_dst['id']).id) self.assertEqual(snapshot_id, db.volume_get( context.get_admin_context(), volume_dst['id']).snapshot_id) self.volume.delete_volume(self.context, volume_dst['id']) self.volume.delete_snapshot(self.context, snapshot_id) self.volume.delete_volume(self.context, volume_src['id']) def test_create_cloned_volume(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) volume_dst = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume_dst['name']) self.assertFalse(os.path.exists(volumepath)) self.driver.create_cloned_volume(volume_dst, volume_src) self.assertEqual(volume_dst['id'], db.volume_get( context.get_admin_context(), volume_dst['id']).id) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume_src['id']) self.volume.delete_volume(self.context, volume_dst['id']) def test_create_volume_from_snapshot_method(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) snapshot = self._create_snapshot(volume_src['id']) snapshot_id = snapshot['id'] self.volume.create_snapshot(self.context, volume_src['id'], snapshot_id) volume_dst = test_utils.create_volume(self.context, host=CONF.host) self.driver.create_volume_from_snapshot(volume_dst, snapshot) self.assertEqual(volume_dst['id'], db.volume_get( context.get_admin_context(), volume_dst['id']).id) volumepath = os.path.join(self.volumes_path, volume_dst['name']) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_snapshot(self.context, snapshot_id) self.volume.delete_volume(self.context, volume_dst['id']) self.volume.delete_volume(self.context, volume_src['id']) def test_clone_image_to_volume_with_copy_on_write_mode(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using copy_on_write image sharing mode. """ # specify image file format is raw self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_raw_image_info) volume = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume['name']) CONF.gpfs_images_share_mode = 'copy_on_write' self.driver.clone_image(volume, None, self.image_id, {}) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume['id']) self.assertFalse(os.path.exists(volumepath)) def test_clone_image_to_volume_with_copy_mode(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using copy image sharing mode. """ # specify image file format is raw self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_raw_image_info) volume = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume['name']) CONF.gpfs_images_share_mode = 'copy' self.driver.clone_image(volume, None, self.image_id, {}) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume['id']) def test_copy_image_to_volume_with_non_gpfs_image_dir(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using a non gpfs glance images directory """ # specify image file format is raw self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_raw_image_info) for share_mode in ['copy_on_write', 'copy']: volume = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume['name']) CONF.gpfs_images_share_mode = share_mode CONF.gpfs_images_dir = None self.driver.copy_image_to_volume(self.context, volume, FakeImageService(), self.image_id) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume['id']) def test_copy_image_to_volume_with_illegal_image_format(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using an illegal image file format """ # specify image file format is qcow2 self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_qcow2_image_info) volume = test_utils.create_volume(self.context, host=CONF.host) CONF.gpfs_images_share_mode = 'copy' CONF.gpfs_images_dir = self.images_dir self.assertRaises(exception.ImageUnacceptable, self.driver.copy_image_to_volume, self.context, volume, FakeImageService(), self.image_id) self.volume.delete_volume(self.context, volume['id']) def test_get_volume_stats(self): stats = self.driver.get_volume_stats() self.assertEqual(stats['volume_backend_name'], 'GPFS') self.assertEqual(stats['storage_protocol'], 'file') def test_extend_volume(self): new_vol_size = 15 mox = mox_lib.Mox() volume = test_utils.create_volume(self.context, host=CONF.host) volpath = os.path.join(self.volumes_path, volume['name']) qemu_img_info_output = """image: %s file format: raw virtual size: %sG (%s bytes) backing file: %s """ % (volume['name'], new_vol_size, new_vol_size * units.GiB, volpath) mox.StubOutWithMock(image_utils, 'resize_image') image_utils.resize_image(volpath, new_vol_size) mox.StubOutWithMock(image_utils, 'qemu_img_info') img_info = imageutils.QemuImgInfo(qemu_img_info_output) image_utils.qemu_img_info(volpath).AndReturn(img_info) mox.ReplayAll() self.driver.extend_volume(volume, new_vol_size) mox.VerifyAll() def test_extend_volume_with_failure(self): new_vol_size = 15 mox = mox_lib.Mox() volume = test_utils.create_volume(self.context, host=CONF.host) volpath = os.path.join(self.volumes_path, volume['name']) mox.StubOutWithMock(image_utils, 'resize_image') image_utils.resize_image(volpath, new_vol_size).AndRaise( processutils.ProcessExecutionError('error')) mox.ReplayAll() self.assertRaises(exception.VolumeBackendAPIException, self.driver.extend_volume, volume, new_vol_size) mox.VerifyAll() def test_check_for_setup_error_ok(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_compatible_cluster_release_level) self.stubs.Set(GPFSDriver, '_get_gpfs_filesystem_release_level', self._fake_gpfs_compatible_filesystem_release_level) self.driver.check_for_setup_error() def test_check_for_setup_error_gpfs_not_active(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_not_active) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def test_check_for_setup_error_not_gpfs_path(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_is_gpfs_path', self._fake_is_not_gpfs_path) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_compatible_cluster_release_level) self.stubs.Set(GPFSDriver, '_get_gpfs_filesystem_release_level', self._fake_gpfs_compatible_filesystem_release_level) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def test_check_for_setup_error_incompatible_cluster_version(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_incompatible_cluster_release_level) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def test_check_for_setup_error_incompatible_filesystem_version(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_compatible_cluster_release_level) self.stubs.Set(GPFSDriver, '_get_gpfs_filesystem_release_level', self._fake_gpfs_incompatible_filesystem_release_level) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def _fake_create_file(self, path, modebits='666'): open(path, 'w').close() utils.execute('chmod', modebits, path) def _fake_gpfs_snap(self, src, dest=None, modebits='644'): if dest is None: dest = src self._fake_create_file(dest, '644') def _fake_gpfs_copy(self, src, dest): self._fake_create_file(dest) def _fake_create_sparse_file(self, path, size): self._fake_create_file(path) def _fake_allocate_file_blocks(self, path, size): self._fake_create_file(path) def _fake_gpfs_change_attributes(self, options, path): pass def _fake_gpfs_redirect(self, src): return True def _fake_is_gpfs_parent(self, gpfs_file): return False def _fake_get_available_capacity(self, path): fake_avail = 80 * units.GiB fake_size = 2 * fake_avail return fake_avail, fake_size def _fake_gpfs_get_state_active(self): active_txt = ('mmgetstate::HEADER:version:reserved:reserved:' 'nodeName:nodeNumber:state:quorum:nodesUp:totalNodes:' 'remarks:cnfsState:\n' 'mmgetstate::0:1:::hostname:1:active:1:1:' '1:quorum node:(undefined):') return active_txt def _fake_gpfs_get_state_not_active(self): inactive_txt = ('mmgetstate::HEADER:version:reserved:reserved:' 'nodeName:nodeNumber:state:quorum:nodesUp:totalNodes:' 'remarks:cnfsState:\n' 'mmgetstate::0:1:::hostname:1:down:1:1:' '1:quorum node:(undefined):') return inactive_txt def _fake_gpfs_compatible_cluster_release_level(self): release = 1400 return release def _fake_gpfs_incompatible_cluster_release_level(self): release = 1105 return release def _fake_gpfs_compatible_filesystem_release_level(self, path=None): release = 1400 fs = '/dev/gpfs' return fs, release def _fake_gpfs_incompatible_filesystem_release_level(self, path=None): release = 1105 fs = '/dev/gpfs' return fs, release def _fake_is_gpfs_path(self, path): pass def _fake_is_not_gpfs_path(self, path): raise(processutils.ProcessExecutionError('invalid gpfs path')) def _fake_convert_image(self, source, dest, out_format): utils.execute('cp', source, dest) def _fake_qemu_qcow2_image_info(self, path): data = FakeQemuImgInfo() data.file_format = 'qcow2' data.backing_file = None data.virtual_size = 1 * units.GiB return data def _fake_qemu_raw_image_info(self, path): data = FakeQemuImgInfo() data.file_format = 'raw' data.backing_file = None data.virtual_size = 1 * units.GiB return data def _fake_qemu_image_resize(self, path, size): LOG.info('wtf') pass def _fake_delete_gpfs_file(self, fchild): volume_path = fchild vol_name = os.path.basename(fchild) vol_id = vol_name.split('volume-').pop() utils.execute('rm', '-f', volume_path) utils.execute('rm', '-f', volume_path + '.snap') all_snaps = db.snapshot_get_all_for_volume(self.context, vol_id) for snap in all_snaps: snap_path = self.volumes_path + '/' + snap['name'] utils.execute('rm', '-f', snap_path)
class GPFSDriverTestCase(test.TestCase): driver_name = "cinder.volume.drivers.gpfs.GPFSDriver" context = context.get_admin_context() def _execute_wrapper(self, cmd, *args, **kwargs): try: kwargs.pop('run_as_root') except KeyError: pass return utils.execute(cmd, *args, **kwargs) def setUp(self): super(GPFSDriverTestCase, self).setUp() self.volumes_path = tempfile.mkdtemp(prefix="gpfs_") self.images_dir = '%s/images' % self.volumes_path if not os.path.exists(self.volumes_path): os.mkdir(self.volumes_path) if not os.path.exists(self.images_dir): os.mkdir(self.images_dir) self.image_id = '70a599e0-31e7-49b7-b260-868f441e862b' self.driver = GPFSDriver(configuration=conf.Configuration(None)) self.driver.set_execute(self._execute_wrapper) self.flags(volume_driver=self.driver_name, gpfs_mount_point_base=self.volumes_path) self.volume = importutils.import_object(CONF.volume_manager) self.volume.driver.set_execute(self._execute_wrapper) self.volume.driver.set_initialized() self.stubs.Set(GPFSDriver, '_create_gpfs_snap', self._fake_gpfs_snap) self.stubs.Set(GPFSDriver, '_create_gpfs_copy', self._fake_gpfs_copy) self.stubs.Set(GPFSDriver, '_gpfs_redirect', self._fake_gpfs_redirect) self.stubs.Set(GPFSDriver, '_is_gpfs_parent_file', self._fake_is_gpfs_parent) self.stubs.Set(GPFSDriver, '_is_gpfs_path', self._fake_is_gpfs_path) self.stubs.Set(GPFSDriver, '_delete_gpfs_file', self._fake_delete_gpfs_file) self.stubs.Set(GPFSDriver, '_create_sparse_file', self._fake_create_sparse_file) self.stubs.Set(GPFSDriver, '_allocate_file_blocks', self._fake_allocate_file_blocks) self.stubs.Set(GPFSDriver, '_get_available_capacity', self._fake_get_available_capacity) self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_qcow2_image_info) self.stubs.Set(image_utils, 'convert_image', self._fake_convert_image) self.stubs.Set(image_utils, 'resize_image', self._fake_qemu_image_resize) self.context = context.get_admin_context() self.context.user_id = 'fake' self.context.project_id = 'fake' CONF.gpfs_images_dir = self.images_dir def tearDown(self): try: os.rmdir(self.images_dir) os.rmdir(self.volumes_path) except OSError: pass super(GPFSDriverTestCase, self).tearDown() def test_create_delete_volume_full_backing_file(self): """create and delete vol with full creation method""" CONF.gpfs_sparse_volumes = False vol = test_utils.create_volume(self.context, host=CONF.host) volume_id = vol['id'] self.assertTrue(os.path.exists(self.volumes_path)) self.volume.create_volume(self.context, volume_id) path = self.volumes_path + '/' + vol['name'] self.assertTrue(os.path.exists(path)) self.volume.delete_volume(self.context, volume_id) self.assertFalse(os.path.exists(path)) def test_create_delete_volume_sparse_backing_file(self): """create and delete vol with default sparse creation method""" CONF.gpfs_sparse_volumes = True vol = test_utils.create_volume(self.context, host=CONF.host) volume_id = vol['id'] self.assertTrue(os.path.exists(self.volumes_path)) self.volume.create_volume(self.context, volume_id) path = self.volumes_path + '/' + vol['name'] self.assertTrue(os.path.exists(path)) self.volume.delete_volume(self.context, volume_id) self.assertFalse(os.path.exists(path)) def test_create_volume_with_attributes(self): self.stubs.Set(GPFSDriver, '_gpfs_change_attributes', self._fake_gpfs_change_attributes) attributes = { 'dio': 'yes', 'data_pool_name': 'ssd_pool', 'replicas': '2', 'write_affinity_depth': '1', 'block_group_factor': '1', 'write_affinity_failure-group': '1,1,1:2;2,1,1:2;2,0,3:4' } vol = test_utils.create_volume(self.context, host=CONF.host, metadata=attributes) volume_id = vol['id'] self.assertTrue(os.path.exists(self.volumes_path)) self.volume.create_volume(self.context, volume_id) path = self.volumes_path + '/' + vol['name'] self.assertTrue(os.path.exists(path)) self.volume.delete_volume(self.context, volume_id) self.assertFalse(os.path.exists(path)) def test_migrate_volume(self): """Test volume migration done by driver.""" loc = 'GPFSDriver:cindertest:openstack' cap = {'location_info': loc} host = {'host': 'foo', 'capabilities': cap} volume = test_utils.create_volume(self.context, host=CONF.host) self.driver.create_volume(volume) self.driver.migrate_volume(self.context, volume, host) self.driver.delete_volume(volume) def _create_snapshot(self, volume_id, size='0'): """Create a snapshot object.""" snap = {} snap['volume_size'] = size snap['user_id'] = 'fake' snap['project_id'] = 'fake' snap['volume_id'] = volume_id snap['status'] = "creating" return db.snapshot_create(context.get_admin_context(), snap) def test_create_delete_snapshot(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) snapCount = len( db.snapshot_get_all_for_volume(self.context, volume_src['id'])) self.assertEqual(snapCount, 0) snapshot = self._create_snapshot(volume_src['id']) snapshot_id = snapshot['id'] self.volume.create_snapshot(self.context, volume_src['id'], snapshot_id) self.assertTrue( os.path.exists(os.path.join(self.volumes_path, snapshot['name']))) snapCount = len( db.snapshot_get_all_for_volume(self.context, volume_src['id'])) self.assertEqual(snapCount, 1) self.volume.delete_snapshot(self.context, snapshot_id) self.volume.delete_volume(self.context, volume_src['id']) self.assertFalse( os.path.exists(os.path.join(self.volumes_path, snapshot['name']))) snapCount = len( db.snapshot_get_all_for_volume(self.context, volume_src['id'])) self.assertEqual(snapCount, 0) def test_create_volume_from_snapshot(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) snapshot = self._create_snapshot(volume_src['id']) snapshot_id = snapshot['id'] self.volume.create_snapshot(self.context, volume_src['id'], snapshot_id) self.assertTrue( os.path.exists(os.path.join(self.volumes_path, snapshot['name']))) volume_dst = test_utils.create_volume(self.context, host=CONF.host, snapshot_id=snapshot_id) self.volume.create_volume(self.context, volume_dst['id'], snapshot_id) self.assertEqual( volume_dst['id'], db.volume_get(context.get_admin_context(), volume_dst['id']).id) self.assertEqual( snapshot_id, db.volume_get(context.get_admin_context(), volume_dst['id']).snapshot_id) self.volume.delete_volume(self.context, volume_dst['id']) self.volume.delete_snapshot(self.context, snapshot_id) self.volume.delete_volume(self.context, volume_src['id']) def test_create_cloned_volume(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) volume_dst = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume_dst['name']) self.assertFalse(os.path.exists(volumepath)) self.driver.create_cloned_volume(volume_dst, volume_src) self.assertEqual( volume_dst['id'], db.volume_get(context.get_admin_context(), volume_dst['id']).id) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume_src['id']) self.volume.delete_volume(self.context, volume_dst['id']) def test_create_volume_from_snapshot_method(self): volume_src = test_utils.create_volume(self.context, host=CONF.host) self.volume.create_volume(self.context, volume_src['id']) snapshot = self._create_snapshot(volume_src['id']) snapshot_id = snapshot['id'] self.volume.create_snapshot(self.context, volume_src['id'], snapshot_id) volume_dst = test_utils.create_volume(self.context, host=CONF.host) self.driver.create_volume_from_snapshot(volume_dst, snapshot) self.assertEqual( volume_dst['id'], db.volume_get(context.get_admin_context(), volume_dst['id']).id) volumepath = os.path.join(self.volumes_path, volume_dst['name']) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_snapshot(self.context, snapshot_id) self.volume.delete_volume(self.context, volume_dst['id']) self.volume.delete_volume(self.context, volume_src['id']) def test_clone_image_to_volume_with_copy_on_write_mode(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using copy_on_write image sharing mode. """ # specify image file format is raw self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_raw_image_info) volume = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume['name']) CONF.gpfs_images_share_mode = 'copy_on_write' self.driver.clone_image(volume, None, self.image_id) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume['id']) self.assertFalse(os.path.exists(volumepath)) def test_clone_image_to_volume_with_copy_mode(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using copy image sharing mode. """ # specify image file format is raw self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_raw_image_info) volume = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume['name']) CONF.gpfs_images_share_mode = 'copy' self.driver.clone_image(volume, None, self.image_id) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume['id']) def test_copy_image_to_volume_with_non_gpfs_image_dir(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using a non gpfs glance images directory """ # specify image file format is raw self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_raw_image_info) for share_mode in ['copy_on_write', 'copy']: volume = test_utils.create_volume(self.context, host=CONF.host) volumepath = os.path.join(self.volumes_path, volume['name']) CONF.gpfs_images_share_mode = share_mode CONF.gpfs_images_dir = None self.driver.copy_image_to_volume(self.context, volume, FakeImageService(), self.image_id) self.assertTrue(os.path.exists(volumepath)) self.volume.delete_volume(self.context, volume['id']) def test_copy_image_to_volume_with_illegal_image_format(self): """Test the function of copy_image_to_volume focusing on the integretion of the image_util using an illegal image file format """ # specify image file format is qcow2 self.stubs.Set(image_utils, 'qemu_img_info', self._fake_qemu_qcow2_image_info) volume = test_utils.create_volume(self.context, host=CONF.host) CONF.gpfs_images_share_mode = 'copy' CONF.gpfs_images_dir = self.images_dir self.assertRaises(exception.ImageUnacceptable, self.driver.copy_image_to_volume, self.context, volume, FakeImageService(), self.image_id) self.volume.delete_volume(self.context, volume['id']) def test_get_volume_stats(self): stats = self.driver.get_volume_stats() self.assertEqual(stats['volume_backend_name'], 'GPFS') self.assertEqual(stats['storage_protocol'], 'file') def test_extend_volume(self): new_vol_size = 15 mox = mox_lib.Mox() volume = test_utils.create_volume(self.context, host=CONF.host) volpath = os.path.join(self.volumes_path, volume['name']) qemu_img_info_output = """image: %s file format: raw virtual size: %sG (%s bytes) backing file: %s """ % (volume['name'], new_vol_size, new_vol_size * units.GiB, volpath) mox.StubOutWithMock(image_utils, 'resize_image') image_utils.resize_image(volpath, new_vol_size) mox.StubOutWithMock(image_utils, 'qemu_img_info') img_info = imageutils.QemuImgInfo(qemu_img_info_output) image_utils.qemu_img_info(volpath).AndReturn(img_info) mox.ReplayAll() self.driver.extend_volume(volume, new_vol_size) mox.VerifyAll() def test_extend_volume_with_failure(self): new_vol_size = 15 mox = mox_lib.Mox() volume = test_utils.create_volume(self.context, host=CONF.host) volpath = os.path.join(self.volumes_path, volume['name']) mox.StubOutWithMock(image_utils, 'resize_image') image_utils.resize_image(volpath, new_vol_size).AndRaise( processutils.ProcessExecutionError('error')) mox.ReplayAll() self.assertRaises(exception.VolumeBackendAPIException, self.driver.extend_volume, volume, new_vol_size) mox.VerifyAll() def test_check_for_setup_error_ok(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_compatible_cluster_release_level) self.stubs.Set(GPFSDriver, '_get_gpfs_filesystem_release_level', self._fake_gpfs_compatible_filesystem_release_level) self.driver.check_for_setup_error() def test_check_for_setup_error_gpfs_not_active(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_not_active) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def test_check_for_setup_error_not_gpfs_path(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_is_gpfs_path', self._fake_is_not_gpfs_path) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_compatible_cluster_release_level) self.stubs.Set(GPFSDriver, '_get_gpfs_filesystem_release_level', self._fake_gpfs_compatible_filesystem_release_level) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def test_check_for_setup_error_incompatible_cluster_version(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_incompatible_cluster_release_level) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def test_check_for_setup_error_incompatible_filesystem_version(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) self.stubs.Set(GPFSDriver, '_get_gpfs_cluster_release_level', self._fake_gpfs_compatible_cluster_release_level) self.stubs.Set(GPFSDriver, '_get_gpfs_filesystem_release_level', self._fake_gpfs_incompatible_filesystem_release_level) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) def _fake_create_file(self, path, modebits='666'): open(path, 'w').close() utils.execute('chmod', modebits, path) def _fake_gpfs_snap(self, src, dest=None, modebits='644'): if dest is None: dest = src self._fake_create_file(dest, '644') def _fake_gpfs_copy(self, src, dest): self._fake_create_file(dest) def _fake_create_sparse_file(self, path, size): self._fake_create_file(path) def _fake_allocate_file_blocks(self, path, size): self._fake_create_file(path) def _fake_gpfs_change_attributes(self, options, path): pass def _fake_gpfs_redirect(self, src): return True def _fake_is_gpfs_parent(self, gpfs_file): return False def _fake_get_available_capacity(self, path): fake_avail = 80 * units.GiB fake_size = 2 * fake_avail return fake_avail, fake_size def _fake_gpfs_get_state_active(self): active_txt = ('mmgetstate::HEADER:version:reserved:reserved:' 'nodeName:nodeNumber:state:quorum:nodesUp:totalNodes:' 'remarks:cnfsState:\n' 'mmgetstate::0:1:::hostname:1:active:1:1:' '1:quorum node:(undefined):') return active_txt def _fake_gpfs_get_state_not_active(self): inactive_txt = ('mmgetstate::HEADER:version:reserved:reserved:' 'nodeName:nodeNumber:state:quorum:nodesUp:totalNodes:' 'remarks:cnfsState:\n' 'mmgetstate::0:1:::hostname:1:down:1:1:' '1:quorum node:(undefined):') return inactive_txt def _fake_gpfs_compatible_cluster_release_level(self): release = 1400 return release def _fake_gpfs_incompatible_cluster_release_level(self): release = 1105 return release def _fake_gpfs_compatible_filesystem_release_level(self, path=None): release = 1400 fs = '/dev/gpfs' return fs, release def _fake_gpfs_incompatible_filesystem_release_level(self, path=None): release = 1105 fs = '/dev/gpfs' return fs, release def _fake_is_gpfs_path(self, path): pass def _fake_is_not_gpfs_path(self, path): raise (processutils.ProcessExecutionError('invalid gpfs path')) def _fake_convert_image(self, source, dest, out_format): utils.execute('cp', source, dest) def _fake_qemu_qcow2_image_info(self, path): data = FakeQemuImgInfo() data.file_format = 'qcow2' data.backing_file = None data.virtual_size = 1 * units.GiB return data def _fake_qemu_raw_image_info(self, path): data = FakeQemuImgInfo() data.file_format = 'raw' data.backing_file = None data.virtual_size = 1 * units.GiB return data def _fake_qemu_image_resize(self, path, size): LOG.info('wtf') pass def _fake_delete_gpfs_file(self, fchild): volume_path = fchild vol_name = os.path.basename(fchild) vol_id = vol_name.split('volume-').pop() utils.execute('rm', '-f', volume_path) utils.execute('rm', '-f', volume_path + '.snap') all_snaps = db.snapshot_get_all_for_volume(self.context, vol_id) for snap in all_snaps: snap_path = self.volumes_path + '/' + snap['name'] utils.execute('rm', '-f', snap_path)