123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- #!/usr/bin/python
- #
- # Python whoall: parallel, multi-threaded version
- # First author: jacopogh - nov 2006
- # Modified and updated by admins & 150 over time
- #
- # Requires python version 2.7 or above
- # Please read the wiki before editing this file
- from time import time
- start = time()
- # Import needed modules
- import argparse
- import collections
- import os
- import telnetlib
- import textwrap
- from threading import Thread
- from socket import error
- from sys import argv,exit,stdout
- # Some array definitions
- lcm1 = ['abe','crash','duke','glados','lara','link','king','pang','pong','snake','sonic','spyro','yoshi']
- lcm2 = ['actarus','elwood','gex','gin','jake','kirk','martini','picard','q','raziel','sarek','spock','tron','worf','zombie']
- laur = ['eskimo','orion','tilde']
- math4 = ['sonic','crash','duke','raziel','actarus','gin','kirk','martini','picard','sarek','tron','worf','zombie','q','elwood','jake']
- math5 = ['abe','glados','link','king','pang','pong','snake','spyro','yoshi']
- math = math4 + math5
- cuda = ['jacobi','yukawa','tesla']
- # Important variables: gods, hosts and term colors
- gods = ['root','andreatsh','andreamalerba','lorenzouboldi','stefanobalzan','eugeniothieme']
- # Former admins: bother them at your own risk
- chucknorris = [ 'agalli', 'ikki', 'buddino', 'alex', 'ema', 'ktf', 'davideg', 'jacopogh', 'lampo', 'gian', 'rbondesan', 'scolari', 'emanueleb', 'giani_matteo','gabryv','fran','alqahirah','giorgio_ruffa','palazzi','algebrato','blanc','blue','silviacotroneo']
- parser = argparse.ArgumentParser( epilog='Please, report bugs or unwanted behavior to: working@lcm.mi.infn.it' )
- ## Optional arguments
- parser.add_argument( '-1', '--lcm1', action='store_true', default=False, dest='lcm1', help='LCM1 hosts ' )
- parser.add_argument( '-2', '--lcm2', action='store_true', default=False, dest='lcm2', help='LCM2 hosts ' )
- parser.add_argument( '-l', '--laur', action='store_true', default=False, dest='laur', help='only LAUR hosts ' )
- parser.add_argument( '-c', '--condor', action='store_true', default=False, dest='condor', help='condor nodes ' )
- parser.add_argument( '-C', '--cuda', action='store_true', default=False, dest='cuda', help='only CUDA hosts ' )
- parser.add_argument( '-f', '--full', action='store_true', default=False, dest='full', help='empty, unreachable and unavailable info' )
- parser.add_argument( '-m', '--math', action='store_true', default=False, dest='math', help='only Mathematica hosts ' )
- parser.add_argument( '-n', action='store_true', default=False, dest='n', help='not display the progressbar and colors' )
- parser.add_argument( '-N', action='store_true', default=False, dest='N', help='also display number of logs' )
- parser.add_argument( '-v', '--version', action='version', version='%(prog)s 2.0', help='Print program version' )
- ####
- args = parser.parse_args()
- hosts=[]
- if (( args.lcm1 and args.lcm2 ) or args.condor ) : hosts = lcm1 + lcm2
- elif args.lcm1: hosts += lcm1
- elif args.lcm2: hosts += lcm2
- elif args.laur: hosts += laur
- elif args.cuda: hosts += cuda
- elif args.math: hosts += math
- else: hosts = lcm1 + lcm2 + laur + cuda
- if args.n:
- splitters = [('jake','LCM1'),('gin','LCM2'),('jacobi','CUDA'),('orion','LAUR')]
- progressbar = 0
- else:
- splitters = [('abe','\033[1;36mLCM1\033[0m'),('actarus','\033[1;32mLCM2\033[0m'),('jacobi','\033[1;35mCUDA\033[0m'),('eskimo','\033[1;33mLAUR\033[0m')]
- progressbar = 1
-
- # Define port
- port = 79
- #############################################
- # Node class
- # The bulk of the program is done here
- #############################################
- class Node(Thread):
- # Constructor
- def __init__(self,nome,port):
- # Fork the thread first thing
- Thread.__init__(self)
- # Variables initialization
- self.hostname = nome
- self.local = []
- self.remote = []
- self.lgod = []
- self.rgod = []
- # Former admins
- self.chuck = []
- # Node status
- self.up = True
- self.aval = True
- self.port = port
- self.timeout = False
- # Ping the host to see if it's up
- def isup(self):
- # Is the host up?
- ping = os.popen("ping -w1 -c1 "+self.hostname,"r")
- if "0 received" in ping.read():
- self.up = False
- return False
- else:
- return True
-
- # Open telnet connection
- def connect(self):
- # Try to connect first
- try:
- self.conn = telnetlib.Telnet(self.hostname,self.port)
- # Inetd is down!
- except error, msg:
- self.aval = False
- return False
- return True
-
- # Read lcm_w ouput and fill accordingly the users-gods lists
- def read(self):
- # Read data
- lista=''
- reachable=0
- try: lista = self.conn.read_until("EOF",1)
- except EOFError: reachable=1
- del self.conn
-
- if lista=='':
- if reachable == 0:
- self.timeout=True
- # Split lines and fields
- righe = lista.splitlines()
- # Needed later for isempty
- self.users = len(righe)
- # Local-remote-god user check
- for x in righe:
- fields = x.split()
- if "tty" in fields[1]:
- if fields[0] in gods:
- self.lgod.append(fields[0].lower())
- else:
- if fields[0] not in chucknorris:
- self.local.append(fields[0].lower())
- else:
- if fields[0] in gods:
- if fields[0] not in self.lgod:
- self.rgod.append(fields[0].lower())
- else:
- if fields[0] not in self.local:
- if fields[0] not in chucknorris:
- self.remote.append(fields[0].lower())
- # Former admins
- if fields[0] in chucknorris:
- self.chuck.append(fields[0].lower())
- # Run method
- # This is the part that every thread executes in parallel
- # If host is up -> open connection -> if connection -> read data
- def run(self):
- if self.isup():
- if self.connect():
- self.read()
-
- # Is the host empty?
- def isempty(self):
- if (self.users > 0):
- return False
- else:
- return True
- # Print output giorgio-style, host based (after threads have finished)
- def printlist(self):
- # Uniq equivalent and string conversion
- strlocal = ""
- strremote = ""
- strlgod = ""
- strrgod = ""
- strchuck = ""
-
-
- if not args.N:
- # A set cannot have duplicate entries: uniq equivalent
- for item in set(self.local):
- strlocal += str(item) + ' '
- for item in set(self.remote):
- strremote += str(item) +' '
- for item in set(self.lgod):
- strlgod += str(item) +' '
- for item in set(self.rgod):
- strrgod += str(item) +' '
- for item in set(self.chuck):
- strchuck += str(item) +' '
- else:
- # Print also how many times users are logged (added by jp)
- for item in set(self.local):
- strlocal += str(item) + '('+str(collections.Counter(self.local).values()[collections.Counter(self.local).keys().index(item)])+') '
- for item in set(self.remote):
- strremote += str(item) +'('+str(collections.Counter(self.remote).values()[collections.Counter(self.remote).keys().index(item)])+') '
- for item in set(self.lgod):
- strlgod += str(item) +'('+str(collections.Counter(self.lgod).values()[collections.Counter(self.lgod).keys().index(item)])+') '
- for item in set(self.rgod):
- strrgod += str(item) +'('+str(collections.Counter(self.rgod).values()[collections.Counter(self.rgod).keys().index(item)])+') '
- for item in set(self.chuck):
- strchuck += str(item) +'('+str(collections.Counter(self.chuck).values()[collections.Counter(self.chuck).keys().index(item)])+') '
- # Print a tag [C] aside CUDA hosts (jp)
- if self.hostname in cuda:
- self.hostname = self.hostname + ' '*(5-len(self.hostname))+'[C]'
- print ' ' + self.hostname + ' '*(15-len(self.hostname))+ red + strlgod + normal + pink + strrgod + normal + green + strlocal + normal + blue + strremote + normal+ turquoise+strchuck+normal
- ###################################################
- # Main
- ###################################################
- # Get user groups
- groups = os.popen("groups").readlines()[0].split()
- # Setting colors
- if progressbar > 0:
- red = "\033[1;31m"
- normal = "\033[0m"
- blue = "\033[1;34m"
- pink = "\033[1;35m"
- green = "\033[1;32m"
- turquoise ="\033[1;36m"
- else:
- red = ""
- normal = ""
- blue = ""
- pink = ""
- green = ""
- turquoise =""
- # Initialization of the four lists
- downlist = ""
- emptylist = ""
- unavlist = ""
- timeoutlist = ""
- # Initialize the threadlist
- threadlist = []
- # Number of hosts (for progressbar)
- num = len(hosts)
- # Start the threads
- for item in hosts:
- m=Node(item,port)
- threadlist.append(m)
- m.start()
- # Used for progressbar
- index = 0
- print ' Querying '+str(num)+' hosts...'
- # Rejoin them when their work is done
- for thread in threadlist:
- thread.join()
- if progressbar > 0:
- # Progessbar
- index += 1
- stdout.write('\r ['+'='*index+'>'*(1-int(index/num))+' '*(num-index-1)+']')
- stdout.flush()
- if progressbar > 0:
- # Newline
- print '\n Done... ( %(t).3f s)' % {'t': (time() - start)}
- # And now print!
- for thread in threadlist:
- # lcm1-lcm2-laur splitters
- for pair in splitters:
- if thread.hostname in pair[0]: print '-' + pair[1] + normal +'----'
-
- # See what they are up to and print accordingly
- if thread.hostname in cuda:
- thread.hostname +='[C]'
- if args.math :
- if thread.hostname in math4:
- thread.hostname +='[M4]'
- if thread.hostname in math5:
- thread.hostname +='[M5]'
- if not thread.up:
- # Host down
- downlist += thread.hostname + ' '
- else:
- if not thread.aval:
- # Host unavailable
- unavlist += thread.hostname + ' '
- continue
- if thread.timeout:
- # Thread has timed out
- timeoutlist += thread.hostname + ' '
- continue
- if thread.isempty():
- # Host is empty
- emptylist += thread.hostname + ' '
- else:
- thread.printlist()
-
- # Some final output
- if progressbar > 0:
- print
- print 'Legenda: '+green + 'utente locale '+normal+blue+'utente remoto '+normal+red+'admin locale '+normal+pink+'admin remoto '+normal+turquoise+'nirvana'+normal
- print " I nodi contrassegnati con [C] sono i nodi CUDA."
- if args.math:
- print " I nodi contrassegnati con [M4] hanno Mathematica 4.0"
- print " I nodi contrassegnati con [M5] hanno Mathematica 5.2"
- print
- # Only in full mode
- #if ("-f" in str(params[0])) or ("-F" in str(params[0])) or ("-m" in str(params[0])) or ("-C" in str(params[0])):
- if args.full or args.math or args.cuda:
- print red+'Empty: '+normal+emptylist
- print red+'Timeout: '+normal+timeoutlist
- print red+'Unreachable: '+normal+downlist
- print red+'Unavailable: '+normal+unavlist
- # Exit gracefully
- exit(0)
|