lib/flapjack/jabber.rb in flapjack-0.6.39 vs lib/flapjack/jabber.rb in flapjack-0.6.40
- old
+ new
@@ -16,33 +16,46 @@
require 'em-synchrony/fiber_iterator'
require 'yajl/json_gem'
require 'flapjack/data/entity_check'
require 'flapjack/pikelet'
+require 'flapjack/redis_pool'
require 'flapjack/utility'
require 'flapjack/version'
module Flapjack
class Jabber < Blather::Client
- include Flapjack::Pikelet
+ include Flapjack::GenericPikelet
include Flapjack::Utility
log = Logger.new(STDOUT)
# log.level = Logger::DEBUG
log.level = Logger::INFO
Blather.logger = log
- def initialize
- super
+ alias_method :generic_bootstrap, :bootstrap
+ alias_method :generic_cleanup, :cleanup
+
+ def bootstrap(opts = {})
+ generic_bootstrap(opts)
+
+ @redis_config = opts[:redis_config]
+ @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 1)
+
@buffer = []
@hostname = Socket.gethostname
end
+ def cleanup
+ @redis.empty! if @redis
+ @redis_handler.empty! if @redis_handler
+ generic_cleanup
+ end
+
def setup
- @redis = build_redis_connection_pool
@flapjack_jid = Blather::JID.new((@config['jabberid'] || 'flapjack') + '/' + @hostname)
super(@flapjack_jid, @config['password'], @config['server'], @config['port'].to_i)
logger.debug("Building jabber connection with jabberid: " +
@@ -77,12 +90,12 @@
end
end
# Join the MUC Chat room after connecting.
def on_ready(stanza)
- return if should_quit?
- @redis_handler ||= build_redis_connection_pool
+ return if should_quit? && @shutting_down
+ @redis_handler ||= Flapjack::RedisPool.new(:config => @redis_config, :size => 1)
@connected_at = Time.now.to_i
logger.info("Jabber Connected")
if @config['rooms'] && @config['rooms'].length > 0
@config['rooms'].each do |room|
logger.info("Joining room #{room}")
@@ -148,10 +161,12 @@
end
when command =~ /^help$/
msg = "commands: \n"
msg += " ACKID <id> <comment> [duration: <time spec>] \n"
+ msg += " find entities matching /pattern/ \n"
+ msg += " test notifications for <entity>[:<check>] \n"
msg += " identify \n"
msg += " help \n"
when command =~ /^identify$/
t = Process.times
@@ -160,21 +175,58 @@
msg += "Boot time: #{boot_time}\n"
msg += "User CPU Time: #{t.utime}\n"
msg += "System CPU Time: #{t.stime}\n"
msg += `uname -a`.chomp + "\n"
+ when command =~ /^test notifications for\s+([a-z0-9-]+)(:(.+))?$/i
+ entity_name = $1
+ check_name = $3 ? $3 : 'test'
+
+ msg = "so you want me to test notifications for entity: #{entity_name}, check: #{check_name} eh? ... well OK!"
+
+ entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => @redis_handler)
+ if entity
+ summary = "Testing notifications to all contacts interested in entity: #{entity.name}, check: #{check_name}"
+
+ entity_check = Flapjack::Data::EntityCheck.for_entity(entity, check_name, :redis => @redis_handler)
+ puts entity_check.inspect
+ entity_check.test_notifications('summary' => summary)
+
+ else
+ msg = "yeah, no i can't see #{entity_name} in my systems"
+ end
+
+ when command =~ /^(find )?entities matching\s+\/(.*)\/.*$/i
+ pattern = $2.chomp.strip
+ entity_list = Flapjack::Data::Entity.find_all_name_matching(pattern, :redis => @redis_handler)
+ max_showable = 30
+ number_found = entity_list.length
+ entity_list = entity_list[0..(max_showable - 1)] if number_found > max_showable
+
+ case
+ when number_found == 0
+ msg = "found no entities matching /#{pattern}/"
+ when number_found == 1
+ msg = "found #{number_found} entity matching /#{pattern}/ ... \n"
+ when number_found > max_showable
+ msg = "showing first #{max_showable} of #{number_found} entities found matching /#{pattern}/\n"
+ else
+ msg = "found #{number_found} entities matching /#{pattern}/ ... \n"
+ end
+ msg += entity_list.join(', ') unless entity_list.empty?
+
when command =~ /^(.*)/
words = $1
msg = "what do you mean, '#{words}'? Type 'help' for a list of acceptable commands."
end
{:msg => msg, :action => action}
end
def on_groupchat(stanza)
- return if should_quit?
+ return if should_quit? && @shutting_down
logger.debug("groupchat message received: #{stanza.inspect}")
if stanza.body =~ /^flapjack:\s+(.*)/
command = $1
end
@@ -189,11 +241,11 @@
action.call if action
end
end
def on_chat(stanza)
- return if should_quit?
+ return if should_quit? && @shutting_down
logger.debug("chat message received: #{stanza.inspect}")
if stanza.body =~ /^flapjack:\s+(.*)/
command = $1
else
@@ -211,11 +263,11 @@
end
end
# returning true to prevent the reactor loop from stopping
def on_disconnect(stanza)
- return true if should_quit?
+ return true if should_quit? && @shutting_down
logger.warn("jabbers disconnected! reconnecting in 1 second ...")
EventMachine::Timer.new(1) do
connect # Blather::Client.connect
end
true
@@ -254,24 +306,25 @@
# simplified to use a single queue only as it makes the shutdown logic easier
queue = @config['queue']
events = {}
- until should_quit?
+ until should_quit? && @shutting_down
# FIXME: should also check if presence has been established in any group chat rooms that are
# configured before starting to process events, otherwise the first few may get lost (send
# before joining the group chat rooms)
if connected?
logger.debug("jabber is connected so commencing blpop on #{queue}")
events[queue] = @redis.blpop(queue, 0)
event = Yajl::Parser.parse(events[queue][1])
- type = event['notification_type']
+ type = event['notification_type'] || 'unknown'
logger.debug('jabber notification event received')
logger.debug(event.inspect)
if 'shutdown'.eql?(type)
if should_quit?
+ @shutting_down = true
EventMachine::Synchrony.next_tick do
# get delays without the next_tick
close # Blather::Client.close
end
end
@@ -282,19 +335,35 @@
duration = event['duration'] ? time_period_in_words(event['duration']) : '4 hours'
address = event['address']
logger.debug("processing jabber notification address: #{address}, event: #{entity}:#{check}, state: #{state}, summary: #{summary}")
- ack_str = event['event_count'] && !state.eql?('ok') && !'acknowledgement'.eql?(type) ?
+ ack_str =
+ event['event_count'] &&
+ !state.eql?('ok') &&
+ !'acknowledgement'.eql?(type) &&
+ !'test'.eql?(type) ?
"::: flapjack: ACKID #{event['event_count']} " : ''
- maint_str = (type && 'acknowledgement'.eql?(type)) ?
- "has been acknowledged, unscheduled maintenance created for #{duration}" :
+ type = 'unknown' unless type
+
+ maint_str = case type
+ when 'acknowledgement'
+ "has been acknowledged, unscheduled maintenance created for #{duration}"
+ when 'test'
+ ''
+ else
"is #{state.upcase}"
+ end
- msg = "#{type.upcase} #{ack_str}::: \"#{check}\" on #{entity} #{maint_str} ::: #{summary}"
+ # FIXME - should probably put all the message composition stuff in one place so
+ # the logic isn't duplicated in each notification channel.
+ # TODO - templatise the messages so they can be customised without changing core code
+ headline = "test".eql?(type.downcase) ? "TEST NOTIFICATION" : type.upcase
+ msg = "#{headline} #{ack_str}::: \"#{check}\" on #{entity} #{maint_str} ::: #{summary}"
+
chat_type = :chat
chat_type = :groupchat if @config['rooms'] && @config['rooms'].include?(address)
EventMachine::Synchrony.next_tick do
say(Blather::JID.new(address), msg, chat_type)
end
@@ -305,12 +374,9 @@
end
end
count_timer.cancel
keepalive_timer.cancel
-
- @redis.empty! if @redis
- @redis_handler.empty! if @redis_handler
end
end
end