diff options
author | BlackNoxis <steven.darklight@gmail.com> | 2014-02-15 23:24:26 +0200 |
---|---|---|
committer | BlackNoxis <steven.darklight@gmail.com> | 2014-02-15 23:24:26 +0200 |
commit | 7224c1253228e5c29c78cb3f0f26ce34770f2356 (patch) | |
tree | 1684924656132935256e034f35f92abee6623265 /sys-boot/grub-handler/files |
Added ebuilds for kogaion desktop
Diffstat (limited to 'sys-boot/grub-handler/files')
-rwxr-xr-x | sys-boot/grub-handler/files/grub-handler | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/sys-boot/grub-handler/files/grub-handler b/sys-boot/grub-handler/files/grub-handler new file mode 100755 index 00000000..4034ba1d --- /dev/null +++ b/sys-boot/grub-handler/files/grub-handler @@ -0,0 +1,318 @@ +#!/usr/bin/python2 +# -*- coding: utf-8 -*- +""" + Kernel grub.conf configuration script + + Copyright (C) 2009 Fabio Erculiani + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + +""" +import os +import sys +import subprocess +import shutil +BOOT_MOUNT = False +NO_SYS_ROOT_BOOT_DIR = "/boot" +if os.path.ismount(NO_SYS_ROOT_BOOT_DIR): + BOOT_MOUNT = True +SYS_ROOT = os.getenv("ROOT","") +GRUB_CONF = SYS_ROOT+"/boot/grub/grub.conf" +FSTAB_CONF = SYS_ROOT+"/etc/fstab" +DISTRO_NAME = "Rogentos Linux" + +def getstatusoutput(cmd): + """Return (status, output) of executing cmd in a shell.""" + pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') + text = pipe.read() + sts = pipe.close() + if sts is None: sts = 0 + if text[-1:] == '\n': text = text[:-1] + return sts, text + +def get_kernel_grub_line(kernel): + return "title=%s (%s)\n" % (DISTRO_NAME, os.path.basename(kernel),) + +def configure_boot_grub(kernel, initramfs): + + grub_dir = os.path.dirname(GRUB_CONF) + if not os.path.isdir(grub_dir): + os.makedirs(grub_dir) + + if os.access(GRUB_CONF, os.R_OK | os.F_OK): + + # open in append + grub = open(GRUB_CONF,"aw") + shutil.copy2(GRUB_CONF, GRUB_CONF+".add") + # get boot dev + boot_dev = get_grub_boot_dev() + # test if entry has been already added + grubtest = open(GRUB_CONF,"r") + content = grubtest.readlines() + content = [unicode(x,'raw_unicode_escape') for x in content] + for line in content: + + if line.find(get_kernel_grub_line(kernel)) != -1: + grubtest.close() + print "** Kernel already in configuration => ", line.strip() + return + + # also check if we have the same kernel listed + if (line.find("kernel") != 1) and \ + (line.find(os.path.basename(kernel)) != -1) and not \ + line.strip().startswith("#") \ + and (line.find("safe mode") == -1): + + grubtest.close() + print "** Kernel already in configuration (2) => ", line.strip() + return + else: + + # create + boot_dev = get_grub_boot_dev() + grub = open(GRUB_CONF,"w") + # write header - guess (hd0,0)... since it is weird + # having a running system without a bootloader, at least, grub. + grub.write("default=0\ntimeout=10\n") + + cmdline = '' + if os.access("/proc/cmdline", os.R_OK): + cmdline_f = open("/proc/cmdline","r") + cmdline = " "+cmdline_f.readline().strip() + cmdline_f.close() + + grub.write(get_kernel_grub_line(kernel)) + grub.write("\troot "+boot_dev+"\n") + grub.write("\tkernel "+kernel+cmdline+"\n") + if initramfs: + grub.write("\tinitrd "+initramfs+"\n") + grub.write("\tsavedefault\n") + grub.write("\n") + grub.flush() + grub.close() + +def remove_boot_grub(kernel, initramfs): + + grub_dir = os.path.dirname(GRUB_CONF) + if not os.path.isdir(grub_dir): + os.makedirs(grub_dir) + + if os.path.isdir(grub_dir) and os.access(GRUB_CONF, os.R_OK | os.F_OK): + + shutil.copy2(GRUB_CONF, GRUB_CONF+".remove") + grub_f = open(GRUB_CONF,"r") + grub_conf = grub_f.readlines() + grub_f.close() + + content = [unicode(x,'raw_unicode_escape') for x in grub_conf] + if not isinstance(kernel, unicode): + kernel = unicode(kernel,'raw_unicode_escape') + if not isinstance(initramfs, unicode): + initramfs = unicode(initramfs,'raw_unicode_escape') + + new_conf = [] + skip = False + for line in content: + + kernel_grub_line = get_kernel_grub_line(kernel) + if (line.find(kernel_grub_line) != -1): + skip = True + continue + + if line.strip().startswith("title"): + skip = False + + if not skip or line.strip().startswith("#"): + new_conf.append(line) + + grub_tmp_f = open(GRUB_CONF+".tmp","w") + for line in new_conf: + try: + grub_tmp_f.write(line) + except UnicodeEncodeError: + grub_tmp_f.write(line.encode('utf-8')) + grub_tmp_f.flush() + grub_tmp_f.close() + os.rename(GRUB_CONF+".tmp", GRUB_CONF) + +def boot_device_translation(boot_dev): + + # actually disabled due to buggy grub.conf entry + if os.access(GRUB_CONF, os.R_OK | os.F_OK) and 0: + + f_grub = open(GRUB_CONF, "r") + stored_boot_dev = [x.strip() for x in f_grub.readlines() if \ + x.strip().startswith("#boot=")] + f_grub.close() + if stored_boot_dev: + stored_boot_dev = stored_boot_dev[0] + boot_dev = "/dev/" + stored_boot_dev[len("#boot="):] + + if boot_dev.startswith("/dev/md"): + + boot_dev = os.path.realpath(boot_dev) + md_dev = os.path.basename(boot_dev) + + if os.access("/proc/mdstat", os.R_OK | os.F_OK): + + f_mdstat = open("/proc/mdstat","r") + stored_boot_dev = [x.split() for x in f_mdstat.readlines() if \ + x.startswith(md_dev)] + f_mdstat.close() + + if stored_boot_dev: + stored_boot_dev = stored_boot_dev[0] + for elem in stored_boot_dev: + if elem.endswith("[0]"): + boot_dev = "/dev/" + elem[:-len("[0]")] + break + + return boot_dev + +def resolve_device(device): + if device.startswith("/dev/"): + return device + if device.startswith("UUID=") or device.startswith("LABEL="): + print "resolving UUID/LABEL to device", device + rc, outstring = getstatusoutput("blkid -lt %s" % (device,)) + if rc != 0: + print "cannot resolve UUID/LABEL for", device + return None # argh! + device = outstring.split(":")[0] + print "UUID/LABEL resolved to", device + return device + +def get_grub_boot_dev(): + + grub_avail = subprocess.call("which grub &> /dev/null", shell = True) + if grub_avail != 0: + print "** Cannot find grub. Cannot properly configure kernel" + return "(hd0,0)" + + # load currently mounted partitions + if not os.access(FSTAB_CONF, os.R_OK | os.F_OK): + print "** Cannot find %s. Cannot properly configure kernel" % ( + FSTAB_CONF,) + return "(hd0,0)" + + f_fstab = open(FSTAB_CONF, "r") + mount_data = [x.split() for x in f_fstab.readlines()] + f_fstab.close() + # filter out bogus devices + mount_data = [x for x in mount_data if x] + mount_data = [x for x in mount_data if x[0].startswith("/") or \ + x[0].startswith("UUID=") or x[0].startswith('LABEL=')] + + mount_hash = {} + for item in mount_data: + solved_dev = resolve_device(item[0]) + if not solved_dev: + continue + mount_hash[item[1]] = solved_dev + boot_dev = mount_hash.get(NO_SYS_ROOT_BOOT_DIR, mount_hash.get("/")) + if boot_dev == None: + print "** Cannot determine boot device. Cannot properly configure" \ + " kernel" + return "(hd0,0)" + + # translate boot device, if needed + boot_dev = boot_device_translation(boot_dev) + + # load grub map file + map_file = "grub.map" + subprocess.call('echo "quit" | grub --no-floppy --no-config-file ' \ + '--no-curses --batch --device-map=grub.map &> /dev/null', shell = True) + if not os.access(map_file, os.R_OK | os.F_OK): + print "** Cannot find grub. Cannot properly configure kernel" + return "(hd0,0)" + + f_map = open(map_file) + map_data = [x.split() for x in f_map.readlines()] + f_map.close() + os.remove(map_file) + map_data = dict(((y, x) for x, y in map_data)) + + map_data_devs = map_data.keys() + grub_dev = None + linux_dev = None + for dev in map_data_devs: + if boot_dev.startswith(dev): + grub_dev = map_data.get(dev) + linux_dev = dev + break + + if grub_dev == None: + print "** Cannot match grub device. Cannot properly configure kernel" + return "(hd0,0)" + + device_number = boot_dev.replace(linux_dev,'') + try: + device_number = int(device_number) + except ValueError: + print "** Cannot get device number for '%s' => '%s' | '%s'. Cannot properly configure kernel" % ( + device_number, boot_dev, linux_dev,) + return "(hd0,0)" + + device_number -= 1 + grub_boot_dev = grub_dev.replace(')',',%s)' % (device_number,)) + return grub_boot_dev + +def print_help(): + print "%s %s %s %s" % (sys.argv[0], "[add/remove]", + "<kernel>", "<initramfs or 'none'>",) + +def add_kernel(kernel, initramfs): + + boot_len = len(NO_SYS_ROOT_BOOT_DIR) + if BOOT_MOUNT: + kernel = kernel[boot_len:] + if initramfs: + initramfs = initramfs[boot_len:] + + # configure GRUB + print "** Configuring GRUB bootloader. Adding the new kernel ..." + configure_boot_grub(kernel, initramfs) + +def remove_kernel(kernel, initramfs): + + boot_len = len(NO_SYS_ROOT_BOOT_DIR) + if BOOT_MOUNT: + kernel = kernel[boot_len:] + if initramfs: + initramfs = initramfs[boot_len:] + + # configure GRUB + print "** Configuring GRUB bootloader. Removing the selected kernel ..." + remove_boot_grub(kernel, initramfs) + + + +if __name__ == "__main__": + + args = sys.argv[1:] + if len(args) < 3: + print_help() + raise SystemExit(1) + + cmd = args[0] + if cmd not in ("add", "remove",): + print_help() + raise SystemExit(1) + + kernel = args[1] + initramfs = args[2] + + if initramfs == "none": + initramfs = '' + + if cmd == "add": + print "** Adding kernel '%s' and initramfs '%s'" % (kernel, initramfs,) + add_kernel(kernel, initramfs) + elif cmd == "remove": + print "** Removing kernel '%s' and initramfs '%s'" % (kernel, + initramfs,) + remove_kernel(kernel, initramfs) + raise SystemExit(0) |