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

''' 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)