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 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list