From 15826c73b0970efb62ee949c0b60b1edc60f0583 Mon Sep 17 00:00:00 2001 From: Franziska Kunsmann Date: Sun, 22 Nov 2020 09:04:02 +0100 Subject: [PATCH] bundles/icinga2: send notifications --- .../files/icinga2/notification_commands.conf | 74 +++++++++++ .../icinga2/files/icinga2/notifications.conf | 61 +++++++++ bundles/icinga2/files/icinga2/users.conf | 2 +- .../files/scripts/icinga_notification_wrapper | 125 ++++++++++++++++++ bundles/icinga2/items.py | 22 +++ 5 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 bundles/icinga2/files/icinga2/notification_commands.conf create mode 100644 bundles/icinga2/files/icinga2/notifications.conf create mode 100644 bundles/icinga2/files/scripts/icinga_notification_wrapper diff --git a/bundles/icinga2/files/icinga2/notification_commands.conf b/bundles/icinga2/files/icinga2/notification_commands.conf new file mode 100644 index 0000000..a1ba8ad --- /dev/null +++ b/bundles/icinga2/files/icinga2/notification_commands.conf @@ -0,0 +1,74 @@ +object NotificationCommand "send-host-notification" { + import "plugin-notification-command" + + command = [ ConfigDir + "/scripts/icinga_notification_wrapper" ] + + arguments = { + "--mail" = { + set_if = {{ + host_vars = host.vars + if (host_vars.notification.mail == true) { + return true + } else { + return false + } + }} + value = "$user.email$" + } + "--sms" = { + set_if = {{ + host_vars = host.vars + if (host_vars.notification.sms == true) { + return true + } else { + return false + } + }} + value = "$user.vars.mobile$" + } + "--host_name" = "$host.display_name$" + "--state" = "$host.state$" + "--output" = "$host.output$" + "--escalation" = { + set_if = "$escalation$" + } + } +} + +object NotificationCommand "send-service-notification" { + import "plugin-notification-command" + + command = [ ConfigDir + "/scripts/icinga_notification_wrapper" ] + + arguments = { + "--mail" = { + set_if = {{ + svc_vars = service.vars + if (svc_vars.notification.mail == true) { + return true + } else { + return false + } + }} + value = "$user.email$" + } + "--sms" = { + set_if = {{ + svc_vars = service.vars + if (svc_vars.notification.sms == true) { + return true + } else { + return false + } + }} + value = "$user.vars.mobile$" + } + "--host_name" = "$host.display_name$" + "--service_name" = "$service.display_name$" + "--state" = "$service.state$" + "--output" = "$service.output$" + "--escalation" = { + set_if = "$escalation$" + } + } +} diff --git a/bundles/icinga2/files/icinga2/notifications.conf b/bundles/icinga2/files/icinga2/notifications.conf new file mode 100644 index 0000000..ad59b34 --- /dev/null +++ b/bundles/icinga2/files/icinga2/notifications.conf @@ -0,0 +1,61 @@ +apply Notification "notify_host-notification" to Host { + import "host-notification" + interval = 30m + + times = { + begin = 1m + end = 30m + } + + assign where host.vars.notification.sms == true +} + + +apply Notification "notify_service-notification" to Service { + import "service-notification" + interval = 30m + + times = { + begin = 1m + end = 30m + } + + assign where service.vars.notification.sms == true +} + + +apply Notification "notify_host-notification-escalation" to Host { + import "host-notification" + interval = 20m + + times = { + begin = 30m + } + + vars.escalation = true + + assign where host.vars.notification.sms == true +} + + +apply Notification "notify_service-notification-escalation" to Service { + import "service-notification" + interval = 20m + + times = { + begin = 30m + } + + vars.escalation = true + + assign where service.vars.notification.sms == true +} + + +apply Notification "notify_service-notification-mail" to Service { + import "service-notification" + interval = 0 + + assign where service.vars.notification.mail == true + ignore where service.vars.notification.sms == true +} diff --git a/bundles/icinga2/files/icinga2/users.conf b/bundles/icinga2/files/icinga2/users.conf index cf5a55e..7e26f68 100644 --- a/bundles/icinga2/files/icinga2/users.conf +++ b/bundles/icinga2/files/icinga2/users.conf @@ -7,7 +7,7 @@ object User "${username}" { display_name = "${username}" enable_notifications = true period = "24x7" - states = [ OK, Critical, Up, Down ] + states = [ OK, Warning, Critical, Up, Down ] types = [ Problem, Recovery ] % if config['is_admin']: diff --git a/bundles/icinga2/files/scripts/icinga_notification_wrapper b/bundles/icinga2/files/scripts/icinga_notification_wrapper new file mode 100644 index 0000000..2caf9db --- /dev/null +++ b/bundles/icinga2/files/scripts/icinga_notification_wrapper @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 + +import email.mime.text +import smtplib +from argparse import ArgumentParser +from requests import get +from subprocess import run +from sys import argv + +parser = ArgumentParser( + prog='icinga_notification_wrapper', + description='Icinga2 Notification Wrapper', +) +parser.add_argument( + '--host_name', + type=str, + required=True, +) +parser.add_argument( + '--service_name', + type=str, +) +parser.add_argument( + '--output', + type=str, + required=True, +) +parser.add_argument( + '--state', + type=str, + required=True, +) +parser.add_argument( + '--sms', + type=str, +) +parser.add_argument( + '--mail', + type=str, +) +parser.add_argument( + '--escalation', + action='store_true', +) + +def log_to_syslog(message): + try: + msg = '{}/{}: {}'.format(args.host_name, args.service_name, message) + run(['logger', '-t', 'icinga_notification_wrapper', msg]) + except: + # We don't expect this to fail. However, *if* it fails, we don't + # want it to get in the way of other notifications we may have + # to send. + pass + + +def notify_per_sms(): + log_to_syslog('SMS requested, but not implemented yet!') # FIXME TODO + return + msg = 'ICINGA: {host}/{service} is {state}: {output}'.format( + host=args.host_name, + service=args.service_name, + state=args.state, + output=args.output + ) + + +def notify_per_mail(): + text = """ + _ _ + (_)____(_)___ ____ _____ _ + / / ___/ / __ \/ __ `/ __ `/ + / / /__/ / / / / /_/ / /_/ / +/_/\___/_/_/ /_/\__, /\__,_/ + /____/ + +Host: {host}""" + + if args.service_name: + text += """ +Service: {service}""" + + text += """ +State: {state} + +{output}""" + + mail = email.mime.text.MIMEText(text.format( + host=args.host_name, + service=args.service_name, + state=args.state, + output=args.output + ), + 'plain', + 'utf-8', + ) + + if args.service_name: + mail['Subject'] = '[ICINGA] {}/{} is {}'.format(args.host_name, args.service_name, args.state) + else: + mail['Subject'] = '[ICINGA] {} is {}'.format(args.host_name, args.state) + + mail['To'] = args.mail + mail['From'] = 'noreply+icinga@kunbox.net' + + try: + s = smtplib.SMTP('localhost') + s.sendmail(mail['From'], [args.mail], mail.as_string()) + s.quit() + + log_to_syslog('Sent mail to "{}"'.format(args.mail)) + except Exception as e: + log_to_syslog('Sending mail to "{}" failed: {}'.format(args.mail, repr(e))) + + +if __name__ == '__main__': + args = parser.parse_args() + + log_to_syslog(' '.join(argv)) + + if args.mail and not args.escalation: + notify_per_mail() + + if args.sms: + notify_per_sms() diff --git a/bundles/icinga2/items.py b/bundles/icinga2/items.py index 5cd1c97..453dda6 100644 --- a/bundles/icinga2/items.py +++ b/bundles/icinga2/items.py @@ -91,6 +91,10 @@ files = { 'svc_systemd:icinga2:restart', }, }, + '/etc/icinga2/scripts/icinga_notification_wrapper': { + 'source': 'scripts/icinga_notification_wrapper', + 'mode': '0755', + }, '/etc/icinga2/features-available/ido-pgsql.conf': { 'source': 'icinga2/ido-pgsql.conf', 'content_type': 'mako', @@ -129,6 +133,24 @@ files = { 'svc_systemd:icinga2:restart', }, }, + '/etc/icinga2/conf.d/notification_commands.conf': { + 'source': 'icinga2/notification_commands.conf', + 'needs': { + 'pkg_apt:icinga2', + }, + 'triggers': { + 'svc_systemd:icinga2:restart', + }, + }, + '/etc/icinga2/conf.d/notifications.conf': { + 'source': 'icinga2/notifications.conf', + 'needs': { + 'pkg_apt:icinga2', + }, + 'triggers': { + 'svc_systemd:icinga2:restart', + }, + }, '/etc/icinga2/conf.d/templates.conf': { 'source': 'icinga2/templates.conf', 'needs': {