blob: 3d7cadefa83d49e5d481554e9636851ffaa886fe [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 Luoaac54572014-06-04 13:57:02 -070040from autotest_lib.frontend.tko import rpc_interface as tko_rpc_interface
Jiaxi Luo90190c92014-06-18 12:35:57 -070041from autotest_lib.server.cros.dynamic_suite import tools
mblighe8819cd2008-02-15 16:48:40 +000042
Eric Lid23bc192011-02-09 14:38:57 -080043def get_parameterized_autoupdate_image_url(job):
44 """Get the parameterized autoupdate image url from a parameterized job."""
45 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
46 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
beeps8bb1f7d2013-08-05 01:30:09 -070047 name='image')
Eric Lid23bc192011-02-09 14:38:57 -080048 para_set = job.parameterized_job.parameterizedjobparameter_set
49 job_test_para = para_set.get(test_parameter=image_parameter)
50 return job_test_para.parameter_value
51
52
mblighe8819cd2008-02-15 16:48:40 +000053# labels
54
showard989f25d2008-10-01 11:38:11 +000055def add_label(name, kernel_config=None, platform=None, only_if_needed=None):
showardc92da832009-04-07 18:14:34 +000056 return models.Label.add_object(
57 name=name, kernel_config=kernel_config, platform=platform,
58 only_if_needed=only_if_needed).id
mblighe8819cd2008-02-15 16:48:40 +000059
60
61def modify_label(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +000062 models.Label.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +000063
64
65def delete_label(id):
jadmanski0afbb632008-06-06 21:10:57 +000066 models.Label.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +000067
68
showardbbabf502008-06-06 00:02:02 +000069def label_add_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000070 host_objs = models.Host.smart_get_bulk(hosts)
showardcafd16e2009-05-29 18:37:49 +000071 label = models.Label.smart_get(id)
72 if label.platform:
73 models.Host.check_no_platform(host_objs)
74 label.host_set.add(*host_objs)
showardbbabf502008-06-06 00:02:02 +000075
76
77def label_remove_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000078 host_objs = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +000079 models.Label.smart_get(id).host_set.remove(*host_objs)
showardbbabf502008-06-06 00:02:02 +000080
81
Jiaxi Luo31874592014-06-11 10:36:35 -070082def get_labels(exclude_filters=(), **filter_data):
showardc92da832009-04-07 18:14:34 +000083 """\
Jiaxi Luo31874592014-06-11 10:36:35 -070084 @param exclude_filters: A sequence of dictionaries of filters.
85
showardc92da832009-04-07 18:14:34 +000086 @returns A sequence of nested dictionaries of label information.
87 """
Jiaxi Luo31874592014-06-11 10:36:35 -070088 labels = models.Label.query_objects(filter_data)
89 for exclude_filter in exclude_filters:
90 labels = labels.exclude(**exclude_filter)
91 return rpc_utils.prepare_rows_as_nested_dicts(labels, ('atomic_group',))
showardc92da832009-04-07 18:14:34 +000092
93
94# atomic groups
95
showarde9450c92009-06-30 01:58:52 +000096def add_atomic_group(name, max_number_of_machines=None, description=None):
showardc92da832009-04-07 18:14:34 +000097 return models.AtomicGroup.add_object(
98 name=name, max_number_of_machines=max_number_of_machines,
99 description=description).id
100
101
102def modify_atomic_group(id, **data):
103 models.AtomicGroup.smart_get(id).update_object(data)
104
105
106def delete_atomic_group(id):
107 models.AtomicGroup.smart_get(id).delete()
108
109
110def atomic_group_add_labels(id, labels):
111 label_objs = models.Label.smart_get_bulk(labels)
112 models.AtomicGroup.smart_get(id).label_set.add(*label_objs)
113
114
115def atomic_group_remove_labels(id, labels):
116 label_objs = models.Label.smart_get_bulk(labels)
117 models.AtomicGroup.smart_get(id).label_set.remove(*label_objs)
118
119
120def get_atomic_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000121 return rpc_utils.prepare_for_serialization(
showardc92da832009-04-07 18:14:34 +0000122 models.AtomicGroup.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000123
124
125# hosts
126
showarddf062562008-07-03 19:56:37 +0000127def add_host(hostname, status=None, locked=None, protection=None):
jadmanski0afbb632008-06-06 21:10:57 +0000128 return models.Host.add_object(hostname=hostname, status=status,
showarddf062562008-07-03 19:56:37 +0000129 locked=locked, protection=protection).id
mblighe8819cd2008-02-15 16:48:40 +0000130
131
132def modify_host(id, **data):
showardbe0d8692009-08-20 23:42:44 +0000133 rpc_utils.check_modify_host(data)
showardce7c0922009-09-11 18:39:24 +0000134 host = models.Host.smart_get(id)
135 rpc_utils.check_modify_host_locking(host, data)
136 host.update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000137
138
showard276f9442009-05-20 00:33:16 +0000139def modify_hosts(host_filter_data, update_data):
140 """
showardbe0d8692009-08-20 23:42:44 +0000141 @param host_filter_data: Filters out which hosts to modify.
142 @param update_data: A dictionary with the changes to make to the hosts.
showard276f9442009-05-20 00:33:16 +0000143 """
showardbe0d8692009-08-20 23:42:44 +0000144 rpc_utils.check_modify_host(update_data)
showard276f9442009-05-20 00:33:16 +0000145 hosts = models.Host.query_objects(host_filter_data)
Alex Miller9658a952013-05-14 16:40:02 -0700146 # Check all hosts before changing data for exception safety.
147 for host in hosts:
148 rpc_utils.check_modify_host_locking(host, update_data)
showard276f9442009-05-20 00:33:16 +0000149 for host in hosts:
150 host.update_object(update_data)
151
152
mblighe8819cd2008-02-15 16:48:40 +0000153def host_add_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000154 labels = models.Label.smart_get_bulk(labels)
showardcafd16e2009-05-29 18:37:49 +0000155 host = models.Host.smart_get(id)
156
157 platforms = [label.name for label in labels if label.platform]
158 if len(platforms) > 1:
159 raise model_logic.ValidationError(
160 {'labels': 'Adding more than one platform label: %s' %
161 ', '.join(platforms)})
162 if len(platforms) == 1:
163 models.Host.check_no_platform([host])
164 host.labels.add(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000165
166
167def host_remove_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000168 labels = models.Label.smart_get_bulk(labels)
jadmanski0afbb632008-06-06 21:10:57 +0000169 models.Host.smart_get(id).labels.remove(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000170
171
showard0957a842009-05-11 19:25:08 +0000172def set_host_attribute(attribute, value, **host_filter_data):
173 """
174 @param attribute string name of attribute
175 @param value string, or None to delete an attribute
176 @param host_filter_data filter data to apply to Hosts to choose hosts to act
177 upon
178 """
179 assert host_filter_data # disallow accidental actions on all hosts
180 hosts = models.Host.query_objects(host_filter_data)
181 models.AclGroup.check_for_acl_violation_hosts(hosts)
182
183 for host in hosts:
showardf8b19042009-05-12 17:22:49 +0000184 host.set_or_delete_attribute(attribute, value)
showard0957a842009-05-11 19:25:08 +0000185
186
mblighe8819cd2008-02-15 16:48:40 +0000187def delete_host(id):
jadmanski0afbb632008-06-06 21:10:57 +0000188 models.Host.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000189
190
showard87cc38f2009-08-20 23:37:04 +0000191def get_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000192 exclude_atomic_group_hosts=False, valid_only=True, **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000193 """
194 @param multiple_labels: match hosts in all of the labels given. Should
195 be a list of label names.
196 @param exclude_only_if_needed_labels: Exclude hosts with at least one
197 "only_if_needed" label applied.
198 @param exclude_atomic_group_hosts: Exclude hosts that have one or more
199 atomic group labels associated with them.
jadmanski0afbb632008-06-06 21:10:57 +0000200 """
showard43a3d262008-11-12 18:17:05 +0000201 hosts = rpc_utils.get_host_query(multiple_labels,
202 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000203 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000204 valid_only, filter_data)
showard0957a842009-05-11 19:25:08 +0000205 hosts = list(hosts)
206 models.Host.objects.populate_relationships(hosts, models.Label,
207 'label_list')
208 models.Host.objects.populate_relationships(hosts, models.AclGroup,
209 'acl_list')
210 models.Host.objects.populate_relationships(hosts, models.HostAttribute,
211 'attribute_list')
showard43a3d262008-11-12 18:17:05 +0000212 host_dicts = []
213 for host_obj in hosts:
214 host_dict = host_obj.get_object_dict()
showard0957a842009-05-11 19:25:08 +0000215 host_dict['labels'] = [label.name for label in host_obj.label_list]
showard909c9142009-07-07 20:54:42 +0000216 host_dict['platform'], host_dict['atomic_group'] = (rpc_utils.
217 find_platform_and_atomic_group(host_obj))
showard0957a842009-05-11 19:25:08 +0000218 host_dict['acls'] = [acl.name for acl in host_obj.acl_list]
219 host_dict['attributes'] = dict((attribute.attribute, attribute.value)
220 for attribute in host_obj.attribute_list)
showard43a3d262008-11-12 18:17:05 +0000221 host_dicts.append(host_dict)
222 return rpc_utils.prepare_for_serialization(host_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000223
224
showard87cc38f2009-08-20 23:37:04 +0000225def get_num_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000226 exclude_atomic_group_hosts=False, valid_only=True,
227 **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000228 """
229 Same parameters as get_hosts().
230
231 @returns The number of matching hosts.
232 """
showard43a3d262008-11-12 18:17:05 +0000233 hosts = rpc_utils.get_host_query(multiple_labels,
234 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000235 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000236 valid_only, filter_data)
showard43a3d262008-11-12 18:17:05 +0000237 return hosts.count()
showard1385b162008-03-13 15:59:40 +0000238
mblighe8819cd2008-02-15 16:48:40 +0000239
240# tests
241
showard909c7a62008-07-15 21:52:38 +0000242def add_test(name, test_type, path, author=None, dependencies=None,
showard3d9899a2008-07-31 02:11:58 +0000243 experimental=True, run_verify=None, test_class=None,
showard909c7a62008-07-15 21:52:38 +0000244 test_time=None, test_category=None, description=None,
245 sync_count=1):
jadmanski0afbb632008-06-06 21:10:57 +0000246 return models.Test.add_object(name=name, test_type=test_type, path=path,
showard909c7a62008-07-15 21:52:38 +0000247 author=author, dependencies=dependencies,
248 experimental=experimental,
249 run_verify=run_verify, test_time=test_time,
250 test_category=test_category,
251 sync_count=sync_count,
jadmanski0afbb632008-06-06 21:10:57 +0000252 test_class=test_class,
253 description=description).id
mblighe8819cd2008-02-15 16:48:40 +0000254
255
256def modify_test(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000257 models.Test.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000258
259
260def delete_test(id):
jadmanski0afbb632008-06-06 21:10:57 +0000261 models.Test.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000262
263
264def get_tests(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000265 return rpc_utils.prepare_for_serialization(
266 models.Test.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000267
268
showard2b9a88b2008-06-13 20:55:03 +0000269# profilers
270
271def add_profiler(name, description=None):
272 return models.Profiler.add_object(name=name, description=description).id
273
274
275def modify_profiler(id, **data):
276 models.Profiler.smart_get(id).update_object(data)
277
278
279def delete_profiler(id):
280 models.Profiler.smart_get(id).delete()
281
282
283def get_profilers(**filter_data):
284 return rpc_utils.prepare_for_serialization(
285 models.Profiler.list_objects(filter_data))
286
287
mblighe8819cd2008-02-15 16:48:40 +0000288# users
289
290def add_user(login, access_level=None):
jadmanski0afbb632008-06-06 21:10:57 +0000291 return models.User.add_object(login=login, access_level=access_level).id
mblighe8819cd2008-02-15 16:48:40 +0000292
293
294def modify_user(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000295 models.User.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000296
297
298def delete_user(id):
jadmanski0afbb632008-06-06 21:10:57 +0000299 models.User.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000300
301
302def get_users(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000303 return rpc_utils.prepare_for_serialization(
304 models.User.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000305
306
307# acl groups
308
309def add_acl_group(name, description=None):
showard04f2cd82008-07-25 20:53:31 +0000310 group = models.AclGroup.add_object(name=name, description=description)
showard64a95952010-01-13 21:27:16 +0000311 group.users.add(models.User.current_user())
showard04f2cd82008-07-25 20:53:31 +0000312 return group.id
mblighe8819cd2008-02-15 16:48:40 +0000313
314
315def modify_acl_group(id, **data):
showard04f2cd82008-07-25 20:53:31 +0000316 group = models.AclGroup.smart_get(id)
317 group.check_for_acl_violation_acl_group()
318 group.update_object(data)
319 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000320
321
322def acl_group_add_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000323 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000324 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000325 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000326 group.users.add(*users)
mblighe8819cd2008-02-15 16:48:40 +0000327
328
329def acl_group_remove_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000330 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000331 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000332 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000333 group.users.remove(*users)
showard04f2cd82008-07-25 20:53:31 +0000334 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000335
336
337def acl_group_add_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000338 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000339 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000340 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000341 group.hosts.add(*hosts)
showard08f981b2008-06-24 21:59:03 +0000342 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000343
344
345def acl_group_remove_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000346 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000347 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000348 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000349 group.hosts.remove(*hosts)
showard08f981b2008-06-24 21:59:03 +0000350 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000351
352
353def delete_acl_group(id):
jadmanski0afbb632008-06-06 21:10:57 +0000354 models.AclGroup.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000355
356
357def get_acl_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000358 acl_groups = models.AclGroup.list_objects(filter_data)
359 for acl_group in acl_groups:
360 acl_group_obj = models.AclGroup.objects.get(id=acl_group['id'])
361 acl_group['users'] = [user.login
362 for user in acl_group_obj.users.all()]
363 acl_group['hosts'] = [host.hostname
364 for host in acl_group_obj.hosts.all()]
365 return rpc_utils.prepare_for_serialization(acl_groups)
mblighe8819cd2008-02-15 16:48:40 +0000366
367
368# jobs
369
mbligh120351e2009-01-24 01:40:45 +0000370def generate_control_file(tests=(), kernel=None, label=None, profilers=(),
showard91f85102009-10-12 20:34:52 +0000371 client_control_file='', use_container=False,
showard232b7ae2009-11-10 00:46:48 +0000372 profile_only=None, upload_kernel_config=False):
jadmanski0afbb632008-06-06 21:10:57 +0000373 """
mbligh120351e2009-01-24 01:40:45 +0000374 Generates a client-side control file to load a kernel and run tests.
375
376 @param tests List of tests to run.
mbligha3c58d22009-08-24 22:01:51 +0000377 @param kernel A list of kernel info dictionaries configuring which kernels
378 to boot for this job and other options for them
mbligh120351e2009-01-24 01:40:45 +0000379 @param label Name of label to grab kernel config from.
380 @param profilers List of profilers to activate during the job.
381 @param client_control_file The contents of a client-side control file to
382 run at the end of all tests. If this is supplied, all tests must be
383 client side.
384 TODO: in the future we should support server control files directly
385 to wrap with a kernel. That'll require changing the parameter
386 name and adding a boolean to indicate if it is a client or server
387 control file.
388 @param use_container unused argument today. TODO: Enable containers
389 on the host during a client side test.
showard91f85102009-10-12 20:34:52 +0000390 @param profile_only A boolean that indicates what default profile_only
391 mode to use in the control file. Passing None will generate a
392 control file that does not explcitly set the default mode at all.
showard232b7ae2009-11-10 00:46:48 +0000393 @param upload_kernel_config: if enabled it will generate server control
394 file code that uploads the kernel config file to the client and
395 tells the client of the new (local) path when compiling the kernel;
396 the tests must be server side tests
mbligh120351e2009-01-24 01:40:45 +0000397
398 @returns a dict with the following keys:
399 control_file: str, The control file text.
400 is_server: bool, is the control file a server-side control file?
401 synch_count: How many machines the job uses per autoserv execution.
402 synch_count == 1 means the job is asynchronous.
403 dependencies: A list of the names of labels on which the job depends.
404 """
showardd86debe2009-06-10 17:37:56 +0000405 if not tests and not client_control_file:
showard2bab8f42008-11-12 18:15:22 +0000406 return dict(control_file='', is_server=False, synch_count=1,
showard989f25d2008-10-01 11:38:11 +0000407 dependencies=[])
mblighe8819cd2008-02-15 16:48:40 +0000408
showard989f25d2008-10-01 11:38:11 +0000409 cf_info, test_objects, profiler_objects, label = (
showard2b9a88b2008-06-13 20:55:03 +0000410 rpc_utils.prepare_generate_control_file(tests, kernel, label,
411 profilers))
showard989f25d2008-10-01 11:38:11 +0000412 cf_info['control_file'] = control_file.generate_control(
mbligha3c58d22009-08-24 22:01:51 +0000413 tests=test_objects, kernels=kernel, platform=label,
mbligh120351e2009-01-24 01:40:45 +0000414 profilers=profiler_objects, is_server=cf_info['is_server'],
showard232b7ae2009-11-10 00:46:48 +0000415 client_control_file=client_control_file, profile_only=profile_only,
416 upload_kernel_config=upload_kernel_config)
showard989f25d2008-10-01 11:38:11 +0000417 return cf_info
mblighe8819cd2008-02-15 16:48:40 +0000418
419
jamesren4a41e012010-07-16 22:33:48 +0000420def create_parameterized_job(name, priority, test, parameters, kernel=None,
421 label=None, profilers=(), profiler_parameters=None,
422 use_container=False, profile_only=None,
423 upload_kernel_config=False, hosts=(),
424 meta_hosts=(), one_time_hosts=(),
425 atomic_group_name=None, synch_count=None,
426 is_template=False, timeout=None,
Simran Basi7e605742013-11-12 13:43:36 -0800427 timeout_mins=None, max_runtime_mins=None,
428 run_verify=False, email_list='', dependencies=(),
429 reboot_before=None, reboot_after=None,
430 parse_failed_repair=None, hostless=False,
431 keyvals=None, drone_set=None, run_reset=True):
jamesren4a41e012010-07-16 22:33:48 +0000432 """
433 Creates and enqueues a parameterized job.
434
435 Most parameters a combination of the parameters for generate_control_file()
436 and create_job(), with the exception of:
437
438 @param test name or ID of the test to run
439 @param parameters a map of parameter name ->
440 tuple of (param value, param type)
441 @param profiler_parameters a dictionary of parameters for the profilers:
442 key: profiler name
443 value: dict of param name -> tuple of
444 (param value,
445 param type)
446 """
447 # Save the values of the passed arguments here. What we're going to do with
448 # them is pass them all to rpc_utils.get_create_job_common_args(), which
449 # will extract the subset of these arguments that apply for
450 # rpc_utils.create_job_common(), which we then pass in to that function.
451 args = locals()
452
453 # Set up the parameterized job configs
454 test_obj = models.Test.smart_get(test)
Aviv Keshet3dd8beb2013-05-13 17:36:04 -0700455 control_type = test_obj.test_type
jamesren4a41e012010-07-16 22:33:48 +0000456
457 try:
458 label = models.Label.smart_get(label)
459 except models.Label.DoesNotExist:
460 label = None
461
462 kernel_objs = models.Kernel.create_kernels(kernel)
463 profiler_objs = [models.Profiler.smart_get(profiler)
464 for profiler in profilers]
465
466 parameterized_job = models.ParameterizedJob.objects.create(
467 test=test_obj, label=label, use_container=use_container,
468 profile_only=profile_only,
469 upload_kernel_config=upload_kernel_config)
470 parameterized_job.kernels.add(*kernel_objs)
471
472 for profiler in profiler_objs:
473 parameterized_profiler = models.ParameterizedJobProfiler.objects.create(
474 parameterized_job=parameterized_job,
475 profiler=profiler)
476 profiler_params = profiler_parameters.get(profiler.name, {})
477 for name, (value, param_type) in profiler_params.iteritems():
478 models.ParameterizedJobProfilerParameter.objects.create(
479 parameterized_job_profiler=parameterized_profiler,
480 parameter_name=name,
481 parameter_value=value,
482 parameter_type=param_type)
483
484 try:
485 for parameter in test_obj.testparameter_set.all():
486 if parameter.name in parameters:
487 param_value, param_type = parameters.pop(parameter.name)
488 parameterized_job.parameterizedjobparameter_set.create(
489 test_parameter=parameter, parameter_value=param_value,
490 parameter_type=param_type)
491
492 if parameters:
493 raise Exception('Extra parameters remain: %r' % parameters)
494
495 return rpc_utils.create_job_common(
496 parameterized_job=parameterized_job.id,
497 control_type=control_type,
498 **rpc_utils.get_create_job_common_args(args))
499 except:
500 parameterized_job.delete()
501 raise
502
503
Simran Basib6ec8ae2014-04-23 12:05:08 -0700504def create_job_page_handler(name, priority, control_file, control_type,
505 image=None, hostless=False, **kwargs):
506 """\
507 Create and enqueue a job.
508
509 @param name name of this job
510 @param priority Integer priority of this job. Higher is more important.
511 @param control_file String contents of the control file.
512 @param control_type Type of control file, Client or Server.
513 @param kwargs extra args that will be required by create_suite_job or
514 create_job.
515
516 @returns The created Job id number.
517 """
518 control_file = rpc_utils.encode_ascii(control_file)
Jiaxi Luodd67beb2014-07-18 16:28:31 -0700519 if not control_file:
520 raise model_logic.ValidationError({
521 'control_file' : "Control file cannot be empty"})
Simran Basib6ec8ae2014-04-23 12:05:08 -0700522
523 if image and hostless:
524 return site_rpc_interface.create_suite_job(
525 name=name, control_file=control_file, priority=priority,
526 build=image, **kwargs)
527 return create_job(name, priority, control_file, control_type, image=image,
528 hostless=hostless, **kwargs)
529
530
showard12f3e322009-05-13 21:27:42 +0000531def create_job(name, priority, control_file, control_type,
532 hosts=(), meta_hosts=(), one_time_hosts=(),
533 atomic_group_name=None, synch_count=None, is_template=False,
Simran Basi7e605742013-11-12 13:43:36 -0800534 timeout=None, timeout_mins=None, max_runtime_mins=None,
535 run_verify=False, email_list='', dependencies=(),
536 reboot_before=None, reboot_after=None, parse_failed_repair=None,
537 hostless=False, keyvals=None, drone_set=None, image=None,
Jiaxi Luo90190c92014-06-18 12:35:57 -0700538 parent_job_id=None, test_retry=0, run_reset=True, args=(),
539 **kwargs):
jadmanski0afbb632008-06-06 21:10:57 +0000540 """\
541 Create and enqueue a job.
mblighe8819cd2008-02-15 16:48:40 +0000542
showarda1e74b32009-05-12 17:32:04 +0000543 @param name name of this job
Alex Miller7d658cf2013-09-04 16:00:35 -0700544 @param priority Integer priority of this job. Higher is more important.
showarda1e74b32009-05-12 17:32:04 +0000545 @param control_file String contents of the control file.
546 @param control_type Type of control file, Client or Server.
547 @param synch_count How many machines the job uses per autoserv execution.
Jiaxi Luo90190c92014-06-18 12:35:57 -0700548 synch_count == 1 means the job is asynchronous. If an atomic group is
549 given this value is treated as a minimum.
showarda1e74b32009-05-12 17:32:04 +0000550 @param is_template If true then create a template job.
551 @param timeout Hours after this call returns until the job times out.
Simran Basi7e605742013-11-12 13:43:36 -0800552 @param timeout_mins Minutes after this call returns until the job times
Jiaxi Luo90190c92014-06-18 12:35:57 -0700553 out.
Simran Basi34217022012-11-06 13:43:15 -0800554 @param max_runtime_mins Minutes from job starting time until job times out
showarda1e74b32009-05-12 17:32:04 +0000555 @param run_verify Should the host be verified before running the test?
556 @param email_list String containing emails to mail when the job is done
557 @param dependencies List of label names on which this job depends
558 @param reboot_before Never, If dirty, or Always
559 @param reboot_after Never, If all tests passed, or Always
560 @param parse_failed_repair if true, results of failed repairs launched by
Jiaxi Luo90190c92014-06-18 12:35:57 -0700561 this job will be parsed as part of the job.
showarda9545c02009-12-18 22:44:26 +0000562 @param hostless if true, create a hostless job
showardc1a98d12010-01-15 00:22:22 +0000563 @param keyvals dict of keyvals to associate with the job
showarda1e74b32009-05-12 17:32:04 +0000564 @param hosts List of hosts to run job on.
565 @param meta_hosts List where each entry is a label name, and for each entry
Jiaxi Luo90190c92014-06-18 12:35:57 -0700566 one host will be chosen from that label to run the job on.
showarda1e74b32009-05-12 17:32:04 +0000567 @param one_time_hosts List of hosts not in the database to run the job on.
568 @param atomic_group_name The name of an atomic group to schedule the job on.
jamesren76fcf192010-04-21 20:39:50 +0000569 @param drone_set The name of the drone set to run this test on.
Paul Pendlebury5a8c6ad2011-02-01 07:20:17 -0800570 @param image OS image to install before running job.
Aviv Keshet0b9cfc92013-02-05 11:36:02 -0800571 @param parent_job_id id of a job considered to be parent of created job.
Simran Basib6ec8ae2014-04-23 12:05:08 -0700572 @param test_retry Number of times to retry test if the test did not
Jiaxi Luo90190c92014-06-18 12:35:57 -0700573 complete successfully. (optional, default: 0)
Simran Basib6ec8ae2014-04-23 12:05:08 -0700574 @param run_reset Should the host be reset before running the test?
Jiaxi Luo90190c92014-06-18 12:35:57 -0700575 @param args A list of args to be injected into control file.
Simran Basib6ec8ae2014-04-23 12:05:08 -0700576 @param kwargs extra keyword args. NOT USED.
showardc92da832009-04-07 18:14:34 +0000577
578 @returns The created Job id number.
jadmanski0afbb632008-06-06 21:10:57 +0000579 """
Jiaxi Luo90190c92014-06-18 12:35:57 -0700580 if args:
581 control_file = tools.inject_vars({'args': args}, control_file)
582
Simran Basiab5a1bf2014-05-28 15:39:44 -0700583 if image is None:
584 return rpc_utils.create_job_common(
585 **rpc_utils.get_create_job_common_args(locals()))
586
587 # When image is supplied use a known parameterized test already in the
588 # database to pass the OS image path from the front end, through the
589 # scheduler, and finally to autoserv as the --image parameter.
590
591 # The test autoupdate_ParameterizedJob is in afe_autotests and used to
592 # instantiate a Test object and from there a ParameterizedJob.
593 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
594 known_parameterized_job = models.ParameterizedJob.objects.create(
595 test=known_test_obj)
596
597 # autoupdate_ParameterizedJob has a single parameter, the image parameter,
598 # stored in the table afe_test_parameters. We retrieve and set this
599 # instance of the parameter to the OS image path.
600 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
601 name='image')
602 known_parameterized_job.parameterizedjobparameter_set.create(
603 test_parameter=image_parameter, parameter_value=image,
604 parameter_type='string')
605
606 # By passing a parameterized_job to create_job_common the job entry in
607 # the afe_jobs table will have the field parameterized_job_id set.
608 # The scheduler uses this id in the afe_parameterized_jobs table to
609 # match this job to our known test, and then with the
610 # afe_parameterized_job_parameters table to get the actual image path.
jamesren4a41e012010-07-16 22:33:48 +0000611 return rpc_utils.create_job_common(
Simran Basiab5a1bf2014-05-28 15:39:44 -0700612 parameterized_job=known_parameterized_job.id,
jamesren4a41e012010-07-16 22:33:48 +0000613 **rpc_utils.get_create_job_common_args(locals()))
mblighe8819cd2008-02-15 16:48:40 +0000614
615
showard9dbdcda2008-10-14 17:34:36 +0000616def abort_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000617 """\
showard9dbdcda2008-10-14 17:34:36 +0000618 Abort a set of host queue entries.
jadmanski0afbb632008-06-06 21:10:57 +0000619 """
showard9dbdcda2008-10-14 17:34:36 +0000620 query = models.HostQueueEntry.query_objects(filter_data)
beepsfaecbce2013-10-29 11:35:10 -0700621
622 # Dont allow aborts on:
623 # 1. Jobs that have already completed (whether or not they were aborted)
624 # 2. Jobs that we have already been aborted (but may not have completed)
625 query = query.filter(complete=False).filter(aborted=False)
showarddc817512008-11-12 18:16:41 +0000626 models.AclGroup.check_abort_permissions(query)
showard9dbdcda2008-10-14 17:34:36 +0000627 host_queue_entries = list(query.select_related())
showard2bab8f42008-11-12 18:15:22 +0000628 rpc_utils.check_abort_synchronous_jobs(host_queue_entries)
mblighe8819cd2008-02-15 16:48:40 +0000629
Simran Basic1b26762013-06-26 14:23:21 -0700630 models.HostQueueEntry.abort_host_queue_entries(host_queue_entries)
showard9d821ab2008-07-11 16:54:29 +0000631
632
beeps8bb1f7d2013-08-05 01:30:09 -0700633def abort_special_tasks(**filter_data):
634 """\
635 Abort the special task, or tasks, specified in the filter.
636 """
637 query = models.SpecialTask.query_objects(filter_data)
638 special_tasks = query.filter(is_active=True)
639 for task in special_tasks:
640 task.abort()
641
642
Simran Basi73dae552013-02-25 14:57:46 -0800643def _call_special_tasks_on_hosts(task, hosts):
644 """\
645 Schedules a set of hosts for a special task.
646
647 @returns A list of hostnames that a special task was created for.
648 """
649 models.AclGroup.check_for_acl_violation_hosts(hosts)
650 for host in hosts:
651 models.SpecialTask.schedule_special_task(host, task)
652 return list(sorted(host.hostname for host in hosts))
653
654
showard1ff7b2e2009-05-15 23:17:18 +0000655def reverify_hosts(**filter_data):
656 """\
657 Schedules a set of hosts for verify.
mbligh4e545a52009-12-19 05:30:39 +0000658
659 @returns A list of hostnames that a verify task was created for.
showard1ff7b2e2009-05-15 23:17:18 +0000660 """
Simran Basi73dae552013-02-25 14:57:46 -0800661 return _call_special_tasks_on_hosts(models.SpecialTask.Task.VERIFY,
662 models.Host.query_objects(filter_data))
663
664
665def repair_hosts(**filter_data):
666 """\
667 Schedules a set of hosts for repair.
668
669 @returns A list of hostnames that a repair task was created for.
670 """
671 return _call_special_tasks_on_hosts(models.SpecialTask.Task.REPAIR,
672 models.Host.query_objects(filter_data))
showard1ff7b2e2009-05-15 23:17:18 +0000673
674
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700675def get_jobs(not_yet_run=False, running=False, finished=False,
676 suite=False, sub=False, standalone=False, **filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000677 """\
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700678 Extra status filter args for get_jobs:
jadmanski0afbb632008-06-06 21:10:57 +0000679 -not_yet_run: Include only jobs that have not yet started running.
680 -running: Include only jobs that have start running but for which not
681 all hosts have completed.
682 -finished: Include only jobs for which all hosts have completed (or
683 aborted).
684 At most one of these three fields should be specified.
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700685
686 Extra type filter args for get_jobs:
687 -suite: Include only jobs with child jobs.
688 -sub: Include only jobs with a parent job.
689 -standalone: Inlcude only jobs with no child or parent jobs.
690 At most one of these three fields should be specified.
jadmanski0afbb632008-06-06 21:10:57 +0000691 """
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700692 extra_args = rpc_utils.extra_job_status_filters(not_yet_run,
693 running,
694 finished)
695 filter_data['extra_args'] = rpc_utils.extra_job_type_filters(extra_args,
696 suite,
697 sub,
698 standalone)
showard0957a842009-05-11 19:25:08 +0000699 job_dicts = []
700 jobs = list(models.Job.query_objects(filter_data))
701 models.Job.objects.populate_relationships(jobs, models.Label,
702 'dependencies')
showardc1a98d12010-01-15 00:22:22 +0000703 models.Job.objects.populate_relationships(jobs, models.JobKeyval, 'keyvals')
showard0957a842009-05-11 19:25:08 +0000704 for job in jobs:
705 job_dict = job.get_object_dict()
706 job_dict['dependencies'] = ','.join(label.name
707 for label in job.dependencies)
showardc1a98d12010-01-15 00:22:22 +0000708 job_dict['keyvals'] = dict((keyval.key, keyval.value)
709 for keyval in job.keyvals)
Eric Lid23bc192011-02-09 14:38:57 -0800710 if job.parameterized_job:
711 job_dict['image'] = get_parameterized_autoupdate_image_url(job)
showard0957a842009-05-11 19:25:08 +0000712 job_dicts.append(job_dict)
713 return rpc_utils.prepare_for_serialization(job_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000714
715
716def get_num_jobs(not_yet_run=False, running=False, finished=False,
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700717 suite=False, sub=False, standalone=False,
jadmanski0afbb632008-06-06 21:10:57 +0000718 **filter_data):
719 """\
720 See get_jobs() for documentation of extra filter parameters.
721 """
Jiaxi Luo15cbf372014-07-01 19:20:20 -0700722 extra_args = rpc_utils.extra_job_status_filters(not_yet_run,
723 running,
724 finished)
725 filter_data['extra_args'] = rpc_utils.extra_job_type_filters(extra_args,
726 suite,
727 sub,
728 standalone)
jadmanski0afbb632008-06-06 21:10:57 +0000729 return models.Job.query_count(filter_data)
mblighe8819cd2008-02-15 16:48:40 +0000730
731
mblighe8819cd2008-02-15 16:48:40 +0000732def get_jobs_summary(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000733 """\
Jiaxi Luoaac54572014-06-04 13:57:02 -0700734 Like get_jobs(), but adds 'status_counts' and 'result_counts' field.
735
736 'status_counts' filed is a dictionary mapping status strings to the number
737 of hosts currently with that status, i.e. {'Queued' : 4, 'Running' : 2}.
738
739 'result_counts' field is piped to tko's rpc_interface and has the return
740 format specified under get_group_counts.
jadmanski0afbb632008-06-06 21:10:57 +0000741 """
742 jobs = get_jobs(**filter_data)
743 ids = [job['id'] for job in jobs]
744 all_status_counts = models.Job.objects.get_status_counts(ids)
745 for job in jobs:
746 job['status_counts'] = all_status_counts[job['id']]
Jiaxi Luoaac54572014-06-04 13:57:02 -0700747 job['result_counts'] = tko_rpc_interface.get_status_counts(
748 ['afe_job_id', 'afe_job_id'],
749 header_groups=[['afe_job_id'], ['afe_job_id']],
750 **{'afe_job_id': job['id']})
jadmanski0afbb632008-06-06 21:10:57 +0000751 return rpc_utils.prepare_for_serialization(jobs)
mblighe8819cd2008-02-15 16:48:40 +0000752
753
showarda965cef2009-05-15 23:17:41 +0000754def get_info_for_clone(id, preserve_metahosts, queue_entry_filter_data=None):
showarda8709c52008-07-03 19:44:54 +0000755 """\
756 Retrieves all the information needed to clone a job.
757 """
showarda8709c52008-07-03 19:44:54 +0000758 job = models.Job.objects.get(id=id)
showard29f7cd22009-04-29 21:16:24 +0000759 job_info = rpc_utils.get_job_info(job,
showarda965cef2009-05-15 23:17:41 +0000760 preserve_metahosts,
761 queue_entry_filter_data)
showard945072f2008-09-03 20:34:59 +0000762
showardd9992fe2008-07-31 02:15:03 +0000763 host_dicts = []
showard29f7cd22009-04-29 21:16:24 +0000764 for host in job_info['hosts']:
765 host_dict = get_hosts(id=host.id)[0]
766 other_labels = host_dict['labels']
767 if host_dict['platform']:
768 other_labels.remove(host_dict['platform'])
769 host_dict['other_labels'] = ', '.join(other_labels)
showardd9992fe2008-07-31 02:15:03 +0000770 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000771
showard29f7cd22009-04-29 21:16:24 +0000772 for host in job_info['one_time_hosts']:
773 host_dict = dict(hostname=host.hostname,
774 id=host.id,
775 platform='(one-time host)',
776 locked_text='')
777 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000778
showard4d077562009-05-08 18:24:36 +0000779 # convert keys from Label objects to strings (names of labels)
showard29f7cd22009-04-29 21:16:24 +0000780 meta_host_counts = dict((meta_host.name, count) for meta_host, count
showard4d077562009-05-08 18:24:36 +0000781 in job_info['meta_host_counts'].iteritems())
showard29f7cd22009-04-29 21:16:24 +0000782
783 info = dict(job=job.get_object_dict(),
784 meta_host_counts=meta_host_counts,
785 hosts=host_dicts)
786 info['job']['dependencies'] = job_info['dependencies']
787 if job_info['atomic_group']:
788 info['atomic_group_name'] = (job_info['atomic_group']).name
789 else:
790 info['atomic_group_name'] = None
jamesren2275ef12010-04-12 18:25:06 +0000791 info['hostless'] = job_info['hostless']
jamesren76fcf192010-04-21 20:39:50 +0000792 info['drone_set'] = job.drone_set and job.drone_set.name
showarda8709c52008-07-03 19:44:54 +0000793
Eric Lid23bc192011-02-09 14:38:57 -0800794 if job.parameterized_job:
795 info['job']['image'] = get_parameterized_autoupdate_image_url(job)
796
showarda8709c52008-07-03 19:44:54 +0000797 return rpc_utils.prepare_for_serialization(info)
798
799
showard34dc5fa2008-04-24 20:58:40 +0000800# host queue entries
801
802def get_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000803 """\
showardc92da832009-04-07 18:14:34 +0000804 @returns A sequence of nested dictionaries of host and job information.
jadmanski0afbb632008-06-06 21:10:57 +0000805 """
showardc92da832009-04-07 18:14:34 +0000806 return rpc_utils.prepare_rows_as_nested_dicts(
807 models.HostQueueEntry.query_objects(filter_data),
808 ('host', 'atomic_group', 'job'))
showard34dc5fa2008-04-24 20:58:40 +0000809
810
811def get_num_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000812 """\
813 Get the number of host queue entries associated with this job.
814 """
815 return models.HostQueueEntry.query_count(filter_data)
showard34dc5fa2008-04-24 20:58:40 +0000816
817
showard1e935f12008-07-11 00:11:36 +0000818def get_hqe_percentage_complete(**filter_data):
819 """
showardc92da832009-04-07 18:14:34 +0000820 Computes the fraction of host queue entries matching the given filter data
showard1e935f12008-07-11 00:11:36 +0000821 that are complete.
822 """
823 query = models.HostQueueEntry.query_objects(filter_data)
824 complete_count = query.filter(complete=True).count()
825 total_count = query.count()
826 if total_count == 0:
827 return 1
828 return float(complete_count) / total_count
829
830
showard1a5a4082009-07-28 20:01:37 +0000831# special tasks
832
833def get_special_tasks(**filter_data):
834 return rpc_utils.prepare_rows_as_nested_dicts(
835 models.SpecialTask.query_objects(filter_data),
836 ('host', 'queue_entry'))
837
838
showardc0ac3a72009-07-08 21:14:45 +0000839# support for host detail view
840
Jiaxi Luo79ce6422014-06-13 17:08:09 -0700841def get_host_queue_entries_and_special_tasks(host_id, query_start=None,
showardc0ac3a72009-07-08 21:14:45 +0000842 query_limit=None):
843 """
844 @returns an interleaved list of HostQueueEntries and SpecialTasks,
845 in approximate run order. each dict contains keys for type, host,
846 job, status, started_on, execution_path, and ID.
847 """
848 total_limit = None
849 if query_limit is not None:
850 total_limit = query_start + query_limit
Jiaxi Luo79ce6422014-06-13 17:08:09 -0700851 filter_data = {'host': host_id,
showardc0ac3a72009-07-08 21:14:45 +0000852 'query_limit': total_limit,
853 'sort_by': ['-id']}
854
855 queue_entries = list(models.HostQueueEntry.query_objects(filter_data))
856 special_tasks = list(models.SpecialTask.query_objects(filter_data))
857
858 interleaved_entries = rpc_utils.interleave_entries(queue_entries,
859 special_tasks)
860 if query_start is not None:
861 interleaved_entries = interleaved_entries[query_start:]
862 if query_limit is not None:
863 interleaved_entries = interleaved_entries[:query_limit]
864 return rpc_utils.prepare_for_serialization(interleaved_entries)
865
866
Jiaxi Luo79ce6422014-06-13 17:08:09 -0700867def get_num_host_queue_entries_and_special_tasks(host_id):
868 filter_data = {'host': host_id}
showardc0ac3a72009-07-08 21:14:45 +0000869 return (models.HostQueueEntry.query_count(filter_data)
870 + models.SpecialTask.query_count(filter_data))
871
872
showard29f7cd22009-04-29 21:16:24 +0000873# recurring run
874
875def get_recurring(**filter_data):
876 return rpc_utils.prepare_rows_as_nested_dicts(
877 models.RecurringRun.query_objects(filter_data),
878 ('job', 'owner'))
879
880
881def get_num_recurring(**filter_data):
882 return models.RecurringRun.query_count(filter_data)
883
884
885def delete_recurring_runs(**filter_data):
886 to_delete = models.RecurringRun.query_objects(filter_data)
887 to_delete.delete()
888
889
890def create_recurring_run(job_id, start_date, loop_period, loop_count):
showard64a95952010-01-13 21:27:16 +0000891 owner = models.User.current_user().login
showard29f7cd22009-04-29 21:16:24 +0000892 job = models.Job.objects.get(id=job_id)
893 return job.create_recurring_job(start_date=start_date,
894 loop_period=loop_period,
895 loop_count=loop_count,
896 owner=owner)
897
898
mblighe8819cd2008-02-15 16:48:40 +0000899# other
900
showarde0b63622008-08-04 20:58:47 +0000901def echo(data=""):
902 """\
903 Returns a passed in string. For doing a basic test to see if RPC calls
904 can successfully be made.
905 """
906 return data
907
908
showardb7a52fd2009-04-27 20:10:56 +0000909def get_motd():
910 """\
911 Returns the message of the day as a string.
912 """
913 return rpc_utils.get_motd()
914
915
mblighe8819cd2008-02-15 16:48:40 +0000916def get_static_data():
jadmanski0afbb632008-06-06 21:10:57 +0000917 """\
918 Returns a dictionary containing a bunch of data that shouldn't change
919 often and is otherwise inaccessible. This includes:
showardc92da832009-04-07 18:14:34 +0000920
921 priorities: List of job priority choices.
922 default_priority: Default priority value for new jobs.
923 users: Sorted list of all users.
Jiaxi Luo31874592014-06-11 10:36:35 -0700924 labels: Sorted list of labels not start with 'cros-version' and
925 'fw-version'.
showardc92da832009-04-07 18:14:34 +0000926 atomic_groups: Sorted list of all atomic groups.
927 tests: Sorted list of all tests.
928 profilers: Sorted list of all profilers.
929 current_user: Logged-in username.
930 host_statuses: Sorted list of possible Host statuses.
931 job_statuses: Sorted list of possible HostQueueEntry statuses.
Simran Basi7e605742013-11-12 13:43:36 -0800932 job_timeout_default: The default job timeout length in minutes.
showarda1e74b32009-05-12 17:32:04 +0000933 parse_failed_repair_default: Default value for the parse_failed_repair job
Jiaxi Luo31874592014-06-11 10:36:35 -0700934 option.
showardc92da832009-04-07 18:14:34 +0000935 reboot_before_options: A list of valid RebootBefore string enums.
936 reboot_after_options: A list of valid RebootAfter string enums.
937 motd: Server's message of the day.
938 status_dictionary: A mapping from one word job status names to a more
939 informative description.
jadmanski0afbb632008-06-06 21:10:57 +0000940 """
showard21baa452008-10-21 00:08:39 +0000941
942 job_fields = models.Job.get_field_dict()
jamesren76fcf192010-04-21 20:39:50 +0000943 default_drone_set_name = models.DroneSet.default_drone_set_name()
944 drone_sets = ([default_drone_set_name] +
945 sorted(drone_set.name for drone_set in
946 models.DroneSet.objects.exclude(
947 name=default_drone_set_name)))
showard21baa452008-10-21 00:08:39 +0000948
jadmanski0afbb632008-06-06 21:10:57 +0000949 result = {}
Alex Miller7d658cf2013-09-04 16:00:35 -0700950 result['priorities'] = priorities.Priority.choices()
951 default_priority = priorities.Priority.DEFAULT
952 result['default_priority'] = 'Default'
953 result['max_schedulable_priority'] = priorities.Priority.DEFAULT
jadmanski0afbb632008-06-06 21:10:57 +0000954 result['users'] = get_users(sort_by=['login'])
Jiaxi Luo31874592014-06-11 10:36:35 -0700955
956 label_exclude_filters = [{'name__startswith': 'cros-version'},
957 {'name__startswith': 'fw-version'}]
958 result['labels'] = get_labels(
959 label_exclude_filters,
960 sort_by=['-platform', 'name'])
961
showardc92da832009-04-07 18:14:34 +0000962 result['atomic_groups'] = get_atomic_groups(sort_by=['name'])
jadmanski0afbb632008-06-06 21:10:57 +0000963 result['tests'] = get_tests(sort_by=['name'])
showard2b9a88b2008-06-13 20:55:03 +0000964 result['profilers'] = get_profilers(sort_by=['name'])
showard0fc38302008-10-23 00:44:07 +0000965 result['current_user'] = rpc_utils.prepare_for_serialization(
showard64a95952010-01-13 21:27:16 +0000966 models.User.current_user().get_object_dict())
showard2b9a88b2008-06-13 20:55:03 +0000967 result['host_statuses'] = sorted(models.Host.Status.names)
mbligh5a198b92008-12-11 19:33:29 +0000968 result['job_statuses'] = sorted(models.HostQueueEntry.Status.names)
Simran Basi7e605742013-11-12 13:43:36 -0800969 result['job_timeout_mins_default'] = models.Job.DEFAULT_TIMEOUT_MINS
Simran Basi34217022012-11-06 13:43:15 -0800970 result['job_max_runtime_mins_default'] = (
971 models.Job.DEFAULT_MAX_RUNTIME_MINS)
showarda1e74b32009-05-12 17:32:04 +0000972 result['parse_failed_repair_default'] = bool(
973 models.Job.DEFAULT_PARSE_FAILED_REPAIR)
jamesrendd855242010-03-02 22:23:44 +0000974 result['reboot_before_options'] = model_attributes.RebootBefore.names
975 result['reboot_after_options'] = model_attributes.RebootAfter.names
showard8fbae652009-01-20 23:23:10 +0000976 result['motd'] = rpc_utils.get_motd()
jamesren76fcf192010-04-21 20:39:50 +0000977 result['drone_sets_enabled'] = models.DroneSet.drone_sets_enabled()
978 result['drone_sets'] = drone_sets
jamesren4a41e012010-07-16 22:33:48 +0000979 result['parameterized_jobs'] = models.Job.parameterized_jobs_enabled()
showard8ac29b42008-07-17 17:01:55 +0000980
showardd3dc1992009-04-22 21:01:40 +0000981 result['status_dictionary'] = {"Aborted": "Aborted",
showard8ac29b42008-07-17 17:01:55 +0000982 "Verifying": "Verifying Host",
Alex Millerdfff2fd2013-05-28 13:05:06 -0700983 "Provisioning": "Provisioning Host",
showard8ac29b42008-07-17 17:01:55 +0000984 "Pending": "Waiting on other hosts",
985 "Running": "Running autoserv",
986 "Completed": "Autoserv completed",
987 "Failed": "Failed to complete",
showardd823b362008-07-24 16:35:46 +0000988 "Queued": "Queued",
showard5deb6772008-11-04 21:54:33 +0000989 "Starting": "Next in host's queue",
990 "Stopped": "Other host(s) failed verify",
showardd3dc1992009-04-22 21:01:40 +0000991 "Parsing": "Awaiting parse of final results",
showard29f7cd22009-04-29 21:16:24 +0000992 "Gathering": "Gathering log files",
showard8cc058f2009-09-08 16:26:33 +0000993 "Template": "Template job for recurring run",
mbligh4608b002010-01-05 18:22:35 +0000994 "Waiting": "Waiting for scheduler action",
Dan Shi07e09af2013-04-12 09:31:29 -0700995 "Archiving": "Archiving results",
996 "Resetting": "Resetting hosts"}
Jiaxi Luo421608e2014-07-07 14:38:00 -0700997
998 result['wmatrix_url'] = rpc_utils.get_wmatrix_url()
999
jadmanski0afbb632008-06-06 21:10:57 +00001000 return result
showard29f7cd22009-04-29 21:16:24 +00001001
1002
1003def get_server_time():
1004 return datetime.datetime.now().strftime("%Y-%m-%d %H:%M")