From: Simon Lorenz Date: Fri, 7 Mar 2014 15:08:13 +0000 (+0100) Subject: GPFS unit tests: increased coverage, uses mock X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=23ff56fd47cc7f8b7633573a1e94357985256b14;p=openstack-build%2Fcinder-build.git GPFS unit tests: increased coverage, uses mock Increased unit tests coverage for the GPFS driver 100%. All tests make usage of mock. This helped to uncover bugs in the error path (see 1289382). Closes-bug: 1290921 Change-Id: Ic78ac9b49c6e22231b966052f65d8ae07824379e --- diff --git a/cinder/tests/test_gpfs.py b/cinder/tests/test_gpfs.py index cac3c02a0..b5d0d978b 100644 --- a/cinder/tests/test_gpfs.py +++ b/cinder/tests/test_gpfs.py @@ -20,40 +20,23 @@ import tempfile from oslo.config import cfg from cinder import context -from cinder import db from cinder import exception -from cinder.image import image_utils -from cinder.openstack.common import imageutils from cinder.openstack.common import log as logging from cinder.openstack.common import processutils from cinder import test -from cinder.tests import utils as test_utils from cinder import units from cinder import utils from cinder.volume import configuration as conf from cinder.volume.drivers.ibm import gpfs from cinder.volume import volume_types +from mock import patch + LOG = logging.getLogger(__name__) CONF = cfg.CONF -class FakeImageService(): - def update(self, context, image_id, path): - pass - - def show(self, context, image_id): - image_meta = {'disk_format': None, - 'container_format': None} - return image_meta - - def download(self, context, image_id, image_fd): - for b in range(256): - image_fd.write('some_image_data') - image_fd.close() - - class FakeQemuImgInfo(object): def __init__(self): self.file_format = None @@ -69,6 +52,7 @@ class GPFSDriverTestCase(test.TestCase): kwargs.pop('run_as_root') except KeyError: pass + return utils.execute(cmd, *args, **kwargs) def setUp(self): @@ -91,31 +75,6 @@ class GPFSDriverTestCase(test.TestCase): self.flags(volume_driver=self.driver_name, gpfs_mount_point_base=self.volumes_path) - self.stubs.Set(gpfs.GPFSDriver, '_create_gpfs_snap', - self._fake_gpfs_snap) - self.stubs.Set(gpfs.GPFSDriver, '_create_gpfs_copy', - self._fake_gpfs_copy) - self.stubs.Set(gpfs.GPFSDriver, '_gpfs_redirect', - self._fake_gpfs_redirect) - self.stubs.Set(gpfs.GPFSDriver, '_is_gpfs_parent_file', - self._fake_is_gpfs_parent) - self.stubs.Set(gpfs.GPFSDriver, '_is_gpfs_path', - self._fake_is_gpfs_path) - self.stubs.Set(gpfs.GPFSDriver, '_delete_gpfs_file', - self._fake_delete_gpfs_file) - self.stubs.Set(gpfs.GPFSDriver, '_create_sparse_file', - self._fake_create_sparse_file) - self.stubs.Set(gpfs.GPFSDriver, '_allocate_file_blocks', - self._fake_allocate_file_blocks) - self.stubs.Set(gpfs.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' @@ -129,575 +88,1312 @@ class GPFSDriverTestCase(test.TestCase): 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.driver.create_volume(vol) - path = self.volumes_path + '/' + vol['name'] - self.assertTrue(os.path.exists(path)) - self.driver.delete_volume(vol) - 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) - self.assertTrue(os.path.exists(self.volumes_path)) - self.driver.create_volume(vol) - path = self.volumes_path + '/' + vol['name'] - self.assertTrue(os.path.exists(path)) - self.driver.delete_volume(vol) - self.assertFalse(os.path.exists(path)) - - def test_create_volume_with_attributes(self): - self.stubs.Set(gpfs.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) - self.assertTrue(os.path.exists(self.volumes_path)) - self.driver.create_volume(vol) - path = self.volumes_path + '/' + vol['name'] - self.assertTrue(os.path.exists(path)) - self.driver.delete_volume(vol) - self.assertFalse(os.path.exists(path)) - - def test_migrate_volume_local(self): - """Verify volume migration performed locally by driver.""" + def test_different(self): + self.assertTrue(gpfs._different((True, False))) + self.assertFalse(gpfs._different((True, True))) + self.assertFalse(gpfs._different(None)) + + def test_sizestr(self): + self.assertEqual(gpfs._sizestr('0'), '100M') + self.assertEqual(gpfs._sizestr('10'), '10G') + + @patch('cinder.utils.execute') + def test_get_gpfs_state_ok(self, mock_exec): + mock_exec.return_value = ('mmgetstate::HEADER:version:reserved:' + 'reserved:nodeName:nodeNumber:state:quorum:' + 'nodesUp:totalNodes:remarks:cnfsState:\n' + 'mmgetstate::0:1:::devstack:3:active:2:3:3:' + 'quorum node:(undefined):', '') + self.assertEqual(True, self.driver._get_gpfs_state().splitlines()[1]. + startswith('mmgetstate::0:1:::devstack')) + + @patch('cinder.utils.execute') + def test_get_gpfs_state_fail_mmgetstate(self, mock_exec): + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_gpfs_state) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_gpfs_state') + def test_check_gpfs_state_ok(self, mock_get_gpfs_state): + mock_get_gpfs_state.return_value = ('mmgetstate::HEADER:version:' + 'reserved:reserved:nodeName:' + 'nodeNumber:state:quorum:nodesUp:' + 'totalNodes:remarks:cnfsState:\n' + 'mmgetstate::0:1:::devstack:3:' + 'active:2:3:3:' + 'quorum node:(undefined):') + self.driver._check_gpfs_state() + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_gpfs_state') + def test_check_gpfs_state_fail_not_active(self, mock_get_gpfs_state): + mock_get_gpfs_state.return_value = ('mmgetstate::HEADER:version:' + 'reserved:reserved:nodeName:' + 'nodeNumber:state:quorum:nodesUp:' + 'totalNodes:remarks:cnfsState:\n' + 'mmgetstate::0:1:::devstack:3:' + 'arbitrating:2:3:3:' + 'quorum node:(undefined):') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._check_gpfs_state) + + @patch('cinder.utils.execute') + def test_get_fs_from_path_ok(self, mock_exec): ctxt = self.context - migrated_by_driver = True - volume = test_utils.create_volume(ctxt, host=CONF.host) - with mock.patch('cinder.utils.execute'): - LOG.debug('Migrate same cluster, different path, ' - 'move file to new path.') - loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id - cap = {'location_info': loc} - host = {'host': 'foo', 'capabilities': cap} - self.driver.create_volume(volume) - migr, updt = self.driver.migrate_volume(ctxt, volume, host) - self.assertEqual(migr, migrated_by_driver) - self.driver.delete_volume(volume) - LOG.debug('Migrate same cluster, different path, ' - 'move file to new path, rv = %s.' % migr) - - LOG.debug('Migrate same cluster, same path, no action taken.') - gpfs_base = self.driver.configuration.gpfs_mount_point_base - loc = 'GPFSDriver:%s:%s' % (self.driver._cluster_id, gpfs_base) - cap = {'location_info': loc} - host = {'host': 'foo', 'capabilities': cap} - self.driver.create_volume(volume) - migr, updt = self.driver.migrate_volume(ctxt, volume, host) - self.assertEqual(migr, migrated_by_driver) - self.driver.delete_volume(volume) - LOG.debug('Migrate same cluster, same path, no action taken, ' - 'rv = %s' % migr) - - def test_migrate_volume_generic(self): - """Verify cases where driver cannot perform migration locally.""" + mock_exec.return_value = ('Filesystem 1K-blocks ' + 'Used Available Use%% Mounted on\n' + '%s 10485760 531968 9953792' + ' 6%% /gpfs0' % self.driver._gpfs_device, + '') + self.assertEqual(self.driver._gpfs_device, + self.driver._get_filesystem_from_path('/gpfs0')) + + @patch('cinder.utils.execute') + def test_get_fs_from_path_fail_path(self, mock_exec): ctxt = self.context - migrated_by_driver = False - volume = test_utils.create_volume(ctxt, host=CONF.host) - with mock.patch('cinder.utils.execute'): - LOG.debug('Migrate request for different cluster, return false ' - 'for generic migration.') - other_cluster_id = '000000' - loc = 'GPFSDriver:%s:testpath' % other_cluster_id - cap = {'location_info': loc} - host = {'host': 'foo', 'capabilities': cap} - self.driver.create_volume(volume) - migr, updt = self.driver.migrate_volume(ctxt, volume, host) - self.assertEqual(migr, migrated_by_driver) - self.driver.delete_volume(volume) - LOG.debug('Migrate request for different cluster, rv = %s.' % migr) - - LOG.debug('Migrate request with no location info, return false ' - 'for generic migration.') - host = {'host': 'foo', 'capabilities': {}} - self.driver.create_volume(volume) - migr, updt = self.driver.migrate_volume(ctxt, volume, host) - self.assertEqual(migr, migrated_by_driver) - self.driver.delete_volume(volume) - LOG.debug('Migrate request with no location info, rv = %s.' % migr) - - LOG.debug('Migrate request with bad location info, return false ' - 'for generic migration.') - bad_loc = 'GPFSDriver:testpath' - cap = {'location_info': bad_loc} - host = {'host': 'foo', 'capabilities': cap} - self.driver.create_volume(volume) - migr, updt = self.driver.migrate_volume(ctxt, volume, host) - self.assertEqual(migr, migrated_by_driver) - self.driver.delete_volume(volume) - LOG.debug('Migrate request with bad location info, rv = %s.' % - migr) - - def test_retype_volume_different_pool(self): + mock_exec.return_value = ('Filesystem 1K-blocks ' + 'Used Available Use% Mounted on\n' + 'test 10485760 531968 ' + '9953792 6% /gpfs0', '') + self.assertNotEqual(self.driver._gpfs_device, + self.driver._get_filesystem_from_path('/gpfs0')) + + @patch('cinder.utils.execute') + def test_get_fs_from_path_fail_raise(self, mock_exec): ctxt = self.context - loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id - cap = {'location_info': loc} - host = {'host': 'foo', 'capabilities': cap} - - key_specs_old = {'capabilities:storage_pool': 'bronze', - 'volume_backend_name': 'backend1'} - key_specs_new = {'capabilities:storage_pool': 'gold', - 'volume_backend_name': 'backend1'} - old_type_ref = volume_types.create(ctxt, 'old', key_specs_old) - new_type_ref = volume_types.create(ctxt, 'new', key_specs_new) - - old_type = volume_types.get_volume_type(ctxt, old_type_ref['id']) - new_type = volume_types.get_volume_type(ctxt, new_type_ref['id']) + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_filesystem_from_path, '/gpfs0') - diff, equal = volume_types.volume_types_diff(ctxt, - old_type_ref['id'], - new_type_ref['id']) + @patch('cinder.utils.execute') + def test_get_gpfs_cluster_id_ok(self, mock_exec): + ctxt = self.context + mock_exec.return_value = ('mmlsconfig::HEADER:version:reserved:' + 'reserved:configParameter:value:nodeList:\n' + 'mmlsconfig::0:1:::clusterId:%s::' + % self.driver._cluster_id, '') + self.assertEqual(self.driver._cluster_id, + self.driver._get_gpfs_cluster_id()) + + @patch('cinder.utils.execute') + def test_get_gpfs_cluster_id_fail_id(self, mock_exec): + ctxt = self.context + mock_exec.return_value = ('mmlsconfig::HEADER.:version:reserved:' + 'reserved:configParameter:value:nodeList:\n' + 'mmlsconfig::0:1:::clusterId:test::', '') + self.assertNotEqual(self.driver._cluster_id, + self.driver._get_gpfs_cluster_id()) + + @patch('cinder.utils.execute') + def test_get_gpfs_cluster_id_fail_raise(self, mock_exec): + ctxt = self.context + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_gpfs_cluster_id) + + @patch('cinder.utils.execute') + def test_get_fileset_from_path_ok(self, mock_exec): + mock_exec.return_value = ('file name: /gpfs0\n' + 'metadata replication: 1 max 2\n' + 'data replication: 1 max 2\n' + 'immutable: no\n' + 'appendOnly: no\n' + 'flags:\n' + 'storage pool name: system\n' + 'fileset name: root\n' + 'snapshot name:\n' + 'Windows attributes: DIRECTORY', '') + self.driver._get_fileset_from_path('') + + @patch('cinder.utils.execute') + def test_get_fileset_from_path_fail_mmlsattr(self, mock_exec): + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_fileset_from_path, '') + + @patch('cinder.utils.execute') + def test_get_fileset_from_path_fail_find_fileset(self, mock_exec): + mock_exec.return_value = ('file name: /gpfs0\n' + 'metadata replication: 1 max 2\n' + 'data replication: 1 max 2\n' + 'immutable: no\n' + 'appendOnly: no\n' + 'flags:\n' + 'storage pool name: system\n' + '*** name: root\n' + 'snapshot name:\n' + 'Windows attributes: DIRECTORY', '') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_fileset_from_path, '') - # set volume host to match target host - volume = test_utils.create_volume(ctxt, host=host['host']) - volume['volume_type_id'] = old_type['id'] - with mock.patch('cinder.utils.execute'): - LOG.debug('Retype different pools, expected rv = True.') - self.driver.create_volume(volume) - rv = self.driver.retype(ctxt, volume, new_type, diff, host) - self.assertTrue(rv) - self.driver.delete_volume(volume) - LOG.debug('Retype different pools, rv = %s.' % rv) - - def test_retype_volume_different_host(self): + @patch('cinder.utils.execute') + def test_verify_gpfs_pool_ok(self, mock_exec): ctxt = self.context - loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id + mock_exec.return_value = ('Storage pools in file system at \'/gpfs0\':' + '\n' + 'Name Id BlkSize Data ' + 'Meta ' + 'Total Data in (KB) Free Data in (KB) ' + 'Total Meta in (KB) Free Meta in (KB)\n' + 'system 0 256 KB yes ' + 'yes ' + ' 10485760 9953792 ( 95%) ' + '10485760 9954560 ( 95%)', '') + self.assertTrue(self.driver._gpfs_device, + self.driver._verify_gpfs_pool('/dev/gpfs')) + + @patch('cinder.utils.execute') + def test_verify_gpfs_pool_fail_pool(self, mock_exec): + ctxt = self.context + mock_exec.return_value = ('Storage pools in file system at \'/gpfs0\':' + '\n' + 'Name Id BlkSize Data ' + 'Meta ' + 'Total Data in (KB) Free Data in (KB) ' + 'Total Meta in (KB) Free Meta in (KB)\n' + 'test 0 256 KB yes ' + 'yes' + ' 10485760 9953792 ( 95%)' + ' 10485760 9954560 ( 95%)', '') + self.assertTrue(self.driver._gpfs_device, + self.driver._verify_gpfs_pool('/dev/gpfs')) + + @patch('cinder.utils.execute') + def test_verify_gpfs_pool_fail_raise(self, mock_exec): + ctxt = self.context + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + self.assertFalse(self.driver._verify_gpfs_pool('/dev/gpfs')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.utils.execute') + def test_update_volume_storage_pool_ok(self, mock_exec, mock_verify_pool): + mock_verify_pool.return_value = True + self.assertTrue(self.driver._update_volume_storage_pool('', 'system')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.utils.execute') + def test_update_volume_storage_pool_ok_pool_none(self, + mock_exec, + mock_verify_pool): + mock_verify_pool.return_value = True + self.assertTrue(self.driver._update_volume_storage_pool('', None)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.utils.execute') + def test_update_volume_storage_pool_fail_pool(self, + mock_exec, + mock_verify_pool): + mock_verify_pool.return_value = False + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._update_volume_storage_pool, + '', + 'system') + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.utils.execute') + def test_update_volume_storage_pool_fail_mmchattr(self, + mock_exec, + mock_verify_pool): + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + mock_verify_pool.return_value = True + self.assertFalse(self.driver._update_volume_storage_pool('', 'system')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_filesystem_from_path') + @patch('cinder.utils.execute') + def test_get_gpfs_fs_release_level_ok(self, + mock_exec, + mock_fs_from_path): + mock_exec.return_value = ('mmlsfs::HEADER:version:reserved:reserved:' + 'deviceName:fieldName:data:remarks:\n' + 'mmlsfs::0:1:::gpfs:filesystemVersion:14.03 ' + '(4.1.0.0):\n' + 'mmlsfs::0:1:::gpfs:filesystemVersionLocal:' + '14.03 (4.1.0.0):\n' + 'mmlsfs::0:1:::gpfs:filesystemVersionManager' + ':14.03 (4.1.0.0):\n' + 'mmlsfs::0:1:::gpfs:filesystemVersion' + 'Original:14.03 (4.1.0.0):\n' + 'mmlsfs::0:1:::gpfs:filesystemHighest' + 'Supported:14.03 (4.1.0.0):', '') + mock_fs_from_path.return_value = '/dev/gpfs' + self.assertEqual(('/dev/gpfs', 1403), + self.driver._get_gpfs_fs_release_level('')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_filesystem_from_path') + @patch('cinder.utils.execute') + def test_get_gpfs_fs_release_level_fail_mmlsfs(self, + mock_exec, + mock_fs_from_path): + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + mock_fs_from_path.return_value = '/dev/gpfs' + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_gpfs_fs_release_level, '') + + @patch('cinder.utils.execute') + def test_get_gpfs_cluster_release_level_ok(self, mock_exec): + mock_exec.return_value = ('mmlsconfig::HEADER:version:reserved:' + 'reserved:configParameter:value:nodeList:\n' + 'mmlsconfig::0:1:::minReleaseLevel:1403::', + '') + self.assertEqual(1403, self.driver._get_gpfs_cluster_release_level()) + + @patch('cinder.utils.execute') + def test_get_gpfs_cluster_release_level_fail_mmlsconfig(self, mock_exec): + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._get_gpfs_cluster_release_level) + + @patch('cinder.utils.execute') + def test_is_gpfs_path_fail_mmlsattr(self, mock_exec): + mock_exec.side_effect = processutils.ProcessExecutionError( + stdout='test', stderr='test') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._is_gpfs_path, '/dummy/path') + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_fileset_from_path') + @patch('cinder.utils.execute') + def test_is_same_fileset_ok(self, + mock_exec, + mock_get_fileset_from_path): + mock_get_fileset_from_path.return_value = True + self.assertTrue(self.driver._is_same_fileset('', '')) + mock_get_fileset_from_path.side_effect = [True, False] + self.assertFalse(self.driver._is_same_fileset('', '')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_available_capacity') + @patch('cinder.utils.execute') + def test_same_cluster_ok(self, mock_exec, mock_avail_capacity): + mock_avail_capacity.return_value = (10192683008, 10737418240) + stats = self.driver.get_volume_stats() + loc = stats['location_info'] cap = {'location_info': loc} host = {'host': 'foo', 'capabilities': cap} + self.assertTrue(self.driver._same_cluster(host)) - newloc = 'GPFSDriver:000000:testpath' - newcap = {'location_info': newloc} - newhost = {'host': 'foo', 'capabilities': newcap} - - key_specs_old = {'capabilities:storage_pool': 'bronze', - 'volume_backend_name': 'backend1'} - old_type_ref = volume_types.create(ctxt, 'old', key_specs_old) - old_type = volume_types.get_volume_type(ctxt, old_type_ref['id']) - diff, equal = volume_types.volume_types_diff(ctxt, - old_type_ref['id'], - old_type_ref['id']) - # set volume host to be different from target host - volume = test_utils.create_volume(ctxt, host=CONF.host) - volume['volume_type_id'] = old_type['id'] - - with mock.patch('cinder.utils.execute'): - LOG.debug('Retype different hosts same cluster, ' - 'expected rv = True.') - self.driver.db = mock.Mock() - self.driver.create_volume(volume) - rv = self.driver.retype(ctxt, volume, old_type, diff, host) - self.assertTrue(rv) - self.driver.delete_volume(volume) - LOG.debug('Retype different hosts same cluster, rv = %s.' % rv) - - LOG.debug('Retype different hosts, different cluster, ' - 'cannot migrate. Expected rv = False.') - self.driver.create_volume(volume) - rv = self.driver.retype(ctxt, volume, old_type, diff, newhost) - self.assertFalse(rv) - self.driver.delete_volume(volume) - LOG.debug('Retype different hosts, different cluster, ' - 'cannot migrate, rv = %s.' % rv) - - def test_retype_volume_different_pool_and_host(self): - ctxt = self.context - loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id + locinfo = stats['location_info'] + '_' + loc = locinfo cap = {'location_info': loc} host = {'host': 'foo', 'capabilities': cap} + self.assertFalse(self.driver._same_cluster(host)) - key_specs_old = {'capabilities:storage_pool': 'bronze', - 'volume_backend_name': 'backend1'} - key_specs_new = {'capabilities:storage_pool': 'gold', - 'volume_backend_name': 'backend1'} - old_type_ref = volume_types.create(ctxt, 'old', key_specs_old) - new_type_ref = volume_types.create(ctxt, 'new', key_specs_new) - - old_type = volume_types.get_volume_type(ctxt, old_type_ref['id']) - new_type = volume_types.get_volume_type(ctxt, new_type_ref['id']) + @patch('cinder.utils.execute') + def test_set_rw_permission(self, mock_exec): + self.driver._set_rw_permission('') - diff, equal = volume_types.volume_types_diff(ctxt, - old_type_ref['id'], - new_type_ref['id']) + @patch('cinder.utils.execute') + def test_can_migrate_locally(self, mock_exec): + host = {'host': 'foo', 'capabilities': ''} + self.assertEqual(self.driver._can_migrate_locally(host), None) - # set volume host to be different from target host - volume = test_utils.create_volume(ctxt, host=CONF.host) - volume['volume_type_id'] = old_type['id'] - - with mock.patch('cinder.utils.execute'): - # different host different pool - LOG.debug('Retype different pools and hosts, expected rv = True.') - self.driver.db = mock.Mock() - self.driver.create_volume(volume) - rv = self.driver.retype(ctxt, volume, new_type, diff, host) - self.assertTrue(rv) - self.driver.delete_volume(volume) - LOG.debug('Retype different pools and hosts, rv = %s.' % rv) - - def test_retype_volume_different_backend(self): - ctxt = self.context - loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id + loc = 'GPFSDriver:%s' % self.driver._cluster_id cap = {'location_info': loc} host = {'host': 'foo', 'capabilities': cap} + self.assertEqual(self.driver._can_migrate_locally(host), None) - key_specs_old = {'capabilities:storage_pool': 'bronze', - 'volume_backend_name': 'backend1'} - key_specs_new = {'capabilities:storage_pool': 'gold', - 'volume_backend_name': 'backend2'} - - old_type_ref = volume_types.create(ctxt, 'old', key_specs_old) - new_type_ref = volume_types.create(ctxt, 'new', key_specs_new) - - old_type = volume_types.get_volume_type(ctxt, old_type_ref['id']) - new_type = volume_types.get_volume_type(ctxt, new_type_ref['id']) - - diff, equal = volume_types.volume_types_diff(ctxt, - old_type_ref['id'], - new_type_ref['id']) - # set volume host to match target host - volume = test_utils.create_volume(ctxt, host=host['host']) - volume['volume_type_id'] = old_type['id'] - - with mock.patch('cinder.utils.execute'): - LOG.debug('Retype different backends, cannot migrate. ' - 'Expected rv = False.') - self.driver.create_volume(volume) - rv = self.driver.retype(ctxt, volume, old_type, diff, host) - self.assertFalse(rv) - self.driver.delete_volume(volume) - LOG.debug('Retype different backends, cannot migrate, ' - 'rv = %s.' % rv) - - 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.driver.create_volume(volume_src) - snapCount = len(db.snapshot_get_all_for_volume(self.context, - volume_src['id'])) - snapshot = self._create_snapshot(volume_src['id']) - self.driver.create_snapshot(snapshot) - self.assertTrue(os.path.exists(os.path.join(self.volumes_path, - snapshot['name']))) - self.driver.delete_snapshot(snapshot) - self.driver.delete_volume(volume_src) - self.assertFalse(os.path.exists(os.path.join(self.volumes_path, - snapshot['name']))) - - def test_create_volume_from_snapshot(self): - volume_src = test_utils.create_volume(self.context, host=CONF.host) - self.driver.create_volume(volume_src) - snapshot = self._create_snapshot(volume_src['id']) - snapshot_id = snapshot['id'] - self.driver.create_snapshot(snapshot) - 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.driver.create_volume_from_snapshot(volume_dst, snapshot) - 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.driver.delete_volume(volume_dst) + loc = 'GPFSDriver_:%s:testpath' % self.driver._cluster_id + cap = {'location_info': loc} + host = {'host': 'foo', 'capabilities': cap} + self.assertEqual(self.driver._can_migrate_locally(host), None) - self.driver.delete_snapshot(snapshot) - self.driver.delete_volume(volume_src) - - def test_create_cloned_volume(self): - volume_src = test_utils.create_volume(self.context, host=CONF.host) - self.driver.create_volume(volume_src) - - 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.driver.delete_volume(volume_src) - self.driver.delete_volume(volume_dst) - - def test_create_volume_from_snapshot_method(self): - volume_src = test_utils.create_volume(self.context, host=CONF.host) - snapshot = self._create_snapshot(volume_src['id']) - snapshot_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.driver.delete_volume(volume_dst) - - 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.driver.delete_volume(volume) - 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)) - - 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)) - - 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) + loc = 'GPFSDriver:%s:testpath' % (self.driver._cluster_id + '_') + cap = {'location_info': loc} + host = {'host': 'foo', 'capabilities': cap} + self.assertEqual(self.driver._can_migrate_locally(host), None) - 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 - volume = test_utils.create_volume(self.context, host=CONF.host) - with mock.patch('cinder.image.image_utils.resize_image'): - with mock.patch('cinder.image.image_utils.qemu_img_info'): - self.driver.extend_volume(volume, new_vol_size) - - def test_extend_volume_with_failure(self): - new_vol_size = 15 - volume = test_utils.create_volume(self.context, host=CONF.host) - volpath = os.path.join(self.volumes_path, volume['name']) - - with mock.patch('cinder.image.image_utils.resize_image') as resize: - with mock.patch('cinder.image.image_utils.qemu_img_info'): - resize.side_effect = processutils.ProcessExecutionError('err') - self.assertRaises(exception.VolumeBackendAPIException, - self.driver.extend_volume, - volume, - new_vol_size) - - def test_resize_volume(self): - new_vol_size = 15 - new_vol_size_bytes = new_vol_size * units.GiB - 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_bytes, volpath) - img_info = imageutils.QemuImgInfo(qemu_img_info_output) - - with mock.patch('cinder.image.image_utils.resize_image'): - with mock.patch('cinder.image.image_utils.qemu_img_info') as info: - info.return_value = img_info - rv = self.driver._resize_volume_file(volume, new_vol_size) - self.assertEqual(rv, new_vol_size_bytes) - - def test_check_for_setup_error_ok(self): - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_state', - self._fake_gpfs_get_state_active) - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_cluster_release_level', - self._fake_gpfs_compatible_cluster_release_level) - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_fs_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(gpfs.GPFSDriver, '_get_gpfs_state', - self._fake_gpfs_get_state_not_active) + loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id + cap = {'location_info': loc} + host = {'host': 'foo', 'capabilities': cap} + self.assertEqual(self.driver._can_migrate_locally(host), 'testpath') + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_filesystem_from_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_gpfs_cluster_id') + @patch('cinder.utils.execute') + def test_do_setup_ok(self, + mock_exec, + mock_get_gpfs_cluster_id, + mock_get_filesystem_from_path, + mock_verify_gpfs_pool): + ctxt = self.context + mock_get_gpfs_cluster_id.return_value = self.driver._cluster_id + mock_get_filesystem_from_path.return_value = '/dev/gpfs' + mock_verify_gpfs_pool.return_value = True + self.driver.do_setup(ctxt) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_filesystem_from_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_gpfs_cluster_id') + @patch('cinder.utils.execute') + def test_do_setup_fail_get_cluster_id(self, + mock_exec, + mock_get_gpfs_cluster_id, + mock_get_filesystem_from_path, + mock_verify_gpfs_pool): + ctxt = self.context + mock_get_gpfs_cluster_id.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + mock_get_filesystem_from_path.return_value = '/dev/gpfs' + mock_verify_gpfs_pool.return_value = True self.assertRaises(exception.VolumeBackendAPIException, - self.driver.check_for_setup_error) - - def test_check_for_setup_error_not_gpfs_path(self): - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_state', - self._fake_gpfs_get_state_active) - self.stubs.Set(gpfs.GPFSDriver, '_is_gpfs_path', - self._fake_is_not_gpfs_path) - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_cluster_release_level', - self._fake_gpfs_compatible_cluster_release_level) - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_fs_release_level', - self._fake_gpfs_compatible_filesystem_release_level) + self.driver.do_setup, ctxt) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_filesystem_from_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_gpfs_cluster_id') + @patch('cinder.utils.execute') + def test_do_setup_fail_get_fs_from_path(self, + mock_exec, + mock_get_gpfs_cluster_id, + mock_get_fs_from_path, + mock_verify_gpfs_pool): + ctxt = self.context + mock_get_gpfs_cluster_id.return_value = self.driver._cluster_id + mock_get_fs_from_path.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + mock_verify_gpfs_pool.return_value = True + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.do_setup, ctxt) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_pool') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_filesystem_from_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._get_gpfs_cluster_id') + @patch('cinder.utils.execute') + def test_do_setup_fail_volume(self, + mock_exec, + mock_get_gpfs_cluster_id, + mock_get_filesystem_from_path, + mock_verify_gpfs_pool): + ctxt = self.context + mock_get_gpfs_cluster_id. return_value = self.driver._cluster_id + mock_get_filesystem_from_path.return_value = '/dev/gpfs' + mock_verify_gpfs_pool.return_value = False + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.do_setup, ctxt) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._check_gpfs_state') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_fs_release_level') + def test_check_for_setup_error_fail_conf(self, + mock_get_gpfs_fs_rel_lev, + mock_is_gpfs_path, + mock_check_gpfs_state): + fake_fs = '/dev/gpfs' + fake_fs_release = 1400 + fake_cluster_release = 1201 + + # fail configuration.gpfs_mount_point_base is None + org_value = self.driver.configuration.gpfs_mount_point_base + self.flags(volume_driver=self.driver_name, gpfs_mount_point_base=None) + mock_get_gpfs_fs_rel_lev.return_value = (fake_fs, fake_fs_release) self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=org_value) - def test_check_for_setup_error_incompatible_cluster_version(self): - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_state', - self._fake_gpfs_get_state_active) - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_cluster_release_level', - self._fake_gpfs_incompatible_cluster_release_level) + # fail configuration.gpfs_images_share_mode not in + # ['copy_on_write', 'copy'] + org_value = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='copy_on_read') self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode=org_value) - def test_check_for_setup_error_incompatible_filesystem_version(self): - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_state', - self._fake_gpfs_get_state_active) - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_cluster_release_level', - self._fake_gpfs_compatible_cluster_release_level) - self.stubs.Set(gpfs.GPFSDriver, '_get_gpfs_fs_release_level', - self._fake_gpfs_incompatible_filesystem_release_level) + # fail configuration.gpfs_images_share_mode and + # configuration.gpfs_images_dir is None + org_value_share_mode = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='copy') + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = None self.assertRaises(exception.VolumeBackendAPIException, self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode=org_value_share_mode) + CONF.gpfs_images_dir = org_value_dir + + # fail configuration.gpfs_images_share_mode == 'copy_on_write' and not + # _same_filesystem(configuration.gpfs_mount_point_base, + # configuration.gpfs_images_dir) + org_value = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='copy_on_write') + with mock.patch('cinder.volume.drivers.ibm.gpfs._same_filesystem', + return_value=False): + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode=org_value) + + # fail self.configuration.gpfs_images_share_mode == 'copy_on_write' and + # not self._is_same_fileset(self.configuration.gpfs_mount_point_base, + # self.configuration.gpfs_images_dir) + org_value = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='copy_on_write') + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_is_same_fileset', return_value=False): + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode=org_value) + + # fail directory is None + org_value_share_mode = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode=None) + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = None + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_cluster_release_level', + return_value=fake_cluster_release): + self.driver.check_for_setup_error() + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode=org_value_share_mode) + CONF.gpfs_images_dir = org_value_dir - def _fake_create_file(self, path, modebits='666'): - open(path, 'w').close() - utils.execute('chmod', modebits, path) + # fail directory.startswith('/') + org_value_mount = self.driver.configuration.gpfs_mount_point_base + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base='_' + self.volumes_path) + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = None + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_cluster_release_level', + return_value=fake_cluster_release): + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=org_value_mount) + CONF.gpfs_images_dir = org_value_dir - def _fake_gpfs_snap(self, src, dest=None, modebits='644'): - if dest is None: - dest = src - self._fake_create_file(dest, '644') + # fail os.path.isdir(directory) + org_value_mount = self.driver.configuration.gpfs_mount_point_base + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=self.volumes_path + '_') + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = None + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_cluster_release_level', + return_value=fake_cluster_release): + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=org_value_mount) + CONF.gpfs_images_dir = org_value_dir + + # fail not cluster release level >= GPFS_CLONE_MIN_RELEASE + org_fake_cluster_release = fake_cluster_release + fake_cluster_release = 1105 + org_value_mount = self.driver.configuration.gpfs_mount_point_base + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=self.volumes_path) + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = None + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_cluster_release_level', + return_value=fake_cluster_release): + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_fs_release_level', + return_value=(fake_fs, fake_fs_release)): + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.check_for_setup_error) + fake_cluster_release = org_fake_cluster_release - def _fake_gpfs_copy(self, src, dest): - self._fake_create_file(dest) + # fail not fs release level >= GPFS_CLONE_MIN_RELEASE + org_fake_fs_release = fake_fs_release + fake_fs_release = 1105 + org_value_mount = self.driver.configuration.gpfs_mount_point_base + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=self.volumes_path) + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = None + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_cluster_release_level', + return_value=fake_cluster_release): + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_gpfs_fs_release_level', + return_value=(fake_fs, fake_fs_release)): + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.check_for_setup_error) + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=org_value_mount) + CONF.gpfs_images_dir = org_value_dir + fake_fs_release = org_fake_fs_release + + @patch('cinder.utils.execute') + def test_create_sparse_file(self, mock_exec): + self.driver._create_sparse_file('', 100) + + @patch('cinder.utils.execute') + def test_allocate_file_blocks(self, mock_exec): + self.driver._allocate_file_blocks(os.path.join(self.images_dir, + 'test'), 1) + + @patch('cinder.utils.execute') + def test_gpfs_change_attributes(self, mock_exec): + options = [] + options.extend(['-T', 'test']) + self.driver._gpfs_change_attributes(options, self.images_dir) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_change_attributes') + def test_set_volume_attributes(self, mock_change_attributes): + metadata = [dict([('key', 'data_pool_name'), ('value', 'test')]), + dict([('key', 'replicas'), ('value', 'test')]), + dict([('key', 'dio'), ('value', 'test')]), + dict([('key', 'write_affinity_depth'), ('value', 'test')]), + dict([('key', 'block_group_factor'), ('value', 'test')]), + dict([('key', 'write_affinity_failure_group'), + ('value', 'test')]), + dict([('key', 'test'), + ('value', 'test')])] + self.driver._set_volume_attributes('', metadata) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_change_attributes') + def test_set_volume_attributes_no_attributes(self, mock_change_attributes): + metadata = [] + org_value = self.driver.configuration.gpfs_storage_pool + self.flags(volume_driver=self.driver_name, gpfs_storage_pool='system') + self.driver._set_volume_attributes('', metadata) + self.flags(volume_driver=self.driver_name, + gpfs_storage_pool=org_value) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_change_attributes') + def test_set_volume_attributes_no_options(self, mock_change_attributes): + metadata = [] + org_value = self.driver.configuration.gpfs_storage_pool + self.flags(volume_driver=self.driver_name, gpfs_storage_pool='') + self.driver._set_volume_attributes('', metadata) + self.flags(volume_driver=self.driver_name, + gpfs_storage_pool=org_value) + + @patch('cinder.utils.execute') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._allocate_file_blocks') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_volume_attributes') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_sparse_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + def test_create_volume(self, + mock_gpfs_path_state, + mock_local_path, + mock_sparse_file, + mock_rw_permission, + mock_set_volume_attributes, + mock_allocate_file_blocks, + mock_exec): + mock_local_path.return_value = 'test' + volume = {} + volume['size'] = 1000 + value = {} + value['value'] = 'test' + volume['volume_metadata'] = [dict([('key', 'fstype'), + ('value', 'test')]), + dict([('key', 'fslabel'), + ('value', 'test')]), + dict([('key', 'test'), + ('value', 'test')])] + + org_value = self.driver.configuration.gpfs_sparse_volumes + self.flags(volume_driver=self.driver_name, gpfs_sparse_volumes=False) + self.driver.create_volume(volume) + self.flags(volume_driver=self.driver_name, + gpfs_sparse_volumes=org_value) + + @patch('cinder.utils.execute') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._allocate_file_blocks') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_volume_attributes') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_sparse_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + def test_create_volume_no_sparse_volume(self, + mock_gpfs_path_state, + mock_local_path, + mock_sparse_file, + mock_rw_permission, + mock_set_volume_attributes, + mock_allocate_file_blocks, + mock_exec): + mock_local_path.return_value = 'test' + volume = {} + volume['size'] = 1000 + value = {} + value['value'] = 'test' + volume['volume_metadata'] = [dict([('key', 'fstype_'), + ('value', 'test')]), + dict([('key', 'fslabel'), + ('value', 'test')]), + dict([('key', 'test'), + ('value', 'test')])] + + org_value = self.driver.configuration.gpfs_sparse_volumes + self.flags(volume_driver=self.driver_name, gpfs_sparse_volumes=True) + self.driver.create_volume(volume) + self.flags(volume_driver=self.driver_name, + gpfs_sparse_volumes=org_value) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_redirect') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_copy') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_create_volume_from_snapshot(self, + mock_local_path, + mock_create_gpfs_copy, + mock_rw_permission, + mock_gpfs_redirect, + mock_resize_volume_file): + mock_resize_volume_file.return_value = 5 * units.GiB + volume = {} + volume['size'] = 1000 + self.assertEqual(self.driver.create_volume_from_snapshot(volume, ''), + {'size': 5.0}) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_clone') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_create_cloned_volume(self, + mock_local_path, + mock_create_gpfs_clone, + mock_rw_permission, + mock_resize_volume_file): + mock_resize_volume_file.return_value = 5 * units.GiB + volume = {} + volume['size'] = 1000 + self.assertEqual(self.driver.create_cloned_volume(volume, ''), + {'size': 5.0}) + + @patch('cinder.utils.execute') + def test_delete_gpfs_file_ok(self, mock_exec): + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 2 148488 ' + '/gpfs0/test.txt', ''), + ('', ''), + ('', '')] + self.driver._delete_gpfs_file(self.images_dir) + self.driver._delete_gpfs_file(self.images_dir + '_') + + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' ' + '/gpfs0/test.txt', ''), + ('', '')] + self.driver._delete_gpfs_file(self.images_dir) + + @patch('os.path.exists') + @patch('cinder.utils.execute') + def test_delete_gpfs_file_ok_parent(self, mock_exec, mock_path_exists): + mock_path_exists.side_effect = [True, False, False, + True, False, False, + True, False, False] + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 2 148488 ' + '/gpfs0/test.txt', ''), + ('/gpfs0/test.snap\ntest', ''), + ('', '')] + self.driver._delete_gpfs_file(self.images_dir) + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 2 148488 ' + '/gpfs0/test.txt', ''), + ('/gpfs0/test.ts\ntest', ''), + ('', '')] + self.driver._delete_gpfs_file(self.images_dir) + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 2 148488 ' + '/gpfs0/test.txt', ''), + ('/gpfs0/test.txt\ntest', ''), + ('', '')] + self.driver._delete_gpfs_file(self.images_dir) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._delete_gpfs_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + def test_delete_volume(self, + mock_verify_gpfs_path_state, + mock_local_path, + mock_delete_gpfs_file): + self.driver.delete_volume('') + + @patch('cinder.utils.execute') + def test_gpfs_redirect_ok(self, mock_exec): + org_value = self.driver.configuration.gpfs_max_clone_depth + self.flags(volume_driver=self.driver_name, gpfs_max_clone_depth=1) + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 2 148488 ' + '/gpfs0/test.txt', ''), + ('', '')] + self.assertEqual(True, self.driver._gpfs_redirect('')) + self.flags(volume_driver=self.driver_name, gpfs_max_clone_depth=1) + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 1 148488 ' + '/gpfs0/test.txt', ''), + ('', '')] + self.assertEqual(False, self.driver._gpfs_redirect('')) + self.flags(volume_driver=self.driver_name, + gpfs_max_clone_depth=org_value) + + @patch('cinder.utils.execute') + def test_gpfs_redirect_fail_depth(self, mock_exec): + org_value = self.driver.configuration.gpfs_max_clone_depth + self.flags(volume_driver=self.driver_name, gpfs_max_clone_depth=0) + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 2 148488 ' + '/gpfs0/test.txt', ''), + ('', '')] + self.assertEqual(False, self.driver._gpfs_redirect('')) + self.flags(volume_driver=self.driver_name, + gpfs_max_clone_depth=org_value) + + @patch('cinder.utils.execute') + def test_gpfs_redirect_fail_match(self, mock_exec): + org_value = self.driver.configuration.gpfs_max_clone_depth + self.flags(volume_driver=self.driver_name, gpfs_max_clone_depth=1) + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' 148488 ' + '/gpfs0/test.txt', ''), + ('', '')] + self.assertEqual(False, self.driver._gpfs_redirect('')) + self.flags(volume_driver=self.driver_name, + gpfs_max_clone_depth=org_value) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_snap') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_copy') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_redirect') + @patch('cinder.utils.execute') + def test_create_gpfs_clone(self, + mock_exec, + mock_redirect, + mock_cr_gpfs_cp, + mock_cr_gpfs_snap): + mock_redirect.return_value = True + self.driver._create_gpfs_clone('', '') + mock_redirect.side_effect = [True, False] + self.driver._create_gpfs_clone('', '') + + @patch('cinder.utils.execute') + def test_create_gpfs_copy(self, mock_exec): + self.driver._create_gpfs_copy('', '') + + @patch('cinder.utils.execute') + def test_create_gpfs_snap(self, mock_exec): + self.driver._create_gpfs_snap('') + self.driver._create_gpfs_snap('', '') + + @patch('cinder.utils.execute') + def test_is_gpfs_parent_file_ok(self, mock_exec): + mock_exec.side_effect = [('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' yes 2 148488 ' + '/gpfs0/test.txt', ''), + ('Parent Depth Parent inode File name\n' + '------ ----- -------------- ---------\n' + ' no 2 148488 ' + '/gpfs0/test.txt', '')] + self.assertEqual(True, self.driver._is_gpfs_parent_file('')) + self.assertEqual(False, self.driver._is_gpfs_parent_file('')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_redirect') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_snap') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_create_snapshot(self, + mock_local_path, + mock_create_gpfs_snap, + mock_set_rw_permission, + mock_gpfs_redirect): + org_value = self.driver.configuration.gpfs_mount_point_base + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=self.volumes_path) + snapshot = {} + snapshot['volume_name'] = 'test' + self.driver.create_snapshot(snapshot) + self.flags(volume_driver=self.driver_name, + gpfs_mount_point_base=org_value) + + @patch('cinder.utils.execute') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_delete_snapshot(self, + mock_local_path, + mock_exec): + snapshot = {} + self.driver.delete_snapshot(snapshot) - def _fake_create_sparse_file(self, path, size): - self._fake_create_file(path) + def test_ensure_export(self): + self.assertEqual(None, self.driver.ensure_export('', '')) - def _fake_allocate_file_blocks(self, path, size): - self._fake_create_file(path) + def test_create_export(self): + self.assertEqual(None, self.driver.create_export('', '')) - def _fake_gpfs_change_attributes(self, options, path): - pass + def test_remove_export(self): + self.assertEqual(None, self.driver.remove_export('', '')) - def _fake_gpfs_redirect(self, src): - return True + def test_initialize_connection(self): + volume = {} + volume['name'] = 'test' + data = self.driver.initialize_connection(volume, '') + self.assertEqual(data['data']['name'], 'test') + self.assertEqual(data['data']['device_path'], os.path.join( + self.driver.configuration.gpfs_mount_point_base, 'test')) - def _fake_is_gpfs_parent(self, gpfs_file): - return False + def test_terminate_connection(self): + self.assertEqual(None, self.driver.terminate_connection('', '')) - def _fake_get_available_capacity(self, path): + def test_get_volume_stats(self): 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) + with mock.patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_get_available_capacity', + return_value=(fake_avail, fake_size)): + stats = self.driver.get_volume_stats() + self.assertEqual(stats['volume_backend_name'], 'GPFS') + self.assertEqual(stats['storage_protocol'], 'file') + stats = self.driver.get_volume_stats(True) + self.assertEqual(stats['volume_backend_name'], 'GPFS') + self.assertEqual(stats['storage_protocol'], 'file') + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._update_volume_stats') + def test_get_volume_stats_none_stats(self, mock_upd_vol_stats): + _stats_org = self.driver._stats + self.driver._stats = mock.Mock() + self.driver._stats.return_value = None + self.driver.get_volume_stats() + self.driver._stats = _stats_org + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._clone_image') + def test_clone_image_pub(self, mock_exec): + self.driver.clone_image('', '', '', '') + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_path') + def test_is_cloneable_ok(self, mock_is_gpfs_path): + org_value_share_mode = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='test') + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = self.images_dir + mock_is_gpfs_path.return_value = None + self.assertEqual((True, None, os.path.join(CONF.gpfs_images_dir, + '12345')), + self.driver._is_cloneable('12345')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_path') + def test_is_cloneable_fail_config(self, mock_is_gpfs_path): + org_value_share_mode = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, gpfs_images_share_mode='') + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = '' + mock_is_gpfs_path.return_value = None + self.assertNotEqual((True, None, os.path.join(CONF.gpfs_images_dir, + '12345')), + self.driver._is_cloneable('12345')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_path') + def test_is_cloneable_fail_path(self, mock_is_gpfs_path): + org_value_share_mode = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='test') + org_value_dir = CONF.gpfs_images_dir + CONF.gpfs_images_dir = self.images_dir + mock_is_gpfs_path.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + self.assertNotEqual((True, None, os.path.join(CONF.gpfs_images_dir, + '12345')), + self.driver._is_cloneable('12345')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission') + @patch('cinder.image.image_utils.convert_image') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_copy') + @patch('cinder.image.image_utils.qemu_img_info') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_snap') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_parent_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_cloneable') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + def test_clone_image(self, + mock_verify_gpfs_path_state, + mock_is_cloneable, + mock_local_path, + mock_is_gpfs_parent_file, + mock_create_gpfs_snap, + mock_qemu_img_info, + mock_create_gpfs_copy, + mock_conv_image, + mock_set_rw_permission, + mock_resize_volume_file): + mock_is_cloneable.return_value = (True, 'test', self.images_dir) + mock_is_gpfs_parent_file.return_value = False + mock_qemu_img_info.return_value = self._fake_qemu_qcow2_image_info('') + volume = {} + volume['id'] = 'test' + volume['size'] = 1000 + self.assertEqual(({'provider_location': None}, True), + self.driver._clone_image(volume, '', 1)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_cloneable') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + def test_clone_image_not_cloneable(self, + mock_verify_gpfs_path_state, + mock_is_cloneable): + mock_is_cloneable.return_value = (False, 'test', self.images_dir) + volume = {} + volume['id'] = 'test' + volume['size'] = 1000 + self.assertEqual((None, False), + self.driver._clone_image(volume, '', 1)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._set_rw_permission') + @patch('cinder.image.image_utils.convert_image') + @patch('shutil.copyfile') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_copy') + @patch('cinder.image.image_utils.qemu_img_info') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_snap') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_parent_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_cloneable') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + def test_clone_image_format(self, + mock_verify_gpfs_path_state, + mock_is_cloneable, + mock_local_path, + mock_is_gpfs_parent_file, + mock_create_gpfs_snap, + mock_qemu_img_info, + mock_create_gpfs_copy, + mock_copyfile, + mock_conv_image, + mock_set_rw_permission, + mock_resize_volume_file): + mock_is_cloneable.return_value = (True, 'test', self.images_dir) + mock_is_gpfs_parent_file.return_value = True + mock_qemu_img_info.return_value = self._fake_qemu_raw_image_info('') + volume = {} + volume['id'] = 'test' + volume['size'] = 1000 + org_value = self.driver.configuration.gpfs_images_share_mode + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='copy_on_write') + self.assertEqual(({'provider_location': None}, True), + self.driver._clone_image(volume, '', 1)) + + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='copy') + self.assertEqual(({'provider_location': None}, True), + self.driver._clone_image(volume, '', 1)) + + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode='copy_on_read') + self.assertEqual(({'provider_location': None}, True), + self.driver._clone_image(volume, '', 1)) + self.flags(volume_driver=self.driver_name, + gpfs_images_share_mode=org_value) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + @patch('cinder.image.image_utils.fetch_to_raw') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + def test_copy_image_to_volume(self, + mock_verify_gpfs_path_state, + mock_fetch_to_raw, + mock_local_path, + mock_resize_volume_file): + volume = {} + volume['id'] = 'test' + volume['size'] = 1000 + self.driver.copy_image_to_volume('', volume, '', 1) + + @patch('cinder.image.image_utils.qemu_img_info') + @patch('cinder.image.image_utils.resize_image') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_resize_volume_file_ok(self, + mock_local_path, + mock_resize_image, + mock_qemu_img_info): + volume = {} + volume['id'] = 'test' + mock_qemu_img_info.return_value = self._fake_qemu_qcow2_image_info('') + self.assertEqual(self._fake_qemu_qcow2_image_info('').virtual_size, + self.driver._resize_volume_file(volume, 2000)) + + @patch('cinder.image.image_utils.qemu_img_info') + @patch('cinder.image.image_utils.resize_image') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_resize_volume_file_fail(self, + mock_local_path, + mock_resize_image, + mock_qemu_img_info): + volume = {} + volume['id'] = 'test' + mock_resize_image.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + mock_qemu_img_info.return_value = self._fake_qemu_qcow2_image_info('') + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._resize_volume_file, volume, 2000) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._resize_volume_file') + def test_extend_volume(self, mock_resize_volume_file): + volume = {} + volume['id'] = 'test' + self.driver.extend_volume(volume, 2000) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + @patch('cinder.image.image_utils.upload_volume') + def test_copy_volume_to_image(self, mock_upload_volume, mock_local_path): + volume = {} + volume['id'] = 'test' + self.driver.copy_volume_to_image('', volume, '', '') + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._delete_gpfs_file') + @patch('cinder.openstack.common.fileutils.file_open') + @patch('cinder.utils.temporary_chown') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._gpfs_redirect') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._create_gpfs_clone') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_backup_volume(self, + mock_local_path, + mock_create_gpfs_clone, + mock_gpfs_redirect, + mock_temp_chown, + mock_file_open, + mock_delete_gpfs_file): + volume = {} + volume['name'] = 'test' + self.driver.db = mock.Mock() + self.driver.db.volume_get = mock.Mock() + self.driver.db.volume_get.return_value = volume + backup = {} + backup['volume_id'] = 'test' + backup['id'] = '123456' + backup_service = mock.Mock() + mock_local_path.return_value = self.volumes_path + self.driver.backup_volume('', backup, backup_service) + + @patch('cinder.openstack.common.fileutils.file_open') + @patch('cinder.utils.temporary_chown') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.local_path') + def test_restore_backup(self, + mock_local_path, + mock_temp_chown, + mock_file_open): + volume = {} + volume['id'] = '123456' + backup = {} + backup['id'] = '123456' + backup_service = mock.Mock() + mock_local_path.return_value = self.volumes_path + self.driver.restore_backup('', backup, volume, backup_service) + + @patch('cinder.utils.execute') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._can_migrate_locally') + def test_migrate_volume_ok(self, mock_local, mock_exec): + volume = {} + volume['name'] = 'test' + host = {} + host = {'host': 'foo', 'capabilities': {}} + mock_local.return_value = (self.driver.configuration. + gpfs_mount_point_base + '_') + self.assertEqual((True, None), + self.driver._migrate_volume(volume, host)) + + @patch('cinder.utils.execute') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._can_migrate_locally') + def test_migrate_volume_fail_dest_path(self, mock_local, mock_exec): + volume = {} + volume['name'] = 'test' + host = {} + host = {'host': 'foo', 'capabilities': {}} + mock_local.return_value = None + self.assertEqual((False, None), + self.driver._migrate_volume(volume, host)) + + @patch('cinder.utils.execute') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._can_migrate_locally') + def test_migrate_volume_fail_mpb(self, mock_local, mock_exec): + volume = {} + volume['name'] = 'test' + host = {} + host = {'host': 'foo', 'capabilities': {}} + mock_local.return_value = (self.driver.configuration. + gpfs_mount_point_base) + mock_exec.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + self.assertEqual((True, None), + self.driver._migrate_volume(volume, host)) + + @patch('cinder.utils.execute') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._can_migrate_locally') + def test_migrate_volume_fail_mv(self, mock_local, mock_exec): + volume = {} + volume['name'] = 'test' + host = {} + host = {'host': 'foo', 'capabilities': {}} + mock_local.return_value = ( + self.driver.configuration.gpfs_mount_point_base + '_') + mock_exec.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + self.assertEqual((False, None), + self.driver._migrate_volume(volume, host)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._migrate_volume') + def test_migrate_volume_ok_pub(self, mock_migrate_volume): + self.driver.migrate_volume('', '', '') + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._migrate_volume') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_update_volume_storage_pool') + @patch('cinder.volume.drivers.ibm.gpfs._different') + def test_retype_ok(self, mock_different, mock_strg_pool, mock_migrate_vol): + ctxt = self.context + (volume, new_type, diff, host) = self._fake_retype_arguments() + self.driver.db = mock.Mock() + mock_different.side_effect = [False, True, True] + mock_strg_pool.return_value = True + mock_migrate_vol.return_value = (True, True) + self.assertTrue(self.driver.retype(ctxt, volume, new_type, diff, host)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._migrate_volume') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_update_volume_storage_pool') + @patch('cinder.volume.drivers.ibm.gpfs._different') + def test_retype_diff_backend(self, + mock_different, + mock_strg_pool, + mock_migrate_vol): + ctxt = self.context + (volume, new_type, diff, host) = self._fake_retype_arguments() + mock_different.side_effect = [True, True, True] + self.assertFalse(self.driver.retype(ctxt, + volume, + new_type, + diff, host)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._migrate_volume') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_update_volume_storage_pool') + @patch('cinder.volume.drivers.ibm.gpfs._different') + def test_retype_diff_pools_migrated(self, + mock_different, + mock_strg_pool, + mock_migrate_vol): + ctxt = self.context + (volume, new_type, diff, host) = self._fake_retype_arguments() + self.driver.db = mock.Mock() + mock_different.side_effect = [False, False, True] + mock_strg_pool.return_value = True + mock_migrate_vol.return_value = (True, True) + self.assertTrue(self.driver.retype(ctxt, volume, new_type, diff, host)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._migrate_volume') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_update_volume_storage_pool') + @patch('cinder.volume.drivers.ibm.gpfs._different') + def test_retype_diff_pools(self, + mock_different, + mock_strg_pool, + mock_migrate_vol): + ctxt = self.context + (volume, new_type, diff, host) = self._fake_retype_arguments() + mock_different.side_effect = [False, False, True] + mock_strg_pool.return_value = True + mock_migrate_vol.return_value = (False, False) + self.assertFalse(self.driver.retype(ctxt, + volume, + new_type, + diff, + host)) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._migrate_volume') + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver.' + '_update_volume_storage_pool') + @patch('cinder.volume.drivers.ibm.gpfs._different') + def test_retype_no_diff_hit(self, + mock_different, + mock_strg_pool, + mock_migrate_vol): + ctxt = self.context + (volume, new_type, diff, host) = self._fake_retype_arguments() + mock_different.side_effect = [False, False, False] + self.assertFalse(self.driver.retype(ctxt, + volume, + new_type, + diff, + host)) + + @patch('cinder.utils.execute') + def test_mkfs_ok(self, mock_exec): + volume = {} + volume['name'] = 'test' + self.driver._mkfs(volume, 'swap') + self.driver._mkfs(volume, 'swap', 'test') + self.driver._mkfs(volume, 'ext3', 'test') + self.driver._mkfs(volume, 'vfat', 'test') + + @patch('cinder.utils.execute') + def test_mkfs_fail_mk(self, mock_exec): + volume = {} + volume['name'] = 'test' + mock_exec.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._mkfs, volume, 'swap', 'test') + + @patch('cinder.utils.execute') + def test_get_available_capacity_ok(self, mock_exec): + mock_exec.return_value = ('Filesystem 1-blocks Used ' + 'Available Capacity Mounted on\n' + '/dev/gpfs 10737418240 544735232 ' + '10192683008 6%% /gpfs0', '') + self.assertEqual((10192683008, 10737418240), + self.driver._get_available_capacity('/gpfs0')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._verify_gpfs_path_state') + @patch('cinder.utils.execute') + def test_get_available_capacity_fail_mounted(self, + mock_exec, + mock_path_state): + mock_path_state.side_effect = ( + exception.VolumeBackendAPIException('test')) + mock_exec.return_value = ('Filesystem 1-blocks Used ' + 'Available Capacity Mounted on\n' + '/dev/gpfs 10737418240 544735232 ' + '10192683008 6%% /gpfs0', '') + self.assertEqual((0, 0), self.driver._get_available_capacity('/gpfs0')) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_path') + def test_verify_gpfs_path_state_ok(self, mock_is_gpfs_path): + self.driver._verify_gpfs_path_state(self.images_dir) + + @patch('cinder.volume.drivers.ibm.gpfs.GPFSDriver._is_gpfs_path') + def test_verify_gpfs_path_state_fail_path(self, mock_is_gpfs_path): + mock_is_gpfs_path.side_effect = ( + processutils.ProcessExecutionError(stdout='test', stderr='test')) + self.assertRaises(exception.VolumeBackendAPIException, + self.driver._verify_gpfs_path_state, self.images_dir) def _fake_qemu_qcow2_image_info(self, path): data = FakeQemuImgInfo() @@ -713,16 +1409,28 @@ class GPFSDriverTestCase(test.TestCase): data.virtual_size = 1 * units.GiB return data - def _fake_qemu_image_resize(self, path, size, run_as_root=False): - 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) + def _fake_retype_arguments(self): + ctxt = self.context + loc = 'GPFSDriver:%s:testpath' % self.driver._cluster_id + cap = {'location_info': loc} + host = {'host': 'foo', 'capabilities': cap} + key_specs_old = {'capabilities:storage_pool': 'bronze', + 'volume_backend_name': 'backend1'} + key_specs_new = {'capabilities:storage_pool': 'gold', + 'volume_backend_name': 'backend1'} + old_type_ref = volume_types.create(ctxt, 'old', key_specs_old) + new_type_ref = volume_types.create(ctxt, 'new', key_specs_new) + + old_type = volume_types.get_volume_type(ctxt, old_type_ref['id']) + new_type = volume_types.get_volume_type(ctxt, new_type_ref['id']) + + diff, equal = volume_types.volume_types_diff(ctxt, + old_type_ref['id'], + new_type_ref['id']) + + volume = {} + volume['name'] = 'test' + volume['host'] = host + volume['id'] = '123456' + + return (volume, new_type, diff, host)