d3df95f37bf2fa06258eae14533316b747fa68ca
[mirror/dsa-puppet.git] / modules / roles / files / mirror_health / mirror-health
1 #! /usr/bin/python3
2
3 import os
4 import requests
5 import time
6 import calendar
7 import logging
8 import subprocess
9 from email.utils import parsedate
10 logging.basicConfig(level=logging.INFO)
11
12 HOSTS = os.environ['MIRROR_CHECK_HOSTS'].split()
13 OUTPUT_DIR = "/run/dsa-mirror-health-{}".format(os.environ['MIRROR_CHECK_SERVICE'])
14 HEALTH_FILE = os.path.join(OUTPUT_DIR, "health")
15 URL = os.environ['MIRROR_CHECK_URL']
16 INTERVAL = int(os.environ.get('MIRROR_CHECK_INTERVAL', '60'))
17
18 latest_ts = 0
19
20 def retrieve_from_host(host, url):
21     proxies = {
22         'http': 'http://{}:80'.format(host),
23         'https': 'http://{}:443'.format(host),
24     }
25     return requests.get(url, timeout=5, proxies=proxies, allow_redirects=False)
26
27 def last_modified(response):
28     lm = 0
29     if response.status_code == 200 and response.headers.get('last-modified'):
30         lm = calendar.timegm(parsedate(response.headers['last-modified']))
31     return lm
32
33 def check_shutdown():
34     if subprocess.call(['dsa-is-shutdown-scheduled']) == 0:
35         logging.info("considering myself unhealthy, shutdown scheduled")
36         return False
37     return True
38
39 def check_uptodate():
40     global latest_ts
41     for host in HOSTS:
42         try:
43             lm = last_modified(retrieve_from_host(host, URL))
44             logging.debug("lm for host %s: %s", host, lm)
45             latest_ts = max(latest_ts, lm)
46         except (requests.exceptions.ProxyError, requests.exceptions.ReadTimeout):
47             pass
48     local_lm = last_modified(retrieve_from_host('localhost', URL))
49     logging.debug("lm for localhost: %s", local_lm)
50     if local_lm < latest_ts:
51         logging.info("considering myself unhealthy my ts=%s latest_ts=%s", local_lm, latest_ts)
52         return False
53     return True
54
55 while True:
56     start = time.time()
57     if check_shutdown() and check_uptodate():
58         logging.info("considering myself healthy")
59         open(HEALTH_FILE, 'w').write("OK")
60     else:
61         try:
62             os.remove(HEALTH_FILE)
63         except OSError:
64             pass
65     sleep_time = start + INTERVAL - time.time()
66     logging.debug("sleeping for %d seconds", sleep_time)
67     time.sleep(sleep_time)