Viewing file: hardware.py (20.65 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/python # # Copyright (c) 1999-2002 Red Hat, Inc. Distributed under GPL. # # Author: Preston Brown <pbrown@redhat.com> # Adrian Likins <alikins@redhat.com> # Cristian Gafton <gafton@redhat.com> # # This thing gets the hardware configuraion out of a system """Used to read hardware info from kudzu, /proc, etc""" from socket import gethostname from socket import gethostbyname import socket
import os import sys import string
import config import up2dateUtils
from rhpl import ethtool from rhpl.translate import _, N_
# Some systems don't have the _locale module installed try: import locale except ImportError: locale = None
# from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/59857 # used to translate dmi info to just printable chars # see bug #136862 def makefilter(keep): """ Return a functor that takes a string and returns a copy of that string consisting of only the characters in 'keep'. """ import string
# make a string of all chars, and one of all those NOT in 'keep' allchars = string.maketrans('', '') delchars = ''.join([c for c in allchars if c not in keep])
# return the functor return lambda s,a=allchars,d=delchars: s.translate(a, d)
identifier = makefilter(string.letters + string.digits + '_') # The registration server has several ways of dealing with this hardware # profile. # One is to add a 'hardware' member to the registration dictionary when # calling new_system # Another is to call registration.add_hw_profile(sysid, Hardware) # (accordingly, there is a registration.delete_hw_profile(sysid)
def read_kudzu(): ret = [] if not os.access("/etc/sysconfig/hwconf", os.R_OK): return ret hwlist = open("/etc/sysconfig/hwconf", "r").read() hwlist = string.split(hwlist, "-\n") for hw in hwlist: if not len(hw): continue items = string.split(hw, '\n') hwdict = {} for item in items: if not len(item): continue vals = string.split(item, ":") if len(vals) <= 1: # skip over bad/malformed lines continue # Some of the first words are used as dict keys server side # so this just helps make that easier strippedstring = string.strip(vals[1]) vals[1] = strippedstring hwdict[vals[0]] = string.join(vals[1:]) if hwdict: ret.append(hwdict) return ret
def read_installinfo(): if not os.access("/etc/sysconfig/installinfo", os.R_OK): return {} installinfo = open("/etc/sysconfig/installinfo", "r").readlines() installdict = {} installdict['class'] = "INSTALLINFO" for info in installinfo: if not len(info): continue vals = string.split(info, '=') if len(vals) <= 1: continue strippedstring = string.strip(vals[0]) vals[0] = strippedstring installdict[vals[0]] = string.strip(string.join(vals[1:])) return installdict
# This has got to be one of the ugliest fucntions alive def read_cpuinfo(): def get_entry(a, entry): e = string.lower(entry) if not a.has_key(e): return "" return a[e]
if not os.access("/proc/cpuinfo", os.R_OK): return {}
# Okay, the kernel likes to give us the information we need in the # standard "C" locale. if locale: # not really needed if you don't plan on using atof() locale.setlocale(locale.LC_NUMERIC, "C")
cpulist = open("/proc/cpuinfo", "r").read() uname = string.lower(os.uname()[4])
# This thing should return a hwdict that has the following # members: # # class, desc (required to identify the hardware device) # count, type, model, model_number, model_ver, model_rev # bogomips, platform, speed, cache hwdict = { 'class': "CPU", "desc" : "Processor", } if uname[0] == "i" and uname[-2:] == "86" or (uname == "x86_64"): # IA32 compatible enough count = 0 tmpdict = {} for cpu in string.split(cpulist, "\n\n"): if not len(cpu): continue count = count + 1 if count > 1: continue # just count the rest for cpu_attr in string.split(cpu, "\n"): if not len(cpu_attr): continue vals = string.split(cpu_attr, ":") if len(vals) != 2: # XXX: make at least some effort to recover this data... continue name, value = string.strip(vals[0]), string.strip(vals[1]) tmpdict[string.lower(name)] = value
if uname == "x86_64": hwdict['platform'] = 'x86_64' else: hwdict['platform'] = "i386" hwdict['count'] = count hwdict['type'] = get_entry(tmpdict, 'vendor_id') hwdict['model'] = get_entry(tmpdict, 'model name') hwdict['model_number'] = get_entry(tmpdict, 'cpu family') hwdict['model_ver'] = get_entry(tmpdict, 'model') hwdict['model_rev'] = get_entry(tmpdict, 'stepping') hwdict['cache'] = get_entry(tmpdict, 'cache size') hwdict['bogomips'] = get_entry(tmpdict, 'bogomips') hwdict['other'] = get_entry(tmpdict, 'flags') mhz_speed = get_entry(tmpdict, 'cpu mhz') if mhz_speed == "": # damn, some machines don't report this mhz_speed = "-1" try: hwdict['speed'] = int(round(float(mhz_speed)) - 1) except ValueError: hwdict['speed'] = -1
elif uname in["alpha", "alphaev6"]: # Treat it as an an Alpha tmpdict = {} for cpu_attr in string.split(cpulist, "\n"): if not len(cpu_attr): continue vals = string.split(cpu_attr, ":") if len(vals) != 2: # XXX: make at least some effort to recover this data... continue name, value = string.strip(vals[0]), string.strip(vals[1]) tmpdict[string.lower(name)] = string.lower(value)
hwdict['platform'] = "alpha" hwdict['count'] = get_entry(tmpdict, 'cpus detected') hwdict['type'] = get_entry(tmpdict, 'cpu') hwdict['model'] = get_entry(tmpdict, 'cpu model') hwdict['model_number'] = get_entry(tmpdict, 'cpu variation') hwdict['model_version'] = "%s/%s" % (get_entry(tmpdict, 'system type'), get_entry(tmpdict,'system variation')) hwdict['model_rev'] = get_entry(tmpdict, 'cpu revision') hwdict['cache'] = "" # pitty the kernel doesn't tell us this. hwdict['bogomips'] = get_entry(tmpdict, 'bogomips') hwdict['other'] = get_entry(tmpdict, 'platform string') hz_speed = get_entry(tmpdict, 'cycle frequency [Hz]') # some funky alphas actually report in the form "462375000 est." hz_speed = string.split(hz_speed) try: hwdict['speed'] = int(round(float(hz_speed[0]))) / 1000000 except ValueError: hwdict['speed'] = -1
elif uname in ["ia64"]: tmpdict = {} count = 0 for cpu in string.split(cpulist, "\n\n"): if not len(cpu): continue count = count + 1 # count the rest if count > 1: continue for cpu_attr in string.split(cpu, "\n"): if not len(cpu_attr): continue vals = string.split(cpu_attr, ":") if len(vals) != 2: # XXX: make at least some effort to recover this data... continue name, value = string.strip(vals[0]), string.strip(vals[1]) tmpdict[string.lower(name)] = string.lower(value)
hwdict['platform'] = uname hwdict['count'] = count hwdict['type'] = get_entry(tmpdict, 'vendor') hwdict['model'] = get_entry(tmpdict, 'family') hwdict['model_ver'] = get_entry(tmpdict, 'archrev') hwdict['model_rev'] = get_entry(tmpdict, 'revision') hwdict['bogomips'] = get_entry(tmpdict, 'bogomips') mhz_speed = tmpdict['cpu mhz'] try: hwdict['speed'] = int(round(float(mhz_speed)) - 1) except ValueError: hwdict['speed'] = -1 hwdict['other'] = get_entry(tmpdict, 'features')
elif uname in ['ppc64']: tmpdict = {} count = 0 for cpu in string.split(cpulist, "\n\n"): if not len(cpu): continue count = count + 1 # count the rest if count > 1: continue for cpu_attr in string.split(cpu, "\n"): if not len(cpu_attr): continue vals = string.split(cpu_attr, ":") if len(vals) != 2: # XXX: make at least some effort to recover this data... continue name, value = string.strip(vals[0]), string.strip(vals[1]) tmpdict[string.lower(name)] = string.lower(value)
hwdict['platform'] = uname hwdict['count'] = count hwdict['model'] = get_entry(tmpdict, "cpu") hwdict['model_ver'] = get_entry(tmpdict, 'revision') hwdict['bogomips'] = get_entry(tmpdict, 'bogomips') hwdict['vendor'] = get_entry(tmpdict, 'machine') # strings are postpended with "mhz" mhz_speed = get_entry(tmpdict, 'clock')[:-3] try: hwdict['speed'] = int(round(float(mhz_speed)) - 1) except ValueError: hwdict['speed'] = -1 else: # XXX: expand me. Be nice to others hwdict['platform'] = uname hwdict['count'] = 1 # Good as any hwdict['type'] = uname hwdict['model'] = uname hwdict['model_number'] = "" hwdict['model_ver'] = "" hwdict['model_rev'] = "" hwdict['cache'] = "" hwdict['bogomips'] = "" hwdict['other'] = "" hwdict['speed'] = 0
# make sure we get the right number here if not hwdict["count"]: hwdict["count"] = 1 else: try: hwdict["count"] = int(hwdict["count"]) except: hwdict["count"] = 1 else: if hwdict["count"] == 0: # we have at least one hwdict["count"] = 1 # This whole things hurts a lot. return hwdict
def read_memory(): un = os.uname() kernel = un[2] if kernel[:3] == "2.6": return read_memory_2_6() if kernel[:3] == "2.4": return read_memory_2_4()
def read_memory_2_4(): if not os.access("/proc/meminfo", os.R_OK): return {}
meminfo = open("/proc/meminfo", "r").read() lines = string.split(meminfo,"\n") curline = lines[1] memlist = string.split(curline) memdict = {} memdict['class'] = "MEMORY" megs = int(long(memlist[1])/(1024*1024)) if megs < 32: megs = megs + (4 - (megs % 4)) else: megs = megs + (16 - (megs % 16)) memdict['ram'] = str(megs) curline = lines[2] memlist = string.split(curline) # otherwise, it breaks on > ~4gigs of swap megs = int(long(memlist[1])/(1024*1024)) memdict['swap'] = str(megs) return memdict
def read_memory_2_6(): if not os.access("/proc/meminfo", os.R_OK): return {} meminfo = open("/proc/meminfo", "r").read() lines = string.split(meminfo,"\n") dict = {} for line in lines: blobs = string.split(line, ":", 1) key = blobs[0] if len(blobs) == 1: continue #print blobs value = string.strip(blobs[1]) dict[key] = value memdict = {} memdict["class"] = "MEMORY" total_str = dict['MemTotal'] blips = string.split(total_str, " ") total_k = long(blips[0]) megs = long(total_k/(1024))
swap_str = dict['SwapTotal'] blips = string.split(swap_str, ' ') swap_k = long(blips[0]) swap_megs = long(swap_k/(1024))
memdict['ram'] = str(megs) memdict['swap'] = str(swap_megs) return memdict
def findHostByRoute(): cfg = config.initUp2dateConfig() sl = cfg['serverURL'] if type(sl) == type(""): sl = [sl]
st = {'https':443, 'http':80} hostname = None intf = None for serverUrl in sl: s = socket.socket() server = string.split(serverUrl, '/')[2] servertype = string.split(serverUrl, ':')[0] port = st[servertype] if cfg['enableProxy']: server_port = up2dateUtils.getProxySetting() (server, port) = string.split(server_port, ':') port = int(port)
try: s.settimeout(5) s.connect((server, port)) (intf, port) = s.getsockname() hostname = socket.gethostbyaddr(intf)[0] # I dislike generic excepts, but is the above fails # for any reason, were not going to be able to # find a good hostname.... except: s.close() continue if hostname == None: hostname = "unknown" s.close() return hostname, intf def read_network(): netdict = {} netdict['class'] = "NETINFO"
netdict['hostname'] = gethostname() try: netdict['ipaddr'] = gethostbyname(gethostname()) except: netdict['ipaddr'] = "127.0.0.1"
if netdict['hostname'] == 'localhost.localdomain' or \ netdict['ipaddr'] == "127.0.0.1": hostname, ipaddr = findHostByRoute() netdict['hostname'] = hostname netdict['ipaddr'] = ipaddr
## # this only works on releases after 9, needs newer ## # rhpl ## # the other, perhaps better approach is to open a ## # socket to serverURL, and look at what ip/interface ## # the sockets was used with, and look up the hostname of ## # that. ## if netdict['hostname'] == 'localhost.localdomain' or \ ## netdict['ipaddr'] == "127.0.0.1": ## # this is all heuristics. Just trying to guess what ## # the actual hostname and primary interface on ## # improperly configured boxes is. ## interfaces = read_network_interfaces() ## ppp_interfaces = [] ## net_interfaces = {} ## for interface in interfaces.keys(): ## if interface == "lo": ## continue ## if interface[:3] == "ppp": ## ppp_interfaces.append(interfaces[interface]) ## continue ## net_interfaces[interface] = interfaces[interface]
## hostname = "" ## if len(net_interfaces): ## ifs = net_interfaces.keys() ## ifs.remove("class") ## ifs.sort() ## # try to hint that eth0 is possibly more likely to ## # be the main interface than eth1 etc ## for ik in ifs: ## i = net_interfaces[ik] ## ip = i['ipaddr'] ## if ip: ## (hostname, alias, ips) = socket.gethostbyaddr(ip) ## continue ## if len(ppp_interfaces): ## ifs = ppp_interfaces.keys() ## ifs.remove("class") ## ifs.sort() ## for ik in ifs: ## i = net_interfaces[ik] ## ip = i['ipaddr'] ## if ip: ## (hostname, alias, ips) = socket.gethostbyaddr(ip) ## continue ## if hostname != "": ## netdict['hostname'] = hostname ## netdict['ipaddr'] = gethostbyname(hostname)
return netdict
def read_network_interfaces(): intDict = {} intDict['class'] = "NETINTERFACES" interfaces = ethtool.get_devices() for interface in interfaces: try: hwaddr = ethtool.get_hwaddr(interface) except: hwaddr = "" try: module = ethtool.get_module(interface) except: if interface == 'lo': module = "loopback" else: module = "Unknown" try: ipaddr = ethtool.get_ipaddr(interface) except: ipaddr = ""
try: netmask = ethtool.get_netmask(interface) except: netmask = ""
try: broadcast = ethtool.get_broadcast(interface) except: broadcast = "" intDict[interface] = {'hwaddr':hwaddr, 'ipaddr':ipaddr, 'netmask':netmask, 'broadcast':broadcast, 'module': module}
return intDict
# This one tries to read the DMI information - it needs root access to do that. # Under normal runs this shouldn;t be a problem, but in case something goes bad # we simply bail out. def read_dmi(): uname = string.lower(os.uname()[4]) dmidict = {} if not (uname[0] == "i" and uname[-2:] == "86") and not (uname == "x86_64"): return {} # Looks like IA32 or x86_64 , try reading dmi try: import dmi except: return {} # Now try to parse DMI try: d = dmi.DMI() except: # failed to read/parse the DMI information print "Reading DMI info failed" return {}
# Now we have the dmi information, parse the best of it if d.has_key("system"): # Get the system information dmidict["vendor"] = d["system"].get("vendor") s = "" if d["system"].has_key("product"): s = "%s" % d["system"]["product"] if d["system"].has_key("version"): s = "%s %s" % (s, d["system"]["version"]) if s: dmidict["system"] = s if d.has_key("board"): dmidict["product"] = d["board"].get("product") dmidict["board"] = d["board"].get("vendor") if d.has_key("bios"): dmidict["bios_vendor"] = d["bios"].get("vendor") dmidict["bios_version"] = d["bios"].get("version") dmidict["bios_release"] = d["bios"].get("release") # The hairy part is figuring out if there is an asset tag/serial number of importance asset = "" for k in ["chassis", "board", "system"]: if not d.has_key(k): continue for l in ["serial", "asset"]: if not d[k].has_key(l): continue t = string.strip(d[k][l]) if t in [None, "", "Not Available", "None", "N/A"]: continue asset = "%s(%s: %s) " % (asset, k, t) if asset: dmidict["asset"] = asset # Clean up empty entries for k in dmidict.keys()[:]: if dmidict[k] is None: del dmidict[k] # Finished dmidict["class"] = "DMI" toascii = makefilter(string.printable) for key in dmidict.keys(): foo = dmidict[key] dmidict[key] = toascii(foo) return dmidict # this one reads it all def Hardware(): allhw = [] ret = read_kudzu()
try: if ret: # kudzu returns a list allhw = ret except: print _("Error reading hardware information:"), sys.exc_type # all others return individual arrays
# cpu info try: ret = read_cpuinfo() if ret: allhw.append(ret) except: print _("Error reading cpu information:"), sys.exc_type # memory size info try: ret = read_memory() if ret: allhw.append(ret) except: print _("Error reading system memory information:"), sys.exc_type # minimal networking info try: ret = read_network() if ret: allhw.append(ret) except: print _("Error reading networking information:"), sys.exc_type # dont like catchall exceptions but theres not # really anything useful we could do at this point # and its been trouble prone enough
# minimal DMI info try: ret = read_dmi() if ret: allhw.append(ret) except: print _("Error reading DMI information:"), sys.exc_type
try: ret = read_installinfo() if ret: allhw.append(ret) except: print _("Error reading install method information:"), sys.exc_type
try: ret = read_network_interfaces() if ret: allhw.append(ret) except: print _("Error reading network interface information:"), sys.exc_type # all Done. return allhw
# XXX: Need more functions here: # - filesystems layout (/proc.mounts and /proc/mdstat) # - is the kudzu config enough or should we strat chasing lscpi and try to parse that # piece of crap output?
# # Main program # if __name__ == '__main__': for hw in Hardware(): for k in hw.keys(): print "'%s' : '%s'" % (k, hw[k]) print
|