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

[Xen-devel] [RFC] bootloader improvements - pygrub-solaris



# HG changeset patch
# User john.levon@xxxxxxx
# Date 1163095817 28800
# Node ID 6d2a4f2c5d6c23e1c5a096eef0112303047b2c78
# Parent  aebe98c33a6bc0cd633d915b9e0bad40718c29d6
Sniff for Solaris if not specified. This allows Solaris domU's to automatically
boot correctly without fiddling with domain configs.

Signed-off-by: John Levon <john.levon@xxxxxxx>

diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub
--- a/tools/pygrub/src/pygrub
+++ b/tools/pygrub/src/pygrub
@@ -65,6 +65,15 @@ def get_active_offset(file):
     # the first partition
     P1 = 446
     return struct.unpack("<L", buf[P1+8:P1+12])[0] * SECTOR_SIZE
+
+def open_fs(file):
+    offset = 0
+    if is_disk_image(file):
+        offset = get_active_offset(file)
+        if offset == -1:
+            raise RuntimeError, "Unable to find active partition on disk"
+
+    return fsimage.open(file, offset)
 
 class GrubLineEditor(curses.textpad.Textbox):
     def __init__(self, screen, startx, starty, line = ""):
@@ -143,12 +152,12 @@ class GrubLineEditor(curses.textpad.Text
         
 
 class Grub:
-    def __init__(self, file, isconfig = False):
+    def __init__(self, file, fs = None):
         self.screen = None
         self.entry_win = None
         self.text_win = None
         if file:
-            self.read_config(file, isconfig)
+            self.read_config(file, fs)
 
     def draw_main_windows(self):
         if self.screen is None: #only init stuff once
@@ -295,8 +304,8 @@ class Grub:
             # else, we cancelled and should just go back
             break
 
-    def read_config(self, fn, isConfig = False):
-        """Read the given file to parse the config.  If isconfig, then
+    def read_config(self, fn, fs = None):
+        """Read the given file to parse the config.  If fs = None, then
         we're being given a raw config file rather than a disk image."""
         
         if not os.access(fn, os.R_OK):
@@ -304,38 +313,25 @@ class Grub:
 
         self.cf = grub.GrubConf.GrubConfigFile()
 
-        if isConfig:
+        if not fs:
             # set the config file and parse it
             self.cf.filename = fn
             self.cf.parse()
             return
 
-        offset = 0
-        if is_disk_image(fn):
-            offset = get_active_offset(fn)
-            if offset == -1:
-                raise RuntimeError, "Unable to find active partition on disk"
-
-        # open the image and read the grub config
-        fs = fsimage.open(fn, offset)
-
-        if fs is not None:
-            grubfile = None
-            for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf",
-                      "/grub/menu.lst", "/grub/grub.conf"):
-                if fs.file_exists(f):
-                    grubfile = f
-                    break
-            if grubfile is None:
-                raise RuntimeError, "we couldn't find grub config file in the 
image provided."
-            f = fs.open_file(grubfile)
-            buf = f.read()
-            del f
-            del fs
-            # then parse the grub config
-            self.cf.parse(buf)
-        else:
-            raise RuntimeError, "Unable to read filesystem" 
+        grubfile = None
+        for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf",
+                  "/grub/menu.lst", "/grub/grub.conf"):
+            if fs.file_exists(f):
+                grubfile = f
+                break
+        if grubfile is None:
+            raise RuntimeError, "we couldn't find grub config file in the 
image provided."
+        f = fs.open_file(grubfile)
+        buf = f.read()
+        del f
+        # then parse the grub config
+        self.cf.parse(buf)
 
     def run(self):
         timeout = int(self.cf.timeout)
@@ -431,15 +427,16 @@ def get_entry_idx(cf, entry):
 
     return None
 
-def run_grub(file, isconfig, entry):
+def run_grub(file, entry, fs):
     global g
+    global sel
 
     def run_main(scr, *args):
         global sel
         global g
         sel = g.run()
 
-    g = Grub(file, isconfig)
+    g = Grub(file, fs)
     if interactive:
         curses.wrapper(run_main)
     else:
@@ -457,21 +454,48 @@ def run_grub(file, isconfig, entry):
 
     img = g.cf.images[sel]
 
+    grubcfg = { "kernel": None, "ramdisk": None, "args": None }
+
     grubcfg["kernel"] = img.kernel[1]
-    grubcfg["ramdisk"] = img.initrd[1]
-    grubcfg["args"] = img.args[1]
-
-    print "Going to boot %s" %(img.title)
-    print "  kernel: %s" % grubcfg["kernel"]
     if img.initrd:
-        print "  initrd: %s" % grubcfg["ramdisk"]
-
-    if isconfig:
-        print "  args: %s" % grubcfg["args"]
-        sys.exit(0)
-        
+        grubcfg["ramdisk"] = img.initrd[1]
+    if img.args:
+        grubcfg["args"] = img.args
+
     return grubcfg
 
+# If nothing has been specified, look for a Solaris domU. If found, perform the
+# necessary tweaks.
+def sniff_solaris(fs, cfg):
+    if not fs.file_exists("/platform/i86xen/kernel/unix"):
+        return cfg
+    
+    # darned python
+    longmode = (sys.maxint != 2147483647L)
+    if not longmode:
+        longmode = os.uname()[4] == "x86_64"
+    if not longmode:
+        if (os.access("/usr/bin/isainfo", os.R_OK) and
+            os.popen("/usr/bin/isainfo -b").read() == "64\n"):
+            longmode = True
+
+    if not cfg["kernel"]:
+        cfg["kernel"] = "/platform/i86xen/kernel/unix";
+        if longmode:
+            cfg["kernel"] = "/platform/i86xen/kernel/amd64/unix";
+        cfg["ramdisk"] = "/platform/i86pc/boot_archive"
+
+    # we need to pass the path to the kernel as the first argument, but only if
+    # it's not present in args already.
+    args = cfg["args"]
+    cfg["args"] = cfg["kernel"] + " "
+    if args:
+        if string.split(args)[0] == cfg["kernel"]:
+            cfg["args"] = ""
+        cfg["args"] += args
+
+    return cfg
+ 
 if __name__ == "__main__":
     sel = None
     
@@ -497,11 +521,11 @@ if __name__ == "__main__":
     isconfig = False
 
     # what was passed in
-    incfg = { "kernel": None, "ramdisk": None, "args": None };
-    # what grub chose
-    chosencfg = { "kernel": None, "ramdisk": None, "args": None };
+    incfg = { "kernel": None, "ramdisk": None, "args": None }
+    # what grub or sniffing chose
+    chosencfg = { "kernel": None, "ramdisk": None, "args": None }
     # what to boot
-    bootcfg = { "kernel": None, "ramdisk": None, "args": None };
+    bootcfg = { "kernel": None, "ramdisk": None, "args": None }
 
     for o, a in opts:
         if o in ("-q", "--quiet"):
@@ -524,25 +548,26 @@ if __name__ == "__main__":
         elif o in ("--isconfig",):
             isconfig = True
 
-
     if output is None or output == "-":
         fd = sys.stdout.fileno()
     else:
         fd = os.open(output, os.O_WRONLY)
 
-    if not incfg["kernel"]:
-        chosencfg = run_grub(file, isconfig, entry)
-    else:
-        chosencfg = incfg
-     
-    offset = 0
-    if is_disk_image(file):
-        offset = get_active_offset(file)
-        if offset == -1:
-            raise RuntimeError, "Unable to find active partition on disk"
-
-    # read the kernel and initrd onto the hostfs
-    fs = fsimage.open(file, offset)
+    # debug
+    if isconfig:
+        chosencfg = run_grub(file, entry)
+        print "  kernel: %s" % chosencfg["kernel"]
+        if img.initrd:
+            print "  initrd: %s" % chosencfg["ramdisk"]
+        print "  args: %s" % chosencfg["args"]
+        sys.exit(0)
+
+    fs = open_fs(file)
+
+    chosencfg = sniff_solaris(fs, incfg)
+
+    if not chosencfg["kernel"]:
+        chosencfg = run_grub(file, entry, fs)
 
     data = fs.open_file(chosencfg["kernel"]).read()
     (tfd, bootcfg["kernel"]) = tempfile.mkstemp(prefix="boot_kernel.", 
dir="/var/lib/xen")

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.