X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=source%2Fsysteminfo.py;h=453629413168198da109a37c4b9d4c23c97a0bcf;hb=3a3e97eb4dfb28bc17b84653ae3c4135394f32a4;hp=2f0ade6e93c3c5a6d88aecdf60f30d501dbd8ac5;hpb=694c9c9272fd30cc7016f31c1562ed2d56ac234c;p=bootmanager.git diff --git a/source/systeminfo.py b/source/systeminfo.py index 2f0ade6..4536294 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. # @@ -18,51 +18,41 @@ #3 4 18804082 hda4 #---------------------------------------------------- +from __future__ import print_function 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,28 +62,28 @@ 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) - except ValueError, e: + total_memory, units = string.split(value) + except ValueError as e: return if total_memory == "" or total_memory == None or \ @@ -104,8 +94,8 @@ def get_total_phsyical_mem(vars = {}, log = sys.stderr): return try: - total_memory= int(total_memory) - except ValueError, e: + total_memory = int(total_memory) + except ValueError as e: return break @@ -118,7 +108,7 @@ def get_block_device_list(vars = {}, log = sys.stderr): get a list of block devices from this system. return an associative array, where the device name (full /dev/device path) is the key, and the value - is a tuple of (major,minor,numblocks,gb_size,readonly) + is a tuple of (major, minor, numblocks, gb_size, readonly) """ # make sure we can access to the files/directories in /proc @@ -128,25 +118,25 @@ 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 + for M in range(0, 1+1): + for N in range(0, 7+1): + devicename = "cciss/c{}d{}".format(M, N) + 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 + devfsname = os.readlink("/dev/{}".format(devicename)) + valid_blk_names[devfsname] = None except OSError: pass @@ -160,74 +150,76 @@ 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/{} > /dev/null 2>&1".format(devicename)) # touch file - fb = open(DEVICES_SCANNED_FLAG,"w") + 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]) - except ValueError, err: + major = int(parts[0]) + minor = int(parts[1]) + blocks = int(parts[2]) + except ValueError as 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 - fb = open(dev_name,"w") + dev_name = "/dev/{}".format(device) + fb = open(dev_name, "w") fb.close() - readonly=False - except IOError, e: + readonly = False + except IOError as e: # check if EROFS errno - if errno.errorcode.get(e.errno,None) == 'EROFS': - readonly=True + if errno.errorcode.get(e.errno, None) == 'EROFS': + 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 -def get_system_modules( vars = {}, log = sys.stderr): +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 @@ -246,8 +238,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; @@ -257,176 +249,98 @@ 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 ) - except OSError, e: + kernel_version = os.listdir("{}/lib/modules/".format(SYSIMG_PATH)) + except OSError as e: return if len(kernel_version) == 0: return if len(kernel_version) > 1: - print( "WARNING: We may be returning modules for the wrong kernel." ) + 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 ) + print("Using kernel version {}".format(kernel_version)) - # test to make sure the three files we need are present - pcitable_path = "%s/%s/pcitable" % (SYSIMG_PATH,hwdatapath) - 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." ) + # test to make sure the file we need is present + modules_pcimap_path = "{}/lib/modules/{}/modules.pcimap"\ + .format(SYSIMG_PATH, kernel_version) + if not os.access(modules_pcimap_path, os.R_OK): + print("WARNING: Unable to read {}".format(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]) - - # XXX ata_piix and ahci both claim 8086:2652 and 8086:2653, - # and it is usually a non-visible BIOS option that decides - # which is appropriate. Just load both. - if vendorid == 0x8086 and (deviceid == 0x2652 or deviceid == 0x2653): - if module[0] == "ahci": - scsi_mods.append("ata_piix") - elif module[0] == "ata_piix": - scsi_mods.append("ahci") - 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 -def getKernelVersion( 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" + raise ValueError("SYSIMG_PATH") - NODE_MODEL_OPTIONS=vars["NODE_MODEL_OPTIONS"] - except KeyError, var: - raise BootManagerException, "Missing variable in vars: %s\n" % var - except ValueError, var: - raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var + NODE_MODEL_OPTIONS = vars["NODE_MODEL_OPTIONS"] + except KeyError as var: + raise BootManagerException("Missing variable in vars: {}\n".format(var)) + except ValueError as var: + raise BootManagerException("Variable in vars, shouldn't be: {}\n".format(var)) option = '' if NODE_MODEL_OPTIONS & ModelOptions.SMP: option = 'smp' try: - os.stat("%s/boot/kernel-boot%s" % (SYSIMG_PATH,option)) - os.stat("%s/boot/initrd-boot%s" % (SYSIMG_PATH,option)) - except OSError, e: + os.stat("{}/boot/kernel-boot{}".format(SYSIMG_PATH, option)) + os.stat("{}/boot/initrd-boot{}".format(SYSIMG_PATH, option)) + except OSError as e: # smp kernel is not there; remove option from modeloptions # such that the rest of the code base thinks we are just # using the base kernel. NODE_MODEL_OPTIONS = NODE_MODEL_OPTIONS & ~ModelOptions.SMP vars["NODE_MODEL_OPTIONS"] = NODE_MODEL_OPTIONS - log.write( "WARNING: Couldn't locate smp kernel.\n") + 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", "") - except OSError, e: + initrd = os.readlink("{}/boot/initrd-boot{}".format(SYSIMG_PATH, option)) + kernel_version = initrd.replace("initrd-", "").replace(".img", "") + except OSError as e: initrd = None kernel_version = None @@ -434,40 +348,37 @@ def getKernelVersion( vars = {} , log = sys.stderr): if __name__ == "__main__": - devices= get_block_device_list() - print "block devices detected:" + devices = get_block_device_list() + print("block devices detected:") if not devices: - print "no devices found!" + print("no devices found!") else: for dev in devices.keys(): - print "%s %s" % (dev, repr(devices[dev])) + print("{} {}".format(dev, repr(devices[dev]))) - print "" - memory= get_total_phsyical_mem() + print("") + memory = get_total_phsyical_mem() if not memory: - print "unable to read /proc/meminfo for memory" + print("unable to read /proc/meminfo for memory") else: - print "total physical memory: %d kb" % memory + print("total physical memory: {} kb".format(memory)) - print "" + print("") kernel_version = None 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" + 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 + "{} ".format(a_mod) + print("all {} modules: {}".format(module_class, module_list))