From 8c399f7c9e5c798f9c8797a0db92c5299726b058 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Wed, 16 Jul 2014 22:49:29 +0200 Subject: 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 --- smokemtr.py | 67 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 24 deletions(-) (limited to 'smokemtr.py') 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 ' -MAIL_TO = 'root@mistral.server-speed.net' -SMTP_HOST = 'localhost' -LOG_FILE = '/tmp/smokealert.out' +MAIL_FROM = 'SmokeMTR ' +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 = """\ -
-    %s
-  
- """ % body + html = """
%s
""" % 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()) -- cgit v1.2.3-24-g4f1b