Add the version 1 of the TKO parser, modify server_job to use this
version, and modify parse.py to look up the status version number
in order to instantiate the correct parser version.

Basically, it's an implementation of the parser that follows
the spec as outlined in
http://test.kernel.org/autotest/DraftParserSpecification. I did that
by implementing the "version 1" parser, as opposed to the existing
"version 0" parser, and it also adds some code to autotest itself to
log the fact that the status logs being written out follow the
"version 1" specification, so that when re-parsing existing results
older logs will still be parsed using the old (rather ad-hoc and
difficult to follow) algorithm.

The implementation is fairly similar to the existing version 0
implementation; it still uses all the same files for gathering
results, but there are the core changes:
- instead of grabbing kernel information from build.log, it gets
embedded into the status logs associated with reboots
- if a group is lacking a proper "END" section it implicitly assumes
it was somehow aborted
- reboots are wrapped in a group
- a "JOB" result is logged even if nothing bad happens (rather than
only logging it when something bad happens)
- you can have arbitrarily large amounts of group nesting

Signed-off-by: John Admanski <jadmanski@google.com>




git-svn-id: http://test.kernel.org/svn/autotest/trunk@1511 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/tko/parse.py b/tko/parse.py
index f18b076..1b96bab 100755
--- a/tko/parse.py
+++ b/tko/parse.py
@@ -3,8 +3,8 @@
 import os, sys, optparse, fcntl, errno, traceback
 
 import common
-from autotest_lib.client.common_lib import mail as common_mail
-from autotest_lib.tko import db as tko_db, utils, status_lib
+from autotest_lib.client.common_lib import mail, utils
+from autotest_lib.tko import db as tko_db, utils as tko_utils, status_lib
 
 
 def parse_args():
@@ -33,8 +33,8 @@
 
 	# we need a results directory
 	if len(args) == 0:
-		utils.dprint("ERROR: at least one results directory must "
-			     "be provided")
+		tko_utils.dprint("ERROR: at least one results directory must "
+				 "be provided")
 		parser.print_help()
 		sys.exit(1)
 
@@ -61,34 +61,45 @@
 	message_header = "\n".join(message_lines)
 
 	subject = "AUTOTEST: FAILED tests from job %s" % jobname
-	common_mail.send("", job.user, "", subject, message_header + message)
+	mail.send("", job.user, "", subject, message_header + message)
 
 
 def parse_one(db, jobname, path, reparse, mail_on_failure):
 	"""
 	Parse a single job. Optionally send email on failure.
 	"""
-	utils.dprint("\nScanning %s (%s)" % (jobname, path))
+	tko_utils.dprint("\nScanning %s (%s)" % (jobname, path))
 	if reparse and db.find_job(jobname):
-		utils.dprint("! Deleting old copy of job results to "
+		tko_utils.dprint("! Deleting old copy of job results to "
 				 "reparse it")
 		db.delete_job(jobname)
 	if db.find_job(jobname):
-		utils.dprint("! Job is already parsed, done")
+		tko_utils.dprint("! Job is already parsed, done")
 		return
 
+	# look up the status version
+	try:
+		job_keyval = utils.read_keyval(path)
+	except IOError, e:
+		if e.errno == errno.ENOENT:
+			status_version = 0
+		else:
+			raise
+	else:
+		status_version = job_keyval.get("status_version", 0)
+
 	# parse out the job
-	parser = status_lib.parser(0)
+	parser = status_lib.parser(status_version)
 	job = parser.make_job(path)
 	status_log = os.path.join(path, "status.log")
 	if not os.path.exists(status_log):
 		status_log = os.path.join(path, "status")
 	if not os.path.exists(status_log):
-		utils.dprint("! Unable to parse job, no status file")
+		tko_utils.dprint("! Unable to parse job, no status file")
 		return
 
 	# parse the status logs
-	utils.dprint("+ Parsing dir=%s, jobname=%s" % (path, jobname))
+	tko_utils.dprint("+ Parsing dir=%s, jobname=%s" % (path, jobname))
 	status_lines = open(status_log).readlines()
 	parser.start(job)
 	tests = parser.end(status_lines)
@@ -99,8 +110,8 @@
 	for test in job.tests:
 		if not test.subdir:
 			continue
-		utils.dprint("* testname, status, reason: %s %s %s"
-			     % (test.subdir, test.status, test.reason))
+		tko_utils.dprint("* testname, status, reason: %s %s %s"
+				 % (test.subdir, test.status, test.reason))
 		if test.status in ("FAIL", "WARN"):
 			message_lines.append(format_failure_message(
 			    jobname, test.kernel.base, test.subdir,
@@ -109,8 +120,8 @@
 
 	# send out a email report of failure
 	if len(message) > 2 and mail_on_failure:
-		utils.dprint("Sending email report of failure on %s to %s"
-			     % (jobname, job.user))
+		tko_utils.dprint("Sending email report of failure on %s to %s"
+				 % (jobname, job.user))
 		mailfailure(jobname, job, message)
 
 	# write the job into the database