autotest: Update servo-topology to the host-info

Regenerate servo-topology only if started servod successful.

BUG=b:166680257
TEST=run local

servo_v4 type-c
./server/autoserv -s --host-info-subdir host_info_store -m chromeos1-row4-rack4-host3 --lab True --local-only-host-info True -R -r /tr/

servo_v3 (no topology)
./server/autoserv -s --host-info-subdir host_info_store -m chromeos1-row4-rack1-host4 --lab True --local-only-host-info True -R -r /tr/

servo_v4 type-a
./server/autoserv -s --host-info-subdir host_info_store -m chromeos1-row4-rack8-host2 --lab True --local-only-host-info True -R -r /tr/

servo_v4 dual
./server/autoserv -s --host-info-subdir host_info_store -m chromeos1-row2-rack11-host6 --lab True --local-only-host-info True -R -r /tr/

with updated control to request servo
test_that --args="servo_host=chromeos1-row4-rack4-labstation servo_port=9995 servo_serial=C1903145222" --board=eve --autotest_dir=.  chromeos1-row4-rack4-host1 dummy_PassServer

Change-Id: I7a74f5f88bf9113244168742630f95371ddde017
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/2477158
Tested-by: Otabek Kasimov <otabek@google.com>
Reviewed-by: Garry Wang <xianuowang@chromium.org>
Commit-Queue: Otabek Kasimov <otabek@google.com>
diff --git a/server/hosts/servo_host.py b/server/hosts/servo_host.py
index 848caa5..01d9518 100644
--- a/server/hosts/servo_host.py
+++ b/server/hosts/servo_host.py
@@ -38,6 +38,7 @@
 from autotest_lib.server.cros.faft.utils import config
 from autotest_lib.client.common_lib import global_config
 from autotest_lib.site_utils.admin_audit import servo_updater
+from autotest_lib.server.cros.servo.topology import servo_topology
 
 try:
     from chromite.lib import metrics
@@ -154,6 +155,7 @@
         # get replaced.
         self.smart_usbhub = None
         self._servo = None
+        self._topology = None
         self._tunnel_proxy = None
         self._tunnel_proxy_lock = threading.Lock()
         self._initial_instance_ts = None
@@ -200,6 +202,9 @@
         self.servo_serial = servo_serial
         self.servo_setup = servo_setup
 
+        if self.is_servo_topology_supported():
+            self._topology = servo_topology.ServoTopology(self)
+
         # The location of the log files on the servo host for this instance.
         self.remote_log_dir = '%s_%s' % (self.SERVOD_LOG_PREFIX,
                                          self.servo_port)
@@ -329,6 +334,8 @@
             self._servo_state = servo_constants.SERVO_STATE_WORKING
             self.record('INFO', None, None,
                         'ServoHost verify set servo_state as WORKING')
+            if self._topology:
+                self._topology.generate()
         except Exception as e:
             if not self.is_localhost():
                 self._servo_state = self.determine_servo_state()
@@ -565,6 +572,8 @@
             # reboot request created by this servo because it passed repair.
             if self.is_labstation():
                 self.withdraw_reboot_request()
+            if self._topology:
+                self._topology.generate()
         except Exception as e:
             if not self.is_localhost():
                 self._servo_state = self.determine_servo_state()
@@ -638,7 +647,7 @@
             cmd += ' SERIAL=%s' % self.servo_serial
 
         # Start servod with dual_v4 based on servo_setup.
-        if self.servo_setup == servo_constants.SERVO_SETUP_VALUE_DUAL_V4:
+        if self.is_dual_setup():
             cmd += ' DUAL_V4=1'
 
         # Start servod with CONFIG=cr50.xml which required for some pools.
@@ -1336,6 +1345,7 @@
         start_servod = self.get_verifier_state('servod_job')
         create_servo = self.get_verifier_state('servod_connection')
         init_servo = self.get_verifier_state('servod_control')
+        servo_topology = self.get_verifier_state('servo_topology')
         dut_connected = self.get_verifier_state('dut_connected')
         pwr_button = self.get_verifier_state('pwr_button')
         lid_open = self.get_verifier_state('lid_open')
@@ -1358,6 +1368,9 @@
             elif self._is_servo_board_present_on_servo_v3() == False:
                 return servo_constants.SERVO_STATE_NOT_CONNECTED
 
+        if servo_topology == hosts.VERIFY_FAILED:
+            return servo_constants.SERVO_STATE_TOPOLOGY_ISSUE
+
         if dut_connected == hosts.VERIFY_FAILED:
             if pwr_button == hosts.VERIFY_SUCCESS:
                 # unexpected case
@@ -1412,6 +1425,28 @@
         logging.info('We do not have special state for this failure yet :)')
         return servo_constants.SERVO_STATE_BROKEN
 
+    def is_servo_topology_supported(self):
+        """Check if servo_topology is supported."""
+        if not self.is_labstation():
+            logging.info('Servo-topology supported only for labstation.')
+            return False
+        if not self.servo_serial:
+            logging.info('Servo-topology required a servo serial.')
+            return False
+        return True
+
+    def get_topology(self):
+        """Get servo topology."""
+        return self._topology
+
+    def is_dual_setup(self):
+        """Check is servo will run in dual setup.
+
+        Dual setup used only for servo_v4 when used ccd_cr50 and servo_micro
+        at the same time.
+        """
+        return self.servo_setup == servo_constants.SERVO_SETUP_VALUE_DUAL_V4
+
 
 def make_servo_hostname(dut_hostname):
     """Given a DUT's hostname, return the hostname of its servo.