Source

vinstall / vinstall / controller / packages.py

Full commit
#-*- coding: utf-8 -*-

"""Partitions options for the Vector installer

"""


from vinstall.core import Render, Controller, model
from vinstall.backend import utils, sp
from itertools import chain
import os, shutil, glob


class PackageSelection(Controller):
    """Select packages to be installed in the target

    """
    def init(self):
        install_media = self.config["install_media"]
        self.required_bulks = install_media.items("bulks/required")
        self.optional_bulks = install_media.items("bulks/optional")
        self.mount_source()

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

        """
        title = "Package selection"
        intro = "Select packages to be installed in your system"
        options = [ model.BoolOption(v) for k, v in self.optional_bulks ]
        return Render(title, intro, *options)

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

        """
        from vinstall.controller import usersetup
        return usersetup.UserSetup

    def previous(self):
        """

        """
        from vinstall.controller import mountpoints
        return mountpoints.Mountpoint

    def command(self, *bulks):
        """Schedule command for later execution

        """
        yield self.preinstall, tuple(), "Preparing package install"
        for package in self.packages(bulks):
            yield self.installpkg, (package,), "Installing %s" % package.split("/")[-1]
        yield self.postinstall, tuple(), "Installing setup routines"
        yield self.install_kernel, tuple(), "Installing Linux kernel"
        yield self.vector_version, tuple(), "Writing /etc/vector-version"

    def packages(self, bulks):
        """Return packages to be installed by chaining required packages with
        selected bulks

        """
        required_bulks = [ i[0] for i in self.required_bulks ]
        optional_bulks = [ self.optional_bulks[i][0] for i, e in enumerate(bulks) if e ]
        bulks = chain(required_bulks, optional_bulks)
        for b in bulks:
            for package in self.bulk_packages(b):
                yield package

    def installpkg(self, package):
        """Install a package in the target

        """
        command = "/usr/sbin/installpkg %s --root=%s" % (package, "/mnt/TARGET")
        sp.check_call(command.split())

    def preinstall(self):
        """Run before installing packages

        """
        aaa = glob.glob("/mnt/SOURCE/packages/a/aaa_base-*.t?z")[0]
        self.installpkg(aaa)

    def postinstall(self):
        """Run after installing packages

        """
        theme = glob.glob("/mnt/SOURCE/packages/*/VL_Theme-*.t?z")
        vlconfig = glob.glob("/mnt/SOURCE/packages/a/vlconfig2-*.t?z")[0]
        for pkg in theme:
            self.installpkg(pkg)
        self.installpkg(vlconfig)

    def install_kernel(self):
        """Install kernel packages

        """
        install_media = self.config["install_media"]
        kernel_version = install_media.config.get("kernels", "sata")
        kernel_version = kernel_version.replace("\"", "")
        source = os.path.join('/mnt', 'SOURCE', 'isolinux', 'kernel',
                'sata')
        target = os.path.join('/mnt', 'TARGET', 'boot', 'vmlinuz-%s' %
            kernel_version)
        shutil.copyfile(source, target)

    def bulk_packages(self, bulk):
        """Return packages in bulk

        """
        excluded =("vlconfig2", "vlsetup", "aaa_base", "VL_Theme")
        basedir = "/mnt/SOURCE/veclinux"
        pkgbasedir = "/mnt/SOURCE/packages"
        path = os.path.join(basedir, bulk)
        with open(path) as f:
            for packagename in f:
                if packagename in excluded:
                    continue
                #XXX do not use glob this way, god forgive us
                packagename = packagename.strip()
                fname = "%s/*/%s*t?z" % (pkgbasedir, packagename)
                fullpath = glob.glob(fname)
                if fullpath:
                    for p in fullpath:
                        f = p.rsplit("/", 1)[1]
                        name, _, _, _ = f.rsplit("-", 3)
                        if name == packagename:
                            yield p
                else:
                    #print "WARNING: missing package", packagename
                    pass

    def vector_version(self):
        """write /etc/vector-version based on the information
        in VINSTALL.INI

        """
        install_media = self.config["install_media"]
        distro = install_media.config.get("general", "distro").replace("\"", "")
        version = install_media.config.get("general", "version").replace("\"", "")
        build_date = install_media.config.get("general",
                "build_date").replace("\"", "")
        vector_version =  "%s built on %s\n" % (version, build_date)
        with open("/mnt/TARGET/etc/vector-version", 'w') as f:
            f.write(vector_version)

    def mount_source(self):
        """Mount the install media, needed for looking for available packages

        """
        mountpoint = "/mnt/SOURCE"
        if not os.path.exists(mountpoint):
            os.mkdir(mountpoint)
        install_media = self.config["install_media"]
        if install_media.is_iso():
            if not os.path.exists(install_media.path):
                mntpoint = install_media.path.rsplit("/", 1)[0]
                dev = mntpoint.replace("/mnt", "/dev")
                utils.mount(dev, mntpoint)
            utils.mountiso(install_media.path, mountpoint)
        else:
            utils.mount(install_media.path, mountpoint, filesystem="auto")


class LivePackageInstaller(object):
    """Install packages from a Live CD

    """
    def init(self):
        self.mount_source()

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

        """
        from vinstall.controller import usersetup
        return usersetup.UserSetup

    def previous(self):
        """

        """
        from vinstall.controller import mountpoints
        return mountpoints.Mountpoint

    def command(self):
        yield self.preinstall, tuple(), "Preparing package install"
        for package in self.packages():
            yield self.installpkg, (package,), "Installing %s" % package.split("/")[-1]
        yield self.install_kernel, tuple(), "Installing Linux kernel"
        yield self.vector_version, tuple(), "Writing /etc/vector-version"

    def packages(self):
        """Return an iterable containing all available packages for a Live
        edition

        """
        return glob.glob("/mnt/SOURCE/*/base/*xzm")

    def installpkg(self, package):
        """Install a package from a Live install media

        """
        command = "/usr/bin/xzm2dir %s %s" % (package, "/mnt/TARGET")
        sp.check_call(command.split())

    def install_kernel(self):
        """Install Linux image from a Live install media

        """
        #XXX do not chdir without switching back to original working dir!
        install_media = self.config["install_media"]
        kernel_version = install_media.config.get("kernels", "sata")
        kernel_version = kernel_version.replace("\"", "")
        source = os.path.join('/mnt', 'SOURCE', 'boot', 'vmlinuz')
        target = os.path.join('/mnt', 'TARGET', 'boot', 'vmlinuz-%s' %
                kernel_version)
        shutil.copyfile(source, target)
        for rc in ("rc.S", "rc.M", "rc.K", "rc.local"):
            rcdir = os.path.join('/mnt', 'TARGET', 'etc', 'rc.d')
            source = os.path.join('%s.real' % rc)
            os.chdir(rcdir)
            os.remove(rc)
            os.symlink(source, rc)


    def preinstall(self):
        """Run before installing packages, used for creating needed dirs

        """
        root = "/mnt/TARGET"
        for d in ("tmp", "mnt", "sys", "proc", "dev"):
            d2 = os.path.join(root, d)
            os.mkdir(d2)
        for d in ("cdrom", "cdwriter", "dvd", "dvdwriter", "floppy", "hd",
                "linux", "loop", "memory", "pendrive", "tmp", "vl-hot",
                "win", "zip"):
            d2 = os.path.join(root, "mnt", d)
            os.mkdir(d2)

    def vector_version(self):
        """write /etc/vector-version based on the information
        in VINSTALL.INI

        """
        install_media = self.config["install_media"]
        distro = install_media.config.get("general", "distro").replace("\"", "")
        version = install_media.config.get("general", "version").replace("\"", "")
        build_date = install_media.config.get("general",
                "build_date").replace("\"", "")
        vector_version =  "%s built on %s\n" % (version, build_date)
        with open("/mnt/TARGET/etc/vector-version", 'w') as f:
            f.write(vector_version)

    def mount_source(self):
        """Mount the install media, needed for looking for available packages

        """
        mountpoint = "/mnt/SOURCE"
        if not os.path.exists(mountpoint):
            os.mkdir(mountpoint)
        install_media = self.config["install_media"]
        if install_media.is_iso():
            if not os.path.exists(install_media.path):
                mntpoint = install_media.path.rsplit("/", 1)[0]
                dev = mntpoint.replace("/mnt", "/dev")
                utils.mount(dev, mntpoint)
            utils.mountiso(install_media.path, mountpoint)
        else:
            utils.mount(install_media.path, mountpoint, filesystem="auto")