summaryrefslogtreecommitdiffstats
path: root/smokemtr.py
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2014-07-16 22:49:29 +0200
committerFlorian Pritz <bluewind@xinu.at>2014-07-16 22:49:29 +0200
commit8c399f7c9e5c798f9c8797a0db92c5299726b058 (patch)
treee3ac15d81c7c2391f6622106370c741a58560a79 /smokemtr.py
parent4da4c0d678df2b9451480f0a624410de50665adc (diff)
downloadbin-8c399f7c9e5c798f9c8797a0db92c5299726b058.tar.gz
bin-8c399f7c9e5c798f9c8797a0db92c5299726b058.tar.xz
smokemtr.py: use sendmail; MTR to all IPs of the target
Use sendmail directly instead of SMTP because the SMTP host could be unreachable and sendmail just dumps the mail into a spool dir for the MTA to pick up whenever it is ready. Less error prone. Look up IP addresses of the target and run MTR to all of them in case the target has both, an ipv4 and ipv6. This also works for hosts with more than one A record in which case all IPs will be pinged and added to the report. Could put a bit of load on the network, but I don't care. Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'smokemtr.py')
-rwxr-xr-xsmokemtr.py67
1 files changed, 43 insertions, 24 deletions
diff --git a/smokemtr.py b/smokemtr.py
index 6d0f30f..b52f35e 100755
--- a/smokemtr.py
+++ b/smokemtr.py
@@ -4,14 +4,16 @@
against a target hosts - meant to be triggered by a
smokeping alert. Output is emailed and saved to log.'''
-import argparse, datetime, subprocess, smtplib
+import argparse, datetime, subprocess, smtplib, socket
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
-MAIL_FROM = 'SmokeMTR <root@mistral.server-speed.net>'
-MAIL_TO = 'root@mistral.server-speed.net'
-SMTP_HOST = 'localhost'
-LOG_FILE = '/tmp/smokealert.out'
+MAIL_FROM = 'SmokeMTR <root@mistral.server-speed.net>'
+MAIL_TO = 'root@mistral.server-speed.net'
+LOG_FILE = '/tmp/smokealert.out'
+SENDMAIL = '/usr/bin/sendmail'
+MTR = 'mtr'
+MTR_CYCLES = 20
def parse_args():
"""Define the argparse parameters to accept for smokeping args:
@@ -25,19 +27,44 @@ def parse_args():
parser.add_argument('raised', action="store", default=None, nargs="?")
return(parser.parse_args())
+def get_ips_for_target(host):
+ """Get a list of IPs for a host"""
+
+ ips = []
+
+ for entry in socket.getaddrinfo(host, None):
+ ip = entry[4][0]
+ if ip not in ips:
+ ips.append(ip)
+
+ return ips
def mtr_host(parsed):
"""Run a matt's traceroute against the problematic host and append the results to
a list which will be used to log to file and send email"""
+ ips = get_ips_for_target(parsed.host)
+
m = []
m.append( '===== %s =====\n' % str(datetime.datetime.now())[:19] )
m.append( 'Alert: %s\n' % parsed.alert )
m.append( 'Loss: %s\n' % parsed.loss )
m.append( 'Round Trip Time: %s\n' % parsed.rtt )
- m.append( '%s: %s\n\n' % (parsed.target, parsed.host) )
- m.append( 'MTR to: %s\n' % parsed.host )
- m.append( cmd_out( ('/usr/sbin/mtr --report-wide --report --show-ips --report-cycles 20 %s' % parsed.host).split() ))
+ m.append( '%s: %s\n\n' % (parsed.target, ", ".join(ips)) )
+
+ cmd = [MTR, '--report-wide', '--report', '--show-ips', '--report-cycles', str(MTR_CYCLES)]
+
+ procs = []
+ for ip in ips:
+ procs.append({
+ "proc": cmd_run(cmd + [ip]),
+ "ip": ip,
+ })
+
+ for entry in procs:
+ entry["proc"].wait()
+ m.append( 'MTR to: %s\n' % entry["ip"] )
+ m.append(entry["proc"].communicate()[0]+"\n")
extra = ""
if parsed.raised == '0':
@@ -46,19 +73,19 @@ def mtr_host(parsed):
extra = "raised"
mail_alert(subject="[SmokeAlert] %s %s %s" % (parsed.host, parsed.alert, extra), body=''.join(m))
-
+
f = open(LOG_FILE, 'a')
f.write( "".join(m) + '\n' )
f.close()
-def cmd_out(args, **kwds):
- """cmd_out uses the subprocess lib to grab the output of a system command.
+def cmd_run(args, **kwds):
+ """cmd_run uses the subprocess lib to run a system command.
There are easier ways to this but apparently this is the 'best practice'
method according to: http://goo.gl/LfYhP"""
kwds.setdefault("stdout", subprocess.PIPE)
kwds.setdefault("stderr", subprocess.STDOUT)
p = subprocess.Popen(args, **kwds)
- return p.communicate()[0]
+ return p
def mail_alert(subject="Smokeping alert", body=""):
'''Generate an HTML and TXT encoded mail with given subject and body'''
@@ -71,11 +98,7 @@ def mail_alert(subject="Smokeping alert", body=""):
# Create the body of the message (a plain-text and an HTML version).
text = body
- html = """\
- <pre>
- %s
- </pre>
- """ % body
+ html = """<pre>%s</pre>""" % body
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
@@ -87,13 +110,9 @@ def mail_alert(subject="Smokeping alert", body=""):
msg.attach(part1)
msg.attach(part2)
- # Send the message via local SMTP server.
- s = smtplib.SMTP(SMTP_HOST)
- # sendmail function takes 3 arguments: sender's address, recipient's address
- # and message to send - here it is sent as one string.
- s.sendmail(MAIL_FROM, MAIL_TO, msg.as_string())
- s.quit()
-
+ #print(msg.as_string())
+ sendmail = subprocess.Popen([SENDMAIL, MAIL_TO], stdin=subprocess.PIPE)
+ sendmail.communicate(msg.as_string())
if __name__ == '__main__':
mtr_host(parse_args())