Merge "Delete the Linux-IO target before setting up local boot"
This commit is contained in:
commit
677e9b7e4b
@ -25,6 +25,7 @@ from oslo_log import log
|
||||
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent.extensions import base
|
||||
from ironic_python_agent.extensions import iscsi
|
||||
from ironic_python_agent import hardware
|
||||
from ironic_python_agent import utils
|
||||
|
||||
@ -194,6 +195,7 @@ class ImageExtension(base.BaseAgentExtension):
|
||||
|
||||
"""
|
||||
device = hardware.dispatch_to_managers('get_os_install_device')
|
||||
iscsi.clean_up(device)
|
||||
_install_grub2(device,
|
||||
root_uuid=root_uuid,
|
||||
efi_system_part_uuid=efi_system_part_uuid)
|
||||
|
@ -95,6 +95,45 @@ def _start_lio(iqn, device):
|
||||
raise errors.ISCSIError(msg)
|
||||
|
||||
|
||||
def clean_up(device):
|
||||
"""Clean up iSCSI for a given device."""
|
||||
try:
|
||||
rts_root = rtslib_fb.RTSRoot()
|
||||
except (EnvironmentError, rtslib_fb.RTSLibError) as exc:
|
||||
LOG.info('Linux-IO is not available, not cleaning up. Error: %s.', exc)
|
||||
return
|
||||
|
||||
storage = None
|
||||
for x in rts_root.storage_objects:
|
||||
if x.udev_path == device:
|
||||
storage = x
|
||||
break
|
||||
|
||||
if storage is None:
|
||||
LOG.info('Device %(dev)s not found in the current iSCSI mounts '
|
||||
'%(mounts)s.',
|
||||
{'dev': device,
|
||||
'mounts': [x.udev_path for x in rts_root.storage_objects]})
|
||||
return
|
||||
else:
|
||||
LOG.info('Deleting iSCSI target %(target)s for device %(dev)s.',
|
||||
{'target': storage.name, 'dev': device})
|
||||
|
||||
try:
|
||||
for x in rts_root.targets:
|
||||
if x.wwn == storage.name:
|
||||
x.delete()
|
||||
break
|
||||
|
||||
storage.delete()
|
||||
except rtslib_fb.utils.RTSLibError as exc:
|
||||
msg = ('Failed to delete iSCSI target %(target)s for device %(dev)s: '
|
||||
'%(error)s') % {'target': storage.name,
|
||||
'dev': device,
|
||||
'error': exc}
|
||||
raise errors.ISCSIError(msg)
|
||||
|
||||
|
||||
class ISCSIExtension(base.BaseAgentExtension):
|
||||
@base.sync_command('start_iscsi_target')
|
||||
def start_iscsi_target(self, iqn=None):
|
||||
|
@ -25,6 +25,7 @@ from oslotest import base as test_base
|
||||
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent.extensions import image
|
||||
from ironic_python_agent.extensions import iscsi
|
||||
from ironic_python_agent import hardware
|
||||
from ironic_python_agent import utils
|
||||
|
||||
@ -45,19 +46,22 @@ class TestImageExtension(test_base.BaseTestCase):
|
||||
self.fake_efi_system_part_uuid = '45AB-2312'
|
||||
self.fake_dir = '/tmp/fake-dir'
|
||||
|
||||
@mock.patch.object(iscsi, 'clean_up')
|
||||
@mock.patch.object(image, '_install_grub2')
|
||||
def test_install_bootloader_bios(self, mock_grub2, mock_execute,
|
||||
mock_dispatch):
|
||||
def test_install_bootloader_bios(self, mock_grub2, mock_iscsi_clean,
|
||||
mock_execute, mock_dispatch):
|
||||
mock_dispatch.return_value = self.fake_dev
|
||||
self.agent_extension.install_bootloader(root_uuid=self.fake_root_uuid)
|
||||
mock_dispatch.assert_called_once_with('get_os_install_device')
|
||||
mock_grub2.assert_called_once_with(
|
||||
self.fake_dev, root_uuid=self.fake_root_uuid,
|
||||
efi_system_part_uuid=None)
|
||||
mock_iscsi_clean.assert_called_once_with(self.fake_dev)
|
||||
|
||||
@mock.patch.object(iscsi, 'clean_up')
|
||||
@mock.patch.object(image, '_install_grub2')
|
||||
def test_install_bootloader_uefi(self, mock_grub2, mock_execute,
|
||||
mock_dispatch):
|
||||
def test_install_bootloader_uefi(self, mock_grub2, mock_iscsi_clean,
|
||||
mock_execute, mock_dispatch):
|
||||
mock_dispatch.return_value = self.fake_dev
|
||||
self.agent_extension.install_bootloader(
|
||||
root_uuid=self.fake_root_uuid,
|
||||
@ -67,6 +71,7 @@ class TestImageExtension(test_base.BaseTestCase):
|
||||
self.fake_dev,
|
||||
root_uuid=self.fake_root_uuid,
|
||||
efi_system_part_uuid=self.fake_efi_system_part_uuid)
|
||||
mock_iscsi_clean.assert_called_once_with(self.fake_dev)
|
||||
|
||||
@mock.patch.object(os, 'environ')
|
||||
@mock.patch.object(image, '_get_partition')
|
||||
|
@ -155,3 +155,66 @@ class TestISCSIExtensionLIO(test_base.BaseTestCase):
|
||||
lun=1)
|
||||
mock_rtslib.NetworkPortal.assert_called_once_with(
|
||||
mock_rtslib.TPG.return_value, '0.0.0.0')
|
||||
|
||||
|
||||
@mock.patch.object(iscsi.rtslib_fb, 'RTSRoot')
|
||||
class TestISCSIExtensionCleanUp(test_base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestISCSIExtensionCleanUp, self).setUp()
|
||||
self.agent_extension = iscsi.ISCSIExtension()
|
||||
self.fake_dev = '/dev/fake'
|
||||
self.fake_iqn = 'iqn-fake'
|
||||
|
||||
def test_lio_not_available(self, mock_rtslib):
|
||||
mock_rtslib.side_effect = IOError()
|
||||
iscsi.clean_up(self.fake_dev)
|
||||
|
||||
def test_device_not_found(self, mock_rtslib):
|
||||
mock_rtslib.return_value.storage_objects = []
|
||||
iscsi.clean_up(self.fake_dev)
|
||||
|
||||
def test_ok(self, mock_rtslib):
|
||||
mock_rtslib.return_value.storage_objects = [
|
||||
mock.Mock(udev_path='wrong path'),
|
||||
mock.Mock(udev_path=self.fake_dev),
|
||||
mock.Mock(udev_path='wrong path'),
|
||||
]
|
||||
# mocks don't play well with name attribute
|
||||
for i, fake_storage in enumerate(
|
||||
mock_rtslib.return_value.storage_objects):
|
||||
fake_storage.name = 'iqn%d' % i
|
||||
|
||||
mock_rtslib.return_value.targets = [
|
||||
mock.Mock(wwn='iqn0'),
|
||||
mock.Mock(wwn='iqn1'),
|
||||
]
|
||||
|
||||
iscsi.clean_up(self.fake_dev)
|
||||
|
||||
for fake_storage in mock_rtslib.return_value.storage_objects:
|
||||
self.assertEqual(fake_storage.udev_path == self.fake_dev,
|
||||
fake_storage.delete.called)
|
||||
for fake_target in mock_rtslib.return_value.targets:
|
||||
self.assertEqual(fake_target.wwn == 'iqn1',
|
||||
fake_target.delete.called)
|
||||
|
||||
def test_delete_fails(self, mock_rtslib):
|
||||
mock_rtslib.return_value.storage_objects = [
|
||||
mock.Mock(udev_path='wrong path'),
|
||||
mock.Mock(udev_path=self.fake_dev),
|
||||
mock.Mock(udev_path='wrong path'),
|
||||
]
|
||||
# mocks don't play well with name attribute
|
||||
for i, fake_storage in enumerate(
|
||||
mock_rtslib.return_value.storage_objects):
|
||||
fake_storage.name = 'iqn%d' % i
|
||||
|
||||
mock_rtslib.return_value.targets = [
|
||||
mock.Mock(wwn='iqn0'),
|
||||
mock.Mock(wwn='iqn1'),
|
||||
]
|
||||
mock_rtslib.return_value.targets[1].delete.side_effect = (
|
||||
_ORIG_UTILS.RTSLibError())
|
||||
|
||||
self.assertRaises(errors.ISCSIError, iscsi.clean_up, self.fake_dev)
|
||||
|
Loading…
Reference in New Issue
Block a user