#!/usr/bin/python2.6 # -*- coding: utf-8 -*- # # Univention Grub menu.lst generator # # Copyright 2012 Univention GmbH # # http://www.univention.de/ # # All rights reserved. # # The source code of this program is made available # under the terms of the GNU Affero General Public License version 3 # (GNU AGPL V3) as published by the Free Software Foundation. # # Binary versions of this program provided by Univention to you as # well as other copyrighted, protected or trademarked materials like # Logos, graphics, fonts, specific documentations and configurations, # cryptographic keys etc. are subject to a license agreement between # you and Univention and not subject to the GNU AGPL V3. # # In the case you use this program under the terms of the GNU AGPL V3, # the program is provided in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License with the Debian GNU/Linux or Univention distribution in file # /usr/share/common-licenses/AGPL-3; if not, see # . import os import sys import re import optparse from shutil import copyfile import univention.config_registry as ucr configRegistry = ucr.ConfigRegistry() configRegistry.load() parser = optparse.OptionParser() parser.add_option("-f", "--force", action="store_true", dest="force", default=False, help="Force writing menu.lst") parser.add_option("-n", "--dry-run", action="store_true", dest="dry", default=False, help="Print to stdout instead of menu.lst") parser.add_option("-c", "--commandline", "--append", action="store", dest="args", default='nosplash', help="Additional kernel command line arguments") parser.add_option("-r", "--root", action="store", dest="root", default=None, help="Overwrite grub root device") options, args = parser.parse_args() if configRegistry.is_false('grub/generate-menu-lst', False): print >>sys.stderr, "Disables via grub/generate-menu-lst" if options.force: print >>sys.stderr, "Forced!" else: sys.exit(0) os.chdir("/boot") if os.path.exists("grub/menu.lst"): f = open("grub/menu.lst", "r") for line in f: if "auto-generated through univention-grub-generate-menu-lst" in line: break else: print >>sys.stderr, "menu.lst already exists. This typically happens if you have updated from UCS 2.4" print >>sys.stderr, "and haven't converted from chain loading" if options.force: print >>sys.stderr, "Forced!" else: sys.exit(0) try: grub2 = open("grub/grub.cfg", "r") except OSError, e: print >>sys.stderr, "Failed to open grub.cfg: %s" % (e,) sys.exit(1) print >>sys.stderr, "Generating legacy menu.lst from grub.cfg" if os.path.exists("grub/menu.lst"): if options.dry: print >>sys.stderr, "Skip moving!" else: copyfile("grub/menu.lst", "grub/menu.lst.bak") if options.dry: out = sys.stdout else: out = open("grub/menu.lst", "w") print >>out, "# This Grub configuration is auto-generated through univention-grub-generate-menu-lst." print >>out, "# It is used when booting UCS 3.0 as a Xen DomU with an older version of PyGrub." print >>out, "" print >>out, "default 0" print >>out, "timeout %s" % configRegistry.get("grub/timeout", "5") print >>out, "" name = kernel = initrd = None root = options.root kernels = [] RE_MENUENTRY = re.compile(r"^menuentry '([^']*)' .*") RE_ROOT = re.compile(r"^\s+set\s+root='\((hd[0-9]+|/dev/\w+d[a-z]),msdos([0-9]+)\)'") RE_LINUX = re.compile(r"^\s+linux\s+(.+)") RE_INITRD = re.compile(r"^\s+initrd\s+(.+)") RE_CLOSE = re.compile(r"^}") for line in grub2: m = RE_MENUENTRY.match(line) if m: (name,) = m.groups() continue m = RE_ROOT.match(line) if m and not options.root: device, part = m.groups() if device.startswith('hd'): root = "(%s,%d)" % (device, int(part) - 1) elif device.startswith('/dev/'): root = "(hd%d,%d)" % (ord(device[-1]) - ord('a'), int(part) - 1) else: print >>sys.stderr, "Unhandled root=%s" % (line,) continue m = RE_LINUX.match(line) if m: (kernel,) = m.groups() continue m = RE_INITRD.match(line) if m: (initrd,) = m.groups() continue m = RE_CLOSE.match(line) if m: if name and root and kernel: print >>out, "title %s" % (name,) print >>out, "root %s" % (root,) print >>out, "kernel %s %s" % (kernel, options.args) if initrd: print >>out, "initrd %s" % (initrd,) print >>out, "" name = root = kernel = initrd = None root = options.root continue grub2.close() out.close()