support@yourtech.us | Webmail |  DNS Login | *Billing* | cPanel | (814) 652-5358

Welcome to YourTech, LLC. If you are unfamiliar with this site, you may want to find out about my services, read my story, or you could simply be looking for a way to contact me. On this site, you will find a collection of technical musings, howto guides, and technical reference information.

February 2011 Archives

Nagios and XMPP

submit to reddit | No Comments | No TrackBacks
I found that someone has written a perl script geared towards sending alerts from Nagios to XMPP usernames.

http://www.gridpp.ac.uk/wiki/Nagios_jabber_notification

I have downloaded this, but have not yet got it working as of yet, but it does look promising.  It took me a while to update all the dependencies for it, but if those were in place, the installation itself is rather simple.  That is, the notification script works, but I haven't actually configured nagios as of yet.

This script has a shortcoming in that it only accepts the username portion of the JID and not the domain name -- and this means that notifications can only be sent between users of the same domain.

To illustrate, user@example.net can not send a message to user@example.com, but user1 and user2 on example.net can send to each other.

# this command will fail:
ytjohn@monitor:/usr/local/bin$ ./notify_by_jabber.pl yourtech\@example.com testing 
# while this one works
ytjohn@monitor:/usr/local/bin$ ./notify_by_jabber.pl yourtech testing


And in the perl script, you have to specify the login credentials and server you're connecting to:


## Configuration
# my $username = 'system@example.com';   # does not work
my $username = 'system';
my $password = "password";
my $resource = "nagios";
## End of configuration


my $len = scalar @ARGV;
if ($len ne 2) {
   die "Usage...\n $0 [jabberid] [message]\n";
}
my @field=split(/,/,$ARGV[0]);
#------------------------------------

# Google Talk & Jabber parameters :

my $hostname = 'talk.google.com';
my $port = 5222;
# componentname is the second half of your JID:
my $componentname = 'example.com';
my $connectiontype = 'tcpip';
my $tls = 1;



Jabbering about Python

submit to reddit | No Comments | No TrackBacks
I am getting more and more into the idea of using XMPP for sending messages.  XMPP (also known as jabber) is a very open protocol.  Anyone can throw up a server, and by publishing a few DNS records, your server can interact with any other XMPP server out there (that is open).  For a popular example, anyone can throw
up their server with their domain and send messages to someone using Google Chat.
    
I have a customer that has their domain email hosted by Google apps for domains, which also means that each person has Google Talk, which is based off of XMPP.  For a monitoring scenario, I decided I'd rather have alerts go to an installed Google Talk client instead of to their email.  This would make alerts more noticeable, but less intrusive to their Inbox.  Google would also tie all their messages together (chat and email) for searching later. So my idea was to have monitoring server send the email alert to a local user, and have it piped through a program that would send the XMPP alert.  In the future, perhaps an XMPP bot could also accept commands to control the monitoring system.
   
I wanted to create a program called "jabblast.py" which would accept either standard input, or a command line argument, and send a message to a pre-defined list of recipients.

  echo "sent from stdin" | jabblast.py
  jabblast.py -m "sent from a command line argument"

Looking at the python and XMPP options out there, I came across three that looked promising. 

  # xmpppy
  # sleekxmpp
  # twisted (the "words" extension)

I was really expecting to find exactly what I wanted to do already written.  However, it seems anyone writing an XMPP script is creating a bot that runs continuously and would need modified for a one-time event.
   
Sleekxmpp was actually the easiest to understand and work with, however the project could be in danger of abandonment.   Twisted looks the most advanced, and I am drawn to it because it seems to offer the most versatility.  In my mind, I suspect that if I learn twisted for this, I can just keep using it for all the other stuff I want to do.  However, it might be "too much" for this simple of an operation.  xmpppy is the middle ground.  The project seems relatively active and popular. 

The problem with all three projects is a severe lack of documentation -- for twisted, this lack is primarily on the xmpp side.  One thing very well hidden is how to specify the server name you want to connect to.  Ideally, this is provided through a DNS record lookup, but that method eliminates experimentation with local network ip addresses.   Sleek never even approaches the concept that you might want your XMPP program to end.   It has a call for disconnecting, but when I call that, sleek immediately tries to reconnect.

I'm going to go ahead and create my program using all three methods and decide later which I like best.

For these examples, I have hardcoded the login credentials, as well as the "to" into the source code itself.  In the real world, I should be pulling that from a configuration file, either XML or YAML (and potentially from a remote web page).  Secondly, I only list one "to".  I believe that going from sending a single message to sending multiple messages should be a matter of a for loop.  Some libraries might even offer a feature to send to multiple recipients at once.
 
For my first example, I have created a script in sleekxmpp.  I wrote this by looking at the EchoBot example found here.  The script will send a message and then hang for a while after disconnecting before it finally exits.  I don't know why.  If you enable logging, an error is thrown after you pass in the disconnect command.  But otherwise, a relatively simple bit of code, easy to expand upon.

#!/usr/bin/env python

import sys
import logging
import sleekxmpp


# Uncomment the following line to turn on debugging
#logging.basicConfig(level=logging.DEBUG, format="%(levelname)-8s %(message)s")

def main() :
  # configure jabber id credentials and to
  to = 'recipient@example.net'
  myjid = 'sender@example.net/blastbot'
  mysecret = 'password'
 
  args = sys.argv[1:]
  if not args:
    message = sys.stdin.read()
  else:
    message = sys.argv[1]
 
  # print to, message
  # sys.exit()
 
  bot = BlastBot(myjid, mysecret, to, message)
  bot.run()
 

class BlastBot :

  def __init__(self, jid, password, to, message) :
    self.message = message
    self.to = to
    self.xmpp = sleekxmpp.ClientXMPP(jid, password)
    self.xmpp.add_event_handler("session_start", self.handleXMPPConnected)
    self.xmpp.add_event_handler("disconnected", self.handleXMPPDisconnected)
   
  def run(self) :
    self.xmpp.connect()
    self.xmpp.process(threaded=False)
   
   
  def handleXMPPDisconnected(self, event) :
    sys.exit()
   
  def handleXMPPConnected(self, event) :
    self.xmpp.sendMessage(self.to, self.message)
    self.xmpp.disconnect(self)
   
   
       
if __name__ == "__main__" :
  main()