SMBFS: add fixed image support
The SMBFS driver currently supports only dynamic vhd/x images. This change will allow configuring the driver to use fixed images using the 'nas_volume_prov_type' config option. Note that fixed images will always be zeroed out. We recommend placing the images on ReFS/SSD backed storage. Implements: blueprint smbfs-fixed-images Change-Id: Ic9e724fcda83fea384406f45f792f7a2d4b979bb
This commit is contained in:
parent
4cfc201b72
commit
54c2787132
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user