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

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



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:
-- 
1.6.0.6


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