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