diff --git a/ironic_python_agent/extensions/image.py b/ironic_python_agent/extensions/image.py index 4f3299036..35c9f76d5 100644 --- a/ironic_python_agent/extensions/image.py +++ b/ironic_python_agent/extensions/image.py @@ -118,6 +118,19 @@ def _install_grub2(device, root_uuid, efi_system_part_uuid=None): '"/usr/sbin/%(bin)s-install %(dev)s"' % {'path': path, 'bin': binary_name, 'dev': device}, shell=True, env_variables={'PATH': path_variable}) + # Also run grub-install with --removable, this installs grub to the + # EFI fallback path. Useful if the NVRAM wasn't written correctly, + # was reset or if testing with virt as libvirt resets the NVRAM + # on instance start. + # This operation is essentially a copy operation. Use of the + # --removable flag, per the grub-install source code changes + # the default file to be copied, destination file name, and + # prevents NVRAM from being updated. + if efi_partition: + utils.execute('chroot %(path)s /bin/bash -c ' + '"/usr/sbin/%(bin)s-install %(dev)s --removable"' % + {'path': path, 'bin': binary_name, 'dev': device}, + shell=True, env_variables={'PATH': path_variable}) # Generate the grub configuration file utils.execute('chroot %(path)s /bin/bash -c ' diff --git a/ironic_python_agent/tests/unit/extensions/test_image.py b/ironic_python_agent/tests/unit/extensions/test_image.py index 78836443c..d47cce19c 100644 --- a/ironic_python_agent/tests/unit/extensions/test_image.py +++ b/ironic_python_agent/tests/unit/extensions/test_image.py @@ -137,6 +137,10 @@ class TestImageExtension(test_base.BaseTestCase): '"/usr/sbin/grub-install %s"' % (self.fake_dir, self.fake_dev)), shell=True, env_variables={'PATH': '/sbin:/bin'}), + mock.call(('chroot %s /bin/bash -c ' + '"/usr/sbin/grub-install %s --removable"' % + (self.fake_dir, self.fake_dev)), shell=True, + env_variables={'PATH': '/sbin:/bin'}), mock.call(('chroot %s /bin/bash -c ' '"/usr/sbin/grub-mkconfig -o ' '/boot/grub/grub.cfg"' % self.fake_dir), @@ -193,6 +197,10 @@ class TestImageExtension(test_base.BaseTestCase): '"/usr/sbin/grub-install %s"' % (self.fake_dir, self.fake_dev)), shell=True, env_variables={'PATH': '/sbin:/bin'}), + mock.call(('chroot %s /bin/bash -c ' + '"/usr/sbin/grub-install %s --removable"' % + (self.fake_dir, self.fake_dev)), shell=True, + env_variables={'PATH': '/sbin:/bin'}), mock.call(('chroot %s /bin/bash -c ' '"/usr/sbin/grub-mkconfig -o ' '/boot/grub/grub.cfg"' % self.fake_dir), diff --git a/releasenotes/notes/uefi-fallback-266c647f6aff58fd.yaml b/releasenotes/notes/uefi-fallback-266c647f6aff58fd.yaml new file mode 100644 index 000000000..8c11a37a3 --- /dev/null +++ b/releasenotes/notes/uefi-fallback-266c647f6aff58fd.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - The ironic-python-agent when writing a partition image now + installs grub to the UEFI fallback path. e.g. EFI/BOOT/BOOTX64.EFI + The fallback path is used to boot the bare metal node if the NVRAM is + reset. \ No newline at end of file