summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Baker <sbaker@redhat.com>2021-11-30 11:25:43 +1300
committerSteve Baker <sbaker@redhat.com>2021-12-10 15:44:50 +1300
commit3f76724dfb49df9501359e9b97acb1fc9c7689c8 (patch)
treea8ada7cc369e2287ace3b69e0aacc71458a4f592
parent45e8adc1df26f2b940603b2f85d54c0ffcfdfa66 (diff)
downloadironic-3f76724dfb49df9501359e9b97acb1fc9c7689c8.tar.gz
Write initial grub config on startup
This change removes the documentation to copy master_grub_cfg.txt to /tftpboot/grub/grub.cfg and instead writes it on conductor startup. This grub config is a simple redirect config requested by grub network boot. "master" has been renamed to "initial" as a more accurate label of its function. New configuration option [pxe]initial_grub_template allows the deployer to specify a different initial grub template. Change-Id: I71191dd399a6c49607f91d69b5b1673799a38624
-rw-r--r--devstack/lib/ironic14
-rw-r--r--doc/source/install/configure-pxe.rst32
-rw-r--r--ironic/common/pxe_utils.py23
-rw-r--r--ironic/conf/pxe.py5
-rw-r--r--ironic/drivers/modules/initial_grub_cfg.template7
-rw-r--r--ironic/drivers/modules/master_grub_cfg.txt7
-rw-r--r--ironic/drivers/modules/pxe.py1
-rw-r--r--ironic/tests/base.py1
-rw-r--r--ironic/tests/unit/common/test_pxe_utils.py47
-rw-r--r--ironic/tests/unit/conductor/mgr_utils.py7
-rw-r--r--releasenotes/notes/initial_grub-566688b16f773fcf.yaml7
11 files changed, 96 insertions, 55 deletions
diff --git a/devstack/lib/ironic b/devstack/lib/ironic
index 73087ae31..78b45f812 100644
--- a/devstack/lib/ironic
+++ b/devstack/lib/ironic
@@ -2745,20 +2745,6 @@ function configure_tftpd {
echo "re ^(^/) $IRONIC_TFTPBOOT_DIR/\1" >>$IRONIC_TFTPBOOT_DIR/map-file
echo "re ^([^/]) $IRONIC_TFTPBOOT_DIR/\1" >>$IRONIC_TFTPBOOT_DIR/map-file
- # Write a grub.cfg redirect for the ubuntu grub. The fedora grub
- # will fetch the generated grub.cfg-01-<mac> directly
- grub_dir=$IRONIC_TFTPBOOT_DIR/grub
- mkdir -p $grub_dir
- cat << EOF > $grub_dir/grub.cfg
-set default=master
-set timeout=1
-set hidden_timeout_quiet=false
-
-menuentry "master" {
-configfile $IRONIC_TFTPBOOT_DIR/\$net_default_mac.conf
-}
-EOF
- chmod 644 $grub_dir/grub.cfg
else
echo "r ^([^/]) $IRONIC_TFTPBOOT_DIR/\1" >$IRONIC_TFTPBOOT_DIR/map-file
echo "r ^(/tftpboot/) $IRONIC_TFTPBOOT_DIR/\2" >>$IRONIC_TFTPBOOT_DIR/map-file
diff --git a/doc/source/install/configure-pxe.rst b/doc/source/install/configure-pxe.rst
index 0d084d839..59346ce14 100644
--- a/doc/source/install/configure-pxe.rst
+++ b/doc/source/install/configure-pxe.rst
@@ -157,38 +157,6 @@ the PXE UEFI environment.
sudo cp /usr/lib64/efi/shim.efi /tftpboot/bootx64.efi
sudo cp /usr/lib/grub2/x86_64-efi/grub.efi /tftpboot/grubx64.efi
-#. Create master grub.cfg:
-
- Ubuntu: Create grub.cfg under ``/tftpboot/grub`` directory::
-
- GRUB_DIR=/tftpboot/grub
-
- Fedora: Create grub.cfg under ``/tftpboot/EFI/fedora`` directory::
-
- GRUB_DIR=/tftpboot/EFI/fedora
-
- RHEL8/CentOS8: Create grub.cfg under ``/tftpboot/EFI/centos`` directory::
-
- GRUB_DIR=/tftpboot/EFI/centos
-
- SUSE: Create grub.cfg under ``/tftpboot/boot/grub`` directory::
-
- GRUB_DIR=/tftpboot/boot/grub
-
- Create directory ``GRUB_DIR``::
-
- sudo mkdir -p $GRUB_DIR
-
- This file is used to redirect grub to baremetal node specific config file.
- It redirects it to specific grub config file based on DHCP IP assigned to
- baremetal node.
-
- .. literalinclude:: ../../../ironic/drivers/modules/master_grub_cfg.txt
-
- Change the permission of grub.cfg::
-
- sudo chmod 644 $GRUB_DIR/grub.cfg
-
#. Update the bare metal node with ``boot_mode:uefi`` capability in
node's properties field. See :ref:`boot_mode_support` for details.
diff --git a/ironic/common/pxe_utils.py b/ironic/common/pxe_utils.py
index 268c17846..e87f73185 100644
--- a/ironic/common/pxe_utils.py
+++ b/ironic/common/pxe_utils.py
@@ -24,6 +24,7 @@ import jinja2
from oslo_concurrency import processutils
from oslo_log import log as logging
from oslo_utils import excutils
+from oslo_utils import fileutils
from ironic.common import dhcp_factory
from ironic.common import exception
@@ -1286,3 +1287,25 @@ def place_loaders_for_boot(base_path):
'the requested destination. %s' % e)
LOG.error(msg)
raise exception.IncorrectConfiguration(error=msg)
+
+
+def place_common_config():
+ """Place template generated config which is not node specific.
+
+ Currently places the initial grub config for grub network boot.
+ """
+ if not CONF.pxe.initial_grub_template:
+ return
+
+ grub_dir_path = os.path.join(_get_root_dir(False), 'grub')
+ if not os.path.isdir(grub_dir_path):
+ fileutils.ensure_tree(grub_dir_path)
+ if CONF.pxe.dir_permission:
+ os.chmod(grub_dir_path, CONF.pxe.dir_permission)
+
+ initial_grub = utils.render_template(
+ CONF.pxe.initial_grub_template,
+ {'tftp_root': _get_root_dir(False)})
+ initial_grub_path = os.path.join(grub_dir_path, 'grub.cfg')
+
+ utils.write_to_file(initial_grub_path, initial_grub)
diff --git a/ironic/conf/pxe.py b/ironic/conf/pxe.py
index 626c5ef6b..d96712824 100644
--- a/ironic/conf/pxe.py
+++ b/ironic/conf/pxe.py
@@ -204,6 +204,11 @@ opts = [
'for bootloaders. Use example: '
'ipxe.efi:/usr/share/ipxe/ipxe-snponly-x86_64.efi,'
'undionly.kpxe:/usr/share/ipxe/undionly.kpxe')),
+ cfg.StrOpt('initial_grub_template',
+ default=os.path.join(
+ '$pybasedir', 'drivers/modules/initial_grub_cfg.template'),
+ help=_('On ironic-conductor node, the path to the initial grub'
+ 'configuration template for grub network boot.')),
]
diff --git a/ironic/drivers/modules/initial_grub_cfg.template b/ironic/drivers/modules/initial_grub_cfg.template
new file mode 100644
index 000000000..3c1a2d76d
--- /dev/null
+++ b/ironic/drivers/modules/initial_grub_cfg.template
@@ -0,0 +1,7 @@
+set default=initial
+set timeout=5
+set hidden_timeout_quiet=false
+
+menuentry "initial" {
+configfile {{ tftp_root }}/$net_default_mac.conf
+}
diff --git a/ironic/drivers/modules/master_grub_cfg.txt b/ironic/drivers/modules/master_grub_cfg.txt
deleted file mode 100644
index 82847b81e..000000000
--- a/ironic/drivers/modules/master_grub_cfg.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-set default=master
-set timeout=5
-set hidden_timeout_quiet=false
-
-menuentry "master" {
-configfile /tftpboot/$net_default_mac.conf
-}
diff --git a/ironic/drivers/modules/pxe.py b/ironic/drivers/modules/pxe.py
index 8cac287ca..50d962fcf 100644
--- a/ironic/drivers/modules/pxe.py
+++ b/ironic/drivers/modules/pxe.py
@@ -39,6 +39,7 @@ class PXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
capabilities = ['ramdisk_boot', 'pxe_boot']
def __init__(self):
+ pxe_utils.place_common_config()
pxe_utils.place_loaders_for_boot(CONF.deploy.http_root)
pxe_utils.place_loaders_for_boot(CONF.pxe.tftp_root)
diff --git a/ironic/tests/base.py b/ironic/tests/base.py
index 014581963..1045b3d34 100644
--- a/ironic/tests/base.py
+++ b/ironic/tests/base.py
@@ -152,6 +152,7 @@ class TestCase(oslo_test_base.BaseTestCase):
group='neutron')
self.config(enabled_hardware_types=['fake-hardware',
'manual-management'])
+ self.config(initial_grub_template=None, group='pxe')
for iface in drivers_base.ALL_INTERFACES:
default = None
diff --git a/ironic/tests/unit/common/test_pxe_utils.py b/ironic/tests/unit/common/test_pxe_utils.py
index fbfe7f05b..ef1e5d1f3 100644
--- a/ironic/tests/unit/common/test_pxe_utils.py
+++ b/ironic/tests/unit/common/test_pxe_utils.py
@@ -1035,6 +1035,53 @@ class TestPXEUtils(db_base.DbTestCase):
next(actual))
self.assertEqual('/tftpboot-path/' + address + '.conf', next(actual))
+ @mock.patch.object(os, 'makedirs', autospec=True)
+ @mock.patch.object(os.path, 'isdir', autospec=True)
+ @mock.patch.object(os, 'chmod', autospec=True)
+ def test_place_common_config(self, mock_chmod, mock_isdir,
+ mock_makedirs):
+ self.config(initial_grub_template=os.path.join(
+ '$pybasedir',
+ 'drivers/modules/initial_grub_cfg.template'),
+ group='pxe')
+ mock_isdir.return_value = False
+ self.config(group='pxe', dir_permission=0o777)
+
+ def write_to_file(path, contents):
+ self.assertEqual('/tftpboot/grub/grub.cfg', path)
+ self.assertIn(
+ 'configfile /tftpboot/$net_default_mac.conf',
+ contents
+ )
+
+ with mock.patch('ironic.common.utils.write_to_file',
+ wraps=write_to_file):
+ pxe_utils.place_common_config()
+
+ mock_isdir.assert_called_once_with('/tftpboot/grub')
+ mock_makedirs.assert_called_once_with('/tftpboot/grub', 511)
+ mock_chmod.assert_called_once_with('/tftpboot/grub', 0o777)
+
+ @mock.patch.object(os, 'makedirs', autospec=True)
+ @mock.patch.object(os.path, 'isdir', autospec=True)
+ @mock.patch.object(os, 'chmod', autospec=True)
+ def test_place_common_config_existing_dirs(self, mock_chmod, mock_isdir,
+ mock_makedirs):
+ self.config(initial_grub_template=os.path.join(
+ '$pybasedir',
+ 'drivers/modules/initial_grub_cfg.template'),
+ group='pxe')
+ mock_isdir.return_value = True
+
+ with mock.patch('ironic.common.utils.write_to_file',
+ autospec=True) as mock_write:
+ pxe_utils.place_common_config()
+ mock_write.assert_called_once()
+
+ mock_isdir.assert_called_once_with('/tftpboot/grub')
+ mock_makedirs.assert_not_called()
+ mock_chmod.assert_not_called()
+
@mock.patch.object(ipxe.iPXEBoot, '__init__', lambda self: None)
@mock.patch.object(pxe.PXEBoot, '__init__', lambda self: None)
diff --git a/ironic/tests/unit/conductor/mgr_utils.py b/ironic/tests/unit/conductor/mgr_utils.py
index 9baadaf42..4451d7a15 100644
--- a/ironic/tests/unit/conductor/mgr_utils.py
+++ b/ironic/tests/unit/conductor/mgr_utils.py
@@ -24,6 +24,7 @@ from oslo_utils import strutils
from oslo_utils import uuidutils
from ironic.common import exception
+from ironic.common import pxe_utils
from ironic.common import states
from ironic.conductor import manager
from ironic import objects
@@ -143,8 +144,10 @@ class ServiceSetUpMixin(object):
self.service.init_host()
else:
with mock.patch.object(periodics, 'PeriodicWorker', autospec=True):
- self.service.prepare_host()
- self.service.init_host()
+ with mock.patch.object(pxe_utils, 'place_common_config',
+ autospec=True):
+ self.service.prepare_host()
+ self.service.init_host()
self.addCleanup(self._stop_service)
diff --git a/releasenotes/notes/initial_grub-566688b16f773fcf.yaml b/releasenotes/notes/initial_grub-566688b16f773fcf.yaml
new file mode 100644
index 000000000..0c8784949
--- /dev/null
+++ b/releasenotes/notes/initial_grub-566688b16f773fcf.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Manually copying the initial grub config for grub network boot is no longer
+ necessary, as this file is now written to the TFTP root directory on
+ conductor startup. A custom template can be used to generate this file with
+ config option ``[pxe]initial_grub_template``.