When using Django models from a script, make the current user default to an actual database user named "autotest_system". This allows for simpler, more consistent code.
Signed-off-by: Steve Howard <[email protected]> --- autotest/frontend/afe/doctests/001_rpc_test.txt 2010-01-06 11:23:35.000000000 -0800 +++ autotest/frontend/afe/doctests/001_rpc_test.txt 2010-01-11 14:03:08.000000000 -0800 @@ -909,8 +909,8 @@ >>> peon_user.access_level = 0 >>> from autotest_lib.client.common_lib.test_utils import mock >>> god = mock.mock_god() ->>> god.stub_function(rpc_interface.thread_local, "get_user") ->>> rpc_interface.thread_local.get_user.expect_call().and_return(peon_user) +>>> god.stub_function(models.User, "current_user") +>>> models.User.current_user.expect_call().and_return(peon_user) >>> rpc_interface.abort_host_queue_entries(job__id=job_id) Traceback (most recent call last): AclAccessViolation: You cannot abort the following job entries: 8-debug_user/two-label --- autotest/frontend/afe/models.py 2010-01-11 14:03:08.000000000 -0800 +++ autotest/frontend/afe/models.py 2010-01-11 14:03:08.000000000 -0800 @@ -129,6 +129,8 @@ ACCESS_ADMIN = 1 ACCESS_USER = 0 + AUTOTEST_SYSTEM = 'autotest_system' + login = dbmodels.CharField(max_length=255, unique=True) access_level = dbmodels.IntegerField(default=ACCESS_USER, blank=True) @@ -161,6 +163,16 @@ return self.access_level >= self.ACCESS_ROOT + @classmethod + def current_user(cls): + user = thread_local.get_user() + if user is None: + user = cls.objects.get_or_create(login=cls.AUTOTEST_SYSTEM) + user.access_level = cls.ACCESS_ROOT + user.save() + return user + + class Meta: db_table = 'afe_users' @@ -259,7 +271,7 @@ if not first_time: AclGroup.check_for_acl_violation_hosts([self]) if self.locked and not self.locked_by: - self.locked_by = thread_local.get_user() + self.locked_by = User.current_user() self.lock_time = datetime.now() self.dirty = True elif not self.locked and self.locked_by: @@ -276,7 +288,7 @@ AclGroup.check_for_acl_violation_hosts([self]) for queue_entry in self.hostqueueentry_set.all(): queue_entry.deleted = True - queue_entry.abort(thread_local.get_user()) + queue_entry.abort() super(Host, self).delete() @@ -459,7 +471,7 @@ @staticmethod def check_for_acl_violation_hosts(hosts): - user = thread_local.get_user() + user = User.current_user() if user.is_superuser(): return accessible_host_ids = set( @@ -483,7 +495,7 @@ * the machine isn't ACL-accessible, or * the machine is in the "Everyone" ACL """ - user = thread_local.get_user() + user = User.current_user() if user.is_superuser(): return not_owned = queue_entries.exclude(job__owner=user.login) @@ -509,7 +521,7 @@ def check_for_acl_violation_acl_group(self): - user = thread_local.get_user() + user = User.current_user() if user.is_superuser(): return if self.name == 'Everyone': @@ -551,12 +563,12 @@ def add_current_user_if_empty(self): if not self.users.count(): - self.users.add(thread_local.get_user()) + self.users.add(User.current_user()) def perform_after_save(self, change): if not change: - self.users.add(thread_local.get_user()) + self.users.add(User.current_user()) self.add_current_user_if_empty() self.on_host_membership_change() @@ -734,9 +746,9 @@ return None - def abort(self, aborted_by): + def abort(self): for queue_entry in self.hostqueueentry_set.all(): - queue_entry.abort(aborted_by) + queue_entry.abort() def tag(self): @@ -845,18 +857,15 @@ def log_abort(self, user): - if user is None: - # automatic system abort (i.e. job timeout) - return abort_log = AbortedHostQueueEntry(queue_entry=self, aborted_by=user) abort_log.save() - def abort(self, user): + def abort(self): # this isn't completely immune to race conditions since it's not atomic, # but it should be safe given the scheduler's behavior. if not self.complete and not self.aborted: - self.log_abort(user) + self.log_abort(User.current_user()) self.aborted = True self.save() --- autotest/frontend/afe/rpc_handler.py 2010-01-11 14:03:08.000000000 -0800 +++ autotest/frontend/afe/rpc_handler.py 2010-01-11 14:03:08.000000000 -0800 @@ -7,8 +7,7 @@ import traceback, pydoc, re, urllib, logging, logging.handlers from autotest_lib.frontend.afe.json_rpc import serviceHandler -from autotest_lib.frontend.afe import rpc_utils -from autotest_lib.frontend import thread_local +from autotest_lib.frontend.afe import models, rpc_utils from autotest_lib.client.common_lib import global_config from autotest_lib.frontend.afe import rpcserver_logging @@ -84,7 +83,7 @@ def handle_rpc_request(self, request): - user = thread_local.get_user() + user = models.User.current_user() json_request = self.raw_request_data(request) decoded_request = self.decode_request(json_request) decoded_result = self.dispatch_request(decoded_request) --- autotest/frontend/afe/rpc_interface.py 2010-01-11 14:03:08.000000000 -0800 +++ autotest/frontend/afe/rpc_interface.py 2010-01-11 14:03:08.000000000 -0800 @@ -31,7 +31,6 @@ import datetime import common -from autotest_lib.frontend import thread_local from autotest_lib.frontend.afe import models, model_logic from autotest_lib.frontend.afe import control_file, rpc_utils from autotest_lib.client.common_lib import global_config @@ -289,7 +288,7 @@ def add_acl_group(name, description=None): group = models.AclGroup.add_object(name=name, description=description) - group.users.add(thread_local.get_user()) + group.users.add(models.User.current_user()) return group.id @@ -435,7 +434,7 @@ @returns The created Job id number. """ - user = thread_local.get_user() + user = models.User.current_user() owner = user.login # input validation if not (hosts or meta_hosts or one_time_hosts or atomic_group_name @@ -550,9 +549,8 @@ host_queue_entries = list(query.select_related()) rpc_utils.check_abort_synchronous_jobs(host_queue_entries) - user = thread_local.get_user() for queue_entry in host_queue_entries: - queue_entry.abort(user) + queue_entry.abort() def reverify_hosts(**filter_data): @@ -750,7 +748,7 @@ def create_recurring_run(job_id, start_date, loop_period, loop_count): - owner = thread_local.get_user().login + owner = models.User.current_user().login job = models.Job.objects.get(id=job_id) return job.create_recurring_job(start_date=start_date, loop_period=loop_period, @@ -813,7 +811,7 @@ result['tests'] = get_tests(sort_by=['name']) result['profilers'] = get_profilers(sort_by=['name']) result['current_user'] = rpc_utils.prepare_for_serialization( - thread_local.get_user().get_object_dict()) + models.User.current_user().get_object_dict()) result['host_statuses'] = sorted(models.Host.Status.names) result['job_statuses'] = sorted(models.HostQueueEntry.Status.names) result['job_timeout_default'] = models.Job.DEFAULT_TIMEOUT --- autotest/frontend/thread_local.py 2010-01-11 14:03:08.000000000 -0800 +++ autotest/frontend/thread_local.py 2010-01-11 14:03:08.000000000 -0800 @@ -1,14 +1,7 @@ import threading -# when using the models from a script, use this object to avoid null checks all -# over the place -class NullUser(object): - def is_superuser(self): - return True - - _store = threading.local() -_store.user = NullUser() +_store.user = None def set_user(user): """\ --- autotest/frontend/tko/rpc_interface.py 2010-01-11 13:14:38.000000000 -0800 +++ autotest/frontend/tko/rpc_interface.py 2010-01-11 14:03:08.000000000 -0800 @@ -1,8 +1,7 @@ import os, pickle, datetime, itertools, operator from django.db import models as dbmodels -from autotest_lib.frontend import thread_local from autotest_lib.frontend.afe import rpc_utils, model_logic -from autotest_lib.frontend.afe import readonly_connection +from autotest_lib.frontend.afe import models as afe_models, readonly_connection from autotest_lib.frontend.tko import models, tko_rpc_utils, graphing_utils from autotest_lib.frontend.tko import preconfigs @@ -334,7 +333,7 @@ def add_saved_query(name, url_token): name = name.strip() - owner = thread_local.get_user() + owner = afe_models.User.current_user().login existing_list = list(models.SavedQuery.objects.filter(owner=owner, name=name)) if existing_list: @@ -348,7 +347,7 @@ def delete_saved_queries(id_list): - user = thread_local.get_user() + user = afe_models.User.current_user().login query = models.SavedQuery.objects.filter(id__in=id_list, owner=user) if query.count() == 0: raise model_logic.ValidationError('No such queries found for this user') @@ -416,7 +415,7 @@ result['all_fields'] = sorted(model_fields + extra_fields) result['test_labels'] = get_test_labels(sort_by=['name']) result['current_user'] = rpc_utils.prepare_for_serialization( - thread_local.get_user().get_object_dict()) + afe_models.User.current_user().get_object_dict()) result['benchmark_key'] = benchmark_key result['tko_perf_view'] = tko_perf_view result['tko_test_view'] = model_fields --- autotest/scheduler/monitor_db.py 2010-01-11 14:03:08.000000000 -0800 +++ autotest/scheduler/monitor_db.py 2010-01-11 14:03:08.000000000 -0800 @@ -2143,6 +2143,9 @@ aborted_on.add(t) # extract some actual, unique aborted by value and write it out + # TODO(showard): this conditional is now obsolete, we just need to leave + # it in temporarily for backwards compatibility over upgrades. delete + # soon. assert len(aborted_by) <= 1 if len(aborted_by) == 1: aborted_by_value = aborted_by.pop() @@ -3566,9 +3569,8 @@ def request_abort(self): """Request that this Job be aborted on the next scheduler cycle.""" - queue_entries = HostQueueEntry.fetch(where="job_id=%s" % self.id) - for hqe in queue_entries: - hqe.update_field('aborted', True) + self_model = models.Job.objects.get(id=self.id) + self_model.abort() def schedule_delayed_callback_task(self, queue_entry): --- autotest/scheduler/monitor_db_cleanup.py 2010-01-10 11:48:52.000000000 -0800 +++ autotest/scheduler/monitor_db_cleanup.py 2010-01-11 14:03:08.000000000 -0800 @@ -65,7 +65,7 @@ where=['created_on + INTERVAL timeout HOUR < NOW()']) for job in query.distinct(): logging.warning('Aborting job %d due to job timeout', job.id) - job.abort(None) + job.abort() def _abort_jobs_past_max_runtime(self): @@ -83,7 +83,7 @@ id__in=[row[0] for row in rows]) for queue_entry in query.distinct(): logging.warning('Aborting entry %s due to max runtime', queue_entry) - queue_entry.abort(None) + queue_entry.abort() def _check_for_db_inconsistencies(self): --- autotest/scheduler/monitor_db_unittest.py 2010-01-11 14:03:08.000000000 -0800 +++ autotest/scheduler/monitor_db_unittest.py 2010-01-11 14:03:08.000000000 -0800 @@ -10,7 +10,6 @@ from autotest_lib.client.common_lib.test_utils import mock from autotest_lib.client.common_lib.test_utils import unittest from autotest_lib.database import database_connection, migrate -from autotest_lib.frontend import thread_local from autotest_lib.frontend.afe import models from autotest_lib.scheduler import monitor_db, drone_manager, email_manager from autotest_lib.scheduler import scheduler_config, gc_stats _______________________________________________ Autotest mailing list [email protected] http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
