Logo Search packages:      
Sourcecode: kde-guidance version File versions  Download package

MicroHAL.py

#!/usr/bin/python
###########################################################################
# MicroHAL.py -                                                           #
# ------------------------------                                          #
# begin     : Tue Oct 30 2004                                             #
# copyright : (C) 2004 by Simon Edwards                                   #
# email     : simon@simonzone.com                                         #
#                                                                         #
###########################################################################
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 2 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
###########################################################################

import os
import os.path
from SimpleCommandRunner import *

############################################################################        
class MicroHAL(object):

    # Major device numbers for Linux block devices that support partitions.
    partitionblockdevs = [
        3,  # IDE harddisks
        8,  # SCSI disks
        13, # 8-bit MFM/RLL/IDE controller
        14, # BIOS harddrive callback support {2.6}
        21, # Acorn MFM hard drive interface
        22, # Second IDE hard disk/CD-ROM interface
        28, # ACSI disk (68k/Atari)
        33, # Third IDE hard disk/CD-ROM interface
        34, # Fourth IDE hard disk/CD-ROM interface
        36, # MCA ESDI hard disk
        44, # Flash Translation Layer (FTL) filesystems
        45, # Parallel port IDE disk devices
        48, # Mylex DAC960 PCI RAID controller; first controller
        49, # Mylex DAC960 PCI RAID controller; second controller
        50, # Mylex DAC960 PCI RAID controller; third controller
        51, # Mylex DAC960 PCI RAID controller; fourth controller
        52, # Mylex DAC960 PCI RAID controller; fifth controller
        53, # Mylex DAC960 PCI RAID controller; sixth controller
        54, # Mylex DAC960 PCI RAID controller; seventh controller
        55, # Mylex DAC960 PCI RAID controller; eigth controller
        56, # Fifth IDE hard disk/CD-ROM interface
        57, # Sixth IDE hard disk/CD-ROM interface
        65, # SCSI disk devices (16-31)
        66, # SCSI disk devices (32-47)
        67, # SCSI disk devices (48-63)
        68, # SCSI disk devices (64-79)
        69, # SCSI disk devices (80-95)
        70, # SCSI disk devices (96-111)
        71, # SCSI disk devices (112-127)
        72, # Compaq Intelligent Drive Array, first controller
        73, # Compaq Intelligent Drive Array, second controller
        74, # Compaq Intelligent Drive Array, third controller
        75, # Compaq Intelligent Drive Array, fourth controller
        76, # Compaq Intelligent Drive Array, fifth controller
        77, # Compaq Intelligent Drive Array, sixth controller
        78, # Compaq Intelligent Drive Array, seventh controller
        79, # Compaq Intelligent Drive Array, eigth controller
        80, # I2O hard disk
        81, # I2O hard disk
        82, # I2O hard disk
        83, # I2O hard disk
        84, # I2O hard disk
        85, # I2O hard disk
        86, # I2O hard disk
        87, # I2O hard disk
        88, # Seventh IDE hard disk/CD-ROM interface
        89, # Eighth IDE hard disk/CD-ROM interface
        90, # Ninth IDE hard disk/CD-ROM interface
        91, # Tenth IDE hard disk/CD-ROM interface
        92, # PPDD encrypted disk driver
        95, # IBM S/390 DASD block storage
        101, # AMI HyperDisk RAID controller
        102, # Compressed block device
        104, # Compaq Next Generation Drive Array, first controller
        105, # Compaq Next Generation Drive Array, second controller
        106, # Compaq Next Generation Drive Array, third controller
        107, # Compaq Next Generation Drive Array, fourth controller
        108, # Compaq Next Generation Drive Array, fifth controller
        109, # Compaq Next Generation Drive Array, sixth controller
        110, # Compaq Next Generation Drive Array, seventh controller
        111, # Compaq Next Generation Drive Array, eigth controller
        112, # IBM iSeries virtual disk
        114, # IDE BIOS powered software RAID interfaces such as the Promise Fastrak
        128, # SCSI disk devices (128-143)
        129, # SCSI disk devices (144-159)
        130, # SCSI disk devices (160-175)
        131, # SCSI disk devices (176-191)
        132, # SCSI disk devices (192-207)
        133, # SCSI disk devices (208-223)
        134, # SCSI disk devices (224-239)
        135, # SCSI disk devices (240-255)
        136, # Mylex DAC960 PCI RAID controller; ninth controller
        137, # Mylex DAC960 PCI RAID controller; tenth controller
        138, # Mylex DAC960 PCI RAID controller; eleventh controller
        139, # Mylex DAC960 PCI RAID controller; twelfth controller
        140, # Mylex DAC960 PCI RAID controller; thirteenth controller
        141, # Mylex DAC960 PCI RAID controller; fourteenth controller
        142, # Mylex DAC960 PCI RAID controller; fifteenth controller
        143, # Mylex DAC960 PCI RAID controller; sixteenth controller
        160, # Promise SX8 8-port SATA Disks on First Controller
        161  # Promise SX8 8-port SATA Disks on Second Controller
        ]
        
    floppydevs = [
        2, # Floppy disks
        40 # Syquest EZ135 parallel port removable drive
    ]
    
    cdromsdevs = [
        11, # SCSI CD-ROM devices
        12, # MSCDEX CD-ROM callback support {2.6}
        15, # Sony CDU-31A/CDU-33A CD-ROM
        16, # GoldStar CD-ROM
        17, # Optics Storage CD-ROM
        18, # Sanyo CD-ROM
        20, # Hitachi CD-ROM (under development)
        23, # Mitsumi proprietary CD-ROM
        24, # Sony CDU-535 CD-ROM
        25, # First Matsushita (Panasonic/SoundBlaster) CD-ROM
        26, # Second Matsushita (Panasonic/SoundBlaster) CD-ROM
        27, # Third Matsushita (Panasonic/SoundBlaster) CD-ROM
        28, # Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
        29, # Aztech/Orchid/Okano/Wearnes CD-ROM
        30, # Philips LMS CM-205 CD-ROM
        32, # Philips LMS CM-206 CD-ROM
        41, # MicroSolutions BackPack parallel port CD-ROM
        46, # Parallel port ATAPI CD-ROM devices
        47, # Parallel port ATAPI disk devices
        48, # Mylex DAC960 PCI RAID controller; first controller
        113 # IBM iSeries virtual CD-ROM
    ]

    burnerpacketdevs = [
        97  # Packet writing for CD/DVD devices
    ]

    # We provide a mapping between filesystems and kernelmodules, so filesystems
    # that are built as modules can be loaded on demand. (In fact, mountconfig will
    # load all filesystem modules needed to be able to mount all fstab entries.) 
    FilesystemProcDriver = [
        # fstab name, /proc name, kernel module name
        ('auto','autofs','autofs4'),
        ('iso9660','iso9660','isofs'),
        ('nfs','nfsd','nfs')
    ]
        
    ############################################################################
    def __init__(self):
        self.devices = None
        self.supportedfs = None
        self.partitionsizelines = None
        
    ############################################################################
    def getDevices(self):
        if self.devices is None:
            self.devices = []
            # Scan through /sys/block for devices. Find out which disks are
            # installed and should be shown in the listview. For real
            # disks we put a 'group' in the listview and under the group
            # we list the partitions, whether they are mounted or not.
            # FIXME: Check if sysfs is mounted.
            blockdevices = os.listdir("/sys/block")
            blockdevices.sort()
            
            for blockdevice in blockdevices:
                # We are looking for block devices that represent hard disks or
                # things that have partitions.
                # Grab the major device number
                fhandle = open(os.path.join("/sys/block",blockdevice,"dev"))
                devnumbers = fhandle.read()
                fhandle.close()
                devnum = int(devnumbers.split(":")[0])
                # Is it on our list of partition devices?
                if devnum in MicroHAL.partitionblockdevs:
                    fulldevice = os.path.join("/dev",blockdevice)
                
                    # Check for removable devices.
                    fhandle = open(os.path.join("/sys/block",blockdevice,"removable"))
                    removable = fhandle.read().strip()=="1"
                    fhandle.close()
                    
                    if not removable:
                        newdisk = Disk(self)
                    else:
                        newdisk = RemovableDisk(self)
                    newdisk.dev = fulldevice
                    newdisk.major = devnum
                    newdisk.removable = removable
                    
                    if not removable:
                        # We have a not removable block device.
                        partitions = os.listdir(os.path.join("/sys/block",blockdevice))
                        partitions.sort()
                        i = 1
                        for partition in partitions:
                            # Look for a partitions device names and not the other
                            # stuff that lives in the directory.
                            if partition.startswith(blockdevice):
                                fullpartition = os.path.join("/dev",partition)
                                newpartition = Partition(self)
                                newpartition.dev = fullpartition
                                newpartition.num = i
                                newdisk.partitions.append(newpartition)
                                i += 1
                    self.devices.append(newdisk)
    
                elif devnum in MicroHAL.cdromsdevs:
                    fulldevice = os.path.join("/dev",blockdevice)
                    newdisk = RemovableDisk(self)
                    newdisk.dev = fulldevice
                    newdisk.major = devnum
                    self.devices.append(newdisk)
                    
                elif devnum in MicroHAL.burnerpacketdevs:
                    fulldevice = os.path.join("/dev",blockdevice)
                    newdisk = BurnerDisk(self)
                    newdisk.dev = fulldevice
                    newdisk.major = devnum
                    self.devices.append(newdisk)

        return self.devices[:]

    ############################################################################
    def getPartitionSize(self,devicename):
        partitionname = os.path.basename(devicename)
    
        if self.partitionsizelines is None:
            fhandle = open('/proc/partitions')
            self.partitionsizelines = fhandle.readlines()
            fhandle.close()        
    
        i = 0
        for line in self.partitionsizelines:
            if i>=2:
                (major, minor, blocks, name) = line.split()
                if name==partitionname:
                    blocks = int(blocks) # 1K blocks now.
                    if blocks<1024:
                        return str(blocks)+" Kb"
                    if blocks<1024*1024:
                        return str(round(float(blocks)/1024.0,1))+" Mb"
                    blocks /= 1024
                    if blocks<1024*1024:
                        return str(round(float(blocks)/1024.0,1))+" Gb"
                    blocks /= 1024
                    return str(round(float(blocks)/1024.0,1))+" Tb"
            i += 1
        return None
        
    ############################################################################
    def getIDEModel(self,devname):
        try:
            fhandle = open(os.path.join("/proc/ide",os.path.basename(devname),"model"))
            model = fhandle.read()
            fhandle.close()
            return model.strip()
        except (OSError, IOError):
            return None
    
    ############################################################################
    def getSCSIModel(self,devname):
        try:
            fhandle_model = open(os.path.join("/sys/block",os.path.basename(devname),"device/model"))
            fhandle_vendor = open(os.path.join("/sys/block",os.path.basename(devname),"device/vendor"))
            model = fhandle_model.read()[:-1]
            vendor = fhandle_vendor.read()[:-1]
            fhandle_model.close()
            fhandle_vendor.close()
        except (OSError, IOError):
            pass
        if len(model) + len(vendor) == 0:
            return None
        return vendor + " " + model
    
    ############################################################################
    def getSupportedFileSystems(self):
        if self.supportedfs is None:
            if os.path.isfile("/proc/filesystems"):
                fhandle = open("/proc/filesystems")
                self.supportedfs = []
                for fs in fhandle.readlines():
                    try:
                        self.supportedfs.append(fs.strip().split()[1])
                    except IndexError:
                        self.supportedfs.append(fs.strip().split()[0])
            # The following filesystems aren't found there, but usually they are
            # supported.
            self.supportedfs.extend(('swap','shm'))
        return self.supportedfs[:]
        
    ############################################################################
    def isSupportedFileSystem(self,fs):
        # Look up the /proc and kernel driver name for the given filesystem type.
        module = fs
        proc = fs
        for entry in self.FilesystemProcDriver:
            if entry[0]==fs:
                proc = entry[1]
                module = entry[2]
        
        if proc not in self.getSupportedFileSystems():
            # The filesystem is not supported by the running kernel,
            # but it might be built as module, so we try to load that.
            retval, msg = SimpleCommandRunner().run(["/sbin/modprobe",module])
            if retval > 0:
                print msg
                print "Couldn't load driver " + module + " for filesystem " + fs
            # Force refresh of list of supported filesystems
            self.supportedfs = None
        return proc in self.getSupportedFileSystems()
        
############################################################################        
class Device(object):
    def __init__(self,hal):
        self.hal = hal
        self.dev = None
        self.major = None
        self.removable = None
    def getDev(self):
        return self.dev
    def getMajor(self):
        return self.major
    def getName(self):
        return self.dev
    def __str__(self):
        return self.getName()+" "+str(self.getDev())
        
############################################################################        
class Disk(Device):
    def __init__(self,hal):
        super(Disk,self).__init__(hal)
        self.removable = False
        self.partitions = []
        self.modelname = None
        self.iconname = "hi16-hdd"
        
    def getModelName(self):
        if self.modelname is None:
            self.modelname = self.hal.getIDEModel(self.getDev())
            if self.modelname is None:
                self.modelname = self.hal.getSCSIModel(self.getDev())
                if self.modelname is None:
                    self.modelname = self.dev
        return " '"+self.modelname+"'"
    
    def getName(self):
        return "Disk"+self.getModelName()
        
    def getPartitions(self):
        return self.partitions[:]

############################################################################        
class RemovableDisk(Disk):
    def __init__(self,hal):
        super(RemovableDisk,self).__init__(hal)
        self.iconname = "hi16-cdrom"
        self.removable = True

    def getName(self):
        return "Optical Disk"+self.getModelName()

############################################################################        
class BurnerDisk(RemovableDisk):
    def __init__(self,hal):
        super(BurnerDisk,self).__init__(hal)
        self.iconname = "hi16-burner"

    def getName(self):
        if self.modelname is None:
            self.modelname = self.hal.getIDEModel(self.getDev())
            if self.modelname is None:
                self.modelname = self.dev
        return "Burner '"+self.modelname+"'"
        
############################################################################        
class Floppy(Device):
    def isRemovable(self):
        return True
    
    def getName(self):
        return "Floppy"
        
class Partition(Device):
    def __init__(self,hal):
        super(Partition,self).__init__(hal)
        self.num = None
        self.size = None
        self.iconname = "hi16-hdd"
    
    def getName(self):
        if self.size is None:
            self.size = self.hal.getPartitionSize(self.dev)
            if self.size is None: self.size = ""
        return str(self.num)+" Partition "+ self.size
        # A group item for all of the other kernel/system mount entries.

############################################################################        
class FakeSystemDevice(object):
    def getName(self): return "System"
    def getIconName(self): return "hi16-blockdevice"

############################################################################
if __name__=='__main__':
    hal = MicroHAL()
    for item in hal.getDevices():
        print str(item)

    

Generated by  Doxygen 1.6.0   Back to index