X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=source%2Fsysteminfo.py;h=a0de77718cfa683f498a43aad1ebb599d1736cec;hb=26dac01fdb602d0c0db3cac2e7c822e197c6d5c7;hp=23b43437395d543c6f797d12a3eca7c2601d2fb6;hpb=6ff7465d1b582b171ebf6d34b1f43c1b98cdacb8;p=bootmanager.git diff --git a/source/systeminfo.py b/source/systeminfo.py index 23b4343..a0de777 100755 --- a/source/systeminfo.py +++ b/source/systeminfo.py @@ -1,5 +1,5 @@ -#!/usr/bin/python2 - +#!/usr/bin/python +# # Copyright (c) 2003 Intel Corporation # All rights reserved. # @@ -23,46 +23,35 @@ import string import sys import os import popen2 -import merge_hw_tables import re import errno import ModelOptions +from pypci import * from Exceptions import * -hwdatapath = "usr/share/hwdata" """ a utility class for finding and returning information about block devices, memory, and other hardware on the system """ -PROC_MEMINFO_PATH= "/proc/meminfo" -PROC_PARTITIONS_PATH= "/proc/partitions" +PROC_MEMINFO_PATH = "/proc/meminfo" +PROC_PARTITIONS_PATH = "/proc/partitions" # set when the sfdisk -l trick has been done to make # all devices show up -DEVICES_SCANNED_FLAG= "/tmp/devices_scanned" +DEVICES_SCANNED_FLAG = "/tmp/devices_scanned" # a /proc/partitions block is 1024 bytes # a GB to a HDD manufacturer is 10^9 bytes BLOCKS_PER_GB = pow(10, 9) / 1024.0; -# -n is numeric ids (no lookup), -m is machine readable -LSPCI_CMD= "/sbin/lspci -nm" - -MODULE_CLASS_NETWORK= "network" -MODULE_CLASS_SCSI= "scsi" +MODULE_CLASS_NETWORK = "network" +MODULE_CLASS_SCSI = "scsi" -PCI_CLASS_NETWORK_ETHERNET=0x0200L -PCI_CLASS_STORAGE_SCSI=0x0100L -PCI_CLASS_STORAGE_SATA=0x0106L -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 +#PCI_* is now defined in the pypci modules +#PCI_BASE_CLASS_NETWORK = 0x02L +#PCI_BASE_CLASS_STORAGE = 0x01L def get_total_phsyical_mem(vars = {}, log = sys.stderr): """ @@ -72,27 +61,27 @@ def get_total_phsyical_mem(vars = {}, log = sys.stderr): """ try: - meminfo_file= file(PROC_MEMINFO_PATH,"r") - except IOError, e: + meminfo_file = file(PROC_MEMINFO_PATH,"r") + except IOError as e: return - total_memory= None + total_memory = None for line in meminfo_file: try: - (fieldname,value)= string.split(line,":") - except ValueError, e: + (fieldname,value) = string.split(line,":") + except ValueError as e: # this will happen for lines that don't have two values # (like the first line on 2.4 kernels) continue - fieldname= string.strip(fieldname) - value= string.strip(value) + fieldname = string.strip(fieldname) + value = string.strip(value) if fieldname == "MemTotal": try: - (total_memory,units)= string.split(value) + total_memory, units = string.split(value) except ValueError, e: return @@ -104,7 +93,7 @@ def get_total_phsyical_mem(vars = {}, log = sys.stderr): return try: - total_memory= int(total_memory) + total_memory = int(total_memory) except ValueError, e: return @@ -128,17 +117,27 @@ def get_block_device_list(vars = {}, log = sys.stderr): # 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 + # also check for vd (virtio devices used with kvm) + for blk_prefix in ('sd','hd','vd'): + for blk_num in string.ascii_lowercase: + devicename = "{}{}".format(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 + valid_blk_names[devicename] = None + + for devicename in valid_blk_names.keys(): + # devfs under 2.4 (old boot cds) used to list partitions + # in a format such as scsi/host0/bus0/target0/lun0/disc + # and /dev/sda, etc. were just symlinks + try: + devfsname = os.readlink( "/dev/%s" % devicename ) + valid_blk_names[devfsname] = None + except OSError: + pass # only do this once every system boot if not os.access(DEVICES_SCANNED_FLAG, os.R_OK): @@ -150,62 +149,66 @@ def get_block_device_list(vars = {}, log = sys.stderr): # 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. + + # 27.6.2012 - Using parted instead of sfdisk, assuming + # that doing so respects the behavior mentioned above. + devicenames = valid_blk_names.keys() devicenames.sort() for devicename in devicenames: - os.system( "sfdisk -l /dev/%s > /dev/null 2>&1" % devicename ) + os.system( "parted --script --list /dev/%s > /dev/null 2>&1" % devicename ) # touch file fb = open(DEVICES_SCANNED_FLAG,"w") fb.close() - devicelist= {} + devicelist = {} - partitions_file= file(PROC_PARTITIONS_PATH,"r") - line_count= 0 + partitions_file = file(PROC_PARTITIONS_PATH,"r") + line_count = 0 for line in partitions_file: - line_count= line_count + 1 + line_count = line_count + 1 # skip the first two lines always if line_count < 2: continue - parts= string.split(line) + parts = string.split(line) if len(parts) < 4: continue - device= parts[3] + device = parts[3] # skip and ignore any partitions if not valid_blk_names.has_key(device): continue try: - major= int(parts[0]) - minor= int(parts[1]) - blocks= int(parts[2]) + major = int(parts[0]) + minor = int(parts[1]) + blocks = int(parts[2]) except ValueError, err: continue - gb_size= blocks/BLOCKS_PER_GB + gb_size = blocks/BLOCKS_PER_GB # check to see if the blk device is readonly try: # can we write to it? - dev_name= "/dev/%s" % device + dev_name = "/dev/%s" % device fb = open(dev_name,"w") fb.close() - readonly=False + readonly = False except IOError, e: # check if EROFS errno if errno.errorcode.get(e.errno,None) == 'EROFS': - readonly=True + readonly = True else: # got some other errno, pretend device is readonly - readonly=True + readonly = True - devicelist[dev_name]= (major,minor,blocks,gb_size,readonly) + devicelist[dev_name] = (major,minor,blocks,gb_size,readonly) return devicelist @@ -214,10 +217,8 @@ def get_system_modules( vars = {}, log = sys.stderr): """ 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: - /usr/share/hwdata/pcitable + directory, as the following file must exist and is used: /lib/modules/(first entry if kernel_version unspecified)/modules.pcimap - /lib/modules/(first entry if kernel version unspecified)/modules.dep If there are more than one kernels installed, and the kernel version is not specified, then only the first one in @@ -236,8 +237,8 @@ def get_system_modules( vars = {}, log = sys.stderr): """ if not vars.has_key("SYSIMG_PATH"): - vars["SYSIMG_PATH"]="/" - SYSIMG_PATH=vars["SYSIMG_PATH"] + vars["SYSIMG_PATH"] = "/" + SYSIMG_PATH = vars["SYSIMG_PATH"] if not vars.has_key("NODE_MODEL_OPTIONS"): vars["NODE_MODEL_OPTIONS"] = 0; @@ -247,7 +248,7 @@ def get_system_modules( vars = {}, log = sys.stderr): # get the kernel version we are assuming if kernel_version is None: try: - kernel_version= os.listdir( "%s/lib/modules/" % SYSIMG_PATH ) + kernel_version = os.listdir( "%s/lib/modules/" % SYSIMG_PATH ) except OSError, e: return @@ -257,122 +258,53 @@ def get_system_modules( vars = {}, log = sys.stderr): 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/%s/pcitable" % (SYSIMG_PATH,hwdatapath) + # test to make sure the file we need is present modules_pcimap_path = "%s/lib/modules/%s/modules.pcimap" % \ (SYSIMG_PATH,kernel_version) - modules_dep_path = "%s/lib/modules/%s/modules.dep" % \ - (SYSIMG_PATH,kernel_version) - - for path in (pcitable_path,modules_pcimap_path,modules_dep_path): - if not os.access(path,os.R_OK): - print( "Unable to read %s" % path ) - return - - # now, with those three files, merge them all into one easy to - # use lookup table - (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." ) + if not os.access(modules_pcimap_path,os.R_OK): + print( "WARNING: Unable to read %s" % modules_pcimap_path ) return + pcimap = pypcimap.PCIMap(modules_pcimap_path) + # this is the actual data structure we return - system_mods= {} + system_mods = {} # these are the lists that will be in system_mods - network_mods= [] - scsi_mods= [] - - - # get all the system devices from lspci - lspci_prog= popen2.Popen3( LSPCI_CMD, 1 ) - if lspci_prog is None: - print( "Unable to run %s with popen2.Popen3" % LSPCI_CMD ) - return - - returncode= lspci_prog.wait() - if returncode != 0: - print( "Running %s failed" % LSPCI_CMD ) - return - else: - print( "Successfully ran %s" % 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: - # 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: - 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 + network_mods = [] + scsi_mods = [] + + # XXX: this is really similar to what BootCD/conf_files/pl_hwinit does. merge? + pcidevs = get_devices() + + devlist =pcidevs.keys() + devlist.sort() + for slot in devlist: + dev = pcidevs[slot] + base = (dev[4] & 0xff0000) >> 16 + modules = pcimap.get(dev) + if base not in (PCI_BASE_CLASS_STORAGE, + PCI_BASE_CLASS_NETWORK): + # special exception for forcedeth NICs whose base id + # claims to be a Bridge, even though it is clearly a + # network device + if "forcedeth" in modules: + base = PCI_BASE_CLASS_NETWORK + else: + continue - if classid not in (PCI_CLASS_NETWORK_ETHERNET, - PCI_CLASS_STORAGE_SCSI, - PCI_CLASS_STORAGE_SATA, - PCI_CLASS_STORAGE_RAID, - PCI_CLASS_STORAGE_OTHER, - PCI_CLASS_STORAGE_IDE): - continue + if len(modules) > 0: + if base == PCI_BASE_CLASS_NETWORK: + network_mods += modules + elif base == PCI_BASE_CLASS_STORAGE: + scsi_mods += modules - # Device may have a subvendorid and subdeviceid - try: - subvendorid = long(parts[4], 16) - subdeviceid = long(parts[5], 16) - except: - subvendorid = PCI_ANY - subdeviceid = 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,PCI_ANY), - (vendorid,deviceid,PCI_ANY,PCI_ANY)) - - for full_id in full_ids: - module = all_pci_ids.get(full_id, None) - if module is not None: - if classid == PCI_CLASS_NETWORK_ETHERNET: - network_mods.append(module[0]) - elif classid in (PCI_CLASS_STORAGE_SCSI, - PCI_CLASS_STORAGE_SATA, - PCI_CLASS_STORAGE_RAID, - PCI_CLASS_STORAGE_OTHER, - PCI_CLASS_STORAGE_IDE): - scsi_mods.append(module[0]) - else: - print "not network or scsi: 0x%x" % classid - break - - system_mods[MODULE_CLASS_SCSI]= scsi_mods - system_mods[MODULE_CLASS_NETWORK]= network_mods + system_mods[MODULE_CLASS_SCSI] = scsi_mods + system_mods[MODULE_CLASS_NETWORK] = network_mods return system_mods @@ -380,11 +312,11 @@ def get_system_modules( vars = {}, log = sys.stderr): def getKernelVersion( vars = {} , log = sys.stderr): # make sure we have the variables we need try: - SYSIMG_PATH= vars["SYSIMG_PATH"] + SYSIMG_PATH = vars["SYSIMG_PATH"] if SYSIMG_PATH == "": raise ValueError, "SYSIMG_PATH" - NODE_MODEL_OPTIONS=vars["NODE_MODEL_OPTIONS"] + NODE_MODEL_OPTIONS = vars["NODE_MODEL_OPTIONS"] except KeyError, var: raise BootManagerException, "Missing variable in vars: %s\n" % var except ValueError, var: @@ -405,8 +337,8 @@ def getKernelVersion( vars = {} , log = sys.stderr): log.write( "WARNING: Couldn't locate smp kernel.\n") option = '' try: - initrd= os.readlink( "%s/boot/initrd-boot%s" % (SYSIMG_PATH,option) ) - kernel_version= initrd.replace("initrd-", "").replace(".img", "") + initrd = os.readlink( "%s/boot/initrd-boot%s" % (SYSIMG_PATH,option) ) + kernel_version = initrd.replace("initrd-", "").replace(".img", "") except OSError, e: initrd = None kernel_version = None @@ -415,7 +347,7 @@ def getKernelVersion( vars = {} , log = sys.stderr): if __name__ == "__main__": - devices= get_block_device_list() + devices = get_block_device_list() print "block devices detected:" if not devices: print "no devices found!" @@ -425,7 +357,7 @@ if __name__ == "__main__": print "" - memory= get_total_phsyical_mem() + memory = get_total_phsyical_mem() if not memory: print "unable to read /proc/meminfo for memory" else: @@ -438,17 +370,14 @@ if __name__ == "__main__": if len(sys.argv) > 2: kernel_version = sys.argv[1] - modules= get_system_modules() + modules = get_system_modules() if not modules: print "unable to list system modules" else: - for type in modules: - if type == MODULE_CLASS_SCSI: - print( "all scsi modules:" ) - for a_mod in modules[type]: - print a_mod - elif type == MODULE_CLASS_NETWORK: - print( "all network modules:" ) - for a_mod in modules[type]: - print a_mod + for module_class in (MODULE_CLASS_SCSI,MODULE_CLASS_NETWORK): + if len(modules[module_class]) > 0: + module_list = "" + for a_mod in modules[module_class]: + module_list = module_list + "%s " % a_mod + print "all %s modules: %s" % (module_class, module_list)