From 85f0814e1a96ea043e8048cf7081f70fa024f20b Mon Sep 17 00:00:00 2001 From: Mike Perez Date: Thu, 19 Mar 2015 18:32:04 -0700 Subject: [PATCH] Removing Windows drivers for no reported CI CI deadlines were set and pushed since last year. An email about this requirement and the deadline of March 19th 2015 has been sent to each individual driver maintainer, as well as the mailing list [1]. This driver is being removed because the maintainer does not have a CI reporting to ensure their driver integration is successful. Therfore, we can not validate the driver is working in Cinder today in a continuous way. DocImpact [1]- http://lists.openstack.org/pipermail/openstack-dev/2015-January/054614.html Change-Id: Idd348bb81680c3f06a3a732d7e2ae657cceaa6f2 --- cinder/tests/windows/test_smbfs.py | 320 ------------------ cinder/tests/windows/test_windows_remotefs.py | 164 --------- cinder/volume/drivers/windows/remotefs.py | 141 -------- cinder/volume/drivers/windows/smbfs.py | 268 --------------- 4 files changed, 893 deletions(-) delete mode 100644 cinder/tests/windows/test_smbfs.py delete mode 100644 cinder/tests/windows/test_windows_remotefs.py delete mode 100644 cinder/volume/drivers/windows/remotefs.py delete mode 100644 cinder/volume/drivers/windows/smbfs.py diff --git a/cinder/tests/windows/test_smbfs.py b/cinder/tests/windows/test_smbfs.py deleted file mode 100644 index 9a7cd16f0..000000000 --- a/cinder/tests/windows/test_smbfs.py +++ /dev/null @@ -1,320 +0,0 @@ -# Copyright 2014 Cloudbase Solutions Srl -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import importlib -import os -import sys - -import mock - -from cinder import exception -from cinder.image import image_utils -from cinder import test - - -class WindowsSmbFsTestCase(test.TestCase): - - _FAKE_SHARE = '//1.2.3.4/share1' - _FAKE_MNT_BASE = 'c:\openstack\mnt' - _FAKE_MNT_POINT = os.path.join(_FAKE_MNT_BASE, 'fake_hash') - _FAKE_VOLUME_NAME = 'volume-4f711859-4928-4cb7-801a-a50c37ceaccc' - _FAKE_SNAPSHOT_NAME = _FAKE_VOLUME_NAME + '-snapshot.vhdx' - _FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, - _FAKE_VOLUME_NAME) - _FAKE_SNAPSHOT_PATH = os.path.join(_FAKE_MNT_POINT, - _FAKE_SNAPSHOT_NAME) - _FAKE_TOTAL_SIZE = '2048' - _FAKE_TOTAL_AVAILABLE = '1024' - _FAKE_TOTAL_ALLOCATED = 1024 - _FAKE_VOLUME = {'id': 'e8d76af4-cbb9-4b70-8e9e-5a133f1a1a66', - 'size': 1, - 'provider_location': _FAKE_SHARE} - _FAKE_SNAPSHOT = {'id': '35a23942-7625-4683-ad84-144b76e87a80', - 'volume': _FAKE_VOLUME, - 'volume_size': _FAKE_VOLUME['size']} - _FAKE_SHARE_OPTS = '-o username=Administrator,password=12345' - _FAKE_VOLUME_PATH = os.path.join(_FAKE_MNT_POINT, - _FAKE_VOLUME_NAME + '.vhdx') - _FAKE_LISTDIR = [_FAKE_VOLUME_NAME + '.vhd', - _FAKE_VOLUME_NAME + '.vhdx', 'fake_folder'] - - def setUp(self): - super(WindowsSmbFsTestCase, self).setUp() - self._mock_wmi = mock.MagicMock() - - self._platform_patcher = mock.patch('sys.platform', 'win32') - - mock.patch.dict(sys.modules, wmi=self._mock_wmi, - ctypes=self._mock_wmi).start() - - self._platform_patcher.start() - # self._wmi_patcher.start() - self.addCleanup(mock.patch.stopall) - - smbfs = importlib.import_module( - 'cinder.volume.drivers.windows.smbfs') - smbfs.WindowsSmbfsDriver.__init__ = lambda x: None - self._smbfs_driver = smbfs.WindowsSmbfsDriver() - self._smbfs_driver._remotefsclient = mock.Mock() - self._smbfs_driver._delete = mock.Mock() - self._smbfs_driver.local_path = mock.Mock( - return_value=self._FAKE_VOLUME_PATH) - self._smbfs_driver.vhdutils = mock.Mock() - self._smbfs_driver._check_os_platform = mock.Mock() - - 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 - self._smbfs_driver.get_volume_format = mock.Mock( - return_value=volume_format) - - with mock.patch('os.path.exists', new=lambda x: volume_exists): - if volume_exists or volume_format not in ('vhd', 'vhdx'): - self.assertRaises(exception.InvalidVolume, - self._smbfs_driver._do_create_volume, - self._FAKE_VOLUME) - else: - fake_vol_path = self._FAKE_VOLUME_PATH - self._smbfs_driver._do_create_volume(self._FAKE_VOLUME) - fake_create.assert_called_once_with( - fake_vol_path, self._FAKE_VOLUME['size'] << 30) - - def test_create_volume(self): - self._test_create_volume() - - def test_create_existing_volume(self): - self._test_create_volume(True) - - def test_create_volume_invalid_volume(self): - self._test_create_volume(volume_format="qcow") - - def test_get_capacity_info(self): - self._smbfs_driver._remotefsclient.get_capacity_info = mock.Mock( - return_value=(self._FAKE_TOTAL_SIZE, self._FAKE_TOTAL_AVAILABLE)) - self._smbfs_driver._get_total_allocated = mock.Mock( - return_value=self._FAKE_TOTAL_ALLOCATED) - - ret_val = self._smbfs_driver._get_capacity_info(self._FAKE_SHARE) - expected_ret_val = [int(x) for x in [self._FAKE_TOTAL_SIZE, - self._FAKE_TOTAL_AVAILABLE, - self._FAKE_TOTAL_ALLOCATED]] - self.assertEqual(ret_val, expected_ret_val) - - def test_get_total_allocated(self): - fake_listdir = mock.Mock(side_effect=[self._FAKE_LISTDIR, - self._FAKE_LISTDIR[:-1]]) - fake_folder_path = os.path.join(self._FAKE_SHARE, 'fake_folder') - fake_isdir = lambda x: x == fake_folder_path - self._smbfs_driver._remotefsclient.is_symlink = mock.Mock( - return_value=False) - fake_getsize = mock.Mock(return_value=self._FAKE_VOLUME['size']) - self._smbfs_driver.vhdutils.get_vhd_size = mock.Mock( - return_value={'VirtualSize': 1}) - - with mock.patch.multiple('os.path', isdir=fake_isdir, - getsize=fake_getsize): - with mock.patch('os.listdir', fake_listdir): - ret_val = self._smbfs_driver._get_total_allocated( - self._FAKE_SHARE) - self.assertEqual(ret_val, 4) - - def _test_get_img_info(self, backing_file=None): - self._smbfs_driver.vhdutils.get_vhd_parent_path.return_value = ( - backing_file) - - image_info = self._smbfs_driver._qemu_img_info(self._FAKE_VOLUME_PATH) - self.assertEqual(self._FAKE_VOLUME_NAME + '.vhdx', - image_info.image) - backing_file_name = backing_file and os.path.basename(backing_file) - self.assertEqual(backing_file_name, image_info.backing_file) - - def test_get_img_info_without_backing_file(self): - self._test_get_img_info() - - def test_get_snapshot_info(self): - self._test_get_img_info(self._FAKE_VOLUME_PATH) - - def test_create_snapshot(self): - self._smbfs_driver.vhdutils.create_differencing_vhd = ( - mock.Mock()) - self._smbfs_driver._local_volume_dir = mock.Mock( - return_value=self._FAKE_MNT_POINT) - - fake_create_diff = ( - self._smbfs_driver.vhdutils.create_differencing_vhd) - - self._smbfs_driver._do_create_snapshot( - self._FAKE_SNAPSHOT, - os.path.basename(self._FAKE_VOLUME_PATH), - self._FAKE_SNAPSHOT_PATH) - - fake_create_diff.assert_called_once_with(self._FAKE_SNAPSHOT_PATH, - self._FAKE_VOLUME_PATH) - - def _test_copy_volume_to_image(self, has_parent=False, - volume_format='vhd'): - drv = self._smbfs_driver - - fake_image_meta = {'id': 'fake-image-id'} - - if has_parent: - fake_volume_path = self._FAKE_SNAPSHOT_PATH - fake_parent_path = self._FAKE_VOLUME_PATH - else: - fake_volume_path = self._FAKE_VOLUME_PATH - fake_parent_path = None - - if volume_format == drv._DISK_FORMAT_VHD: - fake_volume_path = fake_volume_path[:-1] - - fake_active_image = os.path.basename(fake_volume_path) - - drv.get_active_image_from_info = mock.Mock( - return_value=fake_active_image) - drv._local_volume_dir = mock.Mock( - return_value=self._FAKE_MNT_POINT) - drv.get_volume_format = mock.Mock( - return_value=volume_format) - drv.vhdutils.get_vhd_parent_path.return_value = ( - fake_parent_path) - - with mock.patch.object(image_utils, 'upload_volume') as ( - fake_upload_volume): - drv.copy_volume_to_image( - mock.sentinel.context, self._FAKE_VOLUME, - mock.sentinel.image_service, fake_image_meta) - - expected_conversion = ( - has_parent or volume_format == drv._DISK_FORMAT_VHDX) - - if expected_conversion: - fake_temp_image_name = '%s.temp_image.%s.%s' % ( - self._FAKE_VOLUME['id'], - fake_image_meta['id'], - drv._DISK_FORMAT_VHD) - fake_temp_image_path = os.path.join( - self._FAKE_MNT_POINT, - fake_temp_image_name) - fake_active_image_path = os.path.join( - self._FAKE_MNT_POINT, - fake_active_image) - upload_path = fake_temp_image_path - - drv.vhdutils.convert_vhd.assert_called_once_with( - fake_active_image_path, - fake_temp_image_path) - drv._delete.assert_called_once_with( - fake_temp_image_path) - else: - upload_path = fake_volume_path - - fake_upload_volume.assert_called_once_with( - mock.sentinel.context, mock.sentinel.image_service, - fake_image_meta, upload_path, drv._DISK_FORMAT_VHD) - - def test_copy_volume_to_image_having_snapshot(self): - self._test_copy_volume_to_image(has_parent=True) - - def test_copy_vhdx_volume_to_image(self): - self._test_copy_volume_to_image(volume_format='vhdx') - - def test_copy_vhd_volume_to_image(self): - self._test_copy_volume_to_image(volume_format='vhd') - - def _test_copy_image_to_volume(self, qemu_version=[1, 7]): - drv = self._smbfs_driver - - fake_image_id = 'fake_image_id' - fake_image_service = mock.MagicMock() - fake_image_service.show.return_value = ( - {'id': fake_image_id, 'disk_format': 'raw'}) - - drv.get_volume_format = mock.Mock( - return_value='vhdx') - drv.local_path = mock.Mock( - return_value=self._FAKE_VOLUME_PATH) - drv._local_volume_dir = mock.Mock( - return_value=self._FAKE_MNT_POINT) - drv.get_qemu_version = mock.Mock( - return_value=qemu_version) - drv.configuration = mock.MagicMock() - drv.configuration.volume_dd_blocksize = mock.sentinel.block_size - - with mock.patch.object(image_utils, - 'fetch_to_volume_format') as fake_fetch: - drv.copy_image_to_volume( - mock.sentinel.context, self._FAKE_VOLUME, - fake_image_service, - fake_image_id) - - if qemu_version < [1, 7]: - fake_temp_image_name = '%s.temp_image.%s.vhd' % ( - self._FAKE_VOLUME['id'], - fake_image_id) - fetch_path = os.path.join(self._FAKE_MNT_POINT, - fake_temp_image_name) - fetch_format = 'vpc' - drv.vhdutils.convert_vhd.assert_called_once_with( - fetch_path, self._FAKE_VOLUME_PATH) - drv._delete.assert_called_with(fetch_path) - - else: - fetch_path = self._FAKE_VOLUME_PATH - fetch_format = 'vhdx' - - fake_fetch.assert_called_once_with( - mock.sentinel.context, fake_image_service, fake_image_id, - fetch_path, fetch_format, mock.sentinel.block_size) - - def test_copy_image_to_volume(self): - self._test_copy_image_to_volume() - - def test_copy_image_to_volume_with_conversion(self): - self._test_copy_image_to_volume([1, 5]) - - def test_copy_volume_from_snapshot(self): - drv = self._smbfs_driver - fake_volume_info = { - self._FAKE_SNAPSHOT['id']: 'fake_snapshot_file_name'} - fake_img_info = mock.MagicMock() - fake_img_info.backing_file = self._FAKE_VOLUME_NAME + '.vhdx' - - drv._local_path_volume_info = mock.Mock( - return_value=self._FAKE_VOLUME_PATH + '.info') - drv._local_volume_dir = mock.Mock( - return_value=self._FAKE_MNT_POINT) - drv._read_info_file = mock.Mock( - return_value=fake_volume_info) - drv._qemu_img_info = mock.Mock( - return_value=fake_img_info) - drv.local_path = mock.Mock( - return_value=mock.sentinel.new_volume_path) - - drv._copy_volume_from_snapshot( - self._FAKE_SNAPSHOT, self._FAKE_VOLUME, - self._FAKE_VOLUME['size']) - - 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) - drv.vhdutils.resize_vhd.assert_called_once_with( - mock.sentinel.new_volume_path, self._FAKE_VOLUME['size'] << 30) - - def test_rebase_img(self): - self._smbfs_driver._rebase_img( - self._FAKE_SNAPSHOT_PATH, - self._FAKE_VOLUME_NAME + '.vhdx', 'vhdx') - self._smbfs_driver.vhdutils.reconnect_parent.assert_called_once_with( - self._FAKE_SNAPSHOT_PATH, self._FAKE_VOLUME_PATH) diff --git a/cinder/tests/windows/test_windows_remotefs.py b/cinder/tests/windows/test_windows_remotefs.py deleted file mode 100644 index 26bbcfedb..000000000 --- a/cinder/tests/windows/test_windows_remotefs.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright 2014 Cloudbase Solutions Srl -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ctypes -import os - -import mock - -from cinder import exception -from cinder import test -from cinder.volume.drivers.windows import remotefs - - -class WindowsRemoteFsTestCase(test.TestCase): - _FAKE_SHARE = '//1.2.3.4/share1' - _FAKE_MNT_BASE = 'C:\OpenStack\mnt' - _FAKE_HASH = 'db0bf952c1734092b83e8990bd321131' - _FAKE_MNT_POINT = os.path.join(_FAKE_MNT_BASE, _FAKE_HASH) - _FAKE_SHARE_OPTS = '-o username=Administrator,password=12345' - _FAKE_OPTIONS_DICT = {'username': 'Administrator', - 'password': '12345'} - - def setUp(self): - super(WindowsRemoteFsTestCase, self).setUp() - - remotefs.ctypes.windll = mock.MagicMock() - remotefs.WindowsRemoteFsClient.__init__ = mock.Mock(return_value=None) - - self._remotefs = remotefs.WindowsRemoteFsClient( - 'cifs', root_helper=None, - smbfs_mount_point_base=self._FAKE_MNT_BASE) - self._remotefs._mount_base = self._FAKE_MNT_BASE - self._remotefs.smb_conn = mock.MagicMock() - self._remotefs.conn_cimv2 = mock.MagicMock() - - def _test_mount_share(self, mount_point_exists=True, is_symlink=True, - mount_base_exists=True): - fake_exists = mock.Mock(return_value=mount_point_exists) - fake_isdir = mock.Mock(return_value=mount_base_exists) - fake_makedirs = mock.Mock() - with mock.patch.multiple('os.path', exists=fake_exists, - isdir=fake_isdir): - with mock.patch('os.makedirs', fake_makedirs): - self._remotefs.is_symlink = mock.Mock( - return_value=is_symlink) - self._remotefs.create_sym_link = mock.MagicMock() - self._remotefs._mount = mock.MagicMock() - fake_norm_path = os.path.abspath(self._FAKE_SHARE) - - if mount_point_exists: - if not is_symlink: - self.assertRaises(exception.SmbfsException, - self._remotefs.mount, - self._FAKE_MNT_POINT, - self._FAKE_OPTIONS_DICT) - else: - self._remotefs.mount(self._FAKE_SHARE, - self._FAKE_OPTIONS_DICT) - if not mount_base_exists: - fake_makedirs.assert_called_once_with( - self._FAKE_MNT_BASE) - self._remotefs._mount.assert_called_once_with( - fake_norm_path, self._FAKE_OPTIONS_DICT) - self._remotefs.create_sym_link.assert_called_once_with( - self._FAKE_MNT_POINT, fake_norm_path) - - def test_mount_linked_share(self): - # The mountpoint contains a symlink targeting the share path - self._test_mount_share(True) - - def test_mount_unlinked_share(self): - self._test_mount_share(False) - - def test_mount_point_exception(self): - # The mountpoint already exists but it is not a symlink - self._test_mount_share(True, False) - - def test_mount_base_missing(self): - # The mount point base dir does not exist - self._test_mount_share(mount_base_exists=False) - - def _test_check_symlink(self, is_symlink=True, python_version=(2, 7), - is_dir=True): - fake_isdir = mock.Mock(return_value=is_dir) - fake_islink = mock.Mock(return_value=is_symlink) - with mock.patch('sys.version_info', python_version): - with mock.patch.multiple('os.path', isdir=fake_isdir, - islink=fake_islink): - if is_symlink: - ret_value = 0x400 - else: - ret_value = 0x80 - fake_get_attributes = mock.Mock(return_value=ret_value) - ctypes.windll.kernel32.GetFileAttributesW = fake_get_attributes - - ret_value = self._remotefs.is_symlink(self._FAKE_MNT_POINT) - if python_version >= (3, 2): - fake_islink.assert_called_once_with(self._FAKE_MNT_POINT) - else: - fake_get_attributes.assert_called_once_with( - self._FAKE_MNT_POINT) - self.assertEqual(ret_value, is_symlink) - - def test_is_symlink(self): - self._test_check_symlink() - - def test_is_not_symlink(self): - self._test_check_symlink(False) - - def test_check_symlink_python_gt_3_2(self): - self._test_check_symlink(python_version=(3, 3)) - - def test_create_sym_link_exception(self): - ctypes.windll.kernel32.CreateSymbolicLinkW.return_value = 0 - self.assertRaises(exception.VolumeBackendAPIException, - self._remotefs.create_sym_link, - self._FAKE_MNT_POINT, self._FAKE_SHARE) - - def _test_check_smb_mapping(self, existing_mappings=False, - share_available=False): - with mock.patch('os.path.exists', lambda x: share_available): - fake_mapping = mock.MagicMock() - if existing_mappings: - fake_mappings = [fake_mapping] - else: - fake_mappings = [] - - self._remotefs.smb_conn.query.return_value = fake_mappings - ret_val = self._remotefs.check_smb_mapping(self._FAKE_SHARE) - - if existing_mappings: - if share_available: - self.assertTrue(ret_val) - else: - fake_mapping.Remove.assert_called_once_with(True, True) - else: - self.assertFalse(ret_val) - - def test_check_mapping(self): - self._test_check_smb_mapping() - - def test_remake_unavailable_mapping(self): - self._test_check_smb_mapping(True, False) - - def test_available_mapping(self): - self._test_check_smb_mapping(True, True) - - def test_mount_smb(self): - fake_create = self._remotefs.smb_conn.Msft_SmbMapping.Create - self._remotefs._mount(self._FAKE_SHARE, {}) - fake_create.assert_called_once_with(UserName=None, - Password=None, - RemotePath=self._FAKE_SHARE) diff --git a/cinder/volume/drivers/windows/remotefs.py b/cinder/volume/drivers/windows/remotefs.py deleted file mode 100644 index c3acc41c7..000000000 --- a/cinder/volume/drivers/windows/remotefs.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2014 Cloudbase Solutions Srl -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ctypes -import os -import sys - -if sys.platform == 'win32': - import wmi - -from oslo_log import log as logging - -from cinder.brick.remotefs import remotefs -from cinder import exception -from cinder.i18n import _, _LE, _LI - -LOG = logging.getLogger(__name__) - - -class WindowsRemoteFsClient(remotefs.RemoteFsClient): - _FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 - - def __init__(self, *args, **kwargs): - super(WindowsRemoteFsClient, self).__init__(*args, **kwargs) - self.smb_conn = wmi.WMI(moniker='root/Microsoft/Windows/SMB') - self.conn_cimv2 = wmi.WMI(moniker='root/cimv2') - - def mount(self, export_path, mnt_options=None): - if not os.path.isdir(self._mount_base): - os.makedirs(self._mount_base) - export_hash = self._get_hash_str(export_path) - - norm_path = os.path.abspath(export_path) - mnt_options = mnt_options or {} - - if not self.check_smb_mapping(norm_path): - self._mount(norm_path, mnt_options) - - link_path = os.path.join(self._mount_base, export_hash) - if os.path.exists(link_path): - if not self.is_symlink(link_path): - raise exception.SmbfsException(_("Link path already exists " - "and its not a symlink")) - else: - self.create_sym_link(link_path, norm_path) - - def is_symlink(self, path): - if sys.version_info >= (3, 2): - return os.path.islink(path) - - file_attr = ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) - - return bool(os.path.isdir(path) and ( - file_attr & self._FILE_ATTRIBUTE_REPARSE_POINT)) - - def create_sym_link(self, link, target, target_is_dir=True): - """If target_is_dir is True, a junction will be created. - - NOTE: Juctions only work on same filesystem. - """ - symlink = ctypes.windll.kernel32.CreateSymbolicLinkW - symlink.argtypes = ( - ctypes.c_wchar_p, - ctypes.c_wchar_p, - ctypes.c_ulong, - ) - symlink.restype = ctypes.c_ubyte - retcode = symlink(link, target, target_is_dir) - if retcode == 0: - err_msg = (_("Could not create symbolic link. " - "Link: %(link)s Target %(target)s") - % {'link': link, 'target': target}) - raise exception.VolumeBackendAPIException(err_msg) - - def check_smb_mapping(self, smbfs_share): - mappings = self.smb_conn.query("SELECT * FROM " - "MSFT_SmbMapping " - "WHERE RemotePath='%s'" % - smbfs_share) - - if len(mappings) > 0: - if os.path.exists(smbfs_share): - LOG.debug('Share already mounted: %s' % smbfs_share) - return True - else: - LOG.debug('Share exists but is unavailable: %s ' - % smbfs_share) - for mapping in mappings: - # Due to a bug in the WMI module, getting the output of - # methods returning None will raise an AttributeError - try: - mapping.Remove(True, True) - except AttributeError: - pass - return False - - def _mount(self, smbfs_share, options): - smb_opts = {'RemotePath': smbfs_share} - smb_opts['UserName'] = (options.get('username') or - options.get('user')) - smb_opts['Password'] = (options.get('password') or - options.get('pass')) - - try: - LOG.info(_LI('Mounting share: %s') % smbfs_share) - self.smb_conn.Msft_SmbMapping.Create(**smb_opts) - except wmi.x_wmi as exc: - err_msg = (_( - 'Unable to mount SMBFS share: %(smbfs_share)s ' - 'WMI exception: %(wmi_exc)s' - 'Options: %(options)s') % {'smbfs_share': smbfs_share, - 'options': smb_opts, - 'wmi_exc': exc}) - raise exception.VolumeBackendAPIException(data=err_msg) - - def get_capacity_info(self, smbfs_share): - norm_path = os.path.abspath(smbfs_share) - kernel32 = ctypes.windll.kernel32 - - free_bytes = ctypes.c_ulonglong(0) - total_bytes = ctypes.c_ulonglong(0) - retcode = kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(norm_path), - None, - ctypes.pointer(total_bytes), - ctypes.pointer(free_bytes)) - if retcode == 0: - LOG.error(_LE("Could not get share %s capacity info.") % - smbfs_share) - return 0, 0 - return total_bytes.value, free_bytes.value diff --git a/cinder/volume/drivers/windows/smbfs.py b/cinder/volume/drivers/windows/smbfs.py deleted file mode 100644 index 8ec9688ca..000000000 --- a/cinder/volume/drivers/windows/smbfs.py +++ /dev/null @@ -1,268 +0,0 @@ -# Copyright (c) 2014 Cloudbase Solutions SRL -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import os -import re -import sys - -from oslo_config import cfg -from oslo_log import log as logging -from oslo_utils import units - -from cinder import exception -from cinder.i18n import _ -from cinder.image import image_utils -from cinder.openstack.common import fileutils -from cinder import utils -from cinder.volume.drivers import smbfs -from cinder.volume.drivers.windows import remotefs -from cinder.volume.drivers.windows import vhdutils - -VERSION = '1.0.0' - -LOG = logging.getLogger(__name__) - -CONF = cfg.CONF -CONF.set_default('smbfs_shares_config', r'C:\OpenStack\smbfs_shares.txt') -CONF.set_default('smbfs_mount_point_base', r'C:\OpenStack\_mnt') -CONF.set_default('smbfs_default_volume_format', 'vhd') - - -class WindowsSmbfsDriver(smbfs.SmbfsDriver): - VERSION = VERSION - - def __init__(self, *args, **kwargs): - super(WindowsSmbfsDriver, self).__init__(*args, **kwargs) - self.base = getattr(self.configuration, - 'smbfs_mount_point_base', - CONF.smbfs_mount_point_base) - opts = getattr(self.configuration, - 'smbfs_mount_options', - CONF.smbfs_mount_options) - self._remotefsclient = remotefs.WindowsRemoteFsClient( - 'cifs', root_helper=None, smbfs_mount_point_base=self.base, - smbfs_mount_options=opts) - self.vhdutils = vhdutils.VHDUtils() - - def do_setup(self, context): - self._check_os_platform() - super(WindowsSmbfsDriver, self).do_setup(context) - - def _check_os_platform(self): - if sys.platform != 'win32': - _msg = _("This system platform (%s) is not supported. This " - "driver supports only Win32 platforms.") % sys.platform - raise exception.SmbfsException(_msg) - - def _do_create_volume(self, volume): - volume_path = self.local_path(volume) - volume_format = self.get_volume_format(volume) - volume_size_bytes = volume['size'] * units.Gi - - if os.path.exists(volume_path): - err_msg = _('File already exists at: %s') % volume_path - raise exception.InvalidVolume(err_msg) - - if volume_format not in (self._DISK_FORMAT_VHD, - self._DISK_FORMAT_VHDX): - err_msg = _("Unsupported volume format: %s ") % volume_format - raise exception.InvalidVolume(err_msg) - - self.vhdutils.create_dynamic_vhd(volume_path, volume_size_bytes) - - def _ensure_share_mounted(self, smbfs_share): - mnt_options = {} - if self.shares.get(smbfs_share) is not None: - mnt_flags = self.shares[smbfs_share] - mnt_options = self.parse_options(mnt_flags)[1] - self._remotefsclient.mount(smbfs_share, mnt_options) - - def _delete(self, path): - fileutils.delete_if_exists(path) - - def _get_capacity_info(self, smbfs_share): - """Calculate available space on the SMBFS share. - - :param smbfs_share: example //172.18.194.100/var/smbfs - """ - total_size, total_available = self._remotefsclient.get_capacity_info( - smbfs_share) - total_allocated = self._get_total_allocated(smbfs_share) - return_value = [total_size, total_available, total_allocated] - LOG.info('Smb share %s Total size %s Total allocated %s' - % (smbfs_share, total_size, total_allocated)) - return [float(x) for x in return_value] - - def _get_total_allocated(self, smbfs_share): - elements = os.listdir(smbfs_share) - total_allocated = 0 - for element in elements: - element_path = os.path.join(smbfs_share, element) - if not self._remotefsclient.is_symlink(element_path): - if "snapshot" in element: - continue - if re.search(r'\.vhdx?$', element): - total_allocated += self.vhdutils.get_vhd_size( - element_path)['VirtualSize'] - continue - if os.path.isdir(element_path): - total_allocated += self._get_total_allocated(element_path) - continue - total_allocated += os.path.getsize(element_path) - - return total_allocated - - def _img_commit(self, snapshot_path): - self.vhdutils.merge_vhd(snapshot_path) - self._delete(snapshot_path) - - def _rebase_img(self, image, backing_file, volume_format): - # Relative path names are not supported in this case. - image_dir = os.path.dirname(image) - backing_file_path = os.path.join(image_dir, backing_file) - self.vhdutils.reconnect_parent(image, backing_file_path) - - def _qemu_img_info(self, path, volume_name=None): - # This code expects to deal only with relative filenames. - # As this method is needed by the upper class and qemu-img does - # not fully support vhdx images, for the moment we'll use Win32 API - # for retrieving image information. - parent_path = self.vhdutils.get_vhd_parent_path(path) - file_format = os.path.splitext(path)[1][1:].lower() - - if parent_path: - backing_file_name = os.path.split(parent_path)[1].lower() - else: - backing_file_name = None - - class ImageInfo(object): - def __init__(self, image, backing_file): - self.image = image - self.backing_file = backing_file - self.file_format = file_format - - return ImageInfo(os.path.basename(path), - backing_file_name) - - def _do_create_snapshot(self, snapshot, backing_file, new_snap_path): - backing_file_full_path = os.path.join( - self._local_volume_dir(snapshot['volume']), - backing_file) - self.vhdutils.create_differencing_vhd(new_snap_path, - backing_file_full_path) - - def _do_extend_volume(self, volume_path, size_gb): - self.vhdutils.resize_vhd(volume_path, size_gb * units.Gi) - - @utils.synchronized('smbfs', external=False) - def copy_volume_to_image(self, context, volume, image_service, image_meta): - """Copy the volume to the specified image.""" - - # If snapshots exist, flatten to a temporary image, and upload it - - active_file = self.get_active_image_from_info(volume) - active_file_path = os.path.join(self._local_volume_dir(volume), - active_file) - backing_file = self.vhdutils.get_vhd_parent_path(active_file_path) - root_file_fmt = self.get_volume_format(volume) - - temp_path = None - - try: - if backing_file or root_file_fmt == self._DISK_FORMAT_VHDX: - temp_file_name = '%s.temp_image.%s.%s' % ( - volume['id'], - image_meta['id'], - self._DISK_FORMAT_VHD) - temp_path = os.path.join(self._local_volume_dir(volume), - temp_file_name) - - self.vhdutils.convert_vhd(active_file_path, temp_path) - upload_path = temp_path - else: - upload_path = active_file_path - - image_utils.upload_volume(context, - image_service, - image_meta, - upload_path, - self._DISK_FORMAT_VHD) - finally: - if temp_path: - self._delete(temp_path) - - def copy_image_to_volume(self, context, volume, image_service, image_id): - """Fetch the image from image_service and write it to the volume.""" - volume_format = self.get_volume_format(volume, qemu_format=True) - image_meta = image_service.show(context, image_id) - - fetch_format = volume_format - fetch_path = self.local_path(volume) - self._delete(fetch_path) - qemu_version = self.get_qemu_version() - - needs_conversion = False - - if (qemu_version < [1, 7] and ( - volume_format == self._DISK_FORMAT_VHDX and - image_meta['disk_format'] != self._DISK_FORMAT_VHDX)): - needs_conversion = True - fetch_format = 'vpc' - temp_file_name = '%s.temp_image.%s.%s' % ( - volume['id'], - image_meta['id'], - self._DISK_FORMAT_VHD) - fetch_path = os.path.join(self._local_volume_dir(volume), - temp_file_name) - - image_utils.fetch_to_volume_format( - context, image_service, image_id, - fetch_path, fetch_format, - self.configuration.volume_dd_blocksize) - - if needs_conversion: - self.vhdutils.convert_vhd(fetch_path, self.local_path(volume)) - self._delete(fetch_path) - - self.vhdutils.resize_vhd(self.local_path(volume), - volume['size'] * units.Gi) - - def _copy_volume_from_snapshot(self, snapshot, volume, volume_size): - """Copy data from snapshot to destination volume.""" - - LOG.debug("snapshot: %(snap)s, volume: %(vol)s, " - "volume_size: %(size)s" % - {'snap': snapshot['id'], - 'vol': volume['id'], - 'size': snapshot['volume_size']}) - - info_path = self._local_path_volume_info(snapshot['volume']) - snap_info = self._read_info_file(info_path) - vol_dir = self._local_volume_dir(snapshot['volume']) - - forward_file = snap_info[snapshot['id']] - forward_path = os.path.join(vol_dir, forward_file) - - # Find the file which backs this file, which represents the point - # when this snapshot was created. - img_info = self._qemu_img_info(forward_path) - snapshot_path = os.path.join(vol_dir, img_info.backing_file) - - volume_path = self.local_path(volume) - self._delete(volume_path) - self.vhdutils.convert_vhd(snapshot_path, - volume_path) - self.vhdutils.resize_vhd(volume_path, volume_size * units.Gi) -- 2.45.2