blob: 84c5faee035b597105fd5d69091fdca1591edd6d [file] [log] [blame]
Aviv Keshet0b9cfc92013-02-05 11:36:02 -08001# pylint: disable-msg=C0111
2
mblighe8819cd2008-02-15 16:48:40 +00003"""\
4Functions to expose over the RPC interface.
5
6For all modify* and delete* functions that ask for an 'id' parameter to
7identify the object to operate on, the id may be either
8 * the database row ID
9 * the name of the object (label name, hostname, user login, etc.)
10 * a dictionary containing uniquely identifying field (this option should seldom
11 be used)
12
13When specifying foreign key fields (i.e. adding hosts to a label, or adding
14users to an ACL group), the given value may be either the database row ID or the
15name of the object.
16
17All get* functions return lists of dictionaries. Each dictionary represents one
18object and maps field names to values.
19
20Some examples:
21modify_host(2, hostname='myhost') # modify hostname of host with database ID 2
22modify_host('ipaj2', hostname='myhost') # modify hostname of host 'ipaj2'
23modify_test('sleeptest', test_type='Client', params=', seconds=60')
24delete_acl_group(1) # delete by ID
25delete_acl_group('Everyone') # delete by name
26acl_group_add_users('Everyone', ['mbligh', 'showard'])
27get_jobs(owner='showard', status='Queued')
28
mbligh93c80e62009-02-03 17:48:30 +000029See doctests/001_rpc_test.txt for (lots) more examples.
mblighe8819cd2008-02-15 16:48:40 +000030"""
31
32__author__ = 'showard@google.com (Steve Howard)'
33
showard29f7cd22009-04-29 21:16:24 +000034import datetime
showardcafd16e2009-05-29 18:37:49 +000035import common
Simran Basib6ec8ae2014-04-23 12:05:08 -070036from autotest_lib.client.common_lib import priorities
jamesrendd855242010-03-02 22:23:44 +000037from autotest_lib.frontend.afe import models, model_logic, model_attributes
showard6d7b2ff2009-06-10 00:16:47 +000038from autotest_lib.frontend.afe import control_file, rpc_utils
Simran Basib6ec8ae2014-04-23 12:05:08 -070039from autotest_lib.frontend.afe import site_rpc_interface
mblighe8819cd2008-02-15 16:48:40 +000040
Eric Lid23bc192011-02-09 14:38:57 -080041def get_parameterized_autoupdate_image_url(job):
42 """Get the parameterized autoupdate image url from a parameterized job."""
43 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
44 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
beeps8bb1f7d2013-08-05 01:30:09 -070045 name='image')
Eric Lid23bc192011-02-09 14:38:57 -080046 para_set = job.parameterized_job.parameterizedjobparameter_set
47 job_test_para = para_set.get(test_parameter=image_parameter)
48 return job_test_para.parameter_value
49
50
mblighe8819cd2008-02-15 16:48:40 +000051# labels
52
showard989f25d2008-10-01 11:38:11 +000053def add_label(name, kernel_config=None, platform=None, only_if_needed=None):
showardc92da832009-04-07 18:14:34 +000054 return models.Label.add_object(
55 name=name, kernel_config=kernel_config, platform=platform,
56 only_if_needed=only_if_needed).id
mblighe8819cd2008-02-15 16:48:40 +000057
58
59def modify_label(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +000060 models.Label.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +000061
62
63def delete_label(id):
jadmanski0afbb632008-06-06 21:10:57 +000064 models.Label.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +000065
66
showardbbabf502008-06-06 00:02:02 +000067def label_add_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000068 host_objs = models.Host.smart_get_bulk(hosts)
showardcafd16e2009-05-29 18:37:49 +000069 label = models.Label.smart_get(id)
70 if label.platform:
71 models.Host.check_no_platform(host_objs)
72 label.host_set.add(*host_objs)
showardbbabf502008-06-06 00:02:02 +000073
74
75def label_remove_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000076 host_objs = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +000077 models.Label.smart_get(id).host_set.remove(*host_objs)
showardbbabf502008-06-06 00:02:02 +000078
79
Jiaxi Luo31874592014-06-11 10:36:35 -070080def get_labels(exclude_filters=(), **filter_data):
showardc92da832009-04-07 18:14:34 +000081 """\
Jiaxi Luo31874592014-06-11 10:36:35 -070082 @param exclude_filters: A sequence of dictionaries of filters.
83
showardc92da832009-04-07 18:14:34 +000084 @returns A sequence of nested dictionaries of label information.
85 """
Jiaxi Luo31874592014-06-11 10:36:35 -070086 labels = models.Label.query_objects(filter_data)
87 for exclude_filter in exclude_filters:
88 labels = labels.exclude(**exclude_filter)
89 return rpc_utils.prepare_rows_as_nested_dicts(labels, ('atomic_group',))
showardc92da832009-04-07 18:14:34 +000090
91
92# atomic groups
93
showarde9450c92009-06-30 01:58:52 +000094def add_atomic_group(name, max_number_of_machines=None, description=None):
showardc92da832009-04-07 18:14:34 +000095 return models.AtomicGroup.add_object(
96 name=name, max_number_of_machines=max_number_of_machines,
97 description=description).id
98
99
100def modify_atomic_group(id, **data):
101 models.AtomicGroup.smart_get(id).update_object(data)
102
103
104def delete_atomic_group(id):
105 models.AtomicGroup.smart_get(id).delete()
106
107
108def atomic_group_add_labels(id, labels):
109 label_objs = models.Label.smart_get_bulk(labels)
110 models.AtomicGroup.smart_get(id).label_set.add(*label_objs)
111
112
113def atomic_group_remove_labels(id, labels):
114 label_objs = models.Label.smart_get_bulk(labels)
115 models.AtomicGroup.smart_get(id).label_set.remove(*label_objs)
116
117
118def get_atomic_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000119 return rpc_utils.prepare_for_serialization(
showardc92da832009-04-07 18:14:34 +0000120 models.AtomicGroup.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000121
122
123# hosts
124
showarddf062562008-07-03 19:56:37 +0000125def add_host(hostname, status=None, locked=None, protection=None):
jadmanski0afbb632008-06-06 21:10:57 +0000126 return models.Host.add_object(hostname=hostname, status=status,
showarddf062562008-07-03 19:56:37 +0000127 locked=locked, protection=protection).id
mblighe8819cd2008-02-15 16:48:40 +0000128
129
130def modify_host(id, **data):
showardbe0d8692009-08-20 23:42:44 +0000131 rpc_utils.check_modify_host(data)
showardce7c0922009-09-11 18:39:24 +0000132 host = models.Host.smart_get(id)
133 rpc_utils.check_modify_host_locking(host, data)
134 host.update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000135
136
showard276f9442009-05-20 00:33:16 +0000137def modify_hosts(host_filter_data, update_data):
138 """
showardbe0d8692009-08-20 23:42:44 +0000139 @param host_filter_data: Filters out which hosts to modify.
140 @param update_data: A dictionary with the changes to make to the hosts.
showard276f9442009-05-20 00:33:16 +0000141 """
showardbe0d8692009-08-20 23:42:44 +0000142 rpc_utils.check_modify_host(update_data)
showard276f9442009-05-20 00:33:16 +0000143 hosts = models.Host.query_objects(host_filter_data)
Alex Miller9658a952013-05-14 16:40:02 -0700144 # Check all hosts before changing data for exception safety.
145 for host in hosts:
146 rpc_utils.check_modify_host_locking(host, update_data)
showard276f9442009-05-20 00:33:16 +0000147 for host in hosts:
148 host.update_object(update_data)
149
150
mblighe8819cd2008-02-15 16:48:40 +0000151def host_add_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000152 labels = models.Label.smart_get_bulk(labels)
showardcafd16e2009-05-29 18:37:49 +0000153 host = models.Host.smart_get(id)
154
155 platforms = [label.name for label in labels if label.platform]
156 if len(platforms) > 1:
157 raise model_logic.ValidationError(
158 {'labels': 'Adding more than one platform label: %s' %
159 ', '.join(platforms)})
160 if len(platforms) == 1:
161 models.Host.check_no_platform([host])
162 host.labels.add(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000163
164
165def host_remove_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000166 labels = models.Label.smart_get_bulk(labels)
jadmanski0afbb632008-06-06 21:10:57 +0000167 models.Host.smart_get(id).labels.remove(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000168
169
showard0957a842009-05-11 19:25:08 +0000170def set_host_attribute(attribute, value, **host_filter_data):
171 """
172 @param attribute string name of attribute
173 @param value string, or None to delete an attribute
174 @param host_filter_data filter data to apply to Hosts to choose hosts to act
175 upon
176 """
177 assert host_filter_data # disallow accidental actions on all hosts
178 hosts = models.Host.query_objects(host_filter_data)
179 models.AclGroup.check_for_acl_violation_hosts(hosts)
180
181 for host in hosts:
showardf8b19042009-05-12 17:22:49 +0000182 host.set_or_delete_attribute(attribute, value)
showard0957a842009-05-11 19:25:08 +0000183
184
mblighe8819cd2008-02-15 16:48:40 +0000185def delete_host(id):
jadmanski0afbb632008-06-06 21:10:57 +0000186 models.Host.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000187
188
showard87cc38f2009-08-20 23:37:04 +0000189def get_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000190 exclude_atomic_group_hosts=False, valid_only=True, **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000191 """
192 @param multiple_labels: match hosts in all of the labels given. Should
193 be a list of label names.
194 @param exclude_only_if_needed_labels: Exclude hosts with at least one
195 "only_if_needed" label applied.
196 @param exclude_atomic_group_hosts: Exclude hosts that have one or more
197 atomic group labels associated with them.
jadmanski0afbb632008-06-06 21:10:57 +0000198 """
showard43a3d262008-11-12 18:17:05 +0000199 hosts = rpc_utils.get_host_query(multiple_labels,
200 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000201 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000202 valid_only, filter_data)
showard0957a842009-05-11 19:25:08 +0000203 hosts = list(hosts)
204 models.Host.objects.populate_relationships(hosts, models.Label,
205 'label_list')
206 models.Host.objects.populate_relationships(hosts, models.AclGroup,
207 'acl_list')
208 models.Host.objects.populate_relationships(hosts, models.HostAttribute,
209 'attribute_list')
showard43a3d262008-11-12 18:17:05 +0000210 host_dicts = []
211 for host_obj in hosts:
212 host_dict = host_obj.get_object_dict()
showard0957a842009-05-11 19:25:08 +0000213 host_dict['labels'] = [label.name for label in host_obj.label_list]
showard909c9142009-07-07 20:54:42 +0000214 host_dict['platform'], host_dict['atomic_group'] = (rpc_utils.
215 find_platform_and_atomic_group(host_obj))
showard0957a842009-05-11 19:25:08 +0000216 host_dict['acls'] = [acl.name for acl in host_obj.acl_list]
217 host_dict['attributes'] = dict((attribute.attribute, attribute.value)
218 for attribute in host_obj.attribute_list)
showard43a3d262008-11-12 18:17:05 +0000219 host_dicts.append(host_dict)
220 return rpc_utils.prepare_for_serialization(host_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000221
222
showard87cc38f2009-08-20 23:37:04 +0000223def get_num_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000224 exclude_atomic_group_hosts=False, valid_only=True,
225 **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000226 """
227 Same parameters as get_hosts().
228
229 @returns The number of matching hosts.
230 """
showard43a3d262008-11-12 18:17:05 +0000231 hosts = rpc_utils.get_host_query(multiple_labels,
232 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000233 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000234 valid_only, filter_data)
showard43a3d262008-11-12 18:17:05 +0000235 return hosts.count()
showard1385b162008-03-13 15:59:40 +0000236
mblighe8819cd2008-02-15 16:48:40 +0000237
238# tests
239
showard909c7a62008-07-15 21:52:38 +0000240def add_test(name, test_type, path, author=None, dependencies=None,
showard3d9899a2008-07-31 02:11:58 +0000241 experimental=True, run_verify=None, test_class=None,
showard909c7a62008-07-15 21:52:38 +0000242 test_time=None, test_category=None, description=None,
243 sync_count=1):
jadmanski0afbb632008-06-06 21:10:57 +0000244 return models.Test.add_object(name=name, test_type=test_type, path=path,
showard909c7a62008-07-15 21:52:38 +0000245 author=author, dependencies=dependencies,
246 experimental=experimental,
247 run_verify=run_verify, test_time=test_time,
248 test_category=test_category,
249 sync_count=sync_count,
jadmanski0afbb632008-06-06 21:10:57 +0000250 test_class=test_class,
251 description=description).id
mblighe8819cd2008-02-15 16:48:40 +0000252
253
254def modify_test(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000255 models.Test.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000256
257
258def delete_test(id):
jadmanski0afbb632008-06-06 21:10:57 +0000259 models.Test.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000260
261
262def get_tests(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000263 return rpc_utils.prepare_for_serialization(
264 models.Test.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000265
266
showard2b9a88b2008-06-13 20:55:03 +0000267# profilers
268
269def add_profiler(name, description=None):
270 return models.Profiler.add_object(name=name, description=description).id
271
272
273def modify_profiler(id, **data):
274 models.Profiler.smart_get(id).update_object(data)
275
276
277def delete_profiler(id):
278 models.Profiler.smart_get(id).delete()
279
280
281def get_profilers(**filter_data):
282 return rpc_utils.prepare_for_serialization(
283 models.Profiler.list_objects(filter_data))
284
285
mblighe8819cd2008-02-15 16:48:40 +0000286# users
287
288def add_user(login, access_level=None):
jadmanski0afbb632008-06-06 21:10:57 +0000289 return models.User.add_object(login=login, access_level=access_level).id
mblighe8819cd2008-02-15 16:48:40 +0000290
291
292def modify_user(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000293 models.User.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000294
295
296def delete_user(id):
jadmanski0afbb632008-06-06 21:10:57 +0000297 models.User.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000298
299
300def get_users(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000301 return rpc_utils.prepare_for_serialization(
302 models.User.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000303
304
305# acl groups
306
307def add_acl_group(name, description=None):
showard04f2cd82008-07-25 20:53:31 +0000308 group = models.AclGroup.add_object(name=name, description=description)
showard64a95952010-01-13 21:27:16 +0000309 group.users.add(models.User.current_user())
showard04f2cd82008-07-25 20:53:31 +0000310 return group.id
mblighe8819cd2008-02-15 16:48:40 +0000311
312
313def modify_acl_group(id, **data):
showard04f2cd82008-07-25 20:53:31 +0000314 group = models.AclGroup.smart_get(id)
315 group.check_for_acl_violation_acl_group()
316 group.update_object(data)
317 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000318
319
320def acl_group_add_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000321 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000322 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000323 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000324 group.users.add(*users)
mblighe8819cd2008-02-15 16:48:40 +0000325
326
327def acl_group_remove_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000328 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000329 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000330 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000331 group.users.remove(*users)
showard04f2cd82008-07-25 20:53:31 +0000332 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000333
334
335def acl_group_add_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000336 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000337 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000338 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000339 group.hosts.add(*hosts)
showard08f981b2008-06-24 21:59:03 +0000340 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000341
342
343def acl_group_remove_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000344 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000345 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000346 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000347 group.hosts.remove(*hosts)
showard08f981b2008-06-24 21:59:03 +0000348 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000349
350
351def delete_acl_group(id):
jadmanski0afbb632008-06-06 21:10:57 +0000352 models.AclGroup.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000353
354
355def get_acl_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000356 acl_groups = models.AclGroup.list_objects(filter_data)
357 for acl_group in acl_groups:
358 acl_group_obj = models.AclGroup.objects.get(id=acl_group['id'])
359 acl_group['users'] = [user.login
360 for user in acl_group_obj.users.all()]
361 acl_group['hosts'] = [host.hostname
362 for host in acl_group_obj.hosts.all()]
363 return rpc_utils.prepare_for_serialization(acl_groups)
mblighe8819cd2008-02-15 16:48:40 +0000364
365
366# jobs
367
mbligh120351e2009-01-24 01:40:45 +0000368def generate_control_file(tests=(), kernel=None, label=None, profilers=(),
showard91f85102009-10-12 20:34:52 +0000369 client_control_file='', use_container=False,
showard232b7ae2009-11-10 00:46:48 +0000370 profile_only=None, upload_kernel_config=False):
jadmanski0afbb632008-06-06 21:10:57 +0000371 """
mbligh120351e2009-01-24 01:40:45 +0000372 Generates a client-side control file to load a kernel and run tests.
373
374 @param tests List of tests to run.
mbligha3c58d22009-08-24 22:01:51 +0000375 @param kernel A list of kernel info dictionaries configuring which kernels
376 to boot for this job and other options for them
mbligh120351e2009-01-24 01:40:45 +0000377 @param label Name of label to grab kernel config from.
378 @param profilers List of profilers to activate during the job.
379 @param client_control_file The contents of a client-side control file to
380 run at the end of all tests. If this is supplied, all tests must be
381 client side.
382 TODO: in the future we should support server control files directly
383 to wrap with a kernel. That'll require changing the parameter
384 name and adding a boolean to indicate if it is a client or server
385 control file.
386 @param use_container unused argument today. TODO: Enable containers
387 on the host during a client side test.
showard91f85102009-10-12 20:34:52 +0000388 @param profile_only A boolean that indicates what default profile_only
389 mode to use in the control file. Passing None will generate a
390 control file that does not explcitly set the default mode at all.
showard232b7ae2009-11-10 00:46:48 +0000391 @param upload_kernel_config: if enabled it will generate server control
392 file code that uploads the kernel config file to the client and
393 tells the client of the new (local) path when compiling the kernel;
394 the tests must be server side tests
mbligh120351e2009-01-24 01:40:45 +0000395
396 @returns a dict with the following keys:
397 control_file: str, The control file text.
398 is_server: bool, is the control file a server-side control file?
399 synch_count: How many machines the job uses per autoserv execution.
400 synch_count == 1 means the job is asynchronous.
401 dependencies: A list of the names of labels on which the job depends.
402 """
showardd86debe2009-06-10 17:37:56 +0000403 if not tests and not client_control_file:
showard2bab8f42008-11-12 18:15:22 +0000404 return dict(control_file='', is_server=False, synch_count=1,
showard989f25d2008-10-01 11:38:11 +0000405 dependencies=[])
mblighe8819cd2008-02-15 16:48:40 +0000406
showard989f25d2008-10-01 11:38:11 +0000407 cf_info, test_objects, profiler_objects, label = (
showard2b9a88b2008-06-13 20:55:03 +0000408 rpc_utils.prepare_generate_control_file(tests, kernel, label,
409 profilers))
showard989f25d2008-10-01 11:38:11 +0000410 cf_info['control_file'] = control_file.generate_control(
mbligha3c58d22009-08-24 22:01:51 +0000411 tests=test_objects, kernels=kernel, platform=label,
mbligh120351e2009-01-24 01:40:45 +0000412 profilers=profiler_objects, is_server=cf_info['is_server'],
showard232b7ae2009-11-10 00:46:48 +0000413 client_control_file=client_control_file, profile_only=profile_only,
414 upload_kernel_config=upload_kernel_config)
showard989f25d2008-10-01 11:38:11 +0000415 return cf_info
mblighe8819cd2008-02-15 16:48:40 +0000416
417
jamesren4a41e012010-07-16 22:33:48 +0000418def create_parameterized_job(name, priority, test, parameters, kernel=None,
419 label=None, profilers=(), profiler_parameters=None,
420 use_container=False, profile_only=None,
421 upload_kernel_config=False, hosts=(),
422 meta_hosts=(), one_time_hosts=(),
423 atomic_group_name=None, synch_count=None,
424 is_template=False, timeout=None,
Simran Basi7e605742013-11-12 13:43:36 -0800425 timeout_mins=None, max_runtime_mins=None,
426 run_verify=False, email_list='', dependencies=(),
427 reboot_before=None, reboot_after=None,
428 parse_failed_repair=None, hostless=False,
429 keyvals=None, drone_set=None, run_reset=True):
jamesren4a41e012010-07-16 22:33:48 +0000430 """
431 Creates and enqueues a parameterized job.
432
433 Most parameters a combination of the parameters for generate_control_file()
434 and create_job(), with the exception of:
435
436 @param test name or ID of the test to run
437 @param parameters a map of parameter name ->
438 tuple of (param value, param type)
439 @param profiler_parameters a dictionary of parameters for the profilers:
440 key: profiler name
441 value: dict of param name -> tuple of
442 (param value,
443 param type)
444 """
445 # Save the values of the passed arguments here. What we're going to do with
446 # them is pass them all to rpc_utils.get_create_job_common_args(), which
447 # will extract the subset of these arguments that apply for
448 # rpc_utils.create_job_common(), which we then pass in to that function.
449 args = locals()
450
451 # Set up the parameterized job configs
452 test_obj = models.Test.smart_get(test)
Aviv Keshet3dd8beb2013-05-13 17:36:04 -0700453 control_type = test_obj.test_type
jamesren4a41e012010-07-16 22:33:48 +0000454
455 try:
456 label = models.Label.smart_get(label)
457 except models.Label.DoesNotExist:
458 label = None
459
460 kernel_objs = models.Kernel.create_kernels(kernel)
461 profiler_objs = [models.Profiler.smart_get(profiler)
462 for profiler in profilers]
463
464 parameterized_job = models.ParameterizedJob.objects.create(
465 test=test_obj, label=label, use_container=use_container,
466 profile_only=profile_only,
467 upload_kernel_config=upload_kernel_config)
468 parameterized_job.kernels.add(*kernel_objs)
469
470 for profiler in profiler_objs:
471 parameterized_profiler = models.ParameterizedJobProfiler.objects.create(
472 parameterized_job=parameterized_job,
473 profiler=profiler)
474 profiler_params = profiler_parameters.get(profiler.name, {})
475 for name, (value, param_type) in profiler_params.iteritems():
476 models.ParameterizedJobProfilerParameter.objects.create(
477 parameterized_job_profiler=parameterized_profiler,
478 parameter_name=name,
479 parameter_value=value,
480 parameter_type=param_type)
481
482 try:
483 for parameter in test_obj.testparameter_set.all():
484 if parameter.name in parameters:
485 param_value, param_type = parameters.pop(parameter.name)
486 parameterized_job.parameterizedjobparameter_set.create(
487 test_parameter=parameter, parameter_value=param_value,
488 parameter_type=param_type)
489
490 if parameters:
491 raise Exception('Extra parameters remain: %r' % parameters)
492
493 return rpc_utils.create_job_common(
494 parameterized_job=parameterized_job.id,
495 control_type=control_type,
496 **rpc_utils.get_create_job_common_args(args))
497 except:
498 parameterized_job.delete()
499 raise
500
501
Simran Basib6ec8ae2014-04-23 12:05:08 -0700502def create_job_page_handler(name, priority, control_file, control_type,
503 image=None, hostless=False, **kwargs):
504 """\
505 Create and enqueue a job.
506
507 @param name name of this job
508 @param priority Integer priority of this job. Higher is more important.
509 @param control_file String contents of the control file.
510 @param control_type Type of control file, Client or Server.
511 @param kwargs extra args that will be required by create_suite_job or
512 create_job.
513
514 @returns The created Job id number.
515 """
516 control_file = rpc_utils.encode_ascii(control_file)
517
518 if image and hostless:
519 return site_rpc_interface.create_suite_job(
520 name=name, control_file=control_file, priority=priority,
521 build=image, **kwargs)
522 return create_job(name, priority, control_file, control_type, image=image,
523 hostless=hostless, **kwargs)
524
525
showard12f3e322009-05-13 21:27:42 +0000526def create_job(name, priority, control_file, control_type,
527 hosts=(), meta_hosts=(), one_time_hosts=(),
528 atomic_group_name=None, synch_count=None, is_template=False,
Simran Basi7e605742013-11-12 13:43:36 -0800529 timeout=None, timeout_mins=None, max_runtime_mins=None,
530 run_verify=False, email_list='', dependencies=(),
531 reboot_before=None, reboot_after=None, parse_failed_repair=None,
532 hostless=False, keyvals=None, drone_set=None, image=None,
Simran Basib6ec8ae2014-04-23 12:05:08 -0700533 parent_job_id=None, test_retry=0, run_reset=True, **kwargs):
jadmanski0afbb632008-06-06 21:10:57 +0000534 """\
535 Create and enqueue a job.
mblighe8819cd2008-02-15 16:48:40 +0000536
showarda1e74b32009-05-12 17:32:04 +0000537 @param name name of this job
Alex Miller7d658cf2013-09-04 16:00:35 -0700538 @param priority Integer priority of this job. Higher is more important.
showarda1e74b32009-05-12 17:32:04 +0000539 @param control_file String contents of the control file.
540 @param control_type Type of control file, Client or Server.
541 @param synch_count How many machines the job uses per autoserv execution.
542 synch_count == 1 means the job is asynchronous. If an atomic group is
543 given this value is treated as a minimum.
544 @param is_template If true then create a template job.
545 @param timeout Hours after this call returns until the job times out.
Simran Basi7e605742013-11-12 13:43:36 -0800546 @param timeout_mins Minutes after this call returns until the job times
547 out.
Simran Basi34217022012-11-06 13:43:15 -0800548 @param max_runtime_mins Minutes from job starting time until job times out
showarda1e74b32009-05-12 17:32:04 +0000549 @param run_verify Should the host be verified before running the test?
550 @param email_list String containing emails to mail when the job is done
551 @param dependencies List of label names on which this job depends
552 @param reboot_before Never, If dirty, or Always
553 @param reboot_after Never, If all tests passed, or Always
554 @param parse_failed_repair if true, results of failed repairs launched by
555 this job will be parsed as part of the job.
showarda9545c02009-12-18 22:44:26 +0000556 @param hostless if true, create a hostless job
showardc1a98d12010-01-15 00:22:22 +0000557 @param keyvals dict of keyvals to associate with the job
showarda1e74b32009-05-12 17:32:04 +0000558 @param hosts List of hosts to run job on.
559 @param meta_hosts List where each entry is a label name, and for each entry
560 one host will be chosen from that label to run the job on.
561 @param one_time_hosts List of hosts not in the database to run the job on.
562 @param atomic_group_name The name of an atomic group to schedule the job on.
jamesren76fcf192010-04-21 20:39:50 +0000563 @param drone_set The name of the drone set to run this test on.
Paul Pendlebury5a8c6ad2011-02-01 07:20:17 -0800564 @param image OS image to install before running job.
Aviv Keshet0b9cfc92013-02-05 11:36:02 -0800565 @param parent_job_id id of a job considered to be parent of created job.
Simran Basib6ec8ae2014-04-23 12:05:08 -0700566 @param test_retry Number of times to retry test if the test did not
Aviv Keshetcd1ff9b2013-03-01 14:55:19 -0800567 complete successfully. (optional, default: 0)
Simran Basib6ec8ae2014-04-23 12:05:08 -0700568 @param run_reset Should the host be reset before running the test?
569 @param kwargs extra keyword args. NOT USED.
showardc92da832009-04-07 18:14:34 +0000570
571 @returns The created Job id number.
jadmanski0afbb632008-06-06 21:10:57 +0000572 """
Simran Basiab5a1bf2014-05-28 15:39:44 -0700573 if image is None:
574 return rpc_utils.create_job_common(
575 **rpc_utils.get_create_job_common_args(locals()))
576
577 # When image is supplied use a known parameterized test already in the
578 # database to pass the OS image path from the front end, through the
579 # scheduler, and finally to autoserv as the --image parameter.
580
581 # The test autoupdate_ParameterizedJob is in afe_autotests and used to
582 # instantiate a Test object and from there a ParameterizedJob.
583 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
584 known_parameterized_job = models.ParameterizedJob.objects.create(
585 test=known_test_obj)
586
587 # autoupdate_ParameterizedJob has a single parameter, the image parameter,
588 # stored in the table afe_test_parameters. We retrieve and set this
589 # instance of the parameter to the OS image path.
590 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
591 name='image')
592 known_parameterized_job.parameterizedjobparameter_set.create(
593 test_parameter=image_parameter, parameter_value=image,
594 parameter_type='string')
595
596 # By passing a parameterized_job to create_job_common the job entry in
597 # the afe_jobs table will have the field parameterized_job_id set.
598 # The scheduler uses this id in the afe_parameterized_jobs table to
599 # match this job to our known test, and then with the
600 # afe_parameterized_job_parameters table to get the actual image path.
jamesren4a41e012010-07-16 22:33:48 +0000601 return rpc_utils.create_job_common(
Simran Basiab5a1bf2014-05-28 15:39:44 -0700602 parameterized_job=known_parameterized_job.id,
jamesren4a41e012010-07-16 22:33:48 +0000603 **rpc_utils.get_create_job_common_args(locals()))
mblighe8819cd2008-02-15 16:48:40 +0000604
605
showard9dbdcda2008-10-14 17:34:36 +0000606def abort_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000607 """\
showard9dbdcda2008-10-14 17:34:36 +0000608 Abort a set of host queue entries.
jadmanski0afbb632008-06-06 21:10:57 +0000609 """
showard9dbdcda2008-10-14 17:34:36 +0000610 query = models.HostQueueEntry.query_objects(filter_data)
beepsfaecbce2013-10-29 11:35:10 -0700611
612 # Dont allow aborts on:
613 # 1. Jobs that have already completed (whether or not they were aborted)
614 # 2. Jobs that we have already been aborted (but may not have completed)
615 query = query.filter(complete=False).filter(aborted=False)
showarddc817512008-11-12 18:16:41 +0000616 models.AclGroup.check_abort_permissions(query)
showard9dbdcda2008-10-14 17:34:36 +0000617 host_queue_entries = list(query.select_related())
showard2bab8f42008-11-12 18:15:22 +0000618 rpc_utils.check_abort_synchronous_jobs(host_queue_entries)
mblighe8819cd2008-02-15 16:48:40 +0000619
Simran Basic1b26762013-06-26 14:23:21 -0700620 models.HostQueueEntry.abort_host_queue_entries(host_queue_entries)
showard9d821ab2008-07-11 16:54:29 +0000621
622
beeps8bb1f7d2013-08-05 01:30:09 -0700623def abort_special_tasks(**filter_data):
624 """\
625 Abort the special task, or tasks, specified in the filter.
626 """
627 query = models.SpecialTask.query_objects(filter_data)
628 special_tasks = query.filter(is_active=True)
629 for task in special_tasks:
630 task.abort()
631
632
Simran Basi73dae552013-02-25 14:57:46 -0800633def _call_special_tasks_on_hosts(task, hosts):
634 """\
635 Schedules a set of hosts for a special task.
636
637 @returns A list of hostnames that a special task was created for.
638 """
639 models.AclGroup.check_for_acl_violation_hosts(hosts)
640 for host in hosts:
641 models.SpecialTask.schedule_special_task(host, task)
642 return list(sorted(host.hostname for host in hosts))
643
644
showard1ff7b2e2009-05-15 23:17:18 +0000645def reverify_hosts(**filter_data):
646 """\
647 Schedules a set of hosts for verify.
mbligh4e545a52009-12-19 05:30:39 +0000648
649 @returns A list of hostnames that a verify task was created for.
showard1ff7b2e2009-05-15 23:17:18 +0000650 """
Simran Basi73dae552013-02-25 14:57:46 -0800651 return _call_special_tasks_on_hosts(models.SpecialTask.Task.VERIFY,
652 models.Host.query_objects(filter_data))
653
654
655def repair_hosts(**filter_data):
656 """\
657 Schedules a set of hosts for repair.
658
659 @returns A list of hostnames that a repair task was created for.
660 """
661 return _call_special_tasks_on_hosts(models.SpecialTask.Task.REPAIR,
662 models.Host.query_objects(filter_data))
showard1ff7b2e2009-05-15 23:17:18 +0000663
664
mblighe8819cd2008-02-15 16:48:40 +0000665def get_jobs(not_yet_run=False, running=False, finished=False, **filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000666 """\
667 Extra filter args for get_jobs:
668 -not_yet_run: Include only jobs that have not yet started running.
669 -running: Include only jobs that have start running but for which not
670 all hosts have completed.
671 -finished: Include only jobs for which all hosts have completed (or
672 aborted).
673 At most one of these three fields should be specified.
674 """
675 filter_data['extra_args'] = rpc_utils.extra_job_filters(not_yet_run,
676 running,
677 finished)
showard0957a842009-05-11 19:25:08 +0000678 job_dicts = []
679 jobs = list(models.Job.query_objects(filter_data))
680 models.Job.objects.populate_relationships(jobs, models.Label,
681 'dependencies')
showardc1a98d12010-01-15 00:22:22 +0000682 models.Job.objects.populate_relationships(jobs, models.JobKeyval, 'keyvals')
showard0957a842009-05-11 19:25:08 +0000683 for job in jobs:
684 job_dict = job.get_object_dict()
685 job_dict['dependencies'] = ','.join(label.name
686 for label in job.dependencies)
showardc1a98d12010-01-15 00:22:22 +0000687 job_dict['keyvals'] = dict((keyval.key, keyval.value)
688 for keyval in job.keyvals)
Eric Lid23bc192011-02-09 14:38:57 -0800689 if job.parameterized_job:
690 job_dict['image'] = get_parameterized_autoupdate_image_url(job)
showard0957a842009-05-11 19:25:08 +0000691 job_dicts.append(job_dict)
692 return rpc_utils.prepare_for_serialization(job_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000693
694
695def get_num_jobs(not_yet_run=False, running=False, finished=False,
jadmanski0afbb632008-06-06 21:10:57 +0000696 **filter_data):
697 """\
698 See get_jobs() for documentation of extra filter parameters.
699 """
700 filter_data['extra_args'] = rpc_utils.extra_job_filters(not_yet_run,
701 running,
702 finished)
703 return models.Job.query_count(filter_data)
mblighe8819cd2008-02-15 16:48:40 +0000704
705
mblighe8819cd2008-02-15 16:48:40 +0000706def get_jobs_summary(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000707 """\
showarda8709c52008-07-03 19:44:54 +0000708 Like get_jobs(), but adds a 'status_counts' field, which is a dictionary
jadmanski0afbb632008-06-06 21:10:57 +0000709 mapping status strings to the number of hosts currently with that
710 status, i.e. {'Queued' : 4, 'Running' : 2}.
711 """
712 jobs = get_jobs(**filter_data)
713 ids = [job['id'] for job in jobs]
714 all_status_counts = models.Job.objects.get_status_counts(ids)
715 for job in jobs:
716 job['status_counts'] = all_status_counts[job['id']]
717 return rpc_utils.prepare_for_serialization(jobs)
mblighe8819cd2008-02-15 16:48:40 +0000718
719
showarda965cef2009-05-15 23:17:41 +0000720def get_info_for_clone(id, preserve_metahosts, queue_entry_filter_data=None):
showarda8709c52008-07-03 19:44:54 +0000721 """\
722 Retrieves all the information needed to clone a job.
723 """
showarda8709c52008-07-03 19:44:54 +0000724 job = models.Job.objects.get(id=id)
showard29f7cd22009-04-29 21:16:24 +0000725 job_info = rpc_utils.get_job_info(job,
showarda965cef2009-05-15 23:17:41 +0000726 preserve_metahosts,
727 queue_entry_filter_data)
showard945072f2008-09-03 20:34:59 +0000728
showardd9992fe2008-07-31 02:15:03 +0000729 host_dicts = []
showard29f7cd22009-04-29 21:16:24 +0000730 for host in job_info['hosts']:
731 host_dict = get_hosts(id=host.id)[0]
732 other_labels = host_dict['labels']
733 if host_dict['platform']:
734 other_labels.remove(host_dict['platform'])
735 host_dict['other_labels'] = ', '.join(other_labels)
showardd9992fe2008-07-31 02:15:03 +0000736 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000737
showard29f7cd22009-04-29 21:16:24 +0000738 for host in job_info['one_time_hosts']:
739 host_dict = dict(hostname=host.hostname,
740 id=host.id,
741 platform='(one-time host)',
742 locked_text='')
743 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000744
showard4d077562009-05-08 18:24:36 +0000745 # convert keys from Label objects to strings (names of labels)
showard29f7cd22009-04-29 21:16:24 +0000746 meta_host_counts = dict((meta_host.name, count) for meta_host, count
showard4d077562009-05-08 18:24:36 +0000747 in job_info['meta_host_counts'].iteritems())
showard29f7cd22009-04-29 21:16:24 +0000748
749 info = dict(job=job.get_object_dict(),
750 meta_host_counts=meta_host_counts,
751 hosts=host_dicts)
752 info['job']['dependencies'] = job_info['dependencies']
753 if job_info['atomic_group']:
754 info['atomic_group_name'] = (job_info['atomic_group']).name
755 else:
756 info['atomic_group_name'] = None
jamesren2275ef12010-04-12 18:25:06 +0000757 info['hostless'] = job_info['hostless']
jamesren76fcf192010-04-21 20:39:50 +0000758 info['drone_set'] = job.drone_set and job.drone_set.name
showarda8709c52008-07-03 19:44:54 +0000759
Eric Lid23bc192011-02-09 14:38:57 -0800760 if job.parameterized_job:
761 info['job']['image'] = get_parameterized_autoupdate_image_url(job)
762
showarda8709c52008-07-03 19:44:54 +0000763 return rpc_utils.prepare_for_serialization(info)
764
765
showard34dc5fa2008-04-24 20:58:40 +0000766# host queue entries
767
768def get_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000769 """\
showardc92da832009-04-07 18:14:34 +0000770 @returns A sequence of nested dictionaries of host and job information.
jadmanski0afbb632008-06-06 21:10:57 +0000771 """
showardc92da832009-04-07 18:14:34 +0000772 return rpc_utils.prepare_rows_as_nested_dicts(
773 models.HostQueueEntry.query_objects(filter_data),
774 ('host', 'atomic_group', 'job'))
showard34dc5fa2008-04-24 20:58:40 +0000775
776
777def get_num_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000778 """\
779 Get the number of host queue entries associated with this job.
780 """
781 return models.HostQueueEntry.query_count(filter_data)
showard34dc5fa2008-04-24 20:58:40 +0000782
783
showard1e935f12008-07-11 00:11:36 +0000784def get_hqe_percentage_complete(**filter_data):
785 """
showardc92da832009-04-07 18:14:34 +0000786 Computes the fraction of host queue entries matching the given filter data
showard1e935f12008-07-11 00:11:36 +0000787 that are complete.
788 """
789 query = models.HostQueueEntry.query_objects(filter_data)
790 complete_count = query.filter(complete=True).count()
791 total_count = query.count()
792 if total_count == 0:
793 return 1
794 return float(complete_count) / total_count
795
796
showard1a5a4082009-07-28 20:01:37 +0000797# special tasks
798
799def get_special_tasks(**filter_data):
800 return rpc_utils.prepare_rows_as_nested_dicts(
801 models.SpecialTask.query_objects(filter_data),
802 ('host', 'queue_entry'))
803
804
showardc0ac3a72009-07-08 21:14:45 +0000805# support for host detail view
806
807def get_host_queue_entries_and_special_tasks(hostname, query_start=None,
808 query_limit=None):
809 """
810 @returns an interleaved list of HostQueueEntries and SpecialTasks,
811 in approximate run order. each dict contains keys for type, host,
812 job, status, started_on, execution_path, and ID.
813 """
814 total_limit = None
815 if query_limit is not None:
816 total_limit = query_start + query_limit
817 filter_data = {'host__hostname': hostname,
818 'query_limit': total_limit,
819 'sort_by': ['-id']}
820
821 queue_entries = list(models.HostQueueEntry.query_objects(filter_data))
822 special_tasks = list(models.SpecialTask.query_objects(filter_data))
823
824 interleaved_entries = rpc_utils.interleave_entries(queue_entries,
825 special_tasks)
826 if query_start is not None:
827 interleaved_entries = interleaved_entries[query_start:]
828 if query_limit is not None:
829 interleaved_entries = interleaved_entries[:query_limit]
830 return rpc_utils.prepare_for_serialization(interleaved_entries)
831
832
833def get_num_host_queue_entries_and_special_tasks(hostname):
834 filter_data = {'host__hostname': hostname}
835 return (models.HostQueueEntry.query_count(filter_data)
836 + models.SpecialTask.query_count(filter_data))
837
838
showard29f7cd22009-04-29 21:16:24 +0000839# recurring run
840
841def get_recurring(**filter_data):
842 return rpc_utils.prepare_rows_as_nested_dicts(
843 models.RecurringRun.query_objects(filter_data),
844 ('job', 'owner'))
845
846
847def get_num_recurring(**filter_data):
848 return models.RecurringRun.query_count(filter_data)
849
850
851def delete_recurring_runs(**filter_data):
852 to_delete = models.RecurringRun.query_objects(filter_data)
853 to_delete.delete()
854
855
856def create_recurring_run(job_id, start_date, loop_period, loop_count):
showard64a95952010-01-13 21:27:16 +0000857 owner = models.User.current_user().login
showard29f7cd22009-04-29 21:16:24 +0000858 job = models.Job.objects.get(id=job_id)
859 return job.create_recurring_job(start_date=start_date,
860 loop_period=loop_period,
861 loop_count=loop_count,
862 owner=owner)
863
864
mblighe8819cd2008-02-15 16:48:40 +0000865# other
866
showarde0b63622008-08-04 20:58:47 +0000867def echo(data=""):
868 """\
869 Returns a passed in string. For doing a basic test to see if RPC calls
870 can successfully be made.
871 """
872 return data
873
874
showardb7a52fd2009-04-27 20:10:56 +0000875def get_motd():
876 """\
877 Returns the message of the day as a string.
878 """
879 return rpc_utils.get_motd()
880
881
mblighe8819cd2008-02-15 16:48:40 +0000882def get_static_data():
jadmanski0afbb632008-06-06 21:10:57 +0000883 """\
884 Returns a dictionary containing a bunch of data that shouldn't change
885 often and is otherwise inaccessible. This includes:
showardc92da832009-04-07 18:14:34 +0000886
887 priorities: List of job priority choices.
888 default_priority: Default priority value for new jobs.
889 users: Sorted list of all users.
Jiaxi Luo31874592014-06-11 10:36:35 -0700890 labels: Sorted list of labels not start with 'cros-version' and
891 'fw-version'.
showardc92da832009-04-07 18:14:34 +0000892 atomic_groups: Sorted list of all atomic groups.
893 tests: Sorted list of all tests.
894 profilers: Sorted list of all profilers.
895 current_user: Logged-in username.
896 host_statuses: Sorted list of possible Host statuses.
897 job_statuses: Sorted list of possible HostQueueEntry statuses.
Simran Basi7e605742013-11-12 13:43:36 -0800898 job_timeout_default: The default job timeout length in minutes.
showarda1e74b32009-05-12 17:32:04 +0000899 parse_failed_repair_default: Default value for the parse_failed_repair job
Jiaxi Luo31874592014-06-11 10:36:35 -0700900 option.
showardc92da832009-04-07 18:14:34 +0000901 reboot_before_options: A list of valid RebootBefore string enums.
902 reboot_after_options: A list of valid RebootAfter string enums.
903 motd: Server's message of the day.
904 status_dictionary: A mapping from one word job status names to a more
905 informative description.
jadmanski0afbb632008-06-06 21:10:57 +0000906 """
showard21baa452008-10-21 00:08:39 +0000907
908 job_fields = models.Job.get_field_dict()
jamesren76fcf192010-04-21 20:39:50 +0000909 default_drone_set_name = models.DroneSet.default_drone_set_name()
910 drone_sets = ([default_drone_set_name] +
911 sorted(drone_set.name for drone_set in
912 models.DroneSet.objects.exclude(
913 name=default_drone_set_name)))
showard21baa452008-10-21 00:08:39 +0000914
jadmanski0afbb632008-06-06 21:10:57 +0000915 result = {}
Alex Miller7d658cf2013-09-04 16:00:35 -0700916 result['priorities'] = priorities.Priority.choices()
917 default_priority = priorities.Priority.DEFAULT
918 result['default_priority'] = 'Default'
919 result['max_schedulable_priority'] = priorities.Priority.DEFAULT
jadmanski0afbb632008-06-06 21:10:57 +0000920 result['users'] = get_users(sort_by=['login'])
Jiaxi Luo31874592014-06-11 10:36:35 -0700921
922 label_exclude_filters = [{'name__startswith': 'cros-version'},
923 {'name__startswith': 'fw-version'}]
924 result['labels'] = get_labels(
925 label_exclude_filters,
926 sort_by=['-platform', 'name'])
927
showardc92da832009-04-07 18:14:34 +0000928 result['atomic_groups'] = get_atomic_groups(sort_by=['name'])
jadmanski0afbb632008-06-06 21:10:57 +0000929 result['tests'] = get_tests(sort_by=['name'])
showard2b9a88b2008-06-13 20:55:03 +0000930 result['profilers'] = get_profilers(sort_by=['name'])
showard0fc38302008-10-23 00:44:07 +0000931 result['current_user'] = rpc_utils.prepare_for_serialization(
showard64a95952010-01-13 21:27:16 +0000932 models.User.current_user().get_object_dict())
showard2b9a88b2008-06-13 20:55:03 +0000933 result['host_statuses'] = sorted(models.Host.Status.names)
mbligh5a198b92008-12-11 19:33:29 +0000934 result['job_statuses'] = sorted(models.HostQueueEntry.Status.names)
Simran Basi7e605742013-11-12 13:43:36 -0800935 result['job_timeout_mins_default'] = models.Job.DEFAULT_TIMEOUT_MINS
Simran Basi34217022012-11-06 13:43:15 -0800936 result['job_max_runtime_mins_default'] = (
937 models.Job.DEFAULT_MAX_RUNTIME_MINS)
showarda1e74b32009-05-12 17:32:04 +0000938 result['parse_failed_repair_default'] = bool(
939 models.Job.DEFAULT_PARSE_FAILED_REPAIR)
jamesrendd855242010-03-02 22:23:44 +0000940 result['reboot_before_options'] = model_attributes.RebootBefore.names
941 result['reboot_after_options'] = model_attributes.RebootAfter.names
showard8fbae652009-01-20 23:23:10 +0000942 result['motd'] = rpc_utils.get_motd()
jamesren76fcf192010-04-21 20:39:50 +0000943 result['drone_sets_enabled'] = models.DroneSet.drone_sets_enabled()
944 result['drone_sets'] = drone_sets
jamesren4a41e012010-07-16 22:33:48 +0000945 result['parameterized_jobs'] = models.Job.parameterized_jobs_enabled()
showard8ac29b42008-07-17 17:01:55 +0000946
showardd3dc1992009-04-22 21:01:40 +0000947 result['status_dictionary'] = {"Aborted": "Aborted",
showard8ac29b42008-07-17 17:01:55 +0000948 "Verifying": "Verifying Host",
Alex Millerdfff2fd2013-05-28 13:05:06 -0700949 "Provisioning": "Provisioning Host",
showard8ac29b42008-07-17 17:01:55 +0000950 "Pending": "Waiting on other hosts",
951 "Running": "Running autoserv",
952 "Completed": "Autoserv completed",
953 "Failed": "Failed to complete",
showardd823b362008-07-24 16:35:46 +0000954 "Queued": "Queued",
showard5deb6772008-11-04 21:54:33 +0000955 "Starting": "Next in host's queue",
956 "Stopped": "Other host(s) failed verify",
showardd3dc1992009-04-22 21:01:40 +0000957 "Parsing": "Awaiting parse of final results",
showard29f7cd22009-04-29 21:16:24 +0000958 "Gathering": "Gathering log files",
showard8cc058f2009-09-08 16:26:33 +0000959 "Template": "Template job for recurring run",
mbligh4608b002010-01-05 18:22:35 +0000960 "Waiting": "Waiting for scheduler action",
Dan Shi07e09af2013-04-12 09:31:29 -0700961 "Archiving": "Archiving results",
962 "Resetting": "Resetting hosts"}
jadmanski0afbb632008-06-06 21:10:57 +0000963 return result
showard29f7cd22009-04-29 21:16:24 +0000964
965
966def get_server_time():
967 return datetime.datetime.now().strftime("%Y-%m-%d %H:%M")