[autotest] Add heartbeat AFE endpoint to shard Autotest

To improve the workload the autotest setup can handle, jobs should
be executed by multiple shards. They are sharded by type of board.

This a HTTP accessible endpoint to AFE. This assigns jobs and hosts
to moblabs and returns them as records to insert into a shard's
local database.

TEST=Ran suites and tried manually retrieving jobs
DEPLOY=scheduler,apache,host-scheduler

Change-Id: I20ac41364e4c67e17883729181af798e18d8093e
Reviewed-on: https://chromium-review.googlesource.com/217968
Reviewed-by: Jakob Jülich <jakobjuelich@chromium.org>
Reviewed-by: Fang Deng <fdeng@chromium.org>
Commit-Queue: Jakob Jülich <jakobjuelich@chromium.org>
Tested-by: Jakob Jülich <jakobjuelich@chromium.org>
diff --git a/frontend/afe/rpc_utils.py b/frontend/afe/rpc_utils.py
index 687ab15..f1f6ec5 100644
--- a/frontend/afe/rpc_utils.py
+++ b/frontend/afe/rpc_utils.py
@@ -926,4 +926,30 @@
                                    start_time, end_time, **filter_data_common),
            inject_times_to_filter('time_started__gte', 'time_started__lte',
                                   start_time, end_time,
-                                  **filter_data_special_tasks))
\ No newline at end of file
+                                  **filter_data_special_tasks))
+
+
+def retrieve_shard(shard_hostname):
+    """
+    Retrieves the shard with the given hostname from the database or creates it.
+
+    @param shard_hostname: Hostname of the shard to retrieve
+
+    @returns: Shard object
+    """
+    try:
+        shard = models.Shard.smart_get(shard_hostname)
+    except models.Shard.DoesNotExist:
+        shard = models.Shard.objects.create(hostname=shard_hostname)
+    return shard
+
+
+def find_records_for_shard(shard):
+    """Find records that should be sent to a shard.
+
+    @returns: Tuple of two lists for hosts and jobs: (hosts, jobs)
+    """
+    hosts = models.Host.assign_to_shard(shard)
+    jobs = models.Job.assign_to_shard(shard)
+
+    return hosts, jobs