Implementation for UEFI iSCSI boot for ILO
This change adds new methods in management interface and enhance boot interface of 'ilo' hardware type to support boot from iSCSI volume in UEFI boot mode. Change-Id: I585e0ef90f4397af1f09920c3a1bc47ddbcb1a97 Related-Bug: #1526861
This commit is contained in:
parent
a8a57048eb
commit
8763637255
@ -235,9 +235,9 @@ Prerequisites
|
||||
which contains a set of modules for managing HPE ProLiant hardware.
|
||||
|
||||
Install ``proliantutils`` module on the ironic conductor node. Minimum
|
||||
version required is 2.4.1::
|
||||
version required is 2.5.0::
|
||||
|
||||
$ pip install "proliantutils>=2.4.1"
|
||||
$ pip install "proliantutils>=2.5.0"
|
||||
|
||||
* ``ipmitool`` command must be present on the service node(s) where
|
||||
``ironic-conductor`` is running. On most distros, this is provided as part
|
||||
@ -1812,7 +1812,7 @@ firmware components on the node. Refer to `SUM User Guide`_ to get more
|
||||
information on SUM based firmware update.
|
||||
|
||||
``update_firmware_sum`` clean step requires the agent ramdisk with
|
||||
``Proliant Hardware Manager`` from the proliantutils version 2.4.0 or higher.
|
||||
``Proliant Hardware Manager`` from the proliantutils version 2.5.0 or higher.
|
||||
See `DIB support for Proliant Hardware Manager`_ to create the agent ramdisk
|
||||
with ``Proliant Hardware Manager``.
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
# python projects they should package as optional dependencies for Ironic.
|
||||
|
||||
# These are available on pypi
|
||||
proliantutils>=2.4.1
|
||||
proliantutils>=2.5.0
|
||||
pysnmp
|
||||
python-ironic-inspector-client>=1.5.0
|
||||
python-oneviewclient<3.0.0,>=2.5.2
|
||||
|
@ -43,3 +43,6 @@ SAFE = 'safe'
|
||||
|
||||
WANBOOT = 'wanboot'
|
||||
"Boot from Wide Area Network"
|
||||
|
||||
ISCSIBOOT = 'iscsiboot'
|
||||
"Boot from iSCSI volume"
|
||||
|
@ -383,6 +383,8 @@ def disable_secure_boot_if_supported(task):
|
||||
|
||||
class IloVirtualMediaBoot(base.BootInterface):
|
||||
|
||||
capabilities = ['iscsi_volume_boot']
|
||||
|
||||
def get_properties(self):
|
||||
return COMMON_PROPERTIES
|
||||
|
||||
@ -397,9 +399,13 @@ class IloVirtualMediaBoot(base.BootInterface):
|
||||
in instance_info for non-Glance image.
|
||||
"""
|
||||
|
||||
_validate_instance_image_info(task)
|
||||
_validate_driver_info(task)
|
||||
|
||||
if not task.driver.storage.should_write_image(task):
|
||||
return
|
||||
else:
|
||||
_validate_instance_image_info(task)
|
||||
|
||||
@METRICS.timer('IloVirtualMediaBoot.prepare_ramdisk')
|
||||
def prepare_ramdisk(self, task, ramdisk_params):
|
||||
"""Prepares the boot of deploy ramdisk using virtual media.
|
||||
@ -464,8 +470,12 @@ class IloVirtualMediaBoot(base.BootInterface):
|
||||
relevant information from the node's instance_info.
|
||||
It does the following depending on boot_option for deploy:
|
||||
|
||||
- If the boot_option requested for this deploy is 'local' or image
|
||||
is a whole disk image, then it sets the node to boot from disk.
|
||||
- If the boot mode is 'uefi' and its booting from volume, then it
|
||||
sets the iSCSI target info and node to boot from 'UefiTarget'
|
||||
boot device.
|
||||
- If not 'boot from volume' and the boot_option requested for
|
||||
this deploy is 'local' or image is a whole disk image, then
|
||||
it sets the node to boot from disk.
|
||||
- Otherwise it finds/creates the boot ISO to boot the instance
|
||||
image, attaches the boot ISO to the bare metal and then sets
|
||||
the node to boot from CDROM.
|
||||
@ -473,25 +483,44 @@ class IloVirtualMediaBoot(base.BootInterface):
|
||||
:param task: a task from TaskManager.
|
||||
:returns: None
|
||||
:raises: IloOperationError, if some operation on iLO failed.
|
||||
:raises: InstanceDeployFailure, if its try to boot iSCSI volume in
|
||||
'BIOS' boot mode.
|
||||
"""
|
||||
|
||||
ilo_common.cleanup_vmedia_boot(task)
|
||||
|
||||
# For iscsi_ilo driver, we boot from disk every time if the image
|
||||
# deployed is a whole disk image.
|
||||
node = task.node
|
||||
iwdi = node.driver_internal_info.get('is_whole_disk_image')
|
||||
if deploy_utils.get_boot_option(node) == "local" or iwdi:
|
||||
manager_utils.node_set_boot_device(task, boot_devices.DISK,
|
||||
persistent=True)
|
||||
else:
|
||||
drv_int_info = node.driver_internal_info
|
||||
root_uuid_or_disk_id = drv_int_info.get('root_uuid_or_disk_id')
|
||||
if root_uuid_or_disk_id:
|
||||
self._configure_vmedia_boot(task, root_uuid_or_disk_id)
|
||||
boot_mode = deploy_utils.get_boot_mode_for_deploy(task.node)
|
||||
|
||||
if deploy_utils.is_iscsi_boot(task):
|
||||
# It will set iSCSI info onto iLO
|
||||
if boot_mode == 'uefi':
|
||||
# Need to set 'ilo_uefi_iscsi_boot' param for clean up
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['ilo_uefi_iscsi_boot'] = True
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
task.driver.management.set_iscsi_boot_target(task)
|
||||
manager_utils.node_set_boot_device(
|
||||
task, boot_devices.ISCSIBOOT, persistent=True)
|
||||
else:
|
||||
LOG.warning("The UUID for the root partition could not "
|
||||
"be found for node %s", node.uuid)
|
||||
msg = 'Virtual media can not boot volume in BIOS boot mode.'
|
||||
raise exception.InstanceDeployFailure(msg)
|
||||
else:
|
||||
# For iscsi_ilo driver, we boot from disk every time if the image
|
||||
# deployed is a whole disk image.
|
||||
node = task.node
|
||||
iwdi = node.driver_internal_info.get('is_whole_disk_image')
|
||||
if deploy_utils.get_boot_option(node) == "local" or iwdi:
|
||||
manager_utils.node_set_boot_device(task, boot_devices.DISK,
|
||||
persistent=True)
|
||||
else:
|
||||
drv_int_info = node.driver_internal_info
|
||||
root_uuid_or_disk_id = drv_int_info.get('root_uuid_or_disk_id')
|
||||
if root_uuid_or_disk_id:
|
||||
self._configure_vmedia_boot(task, root_uuid_or_disk_id)
|
||||
else:
|
||||
LOG.warning("The UUID for the root partition could not "
|
||||
"be found for node %s", node.uuid)
|
||||
# Set boot mode
|
||||
ilo_common.update_boot_mode(task)
|
||||
# Need to enable secure boot, if being requested
|
||||
@ -502,7 +531,9 @@ class IloVirtualMediaBoot(base.BootInterface):
|
||||
"""Cleans up the boot of instance.
|
||||
|
||||
This method cleans up the environment that was setup for booting
|
||||
the instance. It ejects virtual media
|
||||
the instance. It ejects virtual media.
|
||||
In case of UEFI iSCSI booting, it cleans up iSCSI target information
|
||||
from the node.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:returns: None
|
||||
@ -512,16 +543,23 @@ class IloVirtualMediaBoot(base.BootInterface):
|
||||
LOG.debug("Cleaning up the instance.")
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
disable_secure_boot_if_supported(task)
|
||||
|
||||
_clean_up_boot_iso_for_instance(task.node)
|
||||
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info.pop('boot_iso_created_in_web_server', None)
|
||||
driver_internal_info.pop('root_uuid_or_disk_id', None)
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
|
||||
ilo_common.cleanup_vmedia_boot(task)
|
||||
if (deploy_utils.is_iscsi_boot(task) and
|
||||
task.node.driver_internal_info.get('ilo_uefi_iscsi_boot')):
|
||||
# It will clear iSCSI info from iLO
|
||||
task.driver.management.clear_iscsi_boot_target(task)
|
||||
driver_internal_info.pop('ilo_uefi_iscsi_boot', None)
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
else:
|
||||
_clean_up_boot_iso_for_instance(task.node)
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info.pop('boot_iso_created_in_web_server', None)
|
||||
driver_internal_info.pop('root_uuid_or_disk_id', None)
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
ilo_common.cleanup_vmedia_boot(task)
|
||||
|
||||
@METRICS.timer('IloVirtualMediaBoot.clean_up_ramdisk')
|
||||
def clean_up_ramdisk(self, task):
|
||||
@ -601,6 +639,8 @@ class IloPXEBoot(pxe.PXEBoot):
|
||||
relevant information from the node's instance_info. In case of netboot,
|
||||
it updates the dhcp entries and switches the PXE config. In case of
|
||||
localboot, it cleans up the PXE config.
|
||||
In case of 'boot from volume', it updates the iSCSI info onto iLO and
|
||||
sets the node to boot from 'UefiTarget' boot device.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:returns: None
|
||||
@ -612,7 +652,22 @@ class IloPXEBoot(pxe.PXEBoot):
|
||||
# Need to enable secure boot, if being requested
|
||||
ilo_common.update_secure_boot_mode(task, True)
|
||||
|
||||
super(IloPXEBoot, self).prepare_instance(task)
|
||||
boot_mode = deploy_utils.get_boot_mode_for_deploy(task.node)
|
||||
|
||||
if deploy_utils.is_iscsi_boot(task) and boot_mode == 'uefi':
|
||||
# Need to set 'ilo_uefi_iscsi_boot' param for clean up
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['ilo_uefi_iscsi_boot'] = True
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
# It will set iSCSI info onto iLO
|
||||
task.driver.management.set_iscsi_boot_target(task)
|
||||
manager_utils.node_set_boot_device(task, boot_devices.ISCSIBOOT,
|
||||
persistent=True)
|
||||
else:
|
||||
# Volume boot in BIOS boot mode is handled using
|
||||
# PXE boot interface
|
||||
super(IloPXEBoot, self).prepare_instance(task)
|
||||
|
||||
@METRICS.timer('IloPXEBoot.clean_up_instance')
|
||||
def clean_up_instance(self, task):
|
||||
@ -621,6 +676,8 @@ class IloPXEBoot(pxe.PXEBoot):
|
||||
This method cleans up the PXE environment that was setup for booting
|
||||
the instance. It unlinks the instance kernel/ramdisk in the node's
|
||||
directory in tftproot and removes it's PXE config.
|
||||
In case of UEFI iSCSI booting, it cleans up iSCSI target information
|
||||
from the node.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:returns: None
|
||||
@ -629,5 +686,17 @@ class IloPXEBoot(pxe.PXEBoot):
|
||||
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
disable_secure_boot_if_supported(task)
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
|
||||
super(IloPXEBoot, self).clean_up_instance(task)
|
||||
if (deploy_utils.is_iscsi_boot(task) and
|
||||
task.node.driver_internal_info.get('ilo_uefi_iscsi_boot')):
|
||||
# It will clear iSCSI info from iLO in case of booting from
|
||||
# volume in UEFI boot mode
|
||||
task.driver.management.clear_iscsi_boot_target(task)
|
||||
driver_internal_info.pop('ilo_uefi_iscsi_boot', None)
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
else:
|
||||
# Volume boot in BIOS boot mode is handled using
|
||||
# PXE boot interface
|
||||
super(IloPXEBoot, self).clean_up_instance(task)
|
||||
|
@ -34,6 +34,7 @@ from ironic.drivers.modules.ilo import common as ilo_common
|
||||
from ironic.drivers.modules.ilo import firmware_processor
|
||||
from ironic.drivers.modules import ipmitool
|
||||
from ironic.drivers import utils as driver_utils
|
||||
from ironic.objects import volume_target
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -44,7 +45,8 @@ ilo_error = importutils.try_import('proliantutils.exception')
|
||||
BOOT_DEVICE_MAPPING_TO_ILO = {
|
||||
boot_devices.PXE: 'NETWORK',
|
||||
boot_devices.DISK: 'HDD',
|
||||
boot_devices.CDROM: 'CDROM'
|
||||
boot_devices.CDROM: 'CDROM',
|
||||
boot_devices.ISCSIBOOT: 'ISCSI'
|
||||
}
|
||||
BOOT_DEVICE_ILO_TO_GENERIC = {
|
||||
v: k for k, v in BOOT_DEVICE_MAPPING_TO_ILO.items()}
|
||||
@ -513,3 +515,68 @@ class IloManagement(base.ManagementInterface):
|
||||
'%(node)s for "update_firmware_sum" clean step. '
|
||||
'Error: %(error)s',
|
||||
{'node': node.uuid, 'error': e})
|
||||
|
||||
@METRICS.timer('IloManagement.set_iscsi_boot_target')
|
||||
def set_iscsi_boot_target(self, task):
|
||||
"""Set iSCSI details of the system in UEFI boot mode.
|
||||
|
||||
The initiator is set with the target details like
|
||||
IQN, LUN, IP, Port etc.
|
||||
:param task: a task from TaskManager.
|
||||
:raises: IloCommandNotSupportedInBiosError if system in BIOS boot mode.
|
||||
:raises: IloError on an error from iLO.
|
||||
"""
|
||||
# Getting target info
|
||||
node = task.node
|
||||
boot_volume = node.driver_internal_info.get('boot_from_volume')
|
||||
volume = volume_target.VolumeTarget.get_by_uuid(task.context,
|
||||
boot_volume)
|
||||
properties = volume.properties
|
||||
username = properties.get('auth_username', None)
|
||||
password = properties.get('auth_password', None)
|
||||
portal = properties['target_portal']
|
||||
iqn = properties['target_iqn']
|
||||
lun = properties['target_lun']
|
||||
host, port = portal.split(':')
|
||||
|
||||
ilo_object = ilo_common.get_ilo_object(task.node)
|
||||
try:
|
||||
if username is None:
|
||||
ilo_object.set_iscsi_info(iqn, lun, host, port)
|
||||
else:
|
||||
ilo_object.set_iscsi_info(iqn, lun, host, port, 'CHAP',
|
||||
username, password)
|
||||
except ilo_error.IloCommandNotSupportedInBiosError as ilo_exception:
|
||||
operation = (_("Setting of target IQN %(target_iqn)s for node "
|
||||
"%(node)s")
|
||||
% {'target_iqn': iqn, 'node': node.uuid})
|
||||
raise exception.IloOperationNotSupported(operation=operation,
|
||||
error=ilo_exception)
|
||||
except ilo_error.IloError as ilo_exception:
|
||||
operation = (_("Setting of target IQN %(target_iqn)s for node "
|
||||
"%(node)s")
|
||||
% {'target_iqn': iqn, 'node': node.uuid})
|
||||
raise exception.IloOperationError(operation=operation,
|
||||
error=ilo_exception)
|
||||
|
||||
@METRICS.timer('IloManagement.clear_iscsi_boot_target')
|
||||
def clear_iscsi_boot_target(self, task):
|
||||
"""Unset iSCSI details of the system in UEFI boot mode.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: IloCommandNotSupportedInBiosError if system in BIOS boot mode.
|
||||
:raises: IloError on an error from iLO.
|
||||
"""
|
||||
ilo_object = ilo_common.get_ilo_object(task.node)
|
||||
try:
|
||||
ilo_object.unset_iscsi_info()
|
||||
except ilo_error.IloCommandNotSupportedInBiosError as ilo_exception:
|
||||
operation = (_("Unsetting of iSCSI target for node %(node)s")
|
||||
% {'node': task.node.uuid})
|
||||
raise exception.IloOperationNotSupported(operation=operation,
|
||||
error=ilo_exception)
|
||||
except ilo_error.IloError as ilo_exception:
|
||||
operation = (_("Unsetting of iSCSI target for node %(node)s")
|
||||
% {'node': task.node.uuid})
|
||||
raise exception.IloOperationError(operation=operation,
|
||||
error=ilo_exception)
|
||||
|
@ -34,7 +34,9 @@ from ironic.conductor import utils as manager_utils
|
||||
from ironic.drivers.modules import deploy_utils
|
||||
from ironic.drivers.modules.ilo import boot as ilo_boot
|
||||
from ironic.drivers.modules.ilo import common as ilo_common
|
||||
from ironic.drivers.modules.ilo import management as ilo_management
|
||||
from ironic.drivers.modules import pxe
|
||||
from ironic.drivers.modules.storage import noop as noop_storage
|
||||
from ironic.drivers import utils as driver_utils
|
||||
from ironic.tests.unit.conductor import mgr_utils
|
||||
from ironic.tests.unit.db import base as db_base
|
||||
@ -674,12 +676,14 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
self.node = obj_utils.create_test_node(
|
||||
self.context, driver='iscsi_ilo', driver_info=INFO_DICT)
|
||||
|
||||
@mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_boot, '_validate_driver_info',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_boot, '_validate_instance_image_info',
|
||||
spec_set=True, autospec=True)
|
||||
def test_validate(self, mock_val_instance_image_info,
|
||||
mock_val_driver_info):
|
||||
mock_val_driver_info, storage_mock):
|
||||
instance_info = self.node.instance_info
|
||||
instance_info['ilo_boot_iso'] = 'deploy-iso'
|
||||
instance_info['image_source'] = '6b2f0c0c-79e8-4db6-842e-43c9764204af'
|
||||
@ -689,10 +693,24 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
shared=False) as task:
|
||||
|
||||
task.node.driver_info['ilo_deploy_iso'] = 'deploy-iso'
|
||||
storage_mock.return_value = True
|
||||
task.driver.boot.validate(task)
|
||||
mock_val_instance_image_info.assert_called_once_with(task)
|
||||
mock_val_driver_info.assert_called_once_with(task)
|
||||
|
||||
@mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_boot, '_validate_driver_info',
|
||||
spec_set=True, autospec=True)
|
||||
def test_validate_boot_from_volume(self, mock_val_driver_info,
|
||||
storage_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.node.driver_info['ilo_deploy_iso'] = 'deploy-iso'
|
||||
storage_mock.return_value = False
|
||||
task.driver.boot.validate(task)
|
||||
mock_val_driver_info.assert_called_once_with(task)
|
||||
|
||||
@mock.patch.object(ilo_boot, 'prepare_node_for_deploy',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_power_action',
|
||||
@ -834,6 +852,8 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
self.assertFalse(setup_vmedia_mock.called)
|
||||
self.assertFalse(set_boot_device_mock.called)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
|
||||
@ -844,7 +864,8 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
spec_set=True, autospec=True)
|
||||
def test_clean_up_instance(self, cleanup_iso_mock,
|
||||
cleanup_vmedia_mock, node_power_mock,
|
||||
update_secure_boot_mode_mock):
|
||||
update_secure_boot_mode_mock,
|
||||
is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
@ -853,6 +874,62 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
"12312642-09d3-467f-8e09-12385826a123")
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
is_iscsi_boot_mock.return_value = False
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
cleanup_iso_mock.assert_called_once_with(task.node)
|
||||
cleanup_vmedia_mock.assert_called_once_with(task)
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
self.assertNotIn('boot_iso_created_in_web_server',
|
||||
driver_internal_info)
|
||||
self.assertNotIn('root_uuid_or_disk_id', driver_internal_info)
|
||||
node_power_mock.assert_called_once_with(task,
|
||||
states.POWER_OFF)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, False)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.IloManagement, 'clear_iscsi_boot_target',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clean_up_instance_boot_from_volume(
|
||||
self, node_power_mock, update_secure_boot_mode_mock,
|
||||
clear_iscsi_boot_target_mock,
|
||||
is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['ilo_uefi_iscsi_boot'] = True
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
is_iscsi_boot_mock.return_value = True
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
node_power_mock.assert_called_once_with(task,
|
||||
states.POWER_OFF)
|
||||
clear_iscsi_boot_target_mock.assert_called_once_with(mock.ANY,
|
||||
task)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, False)
|
||||
self.assertIsNone(self.node.driver_internal_info.get(
|
||||
'ilo_uefi_iscsi_boot'))
|
||||
|
||||
@mock.patch.object(ilo_common, 'cleanup_vmedia_boot', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_boot, '_clean_up_boot_iso_for_instance',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clean_up_instance_boot_from_volume_bios(
|
||||
self, node_power_mock, update_secure_boot_mode_mock,
|
||||
is_iscsi_boot_mock, cleanup_iso_mock, cleanup_vmedia_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
is_iscsi_boot_mock.return_value = True
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
cleanup_iso_mock.assert_called_once_with(task.node)
|
||||
cleanup_vmedia_mock.assert_called_once_with(task)
|
||||
@ -872,6 +949,8 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
task.driver.boot.clean_up_ramdisk(task)
|
||||
cleanup_vmedia_mock.assert_called_once_with(task)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
|
||||
@ -882,9 +961,11 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
autospec=True)
|
||||
def _test_prepare_instance_whole_disk_image(
|
||||
self, cleanup_vmedia_boot_mock, set_boot_device_mock,
|
||||
update_boot_mode_mock, update_secure_boot_mode_mock):
|
||||
update_boot_mode_mock, update_secure_boot_mode_mock,
|
||||
is_iscsi_boot_mock):
|
||||
self.node.driver_internal_info = {'is_whole_disk_image': True}
|
||||
self.node.save()
|
||||
is_iscsi_boot_mock.return_value = False
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.boot.prepare_instance(task)
|
||||
@ -904,6 +985,8 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
def test_prepare_instance_whole_disk_image(self):
|
||||
self._test_prepare_instance_whole_disk_image()
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
|
||||
@ -915,20 +998,71 @@ class IloVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
autospec=True)
|
||||
def test_prepare_instance_partition_image(
|
||||
self, cleanup_vmedia_boot_mock, configure_vmedia_mock,
|
||||
update_boot_mode_mock, update_secure_boot_mode_mock):
|
||||
update_boot_mode_mock, update_secure_boot_mode_mock,
|
||||
is_iscsi_boot_mock):
|
||||
self.node.driver_internal_info = {'root_uuid_or_disk_id': (
|
||||
"12312642-09d3-467f-8e09-12385826a123")}
|
||||
self.node.save()
|
||||
is_iscsi_boot_mock.return_value = False
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.boot.prepare_instance(task)
|
||||
|
||||
cleanup_vmedia_boot_mock.assert_called_once_with(task)
|
||||
configure_vmedia_mock.assert_called_once_with(
|
||||
mock.ANY, task, "12312642-09d3-467f-8e09-12385826a123")
|
||||
update_boot_mode_mock.assert_called_once_with(task)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, True)
|
||||
|
||||
@mock.patch.object(ilo_common, 'cleanup_vmedia_boot', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'get_boot_mode_for_deploy',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.IloManagement, 'set_iscsi_boot_target',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
def test_prepare_instance_boot_from_volume(
|
||||
self, update_secure_boot_mode_mock,
|
||||
update_boot_mode_mock, set_boot_device_mock,
|
||||
set_iscsi_boot_target_mock, get_boot_mode_mock,
|
||||
is_iscsi_boot_mock, cleanup_vmedia_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
is_iscsi_boot_mock.return_value = True
|
||||
get_boot_mode_mock.return_value = 'uefi'
|
||||
task.driver.boot.prepare_instance(task)
|
||||
cleanup_vmedia_boot_mock.assert_called_once_with(task)
|
||||
set_iscsi_boot_target_mock.assert_called_once_with(mock.ANY, task)
|
||||
set_boot_device_mock.assert_called_once_with(
|
||||
task, boot_devices.ISCSIBOOT, persistent=True)
|
||||
update_boot_mode_mock.assert_called_once_with(task)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, True)
|
||||
|
||||
@mock.patch.object(ilo_common, 'cleanup_vmedia_boot', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'get_boot_mode_for_deploy',
|
||||
spec_set=True, autospec=True)
|
||||
def test_prepare_instance_boot_from_volume_bios(
|
||||
self, get_boot_mode_mock,
|
||||
is_iscsi_boot_mock, cleanup_vmedia_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
is_iscsi_boot_mock.return_value = True
|
||||
get_boot_mode_mock.return_value = 'bios'
|
||||
self.assertRaisesRegex(exception.InstanceDeployFailure,
|
||||
"Virtual media can not boot volume "
|
||||
"in BIOS boot mode.",
|
||||
task.driver.boot.prepare_instance, task)
|
||||
cleanup_vmedia_boot_mock.assert_called_once_with(task)
|
||||
|
||||
|
||||
class IloPXEBootTestCase(db_base.DbTestCase):
|
||||
|
||||
@ -972,6 +1106,8 @@ class IloPXEBootTestCase(db_base.DbTestCase):
|
||||
pxe_prepare_instance_mock.assert_called_once_with(mock.ANY,
|
||||
task, None)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
|
||||
@ -979,15 +1115,39 @@ class IloPXEBootTestCase(db_base.DbTestCase):
|
||||
@mock.patch.object(pxe.PXEBoot, 'clean_up_instance', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clean_up_instance(self, pxe_cleanup_mock, node_power_mock,
|
||||
update_secure_boot_mode_mock):
|
||||
update_secure_boot_mode_mock,
|
||||
is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
|
||||
is_iscsi_boot_mock.return_value = False
|
||||
node_power_mock.assert_called_once_with(task, states.POWER_OFF)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, False)
|
||||
pxe_cleanup_mock.assert_called_once_with(mock.ANY, task)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(pxe.PXEBoot, 'clean_up_instance', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clean_up_instance_boot_from_volume_bios(
|
||||
self, pxe_cleanup_mock, node_power_mock,
|
||||
update_secure_boot_mode_mock, is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
is_iscsi_boot_mock.return_value = True
|
||||
node_power_mock.assert_called_once_with(task, states.POWER_OFF)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, False)
|
||||
pxe_cleanup_mock.assert_called_once_with(mock.ANY, task)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'get_boot_mode_for_deploy',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
|
||||
@ -996,11 +1156,95 @@ class IloPXEBootTestCase(db_base.DbTestCase):
|
||||
autospec=True)
|
||||
def test_prepare_instance(self, pxe_prepare_instance_mock,
|
||||
update_boot_mode_mock,
|
||||
update_secure_boot_mode_mock):
|
||||
update_secure_boot_mode_mock,
|
||||
get_boot_mode_mock,
|
||||
is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.boot.prepare_instance(task)
|
||||
|
||||
is_iscsi_boot_mock.return_value = False
|
||||
get_boot_mode_mock.return_value = 'uefi'
|
||||
update_boot_mode_mock.assert_called_once_with(task)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, True)
|
||||
pxe_prepare_instance_mock.assert_called_once_with(mock.ANY, task)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'get_boot_mode_for_deploy',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(pxe.PXEBoot, 'prepare_instance', spec_set=True,
|
||||
autospec=True)
|
||||
def test_prepare_instance_bios(self, pxe_prepare_instance_mock,
|
||||
update_boot_mode_mock,
|
||||
update_secure_boot_mode_mock,
|
||||
get_boot_mode_mock,
|
||||
is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.boot.prepare_instance(task)
|
||||
is_iscsi_boot_mock.return_value = False
|
||||
get_boot_mode_mock.return_value = 'bios'
|
||||
update_boot_mode_mock.assert_called_once_with(task)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, True)
|
||||
pxe_prepare_instance_mock.assert_called_once_with(mock.ANY, task)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'get_boot_mode_for_deploy',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.IloManagement, 'set_iscsi_boot_target',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
def test_prepare_instance_boot_from_volume(
|
||||
self, update_secure_boot_mode_mock,
|
||||
update_boot_mode_mock, set_boot_device_mock,
|
||||
set_iscsi_boot_target_mock, get_boot_mode_mock,
|
||||
is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
is_iscsi_boot_mock.return_value = True
|
||||
get_boot_mode_mock.return_value = 'uefi'
|
||||
task.driver.boot.prepare_instance(task)
|
||||
set_iscsi_boot_target_mock.assert_called_once_with(mock.ANY, task)
|
||||
set_boot_device_mock.assert_called_once_with(
|
||||
task, boot_devices.ISCSIBOOT, persistent=True)
|
||||
update_boot_mode_mock.assert_called_once_with(task)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, True)
|
||||
self.assertIsNone(self.node.driver_internal_info.get(
|
||||
'ilo_uefi_iscsi_boot'))
|
||||
|
||||
@mock.patch.object(deploy_utils, 'is_iscsi_boot',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.IloManagement, 'clear_iscsi_boot_target',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clean_up_instance_boot_from_volume(self, node_power_mock,
|
||||
update_secure_boot_mode_mock,
|
||||
clear_iscsi_boot_target_mock,
|
||||
is_iscsi_boot_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['ilo_uefi_iscsi_boot'] = True
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
is_iscsi_boot_mock.return_value = True
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
clear_iscsi_boot_target_mock.assert_called_once_with(mock.ANY,
|
||||
task)
|
||||
node_power_mock.assert_called_once_with(task, states.POWER_OFF)
|
||||
update_secure_boot_mode_mock.assert_called_once_with(task, False)
|
||||
self.assertIsNone(self.node.driver_internal_info.get(
|
||||
'ilo_uefi_iscsi_boot'))
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import mock
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import exception
|
||||
@ -63,7 +64,7 @@ class IloManagementTestCase(db_base.DbTestCase):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
expected = [boot_devices.PXE, boot_devices.DISK,
|
||||
boot_devices.CDROM]
|
||||
boot_devices.CDROM, boot_devices.ISCSIBOOT]
|
||||
self.assertEqual(
|
||||
sorted(expected),
|
||||
sorted(task.driver.management.
|
||||
@ -709,3 +710,132 @@ class IloManagementTestCase(db_base.DbTestCase):
|
||||
task.driver.management._update_firmware_sum_final(
|
||||
task, command)
|
||||
self.assertTrue(log_mock.exception.called)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_set_iscsi_boot_target_with_auth(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
vol_id = uuidutils.generate_uuid()
|
||||
obj_utils.create_test_volume_target(
|
||||
self.context, node_id=self.node.id, volume_type='iscsi',
|
||||
boot_index=0, volume_id='1234', uuid=vol_id,
|
||||
properties={'target_lun': 0,
|
||||
'target_portal': 'fake_host:3260',
|
||||
'target_iqn': 'fake_iqn',
|
||||
'auth_username': 'fake_username',
|
||||
'auth_password': 'fake_password'})
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['boot_from_volume'] = vol_id
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
task.driver.management.set_iscsi_boot_target(task)
|
||||
ilo_object_mock.set_iscsi_info.assert_called_once_with(
|
||||
'fake_iqn', 0, 'fake_host', '3260',
|
||||
'CHAP', 'fake_username', 'fake_password')
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_set_iscsi_boot_target_without_auth(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
vol_id = uuidutils.generate_uuid()
|
||||
obj_utils.create_test_volume_target(
|
||||
self.context, node_id=self.node.id, volume_type='iscsi',
|
||||
boot_index=0, volume_id='1234', uuid=vol_id,
|
||||
properties={'target_lun': 0,
|
||||
'target_portal': 'fake_host:3260',
|
||||
'target_iqn': 'fake_iqn'})
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['boot_from_volume'] = vol_id
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
task.driver.management.set_iscsi_boot_target(task)
|
||||
ilo_object_mock.set_iscsi_info.assert_called_once_with(
|
||||
'fake_iqn', 0, 'fake_host', '3260')
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_set_iscsi_boot_target_failed(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
vol_id = uuidutils.generate_uuid()
|
||||
obj_utils.create_test_volume_target(
|
||||
self.context, node_id=self.node.id, volume_type='iscsi',
|
||||
boot_index=0, volume_id='1234', uuid=vol_id,
|
||||
properties={'target_lun': 0,
|
||||
'target_portal': 'fake_host:3260',
|
||||
'target_iqn': 'fake_iqn',
|
||||
'auth_username': 'fake_username',
|
||||
'auth_password': 'fake_password'})
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['boot_from_volume'] = vol_id
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
ilo_object_mock.set_iscsi_info.side_effect = (
|
||||
ilo_error.IloError)
|
||||
self.assertRaises(exception.IloOperationError,
|
||||
task.driver.management.set_iscsi_boot_target,
|
||||
task)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_set_iscsi_boot_target_in_bios(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
vol_id = uuidutils.generate_uuid()
|
||||
obj_utils.create_test_volume_target(
|
||||
self.context, node_id=self.node.id, volume_type='iscsi',
|
||||
boot_index=0, volume_id='1234', uuid=vol_id,
|
||||
properties={'target_lun': 0,
|
||||
'target_portal': 'fake_host:3260',
|
||||
'target_iqn': 'fake_iqn',
|
||||
'auth_username': 'fake_username',
|
||||
'auth_password': 'fake_password'})
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['boot_from_volume'] = vol_id
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
ilo_object_mock.set_iscsi_info.side_effect = (
|
||||
ilo_error.IloCommandNotSupportedInBiosError)
|
||||
self.assertRaises(exception.IloOperationNotSupported,
|
||||
task.driver.management.set_iscsi_boot_target,
|
||||
task)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clear_iscsi_boot_target(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
|
||||
task.driver.management.clear_iscsi_boot_target(task)
|
||||
ilo_object_mock.unset_iscsi_info.assert_called_once()
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clear_iscsi_boot_target_failed(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
ilo_object_mock.unset_iscsi_info.side_effect = (
|
||||
ilo_error.IloError)
|
||||
self.assertRaises(exception.IloOperationError,
|
||||
task.driver.management.clear_iscsi_boot_target,
|
||||
task)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_clear_iscsi_boot_target_in_bios(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
ilo_object_mock.unset_iscsi_info.side_effect = (
|
||||
ilo_error.IloCommandNotSupportedInBiosError)
|
||||
self.assertRaises(exception.IloOperationNotSupported,
|
||||
task.driver.management.clear_iscsi_boot_target,
|
||||
task)
|
||||
|
@ -61,6 +61,8 @@ if not proliantutils:
|
||||
proliantutils.exception.IloError = type('IloError', (Exception,), {})
|
||||
command_exception = type('IloCommandNotSupportedError', (Exception,), {})
|
||||
proliantutils.exception.IloCommandNotSupportedError = command_exception
|
||||
proliantutils.exception.IloCommandNotSupportedInBiosError = type(
|
||||
'IloCommandNotSupportedInBiosError', (Exception,), {})
|
||||
proliantutils.exception.InvalidInputError = type(
|
||||
'InvalidInputError', (Exception,), {})
|
||||
proliantutils.exception.ImageExtractionFailed = type(
|
||||
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
features:
|
||||
- Enhanced boot interface 'ilo-pxe' and 'ilo-virtual-media' to support
|
||||
firmware based booting from iSCSI volume.
|
||||
upgrade:
|
||||
- The ``update_persistent_boot`` and ``[un]set_iscsi_info`` interfaces
|
||||
of 'proliantutils' library has been enhanced to support booting from
|
||||
an iSCSI volume. To leverage this feature, the 'proliantutils' library
|
||||
needs to be upgraded to version '2.5.0'.
|
Loading…
x
Reference in New Issue
Block a user