aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick J Cherry <patrick@bytemark.co.uk>2011-07-13 16:02:50 +0100
committerPatrick J Cherry <patrick@bytemark.co.uk>2011-07-13 16:02:50 +0100
commite140af144e987ff7f6d767f2dc48b9cf685803fd (patch)
tree4a01971890865b4b3ca837d563bc673cbb787de8
parentd28af4ec946c6aa4b645b73cef47d7e0c680bc0d (diff)
Big commit
* Added manpages for all binaries * Added log-reopening for mauvealert-server, and logrotate snippet * mauveserver now adds a user on install, and runs as that user * Big logging tidy-up * Alert subjects are only overwritten by the source, when the subject in the databse is empty * Removed various attr_writer methods that were being redifined * Added a notes box to the acknowledge form, but this doesn't work yet
-rw-r--r--.hgignore1
-rw-r--r--Makefile8
-rwxr-xr-xbin/mauveclient4
-rwxr-xr-xbin/mauveconsole65
-rwxr-xr-xbin/mauveserver96
-rw-r--r--debian/mauvealert-server.init22
-rw-r--r--debian/mauvealert-server.logrotate10
-rw-r--r--debian/mauvealert-server.postinst20
-rw-r--r--debian/mauvealert-server.postrm23
-rw-r--r--lib/mauve/alert.rb22
-rw-r--r--lib/mauve/alert_changed.rb10
-rw-r--r--lib/mauve/alert_group.rb12
-rw-r--r--lib/mauve/auth_bytemark.rb2
-rw-r--r--lib/mauve/datamapper.rb3
-rw-r--r--lib/mauve/history.rb10
-rw-r--r--lib/mauve/http_server.rb1
-rw-r--r--lib/mauve/mauve_thread.rb11
-rw-r--r--lib/mauve/notification.rb5
-rw-r--r--lib/mauve/notifier.rb5
-rw-r--r--lib/mauve/notifiers/email.rb17
-rw-r--r--lib/mauve/notifiers/sms_aql.rb5
-rw-r--r--lib/mauve/notifiers/xmpp-smack.rb395
-rw-r--r--lib/mauve/notifiers/xmpp.rb26
-rw-r--r--lib/mauve/people_list.rb9
-rw-r--r--lib/mauve/person.rb50
-rw-r--r--lib/mauve/processor.rb23
-rw-r--r--lib/mauve/sender.rb1
-rw-r--r--lib/mauve/server.rb7
-rw-r--r--lib/mauve/timer.rb6
-rw-r--r--lib/mauve/udp_server.rb8
-rw-r--r--lib/mauve/web_interface.rb23
-rw-r--r--mauveserver.conf58
-rw-r--r--views/_acknowledge_input.haml5
-rw-r--r--views/alert.haml6
34 files changed, 386 insertions, 583 deletions
diff --git a/.hgignore b/.hgignore
index 826867e..b734f59 100644
--- a/.hgignore
+++ b/.hgignore
@@ -6,3 +6,4 @@
^debian/mauvealert-.*\.debhelper(.log)?$
^debian/mauvealert-.*.substvars$
^debian/files
+^static/javascript/jquery$
diff --git a/Makefile b/Makefile
index 9ec7fbd..3776678 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,13 @@
#
##
-all: man/mauveclient.1
+all: man man/mauveclient.1 man/mauveserver.1 man/mauveconsole.1
-man/%.1: bin/%
+man:
mkdir -p man
- ruby -I lib $< --help | txt2man -t $(notdir $<) -s 1 > $@; \
+
+man/%.1: bin/%
+ ruby -I lib $< --help | txt2man -t $(notdir $<) -s 1 > $@
clean:
$(RM) -r man
diff --git a/bin/mauveclient b/bin/mauveclient
index 0068435..251b45b 100755
--- a/bin/mauveclient
+++ b/bin/mauveclient
@@ -142,6 +142,10 @@
#
# mauveclient -i heartbeat -d "No heartbeat received for 1.2.3.4. Could be down!" -s "heartbeat failed" -c -r +10m
#
+# SEE ALSO
+#
+# mauveconsole(1), mauveserver(1)
+#
# AUTHOR
#
# Patrick J Cherry <patrick@bytemark.co.uk>
diff --git a/bin/mauveconsole b/bin/mauveconsole
index debe5af..5a16a7e 100755
--- a/bin/mauveconsole
+++ b/bin/mauveconsole
@@ -1,23 +1,70 @@
#!/usr/bin/ruby1.8
+# NAME
+#
+# mauveconsole -- Ruby console to query the mauvealert server directly
+#
+# SYNOPSIS
+#
+# mauveconsole [-h | --help] [<configuration file>]
+#
+# OPTIONS
+#
+# -h, --help Show a help message
+# <configuration file> File to load the configuration from. If none is
+# specified, then mauvealert.conf in the current
+# directory is used, and failing that
+# /etc/mauvealert/mauvealert.conf is used.
+#
+# SEE ALSO
+#
+# irb(1), mauveserver(1), mauveclient(1)
+#
+# AUTHOR
+#
+# Patrick J Cherry <patrick@bytemark.co.uk>
+#
-require 'pp'
-require 'irb'
-require 'thread'
-require 'mauve/configuration'
+def error(msg)
+ STDERR.print "*** Error: #{msg}\n"
+ STDERR.print "*** For help, type: #{$0} -h\n"
+ exit 1
+end
-Thread.abort_on_exception = true
+# CAUTION! Kwality kode.
+#
+if ARGV.any?{|a| a =~ /--?h(elp)?/}
+ # Open the file, stripping the shebang line
+ lines = File.open(__FILE__){|fh| fh.readlines}[1..-1]
+
+ lines.each do |line|
+ line.chomp!
+ break if line.empty?
+ puts line[2..-1].to_s
+ end
+
+ exit 0
+end
configuration_file = ARGV.shift
-configuration_file = [".", "/etc/mauvealert/"].find{|d| File.file?(File.join(d,"mauveserver.conf")) } if configuration_file.nil?
+configuration_file = [".", "/etc/mauvealert/"].collect{|x| File.join("mauveserver.conf") }.find{|d| File.file?(d)} if configuration_file.nil?
configuration_file = File.expand_path(configuration_file)
unless File.file?(configuration_file)
- STDERR.print "Configuration file #{configuration_file} not found"
- Kernel.exit 1
+ error "Configuration file #{configuration_file} not found\n"
end
-Mauve::Configuration.current = Mauve::ConfigurationBuilder.load(configuration_file)
+require 'irb'
+require 'thread'
+require 'mauve/configuration'
+
+Thread.abort_on_exception = true
include Mauve
+begin
+ Configuration.current = ConfigurationBuilder.load(configuration_file)
+rescue StandardError => ex
+ error ex.message
+end
+
IRB.start
diff --git a/bin/mauveserver b/bin/mauveserver
index 2d810b9..a5cf7b5 100755
--- a/bin/mauveserver
+++ b/bin/mauveserver
@@ -1,49 +1,111 @@
#! /usr/bin/ruby1.8
+# NAME
+#
+# mauveserver -- receive alerts from station(s) around the network
+#
+# SYNOPSIS
+#
+# mauveserver [ -h | --help ] [<configuration file>]
+#
+# OPTIONS
+#
+# -h, --help Show a help message
+#
+# <configuration file> File to load the configuration from
+#
+# SEE ALSO
+#
+# mauveclient(1), mauveconsole(1)
+#
+# AUTHOR
+#
+# Patrick J Cherry <patrick@bytemark.co.uk>
+#
+
+def error(msg)
+ STDERR.print "*** Error: #{msg}\n"
+ STDERR.print "*** For help, type: #{$0} -h\n"
+ exit 1
+end
begin
eval "Proc.new { |a,&b| }"
rescue SyntaxError => no_blocks_with_procs
- STDERR.print "mauveserver must have Ruby 1.8.7 or later, sorry (if you "+
- "try, you'll get a SyntaxError trying to load one of its libraries)\n"
- exit 1
+ error "mauveserver must have Ruby 1.8.7 or later"
end
-
-require 'mauve/configuration'
+
+# CAUTION! Kwality kode.
+#
+if ARGV.any?{|a| a =~ /--?h(elp)?/}
+ # Open the file, stripping the shebang line
+ lines = File.open(__FILE__){|fh| fh.readlines}[1..-1]
+
+ lines.each do |line|
+ line.chomp!
+ break if line.empty?
+ puts line[2..-1].to_s
+ end
+
+ exit 0
+end
+
configuration_file = ARGV.shift
-configuration_file = [".", "/etc/mauvealert/"].find{|d| File.file?(File.join(d,"mauveserver.conf")) } if configuration_file.nil?
+configuration_file = [".", "/etc/mauvealert/"].collect{|x| File.join("mauveserver.conf") }.find{|d| File.file?(d)} if configuration_file.nil?
configuration_file = File.expand_path(configuration_file)
unless File.file?(configuration_file)
- STDERR.print "Configuration file #{configuration_file} not found\n"
- Kernel.exit 1
+ error "Configuration file #{configuration_file} not found\n"
end
-Mauve::Configuration.current = Mauve::ConfigurationBuilder.load(configuration_file)
+require 'mauve/configuration'
+
+begin
+ Mauve::Configuration.current = Mauve::ConfigurationBuilder.load(configuration_file)
+rescue StandardError => ex
+ error ex.message
+end
%w(HUP).each do |sig|
- trap("HUP") do
+ trap(sig) do
# this blows up if you do it twice in quick succession, but don't really
# care about that case as it's only for log rotation.
- Mauve::Server.instance.logger.warn "#{sig} signal received. Stopping."
+ Mauve::Server.instance.logger.warn "#{sig} signal received. Restarting."
Mauve::Server.instance.stop
#
# Reload configuration
#
- Mauve::Server.instance.logger.warn "Restarting."
-
begin
new_config = Mauve::ConfigurationBuilder.load(configuration_file)
Mauve::Configuration.current = new_config
rescue BuildException => ex
- Mauve::Server.instance.logger.warn "Reconfiguration failed: #{ex}. Sticking with old one."
+ Mauve::Server.instance.logger.error "Reconfiguration failed: #{ex}. Sticking with old one."
end
Mauve::Server.instance.logger.warn "Restarting."
Mauve::Server.instance.start
end
end
+%w(USR1).each do |sig|
+ trap(sig) do
+ Mauve::Server.instance.logger.warn "#{sig} signal received. Re-opening logs."
+ Log4r::Outputter.each_outputter do |old|
+ next unless old.is_a?(Log4r::FileOutputter)
+
+ new = Log4r::FileOutputter.new(old.name, {:filename => old.filename, :trunc => false})
+ new.formatter = old.formatter
+ new.level = old.level
+
+ Mauve::Server.instance.logger.outputters << new
+ Mauve::Server.instance.logger.outputters.delete(old)
+ old.close
+
+ Mauve::Server.instance.logger.debug "Opened #{new.filename}."
+ end
+ end
+end
+
%w(QUIT TERM INT).each do |sig|
trap(sig) do
Mauve::Server.instance.logger.warn "#{sig} signal received. Stopping."
@@ -52,5 +114,9 @@ end
end
end
-Mauve::Server.instance.run
+begin
+ Mauve::Server.instance.run
+rescue StandardError => ex
+ error ex.message
+end
diff --git a/debian/mauvealert-server.init b/debian/mauvealert-server.init
index 1f0e57f..15c287b 100644
--- a/debian/mauvealert-server.init
+++ b/debian/mauvealert-server.init
@@ -32,8 +32,6 @@ SCRIPTNAME=/etc/init.d/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
-VERBOSE=1
-
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
@@ -48,9 +46,9 @@ do_start()
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
- start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON --test > /dev/null \
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON --chuid $RUNASUSER --test > /dev/null \
|| return 1
- start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --background --startas $DAEMON -- \
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --chuid $RUNASUSER --background --startas $DAEMON -- \
$DAEMON_ARGS \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
@@ -95,10 +93,19 @@ do_reload() {
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
- start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+ start-stop-daemon --stop --signal HUP --quiet --pidfile $PIDFILE --name $NAME
return 0
}
+#
+# Function that sends a SIGUSR1 to reopen logfiles
+#
+do_reopenlogs() {
+ start-stop-daemon --stop --signal USR1 --quiet --pidfile $PIDFILE --name $NAME
+ return 0
+}
+
+
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
@@ -128,6 +135,11 @@ case "$1" in
do_reload
log_end_msg $?
;;
+ reopen-logs)
+ log_daemon_msg "Re-opening logs for $DESC" "$NAME"
+ do_reopenlogs
+ log_end_msg $?
+ ;;
restart)
#
# If the "reload" option is implemented then remove the
diff --git a/debian/mauvealert-server.logrotate b/debian/mauvealert-server.logrotate
new file mode 100644
index 0000000..3885a35
--- /dev/null
+++ b/debian/mauvealert-server.logrotate
@@ -0,0 +1,10 @@
+/var/log/mauvealert.log {
+ rotate 7
+ daily
+ compress
+ delaycompress
+ postrotate
+ /usr/sbin/invoke-rc.d mauvealert-server reopen-logs >/dev/null
+ endscript
+}
+
diff --git a/debian/mauvealert-server.postinst b/debian/mauvealert-server.postinst
new file mode 100644
index 0000000..3d1c09a
--- /dev/null
+++ b/debian/mauvealert-server.postinst
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -e
+
+##
+# Add a mauve user
+##
+RUNASUSER=mauvealert
+
+adduser --system --no-create-home --home /nonexistent $RUNASUSER > /dev/null
+
+##
+# Add default directories
+##
+for i in log lib ; do
+ mkdir -p /var/$i/mauvealert
+ chown -R $RUNASUSER:nogroup /var/$i/mauvealert
+done
+
+#DEBHELPER#
diff --git a/debian/mauvealert-server.postrm b/debian/mauvealert-server.postrm
new file mode 100644
index 0000000..24fd158
--- /dev/null
+++ b/debian/mauvealert-server.postrm
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+set -e
+
+##
+# Add a mauve user
+##
+RUNASUSER=mauvealert
+
+if [ "$1" = "purge" ] ; then
+ ##
+ # Remove the system user
+ ##
+ deluser --system $RUNASUSER > /dev/null
+
+ ##
+ # remove default directories
+ ##
+ rm -rf /var/log/mauvealert/
+ rm -rf /var/lib/mauvealert/
+fi
+
+#DEBHELPER#
diff --git a/lib/mauve/alert.rb b/lib/mauve/alert.rb
index bea2fc4..164139b 100644
--- a/lib/mauve/alert.rb
+++ b/lib/mauve/alert.rb
@@ -104,7 +104,7 @@ module Mauve
default_scope(:default).update(:order => [:source, :importance])
def logger
- Log4r::Logger.new(self.class.to_s)
+ @logger ||= self.class.logger
end
def time_relative(secs)
@@ -186,7 +186,7 @@ module Mauve
if @changes_before_save.has_key?(:update_type) or (self.update_type == "raised" and is_a_change)
self.notify
- h = History.new(:alert => self, :type => "update")
+ h = History.new(:alert_id => self.id, :type => "update")
if self.update_type == "acknowledged"
h.event = "ACKNOWLEDGED by #{self.acknowledged_by} until #{self.will_unacknowledge_at}"
@@ -200,7 +200,9 @@ module Mauve
end
- h.save
+ if !h.save
+ logger.error "Unable to save history due to #{h.errors.inspect}"
+ end
end
true
@@ -244,7 +246,6 @@ module Mauve
# Don't clear will_clear_at
self.update_type = "raised" if self.update_type.nil? or self.update_type != "changed" or self.original_attributes[Alert.properties[:update_type]] == "cleared"
- logger.debug("saving #{self.inspect}")
logger.error("Couldn't save #{self}") unless save
end
@@ -384,8 +385,6 @@ module Mauve
time_offset = (reception_time - transmission_time).round
- logger.debug("Update received from a host #{time_offset}s behind") if time_offset.abs > 5
-
#
# Make sure there is no HTML in the update source.
#
@@ -457,13 +456,14 @@ module Mauve
#
# Set the subject
#
- if alert.subject and !alert.subject.empty?
+ if alert.subject and !alert.subject.empty?
alert_db.subject = Alert.remove_html(alert.subject)
- else
+
+ elsif alert_db.subject.nil?
#
# Use the source, Luke, but only when the subject hasn't already been set.
#
- alert_db.subject = alert_db.source if alert_db.subject.nil?
+ alert_db.subject = alert_db.source
end
alert_db.summary = Alert.remove_html(alert.summary) if alert.summary && !alert.summary.empty?
@@ -501,7 +501,7 @@ module Mauve
#
if update.replace
alert_ids_mentioned = update.alert.map { |alert| alert.id }
- logger.debug "Replacing all alerts from #{update.source} except "+alert_ids_mentioned.join(",")
+ logger.info "Replacing all alerts from #{update.source} except "+alert_ids_mentioned.join(",")
all(:source => update.source,
:alert_id.not => alert_ids_mentioned,
:cleared_at => nil
@@ -513,7 +513,7 @@ module Mauve
end
def logger
- Log4r::Logger.new("Mauve::Alert")
+ Log4r::Logger.new(self.to_s)
end
end
end
diff --git a/lib/mauve/alert_changed.rb b/lib/mauve/alert_changed.rb
index 0b0f72a..740b9dc 100644
--- a/lib/mauve/alert_changed.rb
+++ b/lib/mauve/alert_changed.rb
@@ -39,7 +39,7 @@ module Mauve
)
if old_changed
if !old_changed.update(:remind_at => nil)
- logger.error "Couldn't save #{old_changed}, will get duplicate reminders"
+ logger.info "Couldn't save #{old_changed}, will get duplicate reminders"
end
end
end
@@ -74,7 +74,7 @@ module Mauve
previous.was_relevant_when_raised?
else
# a bug, but hardly inconceivable :)
- logger.warn("Could not see that #{alert} was raised with #{person} "+
+ logger.info("Could not see that #{alert} was raised with #{person} "+
"but further updates exist (e.g. #{self}) "+
"- you may see spurious notifications as a result")
true
@@ -86,18 +86,18 @@ module Mauve
#
def remind
unless alert.is_a?(Alert)
- logger.debug "#{self.inspect} lost alert #{alert_id}. Killing self."
+ logger.info "#{self.inspect} lost alert #{alert_id}. Killing self."
destroy!
return false
end
- logger.debug "Reminding someone about #{self.inspect}"
+ logger.info "Reminding someone about #{self.inspect}"
alert_group = AlertGroup.matches(alert)[0]
if !alert_group || alert.acknowledged?
- logger.debug((alert_group ?
+ logger.info((alert_group ?
"Alert already acknowledged" :
"No alert group matches any more"
) + ", no reminder due"
diff --git a/lib/mauve/alert_group.rb b/lib/mauve/alert_group.rb
index 75f97fd..bfdb3cf 100644
--- a/lib/mauve/alert_group.rb
+++ b/lib/mauve/alert_group.rb
@@ -40,17 +40,15 @@ module Mauve
# Make sure we've got a matching group
#
if groups.empty?
- logger.warn "no groups found for #{alert}"
+ logger.warn "no groups found for #{alert}!"
next
end
#
- # Notify just the group that thinks this alert is the most urgent.
+ # Notify just the first group
#
- logger.warn "Found #{groups.length} matching groups for #{alert}" if groups.length > 1
-
this_group = groups.first
- logger.info("notifying group #{this_group} of #{alert} (matching #{this_group.level})")
+ logger.info("notifying group #{this_group} of #{alert}")
this_group.notify(alert)
end
end
@@ -103,7 +101,7 @@ module Mauve
def matches_alert?(alert)
unless alert.is_a?(Alert)
- logger.warn "Got given a #{alert.class} instead of an Alert!"
+ logger.error "Got given a #{alert.class} instead of an Alert!"
logger.debug caller.join("\n")
return false
end
@@ -126,7 +124,7 @@ module Mauve
# If there are no notifications defined.
#
if notifications.nil?
- logger.warn("No notifications found for #{alert}")
+ logger.warn("No notifications found for #{self.inspect}")
return
end
diff --git a/lib/mauve/auth_bytemark.rb b/lib/mauve/auth_bytemark.rb
index 2273c36..c0834e0 100644
--- a/lib/mauve/auth_bytemark.rb
+++ b/lib/mauve/auth_bytemark.rb
@@ -46,7 +46,7 @@ class AuthBytemark
Mauve::Server.instance.logger.warn "Fault code is #{fault.faultCode} stating #{fault.faultString}"
return false
rescue Exception => ex
- Mauve::Server.instance.logger.warn "Caught #{ex.to_s} whilst trying to loging for #{login}"
+ Mauve::Server.instance.logger.error "Caught #{ex.to_s} whilst trying to loging for #{login}"
Mauve::Server.instance.logger.debug ex.backtrace.join("\n")
return false
end
diff --git a/lib/mauve/datamapper.rb b/lib/mauve/datamapper.rb
index 27d89a3..f46536e 100644
--- a/lib/mauve/datamapper.rb
+++ b/lib/mauve/datamapper.rb
@@ -11,3 +11,6 @@ require 'dm-migrations'
require 'dm-validations'
require 'dm-timestamps'
+
+# DataMapper::Model.raise_on_save_failure = true
+
diff --git a/lib/mauve/history.rb b/lib/mauve/history.rb
index 6c4969b..1c2cdf4 100644
--- a/lib/mauve/history.rb
+++ b/lib/mauve/history.rb
@@ -12,10 +12,16 @@ module Mauve
property :id, Serial
property :alert_id, Integer, :required => true
property :type, String, :required => true, :default => "unknown"
- property :event, Text, :required => true
- property :created_at, DateTime
+ property :event, Text, :required => true, :default => "Nothing set"
+ property :created_at, DateTime, :required => true
belongs_to :alert
+
+ before :valid?, :set_created_at
+
+ def set_created_at(context = :default)
+ self.created_at = Time.now unless self.created_at.is_a?(Time) or self.created_at.is_a?(DateTime)
+ end
def logger
Log4r::Logger.new self.class.to_s
diff --git a/lib/mauve/http_server.rb b/lib/mauve/http_server.rb
index 21c89e5..cb705ea 100644
--- a/lib/mauve/http_server.rb
+++ b/lib/mauve/http_server.rb
@@ -87,6 +87,7 @@ module Mauve
attr_accessor :session_secret
def initialize
+ super
@port = 1288
@ip = "127.0.0.1"
@document_root = "/usr/share/mauvealert"
diff --git a/lib/mauve/mauve_thread.rb b/lib/mauve/mauve_thread.rb
index 79e742a..1aa8619 100644
--- a/lib/mauve/mauve_thread.rb
+++ b/lib/mauve/mauve_thread.rb
@@ -6,6 +6,7 @@ module Mauve
class MauveThread
def initialize
+ @thread = nil
end
def logger
@@ -58,7 +59,7 @@ module Mauve
end
def frozen?
- @frozen and @thread.stop?
+ defined? @frozen and @frozen and @thread.stop?
end
def thaw
@@ -86,6 +87,10 @@ module Mauve
@thread.is_a?(Thread) and @thread.alive?
end
+ def stop?
+ @thread.is_a?(Thread) and @thread.stop?
+ end
+
def join(ok_exceptions=[])
@thread.join if @thread.is_a?(Thread)
end
@@ -94,6 +99,10 @@ module Mauve
@thread.raise(ex)
end
+ def backtrace
+ @thread.backtrace if @thread.is_a?(Thread)
+ end
+
def restart
self.stop
self.start
diff --git a/lib/mauve/notification.rb b/lib/mauve/notification.rb
index 2f77a13..ed96f7e 100644
--- a/lib/mauve/notification.rb
+++ b/lib/mauve/notification.rb
@@ -44,10 +44,7 @@ module Mauve
plus_one_week = MauveTime.now + 604800 # ish
while offset < plus_one_week
offset += interval
- if DuringRunner.new(offset, @alert, &@during).now?
- @logger.debug("Found reminder time of #{offset}")
- return offset
- end
+ return offset if DuringRunner.new(offset, @alert, &@during).now?
end
@logger.info("Could not find a reminder time less than a week "+
"for #{@alert}.")
diff --git a/lib/mauve/notifier.rb b/lib/mauve/notifier.rb
index 90df895..e62f7f4 100644
--- a/lib/mauve/notifier.rb
+++ b/lib/mauve/notifier.rb
@@ -13,6 +13,7 @@ module Mauve
attr_accessor :sleep_interval
def initialize
+ super
end
def main_loop
@@ -22,9 +23,7 @@ module Mauve
sz = Server.notification_buffer_size
return if sz == 0
-
- logger.debug("Notifier buffer is #{sz} in length")
-
+
my_threads = []
sz.times do
person, *args = Server.notification_pop
diff --git a/lib/mauve/notifiers/email.rb b/lib/mauve/notifiers/email.rb
index 129afec..77b10f1 100644
--- a/lib/mauve/notifiers/email.rb
+++ b/lib/mauve/notifiers/email.rb
@@ -7,17 +7,9 @@ module Mauve
module Notifiers
module Email
-
- class Default
+ class Default
attr_reader :name
- attr :server, true
- attr :port, true
- attr :username, true
- attr :password, true
- attr :login_method, true
- attr :from, true
- attr :subject_prefix, true
- attr :email_suffix, true
+ attr_writer :server, :port, :password, :login_method, :from, :subject_prefix, :email_suffix
def username=(username)
@login_method ||= :plain
@@ -47,20 +39,15 @@ module Mauve
message = prepare_message(destination, alert, all_alerts, conditions)
args = [@server, @port]
args += [@username, @password, @login_method.to_sym] if @login_method
- history = Mauve::History.new(:alert => alert, :type => :notification)
begin
Net::SMTP.start(*args) do |smtp|
smtp.send_message(message, @from, destination)
end
- history.event = "Sent mail to #{destination}."
- history.save
true
rescue StandardError => ex
logger.error "SMTP failure: #{ex.to_s}"
logger.debug ex.backtrace.join("\n")
- history.event = "Failed to send mail to #{destination} due to #{ex.to_s}"
- history.save
false
end
end
diff --git a/lib/mauve/notifiers/sms_aql.rb b/lib/mauve/notifiers/sms_aql.rb
index b295e6c..dbda229 100644
--- a/lib/mauve/notifiers/sms_aql.rb
+++ b/lib/mauve/notifiers/sms_aql.rb
@@ -41,17 +41,12 @@ module Mauve
'Content-Length' => opts_string.length.to_s
})
- history = Mauve::History.new(:alert => alert, :type => :notification)
if response.kind_of?(Net::HTTPSuccess)
- history.event = "Sent SMS via AQL to #{destination}"
- history.save
#
# Woo -- return true!
#
true
else
- history.event = "Failed to send SMS via AQL to #{destination} due to #{response.class.to_s}"
- history.save
false
end
end
diff --git a/lib/mauve/notifiers/xmpp-smack.rb b/lib/mauve/notifiers/xmpp-smack.rb
deleted file mode 100644
index a160a35..0000000
--- a/lib/mauve/notifiers/xmpp-smack.rb
+++ /dev/null
@@ -1,395 +0,0 @@
-# encoding: utf-8
-
-# Ruby.
-require 'pp'
-require 'log4r'
-require 'monitor'
-
-# Java. Note that paths are mangeled in jmauve_starter.
-require 'java'
-require 'smack.jar'
-require 'smackx.jar'
-include_class "org.jivesoftware.smack.XMPPConnection"
-include_class "org.jivesoftware.smackx.muc.MultiUserChat"
-include_class "org.jivesoftware.smack.RosterListener"
-
-module Mauve
-
- module Notifiers
-
- module Xmpp
-
- class XMPPSmackException < StandardError
- end
-
- ## Main wrapper to smack java library.
- #
- # @author Yann Golanski
- # @see http://www.igniterealtime.org/builds/smack/docs/3.1.0/javadoc/
- #
- # This is a singleton which is not idea but works well for mauve's
- # configuration file set up.
- #
- # In general, this class is meant to be intialized then the method
- # create_slave_thread must be called. The latter will spawn a new
- # thread that will do the connecting and sending of messages to
- # the XMPP server. Once this is done, messages can be send via the
- # send_msg() method. Those will be queued and depending on the load,
- # should be send quickly enough. This is done so that the main thread
- # can not worry about sending messages and can do important work.
- #
- # @example
- # bot = Mauve::Notifiers::Xmpp::XMPPSmack.new()
- # bot.run_slave_thread("chat.bytemark.co.uk", 'mauvealert', 'TopSecret')
- # msg = "What fresh hell is this? -- Dorothy Parker."
- # bot.send_msg("yann@chat.bytemark.co.uk", msg)
- # bot.send_msg("muc:test@conference.chat.bytemark.co.uk", msg)
- #
- # @FIXME This won't quiet work with how mauve is set up.
- #
- class XMPPSmack
-
- # Globals are evil.
- @@instance = nil
-
- # Default constructor.
- #
- # A queue (@queue) is used to pass information between master/slave.
- def initialize ()
- extend(MonitorMixin)
- @logger = Log4r::Logger.new "mauve::XMPP_smack<#{Process.pid}>"
- @queue = Queue.new
- @xmpp = nil
- @name = "mauve alert"
- @slave_thread = nil
- @regexp_muc = Regexp.compile(/^muc\:/)
- @regexp_tail = Regexp.compile(/\/.*$/)
- @jid_created_chat = Hash.new()
- @separator = '<->'
- @logger.info("Created XMPPSmack singleton")
- end
-
- # Returns the instance of the XMPPSmack singleton.
- #
- # @param [String] login The JID as a full address.
- # @param [String] pwd The password corresponding to the JID.
- # @return [XMPPSmack] The singleton instance.
- def self.instance (login, pwd)
- if true == @@instance.nil?
- @@instance = XMPPSmack.new
- jid, tmp = login.split(/@/)
- srv, name = tmp.split(/\//)
- name = "Mauve Alert Bot" if true == name.nil?
- @@instance.run_slave_thread(srv, jid, pwd, name)
- sleep 5 # FIXME: This really should be synced... But how?
- end
- return @@instance
- end
-
- # Create the thread that sends messages to the server.
- #
- # @param [String] srv The server address.
- # @param [String] jid The JID.
- # @param [String] pwd The password corresponding to the JID.
- # @param [String] name The bot name.
- # @return [NULL] nada
- def run_slave_thread (srv, jid, pwd, name)
- @srv = srv
- @jid = jid
- @pwd = pwd
- @name = name
- @logger.info("Creating slave thread on #{@jid}@#{@srv}/#{@name}.")
- @slave_thread = Thread.new do
- self.create_slave_thread()
- end
- return nil
- end
-
- # Returns whether instance is connected and authenticated.
- #
- # @return [Boolean] True or false.
- def is_connected_and_authenticated? ()
- return false if true == @xmpp.nil?
- return (@xmpp.isConnected() and @xmpp.isAuthenticated())
- end
-
- # Creates the thread that does the actual sending to XMPP.
- # @return [NULL] nada
- def create_slave_thread ()
- begin
- @logger.info("Slave thread is now alive.")
- self.open()
- loop do
- rcp, msg = @queue.deq().split(@separator, 2)
- @logger.debug("New message for '#{rcp}' saying '#{msg}'.")
- if rcp.match(@regexp_muc)
- room = rcp.gsub(@regexp_muc, '').gsub(@regexp_tail, '')
- self.send_to_muc(room, msg)
- else
- self.send_to_jid(rcp, msg)
- end
- end
- rescue XMPPSmackException
- @logger.fatal("Something is wrong")
- ensure
- @logger.info("XMPP bot disconnect.")
- @xmpp.disconnect()
- end
- return nil
- end
-
- # Send a message to the recipient.
- #
- # @param [String] rcp The recipent MUC or JID.
- # @param [String] msg The message.
- # @return [NULL] nada
- def send_msg(rcp, msg)
- #if @slave_thread.nil? or not self.is_connected_and_authenticated?()
- # str = "There is either no slave thread running or a disconnect..."
- # @logger.warn(str)
- # self.reconnect()
- #end
- @queue.enq(rcp + @separator + msg)
- return nil
- end
-
- # Sends a message to a room.
- #
- # @param [String] room The name of the room.
- # @param [String] mgs The message to send.
- # @return [NULL] nada
- def send_to_muc (room, msg)
- if not @jid_created_chat.has_key?(room)
- @jid_created_chat[room] = MultiUserChat.new(@xmpp, room)
- @jid_created_chat[room].join(@name)
- end
- @logger.debug("Sending to MUC '#{room}' message '#{msg}'.")
- @jid_created_chat[room].sendMessage(msg)
- return nil
- end
-
- # Sends a message to a jid.
- #
- # Do not destroy the chat, we can reuse it when the user log back in again.
- # Maybe?
- #
- # @param [String] jid The JID of the recipient.
- # @param [String] mgs The message to send.
- # @return [NULL] nada
- def send_to_jid (jid, msg)
- if true == jid_is_available?(jid)
- if not @jid_created_chat.has_key?(jid)
- @jid_created_chat[jid] = @xmpp.getChatManager.createChat(jid, nil)
- end
- @logger.debug("Sending to JID '#{jid}' message '#{msg}'.")
- @jid_created_chat[jid].sendMessage(msg)
- end
- return nil
- end
-
- # Check to see if the jid is available or not.
- #
- # @param [String] jid The JID of the recipient.
- # @return [Boolean] Whether we can send a message or not.
- def jid_is_available?(jid)
- if true == @xmpp.getRoster().getPresence(jid).isAvailable()
- @logger.debug("#{jid} is available. Status is " +
- "#{@xmpp.getRoster().getPresence(jid).getStatus()}")
- return true
- else
- @logger.warn("#{jid} is not available. Status is " +
- "#{@xmpp.getRoster().getPresence(jid).getStatus()}")
- return false
- end
- end
-
- # Opens a connection to the xmpp server at given port.
- #
- # @return [NULL] nada
- def open()
- @logger.info("XMPP bot is being created.")
- self.open_connection()
- self.open_authentication()
- self.create_roster()
- sleep 5
- return nil
- end
-
- # Connect to server.
- #
- # @return [NULL] nada
- def open_connection()
- @xmpp = XMPPConnection.new(@srv)
- if false == self.connect()
- str = "Connection refused"
- @logger.error(str)
- raise XMPPSmackException.new(str)
- end
- @logger.debug("XMPP bot connected successfully.")
- return nil
- end
-
- # Authenticat connection.
- #
- # @return [NULL] nada
- def open_authentication()
- if false == self.login(@jid, @pwd)
- str = "Authentication failed"
- @logger.error(str)
- raise XMPPSmackException.new(str)
- end
- @logger.debug("XMPP bot authenticated successfully.")
- return nil
- end
-
- # Create a new roster and listener.
- #
- # @return [NULL] nada
- def create_roster
- @xmpp.getRoster().addRosterListener(RosterListener.new())
- @xmpp.getRoster().reload()
- @xmpp.getRoster().getPresence(@xmpp.getUser).setStatus(
- "Purple alert! Purple alert!")
- @logger.debug("XMPP bot roster aquired successfully.")
- return nil
- end
-
- # Connects to the server.
- #
- # @return [Boolean] true (aka sucess) or false (aka failure).
- def connect ()
- @xmpp.connect()
- return @xmpp.isConnected()
- end
-
- # Login onto the server.
- #
- # @param [String] jid The JID.
- # @param [String] pwd The password corresponding to the JID.
- # @return [Boolean] true (aka sucess) or false (aka failure).
- def login (jid, pwd)
- @xmpp.login(jid, pwd, @name)
- return @xmpp.isAuthenticated()
- end
-
- # Reconnects in case of errors.
- #
- # @return [NULL] nada
- def reconnect()
- @xmpp.disconnect
- @slave_thread = Thread.new do
- self.create_slave_thread()
- end
- return nil
- end
-
- def presenceChanged ()
- end
-
- end # XMPPSmack
-
-
- ## This is the class that gets called in person.rb.
- #
- # This class is a wrapper to XMPPSmack which does the hard work. It is
- # done this way to conform to the mauve configuration file way of
- # defining notifications.
- #
- # @author Yann Golanski
- class Default
-
- # Name of the class.
- attr_reader :name
-
- # Atrtribute.
- attr_accessor :jid
-
- # Atrtribute.
- attr_accessor :password
-
- # Atrtribute.
- attr_accessor :initial_jid
-
- # Atrtribute.
- attr_accessor :initial_messages
-
- # Default constructor.
- #
- # @param [String] name The name of the notifier.
- def initialize (name)
- extend(MonitorMixin)
- @name = name
- @logger = Log4r::Logger.new "mauve::XMPP_default<#{Process.pid}>"
- end
-
- # Sends a message to the relevant jid or muc.
- #
- # We have no way to know if a messages was recieved, only that
- # we send it.
- #
- # @param [String] destionation
- # @param [Alert] alert A mauve alert class
- # @param [Array] all_alerts subset of current alerts
- # @param [Hash] conditions Supported conditions, see above.
- # @return [Boolean] Whether a message can be send or not.
- def send_alert(destination, alert, all_alerts, conditions = nil)
- synchronize {
- client = XMPPSmack.instance(@jid, @password)
- if not destination.match(/^muc:/)
- if false == client.jid_is_available?(destination.gsub(/^muc:/, ''))
- return false
- end
- end
- client.send_msg(destination, convert_alert_to_message(alert))
- return true
- }
- end
-
- # Takes an alert and converts it into a message.
- #
- # @param [Alert] alert The alert to convert.
- # @return [String] The message, either as HTML.
- def convert_alert_to_message(alert)
- arr = alert.summary_three_lines
- str = arr[0] + ": " + arr[1]
- str += " -- " + arr[2] if false == arr[2].nil?
- str += "."
- return str
- #return alert.summary_two_lines.join(" -- ")
- #return "<p>" + alert.summary_two_lines.join("<br />") + "</p>"
- end
-
- # This is so unit tests can run fine.
- include Debug
-
- end # Default
-
- end
- end
-end
-
-# This is a simple example of usage. Run with:
-# ../../../jmauve_starter.rb xmpp-smack.rb
-# Clearly, the mauve jabber password is not correct.
-#
-# /!\ WARNING: DO NOT COMMIT THE REAL PASSWORD TO MERCURIAL!!!
-#
-def send_msg()
- bot = Mauve::Notifiers::Xmpp::XMPPSmack.instance(
- "mauvealert@chat.bytemark.co.uk/testing1234", '')
- msg = "What fresh hell is this? -- Dorothy Parker."
- bot.send_msg("yann@chat.bytemark.co.uk", msg)
- bot.send_msg("muc:test@conference.chat.bytemark.co.uk", msg)
- sleep 2
-end
-
-if __FILE__ == './'+$0
- Thread.abort_on_exception = true
- logger = Log4r::Logger.new('mauve')
- logger.level = Log4r::DEBUG
- logger.add Log4r::Outputter.stdout
- send_msg()
- send_msg()
- logger.info("START")
- logger.info("END")
-end
diff --git a/lib/mauve/notifiers/xmpp.rb b/lib/mauve/notifiers/xmpp.rb
index c4e1785..8131096 100644
--- a/lib/mauve/notifiers/xmpp.rb
+++ b/lib/mauve/notifiers/xmpp.rb
@@ -66,10 +66,10 @@ module Mauve
include Jabber
# Atrtribute.
- attr_reader :name
+ attr_reader :name, :jid
# Atrtribute.
- attr_accessor :jid, :password
+ attr_accessor :password
def initialize(name)
Jabber::logger = self.logger
@@ -80,7 +80,7 @@ module Mauve
@mucs = {}
@roster = nil
@closing = false
-
+ @client = nil
end
def logger
@@ -93,7 +93,7 @@ module Mauve
end
def connect
- logger.info "Jabber starting connection to #{@jid}"
+ logger.debug "Starting connection to #{@jid}"
# Make sure we're disconnected.
self.close if @client.is_a?(Client)
@@ -110,7 +110,6 @@ module Mauve
# already
@roster.add_subscription_request_callback do |ri, presence|
Thread.new do
- logger.debug "Known? #{is_known_contact?(presence.from).inspect}"
if is_known_contact?(presence.from)
logger.info("Accepting subscription request from #{presence.from}")
@roster.accept_subscription(presence.from)
@@ -127,10 +126,11 @@ module Mauve
end
@roster.wait_for_roster
- logger.debug "Jabber authenticated, setting presence"
@client.send(Presence.new(nil, "Woo!").set_type(nil))
+ logger.info "Connected as #{@jid}"
+
@client.on_exception do |ex, stream, where|
#
# The XMPP4R exception clauses in Stream all close the stream, so
@@ -203,17 +203,7 @@ module Mauve
alert.to_s
end
- history = Mauve::History.new(:alert_id => alert.id, :type => :notification)
-
- if send_message(destination_jid, txt)
- history.event = "Sent XMPP message to #{destination_jid}"
- history.save
- true
- else
- history.event = "Failed to send XMPP message to #{destination_jid}"
- history.save
- false
- end
+ send_message(destination_jid, txt)
end
# Sends a message to the destionation.
@@ -297,12 +287,12 @@ module Mauve
end
if !@mucs[jid.strip].active?
- logger.info("Joining #{jid}")
#
# Make sure we have a resource.
#
@mucs[jid.strip].join(jid, password)
+ logger.info("Joined #{jid}")
else
logger.debug("Already joined #{jid}.")
end
diff --git a/lib/mauve/people_list.rb b/lib/mauve/people_list.rb
index 23e0c1e..32e0708 100644
--- a/lib/mauve/people_list.rb
+++ b/lib/mauve/people_list.rb
@@ -34,11 +34,16 @@ module Mauve
# Return the array of people
#
def people
- logger.warn "No-one found in the people list for #{self.label}" if self.list.empty?
- list.collect do |name|
+ l = list.collect do |name|
Configuration.current.people.has_key?(name) ? Configuration.current.people[name] : nil
end.reject{|person| person.nil?}
+ #
+ # Hmm.. no-one in the list?!
+ #
+ logger.warn "No-one found in the people list for #{self.label}" if l.empty?
+
+ l
end
end
diff --git a/lib/mauve/person.rb b/lib/mauve/person.rb
index 0290faf..cf29ff9 100644
--- a/lib/mauve/person.rb
+++ b/lib/mauve/person.rb
@@ -63,9 +63,13 @@ module Mauve
# and turn them into false.
#
res = notification_method.send_alert(destination, @alert, @other_alerts, conditions)
+
#
# Log the result
- logger.debug "Notification " + (res ? "succeeded" : "failed" ) + " for #{@person.username} using notifier '#{name}' to '#{destination}'"
+ note = "#{@alert.update_type.upcase}: notification " + (res ? "succeeded" : "failed" ) + " for #{@person.username} using notifier '#{name}' to '#{destination}'."
+ logger.info note
+ h = History.new(:alert_id => @alert.id, :type => "notification", :event => note)
+ logger.error "Unable to save history due to #{h.errors.inspect}" if !h.save
res
end
@@ -144,7 +148,6 @@ module Mauve
end
def remind(alert, level)
- logger.debug("Reminder for #{alert} send at level #{level}.")
send_alert(level, alert)
end
@@ -153,45 +156,45 @@ module Mauve
#
def send_alert(level, alert)
now = MauveTime.now
- suppressed_changed = nil
+
threshold_breached = @notification_thresholds.any? do |period, previous_alert_times|
first = previous_alert_times.first
first.is_a?(MauveTime) and (now - first) < period
end
- this_alert_suppressed = false
+ was_suppressed = self.suppressed?
if Server.instance.started_at > alert.updated_at.to_time and (Server.instance.started_at + Server.instance.initial_sleep) > MauveTime.now
- logger.warn("Alert last updated in prior run of mauve -- ignoring for initial sleep period.")
- this_alert_suppressed = true
- elsif threshold_breached
- unless suppressed?
- logger.warn("Suspending notifications to #{username} until further notice.")
- suppressed_changed = true
- end
+ logger.info("Alert last updated in prior run of mauve -- ignoring for initial sleep period.")
+ return
+ end
+
+ if threshold_breached
+ logger.info("Suspending notifications to #{username} until further notice.") unless was_suppressed
@suppressed = true
+
else
- if suppressed?
- suppressed_changed = false
- logger.warn "Starting to send notifications again for #{username}."
- else
- logger.info "Notifying #{username} of #{alert} at level #{level}"
- end
+ logger.info "Starting to send notifications again for #{username}." if was_suppressed
@suppressed = false
+
end
- return if suppressed? or this_alert_suppressed
+ #
+ # We only suppress notifications if we were suppressed before we started,
+ # and are still suppressed.
+ #
+ return if was_suppressed and self.suppressed?
- Server.notification_push([self, level, alert, suppressed_changed])
+ Server.notification_push([self, level, alert, was_suppressed])
end
- def do_send_alert(level, alert, suppressed_changed)
+ def do_send_alert(level, alert, was_suppressed)
result = NotificationCaller.new(
self,
alert,
current_alerts,
Configuration.current.notification_methods,
- :suppressed_changed => suppressed_changed
+ :was_suppressed => was_suppressed
).instance_eval(&__send__(level))
if result
@@ -205,10 +208,9 @@ module Mauve
@notification_thresholds[period].push MauveTime.now
@notification_thresholds[period].shift
end
-
- logger.info("Notification for #{username} of #{alert} at level #{level} has been successful")
+ true
else
- logger.error("Failed to notify #{username} about #{alert} at level #{level}")
+ false
end
end
diff --git a/lib/mauve/processor.rb b/lib/mauve/processor.rb
index 083b9a1..f36dacb 100644
--- a/lib/mauve/processor.rb
+++ b/lib/mauve/processor.rb
@@ -11,9 +11,7 @@ module Mauve
attr_accessor :transmission_cache_expire_time, :sleep_interval
def initialize
- # Set the logger up
- @logger = Log4r::Logger.new(self.class.to_s)
-
+ super
#
# Set up the transmission id cache
#
@@ -22,10 +20,11 @@ module Mauve
@transmission_cache_checked_at = Time.now
end
- def main_loop
-
- logger.info("Buffer has packets waiting...") if Server.packet_buffer_size > 0
+ def logger
+ @logger ||= Log4r::Logger.new(self.class.to_s)
+ end
+ def main_loop
#
# Only do the loop a maximum of 10 times every @sleep_interval seconds
#
@@ -39,7 +38,9 @@ module Mauve
Timer.instance.freeze unless Timer.instance.frozen?
- @logger.debug("Got #{data.inspect} from #{client.inspect}")
+ raise ArgumentError, "arse"
+
+ logger.debug("Got #{data.inspect} from #{client.inspect}")
ip_source = "#{client[3]}:#{client[1]}"
update = Proto::AlertUpdate.new
@@ -48,14 +49,14 @@ module Mauve
update.parse_from_string(data)
if @transmission_id_cache[update.transmission_id.to_s]
- @logger.debug("Ignoring duplicate transmission id #{update.transmission_id}")
+ logger.info("Ignoring duplicate transmission id #{update.transmission_id}")
#
# Continue with next packet.
#
next
end
- @logger.debug "Update #{update.transmission_id} sent at #{update.transmission_time} from "+
+ logger.info "Update #{update.transmission_id} sent at #{update.transmission_time} from "+
"'#{update.source}'@#{ip_source} alerts #{update.alert.length}"
Alert.receive_update(update, received_at)
@@ -64,10 +65,10 @@ module Mauve
NotImplementedError,
DataObjects::IntegrityError => ex
- @logger.error "#{ex} (#{ex.class}) while parsing #{data.length} bytes "+
+ logger.error "#{ex} (#{ex.class}) while parsing #{data.length} bytes "+
"starting '#{data[0..15].inspect}' from #{ip_source}"
- @logger.debug ex.backtrace.join("\n")
+ logger.debug ex.backtrace.join("\n")
ensure
@transmission_id_cache[update.transmission_id.to_s] = MauveTime.now
diff --git a/lib/mauve/sender.rb b/lib/mauve/sender.rb
index 122456c..ad047fe 100644
--- a/lib/mauve/sender.rb
+++ b/lib/mauve/sender.rb
@@ -3,7 +3,6 @@ require 'ipaddr'
require 'resolv'
require 'socket'
require 'mauve/mauve_time'
-require 'pp'
module Mauve
class Sender
diff --git a/lib/mauve/server.rb b/lib/mauve/server.rb
index 51587c0..4bd5a0f 100644
--- a/lib/mauve/server.rb
+++ b/lib/mauve/server.rb
@@ -43,7 +43,7 @@ module Mauve
# Sleep time between pooling the @buffer buffer.
@sleep = 1
- @freeze = false
+ @frozen = false
@stop = false
@stopped_at = MauveTime.now
@@ -166,7 +166,7 @@ module Mauve
begin
klass.instance.join
rescue StandardError => ex
- logger.warn "Caught #{ex.to_s} whilst checking #{klass} thread"
+ logger.error "Caught #{ex.to_s} whilst checking #{klass} thread"
logger.debug ex.backtrace.join("\n")
end
@@ -177,7 +177,8 @@ module Mauve
end
#
- # Now do the same with other threads.
+ # Now do the same with other threads. However if these ones crash, the
+ # server has to stop, as there is no method to restart them.
#
thread_list.each do |t|
diff --git a/lib/mauve/timer.rb b/lib/mauve/timer.rb
index 40abe43..f6ada88 100644
--- a/lib/mauve/timer.rb
+++ b/lib/mauve/timer.rb
@@ -14,6 +14,7 @@ module Mauve
attr_accessor :sleep_interval, :last_run_at
def initialize
+ super
@initial_sleep = 300
@initial_sleep_threshold = 300
end
@@ -29,7 +30,6 @@ module Mauve
# look for the next alert_changed object.
#
if next_alert.nil? or next_alert.due_at > MauveTime.now
- logger.debug("Next alert was #{next_alert} due at #{next_alert.due_at}") unless next_alert.nil?
next_alert_changed = AlertChanged.find_next_with_event
end
@@ -51,12 +51,12 @@ module Mauve
#
# Sleep indefinitely
#
- logger.debug("Nothing to notify about -- snoozing indefinitely.")
+ logger.info("Nothing to notify about -- snoozing indefinitely.")
else
#
# La la la nothing to do.
#
- logger.debug("Next to notify: #{next_to_notify} -- snoozing until #{next_to_notify.due_at}")
+ logger.info("Next to notify: #{next_to_notify} -- snoozing until #{next_to_notify.due_at}")
end
#
diff --git a/lib/mauve/udp_server.rb b/lib/mauve/udp_server.rb
index 59bc5bc..8649efe 100644
--- a/lib/mauve/udp_server.rb
+++ b/lib/mauve/udp_server.rb
@@ -15,6 +15,7 @@ module Mauve
attr_accessor :ip, :port, :sleep_interval
def initialize
+ super
#
# Set the logger up
#
@@ -49,7 +50,7 @@ module Mauve
@socket.bind(@ip, @port)
- logger.debug("Successfully opened UDP socket on #{@ip}:#{@port}")
+ logger.info("Successfully opened UDP socket on #{@ip}:#{@port}")
end
def close_socket
@@ -59,10 +60,11 @@ module Mauve
@socket.close
rescue IOError => ex
# Just in case there is some sort of explosion!
- logger.debug("Caught IOError #{ex.to_s}")
+ logger.error "Caught IOError #{ex.to_s}"
+ logger.debug ex.backtrace.join("\n")
end
- logger.debug("Successfully closed UDP socket")
+ logger.info("Successfully closed UDP socket")
end
def main_loop
diff --git a/lib/mauve/web_interface.rb b/lib/mauve/web_interface.rb
index 3770924..4594e10 100644
--- a/lib/mauve/web_interface.rb
+++ b/lib/mauve/web_interface.rb
@@ -185,6 +185,7 @@ EOF
n_hours = params[:n_hours] || 2
type_hours = params[:type_hours] || "daylight"
alerts = params[:alerts] || []
+ note = params[:note] || nil
n_hours = (n_hours.to_i > 188 ? 188 : n_hours.to_i)
@@ -196,18 +197,28 @@ EOF
succeeded = []
failed = []
-
+
alerts.each do |k,v|
begin
a = Alert.get!(k.to_i)
rescue DataMapper::ObjectNotFoundError => ex
failed << ex
+ next
end
+ logger.debug "arse"
+
begin
a.acknowledge!(@person, ack_until)
+ logger.debug note
+ unless note.to_s.empty?
+ h = History.new(:alert_id => a.id, :type => "note", :event => note.to_s)
+ logger.debug h.errors unless h.save
+ end
succeeded << a
rescue StandardError => ex
+ logger.error "Caught #{ex.to_s} when trying to save #{a.inspect}"
+ logger.debug ex.backtrace.join("\n")
failed << ex
end
end
@@ -454,14 +465,15 @@ EOF
result = begin
auth.authenticate(usr,pwd)
rescue Exception => ex
- @logger.debug "Caught exception during Bytemark auth for #{usr} (#{ex.to_s})"
+ logger.error "Caught exception during Bytemark auth for #{usr} (#{ex.to_s})"
+ logger.debug ex.backtrace.join("\n")
false
end
if true == result
return true
else
- @logger.debug "Bytemark authentication failed for #{usr}"
+ logger.warn "Bytemark authentication failed for #{usr}"
end
#
@@ -472,14 +484,15 @@ EOF
Digest::SHA1.hexdigest(params['password']) == Configuration.current.people[usr].password
end
rescue Exception => ex
- @logger.debug "Caught exception during local auth for #{usr} (#{ex.to_s})"
+ logger.error "Caught exception during local auth for #{usr} (#{ex.to_s})"
+ logger.debug ex.backtrace.join("\n")
false
end
if true == result
return true
else
- @logger.debug "Local authentication failed for #{usr}"
+ logger.warn "Local authentication failed for #{usr}"
end
#
diff --git a/mauveserver.conf b/mauveserver.conf
index c17f7f7..4baec0a 100644
--- a/mauveserver.conf
+++ b/mauveserver.conf
@@ -5,7 +5,9 @@
# The service which listens for alert messages
#
server {
+ #
# persistent data store, only sqlite3 supported at the moment
+ #
database "sqlite3:///var/lib/mauvealert/alerts.db"
listener {
@@ -14,7 +16,7 @@ server {
}
# default is probably more than enough!
- #transmission_id_expire_time 600
+ # transmission_id_expire_time 600
# few options for web interface, just the TCP port number
web_interface {
@@ -28,44 +30,49 @@ logger {
default_format "%d [ %6.6l ] [ %12.12c ] %m"
-# outputter("stdout") {
-# level Log4r::DEBUG
-# }
-
outputter("file") {
- filename "/var/log/mauve/mauveserver.log"
+ filename "/var/log/mauvealert/mauvealert.log"
trunc false
- level Log4r::DEBUG
+ level Log4r::INFO
}
- outputter("email") {
- server "outgoing.mx.bytemark.co.uk"
- subject "Mauve logger output"
- from "#{ENV['USER']}@#{Socket.gethostname}"
- to "patrick@bytemark.co.uk"
- domain "test.mauve.bytemark.co.uk"
- level Log4r::WARN
- }
+# outputter("stdout") {
+# level Log4r::DEBUG
+# }
+
+# outputter("email") {
+# server "localhost"
+# subject "Mauve logger output"
+# from "mauvealert@localhost"
+# to "boring@localhost"
+# domain "localhost"
+# level Log4r::WARN
+# }
}
notification_method("email") {
+ #
# email address to send from
+ #
from "mauvealert@" + `hostname`.chomp
- # smarthost
+
+ #
+ # outbound smtp host
+ #
server "localhost"
- # add this to the subject of any emails we send
- subject_prefix "[mauve] "
- # for testing, enable this
- #deliver_to_file "/tmp/alerts.txt"
+ #
+ # add this to the subject of any emails we send
+ #
+ subject_prefix "[mauvealert]"
}
# How to log into a jabber server
#
# notification_method("xmpp") {
-# jid "mauvealert@jabber.org/olympus"
-# password "WojIsEv8ScaufOm1"
+# jid "mauvealert@chat.example.com/boo"
+# password "x"
# }
# How to notify by SMS - we use aql.com, you'll need to write a module
@@ -86,12 +93,6 @@ notification_method("email") {
# alert levels. You probably want more people, see below for a more complete
# example.
#
-# Passwords are generated like so:
-# ruby-1.8.7-p72 > require 'digest/sha1'
-# => true
-# ruby-1.8.7-p72 > sha1 = Digest::SHA1.hexdigest('my new super secure and easy to type on phone password')
-# => "729cf161621400fa63fcb3b4750441390fbface2"
-#
person("root") {
all { email("root@localhost") }
}
@@ -148,6 +149,7 @@ person("root") {
# }
# }
+#
# Default notification - tell root about all alerts every hour
#
alert_group {
diff --git a/views/_acknowledge_input.haml b/views/_acknowledge_input.haml
index b6fc24b..82f3044 100644
--- a/views/_acknowledge_input.haml
+++ b/views/_acknowledge_input.haml
@@ -7,7 +7,10 @@ Acknowledge these alerts for
%option{ :value => "wallclock" } wall-clock
hours
%span#ack_until_text
-%input#ack_until{ :value => '', :type => :hidden, :name => 'ack_until' }
+%input#ack_until{ :value => '', :type => :hidden, :name => 'ack_until' }
+%br
+with the note
+%input#note{ :name => 'note', :type => "text"}
%input{ :type => 'submit', :value => 'Go!' }
:javascript
// Change of value in the hours box
diff --git a/views/alert.haml b/views/alert.haml
index 7e7503f..d4e274f 100644
--- a/views/alert.haml
+++ b/views/alert.haml
@@ -47,7 +47,7 @@
%th Notifications sent out
%td
%ul
- - @alert.changes.each do |change|
+ - @alert.changes.first(10).each do |change|
- if change.was_relevant?
%li
%strong= change.level
@@ -59,8 +59,8 @@
%tr
%th History
%td
- %ul
- - @alert.histories.each do |history|
+ %ul#histories
+ - @alert.histories.first(10).each do |history|
%li
= history.event
at