[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [PATCH] Generate more complete device.map grub file when upgrading grub (#533621).



Hi,

Looks ok, so ack.

Regards,

Hans


On 11/13/2009 11:01 AM, Radek Vykydal wrote:
When updating device.map during upgrade of grub, I missed case when driveorder
changes between install and upgrade (e.g. when driveorder different from that
detected during upgrade had been specified when isntalling) in my previous
patch. To fix it, I generate device.map in similar way as when installing (only
updating it with some devices that we can know about only from updated
device.map - e.g.  chainloaded devices). This brought me to another
consolidation of the code (started in previous grub installation patches):

* remove updateGrub, use writeGrub with upgrade flag instead
* move code from writeGrub into separate methods
   writeGrubConf (called only for grub (re)install)
   writeSysconfig (called both for grub (re)install and upgrade)
   writeDeviceMap (called both for grub (re)install and upgrade)
* remove old writeSysconfig and updateDeviceMap that were called
   only from upgradeGrub, use new writeSysconfig and writeDeviceMap
   with upgrade flag instead.
---
  booty/x86.py |  164 ++++++++++++++++++++++-----------------------------------
  1 files changed, 63 insertions(+), 101 deletions(-)

diff --git a/booty/x86.py b/booty/x86.py
index 9106bb0..40ec7f2 100644
--- a/booty/x86.py
+++ b/booty/x86.py
@@ -200,9 +200,44 @@ class x86BootloaderInfo(efiBootloaderInfo):
          return self.runGrubInstall(instRoot, bootDev.name, cmds, cfPath)

      def writeGrub(self, instRoot, bl, kernelList, chainList,
-            defaultDev, justConfigFile):
+            defaultDev, justConfigFile, upgrade=False):

          rootDev = self.storage.rootDevice
+        grubTarget = bl.getDevice()
+
+        try:
+            bootDev = self.storage.mountpoints["/boot"]
+            grubPath = "/grub"
+            cfPath = "/"
+        except KeyError:
+            bootDev = rootDev
+            grubPath = "/boot/grub"
+            cfPath = "/boot/"
+
+        if not upgrade:
+            self.writeGrubConf(instRoot, bootDev, rootDev, defaultDev, kernelList,
+                               chainList, grubTarget, grubPath, cfPath)
+
+        # keep track of which devices are used for the device.map
+        usedDevs = set()
+        usedDevs.update(self.getPhysicalDevices(grubTarget))
+        usedDevs.update(self.getPhysicalDevices(rootDev.name))
+        usedDevs.update(self.getPhysicalDevices(bootDev.name))
+        usedDevs.update([dev for (label, longlabel, dev) in chainList if longlabel])
+
+        if not justConfigFile or not upgrade:
+            self.writeDeviceMap(instRoot, usedDevs, upgrade)
+            self.writeSysconfig(instRoot, grubTarget, upgrade)
+
+        if not justConfigFile:
+            return self.installGrub(instRoot, bootDev, grubTarget, grubPath, cfPath)
+
+        return 0
+
+    def writeGrubConf(self, instRoot, bootDev, rootDev, defaultDev, kernelList,
+                      chainList, grubTarget, grubPath, cfPath):
+
+        bootDevs = self.getPhysicalDevices(bootDev.name)

          # XXX old config file should be read here for upgrade

@@ -212,8 +247,6 @@ class x86BootloaderInfo(efiBootloaderInfo):
              self.perms = os.stat(cf)[0]&  0777
              os.rename(cf, cf + '.rpmsave')

-        grubTarget = bl.getDevice()
-
          f = open(cf, "w+")

          f.write("# grub.conf generated by anaconda\n")
@@ -221,24 +254,16 @@ class x86BootloaderInfo(efiBootloaderInfo):
          f.write("# Note that you do not have to rerun grub "
                  "after making changes to this file\n")

-        try:
-            bootDev = self.storage.mountpoints["/boot"]
-            grubPath = "/grub"
-            cfPath = "/"
+        if grubPath == "/grub":
              f.write("# NOTICE:  You have a /boot partition.  This means "
                      "that\n")
              f.write("#          all kernel and initrd paths are relative "
                      "to /boot/, eg.\n")
-        except KeyError:
-            bootDev = rootDev
-            grubPath = "/boot/grub"
-            cfPath = "/boot/"
+        else:
              f.write("# NOTICE:  You do not have a /boot partition.  "
                      "This means that\n")
              f.write("#          all kernel and initrd paths are relative "
                      "to /, eg.\n")
-
-        bootDevs = self.getPhysicalDevices(bootDev.name)

          f.write('#          root %s\n' % self.grubbyPartitionName(bootDevs[0]))
          f.write("#          kernel %svmlinuz-version ro root=%s\n" % (cfPath, rootDev.path))
@@ -254,8 +279,6 @@ class x86BootloaderInfo(efiBootloaderInfo):
              # chain list
              default = len(kernelList)

-        # keep track of which devices are used for the device.map
-        usedDevs = {}

          f.write('default=%s\n' % (default))
          f.write('timeout=%d\n' % (self.timeout or 0))
@@ -285,8 +308,6 @@ class x86BootloaderInfo(efiBootloaderInfo):
                          % (self.grubbyPartitionName(bootDevs[0]), cfPath))
                  f.write("hiddenmenu\n")

-        for dev in self.getPhysicalDevices(grubTarget):
-            usedDevs[dev] = 1

          if self.password:
              f.write('password --md5 %s\n' %(self.password))
@@ -345,7 +366,6 @@ class x86BootloaderInfo(efiBootloaderInfo):
  #            f.write('\tmakeactive\n')
              f.write('\tchainloader +1')
              f.write('\n')
-            usedDevs[device] = 1

          f.close()

@@ -369,24 +389,31 @@ class x86BootloaderInfo(efiBootloaderInfo):
              os.symlink(".." + self.configfile, etcgrub)
          except:
              pass
-
-        for dev in self.getPhysicalDevices(rootDev.name) + bootDevs:
-            usedDevs[dev] = 1
+
+    def writeDeviceMap(self, instRoot, usedDevs, upgrade=False):

          if os.access(instRoot + "/boot/grub/device.map", os.R_OK):
+            # For upgrade, we want also e.g. devs that has been added
+            # to file during install for chainloading.
+            if upgrade:
+                f = open(instRoot + "/boot/grub/device.map", "r")
+                for line in f:
+                    if line.startswith('(hd'):
+                        (grubdisk, dev) = line.split()[:2]
+                        dev = dev[5:]
+                        if dev in self.drivelist:
+                            usedDevs.add(dev)
+                f.close()
              os.rename(instRoot + "/boot/grub/device.map",
                        instRoot + "/boot/grub/device.map.rpmsave")

          f = open(instRoot + "/boot/grub/device.map", "w+")
          f.write("# this device map was generated by anaconda\n")
-        devs = usedDevs.keys()
-        usedDevs = {}
-        for dev in devs:
+        usedDiskDevs = set()
+        for dev in usedDevs:
              drive = getDiskPart(dev, self.storage)[0]
-            if usedDevs.has_key(drive):
-                continue
-            usedDevs[drive] = 1
-        devs = usedDevs.keys()
+            usedDiskDevs.add(drive)
+        devs = list(usedDiskDevs)
          devs.sort()
          for drive in devs:
              # XXX hack city.  If they're not the sort of thing that'll
@@ -396,25 +423,25 @@ class x86BootloaderInfo(efiBootloaderInfo):
                  f.write("(%s)     %s\n" % (self.grubbyDiskName(drive), dev.path))
          f.close()

+    def writeSysconfig(self, instRoot, grubTarget, upgrade):
          sysconf = '/etc/sysconfig/grub'
          if os.access (instRoot + sysconf, os.R_OK):
+            if upgrade:
+                return
              self.perms = os.stat(instRoot + sysconf)[0]&  0777
              os.rename(instRoot + sysconf,
                        instRoot + sysconf + '.rpmsave')
          # if it's an absolute symlink, just get it out of our way
          elif (os.path.islink(instRoot + sysconf) and
                os.readlink(instRoot + sysconf)[0] == '/'):
+            if upgrade:
+                return
              os.rename(instRoot + sysconf,
                        instRoot + sysconf + '.rpmsave')
          f = open(instRoot + sysconf, 'w+')
          f.write("boot=/dev/%s\n" %(grubTarget,))
          f.write("forcelba=0\n")
          f.close()
-
-        if not justConfigFile:
-            return self.installGrub(instRoot, bootDev, grubTarget, grubPath, cfPath)
-
-        return 0

      def grubbyDiskName(self, name):
          return "hd%d" % self.drivelist.index(name)
@@ -462,72 +489,6 @@ class x86BootloaderInfo(efiBootloaderInfo):

          return config

-    def updateDeviceMap(self, instRoot):
-        if os.access(instRoot + "/boot/grub/device.map", os.R_OK):
-            f = open(instRoot + "/boot/grub/device.map", "r")
-            updatedlines = []
-            update = False
-            for line in f:
-                line = line.strip()
-                if line.startswith('(hd'):
-                    (grubdisk, path) = line.split()[:2]
-                    i = int(grubdisk.lstrip('(hd ').rstrip(') '))
-                    actual_path = self.storage.devicetree.getDeviceByName(self.drivelist[i]).path
-                    if path != actual_path:
-                        line = "%s     %s" % (grubdisk, actual_path)
-                        update = True
-                updatedlines.append(line)
-            f.close()
-
-            if update:
-                os.rename(instRoot + "/boot/grub/device.map",
-                          instRoot + "/boot/grub/device.map.rpmsave")
-                f = open(instRoot + "/boot/grub/device.map", "w+")
-                upd_comment = "# file updated by anaconda\n"
-                f.write(upd_comment + '\n'.join(updatedlines) + '\n')
-                f.close()
-
-    # this is a hackish function that depends on the way anaconda writes
-    # out the grub.conf with a #boot= comment
-    # XXX this falls into the category of self.doUpgradeOnly
-    def upgradeGrub(self, instRoot, bl, kernelList, chainList,
-                    defaultDev, justConfigFile):
-        if justConfigFile:
-            return ""
-
-        grubTarget = bl.getDevice()
-
-        if grubTarget is None:
-            return ""
-
-        # migrate info to /etc/sysconfig/grub
-        self.writeSysconfig(instRoot, grubTarget)
-
-        # update device.map
-        self.updateDeviceMap(instRoot)
-
-        # more suckage.  grub-install can't work without a valid /etc/mtab
-        # so we have to do shenanigans to get updated grub installed...
-        # steal some more code above
-        try:
-            bootDev = self.storage.mountpoints["/boot"]
-            grubPath = "/grub"
-            cfPath = "/"
-        except KeyError:
-            bootDev = self.storage.rootDevice
-            grubPath = "/boot/grub"
-            cfPath = "/boot/"
-
-        return self.installGrub(instRoot, bootDev, grubTarget, grubPath, cfPath)
-
-    def writeSysconfig(self, instRoot, installDev):
-        sysconf = '/etc/sysconfig/grub'
-        if not os.access(instRoot + sysconf, os.R_OK):
-            f = open(instRoot + sysconf, "w+")
-            f.write("boot=%s\n" %(installDev,))
-            f.write("forcelba=0\n")
-            f.close()
-
      def write(self, instRoot, bl, kernelList, chainList,
              defaultDev, justConfig):
          if self.timeout is None and chainList:
@@ -536,8 +497,9 @@ class x86BootloaderInfo(efiBootloaderInfo):
          # XXX HACK ALERT - see declaration above
          if self.doUpgradeOnly:
              if self.useGrubVal:
-                return self.upgradeGrub(instRoot, bl, kernelList,
-                                        chainList, defaultDev, justConfig)
+                return self.writeGrub(instRoot, bl, kernelList,
+                                      chainList, defaultDev, justConfig,
+                                      upgrade = True)
              return 0

          if len(kernelList)<  1:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]