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