autotest: Cherry-pick TKO Skylab hostinfo support

Contains the following commits:

  autotest: Make tko recognize hostinfo format
  Reviewed-on: https://chromium-review.googlesource.com/1290351

  autotest: Add hostinfo support for platform keyval
  Reviewed-on: https://chromium-review.googlesource.com/1309014

  autotest: Fix querying hostinfo subdir
  Reviewed-on: https://chromium-review.googlesource.com/1311736

  autotest: Use absolute path for keyval existence check
  Reviewed-on: https://chromium-review.googlesource.com/c/1327519

  autotest: Fix Skylab path for hostinfo
  Reviewed-on: https://chromium-review.googlesource.com/c/1327824

  autotest: Fix format of keyvals from hostinfo
  Reviewed-on: https://chromium-review.googlesource.com/c/1327825

BUG=b:116258296
TEST=None

Change-Id: I1d582c89377902314037cfdab1823c5385b99108
Reviewed-on: https://chromium-review.googlesource.com/c/1359354
Reviewed-by: Prathmesh Prabhu <pprabhu@chromium.org>
Commit-Queue: Allen Li <ayatane@chromium.org>
Tested-by: Allen Li <ayatane@chromium.org>
Trybot-Ready: Allen Li <ayatane@chromium.org>
diff --git a/tko/models.py b/tko/models.py
index e1226bb..dea6534 100644
--- a/tko/models.py
+++ b/tko/models.py
@@ -1,6 +1,7 @@
 import json
 import os
 
+from autotest_lib.server.hosts import file_store
 from autotest_lib.client.common_lib import utils
 from autotest_lib.tko import tast
 from autotest_lib.tko import utils as tko_utils
@@ -292,9 +293,17 @@
         @return A dictionary representing the host keyvals.
 
         """
+        keyval_path = os.path.join('host_keyvals', hostname)
         # The host keyval is <job_dir>/host_keyvals/<hostname> if it exists.
-        return test._parse_keyval(job_dir,
-                                  os.path.join('host_keyvals', hostname))
+        # Otherwise we're running on Skylab which uses hostinfo.
+        if not os.path.exists(os.path.join(job_dir, keyval_path)):
+            tko_utils.dprint("trying to use hostinfo")
+            try:
+                return _parse_hostinfo_keyval(job_dir, hostname)
+            except Exception as e:
+                # If anything goes wrong, log it and just use the old flow.
+                tko_utils.dprint("tried using hostinfo: %s" % e)
+        return test._parse_keyval(job_dir, keyval_path)
 
 
     @staticmethod
@@ -311,6 +320,30 @@
         return test._parse_keyval(job_dir, 'keyval')
 
 
+def _parse_hostinfo_keyval(job_dir, hostname):
+    """
+    Parse host keyvals from hostinfo.
+
+    @param job_dir: The string directory name of the associated job.
+    @param hostname: The string hostname.
+
+    @return A dictionary representing the host keyvals.
+
+    """
+    # The hostinfo path looks like:
+    # host_info_store/chromeos6-row4-rack11-host6.store
+    #
+    # TODO(ayatane): We should pass hostinfo path explicitly.
+    subdir = 'host_info_store'
+    hostinfo_path = os.path.join(job_dir, subdir, hostname + '.store')
+    store = file_store.FileStore(hostinfo_path)
+    hostinfo = store.get()
+    # TODO(ayatane): Investigate if urllib.quote is better.
+    label_string = ','.join(label.replace(':', '%3A')
+                            for label in hostinfo.labels)
+    return {'labels': label_string, 'platform': hostinfo.model}
+
+
 class patch(object):
     """Represents a patch."""
 
diff --git a/tko/parse.py b/tko/parse.py
index 2425cb5..28db6d2 100755
--- a/tko/parse.py
+++ b/tko/parse.py
@@ -1,7 +1,6 @@
 #!/usr/bin/python -u
 
 import collections
-import datetime
 import errno
 import fcntl
 import json