[autotest] Create a new get_status_task RPC to improve dut_status.
Previously, status was determined by fetching all jobs in a given
time range, and then searching back through the returned list for
a job that indicated host status. This had two drawbacks:
* If the job indicating status was earlier than the start time
of the query, no status could be determined.
* The extra data returned in the query slowed it down.
This adds a new RPC that finds the task through a single database
query searching for the specific necessary condition. This should
largely eliminate the '--' status, and is notably faster (possibly 4
times faster, or more).
This also changes the rules for what constitues a diagnostic job or
task, by changing the diagnosis associated with test jobs. This
is done because
* It makes determining status possible with a query to a single
table.
* The experience has been that test jobs don't indicate a
diagnosis anyway.
This is the first of two parts; this change creates the server
side of the new RPC. This change must be pushed to prod before
the follow-on change for the client side.
BUG=chromium:463632
TEST=Run dut_status using a local instance pointed at the prod database
Change-Id: Ifc61387f0cdc46ceb32062663c6a73c5d4bcfb4f
Reviewed-on: https://chromium-review.googlesource.com/265783
Reviewed-by: Richard Barnette <jrbarnette@chromium.org>
Commit-Queue: Richard Barnette <jrbarnette@chromium.org>
Tested-by: Richard Barnette <jrbarnette@chromium.org>
diff --git a/frontend/afe/rpc_interface.py b/frontend/afe/rpc_interface.py
index 7d30761..352e77f 100644
--- a/frontend/afe/rpc_interface.py
+++ b/frontend/afe/rpc_interface.py
@@ -46,6 +46,7 @@
from autotest_lib.server import frontend
from autotest_lib.server import utils
from autotest_lib.server.cros.dynamic_suite import tools
+from autotest_lib.site_utils import status_history
_timer = autotest_stats.Timer('rpc_interface')
@@ -1138,15 +1139,54 @@
if not host.shard:
return get_special_tasks(host_id=host_id, **filter_data)
else:
- # The return value from AFE.get_special_tasks() is a list of
- # post-processed objects that aren't JSON-serializable. So,
- # we have to call AFE.run() to get the raw, serializable
- # output from the shard.
+ # The return values from AFE methods are post-processed
+ # objects that aren't JSON-serializable. So, we have to
+ # call AFE.run() to get the raw, serializable output from
+ # the shard.
shard_afe = frontend.AFE(server=host.shard.rpc_hostname())
return shard_afe.run('get_special_tasks',
host_id=host_id, **filter_data)
+def get_status_task(host_id, end_time):
+ """Get the special task identifying a host's status.
+
+ Returns information for a single special task for a host
+ identifying whether the host was working or broken at the given
+ `end_time`. A successful task indicates a working host; a
+ failed task indicates a broken host.
+
+ If the host is managed by a shard, this call forwards the
+ request.
+
+ @param host_id Id in the database of the target host.
+ @param end_time Time reference for the host's status.
+
+ @return A single task; its status (successful or not)
+ corresponds to the status of the host (working or
+ broken) at the given time. If no task is found, return
+ `None`.
+
+ """
+ host = models.Host.smart_get(host_id)
+ if not host.shard:
+ tasklist = rpc_utils.prepare_rows_as_nested_dicts(
+ status_history.get_status_task(host_id, end_time),
+ ('host', 'queue_entry'))
+ if tasklist:
+ return tasklist[0]
+ else:
+ return None
+ else:
+ # The return values from AFE methods are post-processed
+ # objects that aren't JSON-serializable. So, we have to
+ # call AFE.run() to get the raw, serializable output from
+ # the shard.
+ shard_afe = frontend.AFE(server=host.shard.rpc_hostname())
+ return shard_afe.run('get_status_task',
+ host_id=host_id, end_time=end_time)
+
+
# support for host detail view
def get_host_queue_entries_and_special_tasks(host_id, query_start=None,