#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention Grub menu.lst generator
#
# Copyright 2012-2014 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
# <http://www.gnu.org/licenses/>.

import os
import sys
import shutil
import re

import univention.debug as udbg
import univention.config_registry as ucr
from distutils.version import LooseVersion

class kernel:
	def __init__(self, kversion, uversion, arch, origversion):
		self.kversion = kversion
		self.uversion = uversion
		self.arch = arch
		self.origversion = origversion
	def __repr__(self):
		return repr((self.kversion, self.uversion, self.arch))

configRegistry=ucr.ConfigRegistry()
configRegistry.load()

if 'grub/generate-menu-lst' not in configRegistry or configRegistry.is_false('grub/generate-menu-lst', False):
	sys.exit(0)

if os.path.exists("/boot/grub/menu.lst"):
    f = open("/boot/grub/menu.lst")
    generated_by_ucs = False

    for i in f.readlines():
        if i.find("auto-generated through univention-grub-generate-menu-lst") != -1:
            generated_by_ucs = True

    if not generated_by_ucs:
        print "menu.lst already exists. This typically happens if you have updated from UCS 2.4"
        print "and haven't converted from chain loading"
        sys.exit(0)

try:
	grub2 = open("/boot/grub/grub.cfg", "r")
except OSError, e:
       print >>sys.stderr, "Failed to open grub.cfg: %s" % (e,)
       sys.exit(1)


lst = []
lst.append("# This Grub configuration is auto-generated through univention-grub-generate-menu-lst.")
lst.append("# It is used when booting UCS 3.0 as a Xen DomU with an older version of Pygrub")
lst.append(" ")
lst.append("default 0")
lst.append("timeout 5 ")
lst.append(" ")

RE_MENUENTRY = re.compile(r"^\s*menuentry '([^']*)' .*")
RE_ROOT = re.compile(r"^\s+set\s+root='\(?(hd[0-9]+|/dev/\w+d[a-z]),[a-z]+([0-9]+)\)?'")
RE_LINUX = re.compile(r"^\s+linux\s+(.+)")
RE_INITRD = re.compile(r"^\s+initrd\s+(.+)")
RE_CLOSE = re.compile(r"^}")

name = kernel = initrd = None

for line in grub2:
	m = RE_MENUENTRY.match(line)
	if m:
		(name,) = m.groups()
		continue

	if 'grub/grub1root' in configRegistry:
		root = configRegistry['grub/grub1root']
	else:
		m = RE_ROOT.match(line)
		if m:
			device, part = m.groups()
			if device.startswith('hd'):
				root = "(%s,%d)" % (device, int(part) - 1)
			elif device.startswith('/dev/'):
				root = "(hd0,%d)" % (int(part) - 1)
			else:
				print >>sys.stderr, "Unhandled root=%s" % (line,)

	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:
			lst.append("title           " + name)
			lst.append("root            " + root)
			lst.append("kernel          " + kernel)
			if initrd:
				lst.append("initrd          " + initrd)
			lst.append(" ")
		name = root = kernel = initrd = None
		continue

if os.path.exists("/boot/grub/menu.lst"):
   shutil.copyfile("/boot/grub/menu.lst", "/boot/grub/menu.lst.bak")

print "Generating legacy menu.lst from current kernels"
generated_list = open("/boot/grub/menu.lst", "w")
for i in lst:
    generated_list.write(i + "\n")
