blob: 73b856875406adb77407bdf57016fb567b40dcc3 [file] [log] [blame]
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Run a job against Autotest.
See http://goto.google.com/monitor_db_per_job_refactor
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import logging
import sys
from lucifer import autotest
from lucifer import eventlib
from lucifer import loglib
logger = logging.getLogger(__name__)
# TODO(crbug.com/748234): This is for moblab. Prod may require
# different path.
_JOB_SHEPHERD_PROGRAM = '/usr/lib/job_shepherd'
def main(args):
"""Main function
@param args: list of command line args
"""
parser = argparse.ArgumentParser(prog='job_reporter', description=__doc__)
loglib.add_logging_options(parser)
parser.add_argument('--job-id', type=int, default=None)
parser.add_argument('--autoserv-exit', type=int, default=None,
help='autoserv exit status')
args = parser.parse_args(args)
loglib.configure_logging_with_args(parser, args)
autotest.monkeypatch()
autotest.load('frontend.setup_django_environment')
scheduler_models = autotest.load('scheduler.scheduler_models')
if args.job_id is not None:
if args.autoserv_exit is None:
# TODO(crbug.com/748234): autoserv not implemented yet.
raise NotImplementedError('not implemented yet (crbug.com/748234)')
job = scheduler_models.Job.objects.get(id=args.job_id)
hqes = list(scheduler_models.HostQueueEntry.objects
.filter(job_id=args.job_id))
else:
# TODO(crbug.com/748234): Full jobs not implemented yet.
raise NotImplementedError('not implemented yet')
handler = _EventHandler(job, hqes, autoserv_exit=args.autoserv_exit)
return _run_shepherd(handler, job_id=args.job_id)
def _run_shepherd(event_handler, job_id):
"""Run job_shepherd.
Events issues by the job_shepherd will be handled by event_handler.
@param event_handler: callable that takes an Event
@param job_id: job ID
"""
args = [_JOB_SHEPHERD_PROGRAM]
args.append('%d' % job_id)
return eventlib.run_event_command(event_handler=event_handler, args=args)
class _EventHandler(object):
"""Event handling dispatcher.
Event handlers are implemented as methods named _handle_<event value>.
Each handler method must handle its exceptions accordingly. If an
exception escapes, the job dies on the spot.
"""
def __init__(self, job, hqes, autoserv_exit):
"""Initialize instance.
@param job: Job instance to own
@param hqes: list of HostQueueEntry instances for the job
@param autoserv_exit: autoserv exit status
"""
self._job = job
self._hqes = hqes
# TODO(crbug.com/748234): autoserv not implemented yet.
self._autoserv_exit = autoserv_exit
def __call__(self, event):
logger.debug('Received event %r', event.name)
method_name = '_handle_%s' % event.value
try:
handler = getattr(self, method_name)
except AttributeError:
raise NotImplementedError('%s is not implemented for handling %s',
method_name, event.name)
handler(event)
def _handle_starting(self):
# TODO(crbug.com/748234): No event update needed yet.
pass
def _handle_parsing(self):
# TODO(crbug.com/748234): monitor_db leaves the HQEs in parsing
pass
def _handle_completed(self):
final_status = self._final_status()
for hqe in self._hqes:
hqe.set_status(final_status)
def _final_status(self):
afe_models = autotest.load('frontend.afe.models')
Status = afe_models.HostQueueEntry.Status
if self._job_was_aborted():
return Status.ABORTED
if self._autoserv_exit == 0:
return Status.COMPLETED
return Status.FAILED
def _job_was_aborted(self):
for hqe in self._hqes:
hqe.update_from_database()
if hqe.aborted:
return True
return False
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))