Fix provisioning failure with ramdisk
deploy interface
Provisioning fails if ironic node is configured with ``ramdisk`` deploy interface and PXE boot config file is not present for the node. Change-Id: Ic3a41b252751195a60e4757fee21cb2f62c3c7c2 Story: #2003532 Task: #24817
This commit is contained in:
parent
1dabeb28f8
commit
9911293e68
@ -589,6 +589,37 @@ class PXEBoot(base.BootInterface):
|
|||||||
else:
|
else:
|
||||||
_clean_up_pxe_env(task, images_info)
|
_clean_up_pxe_env(task, images_info)
|
||||||
|
|
||||||
|
def _prepare_instance_pxe_config(self, task, image_info,
|
||||||
|
iscsi_boot=False,
|
||||||
|
ramdisk_boot=False):
|
||||||
|
"""Prepares the config file for PXE boot
|
||||||
|
|
||||||
|
:param task: a task from TaskManager.
|
||||||
|
:param image_info: a dict of values of instance image
|
||||||
|
metadata to set on the configuration file.
|
||||||
|
:param iscsi_boot: if boot is from an iSCSI volume or not.
|
||||||
|
:param ramdisk_boot: if the boot is to a ramdisk configuration.
|
||||||
|
:returns: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
node = task.node
|
||||||
|
dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
|
||||||
|
provider = dhcp_factory.DHCPFactory()
|
||||||
|
provider.update_dhcp(task, dhcp_opts)
|
||||||
|
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
||||||
|
node.uuid)
|
||||||
|
if not os.path.isfile(pxe_config_path):
|
||||||
|
pxe_options = _build_pxe_config_options(
|
||||||
|
task, image_info, service=ramdisk_boot)
|
||||||
|
pxe_config_template = (
|
||||||
|
deploy_utils.get_pxe_config_template(node))
|
||||||
|
pxe_utils.create_pxe_config(
|
||||||
|
task, pxe_options, pxe_config_template)
|
||||||
|
deploy_utils.switch_pxe_config(
|
||||||
|
pxe_config_path, None,
|
||||||
|
boot_mode_utils.get_boot_mode_for_deploy(node), False,
|
||||||
|
iscsi_boot=iscsi_boot, ramdisk_boot=ramdisk_boot)
|
||||||
|
|
||||||
@METRICS.timer('PXEBoot.prepare_instance')
|
@METRICS.timer('PXEBoot.prepare_instance')
|
||||||
def prepare_instance(self, task):
|
def prepare_instance(self, task):
|
||||||
"""Prepares the boot of instance.
|
"""Prepares the boot of instance.
|
||||||
@ -606,40 +637,18 @@ class PXEBoot(base.BootInterface):
|
|||||||
node = task.node
|
node = task.node
|
||||||
boot_option = deploy_utils.get_boot_option(node)
|
boot_option = deploy_utils.get_boot_option(node)
|
||||||
boot_device = None
|
boot_device = None
|
||||||
if deploy_utils.is_iscsi_boot(task):
|
instance_image_info = {}
|
||||||
dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
|
if boot_option == "ramdisk":
|
||||||
provider = dhcp_factory.DHCPFactory()
|
|
||||||
provider.update_dhcp(task, dhcp_opts)
|
|
||||||
|
|
||||||
# configure iPXE for iscsi boot
|
|
||||||
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
|
||||||
task.node.uuid)
|
|
||||||
if not os.path.isfile(pxe_config_path):
|
|
||||||
pxe_options = _build_pxe_config_options(task, {})
|
|
||||||
pxe_config_template = (
|
|
||||||
deploy_utils.get_pxe_config_template(node))
|
|
||||||
pxe_utils.create_pxe_config(
|
|
||||||
task, pxe_options, pxe_config_template)
|
|
||||||
deploy_utils.switch_pxe_config(
|
|
||||||
pxe_config_path, None,
|
|
||||||
boot_mode_utils.get_boot_mode_for_deploy(node), False,
|
|
||||||
iscsi_boot=True)
|
|
||||||
boot_device = boot_devices.PXE
|
|
||||||
|
|
||||||
elif boot_option == "ramdisk":
|
|
||||||
instance_image_info = _get_instance_image_info(
|
instance_image_info = _get_instance_image_info(
|
||||||
task.node, task.context)
|
task.node, task.context)
|
||||||
_cache_ramdisk_kernel(task.context, task.node,
|
_cache_ramdisk_kernel(task.context, task.node,
|
||||||
instance_image_info)
|
instance_image_info)
|
||||||
dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
|
|
||||||
provider = dhcp_factory.DHCPFactory()
|
if deploy_utils.is_iscsi_boot(task) or boot_option == "ramdisk":
|
||||||
provider.update_dhcp(task, dhcp_opts)
|
self._prepare_instance_pxe_config(
|
||||||
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
task, instance_image_info,
|
||||||
task.node.uuid)
|
iscsi_boot=deploy_utils.is_iscsi_boot(task),
|
||||||
deploy_utils.switch_pxe_config(
|
ramdisk_boot=(boot_option == "ramdisk"))
|
||||||
pxe_config_path, None,
|
|
||||||
boot_mode_utils.get_boot_mode_for_deploy(node), False,
|
|
||||||
iscsi_boot=False, ramdisk_boot=True)
|
|
||||||
boot_device = boot_devices.PXE
|
boot_device = boot_devices.PXE
|
||||||
|
|
||||||
elif boot_option != "local":
|
elif boot_option != "local":
|
||||||
|
@ -1400,7 +1400,7 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
task, mock.ANY, CONF.pxe.pxe_config_template)
|
task, mock.ANY, CONF.pxe.pxe_config_template)
|
||||||
switch_pxe_config_mock.assert_called_once_with(
|
switch_pxe_config_mock.assert_called_once_with(
|
||||||
pxe_config_path, None, boot_modes.LEGACY_BIOS, False,
|
pxe_config_path, None, boot_modes.LEGACY_BIOS, False,
|
||||||
iscsi_boot=True)
|
iscsi_boot=True, ramdisk_boot=False)
|
||||||
set_boot_device_mock.assert_called_once_with(task,
|
set_boot_device_mock.assert_called_once_with(task,
|
||||||
boot_devices.PXE,
|
boot_devices.PXE,
|
||||||
persistent=True)
|
persistent=True)
|
||||||
@ -1453,6 +1453,59 @@ class PXEBootTestCase(db_base.DbTestCase):
|
|||||||
clean_up_pxe_config_mock.assert_called_once_with(task)
|
clean_up_pxe_config_mock.assert_called_once_with(task)
|
||||||
self.assertFalse(set_boot_device_mock.called)
|
self.assertFalse(set_boot_device_mock.called)
|
||||||
|
|
||||||
|
@mock.patch.object(manager_utils, 'node_set_boot_device', autospec=True)
|
||||||
|
@mock.patch.object(deploy_utils, 'switch_pxe_config', autospec=True)
|
||||||
|
@mock.patch.object(pxe_utils, 'create_pxe_config', autospec=True)
|
||||||
|
@mock.patch.object(dhcp_factory, 'DHCPFactory', autospec=True)
|
||||||
|
@mock.patch.object(pxe, '_cache_ramdisk_kernel', autospec=True)
|
||||||
|
@mock.patch.object(pxe, '_get_instance_image_info', autospec=True)
|
||||||
|
def _test_prepare_instance_ramdisk(
|
||||||
|
self, get_image_info_mock, cache_mock,
|
||||||
|
dhcp_factory_mock, create_pxe_config_mock,
|
||||||
|
switch_pxe_config_mock,
|
||||||
|
set_boot_device_mock, config_file_exits=False):
|
||||||
|
image_info = {'kernel': ['', '/path/to/kernel'],
|
||||||
|
'ramdisk': ['', '/path/to/ramdisk']}
|
||||||
|
get_image_info_mock.return_value = image_info
|
||||||
|
provider_mock = mock.MagicMock()
|
||||||
|
dhcp_factory_mock.return_value = provider_mock
|
||||||
|
self.node.provision_state = states.DEPLOYING
|
||||||
|
get_image_info_mock.return_value = image_info
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
instance_info = task.node.instance_info
|
||||||
|
instance_info['capabilities'] = {'boot_option': 'ramdisk'}
|
||||||
|
task.node.instance_info = instance_info
|
||||||
|
task.node.save()
|
||||||
|
dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
|
||||||
|
pxe_config_path = pxe_utils.get_pxe_config_file_path(
|
||||||
|
task.node.uuid)
|
||||||
|
task.driver.boot.prepare_instance(task)
|
||||||
|
|
||||||
|
get_image_info_mock.assert_called_once_with(
|
||||||
|
task.node, task.context)
|
||||||
|
cache_mock.assert_called_once_with(
|
||||||
|
task.context, task.node, image_info)
|
||||||
|
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
|
||||||
|
if config_file_exits:
|
||||||
|
self.assertFalse(create_pxe_config_mock.called)
|
||||||
|
else:
|
||||||
|
create_pxe_config_mock.assert_called_once_with(
|
||||||
|
task, mock.ANY, CONF.pxe.pxe_config_template)
|
||||||
|
switch_pxe_config_mock.assert_called_once_with(
|
||||||
|
pxe_config_path, None,
|
||||||
|
'bios', False, iscsi_boot=False, ramdisk_boot=True)
|
||||||
|
set_boot_device_mock.assert_called_once_with(task,
|
||||||
|
boot_devices.PXE,
|
||||||
|
persistent=True)
|
||||||
|
|
||||||
|
@mock.patch.object(os.path, 'isfile', lambda path: True)
|
||||||
|
def test_prepare_instance_ramdisk_pxe_conf_missing(self):
|
||||||
|
self._test_prepare_instance_ramdisk(config_file_exits=True)
|
||||||
|
|
||||||
|
@mock.patch.object(os.path, 'isfile', lambda path: False)
|
||||||
|
def test_prepare_instance_ramdisk_pxe_conf_exists(self):
|
||||||
|
self._test_prepare_instance_ramdisk(config_file_exits=False)
|
||||||
|
|
||||||
@mock.patch.object(pxe, '_clean_up_pxe_env', autospec=True)
|
@mock.patch.object(pxe, '_clean_up_pxe_env', autospec=True)
|
||||||
@mock.patch.object(pxe, '_get_instance_image_info', autospec=True)
|
@mock.patch.object(pxe, '_get_instance_image_info', autospec=True)
|
||||||
def test_clean_up_instance(self, get_image_info_mock,
|
def test_clean_up_instance(self, get_image_info_mock,
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixes an issue wherein provisioning fails if ironic node is configured
|
||||||
|
with ``ramdisk`` deploy interface.
|
||||||
|
See `bug 2003532 <https://storyboard.openstack.org/#!/story/2003532>`_ for
|
||||||
|
more details.
|
Loading…
x
Reference in New Issue
Block a user