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

[PATCH] add support for bootman to booty



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

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