diff options
author | ccb <ccb> | 2003-06-02 20:35:53 +0000 |
---|---|---|
committer | ccb <ccb> | 2003-06-02 20:35:53 +0000 |
commit | ed4bab31e1eb27130c12fc0b0079648d92de12f6 (patch) | |
tree | 83039631a97f9a99f083309f8dc272b67597f934 | |
parent | ddc4cdc27127ca67c4cc138fa49bcecf5934b75b (diff) | |
download | initscripts-ed4bab31e1eb27130c12fc0b0079648d92de12f6.tar initscripts-ed4bab31e1eb27130c12fc0b0079648d92de12f6.tar.gz initscripts-ed4bab31e1eb27130c12fc0b0079648d92de12f6.tar.bz2 initscripts-ed4bab31e1eb27130c12fc0b0079648d92de12f6.tar.xz initscripts-ed4bab31e1eb27130c12fc0b0079648d92de12f6.zip |
Add support level checking.
-rw-r--r-- | Makefile | 1 | ||||
-rwxr-xr-x | rc.d/rc.sysinit | 5 | ||||
-rw-r--r-- | redhat-support-check.py | 551 |
3 files changed, 557 insertions, 0 deletions
@@ -16,6 +16,7 @@ install: mkdir -p $(ROOT)/etc/profile.d $(ROOT)/sbin $(ROOT)/usr/sbin mkdir -p $(ROOT)$(mandir)/man8 + install -m755 redhat-support-check.py $(ROOT)/sbin/redhat-support-check install -m644 inittab adjtime $(ROOT)/etc if uname -m | grep -q s390 ; then \ install -m644 inittab.s390 $(ROOT)/etc/inittab ; \ diff --git a/rc.d/rc.sysinit b/rc.d/rc.sysinit index e7a5dd51..ffc4f532 100755 --- a/rc.d/rc.sysinit +++ b/rc.d/rc.sysinit @@ -809,3 +809,8 @@ if [ "$PROMPT" != "no" ]; then /sbin/getkey i && touch /var/run/confirm fi wait + +[ $(/bin/uname -p) == "i686" ] && + [ -x /sbin/redhat-support-check ] && + [ -f /var/lib/supportinfo ] && + /sbin/redhat-support-check diff --git a/redhat-support-check.py b/redhat-support-check.py new file mode 100644 index 00000000..def27bd9 --- /dev/null +++ b/redhat-support-check.py @@ -0,0 +1,551 @@ +#!/usr/bin/python +# +# Red Hat Enterprise Linux support level checker +# + +import re +import sys +import time +from syslog import syslog, openlog + +true, false = (1, 0) + +# CPUInfo - visible class from this package +# acts as a container for the existing cpus + +class CPUInfo: + + class CPU: + def __init__(self, procnum): + self.procnum = procnum + self.smp = false + + def __repr__(self): + out = "" + out += "processor\t: %s\n" % self.procnum + out += "vendor\t\t: %s\n" % self.vendor + out += "cpu family\t: %s\n" % self.family + out += "model\t\t: %s\n" % self.model + out += "model name\t: %s\n" % self.modelName + out += "stepping\t: %s\n" % self.stepping + out += "cpu MHz\t\t: %s\n" % self.MHz + out += "cache size\t: %s %s\n" % ( + self.cacheSize, self.cacheUnit) + if self.smp: + out += "physical id\t: %s\n" % self.physicalID + out += "siblings\t: %s\n" % self.siblings + + out += "fdiv_bug\t: %s\n" % self.fdivBug + out += "hlt_bug\t\t: %s\n" % self.hltBug + out += "f00f_bug\t: %s\n" % self.f00fBug + out += "coma_bug\t: %s\n" % self.comaBug + out += "fpu\t\t: %s\n" % self.fpu + out += "fpu_exception\t: %s\n" % self.fpuException + out += "cpuid level\t: %s\n" % self.CPUIDLevel + out += "wp\t\t: %s\n" % self.wp + out += "flags\t\t: %s\n" % self.flags + out += "bogomips\t: %s\n" % self.bogoMips + return out + + # END Class CPU + + def __init__(self): + self.cpus = {} + self.ncpu = 0; + self.physCPU = 0; + + f = open("/proc/cpuinfo"); + l = f.readlines() + f.close() + + havecpu = 0 + + for s in l: + + ms = re.match( r'^$', s ); + if ms: continue + + ms = re.match( r'^processor\s+:\s+(\d+).*$', s ) + if ms: + procnum = int(ms.group(1)) + curcpu = self.cpus[procnum] = self.CPU(procnum) + + self.ncpu += 1; + continue + + if not self.ncpu: + raise RuntimeError, 'processor keyword not found' + + ms = re.match( r'^vendor_id\s+:\s+(.*)\n', s ) + if ms: + curcpu.vendor = ms.group(1) + continue + + ms = re.match( r'^cpu family\s+:\s+(\d+).*', s ) + if ms: + curcpu.family = ms.group(1) + continue + + ms = re.match( r'^model\s+:\s+(\d).*', s ) + if ms: + curcpu.model = ms.group(1) + continue + + ms = re.match( r'^model name\s+:\s+(.*)\n', s ) + if ms: + curcpu.modelName = ms.group(1) + continue + + ms = re.match( r'^stepping\s+:\s+(\d+)', s ) + if ms: + curcpu.stepping = ms.group(1) + continue + + ms = re.match( r'^cpu MHz\s+:\s+(\d+\.\d+)', s ) + if ms: + curcpu.setMHz = ms.group(1) + continue + + ms = re.match( r'^cache size\s+:\s+(\d+)\s+(\S+).*\n', s ) + if ms: + curcpu.setCacheSize = asKB( ms.group(1), ms.group(2) ) + continue + + ms = re.match( r'^physical id\s+:\s+(\d)', s ) + if ms: + curcpu.physicalID = ms.group(1) + curcpu.smp = 1 + continue + + ms = re.match( r'^siblings\s+:\s(\d+)', s ) + if ms: + curcpu.siblings = ms.group(1) + curcpu.smp = 1 + continue + + ms = re.match( r'^fdiv_bug\s+:\s+(yes|no).*\n', s ) + if ms: + curcpu.fdivBug = ms.group(1) + continue + + ms = re.match( r'^hlt_bug\s+:\s+(yes|no).*\n', s ) + if ms: + curcpu.hltBug = ms.group(1) + continue + + ms = re.match( r'^f00f_bug\s+:\s+(yes|no).*\n', s ) + if ms: + curcpu.f00fBug = ms.group(1) + continue + + ms = re.match( r'^coma_bug\s+:\s+(yes|no).*\n', s ) + if ms: + curcpu.comaBug = ms.group(1) + continue + + ms = re.match( r'^fpu\s+:\s+(yes|no).*\n', s ) + if ms: + curcpu.fpu = ms.group(1) + continue + + ms = re.match( r'^fpu_exception\s+:\s+(yes|no).*\n', s ) + if ms: + curcpu.fpuException = ms.group(1) + continue + + ms = re.match( r'^cpuid level\s+:\s+(\d+)', s ) + if ms: + curcpu.cpuIDLevel = ms.group(1) + continue + + ms = re.match( r'^wp\s+:\s+(yes|no).*\n', s ) + if ms: + curcpu.wp = ms.group(1) + continue + + ms = re.match( r'^flags\s+:\s+(.*)\n', s ) + if ms: + curcpu.flags = ms.group(1) + continue + + ms = re.match( r'^bogomips\s+:\s+(\d+\.\d+)', s ) + if ms: + curcpu.bogoMips = ms.group(1) + continue + + print "Unmatched Line: %s" % s + + # end __init__ + + + def __repr__( self ): + out = "" + + for key in self.cpus.keys(): + if out: out += "\n" + curcpu = self.cpus[key] + out += curcpu.__repr__() + + return out + + def physicalCPUcount(self): + """ return number of physical CPUs """ + + # easy stuff first + if self.ncpu == 1: return 1 + + if self.physCPU != 0: + # already computed + return self.physCPU + + self.physCPU = 0 + + # this is currently coded for PII and greater i386 + # CPUs only... we're going to count up the number + # of unique physical ID's + + uniqPhysIDs = {} + for cpu in self.cpus.keys(): + uniqPhysIDs[self.cpus[cpu].physicalID] = 1 + + self.physCPU = len(uniqPhysIDs.keys()) + + return self.physCPU + + # end def physicalCPUcount + +# end class CPUInfo + + +class MemInfo: + def __init__(self): + f = open("/proc/meminfo") + l = f.readlines() + f.close() + + exp = r'\s+(\d+)\s+(\S+)' + + # yes. It is inefficient. But if the kernel reorders + # the items for any reason, we don't have to fix it. + # + for s in l[3:]: + if re.match( r'^$', s ): + continue + + ms = re.match( r'^MemTotal:' + exp, s ) + if ms: + self.memTotal = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^MemFree:' + exp, s ) + if ms: + self.memFree = asKB( int( ms.group(1) ), ms.group(2) ) + continue + + ms = re.match( r'^MemShared:' + exp, s ) + if ms: + self.memShared = asKB( int( ms.group(1) ), ms.group(2) ) + continue + + ms = re.match( r'^Buffers:' + exp, s ) + if ms: + self.buffers = asKB( int( ms.group(1) ), ms.group(2) ) + continue + + ms = re.match( r'^Cached:' + exp, s ) + if ms: + self.cached = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^SwapCached:' + exp, s ) + if ms: + self.swapCached = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'Active:' + exp, s ) + if ms: + self.active = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^ActiveAnon:' + exp, s ) + if ms: + self.activeAnon = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^ActiveCache:' + exp, s ) + if ms: + self.activeCache = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^Inact_dirty:' + exp, s ) + if ms: + self.inactDirty = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^Inact_laundry:' + exp, s ) + if ms: + self.inactLaundry = asKB( int( ms.group(1) ), ms.group(2) ) + continue + + ms = re.match( r'^Inact_clean:' + exp, s ) + if ms: + self.inactClean = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^Inact_target:' + exp, s ) + if ms: + self.inactTarget = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^HighTotal:' + exp, s ) + if ms: + self.highTotal = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^HighFree:' + exp, s ) + if ms: + self.highFree = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^LowTotal:' + exp, s ) + if ms: + self.lowTotal = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^LowFree:' + exp, s ) + if ms: + self.lowFree = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^SwapTotal:' + exp, s ) + if ms: + self.swapTotal = asKB( int(ms.group(1)), ms.group(2) ) + continue + + ms = re.match( r'^SwapFree:' + exp, s ) + if ms: + self.swapFree = asKB( int(ms.group(1)), ms.group(2) ) + continue + + print 'Unmatched meminfo property: ' + s + + # end for s in lines + + # end __init__ + + + def __repr__(self): + """generate string representation for debugging purposes""" + r = "" + f = "%-14s%8d KB\n" + + r = f % ("MemTotal:", self.memTotal) + r += f % ("MemFree:", self.memFree) + r += f % ("MemShared:", self.memShared) + r += f % ("Buffers:", self.buffers) + r += f % ("Cached:", self.cached) + r += f % ("SwapCached:", self.swapCached) + r += f % ("Active:", self.active) + r += f % ("ActiveAnon:", self.activeAnon) + r += f % ("ActiveCache:", self.activeCache) + r += f % ("Inact_dirty:", self.inactDirty) + r += f % ("Inact_laundry:", self.inactLaundry) + r += f % ("Inact_clean:", self.inactClean) + r += f % ("Inact_target:", self.inactTarget) + r += f % ("HighTotal:", self.highTotal) + r += f % ("HighFree:", self.highFree) + r += f % ("LowTotal:", self.lowTotal) + r += f % ("LowFree:", self.lowFree) + r += f % ("SwapTotal:", self.swapTotal) + r += f % ("SwapFree:", self.swapFree) + return r + + # end def __repr__ + +# end class MemInfo + + +def unitToVal( unit ): + """ Map a unit string to a power of 2. + Why a power of 2? + It keeps us from generating big numbers that could overflow. + """ + + ms = re.match( r'[kK][bB]', unit ) + if ms: return 10 + + ms = re.match( r'[mM][bB]', unit ) + if ms: return 20 + + ms = re.match( r'[gG][bB]', unit ) + if ms: return 30 + + raise RuntimError, "unknown unit type: " + unit + +# end def unitToVal + + +def asUnit( val, inunit, outunit ): + """ normalize val in inunit to units in outunit""" + + insize = unitToVal(inunit) + outsize = unitToVal(outunit) + ratio = insize - outsize + +# print "insize = %d\noutsize = %d\nratio = %d\n" % (insize, outsize, ratio) + + return val * (2 ** ratio) + +# end def asUnit + + +def asKB( val, units ): + """normalize val from units to KB""" + + return asUnit( val, units, "KB" ) + +# end def asKB + + +def asMB( val, units ): + """normalize val from units to MB""" + + return asUnit( val, units, "MB" ) + +# end def asMB + + + +supportinfo = "/var/lib/supportinfo" +defaults = ["ES", 262144, 4194304, 2] + +class SupportLevel: + """internalizes the support level file""" + + def __init__(self): + f = open(supportinfo) + lines = f.readlines() + f.close() + exp = r'\s*:\s*(\d+)\s*(\S+)' + found = 0 + (self.variant, self.minRAM, self.maxRAM, self.maxCPU) = defaults + + for line in lines: + ms = re.match( r'(^\s*#|^\s*$)', line ) + if ms: continue + + ms = re.match( r'^\s*Variant\s*:\s*(\S+)\s*$', line ) + if ms: + self.variant = ms.group(1) + found |= 0x01 + continue + + ms = re.match( r'^\s*MinRAM' + exp, line ) + if ms: + self.minRAM = asKB( int(ms.group(1)), ms.group(2) ) + found |= 0x02 + continue + + ms = re.match( r'^\s*MaxRAM' + exp, line ) + if ms: + self.maxRAM = asKB( int(ms.group(1)), ms.group(2) ) + found |= 0x04 + continue + + ms = re.match( r'^\s*MaxCPU\s*:\s*(\d+)', line ) + if ms: + self.maxCPU = int( ms.group(1) ) + found |= 0x08 + continue + + print "Unmatched in SupportLevel: " + line + + # end for line... + if found != 0x0F: + for item in ['Variant', 'MinRAM', 'MaxRAM', 'MaxCPU']: + if not found & 0x01: + print "supportinfo tag %s is missing\n" % item + found = found >> 1 + + # end def __init__: + + def __repr__(self): + f = '%-15s:%10d' + + s = (f + " KB\n") % ("MinRAM", self.minRAM) + s += (f + " KB\n") % ("MaxRAM", self.maxRAM) + s += (f + "\n") % ("MaxCPU", self.maxCPU) + return s + + # end __repr__ + + def check(self): + meminfo = MemInfo() + cpuinfo = CPUInfo() + notes = 0 + + # print self + openlog( 'redhat-support-check' ) + + msgtop = [ + "***", + "*** WARNING: Red Hat Enterprise Linux %s" % self.variant + ] + msgbot = [ + "*** to run as a supported configuration", + "***" + ] + + if meminfo.memTotal < self.minRAM: + message = msgtop + [ + "*** requires at least %d MB RAM" % asMB(self.minRAM,"KB") + ] + msgbot + + + for line in message: + print line + syslog(line) + + notes += 1 + + + if self.maxRAM > 0 and meminfo.memTotal > self.maxRAM: + message = msgtop + [ + "*** allows no more than %d MB RAM" % asMB(self.maxRAM,"KB") + ] + msgbot + + for line in message: + print line + syslog(line) + + notes += 1 + + + if self.maxCPU > 0 and cpuinfo.physicalCPUcount() > self.maxCPU: + plural = "" + if self.maxCPU > 1: plural = "s" + + message = msgtop + [ + "*** allows no more than %d physical CPU%s" % + (self.maxCPU, plural) + ] + msgbot + + for line in message: + print line + syslog(line) + + notes += 1 + + + + if notes: + print "%d support check notifications issued" % notes + print "startup will continue in 30 seconds" + time.sleep(30) + + return notes + +# end class SupportLevel: + + +sys.exit( SupportLevel().check() ) |