self.TEST_SHARES_CONFIG_FILE
self._configuration.glusterfs_mount_point_base = \
self.TEST_MNT_POINT_BASE
- self._configuration.glusterfs_sparsed_volumes = True
- self._configuration.glusterfs_qcow2_volumes = False
self._configuration.nas_secure_file_permissions = 'false'
self._configuration.nas_secure_file_operations = 'false'
self._configuration.nas_ip = None
self.assertEqual(3.0, provisioned_capacity)
- def test_update_volume_stats_sparse(self):
- """_update_volume_stats_sparse with sparse files."""
+ def test_update_volume_stats_thin(self):
+ """_update_volume_stats_thin with qcow2 files."""
drv = self._driver
rfsdriver = remotefs_drv.RemoteFSSnapDriver
data = {'total_capacity_gb': 10.0,
'free_capacity_gb': 2.0}
drv._stats = data
- drv.configuration.glusterfs_sparsed_volumes = True
- drv.configuration.glusterfs_qcow2_volumes = False
- drv.configuration.max_over_subscription_ratio = 20.0
- mock_get_provisioned_capacity.return_value = 8.0
- drv._update_volume_stats()
- data['max_over_subscription_ratio'] = 20.0
- data['thick_provisioning_support'] = False
- data['thin_provisioning_support'] = True
-
- self.assertEqual(data, drv._stats)
- self.assertTrue(mock_get_provisioned_capacity.called)
- self.assertTrue(mock_update_volume_stats.called)
-
- def test_update_volume_stats_qcow2(self):
- """_update_volume_stats_sparse with qcow2 files."""
- drv = self._driver
- rfsdriver = remotefs_drv.RemoteFSSnapDriver
-
- with mock.patch.object(rfsdriver, '_update_volume_stats') as \
- mock_update_volume_stats,\
- mock.patch.object(drv, '_get_provisioned_capacity') as \
- mock_get_provisioned_capacity:
- data = {'total_capacity_gb': 10.0,
- 'free_capacity_gb': 2.0}
- drv._stats = data
- drv.configuration.glusterfs_sparsed_volumes = False
- drv.configuration.glusterfs_qcow2_volumes = True
+ drv.configuration.nas_volume_prov_type = 'thin'
drv.configuration.max_over_subscription_ratio = 20.0
mock_get_provisioned_capacity.return_value = 8.0
drv._update_volume_stats()
self.assertTrue(mock_update_volume_stats.called)
def test_update_volume_stats_thick(self):
- """_update_volume_stats_sparse with raw files."""
+ """_update_volume_stats_thick with raw files."""
drv = self._driver
rfsdriver = remotefs_drv.RemoteFSSnapDriver
data = {'total_capacity_gb': 10.0,
'free_capacity_gb': 2.0}
drv._stats = data
- drv.configuration.glusterfs_sparsed_volumes = False
- drv.configuration.glusterfs_qcow2_volumes = False
+ drv.configuration.nas_volume_prov_type = 'thick'
drv.configuration.max_over_subscription_ratio = 20.0
drv._update_volume_stats()
data['provisioned_capacity_gb'] = 8.0
return volume
- def test_create_sparsed_volume(self):
+ def test_create_thin_volume(self):
drv = self._driver
volume = self._simple_volume()
- self.override_config('glusterfs_sparsed_volumes', True)
+ self._configuration.nas_volume_prov_type = 'thin'
- with mock.patch.object(drv, '_create_sparsed_file') as \
- mock_create_sparsed_file,\
+ with mock.patch.object(drv, '_create_qcow2_file') as \
+ mock_create_qcow2_file,\
mock.patch.object(drv, '_set_rw_permissions_for_all') as \
mock_set_rw_permissions_for_all:
drv._do_create_volume(volume)
volume_path = drv.local_path(volume)
volume_size = volume['size']
- mock_create_sparsed_file.assert_called_once_with(volume_path,
- volume_size)
+ mock_create_qcow2_file.assert_called_once_with(volume_path,
+ volume_size)
mock_set_rw_permissions_for_all.\
assert_called_once_with(volume_path)
- def test_create_nonsparsed_volume(self):
+ def test_create_thick_fallocate_volume(self):
drv = self._driver
volume = self._simple_volume()
- old_value = self._configuration.glusterfs_sparsed_volumes
- self._configuration.glusterfs_sparsed_volumes = False
+ self._configuration.nas_volume_prov_type = 'thick'
- with mock.patch.object(drv, '_create_regular_file') as \
- mock_create_regular_file,\
+ with mock.patch.object(drv, '_fallocate') as \
+ mock_fallocate,\
mock.patch.object(drv, '_set_rw_permissions_for_all') as \
mock_set_rw_permissions_for_all:
drv._do_create_volume(volume)
volume_path = drv.local_path(volume)
volume_size = volume['size']
- mock_create_regular_file.assert_called_once_with(volume_path,
- volume_size)
+ mock_fallocate.assert_called_once_with(volume_path,
+ volume_size)
mock_set_rw_permissions_for_all.\
assert_called_once_with(volume_path)
- self._configuration.glusterfs_sparsed_volumes = old_value
- def test_create_qcow2_volume(self):
+ def test_create_thick_dd_volume(self):
drv = self._driver
volume = self._simple_volume()
- old_value = self._configuration.glusterfs_qcow2_volumes
- self._configuration.glusterfs_qcow2_volumes = True
+ self._configuration.nas_volume_prov_type = 'thick'
- with mock.patch.object(drv, '_execute') as mock_execute,\
+ with mock.patch.object(drv, '_fallocate') as \
+ mock_fallocate,\
+ mock.patch.object(drv, '_create_regular_file') as \
+ mock_create_regular_file,\
mock.patch.object(drv, '_set_rw_permissions_for_all') as \
mock_set_rw_permissions_for_all:
- hashed = drv._get_hash_str(volume['provider_location'])
- path = '%s/%s/volume-%s' % (self.TEST_MNT_POINT_BASE,
- hashed,
- self.VOLUME_UUID)
-
+ mock_fallocate.side_effect = putils.ProcessExecutionError(
+ stderr='Fallocate: Operation not supported.')
drv._do_create_volume(volume)
volume_path = drv.local_path(volume)
volume_size = volume['size']
- mock_execute.assert_called_once_with('qemu-img', 'create',
- '-f', 'qcow2', '-o',
- 'preallocation=metadata',
- path,
- str(volume_size * units.Gi),
- run_as_root=True)
+ mock_fallocate.assert_called_once_with(volume_path,
+ volume_size)
+ mock_create_regular_file.assert_called_once_with(volume_path,
+ volume_size)
mock_set_rw_permissions_for_all.\
assert_called_once_with(volume_path)
- self._configuration.glusterfs_qcow2_volumes = old_value
def test_create_volume_should_ensure_glusterfs_mounted(self):
"""create_volume ensures shares provided in config are mounted."""
import errno
import os
import stat
+import warnings
from os_brick.remotefs import remotefs as remotefs_brick
from oslo_concurrency import processutils
LOG = logging.getLogger(__name__)
+
volume_opts = [
cfg.StrOpt('glusterfs_shares_config',
default='/etc/cinder/glusterfs_shares',
help='File with the list of available gluster shares'),
- cfg.BoolOpt('glusterfs_sparsed_volumes',
- default=True,
- help=('Create volumes as sparsed files which take no space.'
- 'If set to False volume is created as regular file.'
- 'In such case volume creation takes a lot of time.')),
- cfg.BoolOpt('glusterfs_qcow2_volumes',
- default=False,
- help=('Create volumes as QCOW2 files rather than raw files.')),
cfg.StrOpt('glusterfs_mount_point_base',
default='$state_path/mnt',
help='Base dir containing mount points for gluster shares.'),
global_capacity = data['total_capacity_gb']
global_free = data['free_capacity_gb']
- thin_enabled = (self.configuration.glusterfs_sparsed_volumes or
- self.configuration.glusterfs_qcow2_volumes)
+ thin_enabled = self.configuration.nas_volume_prov_type == 'thin'
if thin_enabled:
provisioned_capacity = self._get_provisioned_capacity()
else:
LOG.debug("will copy from snapshot at %s", path_to_snap_img)
- if self.configuration.glusterfs_qcow2_volumes:
+ if self.configuration.nas_volume_prov_type == 'thin':
out_format = 'qcow2'
else:
out_format = 'raw'
LOG.error(msg)
raise exception.InvalidVolume(reason=msg)
- if self.configuration.glusterfs_qcow2_volumes:
+ if self.configuration.nas_volume_prov_type == 'thin':
self._create_qcow2_file(volume_path, volume_size)
else:
- if self.configuration.glusterfs_sparsed_volumes:
- self._create_sparsed_file(volume_path, volume_size)
- else:
- self._create_regular_file(volume_path, volume_size)
+ try:
+ self._fallocate(volume_path, volume_size)
+ except processutils.ProcessExecutionError as exc:
+ if 'Operation not supported' in exc.stderr:
+ warnings.warn('Fallocate not supported by current version '
+ 'of glusterfs. So falling back to dd.')
+ self._create_regular_file(volume_path, volume_size)
+ else:
+ fileutils.delete_if_exists(volume_path)
+ raise
self._set_rw_permissions_for_all(volume_path)
cfg.StrOpt('nas_mount_options',
default=None,
help=('Options used to mount the storage backend file system '
- 'where Cinder volumes are stored.'))
+ 'where Cinder volumes are stored.')),
+]
+
+old_vol_type_opts = [cfg.DeprecatedOpt('glusterfs_sparsed_volumes'),
+ cfg.DeprecatedOpt('glusterfs_qcow2_volumes')]
+
+volume_opts = [
+ cfg.StrOpt('nas_volume_prov_type',
+ default='thin',
+ choices=['thin', 'thick'],
+ deprecated_opts=old_vol_type_opts,
+ help=('Provisioning type that will be used when '
+ 'creating volumes.')),
]
CONF = cfg.CONF
if self.configuration:
self.configuration.append_config_values(nas_opts)
+ self.configuration.append_config_values(volume_opts)
def check_for_setup_error(self):
"""Just to override parent behavior."""
'count=%d' % block_count,
run_as_root=self._execute_as_root)
+ def _fallocate(self, path, size):
+ """Creates a raw file of given size in GiB using fallocate."""
+ self._execute('fallocate', '--length=%sG' % size,
+ path, run_as_root=True)
+
def _create_qcow2_file(self, path, size_gb):
"""Creates a QCOW2 file of a given size in GiB."""