[autotest] Respect exclusive --in-lab or --host-attributes arguments

These two arguments to autoserv are not intended to be used together.
The only user of --host-attributes are test_that / test_droid that use
it for tests run outside the context of the lab via
test_runner_utils.perform_run_from_autotest_root.

This CL enforces this mutual exclusion to make way for a future CL that
depends on this property.

+ As we begin to use HostInfoStore for storing the attribute
information, copy the host_attributes into the store.

BUG=chromium:678430
TEST=(1) test_that / test_droid still works.
     (2) in-lab hwtests via moblab.
CQ-DEPEND=CL:519569

Change-Id: I0dcb3096a4797143df796855bf3babc155e76c67
Reviewed-on: https://chromium-review.googlesource.com/517771
Commit-Ready: Prathmesh Prabhu <pprabhu@chromium.org>
Tested-by: Prathmesh Prabhu <pprabhu@chromium.org>
Reviewed-by: Prathmesh Prabhu <pprabhu@chromium.org>
diff --git a/server/autoserv_parser.py b/server/autoserv_parser.py
index 82f6689..a814e80 100644
--- a/server/autoserv_parser.py
+++ b/server/autoserv_parser.py
@@ -250,8 +250,15 @@
         if self.options.image:
             self.options.install_before = True
             self.options.image =  self.options.image.strip()
+
         self.options.host_attributes = ast.literal_eval(
                 self.options.host_attributes)
+        if self.options.lab and self.options.host_attributes:
+            logging.warn(
+                    '--lab and --host-attributes are mutually exclusive. '
+                    'Ignoring custom host attributes: %s',
+                    str(self.options.host_attributes))
+            self.options.host_attributes = []
 
 
 # create the one and only one instance of autoserv_parser
diff --git a/server/server_job.py b/server/server_job.py
index 83be22a..d96e609 100644
--- a/server/server_job.py
+++ b/server/server_job.py
@@ -95,17 +95,32 @@
             'host_info_store': A host_info.CachingHostInfoStore object to obtain
                     host information. A stub if in_lab is False.
     """
-    if host_attributes is None:
-        host_attributes = dict()
     machine_dict_list = []
     for machine in machine_names:
-        afe_host = _create_afe_host(machine, in_lab)
-        afe_host.attributes.update(host_attributes)
+        # See autoserv_parser.parse_args. Only one of in_lab or host_attributes
+        # can be provided.
+        if not in_lab:
+            afe_host = server_utils.EmptyAFEHost()
+            host_info_store = host_info.InMemoryHostInfoStore()
+            if host_attributes is not None:
+                afe_host.attributes.update(host_attributes)
+                info = host_info.HostInfo(attributes=host_attributes)
+                host_info_store.commit(info)
+        elif host_attributes:
+            raise error.AutoservError(
+                    'in_lab and host_attribute are mutually exclusive. '
+                    'Obtained in_lab:%s, host_attributes:%s'
+                    % (in_lab, host_attributes))
+        else:
+            afe_host = _create_afe_host(machine)
+            host_info_store = _create_host_info_store(machine)
+
         machine_dict_list.append({
                 'hostname' : machine,
                 'afe_host' : afe_host,
-                'host_info_store': _create_host_info_store(machine, in_lab),
+                'host_info_store': host_info_store,
         })
+
     return machine_dict_list
 
 
@@ -1427,16 +1442,12 @@
     return test.testname == 'SERVER_JOB'
 
 
-def _create_afe_host(hostname, in_lab):
-    """Create a real or stub frontend.Host object.
+def _create_afe_host(hostname):
+    """Create an afe_host object backed by the AFE.
 
     @param hostname: Name of the host for which we want the Host object.
-    @param in_lab: (bool) whether we have access to the AFE.
     @returns: An object of type frontend.AFE
     """
-    if not in_lab:
-        return server_utils.EmptyAFEHost()
-
     afe = frontend_wrappers.RetryingAFE(timeout_min=5, delay_sec=10)
     hosts = afe.get_hosts(hostname=hostname)
     if not hosts:
@@ -1445,16 +1456,12 @@
     return hosts[0]
 
 
-def _create_host_info_store(hostname, in_lab):
+def _create_host_info_store(hostname):
     """Create a real or stub afe_store.AfeStore object.
 
     @param hostname: Name of the host for which we want the store.
-    @param in_lab: (bool) whether we have access to the AFE.
     @returns: An object of type afe_store.AfeStore
     """
-    if not in_lab:
-        return host_info.InMemoryHostInfoStore()
-
     host_info_store = afe_store.AfeStore(hostname)
     try:
         host_info_store.get(force_refresh=True)