Sending Zabbix notifications to Skype (Skype calls are a bonus)

image

It so happened that in the company, due to power outages, the server crashed several times, and administrators found out about this only in the morning when employees could not get to work.

The main problem was that all notifications to administrators were sent by mail - which, as you might guess easily, also fell in.

Then I had the idea - “Let the administrators call in critical situations!”

For implementation and scripts - please, under cat.

For the starting point we take the already installed and configured Zabbix which lacks only a notification system.

In our infrastructure, zabbix is ​​deployed on Debian 7 x64 - which added some frills to the notification process, as Skype could not be launched on this system. For those who have a 32-bit system, the headache does not shine.

So let's get started.

First of all, we need to install Skype and its dependencies:
The system is planned to be very resource-efficient, therefore there will be no graphical shell, as such.

1. Install the basic components.

# Добавляем юзера Skype из-под которого будет запускаться наш сервис
useradd skype
passwd skype
# Устанавливаем x server
apt-get install xvfb
apt-get install fluxbox x11vnc
# Удовлетворяем требования для skype
apt-get install dbus
apt-get install libasound2 libqt4-dbus libqt4-network libqtcore4 libqtgui4 libxss1 libpython2.6 libqt4-xml libaudio2 libmng1 fontconfig liblcms1
apt-get install lib32stdc++6 lib32asound2 ia32-libs libc6-i386 lib32gcc1
# Качаем инсталяшку скайпа с сайта  
wget http://www.skype.com/go/getskype-linux-deb-32 -O skype.deb
# Устанавливаем скайп
dpkg -i skype.deb


If any dependencies remain - apt-get install to help us.

* It is worth noting that Skype is only 32-bit. And on Debian 7 x64 it failed to start. My solution was to install another virtual machine with Debian 7 32-bit and launch Skype on it. The

second step is to install Skype4py - a set of Python scripts / utilities with which we can connect to a Skype instance.

# Скачиваем Skype4Py
wget 'http://sourceforge.net/projects/skype4py/files/skype4py/1.0.31.0/Skype4Py-1.0.31.0.tar.gz/download?use_mirror=switch'
# Распаковуем архив
tar -xzf Skype4Py-1.0.31.0.tar.gz
# Устанавливаем Skype4py
cd Skype4Py-1.0.31.0/
python setup.py install


So, at the moment we have everything we need for work.

The third step is to simplify our future work.
To do this, create several scripts to launch the service more quickly.
1. start-server.sh - this script will start \ stop \ restart Xvfb, fluxbox and Skype itself:

#!/bin/bash
if [[ "$USER" != 'skype' ]]; then
	echo "Please start this script as skype!"
	exit 1
fi
export DISPLAY=:1
dnb=`dirname "$0"`
start() {
	if [[ `ps aux | grep skype | grep "Xvfb :1" | grep -v grep | wc -l` == '0' ]]; then
		echo "starting Xvfb"
		Xvfb :1 -screen 0 800x600x16 &
	else
		echo "Xvfb already running"
	fi
	if [[ `ps aux | grep skype | grep "fluxbox" | grep -v grep | wc -l` == '0' ]]; then
		echo "starting fluxbox"
		sleep 1
		fluxbox &
	else
		echo "fluxbox already running"
	fi
	if [[ `ps -eo pid,user,args | grep skype | awk '{ print $1 " " $3; }' | grep skype | wc -l` == '0' ]]; then
		echo "starting skype"
		sleep 2
		skype &
	else
		echo "skype already running"
	fi
}
stop() {
	if [[ `ps -eo pid,user,args | grep skype | awk '{ print $1 " " $3; }' | grep skype | wc -l` == '0' ]]; then
		echo "skype is NOT running"
	else
		echo "killing skype"
		killall skype
	fi
	"$dnb/start-vnc.sh" stop
	if [[ `ps aux | grep skype | grep "fluxbox" | grep -v grep | wc -l` == '0' ]]; then
		echo "fluxbox is NOT running"
	else
		echo "Killing fluxbox"
		killall fluxbox
	fi
	if [[ `ps aux | grep skype | grep "Xvfb :1" | grep -v grep | wc -l` == '0' ]]; then
		echo "Xvfb is NOT running"
	else
		echo "Killing Xvfb"
		killall Xvfb
	fi
}
status() {
	i='3'
	if [[ `ps aux | grep skype | grep "Xvfb :1" | grep -v grep | wc -l` == '0' ]]; then
		echo "Xvfb is NOT running"
	else	
		echo "Xvfb is running"
		((i--))
	fi
	if [[ `ps aux | grep skype | grep "fluxbox" | grep -v grep | wc -l` == '0' ]]; then
		echo "fluxbox is NOT running"
	else
		echo "fluxbox is running"
		((i--))
	fi
	if [[ `ps -eo pid,user,args | grep skype | awk '{ print $1 " " $3; }' | grep skype | wc -l` == '0' ]]; then
		echo "skype is NOT running"
	else
		echo "skype is running"
		((i--))
	fi
	if [[ "$i" == '0' ]]; then
		echo "OVERALL STATUS: OK"
		exit 0
	fi
	if [[ "$i" == '1' || "$i" == '2' ]]; then
		echo "OVERALL STATUS: NOT RUNNING PROPERLY"
	else
		echo "OVERALL STATUS: NOT RUNNING"
	fi
	exit "$i"
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac


2. start-vnc.sh - a script to start a VNC server - since we need a graphical interface to enter a Skype account and confirm permission to work with an external API:

#!/bin/bash
if [[ "$USER" != 'skype' ]]; then
	echo "Please start this script as skype!"
	exit 1
fi
export DISPLAY=:1
dnb=`dirname "$0"`
start() {
	"$dnb/start-server.sh" status
	if [[ "$?" == '0' ]]; then
		echo "Starting x11vnc"
		if [[ `ps aux | grep skype | grep "x11vnc -display :1" | grep -v grep | wc -l` == '0' ]]; then
		x11vnc -display :1 -bg -nopw -listen localhost -xkb
		else
			echo "x11vnc is already running!"
		fi
		#pid=`ps aux | grep skype | grep "x11vnc -display :1" | grep -v grep | awk '{ print $2; }'`
		echo "	now use on your machine: ssh -L 5900:127.0.0.1:5900 'skype@`hostname`'"
		echo "	and connect to your local port with vncviewer!"
	else
		echo "The server doesn't run."
		echo 'Use "'"$dnb"'/start-server.sh" to start the server'
	fi
}
status() {
	if [[ `ps aux | grep skype | grep "x11vnc -display :1" | grep -v grep | wc -l` == '0' ]]; then
		echo "x11vnc isn't running"
		exit 1
	else
		echo "x11vnc is running"
		exit 0
	fi
}
stop() {
	if [[ `ps aux | grep skype | grep "x11vnc -display :1" | grep -v grep | wc -l` == '0' ]]; then
		echo "x11vnc isn't running"
	else
		echo "killing x11vnc"
		killall x11vnc
	fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac


Fourth step - launch and configure skype.
We launch both of our scripts under the user skype:
./start-server.sh start
./start-vnc.sh start

Forward the VNC server port (you can also map \ to the local IP server in the script ./start-vnc.sh \ - but for for greater universality, we use this method):
ssh -L 5900: 127.0.0.1: 5900 'skype@your.zabbix.server'

Connect your favorite VNC viewer to 127.0.0.1 port 5900 and see Skype running
Enter login and password for the account that will send us notifications AND DO NOT FORGET TO DELIVER A TICKET TO SAVE A PASSWORD

Turn on Skype:

no chat history
just people on my list can write me
just people on my list can call me

Before closing the GUI window, we need to allow Skype4py connections to Skype itself.
To do this, we execute from the console (the script text is lower in the text):

./sendim.sh ‘USERNAME’ ‘HELLO WORLD’

where USERNAME is the name of the account WHERE to send the message
HELLO WORLD is the message itself. We

return to the window with VNC and see that skype asks us for permission - click "allow and remember".

Stop the VNC server:

./start-vnc.sh stop


And we check the operation of Skype, sending again:

./sendim.sh ‘USERNAME’ ‘HELLO WORLD’


Now the message should come to our USERNAME.

The last step is to configure zabbix.
1. We are looking for the path for AlertScriptsPath in zabbix_server.conf
2. We create scripts for sending notifications

We create two scripts:
sendim.sh - in the skype user’s home directory and link to the AlertScriptsPath folder

#!/bin/bash
export DISPLAY=:1
python ~skype/sendim.py "$1" "$2"


In this script, the first parameter is the username (to whom to send), the second is the message.

sendim.py - in the Skype home directory:

import Skype4Py
import sys
# Create an instance of the Skype class.
skype = Skype4Py.Skype()
# Connect the Skype object to the Skype client.
skype.Attach()
user = sys.argv[1]
msg = ' '.join(sys.argv[2:])
message = skype.SendMessage(user, msg)


Check again:

./sendim.sh username message


Configure notifications in Zabbix.
1. Set up Media type,
go to Administration -> Media Types and create a new media type: 2. Define the users working with these notifications: go to Administration -> Users and in the properties of the user (s), enable our new media type and configure usernames for Skype YOUR_SKYPE_NAME - Skype login to whom we will send. And so for each user we want to send notifications to whom. Configure Actions for sending notifications: All that we want to send to Skype should be in the subject line (the message body itself is not sent). We create the necessary Conditions and configure Operations: You can test.
Name: Skype
Type: Script
Script name: sendim.sh
Enabled: true




Type: Skype
Send to: YOUR_SKYPE_NAME














* As I indicated at the beginning - we have Skype on a server separate from zabbix and the commands are executed remotely using
sudo sshpass -p 'skype' ssh skype@IP_ADDRESS "./sendim.sh '$1' '$2'"

where IP_ADDRESS is the IP address of the server with skype.

A function is also implemented - the “dialer". Skype calls Admins at the specified numbers.
Script texts are below. If necessary, I’ll tell you how to set it up - but this is a topic for a separate post)

skype_caller.py - connect and call from Skype:

#!python
# ---------------------------------------------------------------------------------------------
#  Python / Skype4Py example that takes a skypename or number from the commandline
# and calls it.
#
import sys
import Skype4Py
# This variable will get its actual value in OnCall handler
CallStatus = 0
# Here we define a set of call statuses that indicate a call has been either aborted or finished
CallIsFinished = set ([Skype4Py.clsFailed, Skype4Py.clsFinished, Skype4Py.clsMissed, Skype4Py.clsRefused, Skype4Py.clsBusy, Skype4Py.clsCancelled]);
def AttachmentStatusText(status):
   return skype.Convert.AttachmentStatusToText(status)
def CallStatusText(status):
    return skype.Convert.CallStatusToText(status)
# This handler is fired when status of Call object has changed
def OnCall(call, status):
    global CallStatus
    CallStatus = status
    print 'Call status: ' + CallStatusText(status)
# This handler is fired when Skype attatchment status changes
def OnAttach(status): 
    print 'API attachment status: ' + AttachmentStatusText(status)
    if status == Skype4Py.apiAttachAvailable:
        skype.Attach()
# Let's see if we were started with a command line parameter..
try:
    CmdLine = sys.argv[1]
    file = sys.argv[2]
except:
    print 'Missing command line parameter'
    sys.exit()
# Creating Skype object and assigning event handlers..
skype = Skype4Py.Skype()
skype.OnAttachmentStatus = OnAttach
skype.OnCallStatus = OnCall
# Starting Skype if it's not running already..
if not skype.Client.IsRunning:
    print 'Starting Skype..'
    skype.Client.Start()
# Attatching to Skype..
print 'Connecting to Skype..'
skype.Attach()
# Make the call
print 'Calling ' + CmdLine + '..'
global cl
cl = skype.PlaceCall(CmdLine)
cl.InputDevice( Skype4Py.callIoDeviceTypeFile ,file )
# Loop until CallStatus gets one of "call terminated" values in OnCall handler
while not CallStatus in CallIsFinished:
    pass


skype_caller.sh - skype_caller.py caller:

#!/bin/bash
export DISPLAY=:1
python ~skype/skype_caller.py "$1" "$2"


To all Habr.

Also popular now: