#!/usr/bin/python2
-
+#
# Copyright (c) 2003 Intel Corporation
# All rights reserved.
#
#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 <dev> 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):
"""
"""
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 \
return
try:
- total_memory= int(total_memory)
- except ValueError, e:
+ total_memory = int(total_memory)
+ except ValueError as e:
return
break
meminfo_file.close()
return total_memory
-def get_block_device_list(vars = {}, log = sys.stderr):
+def get_block_devices_dict(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
# 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/{}".format(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):
# 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:
- <install_root>/usr/share/hwdata/pcitable
+ directory, as the following file must exist and is used:
<install_root>/lib/modules/(first entry if kernel_version unspecified)/modules.pcimap
- <install_root>/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
"""
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;
# 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." )
-
- kernel_version= kernel_version[0]
+ print("WARNING: We may be returning modules for the wrong kernel.")
- print( "Using kernel version %s" % kernel_version )
+ kernel_version = kernel_version[0]
- # 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)
+ print("Using kernel version {}".format(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])
- 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
if __name__ == "__main__":
- devices= get_block_device_list()
- print "block devices detected:"
+ devices = get_block_devices_dict()
+ 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))