Implement --grub option (grub2 only so far)
authorMichael Prokop <mika@grml.org>
Sun, 1 Mar 2009 23:18:58 +0000 (00:18 +0100)
committerMichael Prokop <mika@grml.org>
Sun, 1 Mar 2009 23:44:13 +0000 (00:44 +0100)
grml2usb
grml2usb.8.txt

index 0ea1d01..982623f 100755 (executable)
--- a/grml2usb
+++ b/grml2usb
@@ -47,7 +47,7 @@ parser.add_option("--fat16", dest="fat16", action="store_true",
 parser.add_option("--force", dest="force", action="store_true",
                   help="force any actions requiring manual interaction")
 parser.add_option("--grub", dest="grub", action="store_true",
 parser.add_option("--force", dest="force", action="store_true",
                   help="force any actions requiring manual interaction")
 parser.add_option("--grub", dest="grub", action="store_true",
-                  help="install grub bootloader instead of syslinux [TODO]")
+                  help="install grub bootloader instead of syslinux")
 parser.add_option("--initrd", dest="initrd", action="store", type="string",
                   help="install specified initrd instead of the default [TODO]")
 parser.add_option("--kernel", dest="kernel", action="store", type="string",
 parser.add_option("--initrd", dest="initrd", action="store", type="string",
                   help="install specified initrd instead of the default [TODO]")
 parser.add_option("--kernel", dest="kernel", action="store", type="string",
@@ -213,13 +213,147 @@ def mkfs_fat16(device):
         raise Exception("error executing mkfs.vfat")
 
 
         raise Exception("error executing mkfs.vfat")
 
 
-def generate_grub_config(grml_flavour):
-    """Generate grub configuration for use via menu.lst
+def generate_main_grub2_config(grml_flavour, install_partition, bootoptions):
+    """Generate grub2 configuration for use via grub.cfg
+
+    TODO
 
     @grml_flavour: name of grml flavour the configuration should be generated for"""
 
     @grml_flavour: name of grml flavour the configuration should be generated for"""
-    # TODO
-    # * what about systems using grub2 without having grub1 available?
-    # * support grub2?
+
+    local_datestamp = DATESTAMP
+
+    return("""\
+set default=0
+set timeout=5
+
+insmod fat
+
+insmod png
+if background_image (hd0, %(install_partition)s)/boot/grub/grml.png ; then
+  set color_normal=black/black
+  set color_highlight=magenta/black
+else
+  set menu_color_normal=cyan/blue
+  set menu_color_highlight=white/blue
+fi
+
+## main grub2 configuration - generated by grml2usb [main config generated at: %(local_datestamp)s]
+menuentry "%(grml_flavour)s (default)" {
+    set root=(hd0,%(install_partition)s)
+    linux   /boot/release/%(grml_flavour)s/linux26 apm=power-off lang=us vga=791 quiet boot=live nomce module=%(grml_flavour)s %(bootoptions)s
+    initrd  /boot/release/%(grml_flavour)s/initrd.gz
+}
+
+menuentry "Memory test (memtest86+)" {
+   linux   /boot/addons/memtest
+}
+
+menuentry "Grub - all in one image" {
+   linux   /boot/addons/memdisk
+   initrd  /boot/addons/allinone.img
+}
+
+menuentry "FreeDOS" {
+   linux   /boot/addons/memdisk
+   initrd  /boot/addons/balder10.imz
+}
+
+#menuentry "Operating System on first partition of first disk" {
+#    set root=(hd0,1)
+#    chainloader +1
+#}
+#
+#menuentry "Operating System on second partition of first disk" {
+#    set root=(hd0,2)
+#    chainloader +1
+#}
+#
+#menuentry "Operating System on first partition of second disk" {
+#    set root=(hd1,1)
+#    chainloader +1
+#}
+#menuentry "Operating System on second partition of second disk" {
+#    set root=(hd1,2)
+#    chainloader +1
+#}
+
+""" % {'grml_flavour': grml_flavour, 'local_datestamp': local_datestamp, 'bootoptions': bootoptions, 'install_partition': install_partition } )
+
+
+def generate_flavour_specific_grub2_config(grml_flavour, install_partition, bootoptions):
+    """Generate grub2 configuration for use via grub.cfg
+
+    TODO
+
+    @grml_flavour: name of grml flavour the configuration should be generated for"""
+
+    local_datestamp = DATESTAMP
+
+    return("""\
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s" {
+    set root=(hd0,%(install_partition)s)
+    linux  /boot/release/%(grml_flavour)s/linux26 apm=power-off boot=live nomce vga=791 quiet module=%(grml_flavour)s %(bootoptions)s
+    initrd /boot/release/%(grml_flavour)s/initrd.gz
+}
+
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s2ram" {
+    set root=(hd0,%(install_partition)s)
+    linux  /boot/release/%(grml_flavour)s/linux26 apm=power-off boot=live nomce vga=791 quiet module=%(grml_flavour)s toram=%(grml_flavour)s %(bootoptions)s
+    initrd /boot/release/%(grml_flavour)s/initrd.gz
+
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s-debug" {
+    set root=(hd0,%(install_partition)s)
+    linux /boot/release/%(grml_flavour)s/linux26
+    initrd /boot/release/%(grml_flavour)s/initrd.gz apm=power-off boot=live nomce vga=791 quiet module=%(grml_flavour)s debug boot=live initcall_debug%(bootoptions)s
+}
+
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s-x" {
+    set root=(hd0,%(install_partition)s)
+    linux  /boot/release/%(grml_flavour)s/linux26
+    initrd /boot/release/%(grml_flavour)s/initrd.gz apm=power-off boot=live nomce vga=791 quiet module=%(grml_flavour)s startx=wm-ng %(bootoptions)s
+}
+
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s-nofb" {
+    set root=(hd0,%(install_partition)s)
+    linux  /boot/release/%(grml_flavour)s/linux26
+    initrd /boot/release/%(grml_flavour)s/initrd.gz apm=power-off boot=live nomce quiet module=%(grml_flavour)s vga=normal video=ofonly %(bootoptions)s
+}
+
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s-failsafe" {
+    set root=(hd0,%(install_partition)s)
+    linux /boot/release/%(grml_flavour)s/linux26
+    initrd /boot/release/%(grml_flavour)s/initrd.gz apm=power-off boot=live nomce quiet module=%(grml_flavour)s vga=normal lang=us boot=live noautoconfig atapicd noacpi acpi=off nomodules nofirewire noudev nousb nohotplug noapm nopcmcia maxcpus=1 noscsi noagp nodma ide=nodma noswap nofstab nosound nogpm nosyslog nodhcp nocpu nodisc nomodem xmodule=vesa noraid nolvm %(bootoptions)s
+}
+
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s-forensic" {
+    set root=(hd0,%(install_partition)s)
+    linux /boot/release/%(grml_flavour)s/linux26
+    initrd /boot/release/%(grml_flavour)s/initrd.gz apm=power-off boot=live nomce vga=791 quiet module=%(grml_flavour)s nofstab noraid nolvm noautoconfig noswap raid=noautodetect %(bootoptions)s
+}
+
+# flavour specific configuration for %(grml_flavour)s [grml2usb for %(grml_flavour)s: %(local_datestamp)s]
+menuentry "%(grml_flavour)s-serial" {
+    set root=(hd0,%(install_partition)s)
+    linux /boot/release/%(grml_flavour)s/linux26
+    initrd /boot/release/%(grml_flavour)s/initrd.gz apm=power-off boot=live nomce quiet module=%(grml_flavour)s vga=normal video=vesafb:off console=tty1 console=ttyS0,9600n8 %(bootoptions)s
+}
+
+""" % {'grml_flavour': grml_flavour, 'local_datestamp': local_datestamp, 'bootoptions': bootoptions, 'install_partition': install_partition } )
+
+
+def generate_grub1_config(grml_flavour, install_partition, bootoptions):
+    """Generate grub1 configuration for use via menu.lst
+
+    @grml_flavour: name of grml flavour the configuration should be generated for"""
+
+    local_datestamp = DATESTAMP
 
     return("""\
 # misc options:
 
     return("""\
 # misc options:
@@ -234,8 +368,7 @@ title %(grml_flavour)s  - Default boot (using 1024x768 framebuffer)
 kernel /boot/release/%(grml_flavour)s/linux26 apm=power-off lang=us vga=791 quiet boot=live nomce module=%(grml_flavour)s
 initrd /boot/release/%(grml_flavour)s/initrd.gz
 
 kernel /boot/release/%(grml_flavour)s/linux26 apm=power-off lang=us vga=791 quiet boot=live nomce module=%(grml_flavour)s
 initrd /boot/release/%(grml_flavour)s/initrd.gz
 
-# TODO: extend configuration :)
-""" % {'grml_flavour': grml_flavour} )
+""" % {'grml_flavour': grml_flavour, 'local_datestamp': local_datestamp, 'bootoptions': bootoptions} )
 
 
 def generate_isolinux_splash(grml_flavour):
 
 
 def generate_isolinux_splash(grml_flavour):
@@ -364,12 +497,30 @@ APPEND initrd=/boot/release/%(grml_flavour)s/initrd.gz apm=power-off boot=live n
 def install_grub(device):
     """Install grub on specified device.
 
 def install_grub(device):
     """Install grub on specified device.
 
+    @mntpoint: mountpoint of device where grub should install its files to
     @device: partition where grub should be installed to"""
 
     if options.dryrun:
     @device: partition where grub should be installed to"""
 
     if options.dryrun:
-        logging.info("Would execute grub-install %s now.", device)
+        logging.info("Would execute grub-install [--root-directory=mount_point] %s now.", device)
     else:
     else:
-        logging.critical("TODO: sorry - grub-install %s not implemented yet"  % device)
+        device_mountpoint = tempfile.mkdtemp()
+        register_tmpfile(device_mountpoint)
+        try:
+            mount(device, device_mountpoint, "")
+            logging.debug("grub-install --root-directory=%s %s", device_mountpoint, device)
+            proc = subprocess.Popen(["grub-install", "--root-directory=%s" % device_mountpoint, device])
+            proc.wait()
+            if proc.returncode != 0:
+                raise Exception("error executing grub-install")
+        except CriticalException, error:
+            logging.critical("Fatal: %s" % error)
+            cleanup()
+            sys.exit(1)
+
+        finally:
+            unmount(device_mountpoint, "")
+            os.rmdir(device_mountpoint)
+            unregister_tmpfile(device_mountpoint)
 
 
 def install_syslinux(device):
 
 
 def install_syslinux(device):
@@ -387,7 +538,7 @@ def install_syslinux(device):
     proc = subprocess.Popen(["syslinux", "-d", "boot/syslinux", device])
     proc.wait()
     if proc.returncode != 0:
     proc = subprocess.Popen(["syslinux", "-d", "boot/syslinux", device])
     proc.wait()
     if proc.returncode != 0:
-        raise Exception("error executing syslinux")
+        raise CriticalException("Error executing syslinux (either try --fat16 or --grub?)")
 
 
 def install_bootloader(device):
 
 
 def install_bootloader(device):
@@ -405,7 +556,12 @@ def install_bootloader(device):
     if options.grub:
         install_grub(device)
     else:
     if options.grub:
         install_grub(device)
     else:
-        install_syslinux(device)
+        try:
+            install_syslinux(device)
+        except CriticalException, error:
+            logging.critical("Fatal: %s" % error)
+            cleanup()
+            sys.exit(1)
 
 
 def install_lilo_mbr(lilo, device):
 
 
 def install_lilo_mbr(lilo, device):
@@ -758,7 +914,7 @@ def copy_bootloader_files(iso_mount, target):
         proc.wait()
 
 
         proc.wait()
 
 
-def install_iso_files(grml_flavour, iso_mount, target):
+def install_iso_files(grml_flavour, iso_mount, device, target):
     """Copy files from ISO on given target"""
 
     # TODO
     """Copy files from ISO on given target"""
 
     # TODO
@@ -782,7 +938,7 @@ def install_iso_files(grml_flavour, iso_mount, target):
         copy_bootloader_files(iso_mount, target)
 
         if not options.dryrun:
         copy_bootloader_files(iso_mount, target)
 
         if not options.dryrun:
-            handle_bootloader_config(grml_flavour, target) # FIXME
+            handle_bootloader_config(grml_flavour, device, target) # FIXME
 
     # make sure we sync filesystems before returning
     proc = subprocess.Popen(["sync"])
 
     # make sure we sync filesystems before returning
     proc = subprocess.Popen(["sync"])
@@ -823,7 +979,7 @@ def identify_grml_flavour(mountpath):
     return grml_flavour
 
 
     return grml_flavour
 
 
-def handle_bootloader_config(grml_flavour, target):
+def handle_bootloader_config(grml_flavour, device, target):
     """TODO"""
 
     logging.debug("Generating grub configuration")
     """TODO"""
 
     logging.debug("Generating grub configuration")
@@ -833,10 +989,51 @@ def handle_bootloader_config(grml_flavour, target):
     grub_target = target + '/boot/grub/'
     # should be present via copy_bootloader_files(), but make sure it exists:
     execute(mkdir, grub_target)
     grub_target = target + '/boot/grub/'
     # should be present via copy_bootloader_files(), but make sure it exists:
     execute(mkdir, grub_target)
+    # we have to adjust root() inside grub configuration
+    if device[-1:].isdigit():
+        install_partition = device[-1:]
+
+    # grub1 config
+    logging.debug("Creating grub1 configuration file")
     grub_config_file = open(grub_target + 'menu.lst', 'w')
     grub_config_file = open(grub_target + 'menu.lst', 'w')
-    grub_config_file.write(generate_grub_config(grml_flavour))
+    grub_config_file.write(generate_grub1_config(grml_flavour, install_partition, options.bootoptions))
     grub_config_file.close()
 
     grub_config_file.close()
 
+    # TODO => generate_main_grub1_config() && generate_flavour_specific_grub1_config()
+
+    # grub2 config
+    grub2_cfg = grub_target + 'grub.cfg'
+    logging.debug("Creating grub2 configuration file")
+
+    # install main configuration only *once*, no matter how many ISOs we have:
+    if os.path.isfile(grub2_cfg):
+        string = open(grub2_cfg).readline()
+        main_identifier = re.compile(".*main config generated at: %s.*" % re.escape(str(DATESTAMP)))
+        if not re.match(main_identifier, string):
+            grub2_config_file = open(grub2_cfg, 'w')
+            logging.info("Notice: grml flavour %s is being installed as the default booting system." % grml_flavour)
+            grub2_config_file.write(generate_main_grub2_config(grml_flavour, install_partition, options.bootoptions))
+            grub2_config_file.close()
+    else:
+        grub2_config_file = open(grub2_cfg, 'w')
+        grub2_config_file.write(generate_main_grub2_config(grml_flavour, install_partition, options.bootoptions))
+        grub2_config_file.close()
+
+    grub_flavour_config = True
+    if os.path.isfile(grub2_cfg):
+        string = open(grub2_cfg).readlines()
+        logging.info("Notice: you can boot flavour %s using '%s' on the commandline." % (grml_flavour, grml_flavour))
+        flavour = re.compile("grml2usb for %s: %s" % (re.escape(grml_flavour), re.escape(str(DATESTAMP))))
+        for line in string:
+            if flavour.match(line):
+                grub_flavour_config = False
+
+    if grub_flavour_config:
+        grub2_config_file = open(grub2_cfg, 'a')
+        grub2_config_file.write(generate_flavour_specific_grub2_config(grml_flavour, install_partition, options.bootoptions))
+        grub2_config_file.close( )
+
+
     logging.info("Generating syslinux configuration")
     syslinux_target = target + '/boot/syslinux/'
     # should be present via  copy_bootloader_files(), but make sure it exits:
     logging.info("Generating syslinux configuration")
     syslinux_target = target + '/boot/syslinux/'
     # should be present via  copy_bootloader_files(), but make sure it exits:
@@ -859,16 +1056,16 @@ def handle_bootloader_config(grml_flavour, target):
 
     # install flavour specific configuration only *once* as well
     # kind of ugly - I'm pretty sure this could be smoother...
 
     # install flavour specific configuration only *once* as well
     # kind of ugly - I'm pretty sure this could be smoother...
-    flavour_config = True
+    syslinux_flavour_config = True
     if os.path.isfile(syslinux_cfg):
         string = open(syslinux_cfg).readlines()
         logging.info("Notice: you can boot flavour %s using '%s' on the commandline." % (grml_flavour, grml_flavour))
         flavour = re.compile("grml2usb for %s: %s" % (re.escape(grml_flavour), re.escape(str(DATESTAMP))))
         for line in string:
             if flavour.match(line):
     if os.path.isfile(syslinux_cfg):
         string = open(syslinux_cfg).readlines()
         logging.info("Notice: you can boot flavour %s using '%s' on the commandline." % (grml_flavour, grml_flavour))
         flavour = re.compile("grml2usb for %s: %s" % (re.escape(grml_flavour), re.escape(str(DATESTAMP))))
         for line in string:
             if flavour.match(line):
-                flavour_config = False
+                syslinux_flavour_config = False
 
 
-    if flavour_config:
+    if syslinux_flavour_config:
         syslinux_config_file = open(syslinux_cfg, 'a')
         syslinux_config_file.write(generate_flavour_specific_syslinux_config(grml_flavour, options.bootoptions))
         syslinux_config_file.close( )
         syslinux_config_file = open(syslinux_cfg, 'a')
         syslinux_config_file.write(generate_flavour_specific_syslinux_config(grml_flavour, options.bootoptions))
         syslinux_config_file.close( )
@@ -920,11 +1117,12 @@ def handle_iso(iso, device):
         except CriticalException, error:
             logging.critical("Fatal: %s" % error)
             cleanup()
         except CriticalException, error:
             logging.critical("Fatal: %s" % error)
             cleanup()
+            sys.exit(1)
 
     try:
         grml_flavour = identify_grml_flavour(iso_mountpoint)
         logging.info("Identified grml flavour \"%s\"." % grml_flavour)
 
     try:
         grml_flavour = identify_grml_flavour(iso_mountpoint)
         logging.info("Identified grml flavour \"%s\"." % grml_flavour)
-        install_iso_files(grml_flavour, iso_mountpoint, device_mountpoint)
+        install_iso_files(grml_flavour, iso_mountpoint, device, device_mountpoint)
     except TypeError:
         logging.critical("Fatal: a critical error happend during execution (not a grml ISO?), giving up")
         sys.exit(1)
     except TypeError:
         logging.critical("Fatal: a critical error happend during execution (not a grml ISO?), giving up")
         sys.exit(1)
index 1e7ad6d..346b7e9 100644 (file)
@@ -65,7 +65,7 @@ Force any (possible dangerous) actions requiring manual interaction (like --fat1
 
   *--grub*::
 
 
   *--grub*::
 
-Install grub bootloader instead of syslinux. [Notice: not implemented yet.]
+Install grub bootloader instead of syslinux.
 
   *--help*::
 
 
   *--help*::