Support restricting access to drones by user.  Administrators can put lines like

<hostname>_users: showard,scottz

in the global config, where <hostname> is a drone hostname.  That drone will then be limited to use by those users (that is, by jobs launched by those users, and tasks launched due to those jobs).  This required numerous changes:
* added a requested_by field to SpecialTask (with corresponding migration).  For tasks with queue_entries, we can infer this from the job, but for those without, we need this information explicitly declared.  Note this can be null if the task was created by the system, not in response to any user action.  The only place this occurs now is in scheduler recovery (Dispatcher._recover_hosts_where()), but there may be an upcoming feature to periodically reverify hosts, which would be another (much more common) case.
* modified all SpecialTask creation sites to pass requested_by if necessary.
* modified AgentTask to keep a username attribute, and modified its run() method to pass that to PidfileRunMonitor.run(), which passes it along to DroneManager.execute_command().
* modified Agent to always keep self.task around, there's no reason to throw it away and now that we're looking at it from other classes, it's problematic if it disappears.
* modified Dispatcher throttling code to pass the username when requesting max runnable processes.
* added an allowed_users property to _AbstractDrone, and made DroneManager load it from the global config.
* made DroneManager's max_runnable_processes() and _choose_drone_for_execution() methods accept the username and obey user restrictions.
* added extensive tests for everything.  the modiications required to monitor_db_unittest were annoying but not too bad.  but parts of that file may need to be removed as they'll be obsoleted by monitor_db_functional_test and they'll become increasingly annoying to maintain.

couple other related changes:
* got rid of CleanupHostsMixin.  it was only acutally needed by GatherLogsTasks (since we made the change to have GatherLogsTask always run), so I inlined it there and simplified code accordingly.
* changed a bunch of places in the scheduler that were constructing new instances of Django models for existing rows.  they would do something like "models.Host(id=<id of existing host>)".  that's correct for scheduler DBModels, but not for Django models.  For Django models, you only instantiate new instances when you want to create a new row.  for fetching existing rows you always use a manager -- Model.objects.get() or Model.objects.filter() etc.  this was an existing bug but wasn't exposed until I made some of the changes involved in this feature.

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


git-svn-id: http://test.kernel.org/svn/autotest/trunk@3961 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/scheduler/monitor_db_functional_test.py b/scheduler/monitor_db_functional_test.py
index da930d5..f4cdcbb 100644
--- a/scheduler/monitor_db_functional_test.py
+++ b/scheduler/monitor_db_functional_test.py
@@ -139,7 +139,7 @@
         return 0
 
 
-    def max_runnable_processes(self):
+    def max_runnable_processes(self, username):
         return self.max_runnable_processes_value
 
 
@@ -190,7 +190,8 @@
 
 
     def execute_command(self, command, working_directory, pidfile_name,
-                        log_file=None, paired_with_pidfile=None):
+                        log_file=None, paired_with_pidfile=None,
+                        username=None):
         pidfile_id = self._DummyPidfileId(
                 self._get_pidfile_debug_string(working_directory, pidfile_name))
         self._future_pidfiles.append(pidfile_id)
@@ -472,7 +473,8 @@
     def _create_reverify_request(self):
         host = self.hosts[0]
         models.SpecialTask.objects.create(host=host,
-                                          task=models.SpecialTask.Task.VERIFY)
+                                          task=models.SpecialTask.Task.VERIFY,
+                                          requested_by=self.user)
         return host