These patches add support for bootman to booty as well as expose extlinux as a choice in anaconda. For the time being I am trying to maintain support for installs where bootman is not available. The idea behind bootman is to use a single common bootloader config file that could be used to generate a config file for any supported bootloader. Currently grub and extlinux are the only supported bootloaders. A snapshot of bootman can be found here: ftp://download.rpath.com/autosource/bootman-0.20071120.tar.gz Elliot
diff --exclude .hg -ruN anaconda/bootloader.py anaconda-syslinux/bootloader.py --- anaconda/bootloader.py 2007-11-20 17:01:47.000000000 -0500 +++ anaconda-syslinux/bootloader.py 2007-11-20 17:02:41.000000000 -0500 @@ -209,6 +209,7 @@ bl = booty.getBootloader() + # Support legacy grub.template template = None defaults = None for dir in ('/tmp/product', '/tmp/updates', '/mnt/runtime/etc/sysconfig/', @@ -221,13 +222,30 @@ if not defaults and os.access(d, os.R_OK): defaults = d - if not template: - raise IOError, "no such file %s" % template + blconf = False + for dir in ('/mnt/runtime/etc', + '/mnt/sysimage/etc', + '/tmp/product', + '/tmp/updates'): + file = '%s/bootloader.conf' % dir + if os.access(file, os.R_OK): + bl.loadConfig(file) + blconf = True + + if blconf: + # At this point bootman is most likely avaiable and syslinux is a good + # guess. + bl.setBootLoader(BL_EXTLINUX) + else: + # If no bootloader.conf was found try to use the old grub.template + bl.setBootLoader(BL_GRUB_OLD) + if not template: + raise IOError, "no such file %s" % template - bl.cfg = bootloaderConfig.GrubConfig(template) + bl.cfg = bootloaderConfig.GrubConfig(template) - if defaults: - bl.cfg.read(defaults) + if defaults: + bl.cfg.read(defaults) return bl diff --exclude .hg -ruN anaconda/conaryinstall.py anaconda-syslinux/conaryinstall.py --- anaconda/conaryinstall.py 2007-11-20 17:01:47.000000000 -0500 +++ anaconda-syslinux/conaryinstall.py 2007-11-20 17:02:41.000000000 -0500 @@ -83,6 +83,46 @@ self.comps.selectTroveByName('kernel:runtime') + # Sanity check the bootloader selection + # + # if bootman: + # if have extlinux and bl.isExtlinux or not has grub + # select extlinux + # bl.setBootloader(extlinux) + # elif have grub and bl.isGrub + # select grub + # bl.setBootloder(grub.new) + # else: + # must have grub + # select grub + # bl.setBootloader(grub.old + bootman = self.comps.getTroveByName('bootman') + if len(trvs) >= 1: + if not bootman[0].isSelected(): + bootman[0].select() + # bootman is in the group + extlinux = self.comps.getTroveByName('extlinux') + grub = self.comps.getTroveByName('grub') + curBL = anaconda.id.bootloader.getBootLoader() + + if len(extlinux) >= 1 and (curBL == BL_EXTLINUX or + not len(grub) >= 1): + # need to use extlinux + if not extlinux[0].isSelected(): + extlinux[0].select() + anaconda.id.bootloader.setBootLoader(BL_EXTLINUX) + elif len(grub) >= 1: + # don't have extlinux, use grub + if not grub[0].isSelected(): + grub[0].select() + anaconda.id.bootloader.setBootLoader(BL_GRUB) + else: + # don't have bootman, fall back to old grub install method + assert len(grub) >= 1 + if not grub[0].isSelected(): + grub[0].select() + anaconda.id.bootloader.setBootLoader(BL_GRUB_OLD) + def doInstall(self, anaconda): if flags.test: return diff --exclude .hg -ruN anaconda/constants.py anaconda-syslinux/constants.py --- anaconda/constants.py 2007-11-20 17:01:47.000000000 -0500 +++ anaconda-syslinux/constants.py 2007-11-20 17:02:41.000000000 -0500 @@ -55,6 +55,8 @@ # or decrease over time NUMBER_OF_CDS = 5 +# Pull in the bootloader id contants from booty +from bootman.constants import * # common string needs to be easy to change import product diff --exclude .hg -ruN anaconda/fsset.py anaconda-syslinux/fsset.py --- anaconda/fsset.py 2007-11-20 17:01:47.000000000 -0500 +++ anaconda-syslinux/fsset.py 2007-11-20 17:02:42.000000000 -0500 @@ -1403,9 +1403,7 @@ # similarly, on pseries, we really only want the PReP partition active if rhpl.getArch() == "ia64" \ or iutil.getPPCMachine() in ("pSeries", "iSeries", "PMac") \ - or (rhpl.getArch() in ("i386", "x86_64") \ - and (iutil.isEfi() \ - or partedUtils.hasGptLabel(diskset, drive))): + or rhpl.getArch() in ("i386", "x86_64"): if part and part.is_flag_available(parted.PARTITION_BOOT): part.set_flag(parted.PARTITION_BOOT, 1) return diff --exclude .hg -ruN anaconda/iw/bootloader_main_gui.py anaconda-syslinux/iw/bootloader_main_gui.py --- anaconda/iw/bootloader_main_gui.py 2007-11-20 17:01:47.000000000 -0500 +++ anaconda-syslinux/iw/bootloader_main_gui.py 2007-11-20 17:02:42.000000000 -0500 @@ -20,6 +20,7 @@ import gui import bootloader from iw_gui import * +from constants import * from rhpl.translate import _, N_ from osbootwidget import OSBootWidget @@ -56,6 +57,10 @@ self.dispatch.skipStep("instbootloader", skip = 0) if self.blname == "GRUB": self.bl.setUseGrub(1) + self.bl.setBootLoader(BL_GRUB) + elif self.blname == 'EXTLINUX': + self.bl.setUseGrub(1) + self.bl.setBootLoader(BL_EXTLINUX) else: self.bl.setUseGrub(0) @@ -71,13 +76,22 @@ self.dispatch.skipStep("bootloaderadvanced", skip = 1) def bootloaderChanged(self, *args): - active = self.grub_radio.get_active() + active = self.grub_radio.get_active() or \ + self.extlinux_radio.get_active() for widget in [ self.oslist.getWidget(), self.blpass.getWidget(), self.advanced ]: widget.set_sensitive(active) - - + + if self.grub_radio.get_active(): + self.blname = 'GRUB' + elif self.extlinux_radio.get_active(): + self.blname = 'EXTLINUX' + else: + self.blname = None + + self.oslist.changeBootLoader(self.blname) + def getScreen(self, anaconda): self.dispatch = anaconda.dispatch self.bl = anaconda.id.bootloader @@ -96,10 +110,8 @@ spacer.set_size_request(10, 1) thebox.pack_start(spacer, False) - if self.bl.useGrub(): - self.blname = "GRUB" - else: - self.blname = None + # Set extlinux as the default bootloader + self.blname = "EXTLINUX" # make sure we get a valid device to say we're installing to if self.bl.getDevice() is not None: @@ -114,22 +126,35 @@ self.bldev = choices['boot'][0] vb = gtk.VBox(False, 6) - self.grub_radio = gtk.RadioButton(None, _("The %s boot loader will be " - "installed on /dev/%s.") % - ("GRUB", self.bldev)) - self.grub_radio.set_use_underline(False) - vb.pack_start(self.grub_radio) + + bltext = _("The %s boot loader will be installed on /dev/%s.") + + self.extlinux_radio = gtk.RadioButton(None, bltext % ('EXTLINUX', self.bldev), False) + self.grub_radio = gtk.RadioButton(self.extlinux_radio, bltext % ('GRUB', self.bldev), False) self.none_radio = gtk.RadioButton(self.grub_radio, _("No boot loader will be installed.")) + + vb.pack_start(self.extlinux_radio) + vb.pack_start(self.grub_radio) vb.pack_start(self.none_radio) + if self.blname is None: + self.extlinux_radio.set_active(False) + self.grub_radio.set_active(False) self.none_radio.set_active(True) + elif self.blname == 'EXTLINUX': + self.extlinux_radio.set_active(True) self.grub_radio.set_active(False) + self.none_radio.set_active(False) else: + self.extlinux_radio.set_active(False) self.grub_radio.set_active(True) - self.none_radio.set_active(False) + self.none_radio.set_active(False) + + self.extlinux_radio.connect('toggled', self.bootloaderChanged) self.grub_radio.connect("toggled", self.bootloaderChanged) self.none_radio.connect("toggled", self.bootloaderChanged) + thebox.pack_start(vb, False) spacer = gtk.Label("") diff --exclude .hg -ruN anaconda/iw/osbootwidget.py anaconda-syslinux/iw/osbootwidget.py --- anaconda/iw/osbootwidget.py 2007-11-20 17:01:47.000000000 -0500 +++ anaconda-syslinux/iw/osbootwidget.py 2007-11-20 17:02:42.000000000 -0500 @@ -35,7 +35,7 @@ if blname is not None: self.blname = blname else: - self.blname = "GRUB" + self.blname = "EXTLINUX" self.setIllegalChars() @@ -112,7 +112,7 @@ def setIllegalChars(self): # illegal characters for boot loader labels - if self.blname == "GRUB": + if self.blname == "GRUB" or self.blname == 'EXTLINUX': self.illegalChars = [ "$", "=" ] else: self.illegalChars = [ "$", "=", " " ] @@ -121,7 +121,7 @@ if blname is not None: self.blname = blname else: - self.blname = "GRUB" + self.blname = "EXTLINUX" self.setIllegalChars() self.fillOSList() @@ -236,7 +236,7 @@ for key in self.imagelist.keys(): if dev == key: continue - if self.blname == "GRUB": + if self.blname == "GRUB" or self.blname == 'EXTLINUX': thisLabel = self.imagelist[key][1] else: thisLabel = self.imagelist[key][0] @@ -280,7 +280,7 @@ del self.imagelist[oldDevice] # go ahead and add it - if self.blname == "GRUB": + if self.blname == "GRUB" or self.blname == 'EXTLINUX': self.imagelist[dev] = (oldshort, label, isRoot) else: self.imagelist[dev] = (label, oldlong, isRoot) @@ -356,7 +356,7 @@ for dev in keys: (label, longlabel, fstype) = self.imagelist[dev] - if self.blname == "GRUB": + if self.blname == "GRUB" or self.blname == 'EXTLINUX': theLabel = longlabel else: theLabel = label diff --exclude .hg -ruN anaconda/partitions.py anaconda-syslinux/partitions.py --- anaconda/partitions.py 2007-11-20 17:01:47.000000000 -0500 +++ anaconda-syslinux/partitions.py 2007-11-20 17:02:42.000000000 -0500 @@ -868,6 +868,16 @@ "the first four partitions and thus " "won't be bootable.")) + # Require /boot to be ext2 or ext3 since extlinux might + # be the bootloader. + fskeys = ('ext2', 'ext3') + supBoot = [ fsset.fileSystemTypeGet(x) for x in fskeys ] + if br.fstype not in supBoot: + errors.append(_('You must select either a %s or %s ' + 'filesystem for the boot partition.' + % fskeys)) + + if rhpl.getArch() == "ia64": bootreq = self.getRequestByMountPoint("/boot/efi") if not bootreq or bootreq.getActualSize(self, diskset) < 50: diff --exclude .hg -ruN anaconda/tarinstall.py anaconda-syslinux/tarinstall.py --- anaconda/tarinstall.py 2007-11-20 17:01:49.000000000 -0500 +++ anaconda-syslinux/tarinstall.py 2007-11-20 17:02:44.000000000 -0500 @@ -85,13 +85,27 @@ def doPostInstall(self, anaconda): rPathBackendBase.doPostInstall(self, anaconda) - if os.path.exists(self.instPath + '/boot/grub/device.map'): - os.unlink(self.instPath + '/boot/grub/device.map') - # start in run level 5 if xdm is installed if os.path.exists(self.instPath + '/usr/bin/xdm'): anaconda.id.desktop.setDefaultRunLevel(5) + if os.path.exists(self.instPath + '/boot/grub/device.map'): + os.unlink(self.instPath + '/boot/grub/device.map') + + # Sanity check the bootloader selection + hasGrub = os.access(self.instPath + '/sbin/grub', os.X_OK) + if os.access(self.instPath + '/sbin/bootman', os.X_OK): + hasExtLinux = os.access(self.instPath + '/sbin/extlinux', os.X_OK) + curBL = anaconda.id.bootloader.getBootLoader() + + if hasExtLinux and (curBL == BL_EXTLINUX or not hasGrub): + anaconda.id.bootloader.setBootLoader(BL_EXTLINUX) + elif hasGrub: + anaconda.id.bootloader.setBootLoader(BL_GRUB) + else: + assert hasGrub + anaconda.id.bootloader.setBootLoader(BL_GRUB_OLD) + def getRequiredMedia(self): return self.comps.getRequiredMedia() diff --exclude .hg -ruN anaconda/textw/bootloader_text.py anaconda-syslinux/textw/bootloader_text.py --- anaconda/textw/bootloader_text.py 2007-11-20 17:01:49.000000000 -0500 +++ anaconda-syslinux/textw/bootloader_text.py 2007-11-20 17:02:44.000000000 -0500 @@ -29,22 +29,26 @@ if anaconda.dispatch.stepInSkipList("instbootloader"): useGrub = 0 + useExtlinux = 0 noBl = 1 else: - useGrub = 1 + useGrub = 0 + useExtlinux = 1 noBl = 0 blradio = RadioGroup() + extlinux = blradio.add(_('Use EXTLINUX Boot Loader'), 'extlinux', useExtlinux) grub = blradio.add(_("Use GRUB Boot Loader"), "grub", useGrub) skipbl = blradio.add(_("No Boot Loader"), "nobl", noBl) buttons = ButtonBar(screen, [TEXT_OK_BUTTON, TEXT_BACK_BUTTON ] ) grid = GridFormHelp(screen, _("Boot Loader Configuration"), - "btloadinstall", 1, 5) + "btloadinstall", 1, 6) grid.add(t, 0, 0, (0,0,0,1)) - grid.add(grub, 0, 1, (0,0,0,0)) - grid.add(skipbl, 0, 3, (0,0,0,1)) - grid.add(buttons, 0, 4, growx = 1) + grid.add(extlinux, 0, 1, (0,0,0,0)) + grid.add(grub, 0, 3, (0,0,0,1)) + grid.add(skipbl, 0, 4, (0,0,0,2)) + grid.add(buttons, 0, 5, growx = 1) while 1: result = grid.run() @@ -79,6 +83,11 @@ anaconda.dispatch.skipStep("instbootloader", 0) anaconda.dispatch.skipStep("bootloaderadvanced", 0) + if blradio.getSelection() == 'grub': + anaconda.id.bootloader.setBootLoader(BL_GRUB) + else: + anaconda.id.bootloader.setBootLoader(BL_EXTLINUX) + screen.popWindow() return INSTALL_OK @@ -140,6 +149,9 @@ def __call__(self, screen, anaconda): if anaconda.dispatch.stepInSkipList("instbootloader"): return INSTALL_NOOP + if anaconda.id.bootloader.getBootLoader() == BL_EXTLINUX: + return INSTALL_NOOP + choices = anaconda.id.fsset.bootloaderChoices(anaconda.id.diskset, anaconda.id.bootloader) if len(choices.keys()) == 1: anaconda.id.bootloader.setDevice(choices[choices.keys()[0]][0]) @@ -393,7 +405,7 @@ g.add(text, 0, 0, (0,0,0,1), anchorLeft = 1) - self.checkbox = Checkbox(_("Use a GRUB Password")) + self.checkbox = Checkbox(_("Use a Boot Loader Password")) g.add(self.checkbox, 0, 1, (0,0,0,1)) if self.bl.password:
diff --exclude .hg -ruN booty/bootloaderInfo.py booty-syslinux/bootloaderInfo.py --- booty/bootloaderInfo.py 2007-11-20 17:03:25.000000000 -0500 +++ booty-syslinux/bootloaderInfo.py 2007-11-20 17:03:31.000000000 -0500 @@ -1188,31 +1188,38 @@ if len(kernelList) < 1: self.noKernelsWarn(intf) - out = self.writeGrub(instRoot, fsset, bl, langs, kernelList, - chainList, defaultDev, - justConfig | (not self.useGrubVal)) + self.bootman.write(instRoot, fsset, bl, langs, kernelList, + chainList, defaultDev, + justConfig | (not self.useGrubVal)) + # XXX move the lilo.conf out of the way if they're using GRUB # so that /sbin/installkernel does a more correct thing if self.useGrubVal and os.access(instRoot + '/etc/lilo.conf', os.R_OK): os.rename(instRoot + "/etc/lilo.conf", instRoot + "/etc/lilo.conf.anaconda") - - + + def setBootLoader(self, bootLoaderId): + self.bootman.setBootLoader(bootLoaderId) + + def getBootLoader(self): + return self.bootman.getBootLoader() + + def loadConfig(self, file): + self.bootman.loadConfig(file) def getArgList(self): args = bootloaderInfo.getArgList(self) - + if self.forceLBA32: args.append("--lba32") if self.password: args.append("--md5pass=%s" %(self.password)) - - - # XXX add location of bootloader here too + # XXX add location of bootloader here too return args def __init__(self): + from bootman import BootMan bootloaderInfo.__init__(self) # XXX use checkbootloader to determine what to default to self.useGrubVal = 1 @@ -1221,6 +1228,7 @@ self.password = None self.pure = None self.cfg = bootloaderConfig.GrubConfig() + self.bootman = BootMan(self) class s390BootloaderInfo(bootloaderInfo): def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList, diff --exclude .hg -ruN booty/bootman/bman.py booty-syslinux/bootman/bman.py --- booty/bootman/bman.py 1969-12-31 19:00:00.000000000 -0500 +++ booty-syslinux/bootman/bman.py 2007-11-20 17:03:31.000000000 -0500 @@ -0,0 +1,297 @@ +# +# Copyright (c) 2007 rPath, Inc. +# + +import os +import string + +import rhpl + +import bootloaderInfo + +from bootman.constants import * +from bootman.devicemap import DeviceMap +from bootman.config import BootManConfig, BootLoaderConfig + +class BootMan(object): + def __init__(self, bootloader): + self.bootloader = bootloader + + self._dmcfg = DeviceMap(self.bootloader) + self._bmcfg = BootManConfig() + self._cfg = BootLoaderConfig() + + self._dmcfgfile = os.path.join('etc', 'grub', 'device.map') + self._bmcfgfile = os.path.join('etc', 'bootman.conf') + self._cfgfile = os.path.join('etc', 'bootloader.conf') + + # Default to grub as used in rPath Linux 1. + self._blid = BL_GRUB_OLD + + self._blmap = {BL_EXTLINUX: self.writeExtlinux, + BL_GRUB: self.writeGrub, + BL_GRUB_OLD: self.bootloader.writeGrub} + + self._blnames = {BL_EXTLINUX: 'syslinux', + BL_GRUB: 'grub', + BL_GRUB_OLD: 'grub'} + + def loadConfig(self, file): + self._cfg.read(file) + + def setBootLoader(self, bootLoaderId): + assert bootLoaderId in BL_VALID + self._blid = bootLoaderId + + def getBootLoader(self): + return self._blid + + def write(self, *args, **kwargs): + self._blmap[self._blid](*args, **kwargs) + + def writeExtlinux(self, instRoot, fsset, bl, langs, kernelList, chainList, + defaultDev, justConfigFile): + """ + Syslinux install. + """ + + bootDev, baseBootDir = self._writeConfig(instRoot, fsset, bl, langs, + kernelList, chainList, + defaultDev, justConfigFile) + + if justConfigFile: + return + + for device in self.bootloader.getPhysicalDevices(bootDev): + if device[-1].isdigit(): + device = device[:-1] + + rhpl.executil.execWithRedirect('/bin/dd', + ['/bin/dd', + 'if=/boot/extlinux/mbr.bin', + 'of=/dev/%s' % device], + stdout='/dev/tty5', + stderr='/dev/tty5', + root=instRoot) + + cmd = ['/sbin/extlinux', '--install'] + if len(self.bootloader.getPhysicalDevices(bootDev)) > 1: + cmd.append('-r') + cmd.append('/boot/extlinux') + + rhpl.executil.execWithRedirect('/sbin/extlinux', + cmd, + stdout='/dev/tty5', + stderr='/dev/tty5', + root=instRoot) + + def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList, + defaultDev, justConfigFile): + """ + Grub install stub, bootman doesn't support grub.conf at this time. + """ + + bootDev, baseBootDir = self._writeConfig(instRoot, fsset, bl, langs, + kernelList, chainList, + defaultDev, justConfigFile) + + if justConfigFile: + return + + # Find where to install grub + grubTarget = self.bootloader.getDevice() + target = "mbr" + if (grubTarget.startswith('rd/') or grubTarget.startswith('ida/') or + grubTarget.startswith('cciss/') or grubTarget.startswith('sx8/') or + grubTarget.startswith('mapper/')): + if grubTarget[-1].isdigit(): + if grubTarget[-2] == 'p' or \ + (grubTarget[-2].isdigit() and grubTarget[-3] == 'p'): + type = 'partition' + elif grubTarget[-1].isdigit() and not grubTarget.startswith('md'): + target = 'partition' + + grubPath = os.path.join(baseBootDir, 'grub') + + # assemble grub commands to run + args = '--stage2=/boot/grub/stage2 ' + args += self.bootloader.forceLBA32 and '--force-lba ' or '' + + cmds = [] + for device in self.bootloader.getPhysicalDevices(bootDev): + gtPart = self.bootloader.getMatchingPart(device, grubTarget) + diskPart = bootloaderInfo.getDiskPart(gtPart) + gtDisk = self.bootloader.grubbyPartitionName(diskPart[0]) + bPart = self.bootloader.grubbyPartitionName(device) + + stage1Target = gtDisk + if target == 'partition': + stage1Target = self.bootloader.grubbyPartitionName(gtPart) + + cmd = ('root %s\ninstall %s %s/stage1 d %s %s/stage2 p ' + '%s%s/grub.conf') % (bPart, args, grubPath, stage1Target, + grubPath, bPart, grubPath) + + cmds.append(cmd) + + # install grub + for cmd in cmds: + p = os.pipe() + os.write(p[1], cmd + '\n') + os.close(p[1]) + + rhpl.executil.execWithRedirect('/sbin/grub', + [ 'grub', '--batch', '--no-floppy', + '--device-map=%s' % self._dmcfgfile ], + stdin = p[0], + stdout = '/dev/tty5', + stderr = '/dev/tty5', + root = instRoot) + + os.close(p[0]) + + def _writeConfig(self, instRoot, fsset, bl, langs, kernelList, chainList, + defaultDev, justConfigFile): + """ + Populate bootManConfig object from anaconda supplied data, write + bootloader.conf to disk, run bootman to generate extlinux.conf and grub.conf. + """ + + # Set bootloader + self._bmcfg.setBootLoader(self._blnames[self._blid]) + + # Find the root device + rootDev = fsset.getEntryByMountPoint("/").device.getDevice() + + # Find the correct path for kernel/initramfs + baseBootDir = '/' + bootMount = '/boot' + bootDev = fsset.getEntryByMountPoint('/boot').device.getDevice() + if not bootDev: + baseBootDir = '/boot/' + bootMount = '/' + bootDev = fsset.getEntryByMountPoint('/').device.getDevice() + + # Setup bootloader serial settings + if self.bootloader.serial == 1: + # grab the 0-based number of the serial console device + unit = self.bootloader.serialDevice[-1] + + # and we want to set the speed too + speedend = 0 + for char in self.bootloader.serialOptions: + if char not in string.digits: + break + speedend = speedend + 1 + if speedend != 0: + speed = self.bootloader.serialOptions[:speedend] + else: + # reasonable default + speed = '9600' + + settings = '%sn81' % speed + + self._cfg.serial(unit, settings) + + # don't set background image if using serial + self._cfg.background('') + + # Set default timeout (5 seconds) + self._cfg.timeout(50) + + # set readonly + self._cfg.readonly() + + # Setup boot targets + defaultSet = False + for label, longlabel, version in kernelList: + title = '"%s (%s)"' % (longlabel, version) + kernelTag = "-" + version + kernelFile = '/boot/vmlinuz%s' % kernelTag + + initrdFile = '/boot/initrd%s.img' % kernelTag + + root = bootloaderInfo.getRootDevName(initrdFile, fsset, rootDev, + instRoot) + self._cfg.root(root) + + if defaultDev in root: + defaultSet = True + self._cfg.default(version) + + if self.bootloader.args.get(): + self._cfg.options(self.bootloader.args.get()) + + if version.endswith('xen0') or (version.endswith('xen') and \ + not os.path.exists('/proc/xen')): + # hypervisor case + sermap = { 'ttyS0': 'com1', 'ttyS1': 'com2', + 'ttyS2': 'com3', 'ttyS3': 'com4' } + if self.bootloader.serial and \ + self.bootloader.serialDevice in sermap and \ + self.bootloader.serialOptions: + self._cfg.xenoptions('%s=%s' % + (sermap[self.bootloader.serialDevice], + self.bootloader.serialOptions)) + + if version.endswith('xen0'): + hvVersion = version.replace('xen0', '') + else: + hvVersion = version.replace('xen', '') + hvfile = '/boot/xen.gz-%s' % hvVersion + + self._cfg.xen(version, title, hvfile, kernelFile, initrdFile) + else: # normal kernel + self._cfg.linux(version, title, kernelFile, initrdFile) + + for id, (label, longlabel, device) in enumerate(chainList): + if not longlabel: + continue + + # If the default boot device has not been set use the first item + # in the chainList. + if not defaultSet: + defaultSet = True + self._cfg.default('other%s' % id) + + self._cfg.other('other%s' % id, '"%s"' % longlabel, '/dev/%s' % device) + self._dmcfg.use(device) + + # register devices with the device map + for devices in (self.bootloader.getDevice(), rootDev, bootDev): + for device in self.bootloader.getPhysicalDevices(devices): + self._dmcfg.use(device) + + # check for user supplied password + if self.bootloader.password: + self._cfg.password(self.password) + + # Write out bootman.conf + self._bmcfg.write(os.path.join(instRoot, self._bmcfgfile)) + + # Write out device.map + self._dmcfg.write(os.path.join(instRoot, self._dmcfgfile)) + + # Write out bootloader.conf + self._cfg.write(os.path.join(instRoot, self._cfgfile)) + + # copy the grub stage files over into /boot + if os.access(instRoot + '/sbin/grub-install', os.X_OK): + rhpl.executil.execWithRedirect('/sbin/grub-install', + ['/sbin/grub-install', + '--just-copy'], + stdout = '/dev/tty5', + stderr = '/dev/tty5', + root = instRoot) + + # run bootman to generate extlinux.conf and grub.conf + rhpl.executil.execWithRedirect('/sbin/bootman', + ['/sbin/bootman'], + stdout = '/dev/tty5', + stderr = '/dev/tty5', + root = instRoot) + + # Sync data to disk before installing bootloader + bootloaderInfo.syncDataToDisk(bootDev, bootMount, instRoot) + + return bootDev, baseBootDir diff --exclude .hg -ruN booty/bootman/config.py booty-syslinux/bootman/config.py --- booty/bootman/config.py 1969-12-31 19:00:00.000000000 -0500 +++ booty-syslinux/bootman/config.py 2007-11-20 17:03:31.000000000 -0500 @@ -0,0 +1,335 @@ +# +# Copyright (c) 2007 rPath, Inc. +# + +import os + +class _QuotedLineTokenizer(object): + def __init__(self): + self._cur = None + self._list = None + self._singleQuotedString = False + self._doubleQuotedString = False + self._states = {' ': self._space, + '\'': self._singleQuote, + '"': self._doubleQuote, + 'other': self._add, + } + + def tokenize(self, line): + self._list = [''] + for char in line: + self._cur = char + if char in self._states: + self._states[char]() + else: + self._states['other']() + + if self._list[-1] == '': + self._list = self._list[:-1] + + return self._list + + def _space(self): + if not self._singleQuotedString and not self._doubleQuotedString: + self._list.append('') + + def _singleQuote(self): + self._add() + self._singleQuotedString = not self._singleQuotedString + + def _doubleQuote(self): + self._add() + self._doubleQuotedString = not self._doubleQuotedString + + def _add(self): + self._list[-1] += self._cur + + +class _BootManConfigElement(object): + key = None + + def __init__(self): + self._data = {'key': self.key} + + def __getitem__(self, key): + return self._data[key] + + def __setitem__(self, key, value): + self._data[key] = value + + def __contains__(self, key): + return key in self._data + + def __hash__(self): + return hash(self.key) + + +class _BootManLinuxConfig(_BootManConfigElement): + key = 'linux' + + def __init__(self, version, title, kernelPath, initrdPath): + _BootManConfigElement.__init__(self) + self['version'] = version + self['title'] = title + self['kernelPath'] = kernelPath + self['initrdPath'] = initrdPath + + def __str__(self): + return ('%(key)s %(version)s %(title)s %(kernelPath)s %(initrdPath)s' + % self._data) + + +class _BootManXenConfig(_BootManLinuxConfig): + key = 'xen' + + def __init__(self, version, title, xenImagePath, kernelPath, initrdPath): + _BootManLinuxConfig.__init__(self, version, title, kernelPath, + initrdPath) + self['xenImagePath'] = xenImagePath + + def __str__(self): + return ('%(key)s %(version)s %(title)s %(xenImagePath)s %(kernelPath)s ' + '%(initrdPath)s' % self._data) + + +class _BootManOtherConfig(_BootManConfigElement): + key = 'other' + + def __init__(self, version, title, device): + _BootManConfigElement.__init__(self) + self['version'] = version + self['title'] = title + self['device'] = device + + def __str__(self): + return '%(key)s %(version)s %(title)s %(device)s' % self._data + + +class _BootManIncludeConfig(_BootManConfigElement): + key = 'include' + + def set(self, path): + if 'paths' not in self: + self['paths'] = set() + + self['paths'].add(path) + + def __str__(self): + s = '' + for path in self['paths']: + s += '%s %s\n' % (self.key, path) + return s + + +class _BootManOptionsConfig(_BootManConfigElement): + key = 'options' + + def set(self, options): + for option in options.split(): + if '=' in option: + key, value = option.split('=') + else: + key = option + value = None + + self[key] = value + + def __str__(self): + options = [self.key] + for key, value in self._data.iteritems(): + if key == 'key': + continue + + if value is not None: + opt = '='.join([key, value]) + else: + opt = key + + options.append(opt) + + return ' '.join(options) + + +class _BootManXenOptionsConfig(_BootManOptionsConfig): + key = 'xen_options' + + +class _BootManConfigParser(object): + def __init__(self, cfgobj): + self._line = None + self._cfgobj = cfgobj + self._lineTokenizer = _QuotedLineTokenizer() + self._states = {'serial': self._serial, + 'background': self._background, + 'default': self._default, + 'linux': self._linux, + 'xen': self._xen, + 'other': self._other, + 'root': self._root, + 'options': self._options, + 'xen_options': self._xenoptions, + 'read_only': self._readonly, + 'timeout': self._timeout, + 'password': self._password, + 'include': self._include, + } + + def parse(self, cfgline): + self._line = self._lineTokenizer.tokenize(cfgline) + if len(self._line) > 0 and self._line[0] in self._states: + self._states[self._line[0]]() + + def _checkLength(self, length, gt=False): + if gt: assert(len(self._line) > length) + else: assert(len(self._line) == length) + + def _serial(self): + self._checkLength(3) + self._cfgobj.serial(self._line[1], self._line[2]) + + def _background(self): + self._checkLength(2) + self._cfgobj.background(self._line[1]) + + def _default(self): + self._checkLength(2) + self._cfgobj.default(self._line[1]) + + def _linux(self): + self._checkLength(5) + self._cfgobj.linux(*self._line[1:]) + + def _xen(self): + self._checkLength(6) + self._cfgobj.xen(*self._line[1:]) + + def _other(self): + self._checkLength(4) + self._cfgobj.other(*self._line[1:]) + + def _root(self): + self._checkLength(2) + self._cfgobj.root(self._line[1]) + + def _options(self): + self._checkLength(2, gt=True) + self._cfgobj.options(' '.join(self._line[:-1])) + + def _xenoptions(self): + self._checkLength(2, gt=True) + self._cfgobj.xenoptions(' '.join(self._line[:-1])) + + def _readonly(self): + self._checkLength(1) + self._cfgobj.readonly() + + def _timeout(self): + self._checkLength(2) + self._cfgobj.timeout(self._line[1]) + + def _password(self): + self._checkLength(2) + self._cfgobj.password(self._line[1]) + + def _include(self): + self._checkLength(2) + self._cfgobj.include(self._line[1]) + + +class BaseConfig(object): + def _checkDirs(self, file): + path = os.path.dirname(file) + if not os.path.exists(path): + os.makedirs(path) + + +class BootLoaderConfig(BaseConfig): + def __init__(self): + self._parser = _BootManConfigParser(self) + self._data = {'linux': [], + 'xen': [], + 'other': [], + 'include': _BootManIncludeConfig(), + 'options': _BootManOptionsConfig(), + 'xen_options': _BootManXenOptionsConfig(), + } + + def read(self, file): + for line in open(file, 'r'): + self._parser.parse(line) + + def write(self, file): + self._checkDirs(file) + fh = open(file, 'w') + deferred = [] + for key, value in self._data.iteritems(): + if type(value) == type([]): + for item in value: + deferred.append('%s\n' % item) + elif isinstance(value, _BootManConfigElement): + fh.write('%s\n' % value) + else: + fh.write('%s %s\n' % (key, value)) + for value in deferred: + fh.write(value) + fh.close() + + def serial(self, device, settings): + self._data['serialDevice'] = device + self._data['serialSettings'] = settings + + def background(self, background): + self._data['background'] = background + + def default(self, default): + self._data['default'] = default + + def linux(self, version, title, kernelPath, initrdPath): + obj = _BootManLinuxConfig(version, title, kernelPath, initrdPath) + self._data['linux'].append(obj) + + def xen(self, version, title, xenImagePath, kernelPath, initrdPath): + obj = _BootManXenConfig(version, title, xenImagePath, kernelPath, + initrdPath) + self._data['xen'].append(obj) + + def other(self, version, title, device): + obj = _BootManOtherConfig(version, title, device) + self._data['other'].append(obj) + + def root(self, root): + self._data['root'] = root + + def options(self, options): + self._data['options'].set(options) + + def xenoptions(self, options): + self._data['xen_options'].set(options) + + def readonly(self): + self._data['read_only'] = True + + def timeout(self, timeout): + self._data['timeout'] = timeout + + def password(self, pasword): + self._data['password'] = password + + def include(self, path): + self._data['include'].set(path) + + +class BootManConfig(BaseConfig): + def __init__(self): + self._blname = None + + def write(self, file): + self._checkDirs(file) + fh = open(file, 'w') + fh.write('BOOTLOADER=%s' % self._blname) + fh.write('SYSLINUX_MENU=vesamenu') + fh.close() + + def setBootLoader(self, blname): + self._blname = blname diff --exclude .hg -ruN booty/bootman/constants.py booty-syslinux/bootman/constants.py --- booty/bootman/constants.py 1969-12-31 19:00:00.000000000 -0500 +++ booty-syslinux/bootman/constants.py 2007-11-20 17:03:31.000000000 -0500 @@ -0,0 +1,5 @@ +# +# Copyright (c) 2007 rPath, Inc. +# + +BL_EXTLINUX, BL_GRUB, BL_GRUB_OLD = BL_VALID = range(3) diff --exclude .hg -ruN booty/bootman/devicemap.py booty-syslinux/bootman/devicemap.py --- booty/bootman/devicemap.py 1969-12-31 19:00:00.000000000 -0500 +++ booty-syslinux/bootman/devicemap.py 2007-11-20 17:03:31.000000000 -0500 @@ -0,0 +1,31 @@ +# +# Copyright (c) rPath, Inc. +# + +from bootloaderInfo import getDiskPart + +from bootman.config import BaseConfig + +class DeviceMap(BaseConfig): + def __init__(self, bootloader): + self.bootloader = bootloader + self._devs = [] + self._drives = [] + + def use(self, device): + if device not in self._devs: + self._devs.append(device) + drive = getDiskPart(device)[0] + if drive not in self._drives: + self._drives.append(drive) + + def write(self, file): + self._drives.sort() + + self._checkDirs(file) + fh = open(file, 'w') + for drive in self._drives: + if not drive.startswith('md'): + fh.write('(%s) /dev/%s\n' + % (self.bootloader.grubbyDiskName(drive), drive)) + fh.close() diff --exclude .hg -ruN booty/bootman/__init__.py booty-syslinux/bootman/__init__.py --- booty/bootman/__init__.py 1969-12-31 19:00:00.000000000 -0500 +++ booty-syslinux/bootman/__init__.py 2007-11-20 17:03:31.000000000 -0500 @@ -0,0 +1,6 @@ +# +# Copyright (c) 2007 rPath, Inc. +# + +from bootman.constants import * +from bootman.bman import BootMan
_______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list