Commits

Moises Henriquez committed 1eea060

bootloader.py fix LiLO not detecting other OSs and add tests

  • Participants
  • Parent commits 7d45c65

Comments (0)

Files changed (1)

File vinstall/backend/bootloader.py

 from StringIO import StringIO
 from vinstall.backend import utils, media
 from vinstall.backend import sp
+from vinstall.core import log
 import unittest
 
 
 GRUB2 = object()
 
 
+class LiloDotConfEntry(object):
+    """Dummy wrapper for reading a lilo.conf.  Has absolutely no use at all.
+    The only reason it exists is to do some unittesting"""
+    root = None
+    label = None
+
+    @classmethod
+    def all(cls, fpath):
+	entries = []
+	with open(fpath) as data:
+	    for line in data:
+		line = line.strip()
+		if line.startswith("root") or \
+		  line.startswith("other"):
+		    entry = cls()
+		    entry.root = line.split("=")[-1].strip()
+		    yield entry
+
 class Lilo(object):
     """LiLo bootloader
 
         self.set_timeout(timeout)
         self.buffer = []
         self.lilo_root = utils.get_mounted("/")
-        tamu = "/boot/tamu"
-        if not os.path.exists(tamu):
-            os.mkdir(tamu)
+        self.tamu = "/boot/tamu"
+        if not os.path.exists(self.tamu):
+            os.mkdir(self.tamu)
 
     def add_os(self, system):
+	"""Add the information about this operating system to the
+	class"""
         if system.type == "linux":
             self.add_unix_os(system)
-        elif "microsoft" in system.type:
+        elif "chain" in system.type:
             self.add_ms_os(system)
         else:
             #XXX
             pass
 
+    def copy_unix_bootdata(self, system):
+	"""Copy the kernel and initrd to our partition
+	if necessary"""
+	
+	if system.root != self.lilo_root:
+	    # Mount the os root partition if needed
+	    umount = False
+	    partition = media.Partition(system.root)
+	    if not partition.is_mounted():
+	        mountpoint = system.root.replace("/dev/","/mnt/")
+	        if not os.path.exists(mountpoint):
+		    of.makedir(mountpoint)
+		partition.mount(mountpoint)
+		umount = True
+
+            targetdir = os.path.split(system.tamu_kernel_path)
+	    # Copy the kernel to the local tamu path
+	    kernel_from = os.path.join(partition.mountpoint, system.kernel)
+	    shutil.copy2(kernel_from, system.tamu_kenel_path)
+	    # Copy the initrd to the local tamu path
+	    if system.initrd:
+	        initrd_from = os.path.join(partition.mountpoint, system.initrd)
+	    	shutil.copy2(initrd_from, system.tamu_initrd_path)
+
+        # un-mount the partition if necessary
+	if umount:
+	    partition.umount()
+
     def add_unix_os(self, system):
         """Add an operating system to the boot menu
 
         """
         if system in self.operating_systems:
             raise RuntimeError("OS already added")
-        if system.root != self.lilo_root:
-
-            # mount os root partition if needed
-            umount = False
-            partition = media.Partition(system.root)
-            if not partition.is_mounted():
-                mountpoint = system.root.replace("/dev/", "/mnt/")
-                if not os.path.exists(mountpoint):
-                    os.mkdir(mountpoint)
-                partition.mount(mountpoint)
-                umount = True
-
-            # copy kernel
-            kernel_from = os.path.join(partition.mountpoint, "boot",
-                    system.kernel_name)
-            kernel_dest = os.path.join("/boot/tamu", system.kernel)
-            shutil.copy2(kernel_from, kernel_dest)
-
-            # copy initrd if needed
-            if system.initrd:
-                initrd_from = os.path.join(partition.mountpoint,
-                        system.initrd)
-                initrd_dest = os.path.join("/boot/tamu",
-                        system.initrd)
-                if os.path.exists(initrd_from) and \
-                        not os.path.exists(initrd_dest):
-                    shutil.copy2(initrd_from, initrd_dest)
-
-            # umount if needed
-            if umount:
-                partition.umount()
-
-            # write config lines
-            tab = " " * 4
-            self.buffer.append("# -- %s on %s --" % (system.label,
-                system.root))
-            self.buffer.append("image = %s" % system.kernel)
-            self.buffer.append("%s label = %s" % (tab, system.label))
-            if system.initrd:
-                self.buffer.append("%s initrd = %s" % (tab,
-                    system.initrd))
-#            if system.appendline:
-#                if "splash" not in system.appendline:
-#                    self.buffer.append('%s append = "%s splash quiet"' %
-#                            (tab, system.appendline))
-#                else:
-#                    self.buffer.append('%s append = "%s"' % (tab,
-#                            system.appendline))
-	    if system.appendline:
-	        self.buffer.append('%s append = "%s"'% (tab, system.appendline))
-            self.buffer.append("%s read-only" % tab)
-            self.buffer.append("# --")
-
-            self.operating_systems.append(system)
+
+        # write config lines
+        tab = " " * 4
+        self.buffer.append("# -- %s on %s --" % (system.label,
+            system.root))
+	
+	if system.root != self.lilo_root:
+	    self.buffer.append("image = %s"% system.tamu_kernel_path)
+	    self.buffer.append("%s label = %s"% (tab, system.tamu_lilo_label))
+	    if system.initrd:
+	        self.buffer.append("%s initrd = %s"% (tab, system.tamu_initrd_path))
+	else:
+	    self.buffer.append("image = %s"% system.kernel)
+	    self.buffer.append("%s label = %s"% (tab, system.label))
+	    if system.initrd:
+		self.buffer.append("%s initrd = %s"% ( tab, system.initrd))
+	self.buffer.append("%s root = %s" % (tab, system.root))
+        if system.appendline:
+	    self.buffer.append('%s append = "%s"'% (tab, system.appendline))
+        self.buffer.append("%s read-only" % tab)
+        self.buffer.append("# --")
+
+        self.operating_systems.append(system)
 
     def add_ms_os(self, system):
         """Add MS os to boot menu
 
         """
-        self.buffer.append("# -- %s on %s --" % (system.label, system.root))
+        self.buffer.append("# -- %s on %s --" % (system.long_desc, system.root))
         self.buffer.append("other = %s" % system.root)
         self.buffer.append("label = %s" % system.label)
         self.buffer.append("table = %s" % system.root[:-1])
+	self.operating_systems.append(system)
         
     def set_default_os(self, system):
         """Set the default OS
     """
     type = None         # str indicating OS type
     kernel = None       # Kernel image
+    initrd = None	# Initial Ram Disk
     root = None         # path to OS root
     appendline = None   # append line for lilo.conf
 
     def kernel_name(self):
         return os.path.split(self.kernel)[-1]
 
+    @property
+    def initrd_name(self):
+	if self.initrd:
+	    return os.path.split(self.initrd)[-1]
+	return None
+
+    @property
+    def os_root(self):
+	return self.root
+
+    @property
+    def _short_root(self):
+	return os.path.split(self.root)[-1]
+
+    @property 
+    def tamu_kernel_path(self):
+	return os.path.join("/boot/tamu/", "%s-%s"% (self.kernel_name, self._short_root))
+
+    @property
+    def tamu_initrd_path(self):
+	rootpart = os.path.split(self.os_root)[-1]
+	return os.path.join("/boot/tamu/","%s-%s"% ( self.initrd_name, self._short_root))
+
+    @property
+    def tamu_lilo_label(self):
+	"""Return a lilo-friendly label for an OS on a foreign partition
+	"""
+	return "%s-%s"% (self.label, self._short_root)
+
     @classmethod
-    def all(cls, include_running_os=False):
+    def all(cls, include_running_os=False, op_data = None, bp_data = None):
         """Return one OperatingSystem instance for each OS
         installed
 
         """
-        os_prober = sp.check_output(["os-prober", "&>/dev/null"])
-        found_os = os_prober.split("\n")
-
-        if include_running_os and os.path.exists('/boot/vmlinuz'):
-            running_os = cls()
-            running_os.kernel = '/boot/vmlinuz'
-            running_os.label = 'VectorLinux'
-            running_os.type = "linux"
-            if os.path.exists('/boot/initrd'):
-                running_os.initrd = '/boot/initrd'
-            running_os.root = utils.get_mounted("/")
-            yield running_os
+	if not op_data:
+            op_data = sp.check_output(["os-prober", "&>/dev/null"])
+        found_os = op_data.split("\n")
+#        if include_running_os and os.path.exists('/boot/vmlinuz'):
+#            running_os = cls()
+#            running_os.kernel = '/boot/vmlinuz'
+#            running_os.label = 'VectorLinux'
+#            running_os.type = "linux"
+#            if os.path.exists('/boot/initrd'):
+#                running_os.initrd = '/boot/initrd'
+#            running_os.root = utils.get_mounted("/")
+#            yield running_os
 
         for i in found_os:
             if ":" not in i:
             operating_system.label = short_desc
             if os_type.lower() == "linux":
                 operating_system.type = "linux"
-                bootinfo = get_linux_boot_info(root)
+                bootinfo = get_linux_boot_info(root, bp_data)
                 if bootinfo is None:
                     continue
                 operating_system.root = bootinfo["root"] or root
                 operating_system.initrd = bootinfo["initrd"]
                 operating_system.appendline = bootinfo["append"]
             elif "microsoft" in os_type.lower() or \
-                    "windows" in os_type.lower():
+                    "windows" in os_type.lower() or \
+		    "chain" in os_type.lower():
+		        operating_system.long_desc = long_desc
+			operating_system.short_desc = short_desc
                         operating_system.root = root
-                        operating_system.label = root.split("/")[-1]
-                        operating_system.type = "windows"
-            #XXX what about bsd, osx, etc
+			if "microsoft" in short_desc.lower() or \
+			   "windows" in short_desc.lower():
+			    operating_system.label = "Windows-%s"% os.path.split(root)[-1]
+			else:
+			    operating_system.label = "Other_OS-%s"% os.path.split(root)[-1] 
+                        operating_system.type = "chain"
+            #XXX what about bsd, osx, etc.  Will 'chain' cover them?
             else:
                 continue
             yield operating_system
             return None
 
 
-def get_linux_boot_info(root_partition):
+def get_linux_boot_info(root_partition, data = None):
     """Use linux-boot-prober to find out how to boot this OS
 
     /dev/sdb1:/dev/sdb1::/boot/vmlinuz26:/boot/kernel26.img:root=/dev/sdb1
 
     """
-    proc = sp.check_output(['linux-boot-prober', root_partition])
-    hits = proc.split("\n")
+    if not data:
+        data = sp.check_output(['linux-boot-prober', root_partition])
+    else:
+	data = "\n".join(
+	    [ x for x in data.split("\n") if root_partition in x])
+    hits = data.split("\n")
     if not hits:
         return None
     line = hits[0]
         f = os.fdopen(fd)
         f.seek(140000)
         os.write(fd, "0")
+	self.op_data = "\n".join(
+		("/dev/sda1:Windows 7 (loader):Windows:chain",
+		"/dev/sda2:VLocity 7.1 B2:Linux:linux",
+		"/dev/sdb1:VectorLinux 7.1 B1.1:Linux:linux",
+		"/dev/sdb2:Slackware Linux 14.1:Linux:linux"))
+	self.bp_data = "\n".join(
+	    ("/dev/sda2:/dev/sda2::/boot/vmlinuz:/boot/initrd:root=/dev/sda2",
+		"/dev/sdb1:/dev/sdb1::/boot/vmlinuz:/boot/initrd:root=/dev/sdb1",
+		"/dev/sdb2:/dev/sdb2::/boot/vmlinuz:/boot/initrd:root=/dev/sdb2"))
 
     def tearDown(self):
         os.unlink(self.path)
 class LiloTestCase(FakeDeviceTestCase):
 
     def test_lilo(self):
-        if not os.path.exists('/bin/lilo'):
+        if not os.path.exists('/sbin/lilo'):
             return #XXX 
         lilo = Lilo(self.path)
-        for ops in OperatingSystem.all(include_running_os=True):
+        for ops in OperatingSystem.all(include_running_os=True,
+	    op_data = self.op_data, bp_data = self.bp_data):
             lilo.add_os(ops)
         lilo.write_config(config_path="/tmp/lilo-test")
-        lilo.test_install("/tmp/lilo-test", self.path)
-        mbr = MasterBootRecord(self.path)
-        self.assertEqual(mbr.bootloader(), LILO)
+	# Test to make sure the entries got written to the config file
+	found = [ entry.root for entry in LiloDotConfEntry.all('/tmp/lilo-test')]
+	written = [ x.split(':')[0] for x in self.op_data.split("\n")]
+	for i in written:
+	    self.assertIn(i, found)
+#        lilo.test_install("/tmp/lilo-test", self.path)
+#        mbr = MasterBootRecord(self.path)
+#        self.assertEqual(mbr.bootloader(), LILO)
 
 
 class Grub2TestCase(FakeDeviceTestCase):
 
     def test_grub2(self):
         return #XXX
-        grub2 = Grub2(self.path)
+        grub2 = Grub2(self.path, data = self.testdata)
         grub2.write_config(config_path="/tmp/grub2-test")
         grub2.test_install("/tmp/grub2-test", self.path)
         mbr = MasterBootRecord(self.path)