summaryrefslogtreecommitdiff
path: root/scheduler
diff options
context:
space:
mode:
authorjamesren <jamesren@592f7852-d20e-0410-864c-8624ca9c26a4>2010-08-26 17:56:28 +0000
committerjamesren <jamesren@592f7852-d20e-0410-864c-8624ca9c26a4>2010-08-26 17:56:28 +0000
commite8a3537cb22a5db493b17564a5df650159e5a8b4 (patch)
tree03f4386d6a4a0a3b5204e3149daecf3f4102b31d /scheduler
parent97ed22f89f99c3287a7d46665db409937690e425 (diff)
Sometimes, we just want to have important data about the job
readily available, without having to open the web interface. This patch adds important info to the regular status e-mails: * Number of tests executed * Success rate * Details about test failures So people can decide whether they actually want to inspect the results more carefully. Changes from v1: * Refactored the original code, that repeated a lot of logic to generate the subject and the body of the status e-mail. By refactoring it becomes a lot easier to make changes on the e-mail body if needed. * Fixed a bug, where job failures were being treated incorrectly. * Made floats to be displayed only with 2 decimals. Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com> git-svn-id: svn://test.kernel.org/autotest/trunk@4766 592f7852-d20e-0410-864c-8624ca9c26a4
Diffstat (limited to 'scheduler')
-rw-r--r--scheduler/scheduler_models.py117
1 files changed, 103 insertions, 14 deletions
diff --git a/scheduler/scheduler_models.py b/scheduler/scheduler_models.py
index bafaf5ff..721d0370 100644
--- a/scheduler/scheduler_models.py
+++ b/scheduler/scheduler_models.py
@@ -591,14 +591,53 @@ class HostQueueEntry(DBObject):
_drone_manager.unregister_pidfile(pidfile_id)
+ def _get_status_email_contents(self, status, summary=None, hostname=None):
+ """
+ Gather info for the status notification e-mails.
+
+ If needed, we could start using the Django templating engine to create
+ the subject and the e-mail body, but that doesn't seem necessary right
+ now.
+
+ @param status: Job status text. Mandatory.
+ @param summary: Job summary text. Optional.
+ @param hostname: A hostname for the job. Optional.
+
+ @return: Tuple (subject, body) for the notification e-mail.
+ """
+ job_stats = Job(id=self.job.id).get_execution_details()
+
+ subject = ('Autotest | Job ID: %s "%s" | Status: %s ' %
+ (self.job.id, self.job.name, status))
+
+ if hostname is not None:
+ subject += '| Hostname: %s ' % hostname
+
+ if status not in ["1 Failed", "Failed"]:
+ subject += '| Success Rate: %.2f %%' % job_stats['success_rate']
+
+ body = "Job ID: %s\n" % self.job.id
+ body += "Job Name: %s\n" % self.job.name
+ if hostname is not None:
+ body += "Host: %s\n" % hostname
+ if summary is not None:
+ body += "Summary: %s\n" % summary
+ body += "Status: %s\n" % status
+ body += "Results interface URL: %s\n" % self._view_job_url()
+ body += "Execution Time (HH:MM:SS): %s\n" % job_stats['execution_time']
+ body += "Tests Executed: %s\n" % job_stats['total_executed']
+ body += "Tests Passed: %s\n" % job_stats['total_passed']
+ body += "Tests Failed: %s\n" % job_stats['total_failed']
+ body += "Success Rate: %.2f %%\n" % job_stats['success_rate']
+ body += "Failures Summary:\n"
+ body += job_stats['failed_rows']
+
+ return subject, body
+
+
def _email_on_status(self, status):
hostname = self._get_hostname()
-
- subject = 'Autotest: Job ID: %s "%s" Host: %s %s' % (
- self.job.id, self.job.name, hostname, status)
- body = "Job ID: %s\nJob Name: %s\nHost: %s\nStatus: %s\n%s\n" % (
- self.job.id, self.job.name, hostname, status,
- self._view_job_url())
+ subject, body = self._get_status_email_contents(status, None, hostname)
email_manager.manager.send_email(self.job.email_list, subject, body)
@@ -606,24 +645,20 @@ class HostQueueEntry(DBObject):
if not self.job.is_finished():
return
- summary_text = []
+ summary = []
hosts_queue = HostQueueEntry.fetch('job_id = %s' % self.job.id)
for queue_entry in hosts_queue:
- summary_text.append("Host: %s Status: %s" %
+ summary.append("Host: %s Status: %s" %
(queue_entry._get_hostname(),
queue_entry.status))
- summary_text = "\n".join(summary_text)
+ summary = "\n".join(summary)
status_counts = models.Job.objects.get_status_counts(
[self.job.id])[self.job.id]
status = ', '.join('%d %s' % (count, status) for status, count
in status_counts.iteritems())
- subject = 'Autotest: Job ID: %s "%s" %s' % (
- self.job.id, self.job.name, status)
- body = "Job ID: %s\nJob Name: %s\nStatus: %s\n%s\nSummary:\n%s" % (
- self.job.id, self.job.name, status, self._view_job_url(),
- summary_text)
+ subject, body = self._get_status_email_contents(status, summary, None)
email_manager.manager.send_email(self.job.email_list, subject, body)
@@ -821,6 +856,60 @@ class Job(DBObject):
return entries
+ def get_execution_details(self):
+ """
+ Get test execution details for this job.
+
+ @return: Dictionary with test execution details
+ """
+ stats = {}
+ rows = _db.execute("""
+ SELECT t.test, s.word, t.reason
+ FROM tko_tests AS t, tko_jobs AS j, tko_status AS s
+ WHERE t.job_idx = j.job_idx
+ AND s.status_idx = t.status
+ AND j.afe_job_id = %s
+ """ % self.id)
+ total_executed = len(rows)
+ failed_rows = [r for r in rows if not 'GOOD' in r]
+
+ # Here the job failed, so no 'real' tests were executed
+ if total_executed <= 2:
+ total_executed = 0
+ total_failed = 0
+ success_rate = 0
+ else:
+ # Here we are taking SERVER_JOB and CLIENT_JOB.0, since they are
+ # not 'real' tests
+ total_executed -= 2
+ total_failed = len(failed_rows)
+ success_rate = 100 - ((total_failed / float(total_executed)) * 100)
+
+ failed_str = '%-30s %-10s %-40s\n' % ("Test Name", "Status", "Reason")
+ for row in failed_rows:
+ failed_str += '%-30s %-10s %-40s\n' % row
+
+ stats['total_executed'] = total_executed
+ stats['total_failed'] = total_failed
+ stats['total_passed'] = total_executed - total_failed
+ stats['success_rate'] = success_rate
+ stats['failed_rows'] = failed_str
+
+ time_row = _db.execute("""
+ SELECT started_time, finished_time
+ FROM tko_jobs
+ WHERE afe_job_id = %s;
+ """ % self.id)
+
+ t_begin, t_end = time_row[0]
+ delta = t_end - t_begin
+ minutes, seconds = divmod(delta.seconds, 60)
+ hours, minutes = divmod(minutes, 60)
+ stats['execution_time'] = "%02d:%02d:%02d" % (hours, minutes, seconds)
+
+ return stats
+
+
def set_status(self, status, update_queues=False):
self.update_field('status',status)