blob: f42b32e339105aa397eea528e12fe9f2807981fd [file] [log] [blame]
Chris Masone2d61ca22012-04-02 16:52:46 -07001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Chris Masone96f16632012-04-04 18:36:03 -07005import logging, time
Chris Masone2d61ca22012-04-02 16:52:46 -07006
Chris Masone96f16632012-04-04 18:36:03 -07007import deduping_scheduler, forgiving_config_parser, board_enumerator
8import task, timed_event
Chris Masone2d61ca22012-04-02 16:52:46 -07009
10
11class Driver(object):
12 """Implements the main loop of the suite_scheduler.
13
14 @var _LOOP_INTERVAL: time to wait between loop iterations.
15
16 @var _scheduler: a DedupingScheduler, used to schedule jobs with the AFE.
Chris Masone3fba86f2012-04-03 10:06:56 -070017 @var _enumerator: a BoardEnumerator, used to list plaforms known to
Chris Masone2d61ca22012-04-02 16:52:46 -070018 the AFE
19 @var _events: list of BaseEvents to be handled each time through main loop.
20 """
21
22 _LOOP_INTERVAL = 5
23
24
Chris Masone96f16632012-04-04 18:36:03 -070025 def __init__(self, afe):
Chris Masone2d61ca22012-04-02 16:52:46 -070026 """Constructor
27
28 @param afe: an instance of AFE as defined in server/frontend.py.
29 @param config: an instance of ForgivingConfigParser.
30 """
31 self._scheduler = deduping_scheduler.DedupingScheduler(afe)
Chris Masone3fba86f2012-04-03 10:06:56 -070032 self._enumerator = board_enumerator.BoardEnumerator(afe)
Chris Masone2d61ca22012-04-02 16:52:46 -070033
Chris Masone2d61ca22012-04-02 16:52:46 -070034
Chris Masone96f16632012-04-04 18:36:03 -070035 def SetUpEventsAndTasks(self, config):
36 """Constructor
37 @param config: an instance of ForgivingConfigParser.
38 """
39 self._events = [timed_event.Nightly.CreateFromConfig(config),
40 timed_event.Weekly.CreateFromConfig(config)]
41
42 tasks = self.TasksFromConfig(config)
43
44 for event in self._events:
45 if event.keyword in tasks:
46 event.tasks = tasks[event.keyword]
47 # TODO(cmasone): warn about unknown keywords?
48
49
50 def TasksFromConfig(self, config):
51 """Generate a dict of {event_keyword: [tasks]} mappings from |config|.
52
53 For each section in |config| that encodes a Task, instantiate a Task
54 object. Determine the event that Task is supposed to run_on and
55 append the object to a list associated with the appropriate event
56 keyword. Return a dictionary of these keyword: list of task mappings.
57
58 @param config: a ForgivingConfigParser containing tasks to be parsed.
59 @return dict of {event_keyword: [tasks]} mappings.
60 @raise MalformedConfigEntry on a task parsing error.
61 """
62 tasks = {}
63 for section in config.sections():
64 if not timed_event.TimedEvent.HonorsSection(section):
65 try:
66 keyword, new_task = task.Task.CreateFromConfigSection(
67 config, section)
68 except task.MalformedConfigEntry as e:
69 logging.warn('%s is malformed: %s', section, e)
70 continue
71 tasks.setdefault(keyword, []).append(new_task)
72 return tasks
Chris Masone2d61ca22012-04-02 16:52:46 -070073
74
75 def RunForever(self):
76 """Main loop of the scheduler. Runs til the process is killed."""
77 while True:
78 self.HandleEventsOnce()
79 time.sleep(self._LOOP_INTERVAL)
80
81
82 def HandleEventsOnce(self):
83 """One turn through the loop. Separated out for unit testing."""
Chris Masone92874d32012-04-03 10:13:04 -070084 boards = self._enumerator.Enumerate()
Chris Masone2d61ca22012-04-02 16:52:46 -070085
Chris Masone96f16632012-04-04 18:36:03 -070086 branch_builds = {}
87
Chris Masone2d61ca22012-04-02 16:52:46 -070088 for e in self._events:
89 if e.ShouldHandle():
Chris Masone96f16632012-04-04 18:36:03 -070090 for board in boards:
91 # TODO(cmasone): determine branch_builds per board.
92 e.Handle(self._scheduler, branch_builds, board)