reorganize, fix bugs
This commit is contained in:
parent
39042ba364
commit
74a4849cd8
|
@ -1,3 +1,5 @@
|
||||||
|
.idea
|
||||||
|
|
||||||
# ---> Python
|
# ---> Python
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
@ -137,4 +139,3 @@ dmypy.json
|
||||||
|
|
||||||
# Cython debug symbols
|
# Cython debug symbols
|
||||||
cython_debug/
|
cython_debug/
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
prometheus_client
|
|
||||||
requests
|
|
||||||
numpy
|
|
||||||
nagiosplugin
|
|
||||||
matrix-nio
|
|
||||||
Pillow
|
|
||||||
python-magic
|
|
||||||
numpy
|
|
||||||
beautifulsoup4
|
|
|
@ -1,110 +0,0 @@
|
||||||
import sys
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
import nagios
|
|
||||||
|
|
||||||
|
|
||||||
def handle_err(func):
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
try:
|
|
||||||
crit, ret = func(*args, **kwargs)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"UNKNOWN: exception '{e}'")
|
|
||||||
sys.exit(nagios.UNKNOWN)
|
|
||||||
if crit:
|
|
||||||
print(f"CRITICAL: {crit}")
|
|
||||||
sys.exit(nagios.CRITICAL)
|
|
||||||
else:
|
|
||||||
return ret
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def login(user_id: str, passwd: str, homeserver: str):
|
|
||||||
data = {'type': 'm.login.password', 'user': user_id, 'password': passwd}
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/login', json=data)
|
|
||||||
if r.status_code != 200:
|
|
||||||
return f'Bad status code on login for {user_id}: {r.status_code}\nBody: {r.text}', None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def create_room(room_name, homeserver, auth_token):
|
|
||||||
"""
|
|
||||||
Creates an unencrypted room.
|
|
||||||
"""
|
|
||||||
data = {"name": room_name, "preset": "private_chat", "visibility": "private", # "initial_state": [{"type": "m.room.guest_access", "state_key": "", "content": {"guest_access": "can_join"}}]
|
|
||||||
}
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/createRoom?access_token={auth_token}', json=data)
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on create room for {room_name}: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def send_invite(room_id, target_user_id, homeserver, auth_token):
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/rooms/{room_id}/invite?access_token={auth_token}', json={'user_id': target_user_id})
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on send invite for {room_id}: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def join_room(room_id, homeserver, auth_token):
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/join/{room_id}?access_token={auth_token}', data='{}')
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on join room for {room_id}: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def join_room_invite(room_id, homeserver, auth_token):
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/rooms/{room_id}/join?access_token={auth_token}', data='{}')
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on join room via invite for {room_id}: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def send_msg(message, room_id, homeserver, auth_token):
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/rooms/{room_id}/send/m.room.message?access_token={auth_token}', json={'msgtype': 'm.text', 'body': message})
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on send message for {room_id}: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
# errors will be handled in the other script
|
|
||||||
def get_event(event_id, room_id, homeserver, auth_token):
|
|
||||||
return requests.get(f'{homeserver}/_matrix/client/v3/rooms/{room_id}/event/{event_id}?access_token={auth_token}')
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def get_state(homeserver, auth_token, since=None):
|
|
||||||
if since:
|
|
||||||
url = f'{homeserver}/_matrix/client/r0/sync?since{since}&access_token={auth_token}'
|
|
||||||
else:
|
|
||||||
url = f'{homeserver}/_matrix/client/r0/sync?access_token={auth_token}'
|
|
||||||
r = requests.get(url)
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on sync: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def forget_room(room_id, homeserver, auth_token):
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/rooms/{room_id}/forget?access_token={auth_token}', data='{}')
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on leave room for {room_id}: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
return None, r.json()
|
|
||||||
|
|
||||||
|
|
||||||
@handle_err
|
|
||||||
def leave_room(room_id, homeserver, auth_token, forget=False):
|
|
||||||
r = requests.post(f'{homeserver}/_matrix/client/r0/rooms/{room_id}/leave?access_token={auth_token}', data='{}')
|
|
||||||
if r.status_code != 200:
|
|
||||||
return Exception(f'Bad status code on leave room for {room_id}: {r.status_code}\nBody: {r.text}'), None
|
|
||||||
if forget:
|
|
||||||
f = forget_room(room_id, homeserver, auth_token)
|
|
||||||
return None, r.json()
|
|
|
@ -1,25 +1,23 @@
|
||||||
|
import argparse
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from flask import Flask, Response, request
|
from flask import Flask, Response, request
|
||||||
from icinga2api.client import Client
|
from icinga2api.client import Client
|
||||||
|
|
||||||
client = Client('https://localhost:8080', 'icingaweb2', 'password1234')
|
from checker import nagios
|
||||||
|
|
||||||
OK = 0
|
parser = argparse.ArgumentParser(description='')
|
||||||
WARNING = 1
|
parser.add_argument('--endpoint', default='https://localhost:8080', help='Icinga2 URL for the API. Defaults to "https://localhost:8080"')
|
||||||
CRITICAL = 2
|
parser.add_argument('--user', default='icingaweb2', help='API username. Defaults to "icingaweb2"')
|
||||||
UNKNOWN = 3
|
parser.add_argument('--pw', required=True, help='API password.')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
client = Client(args.endpoint, args.user, args.pw)
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
def return_json(json_dict, start_response, status_code=200):
|
|
||||||
headers = [('Content-Type', 'application/json')]
|
|
||||||
start_response(str(status_code), headers)
|
|
||||||
return iter([json.dumps(json_dict).encode('utf-8')])
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/host')
|
@app.route('/host')
|
||||||
@app.route('/host/')
|
@app.route('/host/')
|
||||||
@app.route("/host/<hostid>")
|
@app.route("/host/<hostid>")
|
||||||
|
@ -74,9 +72,9 @@ def get_host_state(hostid=None):
|
||||||
|
|
||||||
if kuma_mode:
|
if kuma_mode:
|
||||||
for name, service in result['services'].items():
|
for name, service in result['services'].items():
|
||||||
if service['state'] != OK:
|
if service['state'] != nagios.OK:
|
||||||
result['failed_services'].append({'name': name, 'state': service['state']})
|
result['failed_services'].append({'name': name, 'state': service['state']})
|
||||||
if result['host']['state'] != OK:
|
if result['host']['state'] != nagios.OK:
|
||||||
result['failed_services'].append({'name': hostid, 'state': result['host']['state']})
|
result['failed_services'].append({'name': hostid, 'state': result['host']['state']})
|
||||||
|
|
||||||
if len(result['failed_services']):
|
if len(result['failed_services']):
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Based on original E-Mail Icinga2 notification
|
||||||
|
|
||||||
|
PROG="$(basename $0)"
|
||||||
|
ICINGA2HOST="$(hostname)"
|
||||||
|
CURLBIN="curl"
|
||||||
|
MX_TXN="$(date "+%s")$((RANDOM % 9999))"
|
||||||
|
|
||||||
|
if [ -z "$(which $CURLBIN)" ]; then
|
||||||
|
echo "$CURLBIN not found in \$PATH. Consider installing it."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
warn_ico="⚠"
|
||||||
|
error_ico="❌"
|
||||||
|
ok_ico="🆗"
|
||||||
|
question_ico="❓"
|
||||||
|
|
||||||
|
#Set the message icon based on service state
|
||||||
|
# For nagios, replace ICINGA_ with NAGIOS_ to get the environment variables from Nagios
|
||||||
|
## Function helpers
|
||||||
|
Usage() {
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Required parameters:
|
||||||
|
-d LONGDATETIME (\$icinga.long_date_time\$)
|
||||||
|
-l HOSTNAME (\$host.name\$)
|
||||||
|
-n HOSTDISPLAYNAME (\$host.display_name\$)
|
||||||
|
-o HOSTOUTPUT (\$host.output\$)
|
||||||
|
-s HOSTSTATE (\$host.state\$)
|
||||||
|
-t NOTIFICATIONTYPE (\$notification.type\$)
|
||||||
|
-m MATRIXROOM (\$notification_matrix_room_id\$)
|
||||||
|
-x MATRIXSERVER (\$notification_matrix_server\$)
|
||||||
|
-y MATRIXTOKEN (\$notification_matrix_token\$)
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
-4 HOSTADDRESS (\$address\$)
|
||||||
|
-6 HOSTADDRESS6 (\$address6\$)
|
||||||
|
-b NOTIFICATIONAUTHORNAME (\$notification.author\$)
|
||||||
|
-c NOTIFICATIONCOMMENT (\$notification.comment\$)
|
||||||
|
-i ICINGAWEB2URL (\$notification_icingaweb2url\$, Default: unset)
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
Help() {
|
||||||
|
Usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Error() {
|
||||||
|
if [ "$1" ]; then
|
||||||
|
echo $1
|
||||||
|
fi
|
||||||
|
Usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
## Main
|
||||||
|
while getopts 4:6::b:c:d:hi:l:n:o:s:t:m:x:y: opt; do
|
||||||
|
case "$opt" in
|
||||||
|
4) HOSTADDRESS=$OPTARG ;;
|
||||||
|
6) HOSTADDRESS6=$OPTARG ;;
|
||||||
|
b) NOTIFICATIONAUTHORNAME=$OPTARG ;;
|
||||||
|
c) NOTIFICATIONCOMMENT=$OPTARG ;;
|
||||||
|
d) LONGDATETIME=$OPTARG ;; # required
|
||||||
|
h) Help ;;
|
||||||
|
i) ICINGAWEB2URL=$OPTARG ;;
|
||||||
|
l) HOSTNAME=$OPTARG ;; # required
|
||||||
|
n) HOSTDISPLAYNAME=$OPTARG ;; # required
|
||||||
|
o) HOSTOUTPUT=$OPTARG ;; # required
|
||||||
|
s) HOSTSTATE=$OPTARG ;; # required
|
||||||
|
t) NOTIFICATIONTYPE=$OPTARG ;; # required
|
||||||
|
m) MATRIXROOM=$OPTARG ;; # required
|
||||||
|
x) MATRIXSERVER=$OPTARG ;; # required
|
||||||
|
y) MATRIXTOKEN=$OPTARG ;; # required
|
||||||
|
\?)
|
||||||
|
echo "ERROR: Invalid option -$OPTARG" >&2
|
||||||
|
Error
|
||||||
|
;;
|
||||||
|
:)
|
||||||
|
echo "Missing option argument for -$OPTARG" >&2
|
||||||
|
Error
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unimplemented option: -$OPTARG" >&2
|
||||||
|
Error
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
shift $((OPTIND - 1))
|
||||||
|
|
||||||
|
## Check required parameters (TODO: better error message)
|
||||||
|
if [ ! "$LONGDATETIME" ] ||
|
||||||
|
[ ! "$HOSTNAME" ] || [ ! "$HOSTDISPLAYNAME" ] ||
|
||||||
|
[ ! "$HOSTOUTPUT" ] || [ ! "$HOSTSTATE" ] ||
|
||||||
|
[ ! "$NOTIFICATIONTYPE" ]; then
|
||||||
|
Error "Requirement parameters are missing."
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Build the notification message
|
||||||
|
|
||||||
|
if [ "$HOSTSTATE" = "UP" ]; then
|
||||||
|
ICON=$ok_ico
|
||||||
|
elif [ "$HOSTSTATE" = "DOWN" ]; then
|
||||||
|
ICON=$error_ico
|
||||||
|
fi
|
||||||
|
if [ "$HOSTSTATE" = "UNKNOWN" ]; then
|
||||||
|
ICON=$question_ico
|
||||||
|
elif [ "$ICINGA_SERVICESTATE" = "OK" ]; then
|
||||||
|
ICON=$ok_ico
|
||||||
|
elif [ "$ICINGA_SERVICESTATE" = "WARNING" ]; then
|
||||||
|
ICON=$warn_ico
|
||||||
|
elif [ "$ICINGA_SERVICESTATE" = "CRITICAL" ]; then
|
||||||
|
ICON=$error_ico
|
||||||
|
fi
|
||||||
|
|
||||||
|
NOTIFICATION_MESSAGE=$(
|
||||||
|
cat <<EOF
|
||||||
|
$ICON <b>HOST:</b> $HOSTDISPLAYNAME is <b>$HOSTSTATE!</b> <br/>
|
||||||
|
<b>When:</b> $LONGDATETIME<br/>
|
||||||
|
<b>Info:</b> $HOSTOUTPUT<br/>
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
## Check whether IPv4 was specified.
|
||||||
|
if [ -n "$HOSTADDRESS" ]; then
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE <b>IPv4:</b> $HOSTADDRESS <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Check whether IPv6 was specified.
|
||||||
|
if [ -n "$HOSTADDRESS6" ]; then
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE <b>IPv6:</b> $HOSTADDRESS6 <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Check whether author and comment was specified.
|
||||||
|
if [ -n "$NOTIFICATIONCOMMENT" ]; then
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE Comment by <b>$NOTIFICATIONAUTHORNAME:</b> $NOTIFICATIONCOMMENT <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Check whether Icinga Web 2 URL was specified.
|
||||||
|
if [ -n "$ICINGAWEB2URL" ]; then
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE $ICINGAWEB2URL/monitoring/host/show?host=$HOSTNAME <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
while read line; do
|
||||||
|
message="${message}\n${line}"
|
||||||
|
done <<<$NOTIFICATION_MESSAGE
|
||||||
|
|
||||||
|
BODY="${message}"
|
||||||
|
|
||||||
|
/usr/bin/printf "%b" "$NOTIFICATION_MESSAGE" | $CURLBIN -k -X PUT --header 'Content-Type: application/json' --header 'Accept: application/json' -d "{
|
||||||
|
\"msgtype\": \"m.text\",
|
||||||
|
\"body\": \"$BODY\",
|
||||||
|
\"formatted_body\": \"$BODY\",
|
||||||
|
\"format\": \"org.matrix.custom.html\"
|
||||||
|
}" "$MATRIXSERVER/_matrix/client/r0/rooms/$MATRIXROOM/send/m.room.message/$MX_TXN?access_token=$MATRIXTOKEN"
|
|
@ -0,0 +1,165 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Based on original E-Mail Icinga2 notification
|
||||||
|
|
||||||
|
PROG="$(basename $0)"
|
||||||
|
ICINGA2HOST="$(hostname)"
|
||||||
|
CURLBIN="curl"
|
||||||
|
MX_TXN="$(date "+%s")$((RANDOM % 9999))"
|
||||||
|
|
||||||
|
if [ -z "$(which $CURLBIN)" ]; then
|
||||||
|
echo "$CURLBIN not found in \$PATH. Consider installing it."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
warn_ico="⚠"
|
||||||
|
error_ico="❌"
|
||||||
|
ok_ico="🆗"
|
||||||
|
question_ico="❓"
|
||||||
|
|
||||||
|
#Set the message icon based on service state
|
||||||
|
## Function helpers
|
||||||
|
Usage() {
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Required parameters:
|
||||||
|
-d LONGDATETIME (\$icinga.long_date_time\$)
|
||||||
|
-e SERVICENAME (\$service.name\$)
|
||||||
|
-l HOSTNAME (\$host.name\$)
|
||||||
|
-n HOSTDISPLAYNAME (\$host.display_name\$)
|
||||||
|
-o SERVICEOUTPUT (\$service.output\$)
|
||||||
|
-s SERVICESTATE (\$service.state\$)
|
||||||
|
-t NOTIFICATIONTYPE (\$notification.type\$)
|
||||||
|
-u SERVICEDISPLAYNAME (\$service.display_name\$)
|
||||||
|
-m MATRIXROOM (\$notification_matrix_room_id\$)
|
||||||
|
-x MATRIXSERVER (\$notification_matrix_server\$)
|
||||||
|
-y MATRIXTOKEN (\$notification_matrix_token\$)
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
-4 HOSTADDRESS (\$address\$)
|
||||||
|
-6 HOSTADDRESS6 (\$address6\$)
|
||||||
|
-b NOTIFICATIONAUTHORNAME (\$notification.author\$)
|
||||||
|
-c NOTIFICATIONCOMMENT (\$notification.comment\$)
|
||||||
|
-i ICINGAWEB2URL (\$notification_icingaweb2url\$, Default: unset)
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
Help() {
|
||||||
|
Usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Error() {
|
||||||
|
if [ "$1" ]; then
|
||||||
|
echo $1
|
||||||
|
fi
|
||||||
|
Usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
## Main
|
||||||
|
while getopts 4:6:b:c:d:e:hi:l:n:o:s:t:u:m:x:y: opt; do
|
||||||
|
case "$opt" in
|
||||||
|
4) HOSTADDRESS=$OPTARG ;;
|
||||||
|
6) HOSTADDRESS6=$OPTARG ;;
|
||||||
|
b) NOTIFICATIONAUTHORNAME=$OPTARG ;;
|
||||||
|
c) NOTIFICATIONCOMMENT=$OPTARG ;;
|
||||||
|
d) LONGDATETIME=$OPTARG ;; # required
|
||||||
|
e) SERVICENAME=$OPTARG ;; # required
|
||||||
|
h) Usage ;;
|
||||||
|
i) ICINGAWEB2URL=$OPTARG ;;
|
||||||
|
l) HOSTNAME=$OPTARG ;; # required
|
||||||
|
n) HOSTDISPLAYNAME=$OPTARG ;; # required
|
||||||
|
o) SERVICEOUTPUT=$OPTARG ;; # required
|
||||||
|
s) SERVICESTATE=$OPTARG ;; # required
|
||||||
|
t) NOTIFICATIONTYPE=$OPTARG ;; # required
|
||||||
|
u) SERVICEDISPLAYNAME=$OPTARG ;; # required
|
||||||
|
m) MATRIXROOM=$OPTARG ;; # required
|
||||||
|
x) MATRIXSERVER=$OPTARG ;; # required
|
||||||
|
y) MATRIXTOKEN=$OPTARG ;; # required
|
||||||
|
\?)
|
||||||
|
echo "ERROR: Invalid option -$OPTARG" >&2
|
||||||
|
Usage
|
||||||
|
;;
|
||||||
|
:)
|
||||||
|
echo "Missing option argument for -$OPTARG" >&2
|
||||||
|
Usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unimplemented option: -$OPTARG" >&2
|
||||||
|
Usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
shift $((OPTIND - 1))
|
||||||
|
|
||||||
|
echo "$LONGDATETIME $HOSTNAME $HOSTDISPLAYNAME $SERVICENAME $SERVICEDISPLAYNAME $SERVICEOUTPUT $SERVICESTATE $NOTIFICATIONTYPE"
|
||||||
|
|
||||||
|
## Check required parameters (TODO: better error message)
|
||||||
|
if [ ! "$LONGDATETIME" ] ||
|
||||||
|
[ ! "$HOSTNAME" ] || [ ! "$HOSTDISPLAYNAME" ] ||
|
||||||
|
[ ! "$SERVICENAME" ] || [ ! "$SERVICEDISPLAYNAME" ] ||
|
||||||
|
[ ! "$SERVICEOUTPUT" ] || [ ! "$SERVICESTATE" ] ||
|
||||||
|
[ ! "$NOTIFICATIONTYPE" ]; then
|
||||||
|
Error "Requirement parameters are missing."
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Build the notification message
|
||||||
|
if [ "$HOSTSTATE" = "UP" ]; then
|
||||||
|
ICON=$ok_ico
|
||||||
|
elif [ "$HOSTSTATE" = "DOWN" ]; then
|
||||||
|
ICON=$error_ico
|
||||||
|
fi
|
||||||
|
if [ "$SERVICESTATE" = "UNKNOWN" ]; then
|
||||||
|
ICON=$question_ico
|
||||||
|
elif [ "$SERVICESTATE" = "OK" ]; then
|
||||||
|
ICON=$ok_ico
|
||||||
|
elif [ "$SERVICESTATE" = "WARNING" ]; then
|
||||||
|
ICON=$warn_ico
|
||||||
|
elif [ "$SERVICESTATE" = "CRITICAL" ]; then
|
||||||
|
ICON=$error_ico
|
||||||
|
fi
|
||||||
|
|
||||||
|
NOTIFICATION_MESSAGE=$(
|
||||||
|
cat <<-EOF
|
||||||
|
$ICON <strong>Service:</strong> $SERVICEDISPLAYNAME on $HOSTDISPLAYNAME
|
||||||
|
is <strong>$SERVICESTATE.</strong> <br/>
|
||||||
|
<strong>When:</strong> $LONGDATETIME. <br/>
|
||||||
|
<strong>Info:</strong> $SERVICEOUTPUT <br/>
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
## Check whether IPv4 was specified.
|
||||||
|
if [ -n "$HOSTADDRESS" ]; then
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE <strong>IPv4:</strong> $HOSTADDRESS <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Check whether IPv6 was specified.
|
||||||
|
if [ -n "$HOSTADDRESS6" ]; then
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE <strong>IPv6:</strong> $HOSTADDRESS6 <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Check whether author and comment was specified.
|
||||||
|
if [ -n "$NOTIFICATIONCOMMENT" ]; then
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE <strong>Comment by $NOTIFICATIONAUTHORNAME:</strong> $NOTIFICATIONCOMMENT <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Check whether Icinga Web 2 URL was specified.
|
||||||
|
if [ -n "$ICINGAWEB2URL" ]; then
|
||||||
|
# Replace space with HTML
|
||||||
|
SERVICENAME=${SERVICENAME// /%20}
|
||||||
|
NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE $ICINGAWEB2URL/monitoring/service/show?host=$HOSTNAME&service=$SERVICENAME <br/>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
while read line; do
|
||||||
|
message="${message}\n${line}"
|
||||||
|
done <<<$NOTIFICATION_MESSAGE
|
||||||
|
|
||||||
|
BODY="${message}"
|
||||||
|
|
||||||
|
/usr/bin/printf "%b" "$NOTIFICATION_MESSAGE" | $CURLBIN -k -X PUT --header 'Content-Type: application/json' --header 'Accept: application/json' -d "{
|
||||||
|
\"msgtype\": \"m.text\",
|
||||||
|
\"body\": \"$BODY\",
|
||||||
|
\"formatted_body\": \"$BODY\",
|
||||||
|
\"format\": \"org.matrix.custom.html\"
|
||||||
|
}" "$MATRIXSERVER/_matrix/client/r0/rooms/$MATRIXROOM/send/m.room.message/$MX_TXN?access_token=$MATRIXTOKEN"
|
|
@ -11,7 +11,7 @@ from uuid import uuid4
|
||||||
|
|
||||||
from nio import AsyncClient, AsyncClientConfig, JoinError, JoinResponse, LoginResponse, RoomCreateError, RoomGetEventResponse, RoomSendError
|
from nio import AsyncClient, AsyncClientConfig, JoinError, JoinResponse, LoginResponse, RoomCreateError, RoomGetEventResponse, RoomSendError
|
||||||
|
|
||||||
import nagios
|
import checker.nagios as nagios
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Test federation between two homeservers.')
|
parser = argparse.ArgumentParser(description='Test federation between two homeservers.')
|
||||||
parser.add_argument('--bot1-user', required=True, help='User ID for bot 1.')
|
parser.add_argument('--bot1-user', required=True, help='User ID for bot 1.')
|
||||||
|
@ -53,7 +53,7 @@ async def test_one_direction(sender_client, receiver_client, receiver_user_id):
|
||||||
test_room_name = str(uuid4())
|
test_room_name = str(uuid4())
|
||||||
new_test_room = await sender_client.room_create(name=test_room_name, invite=[receiver_user_id])
|
new_test_room = await sender_client.room_create(name=test_room_name, invite=[receiver_user_id])
|
||||||
if isinstance(new_test_room, RoomCreateError):
|
if isinstance(new_test_room, RoomCreateError):
|
||||||
print(new_test_room)
|
return f'UNKNOWN: failed to create room "{new_test_room}"', nagios.UNKNOWN
|
||||||
new_test_room_id = new_test_room.room_id
|
new_test_room_id = new_test_room.room_id
|
||||||
|
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
@ -76,6 +76,13 @@ async def test_one_direction(sender_client, receiver_client, receiver_user_id):
|
||||||
msg = {'id': str(uuid4()), 'ts': send_msg_time.microsecond}
|
msg = {'id': str(uuid4()), 'ts': send_msg_time.microsecond}
|
||||||
resp = (await sender_client.room_send(new_test_room_id, 'm.room.message', {'body': json.dumps(msg), 'msgtype': 'm.room.message'}))
|
resp = (await sender_client.room_send(new_test_room_id, 'm.room.message', {'body': json.dumps(msg), 'msgtype': 'm.room.message'}))
|
||||||
if isinstance(resp, RoomSendError):
|
if isinstance(resp, RoomSendError):
|
||||||
|
await sender_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
|
await sender_client.room_forget(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
|
await receiver_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
|
await receiver_client.room_forget(new_test_room_id)
|
||||||
return f'UNKNOWN: failed to send message "{resp}', nagios.UNKNOWN
|
return f'UNKNOWN: failed to send message "{resp}', nagios.UNKNOWN
|
||||||
msg_event_id = resp.event_id
|
msg_event_id = resp.event_id
|
||||||
|
|
||||||
|
@ -89,16 +96,22 @@ async def test_one_direction(sender_client, receiver_client, receiver_user_id):
|
||||||
break
|
break
|
||||||
if (datetime.now() - start_check).total_seconds() >= args.timeout:
|
if (datetime.now() - start_check).total_seconds() >= args.timeout:
|
||||||
await sender_client.room_leave(new_test_room_id)
|
await sender_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await sender_client.room_forget(new_test_room_id)
|
await sender_client.room_forget(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await receiver_client.room_leave(new_test_room_id)
|
await receiver_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await receiver_client.room_forget(new_test_room_id)
|
await receiver_client.room_forget(new_test_room_id)
|
||||||
return "CRITICAL: timeout - receiver did not recieve the sender's message.", nagios.CRITICAL
|
return "CRITICAL: timeout - receiver did not recieve the sender's message.", nagios.CRITICAL
|
||||||
|
|
||||||
# Double check everything makes sense
|
# Double check everything makes sense
|
||||||
if not msg == recv_msg:
|
if not msg == recv_msg:
|
||||||
await sender_client.room_leave(new_test_room_id)
|
await sender_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await sender_client.room_forget(new_test_room_id)
|
await sender_client.room_forget(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await receiver_client.room_leave(new_test_room_id)
|
await receiver_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await receiver_client.room_forget(new_test_room_id)
|
await receiver_client.room_forget(new_test_room_id)
|
||||||
return "CRITICAL: sender's message did not match the receiver's.", nagios.CRITICAL
|
return "CRITICAL: sender's message did not match the receiver's.", nagios.CRITICAL
|
||||||
|
|
||||||
|
@ -107,11 +120,14 @@ async def test_one_direction(sender_client, receiver_client, receiver_user_id):
|
||||||
|
|
||||||
# Clean up the rooms
|
# Clean up the rooms
|
||||||
await sender_client.room_leave(new_test_room_id)
|
await sender_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await sender_client.room_forget(new_test_room_id)
|
await sender_client.room_forget(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await receiver_client.room_leave(new_test_room_id)
|
await receiver_client.room_leave(new_test_room_id)
|
||||||
|
time.sleep(1)
|
||||||
await receiver_client.room_forget(new_test_room_id)
|
await receiver_client.room_forget(new_test_room_id)
|
||||||
|
|
||||||
return bot1_msg_delta, True
|
return bot1_msg_delta, nagios.OK
|
||||||
|
|
||||||
|
|
||||||
async def login(user_id, passwd, homeserver, config_file=None):
|
async def login(user_id, passwd, homeserver, config_file=None):
|
||||||
|
@ -149,10 +165,10 @@ async def main() -> None:
|
||||||
|
|
||||||
nagios_output = nagios.OK
|
nagios_output = nagios.OK
|
||||||
|
|
||||||
if not bot1_output_code:
|
if bot1_output_code != nagios.OK:
|
||||||
print(bot1_output_msg)
|
print(bot1_output_msg)
|
||||||
nagios_output = bot1_output_code
|
nagios_output = bot1_output_code
|
||||||
if not bot2_output_code:
|
if bot2_output_code != nagios.OK:
|
||||||
print(bot2_output_msg)
|
print(bot2_output_msg)
|
||||||
if nagios_output < bot2_output_code:
|
if nagios_output < bot2_output_code:
|
||||||
# Only set the code if our code is more severe
|
# Only set the code if our code is more severe
|
|
@ -6,8 +6,8 @@ import time
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
import nagios
|
from checker import nagios
|
||||||
from grafana import get_avg_python_gc_time, get_event_send_time, get_outgoing_http_request_rate, get_waiting_for_db
|
from checker.synapse_grafana import get_avg_python_gc_time, get_event_send_time, get_outgoing_http_request_rate, get_waiting_for_db
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Process some integers.')
|
parser = argparse.ArgumentParser(description='Process some integers.')
|
||||||
parser.add_argument('--grafana-server', required=True, help='Grafana server.')
|
parser.add_argument('--grafana-server', required=True, help='Grafana server.')
|
||||||
|
@ -28,10 +28,10 @@ if args.type == 'gc-time':
|
||||||
try:
|
try:
|
||||||
python_gc_time_sum = np.round(np.average(get_avg_python_gc_time(args.grafana_api_key, args.interval, args.range, args.grafana_server)), 5)
|
python_gc_time_sum = np.round(np.average(get_avg_python_gc_time(args.grafana_api_key, args.interval, args.range, args.grafana_server)), 5)
|
||||||
if python_gc_time_sum >= python_gc_time_sum_MAX:
|
if python_gc_time_sum >= python_gc_time_sum_MAX:
|
||||||
print(f'CRITICAL: average GC time per collection is {python_gc_time_sum} sec.')
|
print(f"CRITICAL: average GC time per collection is {python_gc_time_sum} sec. |'garbage-collection'={python_gc_time_sum}s;;;")
|
||||||
sys.exit(nagios.CRITICAL)
|
sys.exit(nagios.CRITICAL)
|
||||||
else:
|
else:
|
||||||
print(f'OK: average GC time per collection is {python_gc_time_sum} sec.')
|
print(f"OK: average GC time per collection is {python_gc_time_sum} sec. |'garbage-collection'={python_gc_time_sum}s;;;")
|
||||||
sys.exit(nagios.OK)
|
sys.exit(nagios.OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'UNKNOWN: failed to check avg. GC time "{e}"')
|
print(f'UNKNOWN: failed to check avg. GC time "{e}"')
|
||||||
|
@ -53,10 +53,10 @@ elif args.type == 'response-time':
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
response_time = np.round(np.average(response_times), 2)
|
response_time = np.round(np.average(response_times), 2)
|
||||||
if response_time > response_time_MAX:
|
if response_time > response_time_MAX:
|
||||||
print(f'CRITICAL: response time is {response_time} sec.')
|
print(f"CRITICAL: response time is {response_time} sec. |'response-time'={response_time}s;;;")
|
||||||
sys.exit(nagios.CRITICAL)
|
sys.exit(nagios.CRITICAL)
|
||||||
else:
|
else:
|
||||||
print(f'OK: response time is {response_time} sec.')
|
print(f"OK: response time is {response_time} sec. |'response-time'={response_time}s;;;")
|
||||||
sys.exit(nagios.OK)
|
sys.exit(nagios.OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'UNKNOWN: failed to check response time "{e}"')
|
print(f'UNKNOWN: failed to check response time "{e}"')
|
||||||
|
@ -64,30 +64,33 @@ elif args.type == 'response-time':
|
||||||
elif args.type == 'outgoing-http-rate':
|
elif args.type == 'outgoing-http-rate':
|
||||||
# outgoing req/sec
|
# outgoing req/sec
|
||||||
outgoing_http_request_rate_MAX = 10 if not args.crit else args.crit
|
outgoing_http_request_rate_MAX = 10 if not args.crit else args.crit
|
||||||
# try:
|
try:
|
||||||
outgoing_http_request_rate = get_outgoing_http_request_rate(args.grafana_api_key, args.interval, args.range, args.grafana_server)
|
outgoing_http_request_rate = get_outgoing_http_request_rate(args.grafana_api_key, args.interval, args.range, args.grafana_server)
|
||||||
failed = {}
|
failed = {}
|
||||||
for k, v in outgoing_http_request_rate.items():
|
perf_data = '|'
|
||||||
if v > outgoing_http_request_rate_MAX:
|
for k, v in outgoing_http_request_rate.items():
|
||||||
failed[k] = v
|
perf_data = perf_data + f"'{k}'={v}s;;; "
|
||||||
if len(failed.keys()) > 0:
|
if v > outgoing_http_request_rate_MAX:
|
||||||
print(f'CRITICAL: outgoing HTTP request rate for {failed} req/sec.')
|
failed[k] = v
|
||||||
sys.exit(nagios.CRITICAL)
|
|
||||||
print(f'OK: outgoing HTTP request rate is {outgoing_http_request_rate} req/sec.')
|
if len(failed.keys()) > 0:
|
||||||
sys.exit(nagios.OK)
|
print(f'CRITICAL: outgoing HTTP request rate for {failed} req/sec.', perf_data)
|
||||||
# except Exception as e:
|
sys.exit(nagios.CRITICAL)
|
||||||
# print(f'UNKNOWN: failed to check outgoing HTTP request rate "{e}"')
|
print(f'OK: outgoing HTTP request rate is {outgoing_http_request_rate} req/sec.', perf_data)
|
||||||
# sys.exit(nagios.UNKNOWN)
|
sys.exit(nagios.OK)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'UNKNOWN: failed to check outgoing HTTP request rate "{e}"')
|
||||||
|
sys.exit(nagios.UNKNOWN)
|
||||||
elif args.type == 'avg-send':
|
elif args.type == 'avg-send':
|
||||||
# Average send time in seconds
|
# Average send time in seconds
|
||||||
event_send_time_MAX = 1 if not args.crit else args.crit
|
event_send_time_MAX = 1 if not args.crit else args.crit
|
||||||
try:
|
try:
|
||||||
event_send_time = get_event_send_time(args.grafana_api_key, args.interval, args.range, args.grafana_server)
|
event_send_time = get_event_send_time(args.grafana_api_key, args.interval, args.range, args.grafana_server)
|
||||||
if event_send_time > event_send_time_MAX:
|
if event_send_time > event_send_time_MAX:
|
||||||
print(f'CRITICAL: average message send time is {event_send_time} sec.')
|
print(f"CRITICAL: average message send time is {event_send_time} sec. |'avg-send-time'={event_send_time}s;;;")
|
||||||
sys.exit(nagios.CRITICAL)
|
sys.exit(nagios.CRITICAL)
|
||||||
else:
|
else:
|
||||||
print(f'OK: average message send time is {event_send_time} sec.')
|
print(f"OK: average message send time is {event_send_time} sec. |'avg-send-time'={event_send_time}s;;;")
|
||||||
sys.exit(nagios.OK)
|
sys.exit(nagios.OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'UNKNOWN: failed to check average message send time "{e}"')
|
print(f'UNKNOWN: failed to check average message send time "{e}"')
|
||||||
|
@ -98,10 +101,10 @@ elif args.type == 'db-lag':
|
||||||
try:
|
try:
|
||||||
db_lag = get_waiting_for_db(args.grafana_api_key, args.interval, args.range, args.grafana_server)
|
db_lag = get_waiting_for_db(args.grafana_api_key, args.interval, args.range, args.grafana_server)
|
||||||
if db_lag > db_lag_MAX:
|
if db_lag > db_lag_MAX:
|
||||||
print(f'CRITICAL: DB lag is {db_lag} sec.')
|
print(f"CRITICAL: DB lag is {db_lag} sec. |'db-lag'={db_lag}s;;;")
|
||||||
sys.exit(nagios.CRITICAL)
|
sys.exit(nagios.CRITICAL)
|
||||||
else:
|
else:
|
||||||
print(f'OK: DB lag is {db_lag} sec.')
|
print(f"OK: DB lag is {db_lag} sec. |'db-lag'={db_lag}s;;;")
|
||||||
sys.exit(nagios.OK)
|
sys.exit(nagios.OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'UNKNOWN: failed to check DB lag "{e}"')
|
print(f'UNKNOWN: failed to check DB lag "{e}"')
|
|
@ -7,15 +7,14 @@ import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
import aiofiles.os
|
|
||||||
import magic
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import requests
|
import requests
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from nio import AsyncClient, AsyncClientConfig, LoginResponse, UploadResponse
|
from nio import AsyncClient, AsyncClientConfig, LoginResponse, RoomSendError
|
||||||
from urllib3.exceptions import InsecureRequestWarning
|
from urllib3.exceptions import InsecureRequestWarning
|
||||||
|
|
||||||
import nagios
|
from checker import nagios
|
||||||
|
from checker.synapse_client import send_image, write_login_details_to_disk
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='')
|
parser = argparse.ArgumentParser(description='')
|
||||||
parser.add_argument('--user', required=True, help='User ID for the bot.')
|
parser.add_argument('--user', required=True, help='User ID for the bot.')
|
||||||
|
@ -30,8 +29,6 @@ parser.add_argument('--warn', type=float, default=2.0, help='Manually set warn l
|
||||||
parser.add_argument('--crit', type=float, default=2.5, help='Manually set critical level.')
|
parser.add_argument('--crit', type=float, default=2.5, help='Manually set critical level.')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
CONFIG_FILE = args.auth_file
|
|
||||||
|
|
||||||
|
|
||||||
def verify_media_header(header: str, header_dict: dict, good_value: str = None, warn_value: str = None, critical_value: str = None):
|
def verify_media_header(header: str, header_dict: dict, good_value: str = None, warn_value: str = None, critical_value: str = None):
|
||||||
"""
|
"""
|
||||||
|
@ -53,98 +50,42 @@ def verify_media_header(header: str, header_dict: dict, good_value: str = None,
|
||||||
return f'OK: {header} is present with value "{header_value}"', nagios.OK
|
return f'OK: {header} is present with value "{header_value}"', nagios.OK
|
||||||
|
|
||||||
|
|
||||||
def write_details_to_disk(resp: LoginResponse, homeserver) -> None:
|
|
||||||
"""Writes the required login details to disk so we can log in later without
|
|
||||||
using a password.
|
|
||||||
Arguments:
|
|
||||||
resp {LoginResponse} -- the successful client login response.
|
|
||||||
homeserver -- URL of homeserver, e.g. "https://matrix.example.org"
|
|
||||||
"""
|
|
||||||
# open the config file in write-mode
|
|
||||||
with open(CONFIG_FILE, "w") as f:
|
|
||||||
# write the login details to disk
|
|
||||||
json.dump({"homeserver": homeserver, # e.g. "https://matrix.example.org"
|
|
||||||
"user_id": resp.user_id, # e.g. "@user:example.org"
|
|
||||||
"device_id": resp.device_id, # device ID, 10 uppercase letters
|
|
||||||
"access_token": resp.access_token, # cryptogr. access token
|
|
||||||
}, f, )
|
|
||||||
|
|
||||||
|
|
||||||
async def send_image(client, room_id, image):
|
|
||||||
"""Send image to room.
|
|
||||||
Arguments:
|
|
||||||
---------
|
|
||||||
client : Client
|
|
||||||
room_id : str
|
|
||||||
image : str, file name of image
|
|
||||||
This is a working example for a JPG image.
|
|
||||||
"content": {
|
|
||||||
"body": "someimage.jpg",
|
|
||||||
"info": {
|
|
||||||
"size": 5420,
|
|
||||||
"mimetype": "image/jpeg",
|
|
||||||
"thumbnail_info": {
|
|
||||||
"w": 100,
|
|
||||||
"h": 100,
|
|
||||||
"mimetype": "image/jpeg",
|
|
||||||
"size": 2106
|
|
||||||
},
|
|
||||||
"w": 100,
|
|
||||||
"h": 100,
|
|
||||||
"thumbnail_url": "mxc://example.com/SomeStrangeThumbnailUriKey"
|
|
||||||
},
|
|
||||||
"msgtype": "m.image",
|
|
||||||
"url": "mxc://example.com/SomeStrangeUriKey"
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
mime_type = magic.from_file(image, mime=True) # e.g. "image/jpeg"
|
|
||||||
if not mime_type.startswith("image/"):
|
|
||||||
print(f'UNKNOWN: wrong mime type "{mime_type}"')
|
|
||||||
sys.exit(nagios.UNKNOWN)
|
|
||||||
|
|
||||||
im = Image.open(image)
|
|
||||||
(width, height) = im.size # im.size returns (width,height) tuple
|
|
||||||
|
|
||||||
# first do an upload of image, then send URI of upload to room
|
|
||||||
file_stat = await aiofiles.os.stat(image)
|
|
||||||
async with aiofiles.open(image, "r+b") as f:
|
|
||||||
resp, maybe_keys = await client.upload(f, content_type=mime_type, # image/jpeg
|
|
||||||
filename=os.path.basename(image), filesize=file_stat.st_size, )
|
|
||||||
if not isinstance(resp, UploadResponse):
|
|
||||||
print(f'UNKNOWN: failed to upload image "{resp}"')
|
|
||||||
sys.exit(nagios.UNKNOWN)
|
|
||||||
|
|
||||||
content = {"body": os.path.basename(image), # descriptive title
|
|
||||||
"info": {"size": file_stat.st_size, "mimetype": mime_type, "thumbnail_info": None, # TODO
|
|
||||||
"w": width, # width in pixel
|
|
||||||
"h": height, # height in pixel
|
|
||||||
"thumbnail_url": None, # TODO
|
|
||||||
}, "msgtype": "m.image", "url": resp.content_uri, }
|
|
||||||
|
|
||||||
try:
|
|
||||||
return await client.room_send(room_id, message_type="m.room.message", content=content)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Image send of file {image} failed.")
|
|
||||||
print(f'UNKNOWN: failed to send image event "{e}"')
|
|
||||||
sys.exit(nagios.UNKNOWN)
|
|
||||||
|
|
||||||
|
|
||||||
async def main() -> None:
|
async def main() -> None:
|
||||||
|
async def cleanup(client, test_image_path, image_event_id=None):
|
||||||
|
global exit_code
|
||||||
|
# Clean up
|
||||||
|
if image_event_id:
|
||||||
|
await client.room_redact(args.room, image_event_id)
|
||||||
|
os.remove(test_image_path)
|
||||||
|
await client.close()
|
||||||
|
|
||||||
|
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
||||||
|
try:
|
||||||
|
r = requests.delete(f'{args.admin_endpoint}/_synapse/admin/v1/users/{args.user}/media', headers={'Authorization': f'Bearer {client.access_token}'}, verify=False)
|
||||||
|
if r.status_code != 200:
|
||||||
|
if nagios.WARNING < exit_code:
|
||||||
|
exit_code = nagios.WARNING
|
||||||
|
print(f"WARN: failed to purge media for this user, request failed with '{r.text}'")
|
||||||
|
except Exception as e:
|
||||||
|
if nagios.WARNING < exit_code:
|
||||||
|
exit_code = nagios.WARNING
|
||||||
|
print(f"WARN: failed to purge media for this user '{e}'")
|
||||||
|
|
||||||
client = AsyncClient(args.hs, args.user, config=AsyncClientConfig(request_timeout=args.timeout, max_timeout_retry_wait_time=10))
|
client = AsyncClient(args.hs, args.user, config=AsyncClientConfig(request_timeout=args.timeout, max_timeout_retry_wait_time=10))
|
||||||
if args.auth_file:
|
if args.auth_file:
|
||||||
# If there are no previously-saved credentials, we'll use the password
|
# If there are no previously-saved credentials, we'll use the password
|
||||||
if not os.path.exists(CONFIG_FILE):
|
if not os.path.exists(args.auth_file):
|
||||||
resp = await client.login(args.pw)
|
resp = await client.login(args.pw)
|
||||||
|
|
||||||
# check that we logged in successfully
|
# check that we logged in successfully
|
||||||
if isinstance(resp, LoginResponse):
|
if isinstance(resp, LoginResponse):
|
||||||
write_details_to_disk(resp, args.hs)
|
write_login_details_to_disk(resp, args.hs, args.auth_file)
|
||||||
else:
|
else:
|
||||||
print(f'UNKNOWN: failed to log in "{resp}"')
|
print(f'UNKNOWN: failed to log in "{resp}"')
|
||||||
sys.exit(nagios.UNKNOWN)
|
sys.exit(nagios.UNKNOWN)
|
||||||
else:
|
else:
|
||||||
# Otherwise the config file exists, so we'll use the stored credentials
|
# Otherwise the config file exists, so we'll use the stored credentials
|
||||||
with open(CONFIG_FILE, "r") as f:
|
with open(args.auth_file, "r") as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
client = AsyncClient(config["homeserver"])
|
client = AsyncClient(config["homeserver"])
|
||||||
client.access_token = config["access_token"]
|
client.access_token = config["access_token"]
|
||||||
|
@ -163,7 +104,12 @@ async def main() -> None:
|
||||||
im.save(test_image_path)
|
im.save(test_image_path)
|
||||||
|
|
||||||
# Send the image and get the event ID
|
# Send the image and get the event ID
|
||||||
image_event_id = (await send_image(client, args.room, test_image_path)).event_id
|
image_event_id = (await send_image(client, args.room, test_image_path))
|
||||||
|
if isinstance(image_event_id, RoomSendError):
|
||||||
|
await cleanup(client, test_image_path)
|
||||||
|
print(f'UNKNOWN: failed to send message "{image_event_id}"')
|
||||||
|
sys.exit(nagios.UNKNOWN)
|
||||||
|
image_event_id = image_event_id.event_id
|
||||||
|
|
||||||
# Get the event
|
# Get the event
|
||||||
image_event = (await client.room_get_event(args.room, image_event_id)).event
|
image_event = (await client.room_get_event(args.room, image_event_id)).event
|
||||||
|
@ -186,29 +132,21 @@ async def main() -> None:
|
||||||
print(f'OK: media CDN domain is "{domain}"')
|
print(f'OK: media CDN domain is "{domain}"')
|
||||||
|
|
||||||
results = [verify_media_header('synapse-media-local-status', headers), verify_media_header('synapse-media-s3-status', headers, good_value='200'), verify_media_header('synapse-media-server', headers, good_value='s3'),
|
results = [verify_media_header('synapse-media-local-status', headers), verify_media_header('synapse-media-s3-status', headers, good_value='200'), verify_media_header('synapse-media-server', headers, good_value='s3'),
|
||||||
verify_media_header('Server', headers, good_value='cloudflare')]
|
verify_media_header('Server', headers, good_value='cloudflare')]
|
||||||
for header_chk, code in results:
|
for header_chk, code in results:
|
||||||
if code != nagios.OK:
|
if code != nagios.OK:
|
||||||
exit_code = code
|
exit_code = code
|
||||||
print(header_chk)
|
print(header_chk)
|
||||||
|
|
||||||
# Clean up
|
# Make sure we aren't redirected if we're a Synapse server
|
||||||
await client.room_redact(args.room, image_event_id)
|
test = requests.head(target_file_url, headers={'User-Agent': 'Synapse/1.77.3'}, allow_redirects=False)
|
||||||
os.remove(test_image_path)
|
if test.status_code != 200:
|
||||||
await client.close()
|
print('CRITICAL: Synapse user-agent redirected with status code', test.status_code)
|
||||||
|
exit_code = nagios.CRITICAL
|
||||||
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
else:
|
||||||
try:
|
print(f'OK: Synapse user-agent not redirected.')
|
||||||
r = requests.delete(f'{args.admin_endpoint}/_synapse/admin/v1/users/{args.user}/media', headers={'Authorization': f'Bearer {client.access_token}'}, verify=False)
|
|
||||||
if r.status_code != 200:
|
|
||||||
if nagios.WARNING < exit_code:
|
|
||||||
exit_code = nagios.WARNING
|
|
||||||
print(f"WARN: failed to purge media for this user, request failed with '{r.text}'")
|
|
||||||
except Exception as e:
|
|
||||||
if nagios.WARNING < exit_code:
|
|
||||||
exit_code = nagios.WARNING
|
|
||||||
print(f"WARN: failed to purge media for this user '{e}'")
|
|
||||||
|
|
||||||
|
await cleanup(client, test_image_path, image_event_id=image_event_id)
|
||||||
sys.exit(exit_code)
|
sys.exit(exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
@ -217,4 +155,7 @@ if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'UNKNOWN: exception "{e}"')
|
print(f'UNKNOWN: exception "{e}"')
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
print(traceback.format_exc())
|
||||||
sys.exit(nagios.UNKNOWN)
|
sys.exit(nagios.UNKNOWN)
|
|
@ -6,7 +6,7 @@ import sys
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
import nagios
|
from checker import nagios
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='')
|
parser = argparse.ArgumentParser(description='')
|
||||||
parser.add_argument('--metrics-endpoint', required=True, help='Target URL to scrape.')
|
parser.add_argument('--metrics-endpoint', required=True, help='Target URL to scrape.')
|
||||||
|
@ -19,7 +19,7 @@ parser.add_argument('--crit', type=float, default=30, help='Manually set critica
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.prometheus:
|
if args.prometheus:
|
||||||
from prometheus import parse_metrics
|
from checker.prometheus import parse_metrics
|
||||||
|
|
||||||
r = requests.get(args.metrics_endpoint)
|
r = requests.get(args.metrics_endpoint)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
|
@ -81,7 +81,6 @@ else:
|
||||||
data = {}
|
data = {}
|
||||||
for item in tooltips:
|
for item in tooltips:
|
||||||
m = re.match(r'<span class="tooltip">\s*Send: (.*?)\s*<br\/>\s*Receive: (.*?)\s*<\/span>', str(item))
|
m = re.match(r'<span class="tooltip">\s*Send: (.*?)\s*<br\/>\s*Receive: (.*?)\s*<\/span>', str(item))
|
||||||
print(item)
|
|
||||||
if m:
|
if m:
|
||||||
domain = item.parent.parent.find('span', {'class': 'domain'}).text
|
domain = item.parent.parent.find('span', {'class': 'domain'}).text
|
||||||
data[domain] = {
|
data[domain] = {
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
warn_ico = "⚠"
|
||||||
|
error_ico = "❌"
|
||||||
|
ok_ico = "✅"
|
||||||
|
question_ico = "❓"
|
||||||
|
host_ico = '🖥️'
|
||||||
|
service_ico = '⚙️'
|
||||||
|
|
||||||
|
|
||||||
|
def choose_icon(state):
|
||||||
|
if state == 'UP':
|
||||||
|
return ok_ico
|
||||||
|
elif state == 'DOWN':
|
||||||
|
return error_ico
|
||||||
|
elif state == 'UNKNOWN':
|
||||||
|
return question_ico
|
||||||
|
elif state == 'OK':
|
||||||
|
return ok_ico
|
||||||
|
elif state == 'WARNING':
|
||||||
|
return warn_ico
|
||||||
|
elif state == 'CRITICAL':
|
||||||
|
return error_ico
|
||||||
|
else:
|
||||||
|
raise Exception('No state to icon matched.')
|
||||||
|
|
||||||
|
|
||||||
|
def choose_color(state):
|
||||||
|
if state == 'UP':
|
||||||
|
return '#44bb77'
|
||||||
|
elif state == 'DOWN':
|
||||||
|
return '#ff5566'
|
||||||
|
elif state == 'UNKNOWN':
|
||||||
|
return '#aa44ff'
|
||||||
|
elif state == 'OK':
|
||||||
|
return '#44bb77'
|
||||||
|
elif state == 'WARNING':
|
||||||
|
return '#ffaa44'
|
||||||
|
elif state == 'CRITICAL':
|
||||||
|
return '#ff5566'
|
||||||
|
else:
|
||||||
|
raise Exception('No state to color matched.')
|
||||||
|
|
||||||
|
|
||||||
|
def newline_to_formatted_html(string):
|
||||||
|
if '\n' in string:
|
||||||
|
string = f'<br><pre>{string}</pre>'
|
||||||
|
return string
|
||||||
|
|
||||||
|
|
||||||
|
def build_msg(host_name, host_display_name, state, date_str, output, service_name=None, service_display_name='', address='', comment='', author='', icinga2_url=''):
|
||||||
|
if service_name:
|
||||||
|
item = f'**{service_display_name}** on **{host_display_name}**'
|
||||||
|
icon = service_ico
|
||||||
|
else:
|
||||||
|
item = f'**{host_display_name}**'
|
||||||
|
icon = host_ico
|
||||||
|
icon = f'{choose_icon(state)} {icon}'
|
||||||
|
|
||||||
|
if address:
|
||||||
|
address = f'<br>**IP:** {address}'
|
||||||
|
if comment and author:
|
||||||
|
comment = f'<br>**Comment by {author}:** {newline_to_formatted_html(comment)}'
|
||||||
|
if icinga2_url:
|
||||||
|
icinga2_url = icinga2_url.strip("/")
|
||||||
|
if service_name:
|
||||||
|
icinga2_url = f'<br>[Quick Link]({icinga2_url}/icingadb/service?name={service_name.replace(" ", "%20")}&host.name={host_name.replace(" ", "%20")})'
|
||||||
|
elif host_name:
|
||||||
|
icinga2_url = f'<br>[Quick Link]({icinga2_url}/icingadb/host?name={host_name.replace(" ", "+")})'
|
||||||
|
|
||||||
|
msg = f"""{icon} {item} is <font color="{choose_color(state)}">{state}</font> <br>
|
||||||
|
**When:** {date_str}. <br>
|
||||||
|
**Info:** {newline_to_formatted_html(output)}{address}{comment}{icinga2_url}"""
|
||||||
|
return msg
|
|
@ -0,0 +1,145 @@
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import aiofiles.os
|
||||||
|
import magic
|
||||||
|
import markdown
|
||||||
|
from PIL import Image
|
||||||
|
from nio import AsyncClient, LoginResponse, RoomSendError, UploadResponse
|
||||||
|
|
||||||
|
from . import nagios
|
||||||
|
|
||||||
|
|
||||||
|
def handle_err(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
crit, ret = func(*args, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"UNKNOWN: exception '{e}'")
|
||||||
|
sys.exit(nagios.UNKNOWN)
|
||||||
|
if crit:
|
||||||
|
print(f"CRITICAL: {crit}")
|
||||||
|
sys.exit(nagios.CRITICAL)
|
||||||
|
else:
|
||||||
|
return ret
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def write_login_details_to_disk(resp: LoginResponse, homeserver, config_file) -> None:
|
||||||
|
"""Writes the required login details to disk so we can log in later without
|
||||||
|
using a password.
|
||||||
|
Arguments:
|
||||||
|
resp {LoginResponse} -- the successful client login response.
|
||||||
|
homeserver -- URL of homeserver, e.g. "https://matrix.example.org"
|
||||||
|
"""
|
||||||
|
# open the config file in write-mode
|
||||||
|
with open(config_file, "w") as f:
|
||||||
|
# write the login details to disk
|
||||||
|
json.dump({"homeserver": homeserver, # e.g. "https://matrix.example.org"
|
||||||
|
"user_id": resp.user_id, # e.g. "@user:example.org"
|
||||||
|
"device_id": resp.device_id, # device ID, 10 uppercase letters
|
||||||
|
"access_token": resp.access_token, # cryptogr. access token
|
||||||
|
}, f, )
|
||||||
|
|
||||||
|
|
||||||
|
async def send_image(client, room_id, image):
|
||||||
|
"""Send image to room.
|
||||||
|
Arguments:
|
||||||
|
---------
|
||||||
|
client : Client
|
||||||
|
room_id : str
|
||||||
|
image : str, file name of image
|
||||||
|
This is a working example for a JPG image.
|
||||||
|
"content": {
|
||||||
|
"body": "someimage.jpg",
|
||||||
|
"info": {
|
||||||
|
"size": 5420,
|
||||||
|
"mimetype": "image/jpeg",
|
||||||
|
"thumbnail_info": {
|
||||||
|
"w": 100,
|
||||||
|
"h": 100,
|
||||||
|
"mimetype": "image/jpeg",
|
||||||
|
"size": 2106
|
||||||
|
},
|
||||||
|
"w": 100,
|
||||||
|
"h": 100,
|
||||||
|
"thumbnail_url": "mxc://example.com/SomeStrangeThumbnailUriKey"
|
||||||
|
},
|
||||||
|
"msgtype": "m.image",
|
||||||
|
"url": "mxc://example.com/SomeStrangeUriKey"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
mime_type = magic.from_file(image, mime=True) # e.g. "image/jpeg"
|
||||||
|
if not mime_type.startswith("image/"):
|
||||||
|
print(f'UNKNOWN: wrong mime type "{mime_type}"')
|
||||||
|
sys.exit(nagios.UNKNOWN)
|
||||||
|
|
||||||
|
im = Image.open(image)
|
||||||
|
(width, height) = im.size # im.size returns (width,height) tuple
|
||||||
|
|
||||||
|
# first do an upload of image, then send URI of upload to room
|
||||||
|
file_stat = await aiofiles.os.stat(image)
|
||||||
|
async with aiofiles.open(image, "r+b") as f:
|
||||||
|
resp, maybe_keys = await client.upload(f, content_type=mime_type, # image/jpeg
|
||||||
|
filename=os.path.basename(image), filesize=file_stat.st_size, )
|
||||||
|
if not isinstance(resp, UploadResponse):
|
||||||
|
print(f'UNKNOWN: failed to upload image "{resp}"')
|
||||||
|
sys.exit(nagios.UNKNOWN)
|
||||||
|
|
||||||
|
content = {"body": os.path.basename(image), # descriptive title
|
||||||
|
"info": {"size": file_stat.st_size, "mimetype": mime_type, "thumbnail_info": None, # TODO
|
||||||
|
"w": width, # width in pixel
|
||||||
|
"h": height, # height in pixel
|
||||||
|
"thumbnail_url": None, # TODO
|
||||||
|
}, "msgtype": "m.image", "url": resp.content_uri, }
|
||||||
|
|
||||||
|
try:
|
||||||
|
return await client.room_send(room_id, message_type="m.room.message", content=content)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Image send of file {image} failed.")
|
||||||
|
print(f'UNKNOWN: failed to send image event "{e}"')
|
||||||
|
sys.exit(nagios.UNKNOWN)
|
||||||
|
|
||||||
|
|
||||||
|
def send_msg(client, room, msg):
|
||||||
|
async def inner(client, room, msg):
|
||||||
|
r = await client.room_send(room_id=room, message_type="m.room.message", content={"msgtype": "m.text", "body": msg, "format": "org.matrix.custom.html", "formatted_body": markdown.markdown(msg), }, )
|
||||||
|
if isinstance(r, RoomSendError):
|
||||||
|
print(r)
|
||||||
|
await client.close()
|
||||||
|
|
||||||
|
return asyncio.run(inner(client, room, msg))
|
||||||
|
|
||||||
|
|
||||||
|
def login(user, pw, hs, auth_file, room):
|
||||||
|
async def inner(user, pw, hs, auth_file, room):
|
||||||
|
client = AsyncClient(hs, user)
|
||||||
|
if auth_file:
|
||||||
|
# If there are no previously-saved credentials, we'll use the password
|
||||||
|
if not os.path.exists(auth_file):
|
||||||
|
resp = await client.login(pw)
|
||||||
|
# check that we logged in successfully
|
||||||
|
if isinstance(resp, LoginResponse):
|
||||||
|
write_login_details_to_disk(resp, hs, auth_file)
|
||||||
|
else:
|
||||||
|
print(f'Failed to log in "{resp}"')
|
||||||
|
else:
|
||||||
|
# Otherwise the config file exists, so we'll use the stored credentials
|
||||||
|
with open(auth_file, "r") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
client = AsyncClient(config["homeserver"])
|
||||||
|
client.access_token = config["access_token"]
|
||||||
|
client.user_id = config["user_id"]
|
||||||
|
client.device_id = config["device_id"]
|
||||||
|
else:
|
||||||
|
await client.login(pw)
|
||||||
|
|
||||||
|
await client.join(room)
|
||||||
|
x = client.access_token
|
||||||
|
await client.close()
|
||||||
|
return x, client
|
||||||
|
|
||||||
|
return asyncio.run(inner(user, pw, hs, auth_file, room))
|
|
@ -0,0 +1,40 @@
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
import checker.synapse_client as synapse_client
|
||||||
|
from checker.notify import build_msg
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='')
|
||||||
|
parser.add_argument('--user', required=True, help='User ID for the bot.')
|
||||||
|
parser.add_argument('--pw', required=True, help='Password for the bot.')
|
||||||
|
parser.add_argument('--hs', required=True, help='Homeserver of the bot.')
|
||||||
|
parser.add_argument('--room', required=True, help='The room the bot should send its messages in.')
|
||||||
|
parser.add_argument('--auth-file', help="File to cache the bot's login details to.")
|
||||||
|
|
||||||
|
parser.add_argument('--longdatetime', required=True, help='$icinga.long_date_time$')
|
||||||
|
parser.add_argument('--hostname', required=True, help='$host.name$')
|
||||||
|
parser.add_argument('--hostdisplayname', required=True, help='$host.display_name$')
|
||||||
|
parser.add_argument('--hoststate', required=True, help='$host.state$')
|
||||||
|
parser.add_argument('--hostoutput', required=True, help='$host.output$')
|
||||||
|
parser.add_argument('--notificationtype', required=True, help='$notification.type$')
|
||||||
|
|
||||||
|
parser.add_argument('--hostaddress', required=False, help='$address$')
|
||||||
|
parser.add_argument('--notificationauthor', required=False, help='$notification.author$')
|
||||||
|
parser.add_argument('--notificationcomment', required=False, help='$notification.comment$')
|
||||||
|
parser.add_argument('--icinga2weburl', required=False, help='$notification.icingaweb2url$')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
msg = build_msg(
|
||||||
|
host_name=args.hostname,
|
||||||
|
host_display_name=args.hostdisplayname,
|
||||||
|
state=args.hoststate,
|
||||||
|
date_str=args.longdatetime,
|
||||||
|
output=args.hostoutput,
|
||||||
|
address=args.hostaddress,
|
||||||
|
comment=args.notificationcomment,
|
||||||
|
author=args.notificationauthor,
|
||||||
|
icinga2_url=args.icinga2weburl
|
||||||
|
)
|
||||||
|
access_token, client = synapse_client.login(args.user, args.pw, args.hs, args.auth_file, args.room)
|
||||||
|
synapse_client.send_msg(client, args.room, msg)
|
|
@ -0,0 +1,33 @@
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
import checker.synapse_client as synapse_client
|
||||||
|
from checker.notify import build_msg
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='')
|
||||||
|
parser.add_argument('--user', required=True, help='User ID for the bot.')
|
||||||
|
parser.add_argument('--pw', required=True, help='Password for the bot.')
|
||||||
|
parser.add_argument('--hs', required=True, help='Homeserver of the bot.')
|
||||||
|
parser.add_argument('--room', required=True, help='The room the bot should send its messages in.')
|
||||||
|
parser.add_argument('--auth-file', help="File to cache the bot's login details to.")
|
||||||
|
|
||||||
|
parser.add_argument('--longdatetime', required=True, help='$icinga.long_date_time$')
|
||||||
|
parser.add_argument('--servicename', required=True, help='$service.name$')
|
||||||
|
parser.add_argument('--servicedisplayname', required=True, help='$service.name$')
|
||||||
|
parser.add_argument('--hostname', required=True, help='$host.name$')
|
||||||
|
parser.add_argument('--hostdisplayname', required=True, help='$host.display_name$')
|
||||||
|
parser.add_argument('--serviceoutput', required=True, help='$service.output$')
|
||||||
|
parser.add_argument('--servicestate', required=True, help='$service.state$')
|
||||||
|
parser.add_argument('--notificationtype', required=True, help='$notification.type$')
|
||||||
|
|
||||||
|
parser.add_argument('--hostaddress', required=False, help='$address$')
|
||||||
|
parser.add_argument('--notificationauthor', required=False, help='$notification.author$')
|
||||||
|
parser.add_argument('--notificationcomment', required=False, help='$notification.comment$')
|
||||||
|
parser.add_argument('--icinga2weburl', required=False, help='$notification.icingaweb2url$')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
msg = build_msg(args.hostname, args.hostdisplayname, args.servicestate, args.longdatetime, args.serviceoutput, args.servicename, args.servicedisplayname, args.hostaddress, args.notificationcomment, args.notificationauthor, args.icinga2weburl)
|
||||||
|
print(msg)
|
||||||
|
access_token, client = synapse_client.login(args.user, args.pw, args.hs, args.auth_file, args.room)
|
||||||
|
synapse_client.send_msg(client, args.room, msg)
|
|
@ -0,0 +1,13 @@
|
||||||
|
prometheus_client
|
||||||
|
requests~=2.28.2
|
||||||
|
numpy~=1.24.2
|
||||||
|
matrix-nio
|
||||||
|
Pillow~=9.4.0
|
||||||
|
python-magic~=0.4.27
|
||||||
|
numpy
|
||||||
|
beautifulsoup4~=4.11.2
|
||||||
|
flask~=2.2.3
|
||||||
|
icinga2api~=0.6.1
|
||||||
|
urllib3~=1.26.14
|
||||||
|
aiofiles~=0.6.0
|
||||||
|
markdown
|
Loading…
Reference in New Issue