Check_MK mit SMS Notifikation über SMSEagle

Folgendes Python Script kann für Check_MK verwendet werden, um Alerts via SMSEagle Geräte zu verschicken. Es muss dazu einfach als Site-Benutzer im Verzeichnis ~/local/share/check_mk/notifications abgelegt und ausführbar gemacht werden. Details dazu hier: Check_MK Alarmierung (Notifications) und SMS Eagle API.

su - mysite
cp /var/tmp/notify_smseagle ~/local/share/check_mk/notifications
chmod 755 ~/local/share/check_mk/notifications/notify_smseagle
omd reload

Ein SMS wird nur dann verschickt, wenn beim Benutzer unter "Pager address" eine gültige Mobilfunknummer gemäss PhoneRegex eingetragen wird. Vorsicht beim Kopieren des Codeblocks, da bei Python die Funktionalität von der Textformatierung abhängt.

#!/usr/bin/env python
# SMS (using SMSEagle failover)

"""
Check_MK SMS Notification
=========================

Alerting via multiple SMSEagle devices, defined in EagleHosts. Uses PhoneNumber
as fallback for sending SMS when NOTIFY_CONTACTPAGER is not defined. If all
SMSEagle hosts fail to send the SMS, the alert is sent to MailTo.

Changelog:
----------
2018-09-05: Try multiple mail servers. Restrict mobile number to +41 or 0041.
2018-08-28: Don't send if NOTIFY_CONTACTPAGER is invalid format. 
2018-08-27: Added NOTIFY_NOTIFICATIONTYPE.
2018-08-23: First release
"""

import urllib
import urllib2
import smtplib
import re
import sys
import socket
from os import environ
from email.mime.text import MIMEText



### Configuration Parameters

EagleHosts    = [ '1.2.3.4', '5.6.7.8', '9.10.11.12' ]
EagleLogin    = 'myuser'
EaglePassword = 'mypassword'
PhoneRegex    = '^(\+|00)41\d+$'

MailFrom      = 'monitoring@example.com'
MailTo        = 'monitoring@example.com'
MailHosts     = [ 'localhost', 'smtp1.example.com', 'smtp2.example.com' ]
MailPort      = 25


# ----------------------------------------------------------------------------
# Complain 
# ----------------------------------------------------------------------------

def complain(error):
    print error
    msg = MIMEText(error)
    msg['To'] = MailTo
    msg['From'] = MailFrom
    msg['Subject'] = 'Check_MK: SMS Notification Error'
    MessageSent  = False

    for host in MailHosts:
        if not MessageSent:
            try:
                server = smtplib.SMTP(host, MailPort)
                server.sendmail(MailFrom, MailTo, msg.as_string())
                server.quit()
            except socket.error as e:
                print "Could not connect to " + host + ": " + str(e) 
            except smtplib.SMTPException as e:
                print "Sending email failed: " + str(e)
            except:
                print "Unknown error:", sys.exc_info()[0]
            else:
                MessageSent = True
                break
    return



# ----------------------------------------------------------------------------
# Format Message 
# ----------------------------------------------------------------------------

def FormatMessage():
    """
    Format the SMS message using the environment variables given by Check_MK.
    See https://mathias-kettner.com/cms_notifications.html for details.
    """ 
    if 'NOTIFY_WHAT' in environ:
        if environ['NOTIFY_WHAT'] == 'HOST':
            msg = "%s %s: %s (%s)" % (
                  environ['NOTIFY_NOTIFICATIONTYPE'], 
                  environ['NOTIFY_HOSTNAME'],
                  environ['NOTIFY_HOSTOUTPUT'],
                  environ['NOTIFY_SHORTDATETIME'])
        elif environ['NOTIFY_WHAT'] == 'SERVICE':
            msg = "%s %s: %s %s (%s)" % (
                  environ['NOTIFY_NOTIFICATIONTYPE'],
                  environ['NOTIFY_HOSTNAME'],
                  environ['NOTIFY_SERVICEDESC'],
                  environ['NOTIFY_SERVICEOUTPUT'],
                  environ['NOTIFY_SHORTDATETIME'])
        else:
            msg = "Unknown notification method: " + environ['NOTIFY_WHAT']
    else:
        msg = "Environment variable NOTIFY_WHAT not defined."
    return msg




# ----------------------------------------------------------------------------
# Send Eagle SMS
# ----------------------------------------------------------------------------

def sendEagleSMS(to,message):
    """
    Sending SMS via SMSEagle HTTP API. Uses hosts defined in list EagleHosts.
    Upon failure an email with the error is sent and next host is used.
    """
    query_args   = { 'login':EagleLogin, 'pass':EaglePassword, 'to':to,
                     'message':message }
    encoded_args = urllib.urlencode(query_args)
    MessageSent  = False
    ErrorMessage = ''

    for host in EagleHosts:
        url =  'http://%s/index.php/http_api/send_sms?%s' % (host, encoded_args)
        if not MessageSent:
            try:
                result = urllib2.urlopen(url).read()
            except urllib2.HTTPError, e:
                complain('Sending SMS via SMSEagle %s failed: %s' 
                          % (host, str(e.code))) 
            except urllib2.URLError, e:
                complain('Sending SMS via SMSEagle %s failed: %s'
                          % (host, str(e.args)))
            else:    
                if result.startswith('OK;'):
                    MessageSent = True
                    print('SMS successfully sent via %s to %s.' % (host, to))
                    break
                else:
                    MessageSent = False
                    complain('Sending SMS via SMSEagle %s failed: %s' 
                             % (host, result.rstrip()))
            
    return



# ----------------------------------------------------------------------------
# Main
# ----------------------------------------------------------------------------

if not 'NOTIFY_CONTACTPAGER' in environ:
    complain('Environment variable NOTIFY_CONTACTPAGER missing')
else:
    PhoneNumber = environ['NOTIFY_CONTACTPAGER']
    if re.match(PhoneRegex, PhoneNumber):
        EagleMessage = FormatMessage()
        sendEagleSMS(PhoneNumber, EagleMessage)