add new portal_port argument into iscsi.start_iscsi_target api

Currently we hardcode the iSCSI port to its default. With this
patch, we added new portal_port argument into iscsi.start_iscsi_target
api, cover both lio and tgt two iscsi target operations.

And for IPA client and driver code change, will commit more patch to
cover.

Change-Id: I6da20487ccba6cbac04d36b8643afdd1e3920b12
Partial-Bug: #1523829
This commit is contained in:
Haomeng, Wang 2016-01-26 08:08:18 +00:00
parent 858c643777
commit c83a968997
3 changed files with 80 additions and 12 deletions

View File

@ -31,6 +31,7 @@ from ironic_python_agent import hardware
from ironic_python_agent import utils
LOG = log.getLogger(__name__)
DEFAULT_ISCSI_PORTAL_PORT = 3260
def _execute(cmd, error_msg, **kwargs):
@ -50,13 +51,21 @@ def _wait_for_tgtd(attempts=10):
_execute(cmd, "ISCSI daemon didn't initialize", attempts=attempts)
def _start_tgtd(iqn, device):
def _start_tgtd(iqn, portal_port, device):
"""Start a ISCSI target for the device."""
# Start ISCSI Target daemon
_execute(['tgtd'], "Unable to start the ISCSI daemon")
_wait_for_tgtd()
# tgt service will create default portal on default port 3260.
# so no need to create again if input portal_port == 3260.
if portal_port != DEFAULT_ISCSI_PORTAL_PORT:
cmd = ['tgtadm', '--lld', 'iscsi', '--mode', 'portal', '--op',
'new', '--param', 'portal=0.0.0.0:' + str(portal_port)]
_execute(cmd, "Error when adding a new portal with portal_port %d"
% portal_port)
cmd = ['tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op',
'new', '--tid', '1', '--targetname', iqn]
_execute(cmd, "Error when adding a new target for iqn %s" % iqn)
@ -71,7 +80,7 @@ def _start_tgtd(iqn, device):
"initiators for iqn %s" % iqn)
def _start_lio(iqn, device):
def _start_lio(iqn, portal_port, device):
try:
storage = rtslib_fb.BlockStorageObject(name=iqn, dev=device)
target = rtslib_fb.Target(rtslib_fb.FabricModule('iscsi'), iqn,
@ -90,7 +99,7 @@ def _start_lio(iqn, device):
try:
# bind to the default port on all interfaces
rtslib_fb.NetworkPortal(tpg, '0.0.0.0')
rtslib_fb.NetworkPortal(tpg, '0.0.0.0', portal_port)
except rtslib_fb.utils.RTSLibError as exc:
msg = 'Failed to publish a target: {0}'.format(exc)
raise errors.ISCSIError(msg)
@ -137,7 +146,8 @@ def clean_up(device):
class ISCSIExtension(base.BaseAgentExtension):
@base.sync_command('start_iscsi_target')
def start_iscsi_target(self, iqn=None, wipe_disk_metadata=False):
def start_iscsi_target(self, iqn=None, wipe_disk_metadata=False,
portal_port=None):
"""Expose the disk as an ISCSI target.
:param wipe_disk_metadata: if the disk metadata should be wiped out
@ -164,15 +174,18 @@ class ISCSIExtension(base.BaseAgentExtension):
'Error: %s.', exc)
rts_root = None
if portal_port is None:
portal_port = DEFAULT_ISCSI_PORTAL_PORT
if rts_root is None:
_start_tgtd(iqn, device)
_start_tgtd(iqn, portal_port, device)
else:
_start_lio(iqn, device)
_start_lio(iqn, portal_port, device)
LOG.debug('Linux-IO configuration: %s', rts_root.dump())
LOG.info('Created iSCSI target with iqn %(iqn)s on device %(dev)s '
'using %(method)s',
{'iqn': iqn, 'dev': device,
LOG.info('Created iSCSI target with iqn %(iqn)s, portal_port %(port)d,'
' on device %(dev)s using %(method)s',
{'iqn': iqn, 'portal_port': portal_port, 'dev': device,
'method': 'tgtd' if rts_root is None else 'linux-io'})
return {"iscsi_target_iqn": iqn}

View File

@ -70,6 +70,34 @@ class TestISCSIExtensionTgt(test_base.BaseTestCase):
result.command_result)
self.assertFalse(mock_destroy.called)
def test_start_iscsi_target_with_special_port(self, mock_execute,
mock_dispatch,
mock_destroy):
mock_dispatch.return_value = self.fake_dev
mock_execute.return_value = ('', '')
result = self.agent_extension.start_iscsi_target(iqn=self.fake_iqn,
portal_port=3268)
expected = [mock.call('tgtd'),
mock.call('tgtadm', '--lld', 'iscsi', '--mode',
'target', '--op', 'show', attempts=10),
mock.call('tgtadm', '--lld', 'iscsi', '--mode',
'portal', '--op', 'new', '--param',
'portal=0.0.0.0:3268'),
mock.call('tgtadm', '--lld', 'iscsi', '--mode',
'target', '--op', 'new', '--tid', '1',
'--targetname', self.fake_iqn),
mock.call('tgtadm', '--lld', 'iscsi', '--mode',
'logicalunit', '--op', 'new', '--tid', '1',
'--lun', '1', '--backing-store', self.fake_dev),
mock.call('tgtadm', '--lld', 'iscsi', '--mode', 'target',
'--op', 'bind', '--tid', '1',
'--initiator-address', 'ALL')]
mock_execute.assert_has_calls(expected)
mock_dispatch.assert_called_once_with('get_os_install_device')
self.assertEqual({'iscsi_target_iqn': self.fake_iqn},
result.command_result)
def test_start_iscsi_target_fail_wait_daemon(self, mock_execute,
mock_dispatch,
mock_destroy):
@ -142,9 +170,31 @@ class TestISCSIExtensionLIO(test_base.BaseTestCase):
storage_object=mock_rtslib.BlockStorageObject.return_value,
lun=1)
mock_rtslib.NetworkPortal.assert_called_once_with(
mock_rtslib.TPG.return_value, '0.0.0.0')
mock_rtslib.TPG.return_value, '0.0.0.0', 3260)
self.assertFalse(mock_destroy.called)
def test_start_iscsi_target_with_special_port(self, mock_rtslib,
mock_dispatch,
mock_destroy):
mock_dispatch.return_value = self.fake_dev
result = self.agent_extension.start_iscsi_target(iqn=self.fake_iqn,
portal_port=3266)
self.assertEqual({'iscsi_target_iqn': self.fake_iqn},
result.command_result)
mock_rtslib.BlockStorageObject.assert_called_once_with(
name=self.fake_iqn, dev=self.fake_dev)
mock_rtslib.Target.assert_called_once_with(mock.ANY, self.fake_iqn,
mode='create')
mock_rtslib.TPG.assert_called_once_with(
mock_rtslib.Target.return_value, mode='create')
mock_rtslib.LUN.assert_called_once_with(
mock_rtslib.TPG.return_value,
storage_object=mock_rtslib.BlockStorageObject.return_value,
lun=1)
mock_rtslib.NetworkPortal.assert_called_once_with(
mock_rtslib.TPG.return_value, '0.0.0.0', 3266)
def test_failed_to_start_iscsi(self, mock_rtslib, mock_dispatch,
mock_destroy):
mock_dispatch.return_value = self.fake_dev
@ -159,7 +209,8 @@ class TestISCSIExtensionLIO(test_base.BaseTestCase):
mock_rtslib.NetworkPortal.side_effect = _ORIG_UTILS.RTSLibError()
self.assertRaisesRegexp(
errors.ISCSIError, 'Failed to publish a target',
self.agent_extension.start_iscsi_target, iqn=self.fake_iqn)
self.agent_extension.start_iscsi_target, iqn=self.fake_iqn,
portal_port=None)
mock_rtslib.BlockStorageObject.assert_called_once_with(
name=self.fake_iqn, dev=self.fake_dev)
@ -172,7 +223,7 @@ class TestISCSIExtensionLIO(test_base.BaseTestCase):
storage_object=mock_rtslib.BlockStorageObject.return_value,
lun=1)
mock_rtslib.NetworkPortal.assert_called_once_with(
mock_rtslib.TPG.return_value, '0.0.0.0')
mock_rtslib.TPG.return_value, '0.0.0.0', 3260)
self.assertFalse(mock_destroy.called)
def test_failed_to_start_iscsi_wipe_disk_metadata(self, mock_rtslib,

View File

@ -0,0 +1,4 @@
---
features:
- Add new portal_port argument into iscsi.start_iscsi_target
to support iscsi portal port customization.