Add email reporting to failing tests when parsing results
* added failtest for testing this (and anything else that needs a failing test
)
* Improved readability in parse script output
* Added getopt() for parse and added -m option for sending mail on failures
* pulled mail* functions in from mirror/mirror
* Get a realuser value in autoserv for run tests
* Fix jobkeyval value
From: David McMahon <[email protected]>
Signed-off-by: Martin Bligh <[email protected]>
git-svn-id: http://test.kernel.org/svn/autotest/trunk@910 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/server/autoserv b/server/autoserv
index 155bc6f..0df92d0 100755
--- a/server/autoserv
+++ b/server/autoserv
@@ -30,11 +30,16 @@
args = sys.argv[1:]
parser = utils.AutoservOptionParser(args)
+# Get a useful value for running 'USER'
+realuser = os.environ.get('USER')
+if not realuser:
+ realuser = 'anonymous'
+
machines = parser.parse_opts_param('-m', None, split = ',')
machines_file = parser.parse_opts_param('-M', None)
results = parser.parse_opts_param('-r', os.path.abspath('.'))
label = parser.parse_opts_param('-l', '')
-user = parser.parse_opts_param('-u', 'anonymous')
+user = parser.parse_opts_param('-u', realuser)
client = parser.parse_opts('-c')
reboot = parser.parse_opts('-b')
install_before = parser.parse_opts('-i')
diff --git a/tko/parse b/tko/parse
index a503ed2..d02596c 100755
--- a/tko/parse
+++ b/tko/parse
@@ -1,45 +1,97 @@
#!/usr/bin/python
-import os, re, parse, db, sys
+import os, re, parse, frontend, db, sys, socket, getopt
+
+usage = """\
+usage: parse
+ [-m] # Send mail for FAILED tests
+ [-o directory] # Specify results directory directly
+ <top level results directory> # Specify top level results directory
+"""
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hmo:", ["help"])
+except getopt.GetoptError:
+ # print help information and exit:
+ usage()
+ sys.exit(2)
+
+if len(sys.argv) < 2:
+ print usage
+ sys.exit(2)
+
+singledir = None
+mailit = False
+for name, value in opts:
+ if name in ("-h", "--help"):
+ usage()
+ sys.exit()
+ if name == "-m":
+ mailit = True
+ if name in ("-o", "--output"):
+ singledir = value
+
+
+if singledir:
+ dir = os.path.abspath(singledir)
+ jobs_list = [(os.path.basename(dir), dir)]
+else:
+ topdir = os.path.abspath(args[0])
+ jobs_list = [(dir, os.path.join(topdir, dir)) for dir in os.listdir(topdir)]
debug = True
-if len(sys.argv) < 2:
- raise "I need a path to the results directory"
-
-if sys.argv[1] == '-o':
- dir = os.path.abspath(sys.argv[2])
- jobs_list = [(os.path.basename(dir), dir)]
-else:
- topdir = os.path.abspath(sys.argv[1])
- jobs_list = [(dir, os.path.join(topdir, dir)) for dir in os.listdir(topdir)]
+failcc = ""
+notify_user = None
db = db.db(autocommit=False) # do commits transactionally
+def mailfailure(jobname, job, mesgtxt):
+ # XXX: Need to insert URL here too (frontend.test.url?)
+ link = "http://" + socket.gethostname() + "/results/" + jobname
+
+ # This looks pretty good on fixed-width-font email reader.
+ message_header = "\n%s\n%s\n\n%-12s %-20s %-12s %-10s %s\n" % ("The following tests FAILED for this job:", link, "Job name", "Kernel", "Test name", "FAIL/WARN", "Failure Reason")
+ message_header += "%-12s %-20s %-12s %-10s %s\n" % ("========", "======", "=========", "=========", "==============")
+
+ subject = "AUTOTEST: FAILED tests from " + " job " + jobname
+ parse.mail(notify_user, job.user, failcc, subject, message_header + mesgtxt)
+
+
def do_parse(jobname, path):
if debug:
- print 'looking for ' + path
+ print '\nScanning' + path
if db.find_job(jobname): # Job has already been parsed
if debug:
- print '\t- already processed'
+ print '! Already processed'
return
job = parse.job(path, 'regression')
if not job:
if debug:
- print '\t- not a job'
+ print '! Not a job'
return
- print 'parsed ' + path
+ print '+ Parsed ' + path
if not job.kernel:
if debug:
- print '\t- not a job.kernel'
+ print '! Not a job.kernel'
return
- print '%s %s' % (jobname, job.kernel.base)
+ print '* jobname, kernel version: %s %s' % (jobname, job.kernel.base)
+ mesgtxt = "\n"
for test in job.tests:
- print "\t%s %s %s" % (test.subdir, test.status, test.reason)
+ if not test.subdir:
+ continue
+ print "* testname, status, reason: %s %s %s" % (test.subdir, test.status, test.reason)
+ if re.match(r'(FAIL|WARN)',test.status):
+ mesgtxt += "%-12s %-20s %-12s %-10s %s" % (jobname, job.kernel.base, test.subdir, test.status, test.reason)
+
+ if len(mesgtxt) > 2 and mailit:
+ print "Sending email report of FAILURES on " + jobname + " to " + job.user
+ mailfailure(jobname, job, mesgtxt)
db.insert_job(jobname, job)
db.commit()
+
for (jobname, path) in jobs_list:
machine_list = os.path.join(path, '.machines')
if os.path.exists(machine_list):
diff --git a/tko/parse.py b/tko/parse.py
index 75f44d4..3ec753d 100755
--- a/tko/parse.py
+++ b/tko/parse.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-import os, re, md5, sys
+import os, re, md5, sys, email.Message, smtplib
valid_users = r'(apw|mbligh|andyw|korgtest)'
build_stock = re.compile('build generic stock (2\.\S+)')
@@ -10,6 +10,46 @@
debug = True
+# XXX: these mail bits came almost verbatim from mirror/mirror and this should
+# probably be refactored into another file and used by both.
+def mail(from_address, to_addresses, cc_addresses, subject, message_text):
+ # if passed a string for the to_addresses convert it to a tuple
+ if type(to_addresses) is str:
+ to_addresses = (to_addresses,)
+
+ message = email.Message.Message()
+ message["To"] = ", ".join(to_addresses)
+ message["Cc"] = ", ".join(cc_addresses)
+ message["From"] = from_address
+ message["Subject"] = subject
+ message.set_payload(message_text)
+
+ try:
+ sendmail(message.as_string())
+ except SendmailException, e:
+ server = smtplib.SMTP("localhost")
+ server.sendmail(from_address, to_addresses, cc_addresses, message.as_string())
+ server.quit()
+
+
+MAIL = "sendmail"
+
+class SendmailException(Exception):
+ pass
+
+def sendmail(message):
+ """Send an email using sendmail"""
+ # open a pipe to the mail program and
+ # write the data to the pipe
+ p = os.popen("%s -t" % MAIL, 'w')
+ p.write(message)
+ exitcode = p.close()
+ if exitcode:
+ raise SendmailException("Exit code: %s" % exitcode)
+
+# XXX: End of code from mirror/mirror
+
+
def shorten_patch(long):
short = os.path.basename(long)
short = re.sub(r'^patch-', '', short)
@@ -35,7 +75,7 @@
self.kernel = None
# Get the user + tag info from the keyval file.
- jobkeyval = os.path.join(dir, "keyval")
+ jobkeyval = os.path.join(os.path.dirname (dir), "keyval")
self.user = None
self.label = None
if os.path.exists(jobkeyval):