import string
import os
import popen2
-from merge_hw_tables import merge_hw_tables
-
+import merge_hw_tables
+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):
"""
device= parts[3]
- # if the last char in device is a number, its
- # a partition, and we ignore it
-
- if device[len(device)-1].isdigit():
- continue
-
dev_name= "/dev/%s" % device
try:
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;
- def get_system_modules( self, install_root ):
+ def get_system_modules( self, install_root, kernel_version= None ):
"""
Return a list of kernel modules that this system requires.
This requires access to the installed system's root
directory, as the following files must exist and are used:
<install_root>/usr/share/hwdata/pcitable
- <install_root>/lib/modules/(first entry)/modules.pcimap
- <install_root>/lib/modules/(first entry)/modules.dep
+ <install_root>/lib/modules/(first entry if kernel_version unspecified)/modules.pcimap
+ <install_root>/lib/modules/(first entry if kernel version unspecified)/modules.dep
- Note, that this assumes there is only one kernel
- that is installed. If there are more than one, then
- only the first one in a directory listing is used.
+ If there are more than one kernels installed, and the kernel
+ version is not specified, then only the first one in
+ /lib/modules is used.
Returns a dictionary, keys being the type of module:
- scsi MODULE_CLASS_SCSI
"""
# get the kernel version we are assuming
- try:
- kernel_version= os.listdir( "%s/lib/modules/" % install_root )
- except OSError, e:
- return
+ if kernel_version is None:
+ try:
+ kernel_version= os.listdir( "%s/lib/modules/" % install_root )
+ except OSError, e:
+ return
- if len(kernel_version) == 0:
- return
+ if len(kernel_version) == 0:
+ return
+
+ if len(kernel_version) > 1:
+ print( "WARNING: We may be returning modules for the wrong kernel." )
- if len(kernel_version) > 1:
- print( "WARNING: We may be returning modules for the wrong kernel." )
+ kernel_version= kernel_version[0]
- kernel_version= kernel_version[0]
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
try:
classid= self.remove_quotes(parts[2])
+ classid= long(classid,16)
+ except IndexError:
+ print( "Skipping invalid classid:", string.strip(line) )
+ continue
+ except ValueError, e:
+ print( "Skipping invalid classid:", string.strip(line) )
+ continue
+
+
+ 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
+
+ vendorid = self.PCI_ANY
+ deviceid = self.PCI_ANY
+ subvendorid = self.PCI_ANY
+ subdeviceid = self.PCI_ANY
+
+ # parse in vendorid
+ try:
vendorid= self.remove_quotes(parts[3])
- deviceid= self.remove_quotes(parts[4])
+ vendorid= long(vendorid,16)
except IndexError:
- print( "Skipping invalid line:", string.strip(line) )
+ print( "Skipping invalid vendorid:", string.strip(line) )
+ continue
+ except ValueError, e:
+ print( "Skipping invalid vendorid:", string.strip(line) )
continue
- if classid not in (self.PCI_CLASS_NETWORK,
- self.PCI_CLASS_RAID,
- self.PCI_CLASS_RAID2,
- self.PCI_CLASS_IDE):
+ # parse in deviceid
+ try:
+ deviceid= self.remove_quotes(parts[4])
+ deviceid= long(deviceid,16)
+ except IndexError:
+ print( "Skipping invalid deviceid:", string.strip(line) )
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)
-
+ except ValueError, e:
+ print( "Skipping invalid deviceid:", string.strip(line) )
+ continue
+
+ # Now get the subvendor & subdevice portion by searching
+ # parts[5:] of the lspci output. Note that we have to skip
+ # the portions of the lspci output string that indicate
+ # revision info.
+
+ # parse in subvendorid
+ subvendorindex = -1
+ for i in range(5,len(parts)):
+ p = self.remove_quotes(parts[i])
+ if p[0] != '-':
+ subvendorindex = i
+ break
+
+ if subvendorindex != -1:
+ try:
+ subvendorid= self.remove_quotes(parts[subvendorindex])
+ subvendorid= long(subvendorid,16)
+ except IndexError:
+ print( "Skipping invalid line:", string.strip(line) )
+ continue
+ except ValueError, e:
+ print( "Skipping invalid line:", string.strip(line) )
+ continue
+
+ # parse in subdeviceid
+ subdeviceindex = -1
+ for i in range(subvendorindex+1,len(parts)):
+ p = self.remove_quotes(parts[i])
+ if p[0] != '-':
+ subdeviceindex = i
+ break
+ if subdeviceindex != -1:
+ error_msg = "Skipping invalid subdeviceid:"
+ try:
+ subdeviceid= self.remove_quotes(parts[subdeviceindex])
+ subdeviceid= long(subdeviceid,16)
+ except IndexError:
+ print( error_msg, string.strip(line) )
+ continue
+ except ValueError, e:
+ print( error_msg, string.strip(line) )
+ continue
+
+ # 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])
+ 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: