diff --git a/cinder/tests/unit/volume/drivers/test_remotefs.py b/cinder/tests/unit/volume/drivers/test_remotefs.py index c36e8a70d67..50669c19e41 100644 --- a/cinder/tests/unit/volume/drivers/test_remotefs.py +++ b/cinder/tests/unit/volume/drivers/test_remotefs.py @@ -658,6 +658,8 @@ class RemoteFSPoolMixinTestCase(test.TestCase): self._driver.driver_volume_type = mock.sentinel.driver_volume_type self._driver._thin_provisioning_support = ( mock.sentinel.thin_prov_support) + self._driver._thick_provisioning_support = ( + mock.sentinel.thick_prov_support) self._driver.get_version = mock.Mock( return_value=mock.sentinel.driver_version) @@ -681,6 +683,8 @@ class RemoteFSPoolMixinTestCase(test.TestCase): self._driver.configuration.max_over_subscription_ratio), 'thin_provisioning_support': ( mock.sentinel.thin_prov_support), + 'thick_provisioning_support': ( + mock.sentinel.thick_prov_support), 'QoS_support': False, } diff --git a/cinder/tests/unit/windows/test_smbfs.py b/cinder/tests/unit/windows/test_smbfs.py index 9cfee2576e8..45766525a62 100644 --- a/cinder/tests/unit/windows/test_smbfs.py +++ b/cinder/tests/unit/windows/test_smbfs.py @@ -398,23 +398,27 @@ class WindowsSmbFsTestCase(test.TestCase): self._smbfs_driver.create_volume(self.volume) mock_create_volume.assert_called_once_with(self.volume) - def _test_create_volume(self, volume_exists=False, volume_format='vhdx'): - self._smbfs_driver.create_dynamic_vhd = mock.MagicMock() - fake_create = self._smbfs_driver._vhdutils.create_dynamic_vhd + @mock.patch('os.path.exists') + @mock.patch.object(smbfs.WindowsSmbfsDriver, '_get_vhd_type') + def _test_create_volume(self, mock_get_vhd_type, mock_exists, + volume_exists=False, volume_format='vhdx'): + mock_exists.return_value = volume_exists + self._smbfs_driver.create_vhd = mock.MagicMock() + fake_create = self._smbfs_driver._vhdutils.create_vhd self._smbfs_driver.get_volume_format = mock.Mock( return_value=volume_format) - with mock.patch('os.path.exists', new=lambda x: volume_exists): - volume = self._simple_volume() - if volume_exists or volume_format not in ('vhd', 'vhdx'): - self.assertRaises(exception.InvalidVolume, - self._smbfs_driver._do_create_volume, - volume) - else: - fake_vol_path = self._FAKE_VOLUME_PATH - self._smbfs_driver._do_create_volume(volume) - fake_create.assert_called_once_with( - fake_vol_path, volume.size << 30) + volume = self._simple_volume() + if volume_exists or volume_format not in ('vhd', 'vhdx'): + self.assertRaises(exception.InvalidVolume, + self._smbfs_driver._do_create_volume, + volume) + else: + fake_vol_path = self._FAKE_VOLUME_PATH + self._smbfs_driver._do_create_volume(volume) + fake_create.assert_called_once_with( + fake_vol_path, mock_get_vhd_type.return_value, + max_internal_size=volume.size << 30) def test_create_volume(self): self._test_create_volume() @@ -706,7 +710,8 @@ class WindowsSmbFsTestCase(test.TestCase): mock.sentinel.context, mock.sentinel.image_service, fake_image_meta, upload_path, fake_img_format) - def test_copy_image_to_volume(self): + @mock.patch.object(smbfs.WindowsSmbfsDriver, '_get_vhd_type') + def test_copy_image_to_volume(self, mock_get_vhd_type): drv = self._smbfs_driver drv.get_volume_format = mock.Mock( @@ -728,13 +733,15 @@ class WindowsSmbFsTestCase(test.TestCase): mock.sentinel.image_service, mock.sentinel.image_id, self._FAKE_VOLUME_PATH, mock.sentinel.volume_format, - mock.sentinel.block_size) + mock.sentinel.block_size, + mock_get_vhd_type.return_value) drv._vhdutils.resize_vhd.assert_called_once_with( self._FAKE_VOLUME_PATH, volume.size * units.Gi, is_file_max_size=False) - def test_copy_volume_from_snapshot(self): + @mock.patch.object(smbfs.WindowsSmbfsDriver, '_get_vhd_type') + def test_copy_volume_from_snapshot(self, mock_get_vhd_type): drv = self._smbfs_driver snapshot = self._simple_snapshot() fake_volume_info = { @@ -760,7 +767,8 @@ class WindowsSmbFsTestCase(test.TestCase): drv._delete.assert_called_once_with(mock.sentinel.new_volume_path) drv._vhdutils.convert_vhd.assert_called_once_with( self._FAKE_VOLUME_PATH, - mock.sentinel.new_volume_path) + mock.sentinel.new_volume_path, + vhd_type=mock_get_vhd_type.return_value) drv._vhdutils.resize_vhd.assert_called_once_with( mock.sentinel.new_volume_path, volume.size * units.Gi, @@ -802,3 +810,12 @@ class WindowsSmbFsTestCase(test.TestCase): self.assertRaises(exception.SmbfsException, self._smbfs_driver._get_share_from_pool_name, mock.sentinel.pool) + + def test_get_vhd_type(self): + drv = self._smbfs_driver + + mock_type = drv._get_vhd_type(qemu_subformat=True) + self.assertEqual(mock_type, 'dynamic') + + mock_type = drv._get_vhd_type(qemu_subformat=False) + self.assertEqual(mock_type, 3) diff --git a/cinder/volume/drivers/remotefs.py b/cinder/volume/drivers/remotefs.py index 554b2785380..119f17faa8d 100644 --- a/cinder/volume/drivers/remotefs.py +++ b/cinder/volume/drivers/remotefs.py @@ -149,6 +149,7 @@ class RemoteFSDriver(driver.BaseVD): # We let the drivers inheriting this specify # whether thin provisioning is supported or not. _thin_provisioning_support = False + _thick_provisioning_support = False def __init__(self, *args, **kwargs): super(RemoteFSDriver, self).__init__(*args, **kwargs) @@ -1727,6 +1728,8 @@ class RemoteFSPoolMixin(object): self.configuration.max_over_subscription_ratio), 'thin_provisioning_support': ( self._thin_provisioning_support), + 'thick_provisioning_support': ( + self._thick_provisioning_support), 'QoS_support': False, } diff --git a/cinder/volume/drivers/windows/smbfs.py b/cinder/volume/drivers/windows/smbfs.py index 1c40214352e..4630ea9c6e1 100644 --- a/cinder/volume/drivers/windows/smbfs.py +++ b/cinder/volume/drivers/windows/smbfs.py @@ -17,6 +17,7 @@ import os import sys from os_brick.remotefs import windows_remotefs as remotefs_brick +from os_win import constants as os_win_const from os_win import utilsfactory from oslo_config import cfg from oslo_log import log as logging @@ -117,6 +118,11 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin, _always_use_temp_snap_when_cloning = False _thin_provisioning_support = True + _vhd_type_mapping = {'thin': os_win_const.VHD_TYPE_DYNAMIC, + 'thick': os_win_const.VHD_TYPE_FIXED} + _vhd_qemu_subformat_mapping = {'thin': 'dynamic', + 'thick': 'fixed'} + def __init__(self, *args, **kwargs): self._remotefsclient = None super(WindowsSmbfsDriver, self).__init__(*args, **kwargs) @@ -134,6 +140,12 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin, self._smbutils = utilsfactory.get_smbutils() self._diskutils = utilsfactory.get_diskutils() + thin_enabled = ( + CONF.backend_defaults.nas_volume_prov_type == + 'thin') + self._thin_provisioning_support = thin_enabled + self._thick_provisioning_support = not thin_enabled + def do_setup(self, context): self._check_os_platform() @@ -329,7 +341,10 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin, err_msg = _("Unsupported volume format: %s ") % volume_format raise exception.InvalidVolume(err_msg) - self._vhdutils.create_dynamic_vhd(volume_path, volume_size_bytes) + vhd_type = self._get_vhd_type() + + self._vhdutils.create_vhd(volume_path, vhd_type, + max_internal_size=volume_size_bytes) def _ensure_share_mounted(self, smbfs_share): mnt_flags = None @@ -520,12 +535,14 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin, """Fetch the image from image_service and write it to the volume.""" volume_path = self.local_path(volume) volume_format = self.get_volume_format(volume, qemu_format=True) + volume_subformat = self._get_vhd_type(qemu_subformat=True) self._delete(volume_path) image_utils.fetch_to_volume_format( context, image_service, image_id, volume_path, volume_format, - self.configuration.volume_dd_blocksize) + self.configuration.volume_dd_blocksize, + volume_subformat) self._vhdutils.resize_vhd(self.local_path(volume), volume.size * units.Gi, @@ -553,9 +570,12 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin, snapshot_path = os.path.join(vol_dir, img_info.backing_file) volume_path = self.local_path(volume) + vhd_type = self._get_vhd_type() + self._delete(volume_path) self._vhdutils.convert_vhd(snapshot_path, - volume_path) + volume_path, + vhd_type=vhd_type) self._vhdutils.resize_vhd(volume_path, volume_size * units.Gi, is_file_max_size=False) @@ -580,3 +600,13 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin, msg % dict(pool_name=pool_name, pool_mappings=self._pool_mappings)) return share + + def _get_vhd_type(self, qemu_subformat=False): + prov_type = CONF.backend_defaults.nas_volume_prov_type + + if qemu_subformat: + vhd_type = self._vhd_qemu_subformat_mapping[prov_type] + else: + vhd_type = self._vhd_type_mapping[prov_type] + + return vhd_type diff --git a/releasenotes/notes/smbfs-fixed-image-9b642b63fcb79c18.yaml b/releasenotes/notes/smbfs-fixed-image-9b642b63fcb79c18.yaml new file mode 100644 index 00000000000..3910925f1df --- /dev/null +++ b/releasenotes/notes/smbfs-fixed-image-9b642b63fcb79c18.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + The SMBFS volume driver can now be configured to use fixed vhd/x images + through the 'nas_volume_prov_type' config option.