Merge "Provide a path to set explicit ipxe bootloaders"
This commit is contained in:
commit
19866e3ddb
@ -1691,10 +1691,8 @@ function configure_ironic_conductor {
|
||||
local pxebin
|
||||
pxebin=`basename $IRONIC_PXE_BOOT_IMAGE`
|
||||
uefipxebin=`basename $(get_uefi_ipxe_boot_file)`
|
||||
iniset $IRONIC_CONF_FILE pxe pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
|
||||
iniset $IRONIC_CONF_FILE pxe pxe_bootfile_name $pxebin
|
||||
iniset $IRONIC_CONF_FILE pxe uefi_pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
|
||||
iniset $IRONIC_CONF_FILE pxe uefi_pxe_bootfile_name $uefipxebin
|
||||
iniset $IRONIC_CONF_FILE pxe ipxe_bootfile_name $pxebin
|
||||
iniset $IRONIC_CONF_FILE pxe uefi_ipxe_bootfile_name $uefipxebin
|
||||
iniset $IRONIC_CONF_FILE deploy http_root $IRONIC_HTTP_DIR
|
||||
iniset $IRONIC_CONF_FILE deploy http_url "http://$([[ $IRONIC_HTTP_SERVER =~ : ]] && echo "[$IRONIC_HTTP_SERVER]" || echo $IRONIC_HTTP_SERVER):$IRONIC_HTTP_PORT"
|
||||
if [[ "$IRONIC_IPXE_USE_SWIFT" == "True" ]]; then
|
||||
|
@ -357,41 +357,59 @@ on the Bare Metal service node(s) where ``ironic-conductor`` is running.
|
||||
|
||||
Ubuntu::
|
||||
|
||||
cp /usr/lib/ipxe/{undionly.kpxe,ipxe.efi} /tftpboot
|
||||
cp /usr/lib/ipxe/{undionly.kpxe,ipxe.efi,snponly.efi} /tftpboot
|
||||
|
||||
Fedora/RHEL7/CentOS7::
|
||||
|
||||
cp /usr/share/ipxe/{undionly.kpxe,ipxe.efi} /tftpboot
|
||||
cp /usr/share/ipxe/{undionly.kpxe,ipxe.efi,snponly.efi} /tftpboot
|
||||
|
||||
#. Enable/Configure iPXE in the Bare Metal Service's configuration file
|
||||
(/etc/ironic/ironic.conf):
|
||||
#. Enable/Configure iPXE overrides in the Bare Metal Service's configuration
|
||||
file **if required** (/etc/ironic/ironic.conf):
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pxe]
|
||||
|
||||
# Enable iPXE boot. (boolean value)
|
||||
ipxe_enabled=True
|
||||
|
||||
# Neutron bootfile DHCP parameter. (string value)
|
||||
pxe_bootfile_name=undionly.kpxe
|
||||
ipxe_bootfile_name=undionly.kpxe
|
||||
|
||||
# Bootfile DHCP parameter for UEFI boot mode. (string value)
|
||||
uefi_pxe_bootfile_name=ipxe.efi
|
||||
uefi_ipxe_bootfile_name=ipxe.efi
|
||||
|
||||
# Template file for PXE configuration. (string value)
|
||||
pxe_config_template=$pybasedir/drivers/modules/ipxe_config.template
|
||||
|
||||
# Template file for PXE configuration for UEFI boot loader.
|
||||
# (string value)
|
||||
uefi_pxe_config_template=$pybasedir/drivers/modules/ipxe_config.template
|
||||
ipxe_config_template=$pybasedir/drivers/modules/ipxe_config.template
|
||||
|
||||
.. note::
|
||||
The ``[pxe]ipxe_enabled`` option has been deprecated and will be removed
|
||||
in the T* development cycle. Users should instead consider use of the
|
||||
``ipxe`` boot interface. The same default use of iPXE functionality can
|
||||
be achieved by setting the ``[DEFAULT]default_boot_interface`` option
|
||||
to ``ipxe``.
|
||||
Most UEFI systems have integrated networking which means the
|
||||
``[pxe]uefi_ipxe_bootfile_name`` setting should be set to
|
||||
``snponly.efi``.
|
||||
|
||||
.. note::
|
||||
Setting the iPXE parameters noted in the code block above to no value,
|
||||
in other words setting a line to something like ``ipxe_bootfile_name=``
|
||||
will result in ironic falling back to the default values of the non-iPXE
|
||||
PXE settings. This is for backwards compatability.
|
||||
|
||||
#. Ensure iPXE is the default PXE, if applicable.
|
||||
|
||||
In earlier versions of ironic, a ``[pxe]ipxe_enabled`` setting allowing
|
||||
operators to declare the behavior of the conductor to exclusively operate
|
||||
as if only iPXE was to be used. As time moved on, iPXE functionality was
|
||||
moved to it's own ``ipxe`` boot interface.
|
||||
|
||||
If you want to emulate that same hehavior, set the following in the
|
||||
configuration file (/etc/ironic/ironic.conf):
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[DEFAULT]
|
||||
default_boot_interface=ipxe
|
||||
enabled_boot_interfaces=ipxe,pxe
|
||||
|
||||
.. note::
|
||||
The ``[DEFAULT]enabled_boot_interfaces`` setting may be exclusively set
|
||||
to ``ipxe``, however ironic has multiple interfaces available depending
|
||||
on the hardware types available for use.
|
||||
|
||||
#. It is possible to configure the Bare Metal service in such a way
|
||||
that nodes will boot into the deploy image directly from Object Storage.
|
||||
@ -442,7 +460,6 @@ on the Bare Metal service node(s) where ``ironic-conductor`` is running.
|
||||
|
||||
sudo service ironic-conductor restart
|
||||
|
||||
|
||||
PXE multi-architecture setup
|
||||
----------------------------
|
||||
|
||||
@ -498,6 +515,10 @@ nodes will be deployed by 'grubaa64.efi', and ppc64 nodes by 'bootppc64'::
|
||||
commands, you'll need to switch to use ``linux`` and ``initrd`` command
|
||||
instead.
|
||||
|
||||
.. note::
|
||||
A ``[pxe]ipxe_bootfile_name_by_arch`` setting is available for multi-arch
|
||||
iPXE based deployment, and defaults to the same behavior as the comperable
|
||||
``[pxe]pxe_bootfile_by_arch`` setting for standard PXE.
|
||||
|
||||
PXE timeouts tuning
|
||||
-------------------
|
||||
|
@ -265,7 +265,10 @@ def create_pxe_config(task, pxe_options, template=None, ipxe_enabled=False):
|
||||
"""
|
||||
LOG.debug("Building PXE config for node %s", task.node.uuid)
|
||||
if template is None:
|
||||
template = deploy_utils.get_pxe_config_template(task.node)
|
||||
if ipxe_enabled:
|
||||
template = deploy_utils.get_ipxe_config_template(task.node)
|
||||
else:
|
||||
template = deploy_utils.get_pxe_config_template(task.node)
|
||||
|
||||
_ensure_config_dirs_exist(task, ipxe_enabled)
|
||||
|
||||
@ -384,7 +387,16 @@ def _dhcp_option_file_or_url(task, urlboot=False, ip_version=None):
|
||||
to return options for DHCP. Possible options
|
||||
are 4, and 6.
|
||||
"""
|
||||
boot_file = deploy_utils.get_pxe_boot_file(task.node)
|
||||
try:
|
||||
if task.driver.boot.ipxe_enabled:
|
||||
boot_file = deploy_utils.get_ipxe_boot_file(task.node)
|
||||
else:
|
||||
boot_file = deploy_utils.get_pxe_boot_file(task.node)
|
||||
except AttributeError:
|
||||
# Support boot interfaces that lack an explicit ipxe_enabled
|
||||
# attribute flag.
|
||||
boot_file = deploy_utils.get_pxe_boot_file(task.node)
|
||||
|
||||
# NOTE(TheJulia): There are additional cases as we add new
|
||||
# features, so the logic below is in the form of if/elif/elif
|
||||
if not urlboot:
|
||||
@ -800,7 +812,10 @@ def build_service_pxe_config(task, instance_image_info,
|
||||
pxe_options = build_pxe_config_options(task, instance_image_info,
|
||||
service=True,
|
||||
ipxe_enabled=ipxe_enabled)
|
||||
pxe_config_template = deploy_utils.get_pxe_config_template(node)
|
||||
if ipxe_enabled:
|
||||
pxe_config_template = deploy_utils.get_ipxe_config_template(node)
|
||||
else:
|
||||
pxe_config_template = deploy_utils.get_pxe_config_template(node)
|
||||
create_pxe_config(task, pxe_options, pxe_config_template,
|
||||
ipxe_enabled=ipxe_enabled)
|
||||
|
||||
@ -942,8 +957,12 @@ def prepare_instance_pxe_config(task, image_info,
|
||||
pxe_options = build_pxe_config_options(
|
||||
task, image_info, service=ramdisk_boot,
|
||||
ipxe_enabled=ipxe_enabled)
|
||||
pxe_config_template = (
|
||||
deploy_utils.get_pxe_config_template(node))
|
||||
if ipxe_enabled:
|
||||
pxe_config_template = (
|
||||
deploy_utils.get_ipxe_config_template(node))
|
||||
else:
|
||||
pxe_config_template = (
|
||||
deploy_utils.get_pxe_config_template(node))
|
||||
create_pxe_config(
|
||||
task, pxe_options, pxe_config_template,
|
||||
ipxe_enabled=ipxe_enabled)
|
||||
|
@ -54,14 +54,21 @@ opts = [
|
||||
'$pybasedir', 'drivers/modules/pxe_config.template'),
|
||||
mutable=True,
|
||||
help=_('On ironic-conductor node, template file for PXE '
|
||||
'configuration.')),
|
||||
'loader configuration.')),
|
||||
cfg.StrOpt('ipxe_config_template',
|
||||
default=os.path.join(
|
||||
'$pybasedir', 'drivers/modules/ipxe_config.template'),
|
||||
mutable=True,
|
||||
help=_('On ironic-conductor node, template file for iPXE '
|
||||
'operations.')),
|
||||
cfg.StrOpt('uefi_pxe_config_template',
|
||||
default=os.path.join(
|
||||
'$pybasedir',
|
||||
'drivers/modules/pxe_grub_config.template'),
|
||||
mutable=True,
|
||||
help=_('On ironic-conductor node, template file for PXE '
|
||||
'configuration for UEFI boot loader.')),
|
||||
'configuration for UEFI boot loader. Generally this '
|
||||
'is used for GRUB specific templates.')),
|
||||
cfg.DictOpt('pxe_config_template_by_arch',
|
||||
default={},
|
||||
mutable=True,
|
||||
@ -107,10 +114,22 @@ opts = [
|
||||
cfg.StrOpt('uefi_pxe_bootfile_name',
|
||||
default='bootx64.efi',
|
||||
help=_('Bootfile DHCP parameter for UEFI boot mode.')),
|
||||
cfg.StrOpt('ipxe_bootfile_name',
|
||||
default='undionly.kpxe',
|
||||
help=_('Bootfile DHCP parameter.')),
|
||||
cfg.StrOpt('uefi_ipxe_bootfile_name',
|
||||
default='ipxe.efi',
|
||||
help=_('Bootfile DHCP parameter for UEFI boot mode. If you '
|
||||
'experience problems with booting using it, try '
|
||||
'snponly.efi.')),
|
||||
cfg.DictOpt('pxe_bootfile_name_by_arch',
|
||||
default={},
|
||||
help=_('Bootfile DHCP parameter per node architecture. '
|
||||
'For example: aarch64:grubaa64.efi')),
|
||||
cfg.DictOpt('ipxe_bootfile_name_by_arch',
|
||||
default={},
|
||||
help=_('Bootfile DHCP parameter per node architecture. '
|
||||
'For example: aarch64:ipxe_aa64.efi')),
|
||||
cfg.StrOpt('ipxe_boot_script',
|
||||
default=os.path.join(
|
||||
'$pybasedir', 'drivers/modules/boot.ipxe'),
|
||||
|
@ -378,6 +378,54 @@ def get_pxe_boot_file(node):
|
||||
return boot_file
|
||||
|
||||
|
||||
def get_ipxe_boot_file(node):
|
||||
"""Return the iPXE boot file name requested for deploy.
|
||||
|
||||
This method returns iPXE boot file name to be used for deploy.
|
||||
Architecture specific boot file is searched first. BIOS/UEFI
|
||||
boot file is used if no valid architecture specific file found.
|
||||
|
||||
If no valid value is found, the default reverts to the
|
||||
``get_pxe_boot_file`` method and thus the
|
||||
``[pxe]pxe_bootfile_name`` and ``[pxe]uefi_ipxe_bootfile_name``
|
||||
settings.
|
||||
|
||||
:param node: A single Node.
|
||||
:returns: The iPXE boot file name.
|
||||
"""
|
||||
cpu_arch = node.properties.get('cpu_arch')
|
||||
boot_file = CONF.pxe.ipxe_bootfile_name_by_arch.get(cpu_arch)
|
||||
if boot_file is None:
|
||||
if boot_mode_utils.get_boot_mode(node) == 'uefi':
|
||||
boot_file = CONF.pxe.uefi_ipxe_bootfile_name
|
||||
else:
|
||||
boot_file = CONF.pxe.ipxe_bootfile_name
|
||||
|
||||
if boot_file is None:
|
||||
boot_file = get_pxe_boot_file(node)
|
||||
|
||||
return boot_file
|
||||
|
||||
|
||||
def get_ipxe_config_template(node):
|
||||
"""Return the iPXE config template file name requested of deploy.
|
||||
|
||||
This method returns the iPXE configuration template file.
|
||||
|
||||
:param node: A single Node.
|
||||
:returns: The iPXE config template file name.
|
||||
"""
|
||||
# NOTE(TheJulia): iPXE configuration files don't change based upon the
|
||||
# architecture and we're not trying to support multiple different boot
|
||||
# loaders by architecture as they are all consistent. Where as PXE
|
||||
# could need to be grub for one arch, PXELINUX for another.
|
||||
configured_template = CONF.pxe.ipxe_config_template
|
||||
override_template = node.driver_info.get('pxe_template')
|
||||
if override_template:
|
||||
configured_template = override_template
|
||||
return configured_template or get_pxe_config_template(node)
|
||||
|
||||
|
||||
def get_pxe_config_template(node):
|
||||
"""Return the PXE config template file name requested for deploy.
|
||||
|
||||
|
@ -200,7 +200,10 @@ class PXEBaseMixin(object):
|
||||
if ramdisk_params.get("ipa-api-url"):
|
||||
pxe_options["ipa-api-url"] = ramdisk_params["ipa-api-url"]
|
||||
|
||||
pxe_config_template = deploy_utils.get_pxe_config_template(node)
|
||||
if self.ipxe_enabled:
|
||||
pxe_config_template = deploy_utils.get_ipxe_config_template(node)
|
||||
else:
|
||||
pxe_config_template = deploy_utils.get_pxe_config_template(node)
|
||||
|
||||
pxe_utils.create_pxe_config(task, pxe_options,
|
||||
pxe_config_template,
|
||||
|
@ -645,7 +645,7 @@ class TestPXEUtils(db_base.DbTestCase):
|
||||
'config'),
|
||||
pxe_utils.get_pxe_config_file_path(self.node.uuid))
|
||||
|
||||
def _dhcp_options_for_instance(self, ip_version=4):
|
||||
def _dhcp_options_for_instance(self, ip_version=4, ipxe=False):
|
||||
self.config(ip_version=ip_version, group='pxe')
|
||||
if ip_version == 4:
|
||||
self.config(tftp_server='192.0.2.1', group='pxe')
|
||||
@ -653,6 +653,10 @@ class TestPXEUtils(db_base.DbTestCase):
|
||||
self.config(tftp_server='ff80::1', group='pxe')
|
||||
self.config(pxe_bootfile_name='fake-bootfile', group='pxe')
|
||||
self.config(tftp_root='/tftp-path/', group='pxe')
|
||||
if ipxe:
|
||||
bootfile = 'fake-bootfile-ipxe'
|
||||
else:
|
||||
bootfile = 'fake-bootfile'
|
||||
|
||||
if ip_version == 6:
|
||||
# NOTE(TheJulia): DHCPv6 RFCs seem to indicate that the prior
|
||||
@ -660,11 +664,11 @@ class TestPXEUtils(db_base.DbTestCase):
|
||||
# by vendors. The apparent proper option is to return a
|
||||
# URL in the field https://tools.ietf.org/html/rfc5970#section-3
|
||||
expected_info = [{'opt_name': '59',
|
||||
'opt_value': 'tftp://[ff80::1]/fake-bootfile',
|
||||
'opt_value': 'tftp://[ff80::1]/%s' % bootfile,
|
||||
'ip_version': ip_version}]
|
||||
elif ip_version == 4:
|
||||
expected_info = [{'opt_name': '67',
|
||||
'opt_value': 'fake-bootfile',
|
||||
'opt_value': bootfile,
|
||||
'ip_version': ip_version},
|
||||
{'opt_name': '210',
|
||||
'opt_value': '/tftp-path/',
|
||||
@ -1320,7 +1324,7 @@ class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
|
||||
# URL in the field https://tools.ietf.org/html/rfc5970#section-3
|
||||
expected_boot_script_url = 'http://[ff80::1]:1234/boot.ipxe'
|
||||
expected_info = [{'opt_name': '!175,59',
|
||||
'opt_value': 'tftp://[ff80::1]/fake-bootfile',
|
||||
'opt_value': 'tftp://[ff80::1]/%s' % boot_file,
|
||||
'ip_version': ip_version},
|
||||
{'opt_name': '59',
|
||||
'opt_value': expected_boot_script_url,
|
||||
@ -1352,7 +1356,7 @@ class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
|
||||
if ip_version == 6:
|
||||
# Boot URL variable set from prior test of isc parameters.
|
||||
expected_info = [{'opt_name': 'tag:!ipxe6,59',
|
||||
'opt_value': 'tftp://[ff80::1]/fake-bootfile',
|
||||
'opt_value': 'tftp://[ff80::1]/%s' % boot_file,
|
||||
'ip_version': ip_version},
|
||||
{'opt_name': 'tag:ipxe6,59',
|
||||
'opt_value': expected_boot_script_url,
|
||||
@ -1381,23 +1385,23 @@ class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
|
||||
|
||||
def test_dhcp_options_for_instance_ipxe_bios(self):
|
||||
self.config(ip_version=4, group='pxe')
|
||||
boot_file = 'fake-bootfile-bios'
|
||||
self.config(pxe_bootfile_name=boot_file, group='pxe')
|
||||
boot_file = 'fake-bootfile-bios-ipxe'
|
||||
self.config(ipxe_bootfile_name=boot_file, group='pxe')
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
self._dhcp_options_for_instance_ipxe(task, boot_file)
|
||||
|
||||
def test_dhcp_options_for_instance_ipxe_uefi(self):
|
||||
self.config(ip_version=4, group='pxe')
|
||||
boot_file = 'fake-bootfile-uefi'
|
||||
self.config(uefi_pxe_bootfile_name=boot_file, group='pxe')
|
||||
boot_file = 'fake-bootfile-uefi-ipxe'
|
||||
self.config(uefi_ipxe_bootfile_name=boot_file, group='pxe')
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
task.node.properties['capabilities'] = 'boot_mode:uefi'
|
||||
self._dhcp_options_for_instance_ipxe(task, boot_file)
|
||||
|
||||
def test_dhcp_options_for_ipxe_ipv6(self):
|
||||
self.config(ip_version=6, group='pxe')
|
||||
boot_file = 'fake-bootfile'
|
||||
self.config(pxe_bootfile_name=boot_file, group='pxe')
|
||||
boot_file = 'fake-bootfile-ipxe'
|
||||
self.config(ipxe_bootfile_name=boot_file, group='pxe')
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
self._dhcp_options_for_instance_ipxe(task, boot_file, ip_version=6)
|
||||
|
||||
|
@ -582,6 +582,34 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
|
||||
result = utils.get_pxe_boot_file(self.node)
|
||||
self.assertEqual('bios-bootfile', result)
|
||||
|
||||
def test_get_ipxe_boot_file(self):
|
||||
self.config(ipxe_bootfile_name='meow', group='pxe')
|
||||
result = utils.get_ipxe_boot_file(self.node)
|
||||
self.assertEqual('meow', result)
|
||||
|
||||
def test_get_ipxe_boot_file_uefi(self):
|
||||
self.config(uefi_ipxe_bootfile_name='ipxe-uefi-bootfile', group='pxe')
|
||||
properties = {'capabilities': 'boot_mode:uefi'}
|
||||
self.node.properties = properties
|
||||
result = utils.get_ipxe_boot_file(self.node)
|
||||
self.assertEqual('ipxe-uefi-bootfile', result)
|
||||
|
||||
def test_get_ipxe_boot_file_other_arch(self):
|
||||
arch_names = {'aarch64': 'ipxe-aa64.efi',
|
||||
'x86_64': 'ipxe.kpxe'}
|
||||
self.config(ipxe_bootfile_name_by_arch=arch_names, group='pxe')
|
||||
properties = {'cpu_arch': 'aarch64', 'capabilities': 'boot_mode:uefi'}
|
||||
self.node.properties = properties
|
||||
result = utils.get_ipxe_boot_file(self.node)
|
||||
self.assertEqual('ipxe-aa64.efi', result)
|
||||
|
||||
def test_get_ipxe_boot_file_fallback(self):
|
||||
self.config(ipxe_bootfile_name=None, group='pxe')
|
||||
self.config(uefi_ipxe_bootfile_name=None, group='pxe')
|
||||
self.config(pxe_bootfile_name='lolcat', group='pxe')
|
||||
result = utils.get_ipxe_boot_file(self.node)
|
||||
self.assertEqual('lolcat', result)
|
||||
|
||||
def test_get_pxe_config_template_emtpy_property(self):
|
||||
self.node.properties = {}
|
||||
self.config(pxe_config_template_by_arch=self.template_by_arch,
|
||||
@ -597,6 +625,28 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
|
||||
result = utils.get_pxe_config_template(node)
|
||||
self.assertEqual('fake-template', result)
|
||||
|
||||
def test_get_ipxe_config_template(self):
|
||||
node = obj_utils.create_test_node(
|
||||
self.context, driver='fake-hardware')
|
||||
self.assertIn('ipxe_config.template',
|
||||
utils.get_ipxe_config_template(node))
|
||||
|
||||
def test_get_ipxe_config_template_none(self):
|
||||
self.config(ipxe_config_template=None, group='pxe')
|
||||
self.config(pxe_config_template='magical_bootloader',
|
||||
group='pxe')
|
||||
node = obj_utils.create_test_node(
|
||||
self.context, driver='fake-hardware')
|
||||
self.assertEqual('magical_bootloader',
|
||||
utils.get_ipxe_config_template(node))
|
||||
|
||||
def test_get_ipxe_config_template_override_pxe_fallback(self):
|
||||
node = obj_utils.create_test_node(
|
||||
self.context, driver='fake-hardware',
|
||||
driver_info={'pxe_template': 'magical'})
|
||||
self.assertEqual('magical',
|
||||
utils.get_ipxe_config_template(node))
|
||||
|
||||
|
||||
@mock.patch('time.sleep', lambda sec: None)
|
||||
class OtherFunctionTestCase(db_base.DbTestCase):
|
||||
|
@ -309,14 +309,9 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
||||
mock_cache_r_k.assert_called_once_with(
|
||||
task, {'rescue_kernel': 'a', 'rescue_ramdisk': 'r'},
|
||||
ipxe_enabled=True)
|
||||
if uefi:
|
||||
mock_pxe_config.assert_called_once_with(
|
||||
task, {}, CONF.pxe.uefi_pxe_config_template,
|
||||
ipxe_enabled=True)
|
||||
else:
|
||||
mock_pxe_config.assert_called_once_with(
|
||||
task, {}, CONF.pxe.pxe_config_template,
|
||||
ipxe_enabled=True)
|
||||
mock_pxe_config.assert_called_once_with(
|
||||
task, {}, CONF.pxe.ipxe_config_template,
|
||||
ipxe_enabled=True)
|
||||
|
||||
def test_prepare_ramdisk(self):
|
||||
self.node.provision_state = states.DEPLOYING
|
||||
@ -699,7 +694,7 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
||||
ipxe_enabled=True)
|
||||
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
|
||||
create_pxe_config_mock.assert_called_once_with(
|
||||
task, mock.ANY, CONF.pxe.pxe_config_template,
|
||||
task, mock.ANY, CONF.pxe.ipxe_config_template,
|
||||
ipxe_enabled=True)
|
||||
switch_pxe_config_mock.assert_called_once_with(
|
||||
pxe_config_path, "30212642-09d3-467f-8e09-21685826ab50",
|
||||
@ -816,7 +811,7 @@ class iPXEBootTestCase(db_base.DbTestCase):
|
||||
self.assertFalse(cache_mock.called)
|
||||
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
|
||||
create_pxe_config_mock.assert_called_once_with(
|
||||
task, mock.ANY, CONF.pxe.pxe_config_template,
|
||||
task, mock.ANY, CONF.pxe.ipxe_config_template,
|
||||
ipxe_enabled=True)
|
||||
switch_pxe_config_mock.assert_called_once_with(
|
||||
pxe_config_path, None, boot_modes.LEGACY_BIOS, False,
|
||||
|
@ -0,0 +1,17 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
Operators upgrading from earlier versions using PXE should explicitly set
|
||||
``[pxe]ipxe_bootfile_name``, ``[pxe]uefi_ipxe_bootfile_name``, and
|
||||
possibly ``[pxe]ipxe_bootfile_name_by_arch`` settings, as well as a
|
||||
iPXE specific ``[pxe]ipxe_config_template`` override, if required.
|
||||
|
||||
Setting the ``[pxe]ipxe_config_template`` to no value will result in the
|
||||
``[pxe]pxe_config_template`` being used. The default value points to the
|
||||
supplied standard iPXE template, so only highly customized operators may
|
||||
have to tune this setting.
|
||||
fixes:
|
||||
- |
|
||||
Addresses the lack of an ability to explicitly set different bootloaders
|
||||
for ``iPXE`` and ``PXE`` based boot operations via their respective
|
||||
``ipxe`` and ``pxe`` boot interfaces.
|
Loading…
x
Reference in New Issue
Block a user