X-Git-Url: http://git.onelab.eu/?p=myops.git;a=blobdiff_plain;f=web%2Fcollect%2Fclient%2Fsysinfo%2Fsysteminfo.py;fp=web%2Fcollect%2Fclient%2Fsysinfo%2Fsysteminfo.py;h=1e6caa76dcca52715f928518a8b10098d2e2330a;hp=0000000000000000000000000000000000000000;hb=85070b3d456667f238051af1a2f1f2a0c12300ab;hpb=607f0e13927eb18075c375fa9ba5527da4fcbb44 diff --git a/web/collect/client/sysinfo/systeminfo.py b/web/collect/client/sysinfo/systeminfo.py new file mode 100755 index 0000000..1e6caa7 --- /dev/null +++ b/web/collect/client/sysinfo/systeminfo.py @@ -0,0 +1,380 @@ +#!/usr/bin/python + +# Copyright (c) 2003 Intel Corporation +# All rights reserved. +# +# Copyright (c) 2004-2006 The Trustees of Princeton University +# All rights reserved. +# expected /proc/partitions format + + +#---------------------------------------------------- +#major minor #blocks name +# +#3 0 40017915 hda +#3 1 208813 hda1 +#3 2 20482875 hda2 +#3 3 522112 hda3 +#3 4 18804082 hda4 +#---------------------------------------------------- + + +import string +import sys +import os +import popen2 +import re +import errno +import ModelOptions +from pypci import * +from Exceptions import * + +""" +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" + +# set when the sfdisk -l trick has been done to make +# all devices show up +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; + + +MODULE_CLASS_NETWORK= "network" +MODULE_CLASS_SCSI= "scsi" + +#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): + """ + return the total physical memory of the machine, in kilobytes. + + Return None if /proc/meminfo not readable. + """ + + try: + meminfo_file= file(PROC_MEMINFO_PATH,"r") + except IOError, e: + return + + total_memory= None + + for line in meminfo_file: + + try: + (fieldname,value)= string.split(line,":") + except ValueError, 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) + + if fieldname == "MemTotal": + try: + (total_memory,units)= string.split(value) + except ValueError, e: + return + + if total_memory == "" or total_memory == None or \ + units == "" or units == None: + return + + if string.lower(units) != "kb": + return + + try: + total_memory= int(total_memory) + except ValueError, e: + return + + break + + meminfo_file.close() + return total_memory + +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) + """ + + # make sure we can access to the files/directories in /proc + if not os.access(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 + + 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): + + # this is ugly. under devfs, device + # entries in /dev/scsi/.. and /dev/ide/... + # don't show up until you attempt to read + # from the associated device at /dev (/dev/sda). + # 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. + devicenames = valid_blk_names.keys() + devicenames.sort() + for devicename in devicenames: + os.system( "sfdisk -l /dev/%s > /dev/null 2>&1" % devicename ) + + # touch file + fb = open(DEVICES_SCANNED_FLAG,"w") + fb.close() + + devicelist= {} + + partitions_file= file(PROC_PARTITIONS_PATH,"r") + line_count= 0 + for line in partitions_file: + line_count= line_count + 1 + + # skip the first two lines always + if line_count < 2: + continue + + parts= string.split(line) + + if len(parts) < 4: + continue + + 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: + continue + + 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") + 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 + + +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 file must exist and is used: + /lib/modules/(first entry if kernel_version unspecified)/modules.pcimap + + 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 + - network MODULE_CLASS_NETWORK + The value being the kernel module name to load. + + Some sata devices show up under an IDE device class, + hence the reason for checking for ide devices as well. + If there actually is a match in the pci -> module lookup + table, and its an ide device, its most likely sata, + as ide modules are built in to the kernel. + """ + + if not vars.has_key("SYSIMG_PATH"): + vars["SYSIMG_PATH"]="/" + SYSIMG_PATH=vars["SYSIMG_PATH"] + + if not vars.has_key("NODE_MODEL_OPTIONS"): + vars["NODE_MODEL_OPTIONS"] = 0; + + initrd, kernel_version = getKernelVersion(vars, log) + + # 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: + return + + if len(kernel_version) == 0: + return + + if len(kernel_version) > 1: + print( "WARNING: We may be returning modules for the wrong kernel." ) + + kernel_version= kernel_version[0] + + print( "Using kernel version %s" % kernel_version ) + + # test to make sure the file we need is present + modules_pcimap_path = "%s/lib/modules/%s/modules.pcimap" % \ + (SYSIMG_PATH,kernel_version) + 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= {} + + # these are the lists that will be in system_mods + 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 len(modules) > 0: + if base == PCI_BASE_CLASS_NETWORK: + network_mods += modules + elif base == PCI_BASE_CLASS_STORAGE: + scsi_mods += modules + + system_mods[MODULE_CLASS_SCSI]= scsi_mods + system_mods[MODULE_CLASS_NETWORK]= network_mods + + return system_mods + + +def getKernelVersion( vars = {} , log = sys.stderr): + # make sure we have the variables we need + try: + SYSIMG_PATH= vars["SYSIMG_PATH"] + if 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 + + 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: + # 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") + option = '' + try: + 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 + + return (initrd, kernel_version) + + +if __name__ == "__main__": + devices= get_block_device_list() + #print "block devices detected:" + if not devices: + print "no devices found!" + else: + for dev in devices.keys(): + #print "%s %s" % (dev, repr(devices[dev])) + print "%s %s" % (repr(devices[dev][3]), dev) + + + #print "" + #memory= get_total_phsyical_mem() + #if not memory: + # print "unable to read /proc/meminfo for memory" + #else: + # print "total physical memory: %d kb" % memory + + + #print "" + + #kernel_version = None + #if len(sys.argv) > 2: + # kernel_version = sys.argv[1] + # + #modules= get_system_modules() + #if not modules: + # print "unable to list system modules" + #else: + # 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) +