aboutsummaryrefslogtreecommitdiff
path: root/bin/mauveclient
diff options
context:
space:
mode:
Diffstat (limited to 'bin/mauveclient')
-rwxr-xr-xbin/mauveclient172
1 files changed, 172 insertions, 0 deletions
diff --git a/bin/mauveclient b/bin/mauveclient
new file mode 100755
index 0000000..d513926
--- /dev/null
+++ b/bin/mauveclient
@@ -0,0 +1,172 @@
+#! /usr/bin/ruby1.8
+# == Synopsis
+#
+# mauvesend: send alert(s) to a given alert station
+#
+# == Usage
+#
+# mauvesend [destination]
+# [--source | -o <source>] [--replace | -p] [--verbose | -v]
+# [--id <alert ID> [alert options] ... ]
+#
+# <destination>:
+# where the alert should go, can be one of:
+# SRV record from DNS (we add _mauvealert._udp to record name)
+# normal hostname (i.e. A record)
+# IP address:port number
+#
+# if no destination is supplied, reads parameter from file
+# /etc/mauvealert/mauvesend.destination (otherwise throws an error).
+#
+# --source | -o <source>:
+# identify the source of the alert (defaults to hostname, but you might
+# want to name your monitoring systems more explicitly).
+#
+# --replace | -p:
+# Send an update replacing all other alerts for this source - any previous
+# alerts not specified in this update are assumed to be cleared. If you
+# specify this option, you don't have to supply *any* alerts to raise or
+# clear (in which case all alerts from that source will be cleared).
+#
+# --verbose | -v:
+# If you specify this option once, it will print the transmission ID
+# of the packet for debugging. If you specify it twice, it will print
+# the entire data structure.
+#
+# You can specify any number of alerts in an update - every time you specify
+# --id starts a new alert.
+#
+# --id | -i <alert ID>:
+# alert ID; unique specified for each alert raised.
+#
+# --summary | -s <summary>:
+# text for humans describing the nature of the alert, first 100 characters
+# are only ones guaranteed to make it to pagers, twitter, SMS etc.
+#
+# --detail | -d <detail>:
+# HTML fragment describing the alert in more detail, no limit on length.
+#
+# --subject | -u <subject>:
+# set the subject of the alert (i.e. the server/entity that this alert
+# concerns).
+#
+# --clear | -c <time>:
+# mark the alert to be cleared at the given time, or +N where N is a number
+# of seconds, or 'now'. If not supplied, the alert is deemed to be raised
+# until explicitly cleared.
+#
+# --raise | -r <time>:
+# mark the alert to be (re)raised at the given time. If not supplied, the
+# alert will be raised immediately.
+#
+
+require 'getoptlong'
+require 'mauve/sender'
+require 'mauve/proto'
+require 'mauve/mauve_time'
+require 'pp'
+
+def error(msg)
+ STDERR.print "*** Error: #{msg}\n"
+ STDERR.print "*** For help, type: #{$0} -h\n"
+ exit 1
+end
+
+def parse_time_spec(spec)
+ now = Mauve::MauveTime.now
+
+ return now if spec == 'now'
+
+ case spec[0]
+ when ?+ then multiplier = 1
+ when ?- then multiplier = -1
+ else
+ return Mauve::MauveTime.parse(spec)
+ end
+ multiplier *= case spec[-1]
+ when ?m then 60
+ when ?h then 3600
+ when ?d then 86400
+ else
+ 1
+ end
+
+ now + spec[1..-1].to_i * multiplier
+end
+
+update = Mauve::Proto::AlertUpdate.new
+update.replace = false
+update.alert = []
+message = nil
+verbose = 0
+help = false
+
+GetoptLong.new(
+ ['-h', '--help', GetoptLong::NO_ARGUMENT],
+ ['-o', '--source', GetoptLong::REQUIRED_ARGUMENT],
+ ['-p', '--replace', GetoptLong::NO_ARGUMENT],
+ ['-i', '--id', GetoptLong::REQUIRED_ARGUMENT],
+ ['-s', '--summary', GetoptLong::REQUIRED_ARGUMENT],
+ ['-u', '--subject', GetoptLong::REQUIRED_ARGUMENT],
+ ['-c', '--clear', GetoptLong::REQUIRED_ARGUMENT],
+ ['-r', '--raise', GetoptLong::REQUIRED_ARGUMENT],
+ ['-d', '--detail', GetoptLong::REQUIRED_ARGUMENT],
+ ['-v', '--verbose', GetoptLong::NO_ARGUMENT]
+).each do |opt,arg|
+ case opt
+ when '-h'
+ help = true
+ when '-p'
+ update.replace = true
+ when '-i'
+ message = Mauve::Proto::Alert.new
+ message.id = arg
+ update.alert << message
+ when '-o'
+ error "Can only specify one source" if update.source
+ update.source = arg
+ when '-v'
+ verbose += 1
+ else
+ error "Must specify --id before message" unless message
+ case opt
+ when '-s' then message.summary = arg
+ when '-u' then message.subject = arg
+ when '-d' then message.detail = arg
+ when '-c' then message.clear_time = parse_time_spec(arg).to_i
+ when '-r' then message.raise_time = parse_time_spec(arg).to_i
+ else
+ error "Unknown option #{opt}"
+ end
+ end
+end
+
+
+# CAUTION! Kwality kode.
+#
+if help
+ # Open the file, stripping the shebang line
+ lines = File.open(__FILE__){|fh| fh.readlines}[2..-1]
+
+ lines.each do |line|
+ line.chomp!
+ break if line.empty?
+ puts line[2..-1].to_s
+ end
+
+ exit 0
+end
+
+
+error "No alerts specified" unless !update.alert.empty? || update.replace
+
+update.transmission_id = rand(2**63)
+
+begin
+ Mauve::Sender.new(ARGV).send(update, verbose)
+rescue ArgumentError => ae
+ error ae.message
+rescue Protobuf::NotInitializedError => bad
+ error "Alert not initialized fully - you must supply an ID"
+end
+