blob: f4f58812593c298d430e5184e00358222e26a002 [file] [log] [blame]
mbligh67647152008-11-19 00:18:14 +00001# Copyright Martin J. Bligh, Google Inc 2008
2# Released under the GPL v2
3
4"""
5This class allows you to communicate with the frontend to submit jobs etc
6It is designed for writing more sophisiticated server-side control files that
7can recursively add and manage other jobs.
8
9We turn the JSON dictionaries into real objects that are more idiomatic
10
mblighc31e4022008-12-11 19:32:30 +000011For docs, see:
Aviv Keshet2c709f62013-05-07 12:52:15 -070012 http://www.chromium.org/chromium-os/testing/afe-rpc-infrastructure
mblighc31e4022008-12-11 19:32:30 +000013 http://docs.djangoproject.com/en/dev/ref/models/querysets/#queryset-api
mbligh67647152008-11-19 00:18:14 +000014"""
15
Richard Barnetteb9b37982016-05-20 19:23:39 -070016#pylint: disable=missing-docstring
17
Dan Shie8e0c052015-09-01 00:27:27 -070018import getpass
19import os
20import re
Dan Shie8e0c052015-09-01 00:27:27 -070021
mbligh67647152008-11-19 00:18:14 +000022import common
23from autotest_lib.frontend.afe import rpc_client_lib
Dan Shie8e0c052015-09-01 00:27:27 -070024from autotest_lib.client.common_lib import control_data
mbligh37eceaa2008-12-15 22:56:37 +000025from autotest_lib.client.common_lib import global_config
mbligh67647152008-11-19 00:18:14 +000026from autotest_lib.client.common_lib import utils
Dan Shie8e0c052015-09-01 00:27:27 -070027from autotest_lib.client.common_lib.cros.graphite import autotest_stats
Scott Zawalski63470dd2012-09-05 00:49:43 -040028from autotest_lib.tko import db
29
30
mbligh4e576612008-12-22 14:56:36 +000031try:
32 from autotest_lib.server.site_common import site_utils as server_utils
33except:
34 from autotest_lib.server import utils as server_utils
35form_ntuples_from_machines = server_utils.form_ntuples_from_machines
mbligh67647152008-11-19 00:18:14 +000036
mbligh37eceaa2008-12-15 22:56:37 +000037GLOBAL_CONFIG = global_config.global_config
38DEFAULT_SERVER = 'autotest'
39
Dan Shie8e0c052015-09-01 00:27:27 -070040_tko_timer = autotest_stats.Timer('tko')
41
mbligh67647152008-11-19 00:18:14 +000042def dump_object(header, obj):
43 """
44 Standard way to print out the frontend objects (eg job, host, acl, label)
45 in a human-readable fashion for debugging
46 """
47 result = header + '\n'
48 for key in obj.hash:
49 if key == 'afe' or key == 'hash':
50 continue
51 result += '%20s: %s\n' % (key, obj.hash[key])
52 return result
53
54
mbligh5280e3b2008-12-22 14:39:28 +000055class RpcClient(object):
mbligh67647152008-11-19 00:18:14 +000056 """
mbligh451ede12009-02-12 21:54:03 +000057 Abstract RPC class for communicating with the autotest frontend
58 Inherited for both TKO and AFE uses.
mbligh67647152008-11-19 00:18:14 +000059
mbligh1ef218d2009-08-03 16:57:56 +000060 All the constructors go in the afe / tko class.
mbligh451ede12009-02-12 21:54:03 +000061 Manipulating methods go in the object classes themselves
mbligh67647152008-11-19 00:18:14 +000062 """
mbligh99b24f42009-06-08 16:45:55 +000063 def __init__(self, path, user, server, print_log, debug, reply_debug):
mbligh67647152008-11-19 00:18:14 +000064 """
mbligh451ede12009-02-12 21:54:03 +000065 Create a cached instance of a connection to the frontend
mbligh67647152008-11-19 00:18:14 +000066
67 user: username to connect as
mbligh451ede12009-02-12 21:54:03 +000068 server: frontend server to connect to
mbligh67647152008-11-19 00:18:14 +000069 print_log: pring a logging message to stdout on every operation
70 debug: print out all RPC traffic
71 """
Dan Shiff78f112015-06-12 13:34:02 -070072 if not user and utils.is_in_container():
73 user = GLOBAL_CONFIG.get_config_value('SSP', 'user', default=None)
mblighc31e4022008-12-11 19:32:30 +000074 if not user:
mblighdb59e3c2009-11-21 01:45:18 +000075 user = getpass.getuser()
mbligh451ede12009-02-12 21:54:03 +000076 if not server:
mbligh475f7762009-01-30 00:34:04 +000077 if 'AUTOTEST_WEB' in os.environ:
mbligh451ede12009-02-12 21:54:03 +000078 server = os.environ['AUTOTEST_WEB']
mbligh475f7762009-01-30 00:34:04 +000079 else:
mbligh451ede12009-02-12 21:54:03 +000080 server = GLOBAL_CONFIG.get_config_value('SERVER', 'hostname',
81 default=DEFAULT_SERVER)
82 self.server = server
mbligh67647152008-11-19 00:18:14 +000083 self.user = user
84 self.print_log = print_log
85 self.debug = debug
mbligh99b24f42009-06-08 16:45:55 +000086 self.reply_debug = reply_debug
Scott Zawalski347aaf42012-04-03 16:33:00 -040087 headers = {'AUTHORIZATION': self.user}
88 rpc_server = 'http://' + server + path
mbligh1354c9d2008-12-22 14:56:13 +000089 if debug:
90 print 'SERVER: %s' % rpc_server
91 print 'HEADERS: %s' % headers
mbligh67647152008-11-19 00:18:14 +000092 self.proxy = rpc_client_lib.get_proxy(rpc_server, headers=headers)
93
94
95 def run(self, call, **dargs):
96 """
97 Make a RPC call to the AFE server
98 """
99 rpc_call = getattr(self.proxy, call)
100 if self.debug:
101 print 'DEBUG: %s %s' % (call, dargs)
mbligh451ede12009-02-12 21:54:03 +0000102 try:
mbligh99b24f42009-06-08 16:45:55 +0000103 result = utils.strip_unicode(rpc_call(**dargs))
104 if self.reply_debug:
105 print result
106 return result
mbligh451ede12009-02-12 21:54:03 +0000107 except Exception:
mbligh451ede12009-02-12 21:54:03 +0000108 raise
mbligh67647152008-11-19 00:18:14 +0000109
110
111 def log(self, message):
112 if self.print_log:
113 print message
114
115
jamesrenc3940222010-02-19 21:57:37 +0000116class Planner(RpcClient):
117 def __init__(self, user=None, server=None, print_log=True, debug=False,
118 reply_debug=False):
119 super(Planner, self).__init__(path='/planner/server/rpc/',
120 user=user,
121 server=server,
122 print_log=print_log,
123 debug=debug,
124 reply_debug=reply_debug)
125
126
mbligh5280e3b2008-12-22 14:39:28 +0000127class TKO(RpcClient):
mbligh99b24f42009-06-08 16:45:55 +0000128 def __init__(self, user=None, server=None, print_log=True, debug=False,
129 reply_debug=False):
Scott Zawalski347aaf42012-04-03 16:33:00 -0400130 super(TKO, self).__init__(path='/new_tko/server/noauth/rpc/',
mbligh99b24f42009-06-08 16:45:55 +0000131 user=user,
132 server=server,
133 print_log=print_log,
134 debug=debug,
135 reply_debug=reply_debug)
Scott Zawalski63470dd2012-09-05 00:49:43 -0400136 self._db = None
137
138
Dan Shie8e0c052015-09-01 00:27:27 -0700139 @_tko_timer.decorate
Scott Zawalski63470dd2012-09-05 00:49:43 -0400140 def get_job_test_statuses_from_db(self, job_id):
141 """Get job test statuses from the database.
142
143 Retrieve a set of fields from a job that reflect the status of each test
144 run within a job.
145 fields retrieved: status, test_name, reason, test_started_time,
146 test_finished_time, afe_job_id, job_owner, hostname.
147
148 @param job_id: The afe job id to look up.
149 @returns a TestStatus object of the resulting information.
150 """
151 if self._db is None:
Dan Shie8e0c052015-09-01 00:27:27 -0700152 self._db = db.db()
Fang Deng5c508332014-03-19 10:26:00 -0700153 fields = ['status', 'test_name', 'subdir', 'reason',
154 'test_started_time', 'test_finished_time', 'afe_job_id',
155 'job_owner', 'hostname', 'job_tag']
Scott Zawalski63470dd2012-09-05 00:49:43 -0400156 table = 'tko_test_view_2'
157 where = 'job_tag like "%s-%%"' % job_id
158 test_status = []
159 # Run commit before we query to ensure that we are pulling the latest
160 # results.
161 self._db.commit()
162 for entry in self._db.select(','.join(fields), table, (where, None)):
163 status_dict = {}
164 for key,value in zip(fields, entry):
165 # All callers expect values to be a str object.
166 status_dict[key] = str(value)
167 # id is used by TestStatus to uniquely identify each Test Status
168 # obj.
169 status_dict['id'] = [status_dict['reason'], status_dict['hostname'],
170 status_dict['test_name']]
171 test_status.append(status_dict)
172
173 return [TestStatus(self, e) for e in test_status]
mblighc31e4022008-12-11 19:32:30 +0000174
175
176 def get_status_counts(self, job, **data):
177 entries = self.run('get_status_counts',
mbligh1ef218d2009-08-03 16:57:56 +0000178 group_by=['hostname', 'test_name', 'reason'],
mblighc31e4022008-12-11 19:32:30 +0000179 job_tag__startswith='%s-' % job, **data)
mbligh5280e3b2008-12-22 14:39:28 +0000180 return [TestStatus(self, e) for e in entries['groups']]
mblighc31e4022008-12-11 19:32:30 +0000181
182
mbligh5280e3b2008-12-22 14:39:28 +0000183class AFE(RpcClient):
mbligh17c75e62009-06-08 16:18:21 +0000184 def __init__(self, user=None, server=None, print_log=True, debug=False,
mbligh99b24f42009-06-08 16:45:55 +0000185 reply_debug=False, job=None):
mbligh17c75e62009-06-08 16:18:21 +0000186 self.job = job
Scott Zawalski347aaf42012-04-03 16:33:00 -0400187 super(AFE, self).__init__(path='/afe/server/noauth/rpc/',
mbligh99b24f42009-06-08 16:45:55 +0000188 user=user,
189 server=server,
190 print_log=print_log,
191 debug=debug,
192 reply_debug=reply_debug)
mblighc31e4022008-12-11 19:32:30 +0000193
mbligh1ef218d2009-08-03 16:57:56 +0000194
mbligh67647152008-11-19 00:18:14 +0000195 def host_statuses(self, live=None):
jamesren121eee62010-04-13 19:10:12 +0000196 dead_statuses = ['Repair Failed', 'Repairing']
mbligh67647152008-11-19 00:18:14 +0000197 statuses = self.run('get_static_data')['host_statuses']
198 if live == True:
mblighc2847b72009-03-25 19:32:20 +0000199 return list(set(statuses) - set(dead_statuses))
mbligh67647152008-11-19 00:18:14 +0000200 if live == False:
201 return dead_statuses
202 else:
203 return statuses
204
205
mbligh71094012009-12-19 05:35:21 +0000206 @staticmethod
207 def _dict_for_host_query(hostnames=(), status=None, label=None):
208 query_args = {}
mbligh4e545a52009-12-19 05:30:39 +0000209 if hostnames:
210 query_args['hostname__in'] = hostnames
211 if status:
212 query_args['status'] = status
213 if label:
214 query_args['labels__name'] = label
mbligh71094012009-12-19 05:35:21 +0000215 return query_args
216
217
218 def get_hosts(self, hostnames=(), status=None, label=None, **dargs):
219 query_args = dict(dargs)
220 query_args.update(self._dict_for_host_query(hostnames=hostnames,
221 status=status,
222 label=label))
223 hosts = self.run('get_hosts', **query_args)
224 return [Host(self, h) for h in hosts]
225
226
227 def get_hostnames(self, status=None, label=None, **dargs):
228 """Like get_hosts() but returns hostnames instead of Host objects."""
229 # This implementation can be replaced with a more efficient one
230 # that does not query for entire host objects in the future.
231 return [host_obj.hostname for host_obj in
232 self.get_hosts(status=status, label=label, **dargs)]
233
234
235 def reverify_hosts(self, hostnames=(), status=None, label=None):
236 query_args = dict(locked=False,
237 aclgroup__users__login=self.user)
238 query_args.update(self._dict_for_host_query(hostnames=hostnames,
239 status=status,
240 label=label))
mbligh4e545a52009-12-19 05:30:39 +0000241 return self.run('reverify_hosts', **query_args)
242
243
mbligh67647152008-11-19 00:18:14 +0000244 def create_host(self, hostname, **dargs):
mbligh54459c72009-01-21 19:26:44 +0000245 id = self.run('add_host', hostname=hostname, **dargs)
mbligh67647152008-11-19 00:18:14 +0000246 return self.get_hosts(id=id)[0]
247
248
MK Ryuacf35922014-10-03 14:56:49 -0700249 def get_host_attribute(self, attr, **dargs):
250 host_attrs = self.run('get_host_attribute', attribute=attr, **dargs)
251 return [HostAttribute(self, a) for a in host_attrs]
252
253
Chris Masone8abb6fc2012-01-31 09:27:36 -0800254 def set_host_attribute(self, attr, val, **dargs):
255 self.run('set_host_attribute', attribute=attr, value=val, **dargs)
256
257
mbligh67647152008-11-19 00:18:14 +0000258 def get_labels(self, **dargs):
259 labels = self.run('get_labels', **dargs)
mbligh5280e3b2008-12-22 14:39:28 +0000260 return [Label(self, l) for l in labels]
mbligh67647152008-11-19 00:18:14 +0000261
262
263 def create_label(self, name, **dargs):
mbligh54459c72009-01-21 19:26:44 +0000264 id = self.run('add_label', name=name, **dargs)
mbligh67647152008-11-19 00:18:14 +0000265 return self.get_labels(id=id)[0]
266
267
268 def get_acls(self, **dargs):
269 acls = self.run('get_acl_groups', **dargs)
mbligh5280e3b2008-12-22 14:39:28 +0000270 return [Acl(self, a) for a in acls]
mbligh67647152008-11-19 00:18:14 +0000271
272
273 def create_acl(self, name, **dargs):
mbligh54459c72009-01-21 19:26:44 +0000274 id = self.run('add_acl_group', name=name, **dargs)
mbligh67647152008-11-19 00:18:14 +0000275 return self.get_acls(id=id)[0]
276
277
mbligh54459c72009-01-21 19:26:44 +0000278 def get_users(self, **dargs):
279 users = self.run('get_users', **dargs)
280 return [User(self, u) for u in users]
281
282
mbligh1354c9d2008-12-22 14:56:13 +0000283 def generate_control_file(self, tests, **dargs):
284 ret = self.run('generate_control_file', tests=tests, **dargs)
285 return ControlFile(self, ret)
286
287
mbligh67647152008-11-19 00:18:14 +0000288 def get_jobs(self, summary=False, **dargs):
289 if summary:
290 jobs_data = self.run('get_jobs_summary', **dargs)
291 else:
292 jobs_data = self.run('get_jobs', **dargs)
mblighafbba0c2009-06-08 16:44:45 +0000293 jobs = []
294 for j in jobs_data:
295 job = Job(self, j)
296 # Set up some extra information defaults
297 job.testname = re.sub('\s.*', '', job.name) # arbitrary default
298 job.platform_results = {}
299 job.platform_reasons = {}
300 jobs.append(job)
301 return jobs
mbligh67647152008-11-19 00:18:14 +0000302
303
304 def get_host_queue_entries(self, **data):
305 entries = self.run('get_host_queue_entries', **data)
mblighf9e35862009-02-26 01:03:11 +0000306 job_statuses = [JobStatus(self, e) for e in entries]
mbligh99b24f42009-06-08 16:45:55 +0000307
308 # Sadly, get_host_queue_entries doesn't return platforms, we have
309 # to get those back from an explicit get_hosts queury, then patch
310 # the new host objects back into the host list.
311 hostnames = [s.host.hostname for s in job_statuses if s.host]
312 host_hash = {}
313 for host in self.get_hosts(hostname__in=hostnames):
314 host_hash[host.hostname] = host
315 for status in job_statuses:
316 if status.host:
Fang Deng97dafbc2015-04-23 23:06:18 -0700317 status.host = host_hash.get(status.host.hostname)
mblighf9e35862009-02-26 01:03:11 +0000318 # filter job statuses that have either host or meta_host
319 return [status for status in job_statuses if (status.host or
320 status.meta_host)]
mbligh67647152008-11-19 00:18:14 +0000321
322
MK Ryu1b2d7f92015-02-24 17:45:02 -0800323 def get_special_tasks(self, **data):
324 tasks = self.run('get_special_tasks', **data)
325 return [SpecialTask(self, t) for t in tasks]
326
327
J. Richard Barnette9f10c9f2015-04-13 16:44:50 -0700328 def get_host_special_tasks(self, host_id, **data):
329 tasks = self.run('get_host_special_tasks',
330 host_id=host_id, **data)
331 return [SpecialTask(self, t) for t in tasks]
332
333
J. Richard Barnette8dbd6d32015-05-01 11:01:12 -0700334 def get_host_status_task(self, host_id, end_time):
335 task = self.run('get_host_status_task',
J. Richard Barnette8abbfd62015-06-23 12:46:54 -0700336 host_id=host_id, end_time=end_time)
J. Richard Barnettebc9a7952015-04-16 17:43:27 -0700337 return SpecialTask(self, task) if task else None
338
339
J. Richard Barnette8abbfd62015-06-23 12:46:54 -0700340 def get_host_diagnosis_interval(self, host_id, end_time, success):
341 return self.run('get_host_diagnosis_interval',
342 host_id=host_id, end_time=end_time,
343 success=success)
344
345
mbligh67647152008-11-19 00:18:14 +0000346 def create_job(self, control_file, name=' ', priority='Medium',
Aviv Keshet3dd8beb2013-05-13 17:36:04 -0700347 control_type=control_data.CONTROL_TYPE_NAMES.CLIENT, **dargs):
mbligh67647152008-11-19 00:18:14 +0000348 id = self.run('create_job', name=name, priority=priority,
349 control_file=control_file, control_type=control_type, **dargs)
350 return self.get_jobs(id=id)[0]
351
352
Simran Basi01984f52015-10-12 15:36:45 -0700353 def abort_jobs(self, jobs):
354 """Abort a list of jobs.
355
356 Already completed jobs will not be affected.
357
358 @param jobs: List of job ids to abort.
359 """
360 for job in jobs:
361 self.run('abort_host_queue_entries', job_id=job)
362
363
mbligh5280e3b2008-12-22 14:39:28 +0000364class TestResults(object):
365 """
366 Container class used to hold the results of the tests for a job
367 """
368 def __init__(self):
369 self.good = []
370 self.fail = []
mbligh451ede12009-02-12 21:54:03 +0000371 self.pending = []
mbligh5280e3b2008-12-22 14:39:28 +0000372
373
374 def add(self, result):
mbligh451ede12009-02-12 21:54:03 +0000375 if result.complete_count > result.pass_count:
376 self.fail.append(result)
377 elif result.incomplete_count > 0:
378 self.pending.append(result)
mbligh5280e3b2008-12-22 14:39:28 +0000379 else:
mbligh451ede12009-02-12 21:54:03 +0000380 self.good.append(result)
mbligh5280e3b2008-12-22 14:39:28 +0000381
382
383class RpcObject(object):
mbligh67647152008-11-19 00:18:14 +0000384 """
385 Generic object used to construct python objects from rpc calls
386 """
387 def __init__(self, afe, hash):
388 self.afe = afe
389 self.hash = hash
390 self.__dict__.update(hash)
391
392
393 def __str__(self):
394 return dump_object(self.__repr__(), self)
395
396
mbligh1354c9d2008-12-22 14:56:13 +0000397class ControlFile(RpcObject):
398 """
399 AFE control file object
400
401 Fields: synch_count, dependencies, control_file, is_server
402 """
403 def __repr__(self):
404 return 'CONTROL FILE: %s' % self.control_file
405
406
mbligh5280e3b2008-12-22 14:39:28 +0000407class Label(RpcObject):
mbligh67647152008-11-19 00:18:14 +0000408 """
409 AFE label object
410
411 Fields:
412 name, invalid, platform, kernel_config, id, only_if_needed
413 """
414 def __repr__(self):
415 return 'LABEL: %s' % self.name
416
417
418 def add_hosts(self, hosts):
Chris Masone3a560bd2011-11-14 16:53:56 -0800419 return self.afe.run('label_add_hosts', id=self.id, hosts=hosts)
mbligh67647152008-11-19 00:18:14 +0000420
421
422 def remove_hosts(self, hosts):
Chris Masone3a560bd2011-11-14 16:53:56 -0800423 return self.afe.run('label_remove_hosts', id=self.id, hosts=hosts)
mbligh67647152008-11-19 00:18:14 +0000424
425
mbligh5280e3b2008-12-22 14:39:28 +0000426class Acl(RpcObject):
mbligh67647152008-11-19 00:18:14 +0000427 """
428 AFE acl object
429
430 Fields:
431 users, hosts, description, name, id
432 """
433 def __repr__(self):
434 return 'ACL: %s' % self.name
435
436
437 def add_hosts(self, hosts):
438 self.afe.log('Adding hosts %s to ACL %s' % (hosts, self.name))
439 return self.afe.run('acl_group_add_hosts', self.id, hosts)
440
441
442 def remove_hosts(self, hosts):
443 self.afe.log('Removing hosts %s from ACL %s' % (hosts, self.name))
444 return self.afe.run('acl_group_remove_hosts', self.id, hosts)
445
446
mbligh54459c72009-01-21 19:26:44 +0000447 def add_users(self, users):
448 self.afe.log('Adding users %s to ACL %s' % (users, self.name))
449 return self.afe.run('acl_group_add_users', id=self.name, users=users)
450
451
mbligh5280e3b2008-12-22 14:39:28 +0000452class Job(RpcObject):
mbligh67647152008-11-19 00:18:14 +0000453 """
454 AFE job object
455
456 Fields:
457 name, control_file, control_type, synch_count, reboot_before,
458 run_verify, priority, email_list, created_on, dependencies,
459 timeout, owner, reboot_after, id
460 """
461 def __repr__(self):
462 return 'JOB: %s' % self.id
463
464
mbligh5280e3b2008-12-22 14:39:28 +0000465class JobStatus(RpcObject):
mbligh67647152008-11-19 00:18:14 +0000466 """
467 AFE job_status object
468
469 Fields:
470 status, complete, deleted, meta_host, host, active, execution_subdir, id
471 """
472 def __init__(self, afe, hash):
MK Ryu1b2d7f92015-02-24 17:45:02 -0800473 super(JobStatus, self).__init__(afe, hash)
mbligh5280e3b2008-12-22 14:39:28 +0000474 self.job = Job(afe, self.job)
Dale Curtis8adf7892011-09-08 16:13:36 -0700475 if getattr(self, 'host'):
mbligh99b24f42009-06-08 16:45:55 +0000476 self.host = Host(afe, self.host)
mbligh67647152008-11-19 00:18:14 +0000477
478
479 def __repr__(self):
mbligh451ede12009-02-12 21:54:03 +0000480 if self.host and self.host.hostname:
481 hostname = self.host.hostname
482 else:
483 hostname = 'None'
484 return 'JOB STATUS: %s-%s' % (self.job.id, hostname)
mbligh67647152008-11-19 00:18:14 +0000485
486
MK Ryu1b2d7f92015-02-24 17:45:02 -0800487class SpecialTask(RpcObject):
488 """
489 AFE special task object
490 """
491 def __init__(self, afe, hash):
492 super(SpecialTask, self).__init__(afe, hash)
493 self.host = Host(afe, self.host)
494
495
496 def __repr__(self):
497 return 'SPECIAL TASK: %s' % self.id
498
499
mbligh5280e3b2008-12-22 14:39:28 +0000500class Host(RpcObject):
mbligh67647152008-11-19 00:18:14 +0000501 """
502 AFE host object
503
504 Fields:
505 status, lock_time, locked_by, locked, hostname, invalid,
506 synch_id, labels, platform, protection, dirty, id
507 """
508 def __repr__(self):
509 return 'HOST OBJECT: %s' % self.hostname
510
511
512 def show(self):
513 labels = list(set(self.labels) - set([self.platform]))
514 print '%-6s %-7s %-7s %-16s %s' % (self.hostname, self.status,
515 self.locked, self.platform,
516 ', '.join(labels))
517
518
mbligh54459c72009-01-21 19:26:44 +0000519 def delete(self):
520 return self.afe.run('delete_host', id=self.id)
521
522
mbligh6463c4b2009-01-30 00:33:37 +0000523 def modify(self, **dargs):
524 return self.afe.run('modify_host', id=self.id, **dargs)
525
526
mbligh67647152008-11-19 00:18:14 +0000527 def get_acls(self):
528 return self.afe.get_acls(hosts__hostname=self.hostname)
529
530
531 def add_acl(self, acl_name):
532 self.afe.log('Adding ACL %s to host %s' % (acl_name, self.hostname))
533 return self.afe.run('acl_group_add_hosts', id=acl_name,
534 hosts=[self.hostname])
535
536
537 def remove_acl(self, acl_name):
538 self.afe.log('Removing ACL %s from host %s' % (acl_name, self.hostname))
539 return self.afe.run('acl_group_remove_hosts', id=acl_name,
540 hosts=[self.hostname])
541
542
543 def get_labels(self):
544 return self.afe.get_labels(host__hostname__in=[self.hostname])
545
546
547 def add_labels(self, labels):
548 self.afe.log('Adding labels %s to host %s' % (labels, self.hostname))
549 return self.afe.run('host_add_labels', id=self.id, labels=labels)
550
551
552 def remove_labels(self, labels):
553 self.afe.log('Removing labels %s from host %s' % (labels,self.hostname))
554 return self.afe.run('host_remove_labels', id=self.id, labels=labels)
mbligh5b618382008-12-03 15:24:01 +0000555
556
mbligh54459c72009-01-21 19:26:44 +0000557class User(RpcObject):
558 def __repr__(self):
559 return 'USER: %s' % self.login
560
561
mbligh5280e3b2008-12-22 14:39:28 +0000562class TestStatus(RpcObject):
mblighc31e4022008-12-11 19:32:30 +0000563 """
564 TKO test status object
565
566 Fields:
567 test_idx, hostname, testname, id
568 complete_count, incomplete_count, group_count, pass_count
569 """
570 def __repr__(self):
571 return 'TEST STATUS: %s' % self.id
572
573
MK Ryuacf35922014-10-03 14:56:49 -0700574class HostAttribute(RpcObject):
575 """
576 AFE host attribute object
577
578 Fields:
579 id, host, attribute, value
580 """
581 def __repr__(self):
582 return 'HOST ATTRIBUTE %d' % self.id