blob: a4b7db17dc72d167cdacd9f2cacf36f3851dff99 [file] [log] [blame]
showard1a5a4082009-07-28 20:01:37 +00001#!/usr/bin/python
Justin Giorgi67ad67d2016-06-29 14:41:04 -07002#pylint: disable-msg=C0111
showardb6d16622009-05-26 19:35:29 +00003
Jiaxi Luoaac54572014-06-04 13:57:02 -07004import datetime
Justin Giorgi67ad67d2016-06-29 14:41:04 -07005import unittest
beepse19d3032013-05-30 09:22:07 -07006
Justin Giorgi67ad67d2016-06-29 14:41:04 -07007import common
showardb6d16622009-05-26 19:35:29 +00008from autotest_lib.frontend import setup_django_environment
9from autotest_lib.frontend.afe import frontend_test_utils
showardb6d16622009-05-26 19:35:29 +000010from autotest_lib.frontend.afe import models, rpc_interface, frontend_test_utils
Shuqian Zhao54a5b672016-05-11 22:12:17 +000011from autotest_lib.frontend.afe import model_logic, model_attributes
jamesren4a41e012010-07-16 22:33:48 +000012from autotest_lib.client.common_lib import global_config
Aviv Keshet3dd8beb2013-05-13 17:36:04 -070013from autotest_lib.client.common_lib import control_data
Alex Miller4a193692013-08-21 13:59:01 -070014from autotest_lib.client.common_lib import error
Shuqian Zhao54a5b672016-05-11 22:12:17 +000015from autotest_lib.client.common_lib import priorities
Jiaxi Luoaac54572014-06-04 13:57:02 -070016from autotest_lib.client.common_lib.test_utils import mock
Jakob Juelich50e91f72014-10-01 12:43:23 -070017from autotest_lib.server import frontend
Fang Deng0cb2a3b2015-12-10 17:59:00 -080018from autotest_lib.server import utils as server_utils
MK Ryu9651ca52015-06-08 17:48:22 -070019from autotest_lib.server.cros.dynamic_suite import frontend_wrappers
showardb6d16622009-05-26 19:35:29 +000020
Aviv Keshet3dd8beb2013-05-13 17:36:04 -070021CLIENT = control_data.CONTROL_TYPE_NAMES.CLIENT
22SERVER = control_data.CONTROL_TYPE_NAMES.SERVER
showardb6d16622009-05-26 19:35:29 +000023
24_hqe_status = models.HostQueueEntry.Status
25
26
27class RpcInterfaceTest(unittest.TestCase,
28 frontend_test_utils.FrontendTestMixin):
29 def setUp(self):
30 self._frontend_common_setup()
Jiaxi Luoaac54572014-06-04 13:57:02 -070031 self.god = mock.mock_god()
showardb6d16622009-05-26 19:35:29 +000032
33
34 def tearDown(self):
Jiaxi Luoaac54572014-06-04 13:57:02 -070035 self.god.unstub_all()
showardb6d16622009-05-26 19:35:29 +000036 self._frontend_common_teardown()
Jakob Juelich50e91f72014-10-01 12:43:23 -070037 global_config.global_config.reset_config_values()
showardb6d16622009-05-26 19:35:29 +000038
39
showarda5288b42009-07-28 20:06:08 +000040 def test_validation(self):
41 # non-number for a numeric field
42 self.assertRaises(model_logic.ValidationError,
43 rpc_interface.add_atomic_group, name='foo',
44 max_number_of_machines='bar')
45 # omit a required field
46 self.assertRaises(model_logic.ValidationError, rpc_interface.add_label,
47 name=None)
48 # violate uniqueness constraint
49 self.assertRaises(model_logic.ValidationError, rpc_interface.add_host,
50 hostname='host1')
51
52
showardcafd16e2009-05-29 18:37:49 +000053 def test_multiple_platforms(self):
54 platform2 = models.Label.objects.create(name='platform2', platform=True)
55 self.assertRaises(model_logic.ValidationError,
Prashanth Balasubramanian5949b4a2014-11-23 12:58:30 -080056 rpc_interface. label_add_hosts, id='platform2',
57 hosts=['host1', 'host2'])
showardcafd16e2009-05-29 18:37:49 +000058 self.assertRaises(model_logic.ValidationError,
MK Ryufbb002c2015-06-08 14:13:16 -070059 rpc_interface.host_add_labels,
60 id='host1', labels=['platform2'])
showardcafd16e2009-05-29 18:37:49 +000061 # make sure the platform didn't get added
62 platforms = rpc_interface.get_labels(
63 host__hostname__in=['host1', 'host2'], platform=True)
64 self.assertEquals(len(platforms), 1)
65 self.assertEquals(platforms[0]['name'], 'myplatform')
66
67
showarda5288b42009-07-28 20:06:08 +000068 def _check_hostnames(self, hosts, expected_hostnames):
69 self.assertEquals(set(host['hostname'] for host in hosts),
70 set(expected_hostnames))
71
72
73 def test_get_hosts(self):
74 hosts = rpc_interface.get_hosts()
75 self._check_hostnames(hosts, [host.hostname for host in self.hosts])
76
77 hosts = rpc_interface.get_hosts(hostname='host1')
78 self._check_hostnames(hosts, ['host1'])
showard7e67b432010-01-20 01:13:04 +000079 host = hosts[0]
80 self.assertEquals(sorted(host['labels']), ['label1', 'myplatform'])
81 self.assertEquals(host['platform'], 'myplatform')
82 self.assertEquals(host['atomic_group'], None)
83 self.assertEquals(host['acls'], ['my_acl'])
84 self.assertEquals(host['attributes'], {})
showarda5288b42009-07-28 20:06:08 +000085
86
87 def test_get_hosts_multiple_labels(self):
88 hosts = rpc_interface.get_hosts(
89 multiple_labels=['myplatform', 'label1'])
90 self._check_hostnames(hosts, ['host1'])
91
92
93 def test_get_hosts_exclude_only_if_needed(self):
94 self.hosts[0].labels.add(self.label3)
95
96 hosts = rpc_interface.get_hosts(hostname__in=['host1', 'host2'],
97 exclude_only_if_needed_labels=True)
98 self._check_hostnames(hosts, ['host2'])
99
100
showard87cc38f2009-08-20 23:37:04 +0000101 def test_get_hosts_exclude_atomic_group_hosts(self):
102 hosts = rpc_interface.get_hosts(
103 exclude_atomic_group_hosts=True,
104 hostname__in=['host4', 'host5', 'host6'])
105 self._check_hostnames(hosts, ['host4'])
106
107
108 def test_get_hosts_exclude_both(self):
109 self.hosts[0].labels.add(self.label3)
110
111 hosts = rpc_interface.get_hosts(
112 hostname__in=['host1', 'host2', 'host5'],
113 exclude_only_if_needed_labels=True,
114 exclude_atomic_group_hosts=True)
115 self._check_hostnames(hosts, ['host2'])
116
117
showardc1a98d12010-01-15 00:22:22 +0000118 def test_job_keyvals(self):
119 keyval_dict = {'mykey': 'myvalue'}
Allen Li352b86a2016-12-14 12:11:27 -0800120 job_id = rpc_interface.create_job(name='test',
121 priority=priorities.Priority.DEFAULT,
showardc1a98d12010-01-15 00:22:22 +0000122 control_file='foo',
Aviv Keshet3dd8beb2013-05-13 17:36:04 -0700123 control_type=CLIENT,
showardc1a98d12010-01-15 00:22:22 +0000124 hosts=['host1'],
125 keyvals=keyval_dict)
126 jobs = rpc_interface.get_jobs(id=job_id)
127 self.assertEquals(len(jobs), 1)
128 self.assertEquals(jobs[0]['keyvals'], keyval_dict)
129
130
Aviv Keshetcd1ff9b2013-03-01 14:55:19 -0800131 def test_test_retry(self):
Allen Li352b86a2016-12-14 12:11:27 -0800132 job_id = rpc_interface.create_job(name='flake',
133 priority=priorities.Priority.DEFAULT,
Aviv Keshetcd1ff9b2013-03-01 14:55:19 -0800134 control_file='foo',
Aviv Keshet3dd8beb2013-05-13 17:36:04 -0700135 control_type=CLIENT,
Aviv Keshetcd1ff9b2013-03-01 14:55:19 -0800136 hosts=['host1'],
137 test_retry=10)
138 jobs = rpc_interface.get_jobs(id=job_id)
139 self.assertEquals(len(jobs), 1)
140 self.assertEquals(jobs[0]['test_retry'], 10)
141
142
showardb6d16622009-05-26 19:35:29 +0000143 def test_get_jobs_summary(self):
showardc0ac3a72009-07-08 21:14:45 +0000144 job = self._create_job(hosts=xrange(1, 4))
showardb6d16622009-05-26 19:35:29 +0000145 entries = list(job.hostqueueentry_set.all())
146 entries[1].status = _hqe_status.FAILED
147 entries[1].save()
148 entries[2].status = _hqe_status.FAILED
149 entries[2].aborted = True
150 entries[2].save()
151
Jiaxi Luoaac54572014-06-04 13:57:02 -0700152 # Mock up tko_rpc_interface.get_status_counts.
153 self.god.stub_function_to_return(rpc_interface.tko_rpc_interface,
154 'get_status_counts',
155 None)
156
showardb6d16622009-05-26 19:35:29 +0000157 job_summaries = rpc_interface.get_jobs_summary(id=job.id)
158 self.assertEquals(len(job_summaries), 1)
159 summary = job_summaries[0]
160 self.assertEquals(summary['status_counts'], {'Queued': 1,
161 'Failed': 2})
162
163
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700164 def _check_job_ids(self, actual_job_dicts, expected_jobs):
165 self.assertEquals(
166 set(job_dict['id'] for job_dict in actual_job_dicts),
167 set(job.id for job in expected_jobs))
168
169
170 def test_get_jobs_status_filters(self):
showard6c65d252009-10-01 18:45:22 +0000171 HqeStatus = models.HostQueueEntry.Status
172 def create_two_host_job():
173 return self._create_job(hosts=[1, 2])
174 def set_hqe_statuses(job, first_status, second_status):
175 entries = job.hostqueueentry_set.all()
176 entries[0].update_object(status=first_status)
177 entries[1].update_object(status=second_status)
178
179 queued = create_two_host_job()
180
181 queued_and_running = create_two_host_job()
182 set_hqe_statuses(queued_and_running, HqeStatus.QUEUED,
183 HqeStatus.RUNNING)
184
185 running_and_complete = create_two_host_job()
186 set_hqe_statuses(running_and_complete, HqeStatus.RUNNING,
187 HqeStatus.COMPLETED)
188
189 complete = create_two_host_job()
190 set_hqe_statuses(complete, HqeStatus.COMPLETED, HqeStatus.COMPLETED)
191
192 started_but_inactive = create_two_host_job()
193 set_hqe_statuses(started_but_inactive, HqeStatus.QUEUED,
194 HqeStatus.COMPLETED)
195
196 parsing = create_two_host_job()
197 set_hqe_statuses(parsing, HqeStatus.PARSING, HqeStatus.PARSING)
198
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700199 self._check_job_ids(rpc_interface.get_jobs(not_yet_run=True), [queued])
200 self._check_job_ids(rpc_interface.get_jobs(running=True),
showard6c65d252009-10-01 18:45:22 +0000201 [queued_and_running, running_and_complete,
202 started_but_inactive, parsing])
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700203 self._check_job_ids(rpc_interface.get_jobs(finished=True), [complete])
204
205
206 def test_get_jobs_type_filters(self):
207 self.assertRaises(AssertionError, rpc_interface.get_jobs,
208 suite=True, sub=True)
209 self.assertRaises(AssertionError, rpc_interface.get_jobs,
210 suite=True, standalone=True)
211 self.assertRaises(AssertionError, rpc_interface.get_jobs,
212 standalone=True, sub=True)
213
214 parent_job = self._create_job(hosts=[1])
215 child_jobs = self._create_job(hosts=[1, 2],
216 parent_job_id=parent_job.id)
217 standalone_job = self._create_job(hosts=[1])
218
219 self._check_job_ids(rpc_interface.get_jobs(suite=True), [parent_job])
220 self._check_job_ids(rpc_interface.get_jobs(sub=True), [child_jobs])
221 self._check_job_ids(rpc_interface.get_jobs(standalone=True),
222 [standalone_job])
showard6c65d252009-10-01 18:45:22 +0000223
224
showarda5288b42009-07-28 20:06:08 +0000225 def _create_job_helper(self, **kwargs):
Allen Li352b86a2016-12-14 12:11:27 -0800226 return rpc_interface.create_job(name='test',
227 priority=priorities.Priority.DEFAULT,
MK Ryue301eb72015-06-25 12:51:02 -0700228 control_file='control file',
229 control_type=SERVER, **kwargs)
showarda5288b42009-07-28 20:06:08 +0000230
231
showard2924b0a2009-06-18 23:16:15 +0000232 def test_one_time_hosts(self):
showarda5288b42009-07-28 20:06:08 +0000233 job = self._create_job_helper(one_time_hosts=['testhost'])
showard2924b0a2009-06-18 23:16:15 +0000234 host = models.Host.objects.get(hostname='testhost')
235 self.assertEquals(host.invalid, True)
236 self.assertEquals(host.labels.count(), 0)
237 self.assertEquals(host.aclgroup_set.count(), 0)
238
239
showard09d80f92009-11-19 01:01:19 +0000240 def test_create_job_duplicate_hosts(self):
241 self.assertRaises(model_logic.ValidationError, self._create_job_helper,
242 hosts=[1, 1])
243
244
Alex Miller4a193692013-08-21 13:59:01 -0700245 def test_create_unrunnable_metahost_job(self):
246 self.assertRaises(error.NoEligibleHostException,
247 self._create_job_helper, meta_hosts=['unused'])
248
249
showarda9545c02009-12-18 22:44:26 +0000250 def test_create_hostless_job(self):
251 job_id = self._create_job_helper(hostless=True)
252 job = models.Job.objects.get(pk=job_id)
253 queue_entries = job.hostqueueentry_set.all()
254 self.assertEquals(len(queue_entries), 1)
255 self.assertEquals(queue_entries[0].host, None)
256 self.assertEquals(queue_entries[0].meta_host, None)
257 self.assertEquals(queue_entries[0].atomic_group, None)
258
259
showard1a5a4082009-07-28 20:01:37 +0000260 def _setup_special_tasks(self):
showardc0ac3a72009-07-08 21:14:45 +0000261 host = self.hosts[0]
262
263 job1 = self._create_job(hosts=[1])
264 job2 = self._create_job(hosts=[1])
265
266 entry1 = job1.hostqueueentry_set.all()[0]
267 entry1.update_object(started_on=datetime.datetime(2009, 1, 2),
showardd1195652009-12-08 22:21:02 +0000268 execution_subdir='host1')
showardc0ac3a72009-07-08 21:14:45 +0000269 entry2 = job2.hostqueueentry_set.all()[0]
270 entry2.update_object(started_on=datetime.datetime(2009, 1, 3),
showardd1195652009-12-08 22:21:02 +0000271 execution_subdir='host1')
showardc0ac3a72009-07-08 21:14:45 +0000272
showard1a5a4082009-07-28 20:01:37 +0000273 self.task1 = models.SpecialTask.objects.create(
showardc0ac3a72009-07-08 21:14:45 +0000274 host=host, task=models.SpecialTask.Task.VERIFY,
275 time_started=datetime.datetime(2009, 1, 1), # ran before job 1
jamesren76fcf192010-04-21 20:39:50 +0000276 is_complete=True, requested_by=models.User.current_user())
showard1a5a4082009-07-28 20:01:37 +0000277 self.task2 = models.SpecialTask.objects.create(
showardc0ac3a72009-07-08 21:14:45 +0000278 host=host, task=models.SpecialTask.Task.VERIFY,
279 queue_entry=entry2, # ran with job 2
jamesren76fcf192010-04-21 20:39:50 +0000280 is_active=True, requested_by=models.User.current_user())
showard1a5a4082009-07-28 20:01:37 +0000281 self.task3 = models.SpecialTask.objects.create(
jamesren76fcf192010-04-21 20:39:50 +0000282 host=host, task=models.SpecialTask.Task.VERIFY,
283 requested_by=models.User.current_user()) # not yet run
showardc0ac3a72009-07-08 21:14:45 +0000284
showard1a5a4082009-07-28 20:01:37 +0000285
286 def test_get_special_tasks(self):
287 self._setup_special_tasks()
288 tasks = rpc_interface.get_special_tasks(host__hostname='host1',
289 queue_entry__isnull=True)
290 self.assertEquals(len(tasks), 2)
291 self.assertEquals(tasks[0]['task'], models.SpecialTask.Task.VERIFY)
292 self.assertEquals(tasks[0]['is_active'], False)
293 self.assertEquals(tasks[0]['is_complete'], True)
294
295
296 def test_get_latest_special_task(self):
297 # a particular usage of get_special_tasks()
298 self._setup_special_tasks()
299 self.task2.time_started = datetime.datetime(2009, 1, 2)
300 self.task2.save()
301
302 tasks = rpc_interface.get_special_tasks(
303 host__hostname='host1', task=models.SpecialTask.Task.VERIFY,
304 time_started__isnull=False, sort_by=['-time_started'],
305 query_limit=1)
306 self.assertEquals(len(tasks), 1)
307 self.assertEquals(tasks[0]['id'], 2)
308
309
310 def _common_entry_check(self, entry_dict):
311 self.assertEquals(entry_dict['host']['hostname'], 'host1')
312 self.assertEquals(entry_dict['job']['id'], 2)
313
314
315 def test_get_host_queue_entries_and_special_tasks(self):
316 self._setup_special_tasks()
317
MK Ryu0c1a37d2015-04-30 12:00:55 -0700318 host = self.hosts[0].id
showardc0ac3a72009-07-08 21:14:45 +0000319 entries_and_tasks = (
Jiaxi Luo79ce6422014-06-13 17:08:09 -0700320 rpc_interface.get_host_queue_entries_and_special_tasks(host))
showardc0ac3a72009-07-08 21:14:45 +0000321
322 paths = [entry['execution_path'] for entry in entries_and_tasks]
323 self.assertEquals(paths, ['hosts/host1/3-verify',
showardfd8b89f2010-01-20 19:06:30 +0000324 '2-autotest_system/host1',
showardc0ac3a72009-07-08 21:14:45 +0000325 'hosts/host1/2-verify',
showardfd8b89f2010-01-20 19:06:30 +0000326 '1-autotest_system/host1',
showardc0ac3a72009-07-08 21:14:45 +0000327 'hosts/host1/1-verify'])
328
329 verify2 = entries_and_tasks[2]
330 self._common_entry_check(verify2)
331 self.assertEquals(verify2['type'], 'Verify')
332 self.assertEquals(verify2['status'], 'Running')
333 self.assertEquals(verify2['execution_path'], 'hosts/host1/2-verify')
334
335 entry2 = entries_and_tasks[1]
336 self._common_entry_check(entry2)
337 self.assertEquals(entry2['type'], 'Job')
338 self.assertEquals(entry2['status'], 'Queued')
339 self.assertEquals(entry2['started_on'], '2009-01-03 00:00:00')
340
341
showard8aa84fc2009-09-16 17:17:55 +0000342 def test_view_invalid_host(self):
343 # RPCs used by View Host page should work for invalid hosts
344 self._create_job_helper(hosts=[1])
Jiaxi Luo79ce6422014-06-13 17:08:09 -0700345 host = self.hosts[0]
346 host.delete()
showard8aa84fc2009-09-16 17:17:55 +0000347
348 self.assertEquals(1, rpc_interface.get_num_hosts(hostname='host1',
349 valid_only=False))
350 data = rpc_interface.get_hosts(hostname='host1', valid_only=False)
351 self.assertEquals(1, len(data))
352
353 self.assertEquals(1, rpc_interface.get_num_host_queue_entries(
354 host__hostname='host1'))
355 data = rpc_interface.get_host_queue_entries(host__hostname='host1')
356 self.assertEquals(1, len(data))
357
358 count = rpc_interface.get_num_host_queue_entries_and_special_tasks(
MK Ryu0c1a37d2015-04-30 12:00:55 -0700359 host=host.id)
showard8aa84fc2009-09-16 17:17:55 +0000360 self.assertEquals(1, count)
361 data = rpc_interface.get_host_queue_entries_and_special_tasks(
MK Ryu0c1a37d2015-04-30 12:00:55 -0700362 host=host.id)
showard8aa84fc2009-09-16 17:17:55 +0000363 self.assertEquals(1, len(data))
364
365
showard9bb960b2009-11-19 01:02:11 +0000366 def test_reverify_hosts(self):
mbligh4e545a52009-12-19 05:30:39 +0000367 hostname_list = rpc_interface.reverify_hosts(id__in=[1, 2])
368 self.assertEquals(hostname_list, ['host1', 'host2'])
showard9bb960b2009-11-19 01:02:11 +0000369 tasks = rpc_interface.get_special_tasks()
370 self.assertEquals(len(tasks), 2)
371 self.assertEquals(set(task['host']['id'] for task in tasks),
372 set([1, 2]))
373
374 task = tasks[0]
375 self.assertEquals(task['task'], models.SpecialTask.Task.VERIFY)
showardfd8b89f2010-01-20 19:06:30 +0000376 self.assertEquals(task['requested_by'], 'autotest_system')
showard9bb960b2009-11-19 01:02:11 +0000377
378
Simran Basi73dae552013-02-25 14:57:46 -0800379 def test_repair_hosts(self):
380 hostname_list = rpc_interface.repair_hosts(id__in=[1, 2])
381 self.assertEquals(hostname_list, ['host1', 'host2'])
382 tasks = rpc_interface.get_special_tasks()
383 self.assertEquals(len(tasks), 2)
384 self.assertEquals(set(task['host']['id'] for task in tasks),
385 set([1, 2]))
386
387 task = tasks[0]
388 self.assertEquals(task['task'], models.SpecialTask.Task.REPAIR)
389 self.assertEquals(task['requested_by'], 'autotest_system')
390
391
Shuqian Zhao54a5b672016-05-11 22:12:17 +0000392 def test_parameterized_job(self):
393 global_config.global_config.override_config_value(
394 'AUTOTEST_WEB', 'parameterized_jobs', 'True')
395
396 string_type = model_attributes.ParameterTypes.STRING
397
398 test = models.Test.objects.create(
399 name='test', test_type=control_data.CONTROL_TYPE.SERVER)
400 test_parameter = test.testparameter_set.create(name='key')
401 profiler = models.Profiler.objects.create(name='profiler')
402
403 kernels = ({'version': 'version', 'cmdline': 'cmdline'},)
404 profilers = ('profiler',)
405 profiler_parameters = {'profiler': {'key': ('value', string_type)}}
406 job_parameters = {'key': ('value', string_type)}
407
408 job_id = rpc_interface.create_parameterized_job(
409 name='job', priority=priorities.Priority.DEFAULT, test='test',
410 parameters=job_parameters, kernel=kernels, label='label1',
411 profilers=profilers, profiler_parameters=profiler_parameters,
412 profile_only=False, hosts=('host1',))
413 parameterized_job = models.Job.smart_get(job_id).parameterized_job
414
415 self.assertEqual(parameterized_job.test, test)
416 self.assertEqual(parameterized_job.label, self.labels[0])
417 self.assertEqual(parameterized_job.kernels.count(), 1)
418 self.assertEqual(parameterized_job.profilers.count(), 1)
419
420 kernel = models.Kernel.objects.get(**kernels[0])
421 self.assertEqual(parameterized_job.kernels.all()[0], kernel)
422 self.assertEqual(parameterized_job.profilers.all()[0], profiler)
423
424 parameterized_profiler = models.ParameterizedJobProfiler.objects.get(
425 parameterized_job=parameterized_job, profiler=profiler)
426 profiler_parameters_obj = (
427 models.ParameterizedJobProfilerParameter.objects.get(
428 parameterized_job_profiler=parameterized_profiler))
429 self.assertEqual(profiler_parameters_obj.parameter_name, 'key')
430 self.assertEqual(profiler_parameters_obj.parameter_value, 'value')
431 self.assertEqual(profiler_parameters_obj.parameter_type, string_type)
432
433 self.assertEqual(
434 parameterized_job.parameterizedjobparameter_set.count(), 1)
435 parameters_obj = (
436 parameterized_job.parameterizedjobparameter_set.all()[0])
437 self.assertEqual(parameters_obj.test_parameter, test_parameter)
438 self.assertEqual(parameters_obj.parameter_value, 'value')
439 self.assertEqual(parameters_obj.parameter_type, string_type)
440
441
Jakob Juelich50e91f72014-10-01 12:43:23 -0700442 def _modify_host_helper(self, on_shard=False, host_on_shard=False):
443 shard_hostname = 'shard1'
444 if on_shard:
445 global_config.global_config.override_config_value(
446 'SHARD', 'shard_hostname', shard_hostname)
447
448 host = models.Host.objects.all()[0]
449 if host_on_shard:
450 shard = models.Shard.objects.create(hostname=shard_hostname)
451 host.shard = shard
452 host.save()
453
454 self.assertFalse(host.locked)
455
456 self.god.stub_class_method(frontend.AFE, 'run')
457
458 if host_on_shard and not on_shard:
459 mock_afe = self.god.create_mock_class_obj(
MK Ryu9651ca52015-06-08 17:48:22 -0700460 frontend_wrappers.RetryingAFE, 'MockAFE')
461 self.god.stub_with(frontend_wrappers, 'RetryingAFE', mock_afe)
Jakob Juelich50e91f72014-10-01 12:43:23 -0700462
MK Ryu9651ca52015-06-08 17:48:22 -0700463 mock_afe2 = frontend_wrappers.RetryingAFE.expect_new(
MK Ryu0a9c82e2015-09-17 17:54:01 -0700464 server=shard_hostname, user=None)
MK Ryu33889612015-09-04 14:32:35 -0700465 mock_afe2.run.expect_call('modify_host_local', id=host.id,
MK Ryud53e1492015-12-15 12:09:03 -0800466 locked=True, lock_reason='_modify_host_helper lock',
467 lock_time=datetime.datetime(2015, 12, 15))
MK Ryu33889612015-09-04 14:32:35 -0700468 elif on_shard:
469 mock_afe = self.god.create_mock_class_obj(
470 frontend_wrappers.RetryingAFE, 'MockAFE')
471 self.god.stub_with(frontend_wrappers, 'RetryingAFE', mock_afe)
472
473 mock_afe2 = frontend_wrappers.RetryingAFE.expect_new(
Fang Deng0cb2a3b2015-12-10 17:59:00 -0800474 server=server_utils.get_global_afe_hostname(), user=None)
MK Ryu33889612015-09-04 14:32:35 -0700475 mock_afe2.run.expect_call('modify_host', id=host.id,
MK Ryud53e1492015-12-15 12:09:03 -0800476 locked=True, lock_reason='_modify_host_helper lock',
477 lock_time=datetime.datetime(2015, 12, 15))
Jakob Juelich50e91f72014-10-01 12:43:23 -0700478
Matthew Sartori68186332015-04-27 17:19:53 -0700479 rpc_interface.modify_host(id=host.id, locked=True,
MK Ryud53e1492015-12-15 12:09:03 -0800480 lock_reason='_modify_host_helper lock',
481 lock_time=datetime.datetime(2015, 12, 15))
Jakob Juelich50e91f72014-10-01 12:43:23 -0700482
483 host = models.Host.objects.get(pk=host.id)
MK Ryu33889612015-09-04 14:32:35 -0700484 if on_shard:
485 # modify_host on shard does nothing but routing the RPC to master.
486 self.assertFalse(host.locked)
487 else:
488 self.assertTrue(host.locked)
Jakob Juelich50e91f72014-10-01 12:43:23 -0700489 self.god.check_playback()
490
491
492 def test_modify_host_on_master_host_on_master(self):
MK Ryu33889612015-09-04 14:32:35 -0700493 """Call modify_host to master for host in master."""
Jakob Juelich50e91f72014-10-01 12:43:23 -0700494 self._modify_host_helper()
495
496
497 def test_modify_host_on_master_host_on_shard(self):
MK Ryu33889612015-09-04 14:32:35 -0700498 """Call modify_host to master for host in shard."""
Jakob Juelich50e91f72014-10-01 12:43:23 -0700499 self._modify_host_helper(host_on_shard=True)
500
501
502 def test_modify_host_on_shard(self):
MK Ryu33889612015-09-04 14:32:35 -0700503 """Call modify_host to shard for host in shard."""
Jakob Juelich50e91f72014-10-01 12:43:23 -0700504 self._modify_host_helper(on_shard=True, host_on_shard=True)
505
506
507 def test_modify_hosts_on_master_host_on_shard(self):
508 """Ensure calls to modify_hosts are correctly forwarded to shards."""
509 host1 = models.Host.objects.all()[0]
510 host2 = models.Host.objects.all()[1]
511
512 shard1 = models.Shard.objects.create(hostname='shard1')
513 host1.shard = shard1
514 host1.save()
515
516 shard2 = models.Shard.objects.create(hostname='shard2')
517 host2.shard = shard2
518 host2.save()
519
520 self.assertFalse(host1.locked)
521 self.assertFalse(host2.locked)
522
MK Ryu9651ca52015-06-08 17:48:22 -0700523 mock_afe = self.god.create_mock_class_obj(frontend_wrappers.RetryingAFE,
MK Ryu33889612015-09-04 14:32:35 -0700524 'MockAFE')
MK Ryu9651ca52015-06-08 17:48:22 -0700525 self.god.stub_with(frontend_wrappers, 'RetryingAFE', mock_afe)
Jakob Juelich50e91f72014-10-01 12:43:23 -0700526
527 # The statuses of one host might differ on master and shard.
528 # Filters are always applied on the master. So the host on the shard
529 # will be affected no matter what his status is.
530 filters_to_use = {'status': 'Ready'}
531
MK Ryu0a9c82e2015-09-17 17:54:01 -0700532 mock_afe2 = frontend_wrappers.RetryingAFE.expect_new(
533 server='shard2', user=None)
Jakob Juelich50e91f72014-10-01 12:43:23 -0700534 mock_afe2.run.expect_call(
MK Ryu33889612015-09-04 14:32:35 -0700535 'modify_hosts_local',
Jakob Juelich50e91f72014-10-01 12:43:23 -0700536 host_filter_data={'id__in': [shard1.id, shard2.id]},
Matthew Sartori68186332015-04-27 17:19:53 -0700537 update_data={'locked': True,
MK Ryud53e1492015-12-15 12:09:03 -0800538 'lock_reason': 'Testing forward to shard',
539 'lock_time' : datetime.datetime(2015, 12, 15) })
Jakob Juelich50e91f72014-10-01 12:43:23 -0700540
MK Ryu0a9c82e2015-09-17 17:54:01 -0700541 mock_afe1 = frontend_wrappers.RetryingAFE.expect_new(
542 server='shard1', user=None)
Jakob Juelich50e91f72014-10-01 12:43:23 -0700543 mock_afe1.run.expect_call(
MK Ryu33889612015-09-04 14:32:35 -0700544 'modify_hosts_local',
Jakob Juelich50e91f72014-10-01 12:43:23 -0700545 host_filter_data={'id__in': [shard1.id, shard2.id]},
Matthew Sartori68186332015-04-27 17:19:53 -0700546 update_data={'locked': True,
MK Ryud53e1492015-12-15 12:09:03 -0800547 'lock_reason': 'Testing forward to shard',
548 'lock_time' : datetime.datetime(2015, 12, 15)})
Jakob Juelich50e91f72014-10-01 12:43:23 -0700549
MK Ryud53e1492015-12-15 12:09:03 -0800550 rpc_interface.modify_hosts(
551 host_filter_data={'status': 'Ready'},
552 update_data={'locked': True,
553 'lock_reason': 'Testing forward to shard',
554 'lock_time' : datetime.datetime(2015, 12, 15) })
Jakob Juelich50e91f72014-10-01 12:43:23 -0700555
556 host1 = models.Host.objects.get(pk=host1.id)
557 self.assertTrue(host1.locked)
558 host2 = models.Host.objects.get(pk=host2.id)
559 self.assertTrue(host2.locked)
560 self.god.check_playback()
561
562
563 def test_delete_host(self):
564 """Ensure an RPC is made on delete a host, if it is on a shard."""
565 host1 = models.Host.objects.all()[0]
566 shard1 = models.Shard.objects.create(hostname='shard1')
567 host1.shard = shard1
568 host1.save()
569 host1_id = host1.id
570
MK Ryu9651ca52015-06-08 17:48:22 -0700571 mock_afe = self.god.create_mock_class_obj(frontend_wrappers.RetryingAFE,
Jakob Juelich50e91f72014-10-01 12:43:23 -0700572 'MockAFE')
MK Ryu9651ca52015-06-08 17:48:22 -0700573 self.god.stub_with(frontend_wrappers, 'RetryingAFE', mock_afe)
Jakob Juelich50e91f72014-10-01 12:43:23 -0700574
MK Ryu0a9c82e2015-09-17 17:54:01 -0700575 mock_afe1 = frontend_wrappers.RetryingAFE.expect_new(
576 server='shard1', user=None)
Jakob Juelich50e91f72014-10-01 12:43:23 -0700577 mock_afe1.run.expect_call('delete_host', id=host1.id)
578
579 rpc_interface.delete_host(id=host1.id)
580
581 self.assertRaises(models.Host.DoesNotExist,
582 models.Host.smart_get, host1_id)
583
584 self.god.check_playback()
585
586
MK Ryu8e2c2d02016-01-06 15:24:38 -0800587 def test_modify_label(self):
588 label1 = models.Label.objects.all()[0]
589 self.assertEqual(label1.invalid, 0)
590
591 host2 = models.Host.objects.all()[1]
592 shard1 = models.Shard.objects.create(hostname='shard1')
593 host2.shard = shard1
594 host2.labels.add(label1)
595 host2.save()
596
597 mock_afe = self.god.create_mock_class_obj(frontend_wrappers.RetryingAFE,
598 'MockAFE')
599 self.god.stub_with(frontend_wrappers, 'RetryingAFE', mock_afe)
600
601 mock_afe1 = frontend_wrappers.RetryingAFE.expect_new(
602 server='shard1', user=None)
603 mock_afe1.run.expect_call('modify_label', id=label1.id, invalid=1)
604
605 rpc_interface.modify_label(label1.id, invalid=1)
606
607 self.assertEqual(models.Label.objects.all()[0].invalid, 1)
608 self.god.check_playback()
609
610
611 def test_delete_label(self):
612 label1 = models.Label.objects.all()[0]
613
614 host2 = models.Host.objects.all()[1]
615 shard1 = models.Shard.objects.create(hostname='shard1')
616 host2.shard = shard1
617 host2.labels.add(label1)
618 host2.save()
619
620 mock_afe = self.god.create_mock_class_obj(frontend_wrappers.RetryingAFE,
621 'MockAFE')
622 self.god.stub_with(frontend_wrappers, 'RetryingAFE', mock_afe)
623
624 mock_afe1 = frontend_wrappers.RetryingAFE.expect_new(
625 server='shard1', user=None)
626 mock_afe1.run.expect_call('delete_label', id=label1.id)
627
628 rpc_interface.delete_label(id=label1.id)
629
630 self.assertRaises(models.Label.DoesNotExist,
631 models.Label.smart_get, label1.id)
632 self.god.check_playback()
633
634
Michael Tang6dc174e2016-05-31 23:13:42 -0700635 def test_get_image_for_job_parameterized(self):
636 test = models.Test.objects.create(
637 name='name', author='author', test_class='class',
638 test_category='category',
639 test_type=control_data.CONTROL_TYPE.SERVER, path='path')
640 parameterized_job = models.ParameterizedJob.objects.create(test=test)
641 job = self._create_job(hosts=[1])
642 job.parameterized_job = parameterized_job
643 self.god.stub_function_to_return(rpc_interface,
644 'get_parameterized_autoupdate_image_url', 'cool-image')
645 image = rpc_interface._get_image_for_job(job, True)
646 self.assertEquals('cool-image', image)
647 self.god.check_playback()
648
649
650 def test_get_image_for_job_with_keyval_build(self):
651 keyval_dict = {'build': 'cool-image'}
Allen Li352b86a2016-12-14 12:11:27 -0800652 job_id = rpc_interface.create_job(name='test',
653 priority=priorities.Priority.DEFAULT,
Michael Tang6dc174e2016-05-31 23:13:42 -0700654 control_file='foo',
655 control_type=CLIENT,
656 hosts=['host1'],
657 keyvals=keyval_dict)
658 job = models.Job.objects.get(id=job_id)
659 self.assertIsNotNone(job)
660 image = rpc_interface._get_image_for_job(job, True)
661 self.assertEquals('cool-image', image)
662
663
664 def test_get_image_for_job_with_keyval_builds(self):
665 keyval_dict = {'builds': {'cros-version': 'cool-image'}}
Allen Li352b86a2016-12-14 12:11:27 -0800666 job_id = rpc_interface.create_job(name='test',
667 priority=priorities.Priority.DEFAULT,
Michael Tang6dc174e2016-05-31 23:13:42 -0700668 control_file='foo',
669 control_type=CLIENT,
670 hosts=['host1'],
671 keyvals=keyval_dict)
672 job = models.Job.objects.get(id=job_id)
673 self.assertIsNotNone(job)
674 image = rpc_interface._get_image_for_job(job, True)
675 self.assertEquals('cool-image', image)
676
677
678 def test_get_image_for_job_with_control_build(self):
679 CONTROL_FILE = """build='cool-image'
680 """
Allen Li352b86a2016-12-14 12:11:27 -0800681 job_id = rpc_interface.create_job(name='test',
682 priority=priorities.Priority.DEFAULT,
Michael Tang6dc174e2016-05-31 23:13:42 -0700683 control_file='foo',
684 control_type=CLIENT,
685 hosts=['host1'])
686 job = models.Job.objects.get(id=job_id)
687 self.assertIsNotNone(job)
688 job.control_file = CONTROL_FILE
689 image = rpc_interface._get_image_for_job(job, True)
690 self.assertEquals('cool-image', image)
691
692
693 def test_get_image_for_job_with_control_builds(self):
694 CONTROL_FILE = """builds={'cros-version': 'cool-image'}
695 """
Allen Li352b86a2016-12-14 12:11:27 -0800696 job_id = rpc_interface.create_job(name='test',
697 priority=priorities.Priority.DEFAULT,
Michael Tang6dc174e2016-05-31 23:13:42 -0700698 control_file='foo',
699 control_type=CLIENT,
700 hosts=['host1'])
701 job = models.Job.objects.get(id=job_id)
702 self.assertIsNotNone(job)
703 job.control_file = CONTROL_FILE
704 image = rpc_interface._get_image_for_job(job, True)
705 self.assertEquals('cool-image', image)
706
707
showardb6d16622009-05-26 19:35:29 +0000708if __name__ == '__main__':
709 unittest.main()