Fabian Deutsch has uploaded a new change for review. Change subject: Add initramfs re-generation during installation ......................................................................
Add initramfs re-generation during installation Previously Node's initramfs was created at build time and never got changed. This lead to problems in situations where some configuration (i.e. a multipath configuration) was required in initramfs. With this patch, the initramfs will be generated at installation time. Change-Id: I209a82ff6bf10edf0857e362584bc6370081c320 Signed-off-by: Fabian Deutsch <[email protected]> --- M ovirt-node.spec.in M scripts/Makefile.am A scripts/ovirt-node-update-initramfs M src/ovirt/node/utils/system.py M src/ovirtnode/install.py 5 files changed, 122 insertions(+), 40 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/12/42912/1 diff --git a/ovirt-node.spec.in b/ovirt-node.spec.in index 5867ec7..5b39f18 100644 --- a/ovirt-node.spec.in +++ b/ovirt-node.spec.in @@ -1043,6 +1043,7 @@ %{_sbindir}/persist %{_sbindir}/unpersist %{_sbindir}/ovirt-node-upgrade +%{_sbindir}/ovirt-node-update-initramfs %{python_sitelib}/ovirt_config_setup %exclude %{python_sitelib}/ovirt_config_setup/cim.py* %exclude %{python_sitelib}/ovirt_config_setup/snmp.py* diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 9facb20..7e3f257 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -21,7 +21,8 @@ dist_sbin_SCRIPTS = \ persist \ unpersist \ - ovirt-node-upgrade.py + ovirt-node-upgrade.py \ + ovirt-node-update-initramfs dist_bin_SCRIPTS = \ ovirt-node-setup \ diff --git a/scripts/ovirt-node-update-initramfs b/scripts/ovirt-node-update-initramfs new file mode 100755 index 0000000..ec724e7 --- /dev/null +++ b/scripts/ovirt-node-update-initramfs @@ -0,0 +1,31 @@ +#!/bin/env python +""" +The bash logic is: +mount -oremount,rw /run/initramfs/live +mount -obind /run/initramfs/live /boot + +dracut -f + +pushd /boot + mv -v initrd0.img initrd0.img.orig + mv -v initramfs-* initrd0.img +popd + +umount /boot +mount -oremount,ro /run/initramfs/live +""" + +import logging +from ovirt.node.utils import system + + +log = logging.getLogger() + + +if __name__ == "__main__": + stdout = logging.StreamHandler() + log.addHandler(stdout) + initramfs = system.Initramfs() + initramfs.rebuild() + +# vim: set sts=4 et: diff --git a/src/ovirt/node/utils/system.py b/src/ovirt/node/utils/system.py index 3c99967..74a9860 100644 --- a/src/ovirt/node/utils/system.py +++ b/src/ovirt/node/utils/system.py @@ -30,6 +30,7 @@ import subprocess import sys import time +from contextlib import contextmanager import rpm import system_config_keyboard.keyboard @@ -37,6 +38,7 @@ from ovirt.node import base, utils from ovirt.node.utils import process, parse_varfile from ovirt.node.utils.fs import File +from ovirt.node.utils.process import check_output, check_call LOGGER = logging.getLogger(__name__) @@ -351,6 +353,32 @@ else: copy_dir_if_not_exist("%s/%s" % (orig, f), "%s/%s" % (target, f)) + + +@contextmanager +def mounted_boot(): + LOGGER.info("Mounting /liveos and /boot") + import ovirtnode.ovirtfunctions as ofunc + + ofunc.mount_liveos() + if not os.path.ismount("/liveos"): + raise RuntimeError("Failed to mount /liveos") + + liveos = Mount("/liveos") + boot = Mount(device="/liveos", path="/boot") + + liveos.remount(rw=True) + boot.mount("bind") + + if not os.path.ismount("/boot"): + raise RuntimeError("Failed to mount /boot") + + # Now run something in this context + yield + + boot.umount() + liveos.umount() + LOGGER.info("Successfully unmounted /liveos and /boot") class NVR(object): @@ -915,17 +943,18 @@ LOGGER.exception("Can't remount %s on %s!" % (device, self.path)) - def mount(self): + def mount(self, options=""): if not self.device: LOGGER.exception("Can't mount without a device specified") raise RuntimeError("No device was specified when Mount() " "was initialized") fstype = self.fstype if self.fstype else "auto" + options = ["-o" + options] if options else [] try: - utils.process.check_call(["mount", "-t", fstype, - self.device, self.path]) + utils.process.check_call(["mount", "-t", fstype] + options + + [self.device, self.path]) except: LOGGER.exception("Can't mount %s on %s" % (self.device, self.path)) @@ -1196,3 +1225,57 @@ vgs = [x.strip() for x in out.split("\n")] return vgs + + +class Initramfs(base.Base): + """This class shallw rap the logic needed to rebuild the initramfs + + The main obstacle is mounting the correct paths. + Furthermore we are taking care that now orphans are left over. + """ + def _regenerate_initramfs(self): + pri_initrd = "/boot/initrd0.img" + new_initrd = pri_initrd + ".new" + backup_initrd = pri_initrd + ".old" + + LOGGER.info("Regenerating initramfs " + "'%s' (this can take a while)" % pri_initrd) + + rd_stdout = "" + try: + rd_stdout = check_output(["dracut", new_initrd], + stderr=process.PIPE) + except: + LOGGER.warn("dracut failed to regenerate the initramfs") + LOGGER.warn("dracut output: %s" % rd_stdout) + raise + + try: + check_call(["mv", pri_initrd, backup_initrd]) + check_call(["mv", new_initrd, pri_initrd]) + except: + LOGGER.warn("Failed to put new initrd in place") + if not os.path.exists(pri_initrd): + check_call(["mv", backup_initrd, pri_initrd]) + raise + finally: + for orph in [backup_initrd, new_initrd]: + try: + os.unlink(orph) + LOGGER.debug("Removed orphan: %s" % orph) + except: + pass + + def rebuild(self): + LOGGER.info("Preparing to regenerate the initramfs") + LOGGER.info("The regenreation is performed in-place, " + "the existing initrd will be overwritten") + try: + with mounted_boot(): + self._regenerate_initramfs() + LOGGER.info("Initramfs regenration completed successfully") + except: + LOGGER.info("Initramfs regenration failed") + raise + +# vim: set sts=4 et: diff --git a/src/ovirtnode/install.py b/src/ovirtnode/install.py index e125daa..c2b808f 100755 --- a/src/ovirtnode/install.py +++ b/src/ovirtnode/install.py @@ -594,42 +594,8 @@ "rd_NO_MULTIPATH", "") - is_mpath_root = self.disk and self.disk.startswith("/dev/mapper") - has_mpath_wwid = "mpath.wwid=" in self.bootparams - if is_mpath_root and not has_mpath_wwid: - """We need to specify the wwid of the root device if it - is using multiple paths to prevent races within dracut. - Basically there are two options: - 1. bake wwid of root device into initrd - 2. pass wwid of root device on kernel cmdline - I choose 2 because it seems to be less invasive. - https://bugzilla.redhat.com/show_bug.cgi?id=1152948 - """ - lsblkcmd = "lsblk -inls %s | awk 'FNR==2 {print $1}'" % self.disk - lsblkproc = _functions.subprocess_closefds(lsblkcmd, shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - lsblkout, lsblkerr = lsblkproc.communicate() - logger.debug("lsblk returned: %s -- %s" % (lsblkout, lsblkerr)) - if not lsblkout.strip(): - raise RuntimeError("Failed to determin parent of partition: %s" % self.disk) - part_parent = "/dev/mapper/" + lsblkout.strip() - logger.debug("lsblk found parent for partition %s: %s" % (self.disk, part_parent)) - - wwidcmd = "multipath -ll %s | egrep -o '^.*dm-[0-9]' | cut -d' ' -f1" % part_parent - logger.debug("Checking device for multipath: %s" % wwidcmd) - wwidproc = _functions.subprocess_closefds(wwidcmd, shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - wwidout, wwiderr = wwidproc.communicate() - logger.debug("multipath returned: %s -- %s" % (wwidout, wwiderr)) - wwid = wwidout.strip() - if wwid: - logger.debug("Using multipath wwid: %s" % wwid) - self.bootparams += " mpath.wwid=%s" % wwid - logger.debug("Cmdline with mpath: %s" % self.bootparams) - else: - logger.debug("Got NO multipath wwid, not using any") + # Update initramfs to pickup multipath wwids + _system.Initramfs().rebuild() if " " in self.disk: # workaround for grub setup failing with spaces in dev.name: -- To view, visit https://gerrit.ovirt.org/42912 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I209a82ff6bf10edf0857e362584bc6370081c320 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-node Gerrit-Branch: master Gerrit-Owner: Fabian Deutsch <[email protected]> _______________________________________________ node-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/node-patches
