KVM test: tests_base.cfg. sample: Fix test dependencies
[autotest-zwu.git] / scheduler / status_server.py
blobc52867127912b63bfcb5214e3b0f0087c4274bf7
1 import os, BaseHTTPServer, cgi, threading, urllib, fcntl, logging
2 import common
3 from autotest_lib.scheduler import drone_manager, scheduler_config
5 _PORT = 13467
7 _HEADER = """
8 <html>
9 <head><title>Scheduler status</title></head>
10 <body>
11 Actions:<br>
12 <a href="?reparse_config=1">Reparse global config values</a><br>
13 <a href="?restart_scheduler=1">Restart the scheduler</a><br>
14 <br>
15 """
17 _FOOTER = """
18 </body>
19 </html>
20 """
22 class StatusServerRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
23 def _send_headers(self):
24 self.send_response(200, 'OK')
25 self.send_header('Content-Type', 'text/html')
26 self.end_headers()
29 def _parse_arguments(self):
30 path_parts = self.path.split('?', 1)
31 if len(path_parts) == 1:
32 return {}
34 encoded_args = path_parts[1]
35 return cgi.parse_qs(encoded_args)
38 def _write_line(self, line=''):
39 self.wfile.write(line + '<br>\n')
42 def _write_field(self, field, value):
43 self._write_line('%s=%s' % (field, value))
46 def _write_all_fields(self):
47 self._write_line('Config values:')
48 for field in scheduler_config.SchedulerConfig.FIELDS:
49 self._write_field(field, getattr(scheduler_config.config, field))
50 self._write_line()
53 def _write_drone(self, drone):
54 if drone.allowed_users:
55 allowed_users = ', '.join(drone.allowed_users)
56 else:
57 allowed_users = 'all'
58 line = ('%s: %s/%s processes, users: %s'
59 % (drone.hostname, drone.active_processes, drone.max_processes,
60 allowed_users))
61 if not drone.enabled:
62 line += ' (disabled)'
63 self._write_line(line)
66 def _write_drone_list(self):
67 self._write_line('Drones:')
68 for drone in self.server._drone_manager.get_drones():
69 self._write_drone(drone)
70 self._write_line()
73 def _execute_actions(self, arguments):
74 if 'reparse_config' in arguments:
75 scheduler_config.config.read_config()
76 self.server._drone_manager.refresh_drone_configs()
77 self._write_line('Reparsed config!')
78 elif 'restart_scheduler' in arguments:
79 self.server._shutdown_scheduler = True
80 self._write_line('Posted the shutdown request')
81 self._write_line()
84 def do_GET(self):
85 self._send_headers()
86 self.wfile.write(_HEADER)
88 arguments = self._parse_arguments()
89 self._execute_actions(arguments)
90 self._write_all_fields()
91 self._write_drone_list()
93 self.wfile.write(_FOOTER)
96 class StatusServer(BaseHTTPServer.HTTPServer):
97 def __init__(self):
98 address = ('', _PORT)
99 # HTTPServer is an old-style class :(
100 BaseHTTPServer.HTTPServer.__init__(self, address,
101 StatusServerRequestHandler)
102 self._shutting_down = False
103 self._drone_manager = drone_manager.instance()
104 self._shutdown_scheduler = False
106 # ensure the listening socket is not inherited by child processes
107 old_flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
108 fcntl.fcntl(self.fileno(), fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
111 def shutdown(self):
112 if self._shutting_down:
113 return
114 logging.info('Shutting down server...')
115 self._shutting_down = True
116 # make one last request to awaken the server thread and make it exit
117 urllib.urlopen('http://localhost:%s' % _PORT)
120 def _serve_until_shutdown(self):
121 logging.info('Status server running on %s', self.server_address)
122 while not self._shutting_down:
123 self.handle_request()
126 def start(self):
127 self._thread = threading.Thread(target=self._serve_until_shutdown,
128 name='status_server')
129 self._thread.start()