vinstall / vinstall / backend /

#!/bin/env python

"""Media handling. Implements a Partition class providing methods
formounting,umounting, formating and querying partitions.


__author__ = "rbistolfi"
# 2012-09-10 Modified by M0E-lnx to use the pyparted API instead of reparted

import re
import os
import subprocess
from utils import mount, umount, is_mounted, format_partition
import partitioning
import parted
#from parted import device as pdevice
#from parted import disk as pdisk

# I think we should have a and import settings from there
DEV_DIR = '/dev'
CD_INFO = '/proc/sys/dev/cdrom/info'
PARTITIONS = '/proc/partitions'
MOUNTPOINT = '/mnt/loop'

def list_cdroms(proc_info=CD_INFO):
    """Find CDROM devices based in the information stored in the proc tree.

    file_handler = open(proc_info)
    data =
    cdroms = re.findall(r'^drive name:\s*([hs]d[a-z]|s[rg]\d*)', data, re.M)
    return ( os.path.join("/dev", i) for i in cdroms )

def list_partitions(proc_partitions_info=PARTITIONS):
    """List the partitions present in the system by parsing /proc/partitions.

    file_handler = open(proc_partitions_info)
    data =
    return [ os.path.join(DEV_DIR, i) for i in \
            re.findall(r'[sh]d[a-z]\d{1,2}', data) ]

def list_swap():
    """Returns a list of swap devices.

    swaps = []
    for i in list_partitions():
        process = subprocess.Popen(['blkid', i],
        data =
        if "swap" in data:
    return swaps

class Partition(object):
    """A class representing a partition in a hard disk.

        device_path: the path to the device node.


    def __str__(self):
        if self.query_filesystem():
            filesystem = self.query_filesystem()
            filesystem = "Not formated"
        return '%s (%s)' % (self.device_path, filesystem)

    def __repr__(self):
        return '<Partition object: %s>' % self.device_path

    def __init__(self, device_path):
        """Initializes a Media object fro the device path."""

        self.mountpoint = None
        self.device_path = device_path
        if self.is_mounted():
           for line in open("/etc/mtab"):
               device, mountpoint, _ = line.split(" ", 2)
               if device == self.device_path:
                   self.mountpoint = mountpoint

    def mount(self, mountpoint, filesystem="auto"):
        """Mount the media in the specified mountpoint."""

        new_mountpoint = mount(self.device_path, mountpoint, filesystem=filesystem)
        self.mountpoint = new_mountpoint

    def umount(self):
        """Umount the media."""

        return umount(self.mountpoint)

    def is_mounted(self):
        """Returns True if the media is mounted, False otherwise."""

        return is_mounted(self.device_path)

    def query_filesystem(self):
        """Retrieve the current filesystem type from the system."""

        process = subprocess.Popen(['blkid', self.device_path],
        data =
            return'TYPE="(\w+)"', data).group(1)
        except AttributeError:
            #blkid returned nothing
            return None

    def format(self, filesystem):
        """Create a filesystem in this partition.

        format_partition(self.device_path, filesystem)

    def all(cls):
        """Return all the partitions in the system

        disks = [ i for i in Disk.all() if i._has_partition_table ]
        partitions = []
        for dsk in disks:
        for part in partitions:
            if part.type in (parted.PARTITION_NORMAL,
                yield cls(part.path)

class Disk(object):

    def __init__(self):

        self._device = None
        self._disk = None
        self._has_partition_table = False

    def __repr__(self):

        return "<Disk %s>" % self.path()

    def __str__(self):

        return "%s - %s GB (%s)" % (self.model(),  self.size(), self.path())

    def model(self):
        """Return the string describing the device model"""
        return self._device.model

    def free_space(self, units="MiB"):
        """Return the ammount of free space available in units specified"""
        raise RuntimeError("Deprecated method")

    def _get_size_from_hw(self, unit="GiB"):
        """ Returns disk size, by default in GB, unit can be GB or MB
        This method is used internally when the disk is not initialized.
        pow = 2 if unit == "MiB" else 3
        cylinders,  heads,  sectors = self._device.hardwareGeometry
        sector_size = self._device.physicalSectorSize #self._device.sector_size
        size = cylinders * heads * sectors * sector_size /1000 ** pow
        return size

    def has_partition_table(self):
        """Return True if the disk has a partition table.  False otherwise"""
        # test if the device has a partition table yet
        return self._has_partition_table
            pdisk = parted.Disk(self._device)
            del pdisk
            return True
            return False

    def size(self, unit="GiB"):
        """ Returns disk size, by default in GB, unit can be GB or MB

        return self._device.getLength(unit)

    def path(self):
        """Return the node path for this device"""
        return self._device.path

    def is_read_only(self):
        """Return True if the device is read-only"""
        return self._device.readOnly

    def all(cls):
        devices = ( dev for dev in parted.getAllDevices() if dev.readOnly is False )
        if not devices:
            raise RuntimeError("No hard drives found")
        for dev in devices:
            disk = cls()
                disk._disk = pdisk.Disk(dev)
                disk._has_partition_table = True
                #disk._disk = parted.freshDisk(dev, 'msdos') # Create the object with an empty partition table in it ??
                # FIXME: ^^
                disk._has_partition_table = False                
            disk._device = dev
            yield disk