Merge "Adds support for 'ramdisk' deploy with 'ilo-virtual-media' boot"

This commit is contained in:
Zuul 2018-10-01 19:18:01 +00:00 committed by Gerrit Code Review
commit 6b87367a0f
3 changed files with 158 additions and 3 deletions

View File

@ -187,7 +187,13 @@ def _get_boot_iso(task, root_uuid):
deploy_iso_uuid = deploy_info['ilo_deploy_iso']
boot_mode = boot_mode_utils.get_boot_mode_for_deploy(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:
boot_iso_tmp_file = fileobj.name
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):
capabilities = ['iscsi_volume_boot']
capabilities = ['iscsi_volume_boot', 'ramdisk_boot']
def get_properties(self):
# 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
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)
@ -501,10 +523,10 @@ class IloVirtualMediaBoot(base.BootInterface):
:raises: InstanceDeployFailure, if its try to boot iSCSI volume in
'BIOS' boot mode.
"""
ilo_common.cleanup_vmedia_boot(task)
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):
# It will set iSCSI info onto iLO
@ -520,6 +542,12 @@ class IloVirtualMediaBoot(base.BootInterface):
else:
msg = 'Virtual media can not boot volume in BIOS boot mode.'
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:
# Boot from disk every time if the image deployed is
# a whole disk image.

View File

@ -683,6 +683,88 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest):
mock_val_instance_image_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',
autospec=True)
@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(
'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):
driver_info = self.node.driver_info
driver_info['ilo_rescue_iso'] = 'rescue.iso'

View File

@ -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.