56 lines
2.3 KiB
Python
Executable File
56 lines
2.3 KiB
Python
Executable File
#!/usr/bin/python3
|
|
"""Serve diagnostics of the router's first setup on PORT, with the Python standard library alone.
|
|
|
|
Run by vpn-router-bootstrap.service, which vpn-router-setup starts until a setup has succeeded and
|
|
then stops. Every request on any address answers, as plain text, the output of COMMANDS run at that
|
|
moment: the state of the last setup run, the state of the services, the addresses, and the end of
|
|
the logs.
|
|
"""
|
|
|
|
import subprocess
|
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
|
|
PORT = 17081
|
|
|
|
#: The title of each section and its command.
|
|
COMMANDS = (
|
|
('Setup state', ['cat', '/run/vpn-router/setup.json']),
|
|
('Services', ['systemctl', 'is-active', 'vpn-router-setup', 'vpn-router-web', 'slapd', 'postgresql',
|
|
'strongswan', 'openvpn-server@vpn-router', 'wg-quick@wg0']),
|
|
('Failed units', ['systemctl', '--failed', '--no-legend', '--plain']),
|
|
('Addresses', ['ip', '-brief', 'address']),
|
|
('Routes', ['ip', 'route']),
|
|
('cloud-init', ['cloud-init', 'status', '--long']),
|
|
('vpn-router-setup log', ['journalctl', '--unit', 'vpn-router-setup', '--lines', '60', '--no-pager', '--output', 'short-iso']),
|
|
('vpn-router-web log', ['journalctl', '--unit', 'vpn-router-web', '--lines', '30', '--no-pager', '--output', 'short-iso']),
|
|
)
|
|
|
|
|
|
def report():
|
|
"""The output of every command of COMMANDS under its title."""
|
|
sections = []
|
|
for title, command in COMMANDS:
|
|
try:
|
|
result = subprocess.run(command, capture_output=True, text=True, timeout=10)
|
|
text = (result.stdout + result.stderr).rstrip()
|
|
except (OSError, subprocess.TimeoutExpired) as exc:
|
|
text = f'cannot run {command[0]}: {exc}'
|
|
sections.append(f'== {title} ==\n{text}\n')
|
|
return '\n'.join(sections)
|
|
|
|
|
|
class Handler(BaseHTTPRequestHandler):
|
|
def do_GET(self):
|
|
body = report().encode()
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', 'text/plain; charset=utf-8')
|
|
self.send_header('Content-Length', str(len(body)))
|
|
self.send_header('Cache-Control', 'no-store')
|
|
self.send_header('Refresh', '10')
|
|
self.end_headers()
|
|
self.wfile.write(body)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
ThreadingHTTPServer(('', PORT), Handler).serve_forever()
|