aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/control1
-rw-r--r--debian/mauvealert-server.postinst8
-rw-r--r--lib/mauve/configuration.rb107
-rw-r--r--lib/mauve/http_server.rb2
-rw-r--r--lib/mauve/mauve_time.rb43
-rw-r--r--lib/mauve/notification.rb32
-rw-r--r--lib/mauve/sender.rb4
-rw-r--r--lib/mauve/server.rb2
-rw-r--r--static/stylesheets/mauve.css21
-rw-r--r--test/tc_mauve_configuration.rb38
-rw-r--r--test/tc_mauve_configuration_builders_logger.rb7
-rw-r--r--test/tc_mauve_notification.rb10
-rw-r--r--test/tc_mauve_time.rb23
-rw-r--r--views/_alerts_table.haml9
-rw-r--r--views/_history.haml9
-rw-r--r--views/alerts.haml12
16 files changed, 280 insertions, 48 deletions
diff --git a/debian/control b/debian/control
index 798f058..a1c5cb1 100644
--- a/debian/control
+++ b/debian/control
@@ -43,6 +43,7 @@ Depends: mauvealert-common (>= 3.8.0),
libxmpp4r-ruby1.8,
${misc:Depends}
Suggests: mauvealert-client
+Recommends: liblocale-ruby1.8 | ruby-locale
Description: Mauve network alert system -- server
Mauve is a network alert system for system and network administrators. You can
use it to quickly set up ad-hoc monitoring for a variety of services, and to
diff --git a/debian/mauvealert-server.postinst b/debian/mauvealert-server.postinst
index 3d1c09a..967aa8d 100644
--- a/debian/mauvealert-server.postinst
+++ b/debian/mauvealert-server.postinst
@@ -17,4 +17,12 @@ for i in log lib ; do
chown -R $RUNASUSER:nogroup /var/$i/mauvealert
done
+#
+# Symlink jquery libraries in.
+#
+if [ -e /usr/share/javascript/jquery -a ! -e /usr/share/mauvealert/static/javascript/jquery ] ; then
+ ln -s /usr/share/javascript/jquery /usr/share/mauvealert/static/javascript/
+fi
+
+
#DEBHELPER#
diff --git a/lib/mauve/configuration.rb b/lib/mauve/configuration.rb
index 8a0b982..55bdd9f 100644
--- a/lib/mauve/configuration.rb
+++ b/lib/mauve/configuration.rb
@@ -27,7 +27,7 @@ module Mauve
# People
# @return [Hash]
attr_reader :people
-
+
# Alert groups
# @return [Array]
attr_reader :alert_groups
@@ -43,7 +43,7 @@ module Mauve
# Various further configuration items
#
attr_reader :bytemark_auth_url, :bytemark_calendar_url, :remote_http_timeout, :remote_https_verify_mode, :failed_login_delay
- attr_reader :max_acknowledgement_time
+ attr_reader :max_acknowledgement_time, :working_hours, :dead_zone, :daytime_hours
#
@@ -66,23 +66,30 @@ module Mauve
#
# Set a couple of params for remote HTTP requests.
#
- @remote_http_timeout = 5
- @remote_https_verify_mode = OpenSSL::SSL::VERIFY_PEER
+ self.remote_http_timeout = 5
+ self.remote_https_verify_mode = "peer"
#
# Rate limit login attempts to limit the success of brute-forcing.
#
- @failed_login_delay = 1
+ self.failed_login_delay = 1
#
# Maximum amount of time to acknowledge for
#
- @max_acknowledgement_time = 15.days
+ self.max_acknowledgement_time = 15.days
+
+ #
+ # Working hours
+ #
+ self.dead_zone = 3...6
+ self.daytime_hours = 8...20
+ self.working_hours = 9...17
end
# Set the calendar URL.
#
- # @param [String] arg
+ # @param [String] arg
# @return [URI]
def bytemark_calendar_url=(arg)
raise ArgumentError, "bytemark_calendar_url must be a string" unless arg.is_a?(String)
@@ -104,7 +111,7 @@ module Mauve
# Set the Bytemark Authentication URL
#
- # @param [String] arg
+ # @param [String] arg
# @return [URI]
def bytemark_auth_url=(arg)
raise ArgumentError, "bytemark_auth_url must be a string" unless arg.is_a?(String)
@@ -128,7 +135,7 @@ module Mauve
# @param [Integer] arg
# @return [Integer]
def remote_http_timeout=(arg)
- raise ArgumentError, "remote_http_timeout must be an integer" unless s.is_a?(Integer)
+ raise ArgumentError, "remote_http_timeout must be an integer" unless arg.is_a?(Integer)
@remote_http_timeout = arg
end
@@ -156,7 +163,7 @@ module Mauve
raise ArgumentError, "failed_login_delay must be numeric" unless arg.is_a?(Numeric)
@failed_login_delay = arg
end
-
+
# Set the maximum amount of time alerts can be ack'd for
#
#
@@ -169,5 +176,85 @@ module Mauve
lambda{|at| CalendarInterface.get_attendees(x,at)}
end
+ def working_hours=(arg)
+ @working_hours = do_parse_range(arg)
+ end
+
+ def daytime_hours=(arg)
+ @daytime_hours = do_parse_range(arg)
+ end
+
+ def dead_zone=(arg)
+ @dead_zone = do_parse_range(arg)
+ end
+
+ private
+
+ # This method takes a range, and wraps it within the specs defined by
+ # allowed_range.
+ #
+ # It can take an array of Numerics, Strings, Ranges etc
+ #
+ # @param
+ #
+ def do_parse_range(arg, allowed_range = (0...24))
+ args = [arg].flatten
+
+ #
+ # Tidy up our allowed ranges
+ #
+ min = allowed_range.first
+ max = allowed_range.last
+
+ #
+ # If we've been given a numeric range, make sure they're all floats.
+ #
+ min = min.to_f if min.is_a?(Numeric)
+ max = max.to_f if max.is_a?(Numeric)
+
+ ranges = []
+
+ args.each do |arg|
+ case arg
+ when Range
+ from = arg.first
+ to = arg.last
+ exclude_end = arg.exclude_end?
+ else
+ from = arg
+ to = arg
+ end
+
+ from = min unless allowed_range.include?(from)
+
+ #
+ # In the case of integers, we want to match up until, but not including
+ # the next integer.
+ #
+ if to.is_a?(Integer)
+ to = (exclude_end ? to : to.succ)
+ exclude_end = true
+ end
+
+ to = max unless allowed_range.include?(to)
+
+ from = from.to_f if from.is_a?(Numeric)
+ to = to.to_f if to.is_a?(Numeric)
+
+ if from > to or (from >= to and exclude_end)
+ ranges << Range.new(from, max, allowed_range.exclude_end?)
+ ranges << Range.new(min, to, exclude_end)
+ else
+ ranges << Range.new(from, to, exclude_end)
+ end
+
+ end
+
+ ranges
+ end
+
+
end
+
+
end
diff --git a/lib/mauve/http_server.rb b/lib/mauve/http_server.rb
index 583e6b5..9250b2e 100644
--- a/lib/mauve/http_server.rb
+++ b/lib/mauve/http_server.rb
@@ -187,7 +187,7 @@ module Mauve
#
# @return [String]
def base_url
- @base_url ||= "http://"+Server.instance.hostname
+ @base_url ||= "http://"+Server.instance.hostname+(self.port == "80" ? "" : ":#{self.port}")
end
# Stop the server
diff --git a/lib/mauve/mauve_time.rb b/lib/mauve/mauve_time.rb
index dfbf99b..ab0734a 100644
--- a/lib/mauve/mauve_time.rb
+++ b/lib/mauve/mauve_time.rb
@@ -103,17 +103,38 @@ class Time
#
#
def bank_holidays
- @bank_holidays ||= []
+ @bank_holidays = if defined? Server and Server.instance
+ Server.instance.bank_holidays
+ else
+ @bank_holidays || []
+ end
end
- # This sets the bank holiday dates for the bank_holiday? check.
+ # Returns an array of ranges of working hours
#
- # @param [Array] arg An array of Date of bank holidays
- # @returns [Array]
#
- def bank_holidays=(arg)
- raise ArgumentError unless arg.is_a?(Array) and arg.all?{|a| a.is_a?(Date)}
- @bank_holidays = arg
+ def working_hours
+ if defined? Configuration and Configuration.current
+ Configuration.current.working_hours
+ else
+ [9.0...17.0]
+ end
+ end
+
+ def dead_zone
+ if defined? Configuration and Configuration.current
+ Configuration.current.working_hours
+ else
+ [3.0...7.0]
+ end
+ end
+
+ def daytime_hours
+ if defined? Configuration and Configuration.current
+ Configuration.current.working_hours
+ else
+ [8.0...20.0]
+ end
end
# This relies on bank_holidays being set.
@@ -128,14 +149,16 @@ class Time
#
# @return [Boolean]
def working_hours?
- !bank_holiday? and (1..5).include?(self.wday) and ((9..16).include?(self.hour) or (self.hour == 8 && self.min >= 30))
+ (1..5).include?(self.wday) and
+ self.working_hours.any?{|r| r.include?(self.hour.to_f + self.min.to_f/60.0)} and
+ !self.bank_holiday?
end
# Test to see if it is currently daytime. The daytime day is 14 hours long
#
# @return [Boolean]
def daytime_hours?
- (8..21).include?(self.hour)
+ self.daytime_hours.any?{|r| r.include?(self.hour.to_f + self.min.to_f/60.0)}
end
# We're always in wallclock hours
@@ -149,7 +172,7 @@ class Time
#
# @return [Boolean]
def dead_zone?
- (3..6).include?(self.hour)
+ self.dead_zone.any?{|r| r.include?(self.hour.to_f + self.min.to_f/60.0)}
end
# Format the time as a string, relative to +now+
diff --git a/lib/mauve/notification.rb b/lib/mauve/notification.rb
index 899972b..fcefcbc 100644
--- a/lib/mauve/notification.rb
+++ b/lib/mauve/notification.rb
@@ -157,6 +157,18 @@ module Mauve
(@test_time - @alert.raised_at) >= seconds
end
+ # Tests if the alert has raised for a certain time.
+ #
+ # @param [Integer] seconds Number of seconds
+ # @return [Boolean]
+ def raised_for(seconds)
+ @test_time = @time if @test_time.nil?
+ @alert &&
+ @alert.raised? &&
+ (@test_time - @alert.raised_at) >= seconds
+ end
+
+
# Checks to see if x is contained in y
#
# @param [Array] y Array to search for +x+
@@ -177,10 +189,17 @@ module Mauve
# @return [Boolean]
def working_hours?
@test_time = @time if @test_time.nil?
- @test_time.bank_holidays = Server.instance.bank_holidays
@test_time.working_hours?
end
+ #
+ # Return true if today is a bank holiday
+ #
+ def bank_holiday?
+ @test_time = @time if @test_time.nil?
+ @test_time.bank_holiday?
+ end
+
# Test to see if we're in the dead zone. See Time#dead_zone?
#
# @return [Boolean]
@@ -189,6 +208,13 @@ module Mauve
@test_time.dead_zone?
end
+ #
+ # Return true if we're in daytime_hours. See Time#daytime_hours?
+ #
+ def daytime_hours?
+ @test_time = @time if @test_time.nil?
+ @test_time.daytime_hours?
+ end
end
# A Notification is an instruction to notify a person, or a list of people,
@@ -249,7 +275,7 @@ module Mauve
end
# Set up a during_runner
- during_runner ||= DuringRunner.new(Time.now, self.alert, &self.during)
+ during_runner ||= DuringRunner.new(Time.now, alert, &self.during)
# Should we notify at all?
return already_sent_to unless during_runner.now?
@@ -287,7 +313,7 @@ module Mauve
return nil unless alert.raised?
# Set up a during_runner
- during_runner ||= DuringRunner.new(Time.now, self.alert, &self.during)
+ during_runner ||= DuringRunner.new(Time.now, alert, &self.during)
if during_runner.now?
return during_runner.find_next(every)
diff --git a/lib/mauve/sender.rb b/lib/mauve/sender.rb
index 054313e..fc12a99 100644
--- a/lib/mauve/sender.rb
+++ b/lib/mauve/sender.rb
@@ -153,7 +153,7 @@ module Mauve
#
# Check the locale charset. This is to maximise the amout of information
- # mauve receives, rather than provide proper sanitised data for the server.
+ # mauve receives, rather than provide proper sanitized data for the server.
#
from_charset = (Locale.current.charset || Locale.charset) if defined?(Locale)
from_charset ||= "UTF-8"
@@ -201,7 +201,7 @@ module Mauve
#
# Clean up the update, and set any missing fields.
#
- update = sanitise(update)
+ update = sanitize(update)
data = sanitize(update).serialize_to_string
diff --git a/lib/mauve/server.rb b/lib/mauve/server.rb
index 0bbfdfb..52933ea 100644
--- a/lib/mauve/server.rb
+++ b/lib/mauve/server.rb
@@ -36,7 +36,7 @@ module Mauve
#
def initialize
super
- @hostname = "localhost"
+ @hostname = Socket.gethostname
@database = "sqlite3::memory:"
@started_at = Time.now
diff --git a/static/stylesheets/mauve.css b/static/stylesheets/mauve.css
index 4649775..cac6833 100644
--- a/static/stylesheets/mauve.css
+++ b/static/stylesheets/mauve.css
@@ -52,27 +52,38 @@ tr.detail {
/** Flash notices **/
-div.error {
+.error {
background-color: #ffe;
border: solid 2px #ffc;
background-image: url('/images/error.png');
}
-div.notice {
+.notice {
background-color: #eef;
border: solid 2px #ccf;
background-image: url('/images/information.png');
}
-div.flash {
+tr.error, tr.notice {
margin: 5px 5px 0px;
padding: 0px;
- padding-left: 20px;
+ padding-left: 25px;
color: black;
font-size: large;
background-position: 5px;
background-repeat: no-repeat;
- min-height: 20px;
+ min-height: 25px;
+}
+
+div.error, div.notice {
+ margin: 5px 5px 0px;
+ padding: 0px;
+ padding-left: 25px;
+ color: black;
+ font-size: large;
+ background-position: 5px;
+ background-repeat: no-repeat;
+ min-height: 25px;
}
div.flash p {
diff --git a/test/tc_mauve_configuration.rb b/test/tc_mauve_configuration.rb
new file mode 100644
index 0000000..bbc1901
--- /dev/null
+++ b/test/tc_mauve_configuration.rb
@@ -0,0 +1,38 @@
+$:.unshift "../lib/"
+
+require 'th_mauve'
+require 'mauve/configuration'
+
+class TcMauveConfiguration < Mauve::UnitTest
+ include Mauve
+
+ def setup
+ setup_logger
+ end
+
+ def teardown
+ teardown_logger
+ end
+
+ def test_do_parse_range
+ [
+ [[1.0...2.0], 1],
+ [[1.0...3.0], 1..2],
+ [[1.0...2.0], 1...2],
+ [[1.0...2.0, 4.0...7.0], [1, 4..6]],
+ [[1.0..1.0], 1.0],
+ [[1.0..2.0], 1.0..2.0],
+ [[1.0...2.0], 1.0...2.0],
+ [[1.0..1.0, 4.0..6.0], [1.0, 4.0..6.0]],
+ [[7.0...24.0, 0.0...7.0], 7..6],
+ [[6.0...7.0, 0.0...1.0], 6..0, 0...7],
+ [["x".."z", "a".."c"], "x".."c", "a".."z"]
+ ].each do |output, *input|
+ c = Configuration.new
+ assert_equal(output, c.__send__("do_parse_range",*input))
+ end
+ end
+
+end
+
+
diff --git a/test/tc_mauve_configuration_builders_logger.rb b/test/tc_mauve_configuration_builders_logger.rb
index 2d2bb80..14df0d8 100644
--- a/test/tc_mauve_configuration_builders_logger.rb
+++ b/test/tc_mauve_configuration_builders_logger.rb
@@ -2,6 +2,7 @@ $:.unshift "../lib/"
require 'th_mauve'
require 'mauve/configuration_builders/logger'
+require 'tempfile'
class TcMauveConfigurationBuildersLogger < Mauve::UnitTest
@@ -10,6 +11,8 @@ class TcMauveConfigurationBuildersLogger < Mauve::UnitTest
def test_load
+ test_log = Tempfile.new(self.class.to_s)
+
config=<<EOF
logger {
default_format "%d [ %l ] [ %12.12c ] %m"
@@ -19,7 +22,7 @@ logger {
outputter ("file") {
trunc false
- filename "test.conf"
+ filename "#{test_log.path}"
level DEBUG
}
@@ -46,7 +49,7 @@ EOF
assert_equal("%d [ %l ] [ %12.12c ] %m", outputter.formatter.pattern )
assert_equal(Log4r::DEBUG, outputter.level )
assert_equal(false, outputter.trunc )
- assert_equal("test.conf", outputter.filename )
+ assert_equal(test_log.path, outputter.filename )
end
def test_levels
diff --git a/test/tc_mauve_notification.rb b/test/tc_mauve_notification.rb
index 21ff41e..df8fa9b 100644
--- a/test/tc_mauve_notification.rb
+++ b/test/tc_mauve_notification.rb
@@ -224,6 +224,16 @@ EOF
logger_pop
end
+ def test_bank_holiday
+ time = Time.now
+
+ dr = DuringRunner.new(time)
+ assert(!dr.send(:bank_holiday?))
+
+ time.bank_holidays << Date.new(Time.now.year, Time.now.month, Time.now.day)
+ assert(dr.send(:bank_holiday?))
+ end
+
end
class TcMauveNotification < Mauve::UnitTest
diff --git a/test/tc_mauve_time.rb b/test/tc_mauve_time.rb
index 6e5989b..66cb4f7 100644
--- a/test/tc_mauve_time.rb
+++ b/test/tc_mauve_time.rb
@@ -16,8 +16,8 @@ class TestMauveTime < Mauve::UnitTest
#
# Working hours..
#
- hour_0 = Time.local(2011,6,6,8,30,0)
- hour_1 = Time.local(2011,6,6,9,30,0)
+ hour_0 = Time.local(2011,6,6,9,0,0)
+ hour_1 = Time.local(2011,6,6,10,0,0)
assert_equal(hour_1, t.in_x_hours(1,"working"))
assert_equal(hour_0, t.in_x_hours(0,"working"))
@@ -31,7 +31,7 @@ class TestMauveTime < Mauve::UnitTest
# Working hours..
#
hour_0 = Time.local(2011,6,3,16,45,32)
- hour_1 = Time.local(2011,6,6,9,15,32)
+ hour_1 = Time.local(2011,6,6,9,45,32)
assert_equal(hour_1, t.in_x_hours(1,"working"))
assert_equal(hour_0, t.in_x_hours(0,"working"))
@@ -41,10 +41,25 @@ class TestMauveTime < Mauve::UnitTest
x = Time.now
assert(!x.bank_holiday?)
-
x.bank_holidays << Date.new(x.year, x.month, x.day)
assert(x.bank_holiday?)
end
+ def test_dead_zone?
+ x = Time.local(2012,5,2,4,30,0)
+ assert(x.dead_zone?)
+
+ x = Time.local(2012,5,2,9,30,0)
+ assert(!x.dead_zone?)
+ end
+
+ def test_daytime_hours
+ x = Time.local(2012,5,2,4,30,0)
+ assert(!x.daytime_hours?)
+
+ x = Time.local(2012,5,2,9,30,0)
+ assert(x.daytime_hours?)
+ end
+
end
diff --git a/views/_alerts_table.haml b/views/_alerts_table.haml
index 40b2b1c..ed759be 100644
--- a/views/_alerts_table.haml
+++ b/views/_alerts_table.haml
@@ -11,7 +11,14 @@
});
%th#summary Summary
%th#time At
- = partial("alerts_table_group", :collection => @grouped_alerts)
+ - if @grouped_alerts.length > 0
+ = partial("alerts_table_group", :collection => @grouped_alerts)
+ - else
+ %tr{:class => %w(notice)}
+ %td
+ %td{:style => "text-align: center;"}
+ = "No #{@alert_type} alerts found!"
+ %td
%tr
%td{ :colspan => 3}
%address
diff --git a/views/_history.haml b/views/_history.haml
index 61bcf59..cfeec51 100644
--- a/views/_history.haml
+++ b/views/_history.haml
@@ -4,7 +4,14 @@
%p
= history.created_at.strftime("%R")
- history.alerts.each do |alert|
- = alert.subject
+ %a{ :href => self.class.url_for(alert) }
+ = alert.id
+ %strong
+ = alert.subject
= alert.summary
+ - if alert.source != alert.subject
+ = "(from #{alert.source})"
= history.event
+ - if history.user
+ = "by #{history.user}"
- @today = history.created_at
diff --git a/views/alerts.haml b/views/alerts.haml
index 896b5a3..88cb82c 100644
--- a/views/alerts.haml
+++ b/views/alerts.haml
@@ -1,11 +1,7 @@
-- if @grouped_alerts.length > 0
- %form#alerts{:method => :post, :action => '/alerts/acknowledge'}
- = partial('alerts_table')
- %h2 Actions
- %p= partial('acknowledge_input')
-- else
- .notice#alerts_table
- %p No alerts to display.
+%form#alerts{:method => :post, :action => '/alerts/acknowledge'}
+ = partial('alerts_table')
+ %h2 Actions
+ %p= partial('acknowledge_input')
:javascript
// Do the magic updates..
setTimeout("updateAlertsTable('#{@alert_type}','#{@group_by}');", 120000)