import string
import os
import popen2
-from merge_hw_tables import merge_hw_tables
-
+import merge_hw_tables
+import re
+import errno
+hwdatapath = "usr/share/hwdata"
class systeminfo:
"""
a utility class for finding and returning information about
MODULE_CLASS_NETWORK= "network"
MODULE_CLASS_SCSI= "scsi"
- PCI_CLASS_NETWORK= "0200"
- PCI_CLASS_RAID= "0104"
- PCI_CLASS_RAID2= "0100"
- PCI_CLASS_IDE= "0101"
+ PCI_CLASS_NETWORK_ETHERNET=0x0200L
+ PCI_CLASS_STORAGE_SCSI=0x0100L
+ PCI_CLASS_STORAGE_IDE=0x0101L
+ PCI_CLASS_STORAGE_FLOPPY=0x0102L
+ PCI_CLASS_STORAGE_IPI=0x0103L
+ PCI_CLASS_STORAGE_RAID=0x0104L
+ PCI_CLASS_STORAGE_OTHER=0x0180L
+
+ PCI_ANY=0xffffffffL
def get_total_phsyical_mem(self):
"""
if not os.access(self.PROC_PARTITIONS_PATH, os.F_OK):
return None
+ # table with valid scsi/sata/ide/raid block device names
+ valid_blk_names = {}
+ # add in valid sd and hd block device names
+ for blk_prefix in ('sd','hd'):
+ for blk_num in map ( \
+ lambda x: chr(x), range(ord('a'),ord('z')+1)):
+ devicename="%s%c" % (blk_prefix, blk_num)
+ valid_blk_names[devicename]=None
+
+ # add in valid scsi raid block device names
+ for M in range(0,1+1):
+ for N in range(0,7+1):
+ devicename = "cciss/c%dd%d" % (M,N)
+ valid_blk_names[devicename]=None
# only do this once every system boot
if not os.access(self.DEVICES_SCANNED_FLAG, os.R_OK):
# so, lets run sfdisk -l (list partitions) against
# most possible block devices, that way they show
# up when it comes time to do the install.
- for dev_prefix in ('sd','hd'):
- block_dev_num= 0
- while block_dev_num < 10:
- if block_dev_num < 26:
- devicename= "/dev/%s%c" % \
- (dev_prefix, chr(ord('a')+block_dev_num))
- else:
- devicename= "/dev/%s%c%c" % \
- ( dev_prefix,
- chr(ord('a')+((block_dev_num/26)-1)),
- chr(ord('a')+(block_dev_num%26)) )
-
- os.system( "sfdisk -l %s > /dev/null 2>&1" % devicename )
- block_dev_num = block_dev_num + 1
-
- additional_scan_devices= ("/dev/cciss/c0d0p", "/dev/cciss/c0d1p",
- "/dev/cciss/c0d2p", "/dev/cciss/c0d3p",
- "/dev/cciss/c0d4p", "/dev/cciss/c0d5p",
- "/dev/cciss/c0d6p", "/dev/cciss/c0d7p",
- "/dev/cciss/c1d0p", "/dev/cciss/c1d1p",
- "/dev/cciss/c1d2p", "/dev/cciss/c1d3p",
- "/dev/cciss/c1d4p", "/dev/cciss/c1d5p",
- "/dev/cciss/c1d6p", "/dev/cciss/c1d7p",)
-
- for devicename in additional_scan_devices:
- os.system( "sfdisk -l %s > /dev/null 2>&1" % devicename )
+ devicenames = valid_blk_names.keys()
+ devicenames.sort()
+ for devicename in devicenames:
+ os.system( "sfdisk -l /dev/%s > /dev/null 2>&1" % devicename )
- os.system( "touch %s" % self.DEVICES_SCANNED_FLAG )
-
+ # touch file
+ fb = open(self.DEVICES_SCANNED_FLAG,"w")
+ fb.close()
devicelist= {}
partitions_file= file(self.PROC_PARTITIONS_PATH,"r")
line_count= 0
-
for line in partitions_file:
line_count= line_count + 1
continue
device= parts[3]
-
- dev_name= "/dev/%s" % device
+ # skip and ignore any partitions
+ if not valid_blk_names.has_key(device):
+ continue
+
try:
major= int(parts[0])
minor= int(parts[1])
except ValueError, err:
continue
- # skip and ignore any partitions
- if minor != 0:
- continue
-
gb_size= blocks/self.BLOCKS_PER_GB
- # parse the output of hdparm <disk> to get the readonly flag;
- # if this fails, assume it isn't read only
- readonly= 0
-
- hdparm_cmd = popen2.Popen3("hdparm %s 2> /dev/null" % dev_name)
- status= hdparm_cmd.wait()
-
- if os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0:
- try:
- hdparm_output= hdparm_cmd.fromchild.read()
- hdparm_cmd= None
-
- # parse the output of hdparm, the lines we are interested
- # in look
- # like:
- #
- # readonly = 0 (off)
- #
-
- for line in string.split(hdparm_output,"\n"):
-
- line= string.strip(line)
- if line == "":
- continue
-
- line_parts= string.split(line,"=")
- if len(line_parts) < 2:
- continue
-
- name= string.strip(line_parts[0])
-
- if name == "readonly":
- value= string.strip(line_parts[1])
- if len(value) == 0:
- break
-
- if value[0] == "1":
- readonly= 1
- break
-
- except IOError:
- pass
+ # check to see if the blk device is readonly
+ try:
+ # can we write to it?
+ dev_name= "/dev/%s" % device
+ fb = open(dev_name,"w")
+ fb.close()
+ readonly=False
+ except IOError, e:
+ # check if EROFS errno
+ if errno.errorcode.get(e.errno,None) == 'EROFS':
+ readonly=True
+ else:
+ # got some other errno, pretend device is readonly
+ readonly=True
devicelist[dev_name]= (major,minor,blocks,gb_size,readonly)
-
return devicelist
print( "Using kernel version %s" % kernel_version )
# test to make sure the three files we need are present
- pcitable_path = "%s/usr/share/hwdata/pcitable" % install_root
+ pcitable_path = "%s/%s/pcitable" % (install_root,hwdatapath)
modules_pcimap_path = "%s/lib/modules/%s/modules.pcimap" % \
(install_root,kernel_version)
modules_dep_path = "%s/lib/modules/%s/modules.dep" % \
# now, with those three files, merge them all into one easy to
# use lookup table
- all_modules= merge_hw_tables().merge_files( modules_dep_path,
- modules_pcimap_path,
- pcitable_path )
-
+ (all_pci_ids, all_modules) = merge_hw_tables.merge_files( modules_dep_path,
+ modules_pcimap_path,
+ pcitable_path )
if all_modules is None:
print( "Unable to merge pci id tables." )
return
-
# this is the actual data structure we return
system_mods= {}
else:
print( "Successfully ran %s" % self.LSPCI_CMD )
+ # for every lspci line, parse in the four tuple PCI id and the
+ # search for the corresponding driver from the dictionary
+ # generated by merge_hw_tables
for line in lspci_prog.fromchild:
- if string.strip(line) == "":
- continue
-
- parts= string.split(line)
-
+ # A sample line:
+ #
+ # 00:1f.1 "Class 0101" "8086" "2411" -r02 -p80 "8086" "2411"
+ #
+ # Remove '"', 'Class ', and anything beginning with '-'
+ # (usually revisions and prog-if flags) so that we can
+ # split on whitespace:
+ #
+ # 00:1f.1 0101 8086 2411 8086 2411
+ #
+ line = line.strip()
+ line = line.replace('"', '')
+ line = line.replace('Class ', '')
+ line = re.sub('-[^ ]*', '', line)
+
+ parts = line.split()
try:
- classid= self.remove_quotes(parts[2])
- vendorid= self.remove_quotes(parts[3])
- deviceid= self.remove_quotes(parts[4])
- except IndexError:
- print( "Skipping invalid line:", string.strip(line) )
+ if len(parts) < 4:
+ raise
+ classid = long(parts[1], 16)
+ vendorid = long(parts[2], 16)
+ deviceid = long(parts[3], 16)
+ except:
+ print "Invalid line:", line
continue
- if classid not in (self.PCI_CLASS_NETWORK,
- self.PCI_CLASS_RAID,
- self.PCI_CLASS_RAID2,
- self.PCI_CLASS_IDE):
+ if classid not in (self.PCI_CLASS_NETWORK_ETHERNET,
+ self.PCI_CLASS_STORAGE_SCSI,
+ self.PCI_CLASS_STORAGE_RAID,
+ self.PCI_CLASS_STORAGE_OTHER,
+ self.PCI_CLASS_STORAGE_IDE):
continue
-
- full_deviceid= "%s:%s" % (vendorid,deviceid)
-
- for module in all_modules.keys():
- if full_deviceid in all_modules[module]:
- if classid == self.PCI_CLASS_NETWORK:
- network_mods.append(module)
- elif classid in (self.PCI_CLASS_RAID,
- self.PCI_CLASS_RAID2,
- self.PCI_CLASS_IDE):
- scsi_mods.append(module)
-
+
+ # Device may have a subvendorid and subdeviceid
+ try:
+ subvendorid = long(parts[4], 16)
+ subdeviceid = long(parts[5], 16)
+ except:
+ subvendorid = self.PCI_ANY
+ subdeviceid = self.PCI_ANY
+
+ # search for driver that most closely matches the full_id
+ # to drivers that can handle any subvendor/subdevice
+ # version of the hardware.
+ full_ids = ((vendorid,deviceid,subvendorid,subdeviceid),
+ (vendorid,deviceid,subvendorid,self.PCI_ANY),
+ (vendorid,deviceid,self.PCI_ANY,self.PCI_ANY))
+
+ for full_id in full_ids:
+ module = all_pci_ids.get(full_id, None)
+ if module is not None:
+ if classid == self.PCI_CLASS_NETWORK_ETHERNET:
+ network_mods.append(module[0])
+ elif classid in (self.PCI_CLASS_STORAGE_SCSI,
+ self.PCI_CLASS_STORAGE_RAID,
+ self.PCI_CLASS_STORAGE_OTHER,
+ self.PCI_CLASS_STORAGE_IDE):
+ scsi_mods.append(module[0])
+ else:
+ print "not network or scsi: 0x%x" % classid
+ break
+
system_mods[self.MODULE_CLASS_SCSI]= scsi_mods
system_mods[self.MODULE_CLASS_NETWORK]= network_mods
print ""
- modules= info.get_system_modules("/")
+
+ import sys
+ kernel_version = None
+ if len(sys.argv) > 2:
+ kernel_version = sys.argv[1]
+
+ modules= info.get_system_modules("/",kernel_version)
if not modules:
print "unable to list system modules"
else: