blob: 481256797e6826c5a21f5c6186933c207dea0a6a [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
Jiaxi Luo90190c92014-06-18 12:35:57 -070040from autotest_lib.server.cros.dynamic_suite import tools
mblighe8819cd2008-02-15 16:48:40 +000041
Eric Lid23bc192011-02-09 14:38:57 -080042def get_parameterized_autoupdate_image_url(job):
43 """Get the parameterized autoupdate image url from a parameterized job."""
44 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
45 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
beeps8bb1f7d2013-08-05 01:30:09 -070046 name='image')
Eric Lid23bc192011-02-09 14:38:57 -080047 para_set = job.parameterized_job.parameterizedjobparameter_set
48 job_test_para = para_set.get(test_parameter=image_parameter)
49 return job_test_para.parameter_value
50
51
mblighe8819cd2008-02-15 16:48:40 +000052# labels
53
showard989f25d2008-10-01 11:38:11 +000054def add_label(name, kernel_config=None, platform=None, only_if_needed=None):
showardc92da832009-04-07 18:14:34 +000055 return models.Label.add_object(
56 name=name, kernel_config=kernel_config, platform=platform,
57 only_if_needed=only_if_needed).id
mblighe8819cd2008-02-15 16:48:40 +000058
59
60def modify_label(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +000061 models.Label.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +000062
63
64def delete_label(id):
jadmanski0afbb632008-06-06 21:10:57 +000065 models.Label.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +000066
67
showardbbabf502008-06-06 00:02:02 +000068def label_add_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000069 host_objs = models.Host.smart_get_bulk(hosts)
showardcafd16e2009-05-29 18:37:49 +000070 label = models.Label.smart_get(id)
71 if label.platform:
72 models.Host.check_no_platform(host_objs)
73 label.host_set.add(*host_objs)
showardbbabf502008-06-06 00:02:02 +000074
75
76def label_remove_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000077 host_objs = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +000078 models.Label.smart_get(id).host_set.remove(*host_objs)
showardbbabf502008-06-06 00:02:02 +000079
80
Jiaxi Luo31874592014-06-11 10:36:35 -070081def get_labels(exclude_filters=(), **filter_data):
showardc92da832009-04-07 18:14:34 +000082 """\
Jiaxi Luo31874592014-06-11 10:36:35 -070083 @param exclude_filters: A sequence of dictionaries of filters.
84
showardc92da832009-04-07 18:14:34 +000085 @returns A sequence of nested dictionaries of label information.
86 """
Jiaxi Luo31874592014-06-11 10:36:35 -070087 labels = models.Label.query_objects(filter_data)
88 for exclude_filter in exclude_filters:
89 labels = labels.exclude(**exclude_filter)
90 return rpc_utils.prepare_rows_as_nested_dicts(labels, ('atomic_group',))
showardc92da832009-04-07 18:14:34 +000091
92
93# atomic groups
94
showarde9450c92009-06-30 01:58:52 +000095def add_atomic_group(name, max_number_of_machines=None, description=None):
showardc92da832009-04-07 18:14:34 +000096 return models.AtomicGroup.add_object(
97 name=name, max_number_of_machines=max_number_of_machines,
98 description=description).id
99
100
101def modify_atomic_group(id, **data):
102 models.AtomicGroup.smart_get(id).update_object(data)
103
104
105def delete_atomic_group(id):
106 models.AtomicGroup.smart_get(id).delete()
107
108
109def atomic_group_add_labels(id, labels):
110 label_objs = models.Label.smart_get_bulk(labels)
111 models.AtomicGroup.smart_get(id).label_set.add(*label_objs)
112
113
114def atomic_group_remove_labels(id, labels):
115 label_objs = models.Label.smart_get_bulk(labels)
116 models.AtomicGroup.smart_get(id).label_set.remove(*label_objs)
117
118
119def get_atomic_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000120 return rpc_utils.prepare_for_serialization(
showardc92da832009-04-07 18:14:34 +0000121 models.AtomicGroup.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000122
123
124# hosts
125
showarddf062562008-07-03 19:56:37 +0000126def add_host(hostname, status=None, locked=None, protection=None):
jadmanski0afbb632008-06-06 21:10:57 +0000127 return models.Host.add_object(hostname=hostname, status=status,
showarddf062562008-07-03 19:56:37 +0000128 locked=locked, protection=protection).id
mblighe8819cd2008-02-15 16:48:40 +0000129
130
131def modify_host(id, **data):
showardbe0d8692009-08-20 23:42:44 +0000132 rpc_utils.check_modify_host(data)
showardce7c0922009-09-11 18:39:24 +0000133 host = models.Host.smart_get(id)
134 rpc_utils.check_modify_host_locking(host, data)
135 host.update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000136
137
showard276f9442009-05-20 00:33:16 +0000138def modify_hosts(host_filter_data, update_data):
139 """
showardbe0d8692009-08-20 23:42:44 +0000140 @param host_filter_data: Filters out which hosts to modify.
141 @param update_data: A dictionary with the changes to make to the hosts.
showard276f9442009-05-20 00:33:16 +0000142 """
showardbe0d8692009-08-20 23:42:44 +0000143 rpc_utils.check_modify_host(update_data)
showard276f9442009-05-20 00:33:16 +0000144 hosts = models.Host.query_objects(host_filter_data)
Alex Miller9658a952013-05-14 16:40:02 -0700145 # Check all hosts before changing data for exception safety.
146 for host in hosts:
147 rpc_utils.check_modify_host_locking(host, update_data)
showard276f9442009-05-20 00:33:16 +0000148 for host in hosts:
149 host.update_object(update_data)
150
151
mblighe8819cd2008-02-15 16:48:40 +0000152def host_add_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000153 labels = models.Label.smart_get_bulk(labels)
showardcafd16e2009-05-29 18:37:49 +0000154 host = models.Host.smart_get(id)
155
156 platforms = [label.name for label in labels if label.platform]
157 if len(platforms) > 1:
158 raise model_logic.ValidationError(
159 {'labels': 'Adding more than one platform label: %s' %
160 ', '.join(platforms)})
161 if len(platforms) == 1:
162 models.Host.check_no_platform([host])
163 host.labels.add(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000164
165
166def host_remove_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000167 labels = models.Label.smart_get_bulk(labels)
jadmanski0afbb632008-06-06 21:10:57 +0000168 models.Host.smart_get(id).labels.remove(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000169
170
showard0957a842009-05-11 19:25:08 +0000171def set_host_attribute(attribute, value, **host_filter_data):
172 """
173 @param attribute string name of attribute
174 @param value string, or None to delete an attribute
175 @param host_filter_data filter data to apply to Hosts to choose hosts to act
176 upon
177 """
178 assert host_filter_data # disallow accidental actions on all hosts
179 hosts = models.Host.query_objects(host_filter_data)
180 models.AclGroup.check_for_acl_violation_hosts(hosts)
181
182 for host in hosts:
showardf8b19042009-05-12 17:22:49 +0000183 host.set_or_delete_attribute(attribute, value)
showard0957a842009-05-11 19:25:08 +0000184
185
mblighe8819cd2008-02-15 16:48:40 +0000186def delete_host(id):
jadmanski0afbb632008-06-06 21:10:57 +0000187 models.Host.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000188
189
showard87cc38f2009-08-20 23:37:04 +0000190def get_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000191 exclude_atomic_group_hosts=False, valid_only=True, **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000192 """
193 @param multiple_labels: match hosts in all of the labels given. Should
194 be a list of label names.
195 @param exclude_only_if_needed_labels: Exclude hosts with at least one
196 "only_if_needed" label applied.
197 @param exclude_atomic_group_hosts: Exclude hosts that have one or more
198 atomic group labels associated with them.
jadmanski0afbb632008-06-06 21:10:57 +0000199 """
showard43a3d262008-11-12 18:17:05 +0000200 hosts = rpc_utils.get_host_query(multiple_labels,
201 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000202 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000203 valid_only, filter_data)
showard0957a842009-05-11 19:25:08 +0000204 hosts = list(hosts)
205 models.Host.objects.populate_relationships(hosts, models.Label,
206 'label_list')
207 models.Host.objects.populate_relationships(hosts, models.AclGroup,
208 'acl_list')
209 models.Host.objects.populate_relationships(hosts, models.HostAttribute,
210 'attribute_list')
showard43a3d262008-11-12 18:17:05 +0000211 host_dicts = []
212 for host_obj in hosts:
213 host_dict = host_obj.get_object_dict()
showard0957a842009-05-11 19:25:08 +0000214 host_dict['labels'] = [label.name for label in host_obj.label_list]
showard909c9142009-07-07 20:54:42 +0000215 host_dict['platform'], host_dict['atomic_group'] = (rpc_utils.
216 find_platform_and_atomic_group(host_obj))
showard0957a842009-05-11 19:25:08 +0000217 host_dict['acls'] = [acl.name for acl in host_obj.acl_list]
218 host_dict['attributes'] = dict((attribute.attribute, attribute.value)
219 for attribute in host_obj.attribute_list)
showard43a3d262008-11-12 18:17:05 +0000220 host_dicts.append(host_dict)
221 return rpc_utils.prepare_for_serialization(host_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000222
223
showard87cc38f2009-08-20 23:37:04 +0000224def get_num_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000225 exclude_atomic_group_hosts=False, valid_only=True,
226 **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000227 """
228 Same parameters as get_hosts().
229
230 @returns The number of matching hosts.
231 """
showard43a3d262008-11-12 18:17:05 +0000232 hosts = rpc_utils.get_host_query(multiple_labels,
233 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000234 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000235 valid_only, filter_data)
showard43a3d262008-11-12 18:17:05 +0000236 return hosts.count()
showard1385b162008-03-13 15:59:40 +0000237
mblighe8819cd2008-02-15 16:48:40 +0000238
239# tests
240
showard909c7a62008-07-15 21:52:38 +0000241def add_test(name, test_type, path, author=None, dependencies=None,
showard3d9899a2008-07-31 02:11:58 +0000242 experimental=True, run_verify=None, test_class=None,
showard909c7a62008-07-15 21:52:38 +0000243 test_time=None, test_category=None, description=None,
244 sync_count=1):
jadmanski0afbb632008-06-06 21:10:57 +0000245 return models.Test.add_object(name=name, test_type=test_type, path=path,
showard909c7a62008-07-15 21:52:38 +0000246 author=author, dependencies=dependencies,
247 experimental=experimental,
248 run_verify=run_verify, test_time=test_time,
249 test_category=test_category,
250 sync_count=sync_count,
jadmanski0afbb632008-06-06 21:10:57 +0000251 test_class=test_class,
252 description=description).id
mblighe8819cd2008-02-15 16:48:40 +0000253
254
255def modify_test(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000256 models.Test.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000257
258
259def delete_test(id):
jadmanski0afbb632008-06-06 21:10:57 +0000260 models.Test.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000261
262
263def get_tests(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000264 return rpc_utils.prepare_for_serialization(
265 models.Test.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000266
267
showard2b9a88b2008-06-13 20:55:03 +0000268# profilers
269
270def add_profiler(name, description=None):
271 return models.Profiler.add_object(name=name, description=description).id
272
273
274def modify_profiler(id, **data):
275 models.Profiler.smart_get(id).update_object(data)
276
277
278def delete_profiler(id):
279 models.Profiler.smart_get(id).delete()
280
281
282def get_profilers(**filter_data):
283 return rpc_utils.prepare_for_serialization(
284 models.Profiler.list_objects(filter_data))
285
286
mblighe8819cd2008-02-15 16:48:40 +0000287# users
288
289def add_user(login, access_level=None):
jadmanski0afbb632008-06-06 21:10:57 +0000290 return models.User.add_object(login=login, access_level=access_level).id
mblighe8819cd2008-02-15 16:48:40 +0000291
292
293def modify_user(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000294 models.User.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000295
296
297def delete_user(id):
jadmanski0afbb632008-06-06 21:10:57 +0000298 models.User.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000299
300
301def get_users(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000302 return rpc_utils.prepare_for_serialization(
303 models.User.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000304
305
306# acl groups
307
308def add_acl_group(name, description=None):
showard04f2cd82008-07-25 20:53:31 +0000309 group = models.AclGroup.add_object(name=name, description=description)
showard64a95952010-01-13 21:27:16 +0000310 group.users.add(models.User.current_user())
showard04f2cd82008-07-25 20:53:31 +0000311 return group.id
mblighe8819cd2008-02-15 16:48:40 +0000312
313
314def modify_acl_group(id, **data):
showard04f2cd82008-07-25 20:53:31 +0000315 group = models.AclGroup.smart_get(id)
316 group.check_for_acl_violation_acl_group()
317 group.update_object(data)
318 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000319
320
321def acl_group_add_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000322 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000323 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000324 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000325 group.users.add(*users)
mblighe8819cd2008-02-15 16:48:40 +0000326
327
328def acl_group_remove_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000329 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000330 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000331 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000332 group.users.remove(*users)
showard04f2cd82008-07-25 20:53:31 +0000333 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000334
335
336def acl_group_add_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000337 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000338 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000339 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000340 group.hosts.add(*hosts)
showard08f981b2008-06-24 21:59:03 +0000341 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000342
343
344def acl_group_remove_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000345 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000346 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000347 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000348 group.hosts.remove(*hosts)
showard08f981b2008-06-24 21:59:03 +0000349 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000350
351
352def delete_acl_group(id):
jadmanski0afbb632008-06-06 21:10:57 +0000353 models.AclGroup.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000354
355
356def get_acl_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000357 acl_groups = models.AclGroup.list_objects(filter_data)
358 for acl_group in acl_groups:
359 acl_group_obj = models.AclGroup.objects.get(id=acl_group['id'])
360 acl_group['users'] = [user.login
361 for user in acl_group_obj.users.all()]
362 acl_group['hosts'] = [host.hostname
363 for host in acl_group_obj.hosts.all()]
364 return rpc_utils.prepare_for_serialization(acl_groups)
mblighe8819cd2008-02-15 16:48:40 +0000365
366
367# jobs
368
mbligh120351e2009-01-24 01:40:45 +0000369def generate_control_file(tests=(), kernel=None, label=None, profilers=(),
showard91f85102009-10-12 20:34:52 +0000370 client_control_file='', use_container=False,
showard232b7ae2009-11-10 00:46:48 +0000371 profile_only=None, upload_kernel_config=False):
jadmanski0afbb632008-06-06 21:10:57 +0000372 """
mbligh120351e2009-01-24 01:40:45 +0000373 Generates a client-side control file to load a kernel and run tests.
374
375 @param tests List of tests to run.
mbligha3c58d22009-08-24 22:01:51 +0000376 @param kernel A list of kernel info dictionaries configuring which kernels
377 to boot for this job and other options for them
mbligh120351e2009-01-24 01:40:45 +0000378 @param label Name of label to grab kernel config from.
379 @param profilers List of profilers to activate during the job.
380 @param client_control_file The contents of a client-side control file to
381 run at the end of all tests. If this is supplied, all tests must be
382 client side.
383 TODO: in the future we should support server control files directly
384 to wrap with a kernel. That'll require changing the parameter
385 name and adding a boolean to indicate if it is a client or server
386 control file.
387 @param use_container unused argument today. TODO: Enable containers
388 on the host during a client side test.
showard91f85102009-10-12 20:34:52 +0000389 @param profile_only A boolean that indicates what default profile_only
390 mode to use in the control file. Passing None will generate a
391 control file that does not explcitly set the default mode at all.
showard232b7ae2009-11-10 00:46:48 +0000392 @param upload_kernel_config: if enabled it will generate server control
393 file code that uploads the kernel config file to the client and
394 tells the client of the new (local) path when compiling the kernel;
395 the tests must be server side tests
mbligh120351e2009-01-24 01:40:45 +0000396
397 @returns a dict with the following keys:
398 control_file: str, The control file text.
399 is_server: bool, is the control file a server-side control file?
400 synch_count: How many machines the job uses per autoserv execution.
401 synch_count == 1 means the job is asynchronous.
402 dependencies: A list of the names of labels on which the job depends.
403 """
showardd86debe2009-06-10 17:37:56 +0000404 if not tests and not client_control_file:
showard2bab8f42008-11-12 18:15:22 +0000405 return dict(control_file='', is_server=False, synch_count=1,
showard989f25d2008-10-01 11:38:11 +0000406 dependencies=[])
mblighe8819cd2008-02-15 16:48:40 +0000407
showard989f25d2008-10-01 11:38:11 +0000408 cf_info, test_objects, profiler_objects, label = (
showard2b9a88b2008-06-13 20:55:03 +0000409 rpc_utils.prepare_generate_control_file(tests, kernel, label,
410 profilers))
showard989f25d2008-10-01 11:38:11 +0000411 cf_info['control_file'] = control_file.generate_control(
mbligha3c58d22009-08-24 22:01:51 +0000412 tests=test_objects, kernels=kernel, platform=label,
mbligh120351e2009-01-24 01:40:45 +0000413 profilers=profiler_objects, is_server=cf_info['is_server'],
showard232b7ae2009-11-10 00:46:48 +0000414 client_control_file=client_control_file, profile_only=profile_only,
415 upload_kernel_config=upload_kernel_config)
showard989f25d2008-10-01 11:38:11 +0000416 return cf_info
mblighe8819cd2008-02-15 16:48:40 +0000417
418
jamesren4a41e012010-07-16 22:33:48 +0000419def create_parameterized_job(name, priority, test, parameters, kernel=None,
420 label=None, profilers=(), profiler_parameters=None,
421 use_container=False, profile_only=None,
422 upload_kernel_config=False, hosts=(),
423 meta_hosts=(), one_time_hosts=(),
424 atomic_group_name=None, synch_count=None,
425 is_template=False, timeout=None,
Simran Basi7e605742013-11-12 13:43:36 -0800426 timeout_mins=None, max_runtime_mins=None,
427 run_verify=False, email_list='', dependencies=(),
428 reboot_before=None, reboot_after=None,
429 parse_failed_repair=None, hostless=False,
430 keyvals=None, drone_set=None, run_reset=True):
jamesren4a41e012010-07-16 22:33:48 +0000431 """
432 Creates and enqueues a parameterized job.
433
434 Most parameters a combination of the parameters for generate_control_file()
435 and create_job(), with the exception of:
436
437 @param test name or ID of the test to run
438 @param parameters a map of parameter name ->
439 tuple of (param value, param type)
440 @param profiler_parameters a dictionary of parameters for the profilers:
441 key: profiler name
442 value: dict of param name -> tuple of
443 (param value,
444 param type)
445 """
446 # Save the values of the passed arguments here. What we're going to do with
447 # them is pass them all to rpc_utils.get_create_job_common_args(), which
448 # will extract the subset of these arguments that apply for
449 # rpc_utils.create_job_common(), which we then pass in to that function.
450 args = locals()
451
452 # Set up the parameterized job configs
453 test_obj = models.Test.smart_get(test)
Aviv Keshet3dd8beb2013-05-13 17:36:04 -0700454 control_type = test_obj.test_type
jamesren4a41e012010-07-16 22:33:48 +0000455
456 try:
457 label = models.Label.smart_get(label)
458 except models.Label.DoesNotExist:
459 label = None
460
461 kernel_objs = models.Kernel.create_kernels(kernel)
462 profiler_objs = [models.Profiler.smart_get(profiler)
463 for profiler in profilers]
464
465 parameterized_job = models.ParameterizedJob.objects.create(
466 test=test_obj, label=label, use_container=use_container,
467 profile_only=profile_only,
468 upload_kernel_config=upload_kernel_config)
469 parameterized_job.kernels.add(*kernel_objs)
470
471 for profiler in profiler_objs:
472 parameterized_profiler = models.ParameterizedJobProfiler.objects.create(
473 parameterized_job=parameterized_job,
474 profiler=profiler)
475 profiler_params = profiler_parameters.get(profiler.name, {})
476 for name, (value, param_type) in profiler_params.iteritems():
477 models.ParameterizedJobProfilerParameter.objects.create(
478 parameterized_job_profiler=parameterized_profiler,
479 parameter_name=name,
480 parameter_value=value,
481 parameter_type=param_type)
482
483 try:
484 for parameter in test_obj.testparameter_set.all():
485 if parameter.name in parameters:
486 param_value, param_type = parameters.pop(parameter.name)
487 parameterized_job.parameterizedjobparameter_set.create(
488 test_parameter=parameter, parameter_value=param_value,
489 parameter_type=param_type)
490
491 if parameters:
492 raise Exception('Extra parameters remain: %r' % parameters)
493
494 return rpc_utils.create_job_common(
495 parameterized_job=parameterized_job.id,
496 control_type=control_type,
497 **rpc_utils.get_create_job_common_args(args))
498 except:
499 parameterized_job.delete()
500 raise
501
502
Simran Basib6ec8ae2014-04-23 12:05:08 -0700503def create_job_page_handler(name, priority, control_file, control_type,
504 image=None, hostless=False, **kwargs):
505 """\
506 Create and enqueue a job.
507
508 @param name name of this job
509 @param priority Integer priority of this job. Higher is more important.
510 @param control_file String contents of the control file.
511 @param control_type Type of control file, Client or Server.
512 @param kwargs extra args that will be required by create_suite_job or
513 create_job.
514
515 @returns The created Job id number.
516 """
517 control_file = rpc_utils.encode_ascii(control_file)
518
519 if image and hostless:
520 return site_rpc_interface.create_suite_job(
521 name=name, control_file=control_file, priority=priority,
522 build=image, **kwargs)
523 return create_job(name, priority, control_file, control_type, image=image,
524 hostless=hostless, **kwargs)
525
526
showard12f3e322009-05-13 21:27:42 +0000527def create_job(name, priority, control_file, control_type,
528 hosts=(), meta_hosts=(), one_time_hosts=(),
529 atomic_group_name=None, synch_count=None, is_template=False,
Simran Basi7e605742013-11-12 13:43:36 -0800530 timeout=None, timeout_mins=None, max_runtime_mins=None,
531 run_verify=False, email_list='', dependencies=(),
532 reboot_before=None, reboot_after=None, parse_failed_repair=None,
533 hostless=False, keyvals=None, drone_set=None, image=None,
Jiaxi Luo90190c92014-06-18 12:35:57 -0700534 parent_job_id=None, test_retry=0, run_reset=True, args=(),
535 **kwargs):
jadmanski0afbb632008-06-06 21:10:57 +0000536 """\
537 Create and enqueue a job.
mblighe8819cd2008-02-15 16:48:40 +0000538
showarda1e74b32009-05-12 17:32:04 +0000539 @param name name of this job
Alex Miller7d658cf2013-09-04 16:00:35 -0700540 @param priority Integer priority of this job. Higher is more important.
showarda1e74b32009-05-12 17:32:04 +0000541 @param control_file String contents of the control file.
542 @param control_type Type of control file, Client or Server.
543 @param synch_count How many machines the job uses per autoserv execution.
Jiaxi Luo90190c92014-06-18 12:35:57 -0700544 synch_count == 1 means the job is asynchronous. If an atomic group is
545 given this value is treated as a minimum.
showarda1e74b32009-05-12 17:32:04 +0000546 @param is_template If true then create a template job.
547 @param timeout Hours after this call returns until the job times out.
Simran Basi7e605742013-11-12 13:43:36 -0800548 @param timeout_mins Minutes after this call returns until the job times
Jiaxi Luo90190c92014-06-18 12:35:57 -0700549 out.
Simran Basi34217022012-11-06 13:43:15 -0800550 @param max_runtime_mins Minutes from job starting time until job times out
showarda1e74b32009-05-12 17:32:04 +0000551 @param run_verify Should the host be verified before running the test?
552 @param email_list String containing emails to mail when the job is done
553 @param dependencies List of label names on which this job depends
554 @param reboot_before Never, If dirty, or Always
555 @param reboot_after Never, If all tests passed, or Always
556 @param parse_failed_repair if true, results of failed repairs launched by
Jiaxi Luo90190c92014-06-18 12:35:57 -0700557 this job will be parsed as part of the job.
showarda9545c02009-12-18 22:44:26 +0000558 @param hostless if true, create a hostless job
showardc1a98d12010-01-15 00:22:22 +0000559 @param keyvals dict of keyvals to associate with the job
showarda1e74b32009-05-12 17:32:04 +0000560 @param hosts List of hosts to run job on.
561 @param meta_hosts List where each entry is a label name, and for each entry
Jiaxi Luo90190c92014-06-18 12:35:57 -0700562 one host will be chosen from that label to run the job on.
showarda1e74b32009-05-12 17:32:04 +0000563 @param one_time_hosts List of hosts not in the database to run the job on.
564 @param atomic_group_name The name of an atomic group to schedule the job on.
jamesren76fcf192010-04-21 20:39:50 +0000565 @param drone_set The name of the drone set to run this test on.
Paul Pendlebury5a8c6ad2011-02-01 07:20:17 -0800566 @param image OS image to install before running job.
Aviv Keshet0b9cfc92013-02-05 11:36:02 -0800567 @param parent_job_id id of a job considered to be parent of created job.
Simran Basib6ec8ae2014-04-23 12:05:08 -0700568 @param test_retry Number of times to retry test if the test did not
Jiaxi Luo90190c92014-06-18 12:35:57 -0700569 complete successfully. (optional, default: 0)
Simran Basib6ec8ae2014-04-23 12:05:08 -0700570 @param run_reset Should the host be reset before running the test?
Jiaxi Luo90190c92014-06-18 12:35:57 -0700571 @param args A list of args to be injected into control file.
Simran Basib6ec8ae2014-04-23 12:05:08 -0700572 @param kwargs extra keyword args. NOT USED.
showardc92da832009-04-07 18:14:34 +0000573
574 @returns The created Job id number.
jadmanski0afbb632008-06-06 21:10:57 +0000575 """
Jiaxi Luo90190c92014-06-18 12:35:57 -0700576 if args:
577 control_file = tools.inject_vars({'args': args}, control_file)
578
Simran Basiab5a1bf2014-05-28 15:39:44 -0700579 if image is None:
580 return rpc_utils.create_job_common(
581 **rpc_utils.get_create_job_common_args(locals()))
582
583 # When image is supplied use a known parameterized test already in the
584 # database to pass the OS image path from the front end, through the
585 # scheduler, and finally to autoserv as the --image parameter.
586
587 # The test autoupdate_ParameterizedJob is in afe_autotests and used to
588 # instantiate a Test object and from there a ParameterizedJob.
589 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
590 known_parameterized_job = models.ParameterizedJob.objects.create(
591 test=known_test_obj)
592
593 # autoupdate_ParameterizedJob has a single parameter, the image parameter,
594 # stored in the table afe_test_parameters. We retrieve and set this
595 # instance of the parameter to the OS image path.
596 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
597 name='image')
598 known_parameterized_job.parameterizedjobparameter_set.create(
599 test_parameter=image_parameter, parameter_value=image,
600 parameter_type='string')
601
602 # By passing a parameterized_job to create_job_common the job entry in
603 # the afe_jobs table will have the field parameterized_job_id set.
604 # The scheduler uses this id in the afe_parameterized_jobs table to
605 # match this job to our known test, and then with the
606 # afe_parameterized_job_parameters table to get the actual image path.
jamesren4a41e012010-07-16 22:33:48 +0000607 return rpc_utils.create_job_common(
Simran Basiab5a1bf2014-05-28 15:39:44 -0700608 parameterized_job=known_parameterized_job.id,
jamesren4a41e012010-07-16 22:33:48 +0000609 **rpc_utils.get_create_job_common_args(locals()))
mblighe8819cd2008-02-15 16:48:40 +0000610
611
showard9dbdcda2008-10-14 17:34:36 +0000612def abort_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000613 """\
showard9dbdcda2008-10-14 17:34:36 +0000614 Abort a set of host queue entries.
jadmanski0afbb632008-06-06 21:10:57 +0000615 """
showard9dbdcda2008-10-14 17:34:36 +0000616 query = models.HostQueueEntry.query_objects(filter_data)
beepsfaecbce2013-10-29 11:35:10 -0700617
618 # Dont allow aborts on:
619 # 1. Jobs that have already completed (whether or not they were aborted)
620 # 2. Jobs that we have already been aborted (but may not have completed)
621 query = query.filter(complete=False).filter(aborted=False)
showarddc817512008-11-12 18:16:41 +0000622 models.AclGroup.check_abort_permissions(query)
showard9dbdcda2008-10-14 17:34:36 +0000623 host_queue_entries = list(query.select_related())
showard2bab8f42008-11-12 18:15:22 +0000624 rpc_utils.check_abort_synchronous_jobs(host_queue_entries)
mblighe8819cd2008-02-15 16:48:40 +0000625
Simran Basic1b26762013-06-26 14:23:21 -0700626 models.HostQueueEntry.abort_host_queue_entries(host_queue_entries)
showard9d821ab2008-07-11 16:54:29 +0000627
628
beeps8bb1f7d2013-08-05 01:30:09 -0700629def abort_special_tasks(**filter_data):
630 """\
631 Abort the special task, or tasks, specified in the filter.
632 """
633 query = models.SpecialTask.query_objects(filter_data)
634 special_tasks = query.filter(is_active=True)
635 for task in special_tasks:
636 task.abort()
637
638
Simran Basi73dae552013-02-25 14:57:46 -0800639def _call_special_tasks_on_hosts(task, hosts):
640 """\
641 Schedules a set of hosts for a special task.
642
643 @returns A list of hostnames that a special task was created for.
644 """
645 models.AclGroup.check_for_acl_violation_hosts(hosts)
646 for host in hosts:
647 models.SpecialTask.schedule_special_task(host, task)
648 return list(sorted(host.hostname for host in hosts))
649
650
showard1ff7b2e2009-05-15 23:17:18 +0000651def reverify_hosts(**filter_data):
652 """\
653 Schedules a set of hosts for verify.
mbligh4e545a52009-12-19 05:30:39 +0000654
655 @returns A list of hostnames that a verify task was created for.
showard1ff7b2e2009-05-15 23:17:18 +0000656 """
Simran Basi73dae552013-02-25 14:57:46 -0800657 return _call_special_tasks_on_hosts(models.SpecialTask.Task.VERIFY,
658 models.Host.query_objects(filter_data))
659
660
661def repair_hosts(**filter_data):
662 """\
663 Schedules a set of hosts for repair.
664
665 @returns A list of hostnames that a repair task was created for.
666 """
667 return _call_special_tasks_on_hosts(models.SpecialTask.Task.REPAIR,
668 models.Host.query_objects(filter_data))
showard1ff7b2e2009-05-15 23:17:18 +0000669
670
mblighe8819cd2008-02-15 16:48:40 +0000671def get_jobs(not_yet_run=False, running=False, finished=False, **filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000672 """\
673 Extra filter args for get_jobs:
674 -not_yet_run: Include only jobs that have not yet started running.
675 -running: Include only jobs that have start running but for which not
676 all hosts have completed.
677 -finished: Include only jobs for which all hosts have completed (or
678 aborted).
679 At most one of these three fields should be specified.
680 """
681 filter_data['extra_args'] = rpc_utils.extra_job_filters(not_yet_run,
682 running,
683 finished)
showard0957a842009-05-11 19:25:08 +0000684 job_dicts = []
685 jobs = list(models.Job.query_objects(filter_data))
686 models.Job.objects.populate_relationships(jobs, models.Label,
687 'dependencies')
showardc1a98d12010-01-15 00:22:22 +0000688 models.Job.objects.populate_relationships(jobs, models.JobKeyval, 'keyvals')
showard0957a842009-05-11 19:25:08 +0000689 for job in jobs:
690 job_dict = job.get_object_dict()
691 job_dict['dependencies'] = ','.join(label.name
692 for label in job.dependencies)
showardc1a98d12010-01-15 00:22:22 +0000693 job_dict['keyvals'] = dict((keyval.key, keyval.value)
694 for keyval in job.keyvals)
Eric Lid23bc192011-02-09 14:38:57 -0800695 if job.parameterized_job:
696 job_dict['image'] = get_parameterized_autoupdate_image_url(job)
showard0957a842009-05-11 19:25:08 +0000697 job_dicts.append(job_dict)
698 return rpc_utils.prepare_for_serialization(job_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000699
700
701def get_num_jobs(not_yet_run=False, running=False, finished=False,
jadmanski0afbb632008-06-06 21:10:57 +0000702 **filter_data):
703 """\
704 See get_jobs() for documentation of extra filter parameters.
705 """
706 filter_data['extra_args'] = rpc_utils.extra_job_filters(not_yet_run,
707 running,
708 finished)
709 return models.Job.query_count(filter_data)
mblighe8819cd2008-02-15 16:48:40 +0000710
711
mblighe8819cd2008-02-15 16:48:40 +0000712def get_jobs_summary(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000713 """\
showarda8709c52008-07-03 19:44:54 +0000714 Like get_jobs(), but adds a 'status_counts' field, which is a dictionary
jadmanski0afbb632008-06-06 21:10:57 +0000715 mapping status strings to the number of hosts currently with that
716 status, i.e. {'Queued' : 4, 'Running' : 2}.
717 """
718 jobs = get_jobs(**filter_data)
719 ids = [job['id'] for job in jobs]
720 all_status_counts = models.Job.objects.get_status_counts(ids)
721 for job in jobs:
722 job['status_counts'] = all_status_counts[job['id']]
723 return rpc_utils.prepare_for_serialization(jobs)
mblighe8819cd2008-02-15 16:48:40 +0000724
725
showarda965cef2009-05-15 23:17:41 +0000726def get_info_for_clone(id, preserve_metahosts, queue_entry_filter_data=None):
showarda8709c52008-07-03 19:44:54 +0000727 """\
728 Retrieves all the information needed to clone a job.
729 """
showarda8709c52008-07-03 19:44:54 +0000730 job = models.Job.objects.get(id=id)
showard29f7cd22009-04-29 21:16:24 +0000731 job_info = rpc_utils.get_job_info(job,
showarda965cef2009-05-15 23:17:41 +0000732 preserve_metahosts,
733 queue_entry_filter_data)
showard945072f2008-09-03 20:34:59 +0000734
showardd9992fe2008-07-31 02:15:03 +0000735 host_dicts = []
showard29f7cd22009-04-29 21:16:24 +0000736 for host in job_info['hosts']:
737 host_dict = get_hosts(id=host.id)[0]
738 other_labels = host_dict['labels']
739 if host_dict['platform']:
740 other_labels.remove(host_dict['platform'])
741 host_dict['other_labels'] = ', '.join(other_labels)
showardd9992fe2008-07-31 02:15:03 +0000742 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000743
showard29f7cd22009-04-29 21:16:24 +0000744 for host in job_info['one_time_hosts']:
745 host_dict = dict(hostname=host.hostname,
746 id=host.id,
747 platform='(one-time host)',
748 locked_text='')
749 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000750
showard4d077562009-05-08 18:24:36 +0000751 # convert keys from Label objects to strings (names of labels)
showard29f7cd22009-04-29 21:16:24 +0000752 meta_host_counts = dict((meta_host.name, count) for meta_host, count
showard4d077562009-05-08 18:24:36 +0000753 in job_info['meta_host_counts'].iteritems())
showard29f7cd22009-04-29 21:16:24 +0000754
755 info = dict(job=job.get_object_dict(),
756 meta_host_counts=meta_host_counts,
757 hosts=host_dicts)
758 info['job']['dependencies'] = job_info['dependencies']
759 if job_info['atomic_group']:
760 info['atomic_group_name'] = (job_info['atomic_group']).name
761 else:
762 info['atomic_group_name'] = None
jamesren2275ef12010-04-12 18:25:06 +0000763 info['hostless'] = job_info['hostless']
jamesren76fcf192010-04-21 20:39:50 +0000764 info['drone_set'] = job.drone_set and job.drone_set.name
showarda8709c52008-07-03 19:44:54 +0000765
Eric Lid23bc192011-02-09 14:38:57 -0800766 if job.parameterized_job:
767 info['job']['image'] = get_parameterized_autoupdate_image_url(job)
768
showarda8709c52008-07-03 19:44:54 +0000769 return rpc_utils.prepare_for_serialization(info)
770
771
showard34dc5fa2008-04-24 20:58:40 +0000772# host queue entries
773
774def get_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000775 """\
showardc92da832009-04-07 18:14:34 +0000776 @returns A sequence of nested dictionaries of host and job information.
jadmanski0afbb632008-06-06 21:10:57 +0000777 """
showardc92da832009-04-07 18:14:34 +0000778 return rpc_utils.prepare_rows_as_nested_dicts(
779 models.HostQueueEntry.query_objects(filter_data),
780 ('host', 'atomic_group', 'job'))
showard34dc5fa2008-04-24 20:58:40 +0000781
782
783def get_num_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000784 """\
785 Get the number of host queue entries associated with this job.
786 """
787 return models.HostQueueEntry.query_count(filter_data)
showard34dc5fa2008-04-24 20:58:40 +0000788
789
showard1e935f12008-07-11 00:11:36 +0000790def get_hqe_percentage_complete(**filter_data):
791 """
showardc92da832009-04-07 18:14:34 +0000792 Computes the fraction of host queue entries matching the given filter data
showard1e935f12008-07-11 00:11:36 +0000793 that are complete.
794 """
795 query = models.HostQueueEntry.query_objects(filter_data)
796 complete_count = query.filter(complete=True).count()
797 total_count = query.count()
798 if total_count == 0:
799 return 1
800 return float(complete_count) / total_count
801
802
showard1a5a4082009-07-28 20:01:37 +0000803# special tasks
804
805def get_special_tasks(**filter_data):
806 return rpc_utils.prepare_rows_as_nested_dicts(
807 models.SpecialTask.query_objects(filter_data),
808 ('host', 'queue_entry'))
809
810
showardc0ac3a72009-07-08 21:14:45 +0000811# support for host detail view
812
813def get_host_queue_entries_and_special_tasks(hostname, query_start=None,
814 query_limit=None):
815 """
816 @returns an interleaved list of HostQueueEntries and SpecialTasks,
817 in approximate run order. each dict contains keys for type, host,
818 job, status, started_on, execution_path, and ID.
819 """
820 total_limit = None
821 if query_limit is not None:
822 total_limit = query_start + query_limit
823 filter_data = {'host__hostname': hostname,
824 'query_limit': total_limit,
825 'sort_by': ['-id']}
826
827 queue_entries = list(models.HostQueueEntry.query_objects(filter_data))
828 special_tasks = list(models.SpecialTask.query_objects(filter_data))
829
830 interleaved_entries = rpc_utils.interleave_entries(queue_entries,
831 special_tasks)
832 if query_start is not None:
833 interleaved_entries = interleaved_entries[query_start:]
834 if query_limit is not None:
835 interleaved_entries = interleaved_entries[:query_limit]
836 return rpc_utils.prepare_for_serialization(interleaved_entries)
837
838
839def get_num_host_queue_entries_and_special_tasks(hostname):
840 filter_data = {'host__hostname': hostname}
841 return (models.HostQueueEntry.query_count(filter_data)
842 + models.SpecialTask.query_count(filter_data))
843
844
showard29f7cd22009-04-29 21:16:24 +0000845# recurring run
846
847def get_recurring(**filter_data):
848 return rpc_utils.prepare_rows_as_nested_dicts(
849 models.RecurringRun.query_objects(filter_data),
850 ('job', 'owner'))
851
852
853def get_num_recurring(**filter_data):
854 return models.RecurringRun.query_count(filter_data)
855
856
857def delete_recurring_runs(**filter_data):
858 to_delete = models.RecurringRun.query_objects(filter_data)
859 to_delete.delete()
860
861
862def create_recurring_run(job_id, start_date, loop_period, loop_count):
showard64a95952010-01-13 21:27:16 +0000863 owner = models.User.current_user().login
showard29f7cd22009-04-29 21:16:24 +0000864 job = models.Job.objects.get(id=job_id)
865 return job.create_recurring_job(start_date=start_date,
866 loop_period=loop_period,
867 loop_count=loop_count,
868 owner=owner)
869
870
mblighe8819cd2008-02-15 16:48:40 +0000871# other
872
showarde0b63622008-08-04 20:58:47 +0000873def echo(data=""):
874 """\
875 Returns a passed in string. For doing a basic test to see if RPC calls
876 can successfully be made.
877 """
878 return data
879
880
showardb7a52fd2009-04-27 20:10:56 +0000881def get_motd():
882 """\
883 Returns the message of the day as a string.
884 """
885 return rpc_utils.get_motd()
886
887
mblighe8819cd2008-02-15 16:48:40 +0000888def get_static_data():
jadmanski0afbb632008-06-06 21:10:57 +0000889 """\
890 Returns a dictionary containing a bunch of data that shouldn't change
891 often and is otherwise inaccessible. This includes:
showardc92da832009-04-07 18:14:34 +0000892
893 priorities: List of job priority choices.
894 default_priority: Default priority value for new jobs.
895 users: Sorted list of all users.
Jiaxi Luo31874592014-06-11 10:36:35 -0700896 labels: Sorted list of labels not start with 'cros-version' and
897 'fw-version'.
showardc92da832009-04-07 18:14:34 +0000898 atomic_groups: Sorted list of all atomic groups.
899 tests: Sorted list of all tests.
900 profilers: Sorted list of all profilers.
901 current_user: Logged-in username.
902 host_statuses: Sorted list of possible Host statuses.
903 job_statuses: Sorted list of possible HostQueueEntry statuses.
Simran Basi7e605742013-11-12 13:43:36 -0800904 job_timeout_default: The default job timeout length in minutes.
showarda1e74b32009-05-12 17:32:04 +0000905 parse_failed_repair_default: Default value for the parse_failed_repair job
Jiaxi Luo31874592014-06-11 10:36:35 -0700906 option.
showardc92da832009-04-07 18:14:34 +0000907 reboot_before_options: A list of valid RebootBefore string enums.
908 reboot_after_options: A list of valid RebootAfter string enums.
909 motd: Server's message of the day.
910 status_dictionary: A mapping from one word job status names to a more
911 informative description.
jadmanski0afbb632008-06-06 21:10:57 +0000912 """
showard21baa452008-10-21 00:08:39 +0000913
914 job_fields = models.Job.get_field_dict()
jamesren76fcf192010-04-21 20:39:50 +0000915 default_drone_set_name = models.DroneSet.default_drone_set_name()
916 drone_sets = ([default_drone_set_name] +
917 sorted(drone_set.name for drone_set in
918 models.DroneSet.objects.exclude(
919 name=default_drone_set_name)))
showard21baa452008-10-21 00:08:39 +0000920
jadmanski0afbb632008-06-06 21:10:57 +0000921 result = {}
Alex Miller7d658cf2013-09-04 16:00:35 -0700922 result['priorities'] = priorities.Priority.choices()
923 default_priority = priorities.Priority.DEFAULT
924 result['default_priority'] = 'Default'
925 result['max_schedulable_priority'] = priorities.Priority.DEFAULT
jadmanski0afbb632008-06-06 21:10:57 +0000926 result['users'] = get_users(sort_by=['login'])
Jiaxi Luo31874592014-06-11 10:36:35 -0700927
928 label_exclude_filters = [{'name__startswith': 'cros-version'},
929 {'name__startswith': 'fw-version'}]
930 result['labels'] = get_labels(
931 label_exclude_filters,
932 sort_by=['-platform', 'name'])
933
showardc92da832009-04-07 18:14:34 +0000934 result['atomic_groups'] = get_atomic_groups(sort_by=['name'])
jadmanski0afbb632008-06-06 21:10:57 +0000935 result['tests'] = get_tests(sort_by=['name'])
showard2b9a88b2008-06-13 20:55:03 +0000936 result['profilers'] = get_profilers(sort_by=['name'])
showard0fc38302008-10-23 00:44:07 +0000937 result['current_user'] = rpc_utils.prepare_for_serialization(
showard64a95952010-01-13 21:27:16 +0000938 models.User.current_user().get_object_dict())
showard2b9a88b2008-06-13 20:55:03 +0000939 result['host_statuses'] = sorted(models.Host.Status.names)
mbligh5a198b92008-12-11 19:33:29 +0000940 result['job_statuses'] = sorted(models.HostQueueEntry.Status.names)
Simran Basi7e605742013-11-12 13:43:36 -0800941 result['job_timeout_mins_default'] = models.Job.DEFAULT_TIMEOUT_MINS
Simran Basi34217022012-11-06 13:43:15 -0800942 result['job_max_runtime_mins_default'] = (
943 models.Job.DEFAULT_MAX_RUNTIME_MINS)
showarda1e74b32009-05-12 17:32:04 +0000944 result['parse_failed_repair_default'] = bool(
945 models.Job.DEFAULT_PARSE_FAILED_REPAIR)
jamesrendd855242010-03-02 22:23:44 +0000946 result['reboot_before_options'] = model_attributes.RebootBefore.names
947 result['reboot_after_options'] = model_attributes.RebootAfter.names
showard8fbae652009-01-20 23:23:10 +0000948 result['motd'] = rpc_utils.get_motd()
jamesren76fcf192010-04-21 20:39:50 +0000949 result['drone_sets_enabled'] = models.DroneSet.drone_sets_enabled()
950 result['drone_sets'] = drone_sets
jamesren4a41e012010-07-16 22:33:48 +0000951 result['parameterized_jobs'] = models.Job.parameterized_jobs_enabled()
showard8ac29b42008-07-17 17:01:55 +0000952
showardd3dc1992009-04-22 21:01:40 +0000953 result['status_dictionary'] = {"Aborted": "Aborted",
showard8ac29b42008-07-17 17:01:55 +0000954 "Verifying": "Verifying Host",
Alex Millerdfff2fd2013-05-28 13:05:06 -0700955 "Provisioning": "Provisioning Host",
showard8ac29b42008-07-17 17:01:55 +0000956 "Pending": "Waiting on other hosts",
957 "Running": "Running autoserv",
958 "Completed": "Autoserv completed",
959 "Failed": "Failed to complete",
showardd823b362008-07-24 16:35:46 +0000960 "Queued": "Queued",
showard5deb6772008-11-04 21:54:33 +0000961 "Starting": "Next in host's queue",
962 "Stopped": "Other host(s) failed verify",
showardd3dc1992009-04-22 21:01:40 +0000963 "Parsing": "Awaiting parse of final results",
showard29f7cd22009-04-29 21:16:24 +0000964 "Gathering": "Gathering log files",
showard8cc058f2009-09-08 16:26:33 +0000965 "Template": "Template job for recurring run",
mbligh4608b002010-01-05 18:22:35 +0000966 "Waiting": "Waiting for scheduler action",
Dan Shi07e09af2013-04-12 09:31:29 -0700967 "Archiving": "Archiving results",
968 "Resetting": "Resetting hosts"}
jadmanski0afbb632008-06-06 21:10:57 +0000969 return result
showard29f7cd22009-04-29 21:16:24 +0000970
971
972def get_server_time():
973 return datetime.datetime.now().strftime("%Y-%m-%d %H:%M")