[node-patches] Change in ovirt-node[master]: update: Make sure to use the right kernel modules

fabiand at redhat.com fabiand at redhat.com
Wed Oct 21 20:37:55 UTC 2015


Fabian Deutsch has uploaded a new change for review.

Change subject: update: Make sure to use the right kernel modules
......................................................................

update: Make sure to use the right kernel modules

The initramfs rebuild suffered from the fact that in the Engine upgrade flow, the running
kernel and the modules available in /lib/modules did not match the updated kernel version,
this is because the new rootfs would only become effective on the next boot.
This is a problem because dracut has assumptions.

This patch does some tricks - mainly mounting /lib/modules and /boot into the right
places - to enable dracut to work nicely.

Change-Id: Ie893e722e24b1dd2e8e41970e16091d83c65dad8
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1270228
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/ovirt-node-update-initramfs
M src/ovirt/node/utils/system.py
M src/ovirtnode/install.py
3 files changed, 82 insertions(+), 19 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/14/47614/1

diff --git a/scripts/ovirt-node-update-initramfs b/scripts/ovirt-node-update-initramfs
index 6af825f..a7a9871 100755
--- a/scripts/ovirt-node-update-initramfs
+++ b/scripts/ovirt-node-update-initramfs
@@ -31,7 +31,8 @@
 
     initramfs = system.Initramfs()
     try:
-        initramfs.rebuild()
+        kver = check_output(["uname", "-r"])
+        initramfs.rebuild(kver)
     except:
         log.exception("Initramfs regeneration failed")
         sys.exit(1)
diff --git a/src/ovirt/node/utils/system.py b/src/ovirt/node/utils/system.py
index 472d0bb..d2e7870 100755
--- a/src/ovirt/node/utils/system.py
+++ b/src/ovirt/node/utils/system.py
@@ -356,16 +356,23 @@
 
 
 @contextmanager
-def mounted_boot():
-    LOGGER.info("Mounting /liveos and /boot")
-    import ovirtnode.ovirtfunctions as ofunc
+def mounted_boot(source="/liveos"):
+    """Used to mount /boot
+    Normally /boot is from the /liveos mountpoint, but sometimes it's
+    elsewhere, thus we have source
+    """
 
-    ofunc.mount_liveos()
-    if not os.path.ismount("/liveos"):
-        raise RuntimeError("Failed to mount /liveos")
+    LOGGER.info("Mounting %r to /boot" % source)
 
-    liveos = Mount("/liveos")
-    boot = Mount(device="/liveos", path="/boot")
+    if source == "/liveos":
+        import ovirtnode.ovirtfunctions as ofunc
+        ofunc.mount_liveos()
+
+        if not os.path.ismount("/liveos"):
+            raise RuntimeError("Failed to mount /liveos")
+
+    liveos = Mount(source)
+    boot = Mount(device=source, path="/boot")
 
     liveos.remount(rw=True)
     boot.mount("bind")
@@ -1321,20 +1328,29 @@
 
     The main obstacle is mounting the correct paths.
     Furthermore we are taking care that now orphans are left over.
+
+    Args:
+        boot_source: Source for the /boot mount point
     """
+    boot_source = None
+
+    def __init__(self, boot_source=None):
+        self.boot_source = boot_source
+
     def try_unlink(self, path):
         try:
             os.unlink(path)
         except OSError as e:
             LOGGER.warn("Failed to remove %r: %s", path, e)
 
-    def _generate_new_initramfs(self, new_initrd):
+    def _generate_new_initramfs(self, new_initrd, kver):
         LOGGER.info("Generating new initramfs "
-                    "%r (this can take a while)" % new_initrd)
-
+                    "%r for kver %s (this can take a while)" %
+                    (new_initrd, kver)
         rd_stdout = ""
         try:
-            rd_stdout = check_output(["dracut", new_initrd],
+            rd_stdout = check_output(["dracut", "--kver",
+                                      kver, new_initrd],
                                      stderr=process.STDOUT)
         except:
             LOGGER.warn("dracut failed to generate the initramfs")
@@ -1368,16 +1384,17 @@
             self.try_unlink(new_initrd)
             raise
 
-    def rebuild(self):
+    def rebuild(self, kver):
         pri_initrd = "/boot/initrd0.img"
         new_initrd = "/var/tmp/initrd0.img.new"
 
         LOGGER.info("Preparing to regenerate the initramfs")
         LOGGER.info("The regenreation will overwrite the "
                     "existing")
+        LOGGER.info("Rebuilding for kver: %s" % kver)
 
-        with mounted_boot():
-            self._generate_new_initramfs(new_initrd)
+        with mounted_boot(source=self.boot_source):
+            self._generate_new_initramfs(new_initrd, kver)
             self._install_new_initramfs(new_initrd, pri_initrd)
 
         LOGGER.info("Initramfs regenration completed successfully")
diff --git a/src/ovirtnode/install.py b/src/ovirtnode/install.py
index d59b3a8..537820c 100755
--- a/src/ovirtnode/install.py
+++ b/src/ovirtnode/install.py
@@ -675,9 +675,6 @@
             else:
                 logger.info("Grub Installation Completed")
 
-        # Update initramfs to pickup multipath wwids
-        _system.Initramfs().rebuild()
-
         if _functions.is_iscsi_install() or _functions.findfs("BootNew"):
             # copy default for when Root/HostVG is inaccessible(iscsi upgrade)
             shutil.copy(_functions.OVIRT_DEFAULTS, "/boot")
@@ -695,6 +692,52 @@
         # mark new Root ready to go, reboot() in ovirt-function switches it
         # to active
         e2label_cmd = "e2label \"%s\" RootUpdate" % candidate_dev
+
+        mnts = []
+        try:
+            # Let's mount the update fs, and use that kernel version and modules
+            # We need this work to help dracut
+
+            isomnt = tempfile.mkdtemp("RootUpdate")
+            squashmnt = tempfile.mkdtemp("RootUpdate-LiveOS")
+            updfs = tempfile.mkdtemp("RootUpdate-LiveOS-Img")
+            mnts += [isomnt, squashmnt, updfs]
+
+            # Unpack the iso
+            subprocess.check_call(["mount",
+                                   "LABEL=RootUpdate", isomnt])
+            subprocess.check_call(["mount",
+                                   "%s/LiveOS/squashfs.img" % isomnt, squashmnt])
+            subprocess.check_call(["mount",
+                                   "%s/LiveOS/ext3fs.img" % squashmnt, updfs])
+
+            # Now mount the update modules into place, and find the
+            # correct kver
+            subprocess.check_call(["mount", "--bind",
+                                   "%s/lib/modules" % updfs,
+                                   "/lib/modules"])
+            mnts += ["/lib/modules"]
+
+            upd_kver = str(_functions.passthrough("ls /lib/modules" % updfs)).strip()
+
+            if len(upd_kver.splitlines()) != 1:
+                # It would be very unusual to see more than one kver directory
+                # in /usr/lib, because our images just contain one kernel
+                raise RuntimeError("Found more than one kernel version")
+
+            # Update initramfs to pickup multipath wwids
+            builder = _system.Initramfs(boot_source=isomnt)
+            builder.rebuild(kver=upd_kver)
+
+        except Exception as e:
+            raise e
+
+        finally:
+            # Clean up all eventual mounts
+            for mnt in reversed(mnts):
+                d = _functions.passthrough("umount %s" % mnt, logger.debug)
+                logger.debug("Returned: %s" % d)
+
         if not _functions.system(e2label_cmd):
             logger.error("Unable to relabel " + candidate_dev +
                          " to RootUpdate ")
@@ -710,3 +753,5 @@
             return True
         else:
             return False
+
+# vim: et sts=4 sw=4:


-- 
To view, visit https://gerrit.ovirt.org/47614
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie893e722e24b1dd2e8e41970e16091d83c65dad8
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-node
Gerrit-Branch: master
Gerrit-Owner: Fabian Deutsch <fabiand at redhat.com>



More information about the node-patches mailing list