141 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
| """
 | |
| sysinfo.py [host1] [host2] [options]
 | |
| 
 | |
| obtain system info from remote machine. 
 | |
| """
 | |
| 
 | |
| import py
 | |
| import sys
 | |
| 
 | |
| optparse = py.compat.optparse
 | |
| 
 | |
| parser = optparse.OptionParser(usage=__doc__)
 | |
| parser.add_option("-f", "--sshconfig", action="store", dest="ssh_config", default=None,
 | |
|                   help="use given ssh config file, and add info all contained hosts for getting info")
 | |
| parser.add_option("-i", "--ignore", action="store", dest="ignores", default=None,
 | |
|                   help="ignore hosts (useful if the list of hostnames come from a file list)")
 | |
| 
 | |
| def parsehosts(path):
 | |
|     path = py.path.local(path)
 | |
|     l = []
 | |
|     rex = py.std.re.compile(r'Host\s*(\S+)')
 | |
|     for line in path.readlines():
 | |
|         m = rex.match(line)
 | |
|         if m is not None:
 | |
|             sshname, = m.groups()
 | |
|             l.append(sshname)
 | |
|     return l
 | |
| 
 | |
| class RemoteInfo:
 | |
|     def __init__(self, gateway):
 | |
|         self.gw = gateway
 | |
|         self._cache = {}
 | |
| 
 | |
|     def exreceive(self, execstring):
 | |
|         if execstring not in self._cache:
 | |
|             channel = self.gw.remote_exec(execstring)
 | |
|             self._cache[execstring] = channel.receive()
 | |
|         return self._cache[execstring]
 | |
| 
 | |
|     def getmodattr(self, modpath):
 | |
|         module = modpath.split(".")[0]
 | |
|         return self.exreceive("""
 | |
|             import %s
 | |
|             channel.send(%s)
 | |
|         """ %(module, modpath))
 | |
| 
 | |
|     def islinux(self):
 | |
|         return self.getmodattr('sys.platform').find("linux") != -1
 | |
| 
 | |
|     def getfqdn(self):
 | |
|         return self.exreceive("""
 | |
|             import socket
 | |
|             channel.send(socket.getfqdn())
 | |
|         """)
 | |
| 
 | |
|     def getmemswap(self):
 | |
|         if self.islinux():
 | |
|             return self.exreceive(""" 
 | |
|             import commands, re
 | |
|             out = commands.getoutput("free")
 | |
|             mem = re.search(r"Mem:\s+(\S*)", out).group(1)
 | |
|             swap = re.search(r"Swap:\s+(\S*)", out).group(1)
 | |
|             channel.send((mem, swap))
 | |
|             """)
 | |
| 
 | |
|     def getcpuinfo(self):
 | |
|         if self.islinux():
 | |
|             return self.exreceive("""
 | |
|                 # a hyperthreaded cpu core only counts as 1, although it
 | |
|                 # is present as 2 in /proc/cpuinfo.  Counting it as 2 is
 | |
|                 # misleading because it is *by far* not as efficient as
 | |
|                 # two independent cores.
 | |
|                 cpus = {}
 | |
|                 cpuinfo = {}
 | |
|                 f = open("/proc/cpuinfo")
 | |
|                 lines = f.readlines()
 | |
|                 f.close()
 | |
|                 for line in lines + ['']:
 | |
|                     if line.strip():
 | |
|                         key, value = line.split(":", 1)
 | |
|                         cpuinfo[key.strip()] = value.strip()
 | |
|                     else:
 | |
|                         corekey = (cpuinfo.get("physical id"),
 | |
|                                    cpuinfo.get("core id"))
 | |
|                         cpus[corekey] = 1
 | |
|                 numcpus = len(cpus)
 | |
|                 model = cpuinfo.get("model name")
 | |
|                 channel.send((numcpus, model))
 | |
|             """)
 | |
| 
 | |
| def debug(*args):
 | |
|     print >>sys.stderr, " ".join(map(str, args))
 | |
| def error(*args):
 | |
|     debug("ERROR", args[0] + ":", *args[1:])
 | |
| 
 | |
| def getinfo(sshname, ssh_config=None, loginfo=sys.stdout):
 | |
|     debug("connecting to", sshname)
 | |
|     try:
 | |
|         gw = py.execnet.SshGateway(sshname, ssh_config=ssh_config)
 | |
|     except IOError:
 | |
|         error("could not get sshagteway", sshname)
 | |
|     else:
 | |
|         ri = RemoteInfo(gw)
 | |
|         #print "%s info:" % sshname
 | |
|         prefix = sshname.upper() + " "
 | |
|         print >>loginfo, prefix, "fqdn:", ri.getfqdn()
 | |
|         for attr in (
 | |
|             "sys.platform", 
 | |
|             "sys.version_info", 
 | |
|         ):
 | |
|             loginfo.write("%s %s: " %(prefix, attr,))
 | |
|             loginfo.flush()
 | |
|             value = ri.getmodattr(attr)
 | |
|             loginfo.write(str(value))
 | |
|             loginfo.write("\n")
 | |
|             loginfo.flush()
 | |
|         memswap = ri.getmemswap()
 | |
|         if memswap:
 | |
|             mem,swap = memswap
 | |
|             print >>loginfo, prefix, "Memory:", mem, "Swap:", swap 
 | |
|         cpuinfo = ri.getcpuinfo()
 | |
|         if cpuinfo:
 | |
|             numcpu, model = cpuinfo
 | |
|             print >>loginfo, prefix, "number of cpus:",  numcpu
 | |
|             print >>loginfo, prefix, "cpu model", model 
 | |
|         return ri
 | |
|             
 | |
| if __name__ == '__main__':
 | |
|     options, args = parser.parse_args()
 | |
|     hosts = list(args)
 | |
|     ssh_config = options.ssh_config
 | |
|     if ssh_config:
 | |
|         hosts.extend(parsehosts(ssh_config))
 | |
|     ignores = options.ignores or ()
 | |
|     if ignores:
 | |
|         ignores = ignores.split(",")
 | |
|     for host in hosts:
 | |
|         if host not in ignores:
 | |
|             getinfo(host, ssh_config=ssh_config)
 | |
|         
 |