OLD | NEW |
1 import time, logging | 1 import time, logging |
2 from autotest_lib.frontend.afe import model_attributes as afe_model_attributes | 2 from autotest_lib.frontend.afe import model_attributes as afe_model_attributes |
3 from autotest_lib.frontend.shared import rest_client | 3 from autotest_lib.frontend.shared import rest_client |
4 from autotest_lib.frontend.planner import model_attributes | 4 from autotest_lib.frontend.planner import model_attributes, support |
5 from autotest_lib.server import frontend | 5 from autotest_lib.server import frontend |
6 | 6 |
7 | 7 |
8 TICK_INTERVAL_SECS = 10 | 8 TICK_INTERVAL_SECS = 10 |
9 | 9 |
10 class ExecutionEngine(object): | 10 class ExecutionEngine(object): |
11 """ | 11 """ |
12 Provides the Test Planner execution engine | 12 Provides the Test Planner execution engine |
13 """ | 13 """ |
14 | 14 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 | 126 |
127 Look for runs that are in PASSED or FAILED, perform any additional | 127 Look for runs that are in PASSED or FAILED, perform any additional |
128 processing required, and set the entry to 'finalized'. | 128 processing required, and set the entry to 'finalized'. |
129 """ | 129 """ |
130 Status = model_attributes.TestRunStatus | 130 Status = model_attributes.TestRunStatus |
131 runs = self._planner_rpc.run('get_test_runs', plan__id=self._plan_id, | 131 runs = self._planner_rpc.run('get_test_runs', plan__id=self._plan_id, |
132 status__in=(Status.PASSED, Status.FAILED), | 132 status__in=(Status.PASSED, Status.FAILED), |
133 finalized=False) | 133 finalized=False) |
134 for run in runs: | 134 for run in runs: |
135 logging.info('finalizing test run %s', run) | 135 logging.info('finalizing test run %s', run) |
136 if run['status'] == Status.FAILED: | 136 |
137 self._planner_rpc.run('modify_host', id=run['host'], | 137 controller = support.TestPlanController( |
| 138 machine=run['host']['host'], |
| 139 test_alias=run['test_job']['test_config']['alias']) |
| 140 self._run_execute_after(controller, tko_test_id=run['tko_test'], |
| 141 success=(run['status'] == Status.PASSED)) |
| 142 |
| 143 if controller._fail: |
| 144 raise NotImplemented('TODO: implement forced failure') |
| 145 |
| 146 failed = (run['status'] == Status.FAILED or controller._fail) |
| 147 if failed and not controller._unblock: |
| 148 self._planner_rpc.run('modify_host', id=run['host']['id'], |
138 blocked=True) | 149 blocked=True) |
139 self._planner_rpc.run('modify_test_run', id=run['id'], | 150 self._planner_rpc.run('modify_test_run', id=run['id'], |
140 finalized=True) | 151 finalized=True) |
141 | 152 |
142 | 153 |
143 def _check_tko_jobs(self): | 154 def _check_tko_jobs(self): |
144 """ | 155 """ |
145 Instructs the server to update the Planner test runs table | 156 Instructs the server to update the Planner test runs table |
146 | 157 |
147 Sends an RPC to have the server pull the proper TKO tests and add them | 158 Sends an RPC to have the server pull the proper TKO tests and add them |
148 to the Planner tables. Logs information about what was added. | 159 to the Planner tables. Logs information about what was added. |
149 """ | 160 """ |
150 test_runs_updated = self._planner_rpc.run('update_test_runs', | 161 test_runs_updated = self._planner_rpc.run('update_test_runs', |
151 plan_id=self._plan_id) | 162 plan_id=self._plan_id) |
152 for update in test_runs_updated: | 163 for update in test_runs_updated: |
153 logging.info('added %s test run for tko test id %s (%s)', | 164 logging.info('added %s test run for tko test id %s (%s)', |
154 update['status'], update['tko_test_idx'], | 165 update['status'], update['tko_test_idx'], |
155 update['hostname']) | 166 update['hostname']) |
156 | 167 |
157 | 168 |
158 def _schedule_new_runs(self): | 169 def _schedule_new_runs(self): |
159 next_configs = self._planner_rpc.run('get_next_test_configs', | 170 next_configs = self._planner_rpc.run('get_next_test_configs', |
160 plan_id=self._plan_id) | 171 plan_id=self._plan_id) |
161 if next_configs['complete']: | 172 if next_configs['complete']: |
162 return True | 173 return True |
163 | 174 |
164 for config in next_configs['next_configs']: | 175 for config in next_configs['next_configs']: |
| 176 config_id = config['next_test_config_id'] |
| 177 controller = support.TestPlanController( |
| 178 machine=config['host'], |
| 179 test_alias=config['next_test_config_alias']) |
| 180 self._run_execute_before(controller) |
| 181 if controller._skip: |
| 182 self._planner_rpc.run('skip_test', test_config_id=config_id, |
| 183 hostname=config['host']) |
| 184 continue |
| 185 |
165 self._run_job(hostname=config['host'], | 186 self._run_job(hostname=config['host'], |
166 test_config_id=config['next_test_config_id']) | 187 test_config_id=config_id, |
| 188 cleanup_before_job=controller._reboot_before, |
| 189 cleanup_after_job=controller._reboot_after, |
| 190 run_verify=controller._run_verify) |
167 | 191 |
168 return False | 192 return False |
169 | 193 |
170 | 194 |
171 def _run_job(self, hostname, test_config_id): | 195 def _run_job(self, hostname, test_config_id, cleanup_before_job, |
| 196 cleanup_after_job, run_verify): |
172 test_config = self._planner_rpc.run('get_test_config', | 197 test_config = self._planner_rpc.run('get_test_config', |
173 id=test_config_id) | 198 id=test_config_id) |
174 | 199 |
175 info = self._afe_rest.execution_info.get().execution_info | 200 info = self._afe_rest.execution_info.get().execution_info |
176 info['control_file'] = test_config['control_file']['contents'] | 201 info['control_file'] = test_config['control_file']['contents'] |
177 info['is_server'] = test_config['is_server'] | 202 info['is_server'] = test_config['is_server'] |
| 203 info['cleanup_before_job'] = cleanup_before_job |
| 204 info['cleanup_after_job'] = cleanup_after_job |
| 205 info['run_verify'] = run_verify |
178 | 206 |
179 atomic_group_class = self._afe_rest.labels.get( | 207 atomic_group_class = self._afe_rest.labels.get( |
180 name=self._label_name).members[0].get().atomic_group_class.href | 208 name=self._label_name).members[0].get().atomic_group_class.href |
181 | 209 |
182 request = self._afe_rest.queue_entries_request.get( | 210 request = self._afe_rest.queue_entries_request.get( |
183 hosts=(hostname,), atomic_group_class=atomic_group_class) | 211 hosts=(hostname,), atomic_group_class=atomic_group_class) |
184 entries = request.queue_entries | 212 entries = request.queue_entries |
185 | 213 |
186 plan = self._planner_rpc.run('get_plan', id=self._plan_id) | 214 plan = self._planner_rpc.run('get_plan', id=self._plan_id) |
187 prefix = plan['label_override'] | 215 prefix = plan['label_override'] |
188 if prefix is None: | 216 if prefix is None: |
189 prefix = plan['name'] | 217 prefix = plan['name'] |
190 job_req = {'name' : '%s_%s_%s' % (prefix, test_config['alias'], | 218 job_req = {'name' : '%s_%s_%s' % (prefix, test_config['alias'], |
191 hostname), | 219 hostname), |
192 'execution_info' : info, | 220 'execution_info' : info, |
193 'queue_entries' : entries} | 221 'queue_entries' : entries} |
194 | 222 |
195 logging.info('starting test alias %s for host %s', | 223 logging.info('starting test alias %s for host %s', |
196 test_config['alias'], hostname) | 224 test_config['alias'], hostname) |
197 job = self._afe_rest.jobs.post(job_req) | 225 job = self._afe_rest.jobs.post(job_req) |
198 self._planner_rpc.run('add_job', | 226 self._planner_rpc.run('add_job', |
199 plan_id=self._plan_id, | 227 plan_id=self._plan_id, |
200 test_config_id=test_config_id, | 228 test_config_id=test_config_id, |
201 afe_job_id=job.get().id) | 229 afe_job_id=job.get().id) |
| 230 |
| 231 |
| 232 def _run_execute_before(self, controller): |
| 233 """ |
| 234 Execute the global support's execute_before() for the plan |
| 235 """ |
| 236 self._run_global_support(controller, 'execute_before') |
| 237 |
| 238 |
| 239 def _run_execute_after(self, controller, tko_test_id, success): |
| 240 """ |
| 241 Execute the global support's execute_after() for the plan |
| 242 """ |
| 243 self._run_global_support(controller, 'execute_after', |
| 244 tko_test_id=tko_test_id, success=success) |
| 245 |
| 246 |
| 247 def _run_global_support(self, controller, function_name, **kwargs): |
| 248 plan = self._planner_rpc.run('get_plan', id=self._plan_id) |
| 249 if plan['support']: |
| 250 context = {'model_attributes': afe_model_attributes} |
| 251 exec plan['support'] in context |
| 252 function = context.get(function_name) |
| 253 if function: |
| 254 if not callable(function): |
| 255 raise Exception('Global support defines %s, but it is not ' |
| 256 'callable' % function_name) |
| 257 function(controller, **kwargs) |
OLD | NEW |