162 lines
6.1 KiB
Python
162 lines
6.1 KiB
Python
# 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)
|