123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- """
- Query the heartbeat server from the command line.
- As an argument, takes either server:port or the falcon run directory
- (if not argument is given, uses the current directory).
- """
- import argparse
- import collections
- import os
- import re
- import socket
- import sys
- STATE_FN = 'state.py' # taken from network_based.py
- STATE_DIR = 'mypwatcher' # taken from pwatcher_bridge.py
- # send message delimited with a \0
- def socket_send(socket, message):
- socket.sendall(b'{}\0'.format(message))
- # receive all of \0 delimited message
- # may discard content past \0, if any, so not safe to call twice on same socket
- def socket_read(socket):
- buffer = bytearray(b' ' * 256)
- nbytes = socket.recv_into(buffer, 256)
- if nbytes == 0: # empty message
- return
- message = ''
- while nbytes != 0:
- try: # index() raises when it can't find the character
- i = buffer[:nbytes].index('\0')
- message += str(buffer[:i]) # discard past delimiter
- break
- except ValueError: # haven't reached end yet
- message += str(buffer)
- nbytes = socket.recv_into(buffer, 256)
- return message
- # get server and port from watcher state file
- def use_state(filename):
- with open(filename, 'r') as f:
- for line in f:
- match = re.match(r" 'server': \('([^']+)', (\d+)\)", line)
- if match:
- return (match.group(1), int(match.group(2)))
- print('Error: could not find server info in state file {}'.format(filename))
- def parse_args():
- parser = argparse.ArgumentParser(description='query falcon network based heartbeat server')
- parser.add_argument('-s', '--server', help='<server_name:port>')
- parser.add_argument('-f', '--file', help='location of pwatcher state file')
- parser.add_argument('-d', '--debug', default=False, action='store_const', const=True, help='get server state instead of process list')
- parser.add_argument('sf', nargs='?', help='specify server or file')
- return parser.parse_args()
- # parse command line argument (if any) to find server info
- def find_server(args):
- i = 0
- if args.server:
- i += 1
- if args.file:
- i += 1
- if args.sf:
- i += 1
- if i > 1:
- raise Exception('Error: may only specify server once. Try "--help".')
- if args.sf:
- if os.path.exists(args.sf):
- args.file = args.sf
- else:
- try:
- args.sf.index(':')
- except ValueError:
- print('Error: could not parse argument as file or server:port: {}'.format(args.sf))
- return
- args.server = args.sf
- if args.server:
- try:
- i = args.server.index(':')
- except ValueError:
- print('Error: could not parse argument as server:port: {}'.format(args.server))
- return
- server = args.server[:i]
- port = int(args.server[i + 1:])
- return (server, port)
- if not args.file:
- args.file = '.'
- if os.path.isfile(args.file):
- return use_state(args.file)
- elif os.path.isdir(args.file):
- if os.path.isfile(os.path.join(args.file, STATE_FN)):
- return use_state(os.path.join(args.file, STATE_FN))
- elif os.path.isfile(os.path.join(args.file, STATE_DIR, STATE_FN)):
- return use_state(os.path.join(args.file, STATE_DIR, STATE_FN))
- print('Error: could not find state file: {}'.format(args.file))
- def main():
- args = parse_args()
- server = find_server(args)
- if not server:
- sys.exit(1)
- s = socket.socket()
- s.connect(server)
- if args.debug:
- socket_send(s, 'D')
- server_state = socket_read(s)
- s.close()
- state = eval(server_state)
- for jobid, val in state.items():
- print('{}: {} {} {} {}'.format(jobid, val[0], val[1], val[2], val[3]))
- else:
- socket_send(s, 'L')
- jobids = socket_read(s)
- s.close()
- for jobid in jobids.split():
- s = socket.socket()
- s.connect(server)
- socket_send(s, 'Q {}'.format(jobid))
- m = socket_read(s)
- s.close()
- print('{} {}'.format(jobid, m))
- if __name__ == "__main__":
- main()
|