1 import os
, BaseHTTPServer
, cgi
, threading
, urllib
, fcntl
, logging
3 from autotest_lib
.scheduler
import drone_manager
, scheduler_config
9 <head><title>Scheduler status</title></head>
12 <a href="?reparse_config=1">Reparse global config values</a><br>
13 <a href="?restart_scheduler=1">Restart the scheduler</a><br>
22 class StatusServerRequestHandler(BaseHTTPServer
.BaseHTTPRequestHandler
):
23 def _send_headers(self
):
24 self
.send_response(200, 'OK')
25 self
.send_header('Content-Type', 'text/html')
29 def _parse_arguments(self
):
30 path_parts
= self
.path
.split('?', 1)
31 if len(path_parts
) == 1:
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
))
53 def _write_drone(self
, drone
):
54 if drone
.allowed_users
:
55 allowed_users
= ', '.join(drone
.allowed_users
)
58 line
= ('%s: %s/%s processes, users: %s'
59 % (drone
.hostname
, drone
.active_processes
, drone
.max_processes
,
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
)
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')
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
):
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
)
112 if self
._shutting
_down
:
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()
127 self
._thread
= threading
.Thread(target
=self
._serve
_until
_shutdown
,
128 name
='status_server')