Make recovered tasks correctly handle being aborted before being started.  Unlike other tasks, recovered tasks are effectively "started" as soon as they're created, since they're recovering a previously started task.  So implement that properly so that when they're aborted, they do all the necessary killing and cleanup stuff.

This should fix a bug where jobs aborted while the scheduler is down won't get properly aborted when the scheduler starts up.

Signed-off-by: Steve Howard <showard@google.com>


git-svn-id: http://test.kernel.org/svn/autotest/trunk@3171 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/scheduler/monitor_db_unittest.py b/scheduler/monitor_db_unittest.py
index 240eb5a..773af7b 100644
--- a/scheduler/monitor_db_unittest.py
+++ b/scheduler/monitor_db_unittest.py
@@ -1563,7 +1563,7 @@
         self.test_verify_task_with_queue_entry()
 
 
-    def _setup_post_job_task_expects(self, autoserv_success, hqe_status,
+    def _setup_post_job_task_expects(self, autoserv_success, hqe_status=None,
                                      hqe_aborted=False):
         self.queue_entry.execution_tag.expect_call().and_return('tag')
         self.pidfile_monitor = monitor_db.PidfileRunMonitor.expect_new()
@@ -1578,7 +1578,8 @@
         if not hqe_aborted:
             self.pidfile_monitor.exit_code.expect_call().and_return(code)
 
-        self.queue_entry.set_status.expect_call(hqe_status)
+        if hqe_status:
+            self.queue_entry.set_status.expect_call(hqe_status)
 
 
     def _setup_pre_parse_expects(self, autoserv_success):
@@ -1593,6 +1594,12 @@
         self.queue_entry.set_status.expect_call(status)
 
 
+    def _expect_execute_run_monitor(self):
+        self.monitor.exit_code.expect_call()
+        self.monitor.exit_code.expect_call().and_return(0)
+        self._expect_copy_results()
+
+
     def _setup_post_job_run_monitor(self, pidfile_name):
         self.pidfile_monitor.has_process.expect_call().and_return(True)
         autoserv_pidfile_id = object()
@@ -1604,9 +1611,7 @@
             log_file=mock.anything_comparator(),
             pidfile_name=pidfile_name,
             paired_with_pidfile=self.PIDFILE_ID)
-        self.monitor.exit_code.expect_call()
-        self.monitor.exit_code.expect_call().and_return(0)
-        self._expect_copy_results()
+        self._expect_execute_run_monitor()
 
 
     def _expect_copy_results(self, monitor=None, queue_entry=None):
@@ -1658,6 +1663,20 @@
         self.god.check_playback()
 
 
+    def test_final_reparse_recovery(self):
+        self.god.stub_class(monitor_db, 'PidfileRunMonitor')
+        self.monitor = self.god.create_mock_class(monitor_db.PidfileRunMonitor,
+                                                  'run_monitor')
+        self._setup_post_job_task_expects(True)
+        self._expect_execute_run_monitor()
+        self._setup_post_parse_expects(True)
+
+        task = monitor_db.FinalReparseTask([self.queue_entry],
+                                           run_monitor=self.monitor)
+        self.run_task(task, True)
+        self.god.check_playback()
+
+
     def _setup_gather_logs_expects(self, autoserv_killed=True,
                                    hqe_aborted=False):
         self.god.stub_class(monitor_db, 'PidfileRunMonitor')
@@ -1773,6 +1792,26 @@
         self._test_cleanup_task_helper(False, True)
 
 
+    def test_recovery_queue_task_aborted_early(self):
+        # abort a RecoveryQueueTask right after it's created
+        self.god.stub_class_method(monitor_db.QueueTask, '_log_abort')
+        self.god.stub_class_method(monitor_db.QueueTask, '_finish_task')
+        run_monitor = self.god.create_mock_class(monitor_db.PidfileRunMonitor,
+                                                 'run_monitor')
+
+        self.queue_entry.execution_tag.expect_call().and_return('tag')
+        run_monitor.kill.expect_call()
+        run_monitor.has_process.expect_call().and_return(True)
+        monitor_db.QueueTask._log_abort.expect_call()
+        monitor_db.QueueTask._finish_task.expect_call()
+
+        task = monitor_db.RecoveryQueueTask(self.job, [self.queue_entry],
+                                            run_monitor)
+        task.abort()
+        self.assert_(task.aborted)
+        self.god.check_playback()
+
+
 class HostTest(BaseSchedulerTest):
     def test_cmp_for_sort(self):
         expected_order = [