blob: 24f813a8811a5670e7b7f013bfe41fa5faeabd98 [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
Alex Miller7d658cf2013-09-04 16:00:35 -070036from autotest_lib.client.common_lib import error, 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
mblighe8819cd2008-02-15 16:48:40 +000039
Eric Lid23bc192011-02-09 14:38:57 -080040def get_parameterized_autoupdate_image_url(job):
41 """Get the parameterized autoupdate image url from a parameterized job."""
42 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
43 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
beeps8bb1f7d2013-08-05 01:30:09 -070044 name='image')
Eric Lid23bc192011-02-09 14:38:57 -080045 para_set = job.parameterized_job.parameterizedjobparameter_set
46 job_test_para = para_set.get(test_parameter=image_parameter)
47 return job_test_para.parameter_value
48
49
mblighe8819cd2008-02-15 16:48:40 +000050# labels
51
showard989f25d2008-10-01 11:38:11 +000052def add_label(name, kernel_config=None, platform=None, only_if_needed=None):
showardc92da832009-04-07 18:14:34 +000053 return models.Label.add_object(
54 name=name, kernel_config=kernel_config, platform=platform,
55 only_if_needed=only_if_needed).id
mblighe8819cd2008-02-15 16:48:40 +000056
57
58def modify_label(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +000059 models.Label.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +000060
61
62def delete_label(id):
jadmanski0afbb632008-06-06 21:10:57 +000063 models.Label.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +000064
65
showardbbabf502008-06-06 00:02:02 +000066def label_add_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000067 host_objs = models.Host.smart_get_bulk(hosts)
showardcafd16e2009-05-29 18:37:49 +000068 label = models.Label.smart_get(id)
69 if label.platform:
70 models.Host.check_no_platform(host_objs)
71 label.host_set.add(*host_objs)
showardbbabf502008-06-06 00:02:02 +000072
73
74def label_remove_hosts(id, hosts):
showardbe3ec042008-11-12 18:16:07 +000075 host_objs = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +000076 models.Label.smart_get(id).host_set.remove(*host_objs)
showardbbabf502008-06-06 00:02:02 +000077
78
mblighe8819cd2008-02-15 16:48:40 +000079def get_labels(**filter_data):
showardc92da832009-04-07 18:14:34 +000080 """\
81 @returns A sequence of nested dictionaries of label information.
82 """
83 return rpc_utils.prepare_rows_as_nested_dicts(
84 models.Label.query_objects(filter_data),
85 ('atomic_group',))
86
87
88# atomic groups
89
showarde9450c92009-06-30 01:58:52 +000090def add_atomic_group(name, max_number_of_machines=None, description=None):
showardc92da832009-04-07 18:14:34 +000091 return models.AtomicGroup.add_object(
92 name=name, max_number_of_machines=max_number_of_machines,
93 description=description).id
94
95
96def modify_atomic_group(id, **data):
97 models.AtomicGroup.smart_get(id).update_object(data)
98
99
100def delete_atomic_group(id):
101 models.AtomicGroup.smart_get(id).delete()
102
103
104def atomic_group_add_labels(id, labels):
105 label_objs = models.Label.smart_get_bulk(labels)
106 models.AtomicGroup.smart_get(id).label_set.add(*label_objs)
107
108
109def atomic_group_remove_labels(id, labels):
110 label_objs = models.Label.smart_get_bulk(labels)
111 models.AtomicGroup.smart_get(id).label_set.remove(*label_objs)
112
113
114def get_atomic_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000115 return rpc_utils.prepare_for_serialization(
showardc92da832009-04-07 18:14:34 +0000116 models.AtomicGroup.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000117
118
119# hosts
120
showarddf062562008-07-03 19:56:37 +0000121def add_host(hostname, status=None, locked=None, protection=None):
jadmanski0afbb632008-06-06 21:10:57 +0000122 return models.Host.add_object(hostname=hostname, status=status,
showarddf062562008-07-03 19:56:37 +0000123 locked=locked, protection=protection).id
mblighe8819cd2008-02-15 16:48:40 +0000124
125
126def modify_host(id, **data):
showardbe0d8692009-08-20 23:42:44 +0000127 rpc_utils.check_modify_host(data)
showardce7c0922009-09-11 18:39:24 +0000128 host = models.Host.smart_get(id)
129 rpc_utils.check_modify_host_locking(host, data)
130 host.update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000131
132
showard276f9442009-05-20 00:33:16 +0000133def modify_hosts(host_filter_data, update_data):
134 """
showardbe0d8692009-08-20 23:42:44 +0000135 @param host_filter_data: Filters out which hosts to modify.
136 @param update_data: A dictionary with the changes to make to the hosts.
showard276f9442009-05-20 00:33:16 +0000137 """
showardbe0d8692009-08-20 23:42:44 +0000138 rpc_utils.check_modify_host(update_data)
showard276f9442009-05-20 00:33:16 +0000139 hosts = models.Host.query_objects(host_filter_data)
Alex Miller9658a952013-05-14 16:40:02 -0700140 # Check all hosts before changing data for exception safety.
141 for host in hosts:
142 rpc_utils.check_modify_host_locking(host, update_data)
showard276f9442009-05-20 00:33:16 +0000143 for host in hosts:
144 host.update_object(update_data)
145
146
mblighe8819cd2008-02-15 16:48:40 +0000147def host_add_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000148 labels = models.Label.smart_get_bulk(labels)
showardcafd16e2009-05-29 18:37:49 +0000149 host = models.Host.smart_get(id)
150
151 platforms = [label.name for label in labels if label.platform]
152 if len(platforms) > 1:
153 raise model_logic.ValidationError(
154 {'labels': 'Adding more than one platform label: %s' %
155 ', '.join(platforms)})
156 if len(platforms) == 1:
157 models.Host.check_no_platform([host])
158 host.labels.add(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000159
160
161def host_remove_labels(id, labels):
showardbe3ec042008-11-12 18:16:07 +0000162 labels = models.Label.smart_get_bulk(labels)
jadmanski0afbb632008-06-06 21:10:57 +0000163 models.Host.smart_get(id).labels.remove(*labels)
mblighe8819cd2008-02-15 16:48:40 +0000164
165
showard0957a842009-05-11 19:25:08 +0000166def set_host_attribute(attribute, value, **host_filter_data):
167 """
168 @param attribute string name of attribute
169 @param value string, or None to delete an attribute
170 @param host_filter_data filter data to apply to Hosts to choose hosts to act
171 upon
172 """
173 assert host_filter_data # disallow accidental actions on all hosts
174 hosts = models.Host.query_objects(host_filter_data)
175 models.AclGroup.check_for_acl_violation_hosts(hosts)
176
177 for host in hosts:
showardf8b19042009-05-12 17:22:49 +0000178 host.set_or_delete_attribute(attribute, value)
showard0957a842009-05-11 19:25:08 +0000179
180
mblighe8819cd2008-02-15 16:48:40 +0000181def delete_host(id):
jadmanski0afbb632008-06-06 21:10:57 +0000182 models.Host.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000183
184
showard87cc38f2009-08-20 23:37:04 +0000185def get_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000186 exclude_atomic_group_hosts=False, valid_only=True, **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000187 """
188 @param multiple_labels: match hosts in all of the labels given. Should
189 be a list of label names.
190 @param exclude_only_if_needed_labels: Exclude hosts with at least one
191 "only_if_needed" label applied.
192 @param exclude_atomic_group_hosts: Exclude hosts that have one or more
193 atomic group labels associated with them.
jadmanski0afbb632008-06-06 21:10:57 +0000194 """
showard43a3d262008-11-12 18:17:05 +0000195 hosts = rpc_utils.get_host_query(multiple_labels,
196 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000197 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000198 valid_only, filter_data)
showard0957a842009-05-11 19:25:08 +0000199 hosts = list(hosts)
200 models.Host.objects.populate_relationships(hosts, models.Label,
201 'label_list')
202 models.Host.objects.populate_relationships(hosts, models.AclGroup,
203 'acl_list')
204 models.Host.objects.populate_relationships(hosts, models.HostAttribute,
205 'attribute_list')
showard43a3d262008-11-12 18:17:05 +0000206 host_dicts = []
207 for host_obj in hosts:
208 host_dict = host_obj.get_object_dict()
showard0957a842009-05-11 19:25:08 +0000209 host_dict['labels'] = [label.name for label in host_obj.label_list]
showard909c9142009-07-07 20:54:42 +0000210 host_dict['platform'], host_dict['atomic_group'] = (rpc_utils.
211 find_platform_and_atomic_group(host_obj))
showard0957a842009-05-11 19:25:08 +0000212 host_dict['acls'] = [acl.name for acl in host_obj.acl_list]
213 host_dict['attributes'] = dict((attribute.attribute, attribute.value)
214 for attribute in host_obj.attribute_list)
showard43a3d262008-11-12 18:17:05 +0000215 host_dicts.append(host_dict)
216 return rpc_utils.prepare_for_serialization(host_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000217
218
showard87cc38f2009-08-20 23:37:04 +0000219def get_num_hosts(multiple_labels=(), exclude_only_if_needed_labels=False,
showard8aa84fc2009-09-16 17:17:55 +0000220 exclude_atomic_group_hosts=False, valid_only=True,
221 **filter_data):
showard87cc38f2009-08-20 23:37:04 +0000222 """
223 Same parameters as get_hosts().
224
225 @returns The number of matching hosts.
226 """
showard43a3d262008-11-12 18:17:05 +0000227 hosts = rpc_utils.get_host_query(multiple_labels,
228 exclude_only_if_needed_labels,
showard87cc38f2009-08-20 23:37:04 +0000229 exclude_atomic_group_hosts,
showard8aa84fc2009-09-16 17:17:55 +0000230 valid_only, filter_data)
showard43a3d262008-11-12 18:17:05 +0000231 return hosts.count()
showard1385b162008-03-13 15:59:40 +0000232
mblighe8819cd2008-02-15 16:48:40 +0000233
234# tests
235
showard909c7a62008-07-15 21:52:38 +0000236def add_test(name, test_type, path, author=None, dependencies=None,
showard3d9899a2008-07-31 02:11:58 +0000237 experimental=True, run_verify=None, test_class=None,
showard909c7a62008-07-15 21:52:38 +0000238 test_time=None, test_category=None, description=None,
239 sync_count=1):
jadmanski0afbb632008-06-06 21:10:57 +0000240 return models.Test.add_object(name=name, test_type=test_type, path=path,
showard909c7a62008-07-15 21:52:38 +0000241 author=author, dependencies=dependencies,
242 experimental=experimental,
243 run_verify=run_verify, test_time=test_time,
244 test_category=test_category,
245 sync_count=sync_count,
jadmanski0afbb632008-06-06 21:10:57 +0000246 test_class=test_class,
247 description=description).id
mblighe8819cd2008-02-15 16:48:40 +0000248
249
250def modify_test(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000251 models.Test.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000252
253
254def delete_test(id):
jadmanski0afbb632008-06-06 21:10:57 +0000255 models.Test.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000256
257
258def get_tests(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000259 return rpc_utils.prepare_for_serialization(
260 models.Test.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000261
262
showard2b9a88b2008-06-13 20:55:03 +0000263# profilers
264
265def add_profiler(name, description=None):
266 return models.Profiler.add_object(name=name, description=description).id
267
268
269def modify_profiler(id, **data):
270 models.Profiler.smart_get(id).update_object(data)
271
272
273def delete_profiler(id):
274 models.Profiler.smart_get(id).delete()
275
276
277def get_profilers(**filter_data):
278 return rpc_utils.prepare_for_serialization(
279 models.Profiler.list_objects(filter_data))
280
281
mblighe8819cd2008-02-15 16:48:40 +0000282# users
283
284def add_user(login, access_level=None):
jadmanski0afbb632008-06-06 21:10:57 +0000285 return models.User.add_object(login=login, access_level=access_level).id
mblighe8819cd2008-02-15 16:48:40 +0000286
287
288def modify_user(id, **data):
jadmanski0afbb632008-06-06 21:10:57 +0000289 models.User.smart_get(id).update_object(data)
mblighe8819cd2008-02-15 16:48:40 +0000290
291
292def delete_user(id):
jadmanski0afbb632008-06-06 21:10:57 +0000293 models.User.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000294
295
296def get_users(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000297 return rpc_utils.prepare_for_serialization(
298 models.User.list_objects(filter_data))
mblighe8819cd2008-02-15 16:48:40 +0000299
300
301# acl groups
302
303def add_acl_group(name, description=None):
showard04f2cd82008-07-25 20:53:31 +0000304 group = models.AclGroup.add_object(name=name, description=description)
showard64a95952010-01-13 21:27:16 +0000305 group.users.add(models.User.current_user())
showard04f2cd82008-07-25 20:53:31 +0000306 return group.id
mblighe8819cd2008-02-15 16:48:40 +0000307
308
309def modify_acl_group(id, **data):
showard04f2cd82008-07-25 20:53:31 +0000310 group = models.AclGroup.smart_get(id)
311 group.check_for_acl_violation_acl_group()
312 group.update_object(data)
313 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000314
315
316def acl_group_add_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000317 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000318 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000319 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000320 group.users.add(*users)
mblighe8819cd2008-02-15 16:48:40 +0000321
322
323def acl_group_remove_users(id, users):
jadmanski0afbb632008-06-06 21:10:57 +0000324 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000325 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000326 users = models.User.smart_get_bulk(users)
jadmanski0afbb632008-06-06 21:10:57 +0000327 group.users.remove(*users)
showard04f2cd82008-07-25 20:53:31 +0000328 group.add_current_user_if_empty()
mblighe8819cd2008-02-15 16:48:40 +0000329
330
331def acl_group_add_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000332 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000333 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000334 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000335 group.hosts.add(*hosts)
showard08f981b2008-06-24 21:59:03 +0000336 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000337
338
339def acl_group_remove_hosts(id, hosts):
jadmanski0afbb632008-06-06 21:10:57 +0000340 group = models.AclGroup.smart_get(id)
showard04f2cd82008-07-25 20:53:31 +0000341 group.check_for_acl_violation_acl_group()
showardbe3ec042008-11-12 18:16:07 +0000342 hosts = models.Host.smart_get_bulk(hosts)
jadmanski0afbb632008-06-06 21:10:57 +0000343 group.hosts.remove(*hosts)
showard08f981b2008-06-24 21:59:03 +0000344 group.on_host_membership_change()
mblighe8819cd2008-02-15 16:48:40 +0000345
346
347def delete_acl_group(id):
jadmanski0afbb632008-06-06 21:10:57 +0000348 models.AclGroup.smart_get(id).delete()
mblighe8819cd2008-02-15 16:48:40 +0000349
350
351def get_acl_groups(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000352 acl_groups = models.AclGroup.list_objects(filter_data)
353 for acl_group in acl_groups:
354 acl_group_obj = models.AclGroup.objects.get(id=acl_group['id'])
355 acl_group['users'] = [user.login
356 for user in acl_group_obj.users.all()]
357 acl_group['hosts'] = [host.hostname
358 for host in acl_group_obj.hosts.all()]
359 return rpc_utils.prepare_for_serialization(acl_groups)
mblighe8819cd2008-02-15 16:48:40 +0000360
361
362# jobs
363
mbligh120351e2009-01-24 01:40:45 +0000364def generate_control_file(tests=(), kernel=None, label=None, profilers=(),
showard91f85102009-10-12 20:34:52 +0000365 client_control_file='', use_container=False,
showard232b7ae2009-11-10 00:46:48 +0000366 profile_only=None, upload_kernel_config=False):
jadmanski0afbb632008-06-06 21:10:57 +0000367 """
mbligh120351e2009-01-24 01:40:45 +0000368 Generates a client-side control file to load a kernel and run tests.
369
370 @param tests List of tests to run.
mbligha3c58d22009-08-24 22:01:51 +0000371 @param kernel A list of kernel info dictionaries configuring which kernels
372 to boot for this job and other options for them
mbligh120351e2009-01-24 01:40:45 +0000373 @param label Name of label to grab kernel config from.
374 @param profilers List of profilers to activate during the job.
375 @param client_control_file The contents of a client-side control file to
376 run at the end of all tests. If this is supplied, all tests must be
377 client side.
378 TODO: in the future we should support server control files directly
379 to wrap with a kernel. That'll require changing the parameter
380 name and adding a boolean to indicate if it is a client or server
381 control file.
382 @param use_container unused argument today. TODO: Enable containers
383 on the host during a client side test.
showard91f85102009-10-12 20:34:52 +0000384 @param profile_only A boolean that indicates what default profile_only
385 mode to use in the control file. Passing None will generate a
386 control file that does not explcitly set the default mode at all.
showard232b7ae2009-11-10 00:46:48 +0000387 @param upload_kernel_config: if enabled it will generate server control
388 file code that uploads the kernel config file to the client and
389 tells the client of the new (local) path when compiling the kernel;
390 the tests must be server side tests
mbligh120351e2009-01-24 01:40:45 +0000391
392 @returns a dict with the following keys:
393 control_file: str, The control file text.
394 is_server: bool, is the control file a server-side control file?
395 synch_count: How many machines the job uses per autoserv execution.
396 synch_count == 1 means the job is asynchronous.
397 dependencies: A list of the names of labels on which the job depends.
398 """
showardd86debe2009-06-10 17:37:56 +0000399 if not tests and not client_control_file:
showard2bab8f42008-11-12 18:15:22 +0000400 return dict(control_file='', is_server=False, synch_count=1,
showard989f25d2008-10-01 11:38:11 +0000401 dependencies=[])
mblighe8819cd2008-02-15 16:48:40 +0000402
showard989f25d2008-10-01 11:38:11 +0000403 cf_info, test_objects, profiler_objects, label = (
showard2b9a88b2008-06-13 20:55:03 +0000404 rpc_utils.prepare_generate_control_file(tests, kernel, label,
405 profilers))
showard989f25d2008-10-01 11:38:11 +0000406 cf_info['control_file'] = control_file.generate_control(
mbligha3c58d22009-08-24 22:01:51 +0000407 tests=test_objects, kernels=kernel, platform=label,
mbligh120351e2009-01-24 01:40:45 +0000408 profilers=profiler_objects, is_server=cf_info['is_server'],
showard232b7ae2009-11-10 00:46:48 +0000409 client_control_file=client_control_file, profile_only=profile_only,
410 upload_kernel_config=upload_kernel_config)
showard989f25d2008-10-01 11:38:11 +0000411 return cf_info
mblighe8819cd2008-02-15 16:48:40 +0000412
413
jamesren4a41e012010-07-16 22:33:48 +0000414def create_parameterized_job(name, priority, test, parameters, kernel=None,
415 label=None, profilers=(), profiler_parameters=None,
416 use_container=False, profile_only=None,
417 upload_kernel_config=False, hosts=(),
418 meta_hosts=(), one_time_hosts=(),
419 atomic_group_name=None, synch_count=None,
420 is_template=False, timeout=None,
Dan Shi07e09af2013-04-12 09:31:29 -0700421 max_runtime_mins=None, run_verify=False,
jamesren4a41e012010-07-16 22:33:48 +0000422 email_list='', dependencies=(), reboot_before=None,
423 reboot_after=None, parse_failed_repair=None,
Dan Shi07e09af2013-04-12 09:31:29 -0700424 hostless=False, keyvals=None, drone_set=None,
425 run_reset=True):
jamesren4a41e012010-07-16 22:33:48 +0000426 """
427 Creates and enqueues a parameterized job.
428
429 Most parameters a combination of the parameters for generate_control_file()
430 and create_job(), with the exception of:
431
432 @param test name or ID of the test to run
433 @param parameters a map of parameter name ->
434 tuple of (param value, param type)
435 @param profiler_parameters a dictionary of parameters for the profilers:
436 key: profiler name
437 value: dict of param name -> tuple of
438 (param value,
439 param type)
440 """
441 # Save the values of the passed arguments here. What we're going to do with
442 # them is pass them all to rpc_utils.get_create_job_common_args(), which
443 # will extract the subset of these arguments that apply for
444 # rpc_utils.create_job_common(), which we then pass in to that function.
445 args = locals()
446
447 # Set up the parameterized job configs
448 test_obj = models.Test.smart_get(test)
Aviv Keshet3dd8beb2013-05-13 17:36:04 -0700449 control_type = test_obj.test_type
jamesren4a41e012010-07-16 22:33:48 +0000450
451 try:
452 label = models.Label.smart_get(label)
453 except models.Label.DoesNotExist:
454 label = None
455
456 kernel_objs = models.Kernel.create_kernels(kernel)
457 profiler_objs = [models.Profiler.smart_get(profiler)
458 for profiler in profilers]
459
460 parameterized_job = models.ParameterizedJob.objects.create(
461 test=test_obj, label=label, use_container=use_container,
462 profile_only=profile_only,
463 upload_kernel_config=upload_kernel_config)
464 parameterized_job.kernels.add(*kernel_objs)
465
466 for profiler in profiler_objs:
467 parameterized_profiler = models.ParameterizedJobProfiler.objects.create(
468 parameterized_job=parameterized_job,
469 profiler=profiler)
470 profiler_params = profiler_parameters.get(profiler.name, {})
471 for name, (value, param_type) in profiler_params.iteritems():
472 models.ParameterizedJobProfilerParameter.objects.create(
473 parameterized_job_profiler=parameterized_profiler,
474 parameter_name=name,
475 parameter_value=value,
476 parameter_type=param_type)
477
478 try:
479 for parameter in test_obj.testparameter_set.all():
480 if parameter.name in parameters:
481 param_value, param_type = parameters.pop(parameter.name)
482 parameterized_job.parameterizedjobparameter_set.create(
483 test_parameter=parameter, parameter_value=param_value,
484 parameter_type=param_type)
485
486 if parameters:
487 raise Exception('Extra parameters remain: %r' % parameters)
488
489 return rpc_utils.create_job_common(
490 parameterized_job=parameterized_job.id,
491 control_type=control_type,
492 **rpc_utils.get_create_job_common_args(args))
493 except:
494 parameterized_job.delete()
495 raise
496
497
showard12f3e322009-05-13 21:27:42 +0000498def create_job(name, priority, control_file, control_type,
499 hosts=(), meta_hosts=(), one_time_hosts=(),
500 atomic_group_name=None, synch_count=None, is_template=False,
Dan Shi07e09af2013-04-12 09:31:29 -0700501 timeout=None, max_runtime_mins=None, run_verify=False,
showard12f3e322009-05-13 21:27:42 +0000502 email_list='', dependencies=(), reboot_before=None,
showardc1a98d12010-01-15 00:22:22 +0000503 reboot_after=None, parse_failed_repair=None, hostless=False,
Aviv Keshetcd1ff9b2013-03-01 14:55:19 -0800504 keyvals=None, drone_set=None, image=None, parent_job_id=None,
Dan Shi07e09af2013-04-12 09:31:29 -0700505 test_retry=0, run_reset=True):
jadmanski0afbb632008-06-06 21:10:57 +0000506 """\
507 Create and enqueue a job.
mblighe8819cd2008-02-15 16:48:40 +0000508
showarda1e74b32009-05-12 17:32:04 +0000509 @param name name of this job
Alex Miller7d658cf2013-09-04 16:00:35 -0700510 @param priority Integer priority of this job. Higher is more important.
showarda1e74b32009-05-12 17:32:04 +0000511 @param control_file String contents of the control file.
512 @param control_type Type of control file, Client or Server.
513 @param synch_count How many machines the job uses per autoserv execution.
514 synch_count == 1 means the job is asynchronous. If an atomic group is
515 given this value is treated as a minimum.
516 @param is_template If true then create a template job.
517 @param timeout Hours after this call returns until the job times out.
Simran Basi34217022012-11-06 13:43:15 -0800518 @param max_runtime_mins Minutes from job starting time until job times out
showarda1e74b32009-05-12 17:32:04 +0000519 @param run_verify Should the host be verified before running the test?
520 @param email_list String containing emails to mail when the job is done
521 @param dependencies List of label names on which this job depends
522 @param reboot_before Never, If dirty, or Always
523 @param reboot_after Never, If all tests passed, or Always
524 @param parse_failed_repair if true, results of failed repairs launched by
525 this job will be parsed as part of the job.
showarda9545c02009-12-18 22:44:26 +0000526 @param hostless if true, create a hostless job
showardc1a98d12010-01-15 00:22:22 +0000527 @param keyvals dict of keyvals to associate with the job
showarda1e74b32009-05-12 17:32:04 +0000528
529 @param hosts List of hosts to run job on.
530 @param meta_hosts List where each entry is a label name, and for each entry
531 one host will be chosen from that label to run the job on.
532 @param one_time_hosts List of hosts not in the database to run the job on.
533 @param atomic_group_name The name of an atomic group to schedule the job on.
jamesren76fcf192010-04-21 20:39:50 +0000534 @param drone_set The name of the drone set to run this test on.
Paul Pendlebury5a8c6ad2011-02-01 07:20:17 -0800535 @param image OS image to install before running job.
Aviv Keshet0b9cfc92013-02-05 11:36:02 -0800536 @param parent_job_id id of a job considered to be parent of created job.
Aviv Keshetcd1ff9b2013-03-01 14:55:19 -0800537 @param test_retry: Number of times to retry test if the test did not
538 complete successfully. (optional, default: 0)
Dan Shi07e09af2013-04-12 09:31:29 -0700539 @param run_reset: Should the host be reset before running the test?
showardc92da832009-04-07 18:14:34 +0000540
541 @returns The created Job id number.
jadmanski0afbb632008-06-06 21:10:57 +0000542 """
Alex Millera713e252013-03-01 10:45:44 -0800543 # Force control files to only contain ascii characters.
544 try:
545 control_file.encode('ascii')
546 except UnicodeDecodeError as e:
547 raise error.ControlFileMalformed(str(e))
548
Paul Pendlebury5a8c6ad2011-02-01 07:20:17 -0800549 if image is None:
550 return rpc_utils.create_job_common(
551 **rpc_utils.get_create_job_common_args(locals()))
552
553 # When image is supplied use a known parameterized test already in the
554 # database to pass the OS image path from the front end, through the
555 # scheduler, and finally to autoserv as the --image parameter.
556
557 # The test autoupdate_ParameterizedJob is in afe_autotests and used to
558 # instantiate a Test object and from there a ParameterizedJob.
559 known_test_obj = models.Test.smart_get('autoupdate_ParameterizedJob')
560 known_parameterized_job = models.ParameterizedJob.objects.create(
561 test=known_test_obj)
562
563 # autoupdate_ParameterizedJob has a single parameter, the image parameter,
564 # stored in the table afe_test_parameters. We retrieve and set this
565 # instance of the parameter to the OS image path.
Eric Lid23bc192011-02-09 14:38:57 -0800566 image_parameter = known_test_obj.testparameter_set.get(test=known_test_obj,
567 name='image')
Paul Pendlebury5a8c6ad2011-02-01 07:20:17 -0800568 known_parameterized_job.parameterizedjobparameter_set.create(
569 test_parameter=image_parameter, parameter_value=image,
570 parameter_type='string')
571
572 # By passing a parameterized_job to create_job_common the job entry in
573 # the afe_jobs table will have the field parameterized_job_id set.
574 # The scheduler uses this id in the afe_parameterized_jobs table to
575 # match this job to our known test, and then with the
576 # afe_parameterized_job_parameters table to get the actual image path.
jamesren4a41e012010-07-16 22:33:48 +0000577 return rpc_utils.create_job_common(
Paul Pendlebury5a8c6ad2011-02-01 07:20:17 -0800578 parameterized_job=known_parameterized_job.id,
jamesren4a41e012010-07-16 22:33:48 +0000579 **rpc_utils.get_create_job_common_args(locals()))
mblighe8819cd2008-02-15 16:48:40 +0000580
581
showard9dbdcda2008-10-14 17:34:36 +0000582def abort_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000583 """\
showard9dbdcda2008-10-14 17:34:36 +0000584 Abort a set of host queue entries.
jadmanski0afbb632008-06-06 21:10:57 +0000585 """
showard9dbdcda2008-10-14 17:34:36 +0000586 query = models.HostQueueEntry.query_objects(filter_data)
beepsfaecbce2013-10-29 11:35:10 -0700587
588 # Dont allow aborts on:
589 # 1. Jobs that have already completed (whether or not they were aborted)
590 # 2. Jobs that we have already been aborted (but may not have completed)
591 query = query.filter(complete=False).filter(aborted=False)
showarddc817512008-11-12 18:16:41 +0000592 models.AclGroup.check_abort_permissions(query)
showard9dbdcda2008-10-14 17:34:36 +0000593 host_queue_entries = list(query.select_related())
showard2bab8f42008-11-12 18:15:22 +0000594 rpc_utils.check_abort_synchronous_jobs(host_queue_entries)
mblighe8819cd2008-02-15 16:48:40 +0000595
Simran Basic1b26762013-06-26 14:23:21 -0700596 models.HostQueueEntry.abort_host_queue_entries(host_queue_entries)
showard9d821ab2008-07-11 16:54:29 +0000597
598
beeps8bb1f7d2013-08-05 01:30:09 -0700599def abort_special_tasks(**filter_data):
600 """\
601 Abort the special task, or tasks, specified in the filter.
602 """
603 query = models.SpecialTask.query_objects(filter_data)
604 special_tasks = query.filter(is_active=True)
605 for task in special_tasks:
606 task.abort()
607
608
Simran Basi73dae552013-02-25 14:57:46 -0800609def _call_special_tasks_on_hosts(task, hosts):
610 """\
611 Schedules a set of hosts for a special task.
612
613 @returns A list of hostnames that a special task was created for.
614 """
615 models.AclGroup.check_for_acl_violation_hosts(hosts)
616 for host in hosts:
617 models.SpecialTask.schedule_special_task(host, task)
618 return list(sorted(host.hostname for host in hosts))
619
620
showard1ff7b2e2009-05-15 23:17:18 +0000621def reverify_hosts(**filter_data):
622 """\
623 Schedules a set of hosts for verify.
mbligh4e545a52009-12-19 05:30:39 +0000624
625 @returns A list of hostnames that a verify task was created for.
showard1ff7b2e2009-05-15 23:17:18 +0000626 """
Simran Basi73dae552013-02-25 14:57:46 -0800627 return _call_special_tasks_on_hosts(models.SpecialTask.Task.VERIFY,
628 models.Host.query_objects(filter_data))
629
630
631def repair_hosts(**filter_data):
632 """\
633 Schedules a set of hosts for repair.
634
635 @returns A list of hostnames that a repair task was created for.
636 """
637 return _call_special_tasks_on_hosts(models.SpecialTask.Task.REPAIR,
638 models.Host.query_objects(filter_data))
showard1ff7b2e2009-05-15 23:17:18 +0000639
640
mblighe8819cd2008-02-15 16:48:40 +0000641def get_jobs(not_yet_run=False, running=False, finished=False, **filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000642 """\
643 Extra filter args for get_jobs:
644 -not_yet_run: Include only jobs that have not yet started running.
645 -running: Include only jobs that have start running but for which not
646 all hosts have completed.
647 -finished: Include only jobs for which all hosts have completed (or
648 aborted).
649 At most one of these three fields should be specified.
650 """
651 filter_data['extra_args'] = rpc_utils.extra_job_filters(not_yet_run,
652 running,
653 finished)
showard0957a842009-05-11 19:25:08 +0000654 job_dicts = []
655 jobs = list(models.Job.query_objects(filter_data))
656 models.Job.objects.populate_relationships(jobs, models.Label,
657 'dependencies')
showardc1a98d12010-01-15 00:22:22 +0000658 models.Job.objects.populate_relationships(jobs, models.JobKeyval, 'keyvals')
showard0957a842009-05-11 19:25:08 +0000659 for job in jobs:
660 job_dict = job.get_object_dict()
661 job_dict['dependencies'] = ','.join(label.name
662 for label in job.dependencies)
showardc1a98d12010-01-15 00:22:22 +0000663 job_dict['keyvals'] = dict((keyval.key, keyval.value)
664 for keyval in job.keyvals)
Eric Lid23bc192011-02-09 14:38:57 -0800665 if job.parameterized_job:
666 job_dict['image'] = get_parameterized_autoupdate_image_url(job)
showard0957a842009-05-11 19:25:08 +0000667 job_dicts.append(job_dict)
668 return rpc_utils.prepare_for_serialization(job_dicts)
mblighe8819cd2008-02-15 16:48:40 +0000669
670
671def get_num_jobs(not_yet_run=False, running=False, finished=False,
jadmanski0afbb632008-06-06 21:10:57 +0000672 **filter_data):
673 """\
674 See get_jobs() for documentation of extra filter parameters.
675 """
676 filter_data['extra_args'] = rpc_utils.extra_job_filters(not_yet_run,
677 running,
678 finished)
679 return models.Job.query_count(filter_data)
mblighe8819cd2008-02-15 16:48:40 +0000680
681
mblighe8819cd2008-02-15 16:48:40 +0000682def get_jobs_summary(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000683 """\
showarda8709c52008-07-03 19:44:54 +0000684 Like get_jobs(), but adds a 'status_counts' field, which is a dictionary
jadmanski0afbb632008-06-06 21:10:57 +0000685 mapping status strings to the number of hosts currently with that
686 status, i.e. {'Queued' : 4, 'Running' : 2}.
687 """
688 jobs = get_jobs(**filter_data)
689 ids = [job['id'] for job in jobs]
690 all_status_counts = models.Job.objects.get_status_counts(ids)
691 for job in jobs:
692 job['status_counts'] = all_status_counts[job['id']]
693 return rpc_utils.prepare_for_serialization(jobs)
mblighe8819cd2008-02-15 16:48:40 +0000694
695
showarda965cef2009-05-15 23:17:41 +0000696def get_info_for_clone(id, preserve_metahosts, queue_entry_filter_data=None):
showarda8709c52008-07-03 19:44:54 +0000697 """\
698 Retrieves all the information needed to clone a job.
699 """
showarda8709c52008-07-03 19:44:54 +0000700 job = models.Job.objects.get(id=id)
showard29f7cd22009-04-29 21:16:24 +0000701 job_info = rpc_utils.get_job_info(job,
showarda965cef2009-05-15 23:17:41 +0000702 preserve_metahosts,
703 queue_entry_filter_data)
showard945072f2008-09-03 20:34:59 +0000704
showardd9992fe2008-07-31 02:15:03 +0000705 host_dicts = []
showard29f7cd22009-04-29 21:16:24 +0000706 for host in job_info['hosts']:
707 host_dict = get_hosts(id=host.id)[0]
708 other_labels = host_dict['labels']
709 if host_dict['platform']:
710 other_labels.remove(host_dict['platform'])
711 host_dict['other_labels'] = ', '.join(other_labels)
showardd9992fe2008-07-31 02:15:03 +0000712 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000713
showard29f7cd22009-04-29 21:16:24 +0000714 for host in job_info['one_time_hosts']:
715 host_dict = dict(hostname=host.hostname,
716 id=host.id,
717 platform='(one-time host)',
718 locked_text='')
719 host_dicts.append(host_dict)
showarda8709c52008-07-03 19:44:54 +0000720
showard4d077562009-05-08 18:24:36 +0000721 # convert keys from Label objects to strings (names of labels)
showard29f7cd22009-04-29 21:16:24 +0000722 meta_host_counts = dict((meta_host.name, count) for meta_host, count
showard4d077562009-05-08 18:24:36 +0000723 in job_info['meta_host_counts'].iteritems())
showard29f7cd22009-04-29 21:16:24 +0000724
725 info = dict(job=job.get_object_dict(),
726 meta_host_counts=meta_host_counts,
727 hosts=host_dicts)
728 info['job']['dependencies'] = job_info['dependencies']
729 if job_info['atomic_group']:
730 info['atomic_group_name'] = (job_info['atomic_group']).name
731 else:
732 info['atomic_group_name'] = None
jamesren2275ef12010-04-12 18:25:06 +0000733 info['hostless'] = job_info['hostless']
jamesren76fcf192010-04-21 20:39:50 +0000734 info['drone_set'] = job.drone_set and job.drone_set.name
showarda8709c52008-07-03 19:44:54 +0000735
Eric Lid23bc192011-02-09 14:38:57 -0800736 if job.parameterized_job:
737 info['job']['image'] = get_parameterized_autoupdate_image_url(job)
738
showarda8709c52008-07-03 19:44:54 +0000739 return rpc_utils.prepare_for_serialization(info)
740
741
showard34dc5fa2008-04-24 20:58:40 +0000742# host queue entries
743
744def get_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000745 """\
showardc92da832009-04-07 18:14:34 +0000746 @returns A sequence of nested dictionaries of host and job information.
jadmanski0afbb632008-06-06 21:10:57 +0000747 """
showardc92da832009-04-07 18:14:34 +0000748 return rpc_utils.prepare_rows_as_nested_dicts(
749 models.HostQueueEntry.query_objects(filter_data),
750 ('host', 'atomic_group', 'job'))
showard34dc5fa2008-04-24 20:58:40 +0000751
752
753def get_num_host_queue_entries(**filter_data):
jadmanski0afbb632008-06-06 21:10:57 +0000754 """\
755 Get the number of host queue entries associated with this job.
756 """
757 return models.HostQueueEntry.query_count(filter_data)
showard34dc5fa2008-04-24 20:58:40 +0000758
759
showard1e935f12008-07-11 00:11:36 +0000760def get_hqe_percentage_complete(**filter_data):
761 """
showardc92da832009-04-07 18:14:34 +0000762 Computes the fraction of host queue entries matching the given filter data
showard1e935f12008-07-11 00:11:36 +0000763 that are complete.
764 """
765 query = models.HostQueueEntry.query_objects(filter_data)
766 complete_count = query.filter(complete=True).count()
767 total_count = query.count()
768 if total_count == 0:
769 return 1
770 return float(complete_count) / total_count
771
772
showard1a5a4082009-07-28 20:01:37 +0000773# special tasks
774
775def get_special_tasks(**filter_data):
776 return rpc_utils.prepare_rows_as_nested_dicts(
777 models.SpecialTask.query_objects(filter_data),
778 ('host', 'queue_entry'))
779
780
showardc0ac3a72009-07-08 21:14:45 +0000781# support for host detail view
782
783def get_host_queue_entries_and_special_tasks(hostname, query_start=None,
784 query_limit=None):
785 """
786 @returns an interleaved list of HostQueueEntries and SpecialTasks,
787 in approximate run order. each dict contains keys for type, host,
788 job, status, started_on, execution_path, and ID.
789 """
790 total_limit = None
791 if query_limit is not None:
792 total_limit = query_start + query_limit
793 filter_data = {'host__hostname': hostname,
794 'query_limit': total_limit,
795 'sort_by': ['-id']}
796
797 queue_entries = list(models.HostQueueEntry.query_objects(filter_data))
798 special_tasks = list(models.SpecialTask.query_objects(filter_data))
799
800 interleaved_entries = rpc_utils.interleave_entries(queue_entries,
801 special_tasks)
802 if query_start is not None:
803 interleaved_entries = interleaved_entries[query_start:]
804 if query_limit is not None:
805 interleaved_entries = interleaved_entries[:query_limit]
806 return rpc_utils.prepare_for_serialization(interleaved_entries)
807
808
809def get_num_host_queue_entries_and_special_tasks(hostname):
810 filter_data = {'host__hostname': hostname}
811 return (models.HostQueueEntry.query_count(filter_data)
812 + models.SpecialTask.query_count(filter_data))
813
814
showard29f7cd22009-04-29 21:16:24 +0000815# recurring run
816
817def get_recurring(**filter_data):
818 return rpc_utils.prepare_rows_as_nested_dicts(
819 models.RecurringRun.query_objects(filter_data),
820 ('job', 'owner'))
821
822
823def get_num_recurring(**filter_data):
824 return models.RecurringRun.query_count(filter_data)
825
826
827def delete_recurring_runs(**filter_data):
828 to_delete = models.RecurringRun.query_objects(filter_data)
829 to_delete.delete()
830
831
832def create_recurring_run(job_id, start_date, loop_period, loop_count):
showard64a95952010-01-13 21:27:16 +0000833 owner = models.User.current_user().login
showard29f7cd22009-04-29 21:16:24 +0000834 job = models.Job.objects.get(id=job_id)
835 return job.create_recurring_job(start_date=start_date,
836 loop_period=loop_period,
837 loop_count=loop_count,
838 owner=owner)
839
840
mblighe8819cd2008-02-15 16:48:40 +0000841# other
842
showarde0b63622008-08-04 20:58:47 +0000843def echo(data=""):
844 """\
845 Returns a passed in string. For doing a basic test to see if RPC calls
846 can successfully be made.
847 """
848 return data
849
850
showardb7a52fd2009-04-27 20:10:56 +0000851def get_motd():
852 """\
853 Returns the message of the day as a string.
854 """
855 return rpc_utils.get_motd()
856
857
mblighe8819cd2008-02-15 16:48:40 +0000858def get_static_data():
jadmanski0afbb632008-06-06 21:10:57 +0000859 """\
860 Returns a dictionary containing a bunch of data that shouldn't change
861 often and is otherwise inaccessible. This includes:
showardc92da832009-04-07 18:14:34 +0000862
863 priorities: List of job priority choices.
864 default_priority: Default priority value for new jobs.
865 users: Sorted list of all users.
866 labels: Sorted list of all labels.
867 atomic_groups: Sorted list of all atomic groups.
868 tests: Sorted list of all tests.
869 profilers: Sorted list of all profilers.
870 current_user: Logged-in username.
871 host_statuses: Sorted list of possible Host statuses.
872 job_statuses: Sorted list of possible HostQueueEntry statuses.
873 job_timeout_default: The default job timeout length in hours.
showarda1e74b32009-05-12 17:32:04 +0000874 parse_failed_repair_default: Default value for the parse_failed_repair job
875 option.
showardc92da832009-04-07 18:14:34 +0000876 reboot_before_options: A list of valid RebootBefore string enums.
877 reboot_after_options: A list of valid RebootAfter string enums.
878 motd: Server's message of the day.
879 status_dictionary: A mapping from one word job status names to a more
880 informative description.
jadmanski0afbb632008-06-06 21:10:57 +0000881 """
showard21baa452008-10-21 00:08:39 +0000882
883 job_fields = models.Job.get_field_dict()
jamesren76fcf192010-04-21 20:39:50 +0000884 default_drone_set_name = models.DroneSet.default_drone_set_name()
885 drone_sets = ([default_drone_set_name] +
886 sorted(drone_set.name for drone_set in
887 models.DroneSet.objects.exclude(
888 name=default_drone_set_name)))
showard21baa452008-10-21 00:08:39 +0000889
jadmanski0afbb632008-06-06 21:10:57 +0000890 result = {}
Alex Miller7d658cf2013-09-04 16:00:35 -0700891 result['priorities'] = priorities.Priority.choices()
892 default_priority = priorities.Priority.DEFAULT
893 result['default_priority'] = 'Default'
894 result['max_schedulable_priority'] = priorities.Priority.DEFAULT
jadmanski0afbb632008-06-06 21:10:57 +0000895 result['users'] = get_users(sort_by=['login'])
896 result['labels'] = get_labels(sort_by=['-platform', 'name'])
showardc92da832009-04-07 18:14:34 +0000897 result['atomic_groups'] = get_atomic_groups(sort_by=['name'])
jadmanski0afbb632008-06-06 21:10:57 +0000898 result['tests'] = get_tests(sort_by=['name'])
showard2b9a88b2008-06-13 20:55:03 +0000899 result['profilers'] = get_profilers(sort_by=['name'])
showard0fc38302008-10-23 00:44:07 +0000900 result['current_user'] = rpc_utils.prepare_for_serialization(
showard64a95952010-01-13 21:27:16 +0000901 models.User.current_user().get_object_dict())
showard2b9a88b2008-06-13 20:55:03 +0000902 result['host_statuses'] = sorted(models.Host.Status.names)
mbligh5a198b92008-12-11 19:33:29 +0000903 result['job_statuses'] = sorted(models.HostQueueEntry.Status.names)
showardb1e51872008-10-07 11:08:18 +0000904 result['job_timeout_default'] = models.Job.DEFAULT_TIMEOUT
Simran Basi34217022012-11-06 13:43:15 -0800905 result['job_max_runtime_mins_default'] = (
906 models.Job.DEFAULT_MAX_RUNTIME_MINS)
showarda1e74b32009-05-12 17:32:04 +0000907 result['parse_failed_repair_default'] = bool(
908 models.Job.DEFAULT_PARSE_FAILED_REPAIR)
jamesrendd855242010-03-02 22:23:44 +0000909 result['reboot_before_options'] = model_attributes.RebootBefore.names
910 result['reboot_after_options'] = model_attributes.RebootAfter.names
showard8fbae652009-01-20 23:23:10 +0000911 result['motd'] = rpc_utils.get_motd()
jamesren76fcf192010-04-21 20:39:50 +0000912 result['drone_sets_enabled'] = models.DroneSet.drone_sets_enabled()
913 result['drone_sets'] = drone_sets
jamesren4a41e012010-07-16 22:33:48 +0000914 result['parameterized_jobs'] = models.Job.parameterized_jobs_enabled()
showard8ac29b42008-07-17 17:01:55 +0000915
showardd3dc1992009-04-22 21:01:40 +0000916 result['status_dictionary'] = {"Aborted": "Aborted",
showard8ac29b42008-07-17 17:01:55 +0000917 "Verifying": "Verifying Host",
Alex Millerdfff2fd2013-05-28 13:05:06 -0700918 "Provisioning": "Provisioning Host",
showard8ac29b42008-07-17 17:01:55 +0000919 "Pending": "Waiting on other hosts",
920 "Running": "Running autoserv",
921 "Completed": "Autoserv completed",
922 "Failed": "Failed to complete",
showardd823b362008-07-24 16:35:46 +0000923 "Queued": "Queued",
showard5deb6772008-11-04 21:54:33 +0000924 "Starting": "Next in host's queue",
925 "Stopped": "Other host(s) failed verify",
showardd3dc1992009-04-22 21:01:40 +0000926 "Parsing": "Awaiting parse of final results",
showard29f7cd22009-04-29 21:16:24 +0000927 "Gathering": "Gathering log files",
showard8cc058f2009-09-08 16:26:33 +0000928 "Template": "Template job for recurring run",
mbligh4608b002010-01-05 18:22:35 +0000929 "Waiting": "Waiting for scheduler action",
Dan Shi07e09af2013-04-12 09:31:29 -0700930 "Archiving": "Archiving results",
931 "Resetting": "Resetting hosts"}
jadmanski0afbb632008-06-06 21:10:57 +0000932 return result
showard29f7cd22009-04-29 21:16:24 +0000933
934
935def get_server_time():
936 return datetime.datetime.now().strftime("%Y-%m-%d %H:%M")