diff --git a/os_win/tests/unit/test_utilsfactory.py b/os_win/tests/unit/test_utilsfactory.py index a5de941..5dbaeba 100644 --- a/os_win/tests/unit/test_utilsfactory.py +++ b/os_win/tests/unit/test_utilsfactory.py @@ -32,7 +32,6 @@ from os_win.utils import hostutils from os_win.utils.network import networkutils from os_win.utils import pathutils from os_win.utils.storage import diskutils -from os_win.utils.storage.initiator import iscsi_cli_utils from os_win.utils.storage.initiator import iscsi_utils from os_win.utils.storage import smbutils from os_win.utils.storage.virtdisk import vhdutils @@ -107,25 +106,9 @@ class TestHyperVUtilsFactory(test_base.OsWinBaseTestCase): self._check_get_class(expected_class=rdpconsoleutils.RDPConsoleUtils, class_type='rdpconsoleutils') - @mock.patch.object(iscsi_utils.ISCSIInitiatorUtils, '__init__', - lambda *args, **kwargs: None) def test_get_iscsi_initiator_utils(self): - self._test_get_initiator_utils( - expected_class=iscsi_utils.ISCSIInitiatorUtils) - - def test_get_iscsi_initiator_utils_force_v1(self): - self._test_get_initiator_utils( - expected_class=iscsi_cli_utils.ISCSIInitiatorCLIUtils, - force_v1=True) - - @mock.patch.object(utilsfactory.utils, 'get_windows_version') - def _test_get_initiator_utils(self, mock_get_windows_version, - expected_class, force_v1=False): - CONF.set_override('force_volumeutils_v1', force_v1, 'hyperv') - mock_get_windows_version.return_value = '6.2' - - actual_class = type(utilsfactory.get_iscsi_initiator_utils()) - self.assertEqual(expected_class, actual_class) + self._check_get_class(expected_class=iscsi_utils.ISCSIInitiatorUtils, + class_type='iscsi_initiator_utils') @mock.patch('os_win.utils.storage.initiator.fc_utils.FCUtils') def test_get_fc_utils(self, mock_cls_fcutils): diff --git a/os_win/tests/unit/utils/storage/initiator/test_base_iscsi_utils.py b/os_win/tests/unit/utils/storage/initiator/test_base_iscsi_utils.py deleted file mode 100644 index 33199b5..0000000 --- a/os_win/tests/unit/utils/storage/initiator/test_base_iscsi_utils.py +++ /dev/null @@ -1,181 +0,0 @@ -# Copyright 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 mock - -from os_win.tests.unit import test_base -from os_win.utils.storage.initiator import base_iscsi_utils - - -class BaseISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase): - """Unit tests for the Hyper-V BaseISCSIInitiatorUtils class.""" - - _FAKE_COMPUTER_NAME = "fake_computer_name" - _FAKE_DOMAIN_NAME = "fake_domain_name" - _FAKE_INITIATOR_NAME = "fake_initiator_name" - _FAKE_INITIATOR_IQN_NAME = "iqn.1991-05.com.microsoft:fake_computer_name" - _FAKE_DISK_PATH = 'fake_path DeviceID="123\\\\2"' - _FAKE_MOUNT_DEVICE = '/dev/fake/mount' - _FAKE_DEVICE_NAME = '/dev/fake/path' - _FAKE_SWAP = {'device_name': _FAKE_DISK_PATH} - - def setUp(self): - self._utils = base_iscsi_utils.BaseISCSIInitiatorUtils() - self._utils._conn_wmi = mock.MagicMock() - self._utils._conn_cimv2 = mock.MagicMock() - - super(BaseISCSIInitiatorUtilsTestCase, self).setUp() - - def test_get_iscsi_initiator_ok(self): - self._check_get_iscsi_initiator( - self._FAKE_INITIATOR_NAME) - - def test_get_iscsi_initiator_exception(self): - initiator_name = "%(iqn)s.%(domain)s" % { - 'iqn': self._FAKE_INITIATOR_IQN_NAME, - 'domain': self._FAKE_DOMAIN_NAME - } - - self._check_get_iscsi_initiator(initiator_name, - side_effect=Exception) - - def _check_get_iscsi_initiator(self, expected=None, side_effect=None): - mock_computer = mock.MagicMock() - mock_computer.name = self._FAKE_COMPUTER_NAME - mock_computer.Domain = self._FAKE_DOMAIN_NAME - self._utils._conn_cimv2.Win32_ComputerSystem.return_value = [ - mock_computer] - - expected_key_path = ( - "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\" - "iSCSI\\Discovery") - - with mock.patch.object(base_iscsi_utils, - 'winreg', create=True) as mock_winreg: - mock_winreg.CloseKey.side_effect = side_effect - mock_winreg.QueryValueEx.return_value = [expected] - mock_winreg.OpenKey.return_value = mock.sentinel.key - - initiator_name = self._utils.get_iscsi_initiator() - self.assertEqual(expected, initiator_name) - mock_winreg.OpenKey.assert_called_once_with( - mock_winreg.HKEY_LOCAL_MACHINE, - expected_key_path, - 0, - mock_winreg.KEY_WOW64_64KEY + mock_winreg.KEY_ALL_ACCESS) - mock_winreg.QueryValueEx.assert_called_once_with( - mock.sentinel.key, "DefaultInitiatorName") - mock_winreg.CloseKey.assert_called_once_with(mock.sentinel.key) - - def test_get_drive_number_from_disk_path(self): - fake_disk_path = ( - '\\\\WIN-I5BTVHOIFGK\\root\\virtualization\\v2:Msvm_DiskDrive.' - 'CreationClassName="Msvm_DiskDrive",DeviceID="Microsoft:353B3BE8-' - '310C-4cf4-839E-4E1B14616136\\\\1",SystemCreationClassName=' - '"Msvm_ComputerSystem",SystemName="WIN-I5BTVHOIFGK"') - expected_disk_number = 1 - - ret_val = self._utils._get_drive_number_from_disk_path( - fake_disk_path) - - self.assertEqual(expected_disk_number, ret_val) - - def test_get_drive_number_not_found(self): - fake_disk_path = 'fake_disk_path' - - ret_val = self._utils._get_drive_number_from_disk_path( - fake_disk_path) - - self.assertFalse(ret_val) - - @mock.patch.object(base_iscsi_utils.BaseISCSIInitiatorUtils, - "_get_drive_number_from_disk_path") - def test_get_session_id_from_mounted_disk(self, mock_get_session_id): - mock_get_session_id.return_value = mock.sentinel.FAKE_DEVICE_NUMBER - mock_initiator_session = self._create_initiator_session() - mock_ses_class = self._utils._conn_wmi.MSiSCSIInitiator_SessionClass - mock_ses_class.return_value = [mock_initiator_session] - - session_id = self._utils.get_session_id_from_mounted_disk( - self._FAKE_DISK_PATH) - - self.assertEqual(mock.sentinel.FAKE_SESSION_ID, session_id) - - def test_get_devices_for_target(self): - init_session = self._create_initiator_session() - mock_ses_class = self._utils._conn_wmi.MSiSCSIInitiator_SessionClass - mock_ses_class.return_value = [init_session] - devices = self._utils._get_devices_for_target( - mock.sentinel.FAKE_IQN) - - self.assertEqual(init_session.Devices, devices) - - def test_get_devices_for_target_not_found(self): - mock_ses_class = self._utils._conn_wmi.MSiSCSIInitiator_SessionClass - mock_ses_class.return_value = [] - devices = self._utils._get_devices_for_target(mock.sentinel.FAKE_IQN) - - self.assertEqual(0, len(devices)) - - @mock.patch.object(base_iscsi_utils.BaseISCSIInitiatorUtils, - '_get_devices_for_target') - def test_get_device_number_for_target(self, fake_get_devices): - init_session = self._create_initiator_session() - fake_get_devices.return_value = init_session.Devices - mock_ses_class = self._utils._conn_wmi.MSiSCSIInitiator_SessionClass - mock_ses_class.return_value = [init_session] - device_number = self._utils.get_device_number_for_target( - mock.sentinel.FAKE_IQN, mock.sentinel.FAKE_LUN) - - self.assertEqual(mock.sentinel.FAKE_DEVICE_NUMBER, device_number) - - @mock.patch.object(base_iscsi_utils.BaseISCSIInitiatorUtils, - '_get_devices_for_target') - def test_get_target_lun_count(self, fake_get_devices): - init_session = self._create_initiator_session() - # Only disk devices are being counted. - disk_device = mock.Mock(DeviceType=self._utils._FILE_DEVICE_DISK) - init_session.Devices.append(disk_device) - fake_get_devices.return_value = init_session.Devices - - lun_count = self._utils.get_target_lun_count(mock.sentinel.FAKE_IQN) - - self.assertEqual(1, lun_count) - - @mock.patch.object(base_iscsi_utils.BaseISCSIInitiatorUtils, - "_get_drive_number_from_disk_path") - def test_get_target_from_disk_path(self, mock_get_session_id): - mock_get_session_id.return_value = mock.sentinel.FAKE_DEVICE_NUMBER - init_sess = self._create_initiator_session() - mock_ses_class = self._utils._conn_wmi.MSiSCSIInitiator_SessionClass - mock_ses_class.return_value = [init_sess] - - (target_name, scsi_lun) = self._utils.get_target_from_disk_path( - self._FAKE_DISK_PATH) - - self.assertEqual(mock.sentinel.FAKE_TARGET_NAME, target_name) - self.assertEqual(mock.sentinel.FAKE_LUN, scsi_lun) - - def _create_initiator_session(self): - device = mock.MagicMock() - device.ScsiLun = mock.sentinel.FAKE_LUN - device.DeviceNumber = mock.sentinel.FAKE_DEVICE_NUMBER - device.TargetName = mock.sentinel.FAKE_TARGET_NAME - init_session = mock.MagicMock() - init_session.Devices = [device] - init_session.SessionId = mock.sentinel.FAKE_SESSION_ID - - return init_session diff --git a/os_win/tests/unit/utils/storage/initiator/test_iscsi_cli_utils.py b/os_win/tests/unit/utils/storage/initiator/test_iscsi_cli_utils.py deleted file mode 100644 index 0c477af..0000000 --- a/os_win/tests/unit/utils/storage/initiator/test_iscsi_cli_utils.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright 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 mock -from oslotest import base - -from os_win import exceptions -from os_win.utils.storage.initiator import iscsi_cli_utils - - -class ISCSIInitiatorCLIUtilsTestCase(base.BaseTestCase): - """Unit tests for the Hyper-V ISCSIInitiatorCLIUtils class.""" - - _FAKE_PORTAL_ADDR = '10.1.1.1' - _FAKE_PORTAL_PORT = '3260' - _FAKE_LUN = 0 - _FAKE_TARGET = 'iqn.2010-10.org.openstack:fake_target' - - _FAKE_STDOUT_VALUE = 'The operation completed successfully' - - def setUp(self): - super(ISCSIInitiatorCLIUtilsTestCase, self).setUp() - self._initiator = iscsi_cli_utils.ISCSIInitiatorCLIUtils() - self._initiator._conn_wmi = mock.MagicMock() - self._initiator._conn_cimv2 = mock.MagicMock() - - def _test_login_target_portal(self, portal_connected): - fake_portal = '%s:%s' % (self._FAKE_PORTAL_ADDR, - self._FAKE_PORTAL_PORT) - - self._initiator.execute = mock.MagicMock() - if portal_connected: - exec_output = 'Address and Socket: %s %s' % ( - self._FAKE_PORTAL_ADDR, self._FAKE_PORTAL_PORT) - else: - exec_output = '' - - self._initiator.execute.return_value = exec_output - - self._initiator._login_target_portal(fake_portal) - - call_list = self._initiator.execute.call_args_list - all_call_args = [arg for call in call_list for arg in call[0]] - - if portal_connected: - self.assertIn('RefreshTargetPortal', all_call_args) - else: - self.assertIn('AddTargetPortal', all_call_args) - - def test_login_connected_portal(self): - self._test_login_target_portal(True) - - def test_login_new_portal(self): - self._test_login_target_portal(False) - - @mock.patch.object(iscsi_cli_utils, 'CONF') - def _test_login_target(self, mock_CONF, target_connected=False, - raise_exception=False, use_chap=False): - mock_CONF.hyperv.volume_attach_retry_count = 4 - mock_CONF.hyperv.volume_attach_retry_interval = 0 - fake_portal = '%s:%s' % (self._FAKE_PORTAL_ADDR, - self._FAKE_PORTAL_PORT) - self._initiator.execute = mock.MagicMock() - self._initiator._login_target_portal = mock.MagicMock() - - if use_chap: - username, password = (mock.sentinel.username, - mock.sentinel.password) - else: - username, password = None, None - - if target_connected: - self._initiator.execute.return_value = self._FAKE_TARGET - elif raise_exception: - self._initiator.execute.return_value = '' - else: - self._initiator.execute.side_effect = ( - ['', '', '', self._FAKE_TARGET, '']) - - if raise_exception: - self.assertRaises(exceptions.HyperVException, - self._initiator.login_storage_target, - self._FAKE_LUN, self._FAKE_TARGET, - fake_portal, username, password) - else: - self._initiator.login_storage_target(self._FAKE_LUN, - self._FAKE_TARGET, - fake_portal, - username, password) - - if target_connected: - call_list = self._initiator.execute.call_args_list - all_call_args = [arg for call in call_list for arg in call[0]] - self.assertNotIn('qlogintarget', all_call_args) - else: - self._initiator.execute.assert_any_call( - 'iscsicli.exe', 'qlogintarget', - self._FAKE_TARGET, username, password) - - def test_login_connected_target(self): - self._test_login_target(target_connected=True) - - def test_login_disconncted_target(self): - self._test_login_target() - - def test_login_target_exception(self): - self._test_login_target(raise_exception=True) - - def test_login_target_using_chap(self): - self._test_login_target(use_chap=True) - - def _test_execute_wrapper(self, raise_exception): - fake_cmd = ('iscsicli.exe', 'ListTargetPortals') - - if raise_exception: - output = 'fake error' - else: - output = 'The operation completed successfully' - - with mock.patch('os_win._utils.execute') as fake_execute: - fake_execute.return_value = (output, None) - - if raise_exception: - self.assertRaises(exceptions.HyperVException, - self._initiator.execute, - *fake_cmd) - else: - ret_val = self._initiator.execute(*fake_cmd) - self.assertEqual(output, ret_val) - - def test_execute_raise_exception(self): - self._test_execute_wrapper(True) - - def test_execute_exception(self): - self._test_execute_wrapper(False) - - @mock.patch.object(iscsi_cli_utils, '_utils') - def test_logout_storage_target(self, mock_utils): - mock_utils.execute.return_value = (self._FAKE_STDOUT_VALUE, - mock.sentinel.FAKE_STDERR_VALUE) - session = mock.MagicMock() - session.SessionId = mock.sentinel.FAKE_SESSION_ID - self._initiator._conn_wmi.query.return_value = [session] - - self._initiator.logout_storage_target(mock.sentinel.FAKE_IQN) - mock_utils.execute.assert_called_once_with( - 'iscsicli.exe', 'logouttarget', mock.sentinel.FAKE_SESSION_ID) diff --git a/os_win/tests/unit/utils/storage/initiator/test_iscsi_wmi_utils.py b/os_win/tests/unit/utils/storage/initiator/test_iscsi_wmi_utils.py deleted file mode 100644 index cfd7981..0000000 --- a/os_win/tests/unit/utils/storage/initiator/test_iscsi_wmi_utils.py +++ /dev/null @@ -1,161 +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 mock - -from os_win import exceptions -from os_win.tests.unit import test_base -from os_win.utils.storage.initiator import iscsi_wmi_utils - - -class ISCSIInitiatorWMIUtilsTestCase(test_base.OsWinBaseTestCase): - """Unit tests for the Hyper-V ISCSIInitiatorWMIUtils class.""" - - _FAKE_PORTAL_ADDR = '10.1.1.1' - _FAKE_PORTAL_PORT = '3260' - _FAKE_LUN = 0 - _FAKE_TARGET = 'iqn.2010-10.org.openstack:fake_target' - - def setUp(self): - super(ISCSIInitiatorWMIUtilsTestCase, self).setUp() - self._initiator = iscsi_wmi_utils.ISCSIInitiatorWMIUtils() - self._initiator._conn_storage = mock.MagicMock() - self._initiator._conn_wmi = mock.MagicMock() - - def _test_login_target_portal(self, portal_connected): - fake_portal = '%s:%s' % (self._FAKE_PORTAL_ADDR, - self._FAKE_PORTAL_PORT) - fake_portal_object = mock.MagicMock() - _query = self._initiator._conn_storage.query - self._initiator._conn_storage.MSFT_iSCSITargetPortal = ( - fake_portal_object) - - if portal_connected: - _query.return_value = [fake_portal_object] - else: - _query.return_value = None - - self._initiator._login_target_portal(fake_portal) - - if portal_connected: - fake_portal_object.Update.assert_called_once_with() - else: - fake_portal_object.New.assert_called_once_with( - TargetPortalAddress=self._FAKE_PORTAL_ADDR, - TargetPortalPortNumber=self._FAKE_PORTAL_PORT) - - def test_login_connected_portal(self): - self._test_login_target_portal(True) - - def test_login_new_portal(self): - self._test_login_target_portal(False) - - @mock.patch.object(iscsi_wmi_utils, 'CONF') - def _test_login_target(self, mock_CONF, target_connected=False, - raise_exception=False, use_chap=False): - mock_CONF.hyperv.volume_attach_retry_count = 4 - mock_CONF.hyperv.volume_attach_retry_interval = 0 - fake_portal = '%s:%s' % (self._FAKE_PORTAL_ADDR, - self._FAKE_PORTAL_PORT) - - fake_target_object = mock.MagicMock() - - if target_connected: - fake_target_object.IsConnected = True - elif not raise_exception: - type(fake_target_object).IsConnected = mock.PropertyMock( - side_effect=[False, True]) - else: - fake_target_object.IsConnected = False - - _query = self._initiator._conn_storage.query - _query.return_value = [fake_target_object] - - self._initiator._conn_storage.MSFT_iSCSITarget = ( - fake_target_object) - - if use_chap: - username, password = (mock.sentinel.username, - mock.sentinel.password) - auth = { - 'AuthenticationType': self._initiator._CHAP_AUTH_TYPE, - 'ChapUsername': username, - 'ChapSecret': password, - } - else: - username, password = None, None - auth = {} - - if raise_exception: - self.assertRaises(exceptions.HyperVException, - self._initiator.login_storage_target, - self._FAKE_LUN, self._FAKE_TARGET, fake_portal) - else: - self._initiator.login_storage_target(self._FAKE_LUN, - self._FAKE_TARGET, - fake_portal, - username, password) - - if target_connected: - fake_target_object.Update.assert_called_with() - else: - fake_target_object.Connect.assert_called_once_with( - IsPersistent=True, NodeAddress=self._FAKE_TARGET, **auth) - - def test_login_connected_target(self): - self._test_login_target(target_connected=True) - - def test_login_disconncted_target(self): - self._test_login_target() - - def test_login_target_exception(self): - self._test_login_target(raise_exception=True) - - def test_login_target_using_chap(self): - self._test_login_target(use_chap=True) - - def test_logout_storage_target(self): - mock_msft_target = self._initiator._conn_storage.MSFT_iSCSITarget - mock_msft_session = self._initiator._conn_storage.MSFT_iSCSISession - - mock_target = mock.MagicMock() - mock_target.IsConnected = True - mock_msft_target.return_value = [mock_target] - - mock_session = mock.MagicMock() - mock_session.IsPersistent = True - mock_msft_session.return_value = [mock_session] - - self._initiator.logout_storage_target(self._FAKE_TARGET) - - mock_msft_target.assert_called_once_with(NodeAddress=self._FAKE_TARGET) - mock_msft_session.assert_called_once_with( - TargetNodeAddress=self._FAKE_TARGET) - - mock_session.Unregister.assert_called_once_with() - mock_target.Disconnect.assert_called_once_with() - - @mock.patch.object(iscsi_wmi_utils.ISCSIInitiatorWMIUtils, - 'logout_storage_target') - def test_execute_log_out(self, mock_logout_target): - sess_class = self._initiator._conn_wmi.MSiSCSIInitiator_SessionClass - - mock_session = mock.MagicMock() - sess_class.return_value = [mock_session] - - self._initiator.execute_log_out(mock.sentinel.FAKE_SESSION_ID) - - sess_class.assert_called_once_with( - SessionId=mock.sentinel.FAKE_SESSION_ID) - mock_logout_target.assert_called_once_with(mock_session.TargetName) diff --git a/os_win/utils/storage/initiator/base_iscsi_utils.py b/os_win/utils/storage/initiator/base_iscsi_utils.py deleted file mode 100644 index 20ee145..0000000 --- a/os_win/utils/storage/initiator/base_iscsi_utils.py +++ /dev/null @@ -1,132 +0,0 @@ -# -# Copyright 2012 Pedro Navarro Perez -# Copyright 2013 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. - -""" -Helper methods for operations related to the management of volumes, -and storage repositories -""" - -import abc -import re -import sys - -from oslo_log import log as logging - -from os_win._i18n import _LI -from os_win.utils import baseutils - -if sys.platform == 'win32': - from six.moves import winreg - -LOG = logging.getLogger(__name__) - - -class BaseISCSIInitiatorUtils(baseutils.BaseUtils): - _FILE_DEVICE_DISK = 7 - - def __init__(self, host='.'): - self._conn_wmi = self._get_wmi_conn('//%s/root/wmi' % host) - self._conn_cimv2 = self._get_wmi_conn('//%s/root/cimv2' % host) - self._drive_number_regex = re.compile(r'DeviceID=\"[^,]*\\(\d+)\"') - - @abc.abstractmethod - def login_storage_target(self, target_lun, target_iqn, target_portal): - pass - - @abc.abstractmethod - def logout_storage_target(self, target_iqn): - pass - - @abc.abstractmethod - def execute_log_out(self, session_id): - pass - - def get_iscsi_initiator(self): - """Get iscsi initiator name for this machine.""" - - computer_system = self._conn_cimv2.Win32_ComputerSystem()[0] - hostname = computer_system.name - keypath = ("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\" - "iSCSI\\Discovery") - try: - key = winreg.OpenKey( - winreg.HKEY_LOCAL_MACHINE, - keypath, - 0, - winreg.KEY_WOW64_64KEY + winreg.KEY_ALL_ACCESS) - temp = winreg.QueryValueEx(key, 'DefaultInitiatorName') - initiator_name = str(temp[0]) - winreg.CloseKey(key) - except Exception: - LOG.info(_LI("The ISCSI initiator name can't be found. " - "Choosing the default one")) - initiator_name = "iqn.1991-05.com.microsoft:" + hostname.lower() - if computer_system.PartofDomain: - initiator_name += '.' + computer_system.Domain.lower() - return initiator_name - - def _get_drive_number_from_disk_path(self, disk_path): - drive_number = self._drive_number_regex.findall(disk_path) - if drive_number: - return int(drive_number[0]) - - def get_session_id_from_mounted_disk(self, physical_drive_path): - drive_number = self._get_drive_number_from_disk_path( - physical_drive_path) - if not drive_number: - return None - - initiator_sessions = self._conn_wmi.MSiSCSIInitiator_SessionClass() - for initiator_session in initiator_sessions: - devices = initiator_session.Devices - for device in devices: - device_number = device.DeviceNumber - if device_number == drive_number: - return initiator_session.SessionId - - def _get_devices_for_target(self, target_iqn): - initiator_sessions = self._conn_wmi.MSiSCSIInitiator_SessionClass( - TargetName=target_iqn) - if not initiator_sessions: - return [] - - return initiator_sessions[0].Devices - - def get_device_number_for_target(self, target_iqn, target_lun): - devices = self._get_devices_for_target(target_iqn) - - for device in devices: - if device.ScsiLun == target_lun: - return device.DeviceNumber - - def get_target_lun_count(self, target_iqn): - devices = self._get_devices_for_target(target_iqn) - disk_devices = [device for device in devices - if device.DeviceType == self._FILE_DEVICE_DISK] - return len(disk_devices) - - def get_target_from_disk_path(self, disk_path): - initiator_sessions = self._conn_wmi.MSiSCSIInitiator_SessionClass() - drive_number = self._get_drive_number_from_disk_path(disk_path) - if not drive_number: - return None - - for initiator_session in initiator_sessions: - devices = initiator_session.Devices - for device in devices: - if device.DeviceNumber == drive_number: - return (device.TargetName, device.ScsiLun) diff --git a/os_win/utils/storage/initiator/iscsi_cli_utils.py b/os_win/utils/storage/initiator/iscsi_cli_utils.py deleted file mode 100644 index 8fa91c2..0000000 --- a/os_win/utils/storage/initiator/iscsi_cli_utils.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2012 Pedro Navarro Perez -# Copyright 2013 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. - -""" -Helper methods for operations related to the management of volumes, -and storage repositories - -Official Microsoft iSCSI Initiator and iSCSI command line interface -documentation can be retrieved at: -http://www.microsoft.com/en-us/download/details.aspx?id=34750 -""" - -import re -import time - -from oslo_config import cfg -from oslo_log import log as logging -from six.moves import range # noqa - -from os_win._i18n import _ -from os_win import _utils -from os_win import exceptions -from os_win.utils.storage.initiator import base_iscsi_utils - -LOG = logging.getLogger(__name__) - -CONF = cfg.CONF - - -class ISCSIInitiatorCLIUtils(base_iscsi_utils.BaseISCSIInitiatorUtils): - - def execute(self, *args, **kwargs): - stdout_value, stderr_value = _utils.execute(*args, **kwargs) - if stdout_value.find('The operation completed successfully') == -1: - raise exceptions.HyperVException - (_('An error has occurred when calling the iscsi initiator: %s') - % stdout_value) - return stdout_value - - def _login_target_portal(self, target_portal): - (target_address, - target_port) = _utils.parse_server_string(target_portal) - - output = self.execute('iscsicli.exe', 'ListTargetPortals') - pattern = r'Address and Socket *: (.*)' - portals = [addr.split() for addr in re.findall(pattern, output)] - LOG.debug("Ensuring connection to portal: %s" % target_portal) - if [target_address, str(target_port)] in portals: - self.execute('iscsicli.exe', 'RefreshTargetPortal', - target_address, target_port) - else: - # Adding target portal to iscsi initiator. Sending targets - self.execute('iscsicli.exe', 'AddTargetPortal', - target_address, target_port, - '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', - '*', '*') - - def login_storage_target(self, target_lun, target_iqn, target_portal, - auth_username=None, auth_password=None): - """Ensure that the target is logged in.""" - - self._login_target_portal(target_portal) - # Listing targets - self.execute('iscsicli.exe', 'ListTargets') - - retry_count = CONF.hyperv.volume_attach_retry_count - - # If the target is not connected, at least two iterations are needed: - # one for performing the login and another one for checking if the - # target was logged in successfully. - if retry_count < 2: - retry_count = 2 - - for attempt in range(retry_count): - try: - session_info = self.execute('iscsicli.exe', 'SessionList') - if session_info.find(target_iqn) == -1: - # Sending login - self.execute('iscsicli.exe', 'qlogintarget', target_iqn, - auth_username, auth_password) - else: - return - except exceptions.HyperVException as exc: - LOG.debug("Attempt %(attempt)d to connect to target " - "%(target_iqn)s failed. Retrying. " - "Exceptipn: %(exc)s ", - {'target_iqn': target_iqn, - 'exc': exc, - 'attempt': attempt}) - time.sleep(CONF.hyperv.volume_attach_retry_interval) - - raise exceptions.HyperVException(_('Failed to login target %s') % - target_iqn) - - def logout_storage_target(self, target_iqn): - """Logs out storage target through its session id.""" - - sessions = self._conn_wmi.query("SELECT * FROM " - "MSiSCSIInitiator_SessionClass " - "WHERE TargetName='%s'" % target_iqn) - for session in sessions: - self.execute_log_out(session.SessionId) - - def execute_log_out(self, session_id): - """Executes log out of the session described by its session ID.""" - self.execute('iscsicli.exe', 'logouttarget', session_id) diff --git a/os_win/utils/storage/initiator/iscsi_wmi_utils.py b/os_win/utils/storage/initiator/iscsi_wmi_utils.py deleted file mode 100644 index 884f468..0000000 --- a/os_win/utils/storage/initiator/iscsi_wmi_utils.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright 2012 Pedro Navarro Perez -# Copyright 2013 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. - -""" -Helper methods for operations related to the management of volumes -and storage repositories on Windows Server 2012 and above -""" -import time - -from oslo_config import cfg -from oslo_log import log as logging -from six.moves import range # noqa - -from os_win._i18n import _ -from os_win import _utils -from os_win import exceptions -from os_win.utils.storage.initiator import base_iscsi_utils - -LOG = logging.getLogger(__name__) -CONF = cfg.CONF - - -class ISCSIInitiatorWMIUtils(base_iscsi_utils.BaseISCSIInitiatorUtils): - _CHAP_AUTH_TYPE = 'ONEWAYCHAP' - - def __init__(self, host='.'): - super(ISCSIInitiatorWMIUtils, self).__init__(host) - - storage_namespace = '//%s/root/microsoft/windows/storage' % host - self._conn_storage = self._get_wmi_conn(storage_namespace) - - def _login_target_portal(self, target_portal): - (target_address, - target_port) = _utils.parse_server_string(target_portal) - - # Checking if the portal is already connected. - portal = self._conn_storage.query("SELECT * FROM " - "MSFT_iSCSITargetPortal " - "WHERE TargetPortalAddress='%s' " - "AND TargetPortalPortNumber='%s'" - % (target_address, target_port)) - if portal: - portal[0].Update() - else: - # Adding target portal to iscsi initiator. Sending targets - portal = self._conn_storage.MSFT_iSCSITargetPortal - portal.New(TargetPortalAddress=target_address, - TargetPortalPortNumber=target_port) - - def login_storage_target(self, target_lun, target_iqn, target_portal, - auth_username=None, auth_password=None): - """Ensure that the target is logged in.""" - - self._login_target_portal(target_portal) - - retry_count = CONF.hyperv.volume_attach_retry_count - - # If the target is not connected, at least two iterations are needed: - # one for performing the login and another one for checking if the - # target was logged in successfully. - if retry_count < 2: - retry_count = 2 - - for attempt in range(retry_count): - target = self._conn_storage.query("SELECT * FROM MSFT_iSCSITarget " - "WHERE NodeAddress='%s' " % - target_iqn) - - if target and target[0].IsConnected: - if attempt == 0: - # The target was already connected but an update may be - # required - target[0].Update() - return - try: - target = self._conn_storage.MSFT_iSCSITarget - auth = {} - if auth_username and auth_password: - auth['AuthenticationType'] = self._CHAP_AUTH_TYPE - auth['ChapUsername'] = auth_username - auth['ChapSecret'] = auth_password - target.Connect(NodeAddress=target_iqn, - IsPersistent=True, **auth) - time.sleep(CONF.hyperv.volume_attach_retry_interval) - except exceptions.x_wmi as exc: - LOG.debug("Attempt %(attempt)d to connect to target " - "%(target_iqn)s failed. Retrying. " - "WMI exception: %(exc)s " % - {'target_iqn': target_iqn, - 'exc': exc, - 'attempt': attempt}) - raise exceptions.HyperVException(_('Failed to login target %s') % - target_iqn) - - def logout_storage_target(self, target_iqn): - """Logs out storage target through its session id.""" - targets = self._conn_storage.MSFT_iSCSITarget(NodeAddress=target_iqn) - if targets: - target = targets[0] - if target.IsConnected: - sessions = self._conn_storage.MSFT_iSCSISession( - TargetNodeAddress=target_iqn) - - for session in sessions: - if session.IsPersistent: - session.Unregister() - - target.Disconnect() - - def execute_log_out(self, session_id): - sessions = self._conn_wmi.MSiSCSIInitiator_SessionClass( - SessionId=session_id) - if sessions: - self.logout_storage_target(sessions[0].TargetName) diff --git a/os_win/utilsfactory.py b/os_win/utilsfactory.py index 11367fc..18686e0 100644 --- a/os_win/utilsfactory.py +++ b/os_win/utilsfactory.py @@ -13,24 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_config import cfg from oslo_utils import importutils from os_win._i18n import _, _LW # noqa from os_win import exceptions from os_win.utils import hostutils from os_win.utils.io import namedpipe -from os_win.utils.storage.initiator import iscsi_cli_utils - -hyper_opts = [ - cfg.BoolOpt('force_volumeutils_v1', - default=False, - help='DEPRECATED: Force V1 volume utility class', - deprecated_for_removal=True), -] - -CONF = cfg.CONF -CONF.register_opts(hyper_opts, 'hyperv') utils = hostutils.HostUtils() @@ -196,10 +184,7 @@ def get_pathutils(): return _get_class(class_type='pathutils') -def get_iscsi_initiator_utils(use_iscsi_cli=False): - use_iscsi_cli = use_iscsi_cli or CONF.hyperv.force_volumeutils_v1 - if use_iscsi_cli: - return iscsi_cli_utils.ISCSIInitiatorCLIUtils() +def get_iscsi_initiator_utils(): return _get_class(class_type='iscsi_initiator_utils')