vinstall / vinstall / controller /

#-*- coding: utf-8 -*-

"""Bootloader options for the Vector installer


import os, shutil
from vinstall.backend import bootloader, utils, sp
from import Disk, Partition
from vinstall.core import Render, Controller, model, log

LOG = log.get_logger("bootloader_controller")

class Bootloader(Controller):
    """Select a bootloader

    def init(self):
        """Find the disks available in the system.

        self.disks = [ i for i in Disk.all() if not i.is_read_only() ]
        self.partitions = [ i for i in Partition.all() if i.query_filesystem()
                != "xfs" ]
        self.targets = self.disks + self.partitions
        self.bootloaders = [ u"Lilo", u"Grub2", u"None" ]

    def render(self):
        """Show bootloader options

        title = u"Bootloader"
        intro = u"Select a bootloader to boot your system"

        bootloaders = model.DropdownOptionList()
        bootloaders.label = u"Select a bootloader"
        for i in self.bootloaders:

        location = model.DropdownOptionList()
        location.label = u"Install the bootloader in"
	splash_opt = model.BoolOption(u"Disable boot animation","Disable boot animation","Disable bootsplash")
        for i in self.targets:

        return Render(title, intro, bootloaders, location, splash_opt)

    def next(self):
        """Return next step

        return None

    def previous(self):
        """Return previous step

        from vinstall.controller import usersetup
        return usersetup.UserSetup

    def disable_bootsplash(self, splash_disabled):
	"""Disable the bootsplash if asked to by the preference set by splash_opt.
	splash_opt is a Boolean"""
	if splash_disabled == True :
	    # Disable the bootsplash by renaming the initrd.
	    if not os.path.exists(os.path.join(ramdiskdir,'initrd.gz')):
	        LOG.error("User selected to disable bootsplash, but no initrd was found in target")
	    LOG.debug("Renaming initrd.gz to disable bootsplash animation per user's request")

    def command(self, bootloader, target, splash_opt):
        """Schedule command for later execution

        LOG.debug("Bootloader: %s", bootloader)
        LOG.debug("Target: %s", target)
        yield self.set_bind_mounts, tuple(), "Mounting pseudo filesystems"
        yield self.depmod, tuple(), "Running depmod"
        yield self.mkinitrd, tuple(), "Creating initrd"
	if splash_opt == True : # This will have a True value if it was disabled by the user
	    LOG.debug("User selected to disable the bootsplash animation.  Scheduling method to disable it.")
	    yield self.disable_bootsplash, (splash_opt,), "Setting bootsplash preference"
        yield self.install_bootloader, (bootloader, target, splash_opt), "Installing bootloader"
        yield self.clear_bind_mounts, tuple(), "Clearing bind mounts"
	yield self.save_installation_logs, tuple(), "Saving installation logs"

    def save_installation_logs(self):
	"""Save the installation logs to the target"""
	logloc = os.getcwd()
	logtarget = "/mnt/TARGET/var/log"
	shutil.copy(os.path.join(logloc,'installer.log'), os.path.join(logtarget,'installer.log'))
	shutil.copy(os.path.join(logloc,'subprocess.log'), os.path.join(logtarget,'installer-subprocess.log'))

    def install_bootloader(self, bloader, target, splash_opt):
        """Install the bootloader

        bloader = self.bootloaders[bloader]
        disk = self.targets[target]
        target = disk.path()

        if bloader.lower() == "lilo":
            self.install_lilo(target, splash_opt)
        elif bloader == "Grub2":

    def install_lilo(self, target, splash_opt):
        """ Install LILO to target

        LOG.debug("Installing LILO to %s", target)
        # Set the current root.  We would normally use utils.get_mounted("/") for this
        # but on a new install, that returns None, so we must give it the
        # self.config['target_device'] object itself.
	with utils.Chroot("/mnt/TARGET"):
            current_root = self.config['target_device'].path()
	    lilo = bootloader.Lilo(target = target,
		                   bootloader_root = current_root)

            for system in bootloader.OperatingSystem.all(
                    include_running_os = True,
                    bootsplash_disabled = splash_opt,
                    current_root = self.config['target_device']):
		LOG.debug("Adding LiLO boot menu item for %s from %s"% \
			(system.label, system.root))
		if system.root == current_root and "-TUI" not in system.label:
		    LOG.debug("Setting %s from %s as the default boot OS"% \
			(system.label, system.root))


    def install_grub(self, target):
        """ Install Grub2 to target

        LOG.debug("Installing Grub2 to %s", target)
        grub2 = bootloader.Grub2(target)
        with utils.Chroot("/mnt/TARGET"):

    def mkinitrd(self):
        LOG.debug("Creating initrd")
        device = self.config["target_device"]
        fs = self.config["target_device_fs"]
        err = None
        with utils.Chroot("/mnt/TARGET"):
                utils.mkinitrd(device.path(), fs)
            except Exception as e:
                # initrd no supported
                err = e
        if err is not None:
            LOG.error("Initrd not supported: %s", e)

    def depmod(self):
        LOG.debug("Running depmod -a")
        with utils.Chroot("/mnt/TARGET"):

    def clear_bind_mounts(self):
        """Clear the mountpoints that were mounted for the configuration

        for mpoint in ("sys","proc","dev"):
            cmd = "umount -f /mnt/TARGET/%s" % mpoint

    def set_bind_mounts(self):
        """Bind mount some paths into the target.
        Later steps will need this when we chroot there

        LOG.debug("Bind mounting filesystems")
        for point in ("sys","proc","dev"):
            cmd = "mount -o bind /%s /mnt/TARGET/%s" % (point, point)