-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrestart_script.py
More file actions
97 lines (77 loc) · 2.81 KB
/
Copy pathrestart_script.py
File metadata and controls
97 lines (77 loc) · 2.81 KB
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
"""Reboots every device from devices.ini, clones first, master last.
Exit codes: 0 ok, 1 a device failed, 2 nothing ran, 3 watchdog.
"""
from __future__ import annotations
import argparse
import logging
import sys
import time
import requests
from anthias_common import (
EXIT_FATAL,
ApiClient,
ConfigError,
build_devices,
finish,
load_credentials,
load_settings,
setup_logging,
start_watchdog,
)
# a rebooting device often drops the connection before it answers
TREAT_TIMEOUT_AS_ERROR = False
SECONDS_BETWEEN_DEVICES = 2
def reboot(device, timeout):
client = ApiClient(device, timeout)
response = client.request("POST", "/api/v2/reboot", body="reboot")
body = " ".join((response.text or "").split())[:120]
if response.status_code not in (200, 201, 202, 204):
raise RuntimeError(f"HTTP {response.status_code} {body}")
return response.status_code, body
def main():
parser = argparse.ArgumentParser(description="Reboot all Anthias devices")
parser.add_argument("--config", default=None, help="path to devices.ini")
args = parser.parse_args()
started = time.time()
try:
settings, entries = load_settings(args.config)
except ConfigError as exc:
print(f"FATAL: {exc}", file=sys.stderr)
return EXIT_FATAL
setup_logging(settings, "restart")
start_watchdog(settings)
try:
master, clones = build_devices(entries, load_credentials(settings))
except ConfigError as exc:
logging.error("FATAL: %s", exc)
logging.shutdown()
return EXIT_FATAL
devices = clones + [master]
timeout = settings["http_timeout"]
failures = {}
logging.info("rebooting %d device(s)", len(devices))
for index, device in enumerate(devices):
try:
code, body = reboot(device, timeout)
logging.info("%s: HTTP %s %s", device, code, body or "(empty response)")
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as exc:
if TREAT_TIMEOUT_AS_ERROR:
failures[device.name] = f"no answer: {exc}"
logging.error("%s: no answer to the reboot command: %s", device, exc)
else:
logging.warning("%s: no answer, probably already rebooting (%s)", device, exc)
except Exception as exc:
failures[device.name] = str(exc)
logging.error("%s: reboot failed: %s", device, exc)
if index < len(devices) - 1:
time.sleep(SECONDS_BETWEEN_DEVICES)
return finish(failures, len(devices), "device(s)", started)
if __name__ == "__main__":
try:
sys.exit(main())
except KeyboardInterrupt:
sys.exit(EXIT_FATAL)
except Exception:
logging.exception("FATAL: unexpected error")
logging.shutdown()
sys.exit(EXIT_FATAL)