|
|
|
#!/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()
|
|
|
|
else:
|
|
|
|
if os.readlink(os.path.join("/sys/block",blockdevice,"device")).split(os.path.sep)[5].startswith("usb"):
|
|
|
|
newdisk = USBDisk()
|
|
|
|
else:
|
|
|
|
newdisk = RemovableDisk()
|
|
|
|
newdisk.dev = fulldevice
|
|
|
|
newdisk.major = devnum
|
|
|
|
newdisk.removable = removable
|
|
|
|
newdisk.modelname = self.getModelName(fulldevice)
|
|
|
|
|
|
|
|
if not removable or isinstance(newdisk, USBDisk):
|
|
|
|
# We have a not removable block device or a USB Disk here.
|
|
|
|
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()
|
|
|
|
newpartition.dev = fullpartition
|
|
|
|
newpartition.size = self.getPartitionSize(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()
|
|
|
|
newdisk.dev = fulldevice
|
|
|
|
newdisk.major = devnum
|
|
|
|
newdisk.modelname = self.getModelName(fulldevice)
|
|
|
|
self.devices.append(newdisk)
|
|
|
|
|
|
|
|
elif devnum in MicroHAL.burnerpacketdevs:
|
|
|
|
fulldevice = os.path.join("/dev",blockdevice)
|
|
|
|
newdisk = BurnerDisk(self)
|
|
|
|
newdisk.dev = fulldevice
|
|
|
|
newdisk.major = devnum
|
|
|
|
newdisk.modelname = self.getModelName(fulldevice)
|
|
|
|
|
|
|
|
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 getModelName(self,devname):
|
|
|
|
modelname = self.getIDEModel(devname)
|
|
|
|
if modelname is None:
|
|
|
|
modelname = self.getSCSIModel(devname)
|
|
|
|
if modelname is None:
|
|
|
|
modelname = devname
|
|
|
|
return " '"+modelname+"'"
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
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):
|
|
|
|
self.dev = None
|
|
|
|
self.major = None
|
|
|
|
self.removable = None
|
|
|
|
self.uuid = None
|
|
|
|
self.label = None
|
|
|
|
|
|
|
|
def getDev(self):
|
|
|
|
return self.dev
|
|
|
|
|
|
|
|
def getMajor(self):
|
|
|
|
return self.major
|
|
|
|
|
|
|
|
def getName(self):
|
|
|
|
return self.dev
|
|
|
|
|
|
|
|
def getUUID(self):
|
|
|
|
if not self.uuid:
|
|
|
|
return ""
|
|
|
|
return self.uuid
|
|
|
|
|
|
|
|
def getLabel(self):
|
|
|
|
if not self.label:
|
|
|
|
return ""
|
|
|
|
return self.label
|
|
|
|
|
|
|
|
def isRemovable(self):
|
|
|
|
return self.removable
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "Name: %s, Device: %s, Major: %i, " % (self.getName(),
|
|
|
|
self.getDev(),
|
|
|
|
self.getMajor())
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
class Disk(Device):
|
|
|
|
def __init__(self):
|
|
|
|
super(Disk,self).__init__()
|
|
|
|
self.removable = False
|
|
|
|
self.partitions = []
|
|
|
|
self.modelname = None
|
|
|
|
self.iconname = "hi16-hdd"
|
|
|
|
|
|
|
|
def getModelName(self):
|
|
|
|
return self.modelname
|
|
|
|
|
|
|
|
def getName(self):
|
|
|
|
if self.getModelName():
|
|
|
|
return i18n("Disk ")+self.getModelName()
|
|
|
|
else:
|
|
|
|
return i18n("Unknown Disk")
|
|
|
|
|
|
|
|
def getPartitions(self):
|
|
|
|
return self.partitions[:]
|
|
|
|
|
|
|
|
def appendPartition(self,partition):
|
|
|
|
self.partitions.append(partition)
|
|
|
|
def cmpNum(a,b): return cmp(a.num,b.num)
|
|
|
|
self.partitions.sort(cmpNum)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
x = Device.__str__(self) + "Partitions: ["
|
|
|
|
for part in self.partitions:
|
|
|
|
x += "["
|
|
|
|
x += str(part)
|
|
|
|
x += "], "
|
|
|
|
x += "],"
|
|
|
|
return x
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
class RemovableDisk(Disk):
|
|
|
|
def __init__(self):
|
|
|
|
super(RemovableDisk,self).__init__()
|
|
|
|
self.iconname = "hi16-cdrom"
|
|
|
|
self.removable = True
|
|
|
|
|
|
|
|
def getName(self):
|
|
|
|
return "Optical Disk "+self.getModelName()
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
class USBDisk(Disk):
|
|
|
|
def __init__(self):
|
|
|
|
super(USBDisk,self).__init__()
|
|
|
|
self.iconname = "hi16-usbpen"
|
|
|
|
self.removable = True
|
|
|
|
|
|
|
|
def getName(self):
|
|
|
|
return "Removable USB Disk "+self.getModelName()
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
class BurnerDisk(RemovableDisk):
|
|
|
|
def __init__(self):
|
|
|
|
super(BurnerDisk,self).__init__()
|
|
|
|
self.iconname = "hi16-burner"
|
|
|
|
|
|
|
|
def getName(self):
|
|
|
|
return "Burner "+self.modelname
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
class Floppy(Device):
|
|
|
|
def isRemovable(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def getName(self):
|
|
|
|
return "Floppy"
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
class Partition(Device):
|
|
|
|
def __init__(self):
|
|
|
|
super(Partition,self).__init__()
|
|
|
|
self.num = None
|
|
|
|
self.size = None
|
|
|
|
self.iconname = "hi16-hdd"
|
|
|
|
|
|
|
|
def getName(self):
|
|
|
|
return str(self.num)+" Partition "+ self.getSize()
|
|
|
|
# A group item for all of the other kernel/system mount entries.
|
|
|
|
|
|
|
|
def getSize(self):
|
|
|
|
return self.size
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "Device: %s, Num: %i, Size: %s, Label: %s, UUID: %s" % (self.dev, self.num, self.getSize(),
|
|
|
|
self.getLabel(), self.getUUID())
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
class FakeSystemDevice(object):
|
|
|
|
def getName(self): return "System"
|
|
|
|
def getIconName(self): return "hi16-blockdevice"
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
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
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
def getDevices(self):
|
|
|
|
if self.devices is None:
|
|
|
|
self.devices = []
|
|
|
|
|
|
|
|
retval, msg = SimpleCommandRunner().run(["/usr/bin/lshal"])
|
|
|
|
if retval > 0:
|
|
|
|
return []
|
|
|
|
|
|
|
|
partition_to_uid = {}
|
|
|
|
uid_to_disk = {}
|
|
|
|
|
|
|
|
READING_TOP = 0
|
|
|
|
READING_DEVICE = 1
|
|
|
|
state = READING_TOP
|
|
|
|
|
|
|
|
parsed_hash = None
|
|
|
|
current_uid = None
|
|
|
|
|
|
|
|
for line in msg.split('\n'):
|
|
|
|
|
|
|
|
if state==READING_TOP:
|
|
|
|
if line.startswith("udi ="):
|
|
|
|
parsed_hash = {}
|
|
|
|
current_uid = self._parseString(line[6:])
|
|
|
|
state = READING_DEVICE
|
|
|
|
|
|
|
|
elif state==READING_DEVICE:
|
|
|
|
if line=="" or not line.startswith(" "):
|
|
|
|
# Detect the end of this block of device data.
|
|
|
|
state = READING_TOP
|
|
|
|
|
|
|
|
if u"info.category" in parsed_hash:
|
|
|
|
|
|
|
|
new_device = None
|
|
|
|
|
|
|
|
capabilities_string = u" ".join(parsed_hash[u"info.capabilities"])
|
|
|
|
capabilities = self._parseStringList(capabilities_string)
|
|
|
|
|
|
|
|
category = self._parseString(' '.join(parsed_hash[u"info.category"]))
|
|
|
|
if category==u"volume":
|
|
|
|
# Is it a volume?
|
|
|
|
|
|
|
|
is_disc = parsed_hash.get(u"volume.is_disc")
|
|
|
|
if is_disc is not None and is_disc[0]=='true':
|
|
|
|
continue
|
|
|
|
|
|
|
|
is_partition = parsed_hash.get(u"volume.is_partition")
|
|
|
|
if is_partition is not None:
|
|
|
|
is_partition = is_partition[0]
|
|
|
|
|
|
|
|
if is_partition=='true':
|
|
|
|
new_device = Partition()
|
|
|
|
new_device.num = int(parsed_hash[u"volume.partition.number"][0])
|
|
|
|
partition_to_uid[new_device] = current_uid
|
|
|
|
|
|
|
|
if u"info.parent" in parsed_hash:
|
|
|
|
parent_uid = self._parseString(' '.join(parsed_hash[u"info.parent"]))
|
|
|
|
partition_to_uid[new_device] = parent_uid
|
|
|
|
|
|
|
|
else:
|
|
|
|
new_device = Disk()
|
|
|
|
uid_to_disk[current_uid] = new_device
|
|
|
|
|
|
|
|
if u"volume.uuid" in parsed_hash:
|
|
|
|
new_device.uuid = self._parseString(' '.join(parsed_hash[u"volume.uuid"]))
|
|
|
|
|
|
|
|
if u"volume.label" in parsed_hash:
|
|
|
|
new_device.label = self._parseString(parsed_hash[u"volume.label"][0])
|
|
|
|
# If HAL returns label beginning with '#', it usually means that the
|
|
|
|
# actual label contains an Unix path. So we replace '#' with '/'.
|
|
|
|
if len(new_device.label) and new_device.label[0]=='%':
|
|
|
|
new_device.label = new_device.label.replace('%', '/')
|
|
|
|
|
|
|
|
if u"volume.size" in parsed_hash:
|
|
|
|
size = parsed_hash[u"volume.size"][0]
|
|
|
|
new_device.size = self.formatSizeBytes(int(size))
|
|
|
|
else:
|
|
|
|
new_device.size = "?"
|
|
|
|
|
|
|
|
|
|
|
|
# is it a storage device?
|
|
|
|
elif category==u"storage":
|
|
|
|
storage_model = self._parseString(' '.join(parsed_hash[u"storage.model"]))
|
|
|
|
storage_removable = parsed_hash[u"storage.removable"][0]==u"true"
|
|
|
|
|
|
|
|
if u"storage.cdrom" in capabilities:
|
|
|
|
|
|
|
|
if u"storage.cdrom.cdrw" in parsed_hash \
|
|
|
|
and parsed_hash[u"storage.cdrom.cdrw"][0]==u"true":
|
|
|
|
new_device = BurnerDisk()
|
|
|
|
else:
|
|
|
|
new_device= RemovableDisk()
|
|
|
|
|
|
|
|
elif u"storage.floppy" in capabilities:
|
|
|
|
new_device = FloppyDevice()
|
|
|
|
else:
|
|
|
|
if u"storage.bus" in parsed_hash \
|
|
|
|
and self._parseString(' '.join(parsed_hash[u"storage.bus"]))==u"usb":
|
|
|
|
|
|
|
|
new_device = USBDisk()
|
|
|
|
else:
|
|
|
|
new_device = Disk()
|
|
|
|
|
|
|
|
new_device.modelname = storage_model
|
|
|
|
uid_to_disk[current_uid] = new_device
|
|
|
|
else:
|
|
|
|
# Not interesting, skip it.
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Handle the generic properties.
|
|
|
|
new_device.dev = self._parseString(' '.join(parsed_hash[u"block.device"]))
|
|
|
|
new_device.major = int(parsed_hash[u"block.major"][0])
|
|
|
|
|
|
|
|
self.devices.append(new_device)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# Keep on accumulating info about this device.
|
|
|
|
parts = line.split()
|
|
|
|
parsed_hash[ parts[0] ] = parts[2:]
|
|
|
|
|
|
|
|
# Attach the partitions to thier devices.
|
|
|
|
for partition in partition_to_uid.keys():
|
|
|
|
parent = partition_to_uid[partition]
|
|
|
|
if parent in uid_to_disk.keys():
|
|
|
|
parent_device = uid_to_disk[parent]
|
|
|
|
parent_device.appendPartition(partition)
|
|
|
|
self.devices.remove(partition)
|
|
|
|
|
|
|
|
return self.devices[:]
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
def _parseStringList(self,source_string):
|
|
|
|
STATE_TOP = 0
|
|
|
|
STATE_STRING = 1
|
|
|
|
|
|
|
|
state = STATE_TOP
|
|
|
|
current_string = ""
|
|
|
|
string_list = []
|
|
|
|
for c in source_string:
|
|
|
|
if state==STATE_TOP:
|
|
|
|
if c=='}':
|
|
|
|
break
|
|
|
|
if c=="'":
|
|
|
|
state = STATE_STRING
|
|
|
|
else:
|
|
|
|
if c=="'":
|
|
|
|
state = STATE_TOP
|
|
|
|
string_list.append(current_string)
|
|
|
|
current_string = ""
|
|
|
|
else:
|
|
|
|
current_string += c
|
|
|
|
|
|
|
|
return string_list
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
def _parseString(self,source_string):
|
|
|
|
STATE_TOP = 0
|
|
|
|
STATE_STRING = 1
|
|
|
|
|
|
|
|
state = STATE_TOP
|
|
|
|
current_string = ""
|
|
|
|
for c in source_string:
|
|
|
|
if state==STATE_TOP:
|
|
|
|
if c=="'":
|
|
|
|
state = STATE_STRING
|
|
|
|
else:
|
|
|
|
if c=="'":
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
current_string += c
|
|
|
|
return current_string
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
def formatSizeBytes(self,size):
|
|
|
|
if size<1024:
|
|
|
|
return str(size+" B")
|
|
|
|
if size<1024*1042:
|
|
|
|
return str(round(float(size)/1024.0,1))+" Kb"
|
|
|
|
size /= 1024
|
|
|
|
if size<1024*1024:
|
|
|
|
return str(round(float(size)/1024.0,1))+" Mb"
|
|
|
|
size /= 1024
|
|
|
|
if size<1024*1024:
|
|
|
|
return str(round(float(size)/1024.0,1))+" Gb"
|
|
|
|
size /= 1024
|
|
|
|
return str(round(float(size)/1024.0,1))+" Tb"
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
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()
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
def getDeviceByLabel(self, label):
|
|
|
|
for device in self.getDevices():
|
|
|
|
if device.getLabel()==label:
|
|
|
|
return device
|
|
|
|
|
|
|
|
if isinstance(device,Disk):
|
|
|
|
for partition in device.getPartitions():
|
|
|
|
if partition.getLabel()==label:
|
|
|
|
return partition
|
|
|
|
return None
|
|
|
|
|
|
|
|
def getLabelByDevice(self, device):
|
|
|
|
for item in self.getDevices():
|
|
|
|
for partition in item.partitions:
|
|
|
|
if partition.dev==device:
|
|
|
|
return partition.label
|
|
|
|
print "No Label found for ",device
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def getUUIDByDevice(self, device):
|
|
|
|
for item in self.getDevices():
|
|
|
|
for partition in item.partitions:
|
|
|
|
#print partition, partition.getUUID()
|
|
|
|
if partition.dev==device:
|
|
|
|
return partition.uuid
|
|
|
|
print "No UUID found for ",device
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def getDeviceByUUID(self, uuid):
|
|
|
|
for device in self.getDevices():
|
|
|
|
if device.getUUID()==uuid:
|
|
|
|
return device
|
|
|
|
|
|
|
|
if isinstance(device,Disk):
|
|
|
|
for partition in device.getPartitions():
|
|
|
|
if partition.getUUID()==uuid:
|
|
|
|
return partition
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
############################################################################
|
|
|
|
if __name__=='__main__':
|
|
|
|
hal = MicroHAL()
|
|
|
|
for item in hal.getDevices():
|
|
|
|
print(str(item))
|
|
|
|
|
|
|
|
print
|
|
|
|
|
|
|
|
#"""
|
|
|
|
for item in hal.getDevices():
|
|
|
|
for partition in item.partitions:
|
|
|
|
print partition, partition.getLabel()
|
|
|
|
#"""
|
|
|
|
#realhal = RealHAL()
|
|
|
|
#for item in realhal.getDevices():
|
|
|
|
# print(str(item))
|
|
|
|
|
|
|
|
print
|
|
|
|
|
|
|
|
|