Merge "Implementation for UEFI iSCSI boot for ILO"
This commit is contained in:
commit
7371477064
@ -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…
Reference in New Issue
Block a user