You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.5 KiB
128 lines
3.5 KiB
''' Simple watchdog script for the deep freezer alert system |
|
|
|
The alert system of our deep freezer in the s2 scullery will send emails as |
|
soon, as the temperature exceeds a certain level. |
|
|
|
This script will check regularly if the alert system itself is reachable and |
|
send an email if the system is not available (network down or power failure). |
|
''' |
|
|
|
import json |
|
import requests |
|
|
|
from datetime import datetime |
|
|
|
from . import pysema |
|
|
|
|
|
|
|
# alert emails recipients, subject and message |
|
EMAIL_RECIPIENTS = ['frey@imtek.de'] |
|
EMAIL_SUBJECT = '[S2 Scullery]: Deep Freezer Alert System Is Offline' |
|
EMAIL_BODY = [ |
|
'The -80 alert system in the S2 scullery seems to be offline.', |
|
'Maybe the network is down, there is a power outage or the system crashed.', |
|
'', |
|
'>>> Please have a look as soon as possible. <<<', |
|
'', |
|
'The system was last seen on {} (UTC)' |
|
] |
|
|
|
# which url to check |
|
ALERT_SYSTEM_URL = 'http://test.cpi.imtek.uni-freiburg.de' |
|
|
|
|
|
# How many times can an error be ignored? |
|
GRACE_PERIOD = 4 |
|
|
|
# where to store the data and default values |
|
DATA_STORE_PATH = '/val/local/s2watchdog.json' |
|
DEFAULTS = { |
|
'emails_sent': 0, |
|
'last_seen': 'Never', |
|
'last_result': '', |
|
'time_to_live': 0, |
|
'url': ALERT_SYSTEM_URL, |
|
} |
|
|
|
# how long (in seconds) to wait for a response from the alert system |
|
TIMEOUT = 5 |
|
|
|
|
|
|
|
def load_data(path): |
|
''' load and decode the saved data ''' |
|
try: |
|
with open(path, 'r') as file_handle: |
|
data = json.load(file_handle) |
|
|
|
# ensure, that these two keys are integers: |
|
for key in ['time_to_live', 'emails_sent']: |
|
value = data.get(key, None) |
|
if not isinstance(value, int): |
|
data[key] = 0 |
|
return data |
|
except (FileNotFoundError, AttributeError): |
|
return DEFAULTS |
|
|
|
|
|
def save_data(path, data=None): |
|
data = data or DEFAULTS |
|
with open(path, 'w') as file_handle: |
|
json.dump(data, file_handle) |
|
|
|
|
|
def query_alert_system(url): |
|
response = requests.get( |
|
url, |
|
allow_redirects=False, |
|
timeout=TIMEOUT |
|
) |
|
response.raise_for_status() |
|
return response.text |
|
|
|
|
|
def send_alert_mail(data): |
|
headers['Reply-To'] = EMAIL_RECIPIENTS |
|
body = '\n'.join(EMAIL_BODY) |
|
pysema.send( |
|
EMAIL_RECIPIENTS, |
|
EMAIL_SUBJECT, |
|
body.format(data['last_seen']), |
|
headers |
|
) |
|
|
|
def run(): |
|
data = load_data(DATA_STORE_PATH) |
|
|
|
# the url has changed, use the default values |
|
if data['url'] != ALERT_SYSTEM_URL: |
|
data = DEFAULTS |
|
|
|
try: |
|
result = query_alert_system(ALERT_SYSTEM_URL) |
|
if result != data['last_result']: |
|
# the retrieved result was not cached somehow |
|
# everything is all right! |
|
# we'd return after the data is saved |
|
data = { |
|
'emails_sent': 0, |
|
'last_seen': datetime.utcnow().isoformat(), |
|
'last_result': result, |
|
'time_to_live': GRACE_PERIOD, |
|
'url': ALERT_SYSTEM_URL, |
|
} |
|
save_data(DATA_STORE_PATH, data) |
|
return |
|
except requests.exceptions.RequestException: |
|
# the alarm system could not be reached. |
|
# but maybe its in the grace period, so we pass here |
|
pass |
|
|
|
ttl = data['time_to_live'] - 1 |
|
if ttl <= 0: |
|
data['emails_sent'] = data['emails_sent'] + 1 |
|
data['time_to_live'] = GRACE_PERIOD * data['emails_sent'] |
|
save_data(DATA_STORE_PATH, data) |
|
send_alert_mail(data) |
|
|
|
|