Adds support for 'ramdisk' deploy with 'ilo-virtual-media' boot
Adds support for ramdisk boot using 'ramdisk' deploy interface with 'ilo-virtual-media' boot interface for 'ilo' hardware type. Change-Id: Ifc187f9a7a5e086b3c609f619edd09423c1692a0 Story: #2003573 Task: #24867
This commit is contained in:
parent
1dabeb28f8
commit
9ce6e55d47
@ -187,7 +187,13 @@ def _get_boot_iso(task, root_uuid):
|
|||||||
deploy_iso_uuid = deploy_info['ilo_deploy_iso']
|
deploy_iso_uuid = deploy_info['ilo_deploy_iso']
|
||||||
boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)
|
boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)
|
||||||
boot_iso_object_name = _get_boot_iso_object_name(task.node)
|
boot_iso_object_name = _get_boot_iso_object_name(task.node)
|
||||||
kernel_params = CONF.pxe.pxe_append_params
|
kernel_params = ""
|
||||||
|
if deploy_utils.get_boot_option(task.node) == "ramdisk":
|
||||||
|
i_info = task.node.instance_info
|
||||||
|
kernel_params = "root=/dev/ram0 text "
|
||||||
|
kernel_params += i_info.get("ramdisk_kernel_arguments", "")
|
||||||
|
else:
|
||||||
|
kernel_params = CONF.pxe.pxe_append_params
|
||||||
with tempfile.NamedTemporaryFile(dir=CONF.tempdir) as fileobj:
|
with tempfile.NamedTemporaryFile(dir=CONF.tempdir) as fileobj:
|
||||||
boot_iso_tmp_file = fileobj.name
|
boot_iso_tmp_file = fileobj.name
|
||||||
images.create_boot_iso(task.context, boot_iso_tmp_file,
|
images.create_boot_iso(task.context, boot_iso_tmp_file,
|
||||||
@ -396,7 +402,7 @@ def disable_secure_boot_if_supported(task):
|
|||||||
|
|
||||||
class IloVirtualMediaBoot(base.BootInterface):
|
class IloVirtualMediaBoot(base.BootInterface):
|
||||||
|
|
||||||
capabilities = ['iscsi_volume_boot']
|
capabilities = ['iscsi_volume_boot', 'ramdisk_boot']
|
||||||
|
|
||||||
def get_properties(self):
|
def get_properties(self):
|
||||||
# TODO(stendulker): COMMON_PROPERTIES should also include rescue
|
# TODO(stendulker): COMMON_PROPERTIES should also include rescue
|
||||||
@ -414,6 +420,22 @@ class IloVirtualMediaBoot(base.BootInterface):
|
|||||||
missing in the Glance image or 'kernel' and 'ramdisk' not provided
|
missing in the Glance image or 'kernel' and 'ramdisk' not provided
|
||||||
in instance_info for non-Glance image.
|
in instance_info for non-Glance image.
|
||||||
"""
|
"""
|
||||||
|
node = task.node
|
||||||
|
boot_option = deploy_utils.get_boot_option(node)
|
||||||
|
boot_iso = node.instance_info.get('ilo_boot_iso')
|
||||||
|
if (boot_option == "ramdisk" and boot_iso):
|
||||||
|
if not service_utils.is_glance_image(boot_iso):
|
||||||
|
try:
|
||||||
|
image_service.HttpImageService().validate_href(boot_iso)
|
||||||
|
except exception.ImageRefValidationFailed:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.error("Virtual media deploy with 'ramdisk' "
|
||||||
|
"boot_option accepts only Glance images or "
|
||||||
|
"HTTP(S) URLs as "
|
||||||
|
"instance_info['ilo_boot_iso']. Either %s "
|
||||||
|
"is not a valid HTTP(S) URL or is not "
|
||||||
|
"reachable.", boot_iso)
|
||||||
|
return
|
||||||
|
|
||||||
_validate_driver_info(task)
|
_validate_driver_info(task)
|
||||||
|
|
||||||
@ -501,10 +523,10 @@ class IloVirtualMediaBoot(base.BootInterface):
|
|||||||
:raises: InstanceDeployFailure, if its try to boot iSCSI volume in
|
:raises: InstanceDeployFailure, if its try to boot iSCSI volume in
|
||||||
'BIOS' boot mode.
|
'BIOS' boot mode.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ilo_common.cleanup_vmedia_boot(task)
|
ilo_common.cleanup_vmedia_boot(task)
|
||||||
|
|
||||||
boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)
|
boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)
|
||||||
|
boot_option = deploy_utils.get_boot_option(task.node)
|
||||||
|
|
||||||
if deploy_utils.is_iscsi_boot(task):
|
if deploy_utils.is_iscsi_boot(task):
|
||||||
# It will set iSCSI info onto iLO
|
# It will set iSCSI info onto iLO
|
||||||
@ -520,6 +542,12 @@ class IloVirtualMediaBoot(base.BootInterface):
|
|||||||
else:
|
else:
|
||||||
msg = 'Virtual media can not boot volume in BIOS boot mode.'
|
msg = 'Virtual media can not boot volume in BIOS boot mode.'
|
||||||
raise exception.InstanceDeployFailure(msg)
|
raise exception.InstanceDeployFailure(msg)
|
||||||
|
elif boot_option == "ramdisk":
|
||||||
|
boot_iso = _get_boot_iso(task, None)
|
||||||
|
ilo_common.setup_vmedia_for_boot(task, boot_iso)
|
||||||
|
manager_utils.node_set_boot_device(task,
|
||||||
|
boot_devices.CDROM,
|
||||||
|
persistent=True)
|
||||||
else:
|
else:
|
||||||
# Boot from disk every time if the image deployed is
|
# Boot from disk every time if the image deployed is
|
||||||
# a whole disk image.
|
# a whole disk image.
|
||||||
|
@ -683,6 +683,88 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest):
|
|||||||
mock_val_instance_image_info.assert_called_once_with(task)
|
mock_val_instance_image_info.assert_called_once_with(task)
|
||||||
mock_val_driver_info.assert_called_once_with(task)
|
mock_val_driver_info.assert_called_once_with(task)
|
||||||
|
|
||||||
|
@mock.patch.object(ilo_boot, '_validate_driver_info',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(image_service.HttpImageService, 'validate_href',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(service_utils, 'is_glance_image', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
def test_validate_ramdisk_boot_option_glance(self, is_glance_image_mock,
|
||||||
|
validate_href_mock,
|
||||||
|
val_driver_info_mock):
|
||||||
|
instance_info = self.node.instance_info
|
||||||
|
boot_iso = '6b2f0c0c-79e8-4db6-842e-43c9764204af'
|
||||||
|
instance_info['ilo_boot_iso'] = boot_iso
|
||||||
|
instance_info['capabilities'] = '{"boot_option": "ramdisk"}'
|
||||||
|
self.node.instance_info = instance_info
|
||||||
|
self.node.save()
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=False) as task:
|
||||||
|
is_glance_image_mock.return_value = True
|
||||||
|
task.driver.boot.validate(task)
|
||||||
|
is_glance_image_mock.assert_called_once_with(boot_iso)
|
||||||
|
self.assertFalse(validate_href_mock.called)
|
||||||
|
self.assertFalse(val_driver_info_mock.called)
|
||||||
|
|
||||||
|
@mock.patch.object(ilo_boot, '_validate_driver_info',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(image_service.HttpImageService, 'validate_href',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(service_utils, 'is_glance_image', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
def test_validate_ramdisk_boot_option_webserver(self, is_glance_image_mock,
|
||||||
|
validate_href_mock,
|
||||||
|
val_driver_info_mock):
|
||||||
|
instance_info = self.node.instance_info
|
||||||
|
boot_iso = 'http://myserver/boot.iso'
|
||||||
|
instance_info['ilo_boot_iso'] = boot_iso
|
||||||
|
instance_info['capabilities'] = '{"boot_option": "ramdisk"}'
|
||||||
|
self.node.instance_info = instance_info
|
||||||
|
self.node.save()
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=False) as task:
|
||||||
|
is_glance_image_mock.return_value = False
|
||||||
|
task.driver.boot.validate(task)
|
||||||
|
is_glance_image_mock.assert_called_once_with(boot_iso)
|
||||||
|
validate_href_mock.assert_called_once_with(mock.ANY, boot_iso)
|
||||||
|
self.assertFalse(val_driver_info_mock.called)
|
||||||
|
|
||||||
|
@mock.patch.object(ilo_boot.LOG, 'error', spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(ilo_boot, '_validate_driver_info',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(image_service.HttpImageService, 'validate_href',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(service_utils, 'is_glance_image', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
def test_validate_ramdisk_boot_option_webserver_exc(self,
|
||||||
|
is_glance_image_mock,
|
||||||
|
validate_href_mock,
|
||||||
|
val_driver_info_mock,
|
||||||
|
log_mock):
|
||||||
|
instance_info = self.node.instance_info
|
||||||
|
validate_href_mock.side_effect = exception.ImageRefValidationFailed(
|
||||||
|
image_href='http://myserver/boot.iso', reason='fail')
|
||||||
|
boot_iso = 'http://myserver/boot.iso'
|
||||||
|
instance_info['ilo_boot_iso'] = boot_iso
|
||||||
|
instance_info['capabilities'] = '{"boot_option": "ramdisk"}'
|
||||||
|
self.node.instance_info = instance_info
|
||||||
|
self.node.save()
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=False) as task:
|
||||||
|
|
||||||
|
is_glance_image_mock.return_value = False
|
||||||
|
self.assertRaisesRegex(exception.ImageRefValidationFailed,
|
||||||
|
"Validation of image href "
|
||||||
|
"http://myserver/boot.iso failed",
|
||||||
|
task.driver.boot.validate, task)
|
||||||
|
is_glance_image_mock.assert_called_once_with(boot_iso)
|
||||||
|
validate_href_mock.assert_called_once_with(mock.ANY, boot_iso)
|
||||||
|
self.assertFalse(val_driver_info_mock.called)
|
||||||
|
self.assertIn("Virtual media deploy with 'ramdisk' boot_option "
|
||||||
|
"accepts only Glance images or HTTP(S) URLs as "
|
||||||
|
"instance_info['ilo_boot_iso'].",
|
||||||
|
log_mock.call_args[0][0])
|
||||||
|
|
||||||
@mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
|
@mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
|
||||||
autospec=True)
|
autospec=True)
|
||||||
@mock.patch.object(ilo_boot, '_validate_driver_info',
|
@mock.patch.object(ilo_boot, '_validate_driver_info',
|
||||||
@ -1086,6 +1168,45 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest):
|
|||||||
self.assertIsNone(task.node.driver_internal_info.get(
|
self.assertIsNone(task.node.driver_internal_info.get(
|
||||||
'ilo_uefi_iscsi_boot'))
|
'ilo_uefi_iscsi_boot'))
|
||||||
|
|
||||||
|
@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(ilo_common, 'setup_vmedia_for_boot',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(ilo_boot, '_get_boot_iso',
|
||||||
|
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_ramdisk(self, update_secure_boot_mode_mock,
|
||||||
|
update_boot_mode_mock,
|
||||||
|
set_boot_device_mock,
|
||||||
|
get_boot_iso_mock,
|
||||||
|
setup_vmedia_mock,
|
||||||
|
is_iscsi_boot_mock,
|
||||||
|
cleanup_vmedia_boot_mock):
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=False) as task:
|
||||||
|
instance_info = task.node.instance_info
|
||||||
|
instance_info['capabilities'] = '{"boot_option": "ramdisk"}'
|
||||||
|
task.node.instance_info = instance_info
|
||||||
|
task.node.save()
|
||||||
|
is_iscsi_boot_mock.return_value = False
|
||||||
|
url = 'http://myserver/boot.iso'
|
||||||
|
get_boot_iso_mock.return_value = url
|
||||||
|
task.driver.boot.prepare_instance(task)
|
||||||
|
cleanup_vmedia_boot_mock.assert_called_once_with(task)
|
||||||
|
get_boot_iso_mock.assert_called_once_with(task, None)
|
||||||
|
setup_vmedia_mock.assert_called_once_with(task, url)
|
||||||
|
set_boot_device_mock.assert_called_once_with(
|
||||||
|
task, boot_devices.CDROM, persistent=True)
|
||||||
|
update_boot_mode_mock.assert_called_once_with(task)
|
||||||
|
update_secure_boot_mode_mock.assert_called_once_with(task, True)
|
||||||
|
|
||||||
def test_validate_rescue(self):
|
def test_validate_rescue(self):
|
||||||
driver_info = self.node.driver_info
|
driver_info = self.node.driver_info
|
||||||
driver_info['ilo_rescue_iso'] = 'rescue.iso'
|
driver_info['ilo_rescue_iso'] = 'rescue.iso'
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds support for booting a ramdisk using virtual media to
|
||||||
|
``ilo-virtual-media`` boot interface when an ironic node is configured
|
||||||
|
with ``ramdisk`` deploy interface.
|
Loading…
x
Reference in New Issue
Block a user