query_server.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. """
  2. Query the heartbeat server from the command line.
  3. As an argument, takes either server:port or the falcon run directory
  4. (if not argument is given, uses the current directory).
  5. """
  6. import argparse
  7. import collections
  8. import os
  9. import re
  10. import socket
  11. import sys
  12. STATE_FN = 'state.py' # taken from network_based.py
  13. STATE_DIR = 'mypwatcher' # taken from pwatcher_bridge.py
  14. # send message delimited with a \0
  15. def socket_send(socket, message):
  16. socket.sendall(b'{}\0'.format(message))
  17. # receive all of \0 delimited message
  18. # may discard content past \0, if any, so not safe to call twice on same socket
  19. def socket_read(socket):
  20. buffer = bytearray(b' ' * 256)
  21. nbytes = socket.recv_into(buffer, 256)
  22. if nbytes == 0: # empty message
  23. return
  24. message = ''
  25. while nbytes != 0:
  26. try: # index() raises when it can't find the character
  27. i = buffer[:nbytes].index('\0')
  28. message += str(buffer[:i]) # discard past delimiter
  29. break
  30. except ValueError: # haven't reached end yet
  31. message += str(buffer)
  32. nbytes = socket.recv_into(buffer, 256)
  33. return message
  34. # get server and port from watcher state file
  35. def use_state(filename):
  36. with open(filename, 'r') as f:
  37. for line in f:
  38. match = re.match(r" 'server': \('([^']+)', (\d+)\)", line)
  39. if match:
  40. return (match.group(1), int(match.group(2)))
  41. print('Error: could not find server info in state file {}'.format(filename))
  42. def parse_args():
  43. parser = argparse.ArgumentParser(description='query falcon network based heartbeat server')
  44. parser.add_argument('-s', '--server', help='<server_name:port>')
  45. parser.add_argument('-f', '--file', help='location of pwatcher state file')
  46. parser.add_argument('-d', '--debug', default=False, action='store_const', const=True, help='get server state instead of process list')
  47. parser.add_argument('sf', nargs='?', help='specify server or file')
  48. return parser.parse_args()
  49. # parse command line argument (if any) to find server info
  50. def find_server(args):
  51. i = 0
  52. if args.server:
  53. i += 1
  54. if args.file:
  55. i += 1
  56. if args.sf:
  57. i += 1
  58. if i > 1:
  59. raise Exception('Error: may only specify server once. Try "--help".')
  60. if args.sf:
  61. if os.path.exists(args.sf):
  62. args.file = args.sf
  63. else:
  64. try:
  65. args.sf.index(':')
  66. except ValueError:
  67. print('Error: could not parse argument as file or server:port: {}'.format(args.sf))
  68. return
  69. args.server = args.sf
  70. if args.server:
  71. try:
  72. i = args.server.index(':')
  73. except ValueError:
  74. print('Error: could not parse argument as server:port: {}'.format(args.server))
  75. return
  76. server = args.server[:i]
  77. port = int(args.server[i + 1:])
  78. return (server, port)
  79. if not args.file:
  80. args.file = '.'
  81. if os.path.isfile(args.file):
  82. return use_state(args.file)
  83. elif os.path.isdir(args.file):
  84. if os.path.isfile(os.path.join(args.file, STATE_FN)):
  85. return use_state(os.path.join(args.file, STATE_FN))
  86. elif os.path.isfile(os.path.join(args.file, STATE_DIR, STATE_FN)):
  87. return use_state(os.path.join(args.file, STATE_DIR, STATE_FN))
  88. print('Error: could not find state file: {}'.format(args.file))
  89. def main():
  90. args = parse_args()
  91. server = find_server(args)
  92. if not server:
  93. sys.exit(1)
  94. s = socket.socket()
  95. s.connect(server)
  96. if args.debug:
  97. socket_send(s, 'D')
  98. server_state = socket_read(s)
  99. s.close()
  100. state = eval(server_state)
  101. for jobid, val in state.items():
  102. print('{}: {} {} {} {}'.format(jobid, val[0], val[1], val[2], val[3]))
  103. else:
  104. socket_send(s, 'L')
  105. jobids = socket_read(s)
  106. s.close()
  107. for jobid in jobids.split():
  108. s = socket.socket()
  109. s.connect(server)
  110. socket_send(s, 'Q {}'.format(jobid))
  111. m = socket_read(s)
  112. s.close()
  113. print('{} {}'.format(jobid, m))
  114. if __name__ == "__main__":
  115. main()