[autotest] Endpoints for syncing jobs and hqes back to master

The status of jobs that were completed on a shard should be visible
in the master AFE, so a human can easily see which jobs have been run in one
central place.

This adds the functionality to the AFE to retrieve newer versions of
jobs and hqes from shards.

This is a newer version of CL:213901 which was reverted because of
http://crbug.com/418022.

BUG=418022
DEPLOY=apache, afe
TEST=Ran Suites

Change-Id: I3c9a35c78585a43d193874decbb7b16216b2c69a
Reviewed-on: https://chromium-review.googlesource.com/220141
Reviewed-by: Fang Deng <fdeng@chromium.org>
Tested-by: Jakob Jülich <jakobjuelich@chromium.org>
Commit-Queue: Jakob Jülich <jakobjuelich@chromium.org>
diff --git a/frontend/afe/site_rpc_interface.py b/frontend/afe/site_rpc_interface.py
index b7a945c..9e175d5 100644
--- a/frontend/afe/site_rpc_interface.py
+++ b/frontend/afe/site_rpc_interface.py
@@ -305,16 +305,23 @@
                     process_pool_size=4))
 
 
-def shard_heartbeat(shard_hostname):
-    """Register shard if it doesn't exist, then assign hosts and jobs.
+def shard_heartbeat(shard_hostname, jobs=(), hqes=()):
+    """Register shard if not existing, then assign hosts and jobs.
 
     @param shard_hostname: Hostname of the calling shard
+    @param jobs: Jobs in serialized form that should be updated with newer
+                 status from a shard.
+    @param hqes: Hostqueueentries in serialized form that should be updated with
+                 newer status from a shard. Note that for every hostqueueentry
+                 the corresponding job must be in jobs.
+
     @returns: Serialized representations of hosts, jobs and their dependencies
               to be inserted into a shard's database.
     """
     timer = stats.Timer('shard_heartbeat')
     with timer:
         shard_obj = rpc_utils.retrieve_shard(shard_hostname=shard_hostname)
+        rpc_utils.persist_records_sent_from_shard(shard_obj, jobs, hqes)
         hosts, jobs = rpc_utils.find_records_for_shard(shard_obj)
         return {
             'hosts': [host.serialize() for host in hosts],