Source

vinstall / vinstall / backend / installmedia.py

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

"""install media returns a list of install media

"""


import media
from utils import mount, mountiso, umount

import os
import ConfigParser
from itertools import chain


__author__ = "Uel Archuletta, Rodrigo Bistolfi"


class InstallMedia(object):
    """Represents a source media containing the installer

    """
    @classmethod
    def all(cls):
        """Find install media in devices and partitions

        """
        finders = [ CdRomInstallMediaFinder(), PartitionInstallMediaFinder() ]
        return chain(*[i.find() for i in finders])

    def __init__(self, path, config):
        """Expose install media base dir and the config object

        """
        self.path = path
        self.config = config

    def __str__(self):
        if self.is_iso():
            format = "%s %s - ISO on %s"
            path = self.path.rsplit("/", 1)[0] or "/"
        else:
            format = "%s %s on %s"
            path = self.path
        return format % (self.get("general", "distro"),
                self.get("general", "version"), path)

    def __getattr__(self, name):
        """Delegate in config object

        """
        return getattr(self.config, name)

    def is_iso(self):
        """Answer if the installer source is in an iso file

        """
        return self.path.endswith("iso")


class InstallMediaFinder(object):
    "Interface for media finder objects"

    def find(self):
        "Find install media. Return an iterable containing InstallMedia objects"


class CdRomInstallMediaFinder(InstallMediaFinder):
    "Find install media in cdrom devices"

    def __init__(self):
        self.devices = (media.Partition(i) for i in media.list_cdroms())
        self.mountpoint = "/tmp/DEVMNT"
        create_mountpoint(self.mountpoint)

    def find(self):
        "Find install media in cdrom devices"
        for cdrom in self.devices:
            needs_umount = False
            if not cdrom.is_mounted():
                cdrom.mount(self.mountpoint)
                needs_umount = True
            if is_install_media(cdrom.mountpoint):
                config = parse_config(cdrom.mountpoint)
                yield InstallMedia(cdrom.device_path, config)
            if needs_umount:
                cdrom.umount()


class PartitionInstallMediaFinder(InstallMediaFinder):
    "Find install media in existing partitions"

    def __init__(self):
        self.partitions = media.Partition.all()

    def find(self):
        for partition in self.partitions:
            needs_umount = False
            if not partition.is_mounted():
                partition.mount(partition.mountpoint)
                needs_umount = True
            if is_install_media(partition.mountpoint):
                config = parse_config(partition.mountpoint)
                yield InstallMedia(partition.mountpoint, config)
            else:
                isofinder = ISOInstallMediaFinder(partition.mountpoint)
                for im in isofinder.find():
                    yield im
            if needs_umount:
                partition.umount()


class ISOInstallMediaFinder(InstallMediaFinder):
    "Find install media in ISO files"

    def __init__(self,root_dir):
        self.root_dir = root_dir
        self.mountpoint = "/tmp/ISOMNT"
        create_mountpoint(self.mountpoint)

    def find(self):
        for f in os.listdir(self.root_dir):
            if os.path.isfile(os.path.join(self.root_dir, f)) and f.endswith(".iso"):
                isopath = os.path.join(self.root_dir, f)
                mountiso(isopath, self.mountpoint)
                if is_install_media(self.mountpoint):
                    config = parse_config(self.mountpoint)
                    yield InstallMedia(isopath, config)
                umount(self.mountpoint)


def parse_config(mnt):
    """ Reads VINSTALL.INI

    """
    conf = "veclinux/VINSTALL.INI"
    config = ConfigParser.RawConfigParser()
    config.optionxform = str
    config.read(os.path.join(mnt,conf))
    return config


def make_mountpoint(device):
    """Create mountpoint for device

    """
    mountpoint = device.replace("/dev", "/mnt")
    if not os.path.exists(mountpoint):
        os.mkdir(mountpoint)


def is_install_media(mnt):
    """ Checks for VINSTALL.INI the install config file added in 6.0

    """
    config = "veclinux/VINSTALL.INI"
    return os.path.exists(os.path.join(mnt,config))


def create_mountpoint(location):
    "Create mountpoint if it doesnt exist"
    try:
        os.mkdir(location)
    except OSError as e:
        if e.errno == 17:
            pass
        else:
            raise e