autotest: Move host dependency check inside verifier.

Moved it to minimize fail case if host is not available.
AdminAudit is starting with the set of actions and all of them has to
run if possible. By this move we allowed each verifier to check what
required to run.
If dependency not provided we can skip of the action.

BUG=chromium:1069101, chromium:1059439
TEST=unittests, presubmit, run local

./site_utils/admin_audit/main.py --hostname chromeos1-row4-rack4-host4   --results-dir /tr --host-info-file /tr/host_info_store/chromeos1-row4-rack4-host4.store   verify-dut-storage verify-servo-usb-drive verify-servo-fw
./site_utils/admin_audit/main.py --hostname chromeos1-row4-rack4-host3   --results-dir /tr --host-info-file /tr/host_info_store/chromeos1-row4-rack4-host3.store   verify-dut-storage verify-servo-usb-drive verify-servo-fw

Change-Id: I9dab24a61290970ff95b4e0431c6f74381f972cc
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/2253052
Tested-by: Otabek Kasimov <otabek@google.com>
Commit-Queue: Otabek Kasimov <otabek@google.com>
Reviewed-by: Garry Wang <xianuowang@chromium.org>
diff --git a/site_utils/admin_audit/base.py b/site_utils/admin_audit/base.py
index a4730f7..a2153a8 100644
--- a/site_utils/admin_audit/base.py
+++ b/site_utils/admin_audit/base.py
@@ -54,6 +54,19 @@
                             prefix, state, old_state)
             self._dut_host.host_info_store.commit(host_info)
 
+    def host_is_up(self):
+        """Check if the host is up and available by ssh"""
+        return self._dut_host.is_up(timeout=20)
+
+    def servo_is_up(self):
+        """Check if servo host is up and servod is initialized"""
+        return self.servo_host_is_up() and bool(self._dut_host.servo)
+
+    def servo_host_is_up(self):
+        """Check if servo host is up and available by ssh"""
+        return (self._dut_host._servo_host
+            and self._dut_host._servo_host.is_up(timeout=20))
+
 
 class _BaseDUTVerifier(_BaseVerifier):
     """Base verify check availability of DUT before run actual verifier.
@@ -69,10 +82,6 @@
         """Vallidate the host reachable by SSH and run verifier"""
         if not self._dut_host:
             raise AuditError('host is not present')
-        if not self._dut_host.is_up(timeout=20):
-            # for failed DUTs will add logic to try to load them from USB
-            # need more analysis to confirm it
-            raise AuditError('host is not ssh-able')
         self._verify(**args)
 
 
@@ -81,15 +90,12 @@
 
     Verifier run audit actions against ServoHost.
     """
-
     def get_host(self):
         """Return ServoHost"""
         return self._dut_host._servo_host
 
     def verify(self):
         """Vallidate the host and servo initialized and run verifier"""
-        if not self._dut_host or not self._dut_host._servo_host:
+        if not self._dut_host:
             raise AuditError('host is not present')
-        if not self._dut_host.servo:
-            raise AuditError('servo is not initialized')
         self._verify()
diff --git a/site_utils/admin_audit/main.py b/site_utils/admin_audit/main.py
index 1162edf..f31577f 100755
--- a/site_utils/admin_audit/main.py
+++ b/site_utils/admin_audit/main.py
@@ -22,6 +22,7 @@
 from autotest_lib.client.common_lib import logging_manager
 from autotest_lib.server import server_logging_config
 from autotest_lib.server.hosts import factory
+from autotest_lib.server.hosts import servo_host
 
 import verifiers
 
@@ -43,11 +44,15 @@
     ACTION_VERIFY_SERVO_FW: verifiers.VerifyServoFw
 }
 
-ACTIONS_REQUIRED_SERVO = set([
+# Actions required Servod service
+ACTIONS_REQUIRED_SERVOD = set([
     ACTION_VERIFY_SERVO_USB,
-    ACTION_VERIFY_SERVO_FW
 ])
 
+# Actions required ServoHost without Servod process
+ACTIONS_REQUIRED_SERVO_HOST = set([
+    ACTION_VERIFY_SERVO_FW,
+])
 
 class DutAuditError(Exception):
   """Generic error raised during DUT audit."""
@@ -67,17 +72,29 @@
     logging.debug('audit command was: %s', ' '.join(sys.argv))
     logging.debug('audit parsed options: %s', opts)
 
+    # Initialize ServoHost without running Servod process.
+    need_servo_host = bool(set(opts.actions) & ACTIONS_REQUIRED_SERVO_HOST)
+    # Initialize ServoHost with running Servod process.
+    need_servod = bool(set(opts.actions) & ACTIONS_REQUIRED_SERVOD)
     try:
-        need_servo = _need_servo(opts.actions)
         host_object = factory.create_target_host(
             opts.hostname,
             host_info_path=opts.host_info_file,
-            try_lab_servo=need_servo)
+            try_lab_servo=need_servod)
     except Exception as err:
         logging.error("fail to create host: %s", err)
         return RETURN_CODES.OTHER_FAILURES
 
     with host_object as host:
+        if need_servo_host and not need_servod:
+            try:
+                host.set_servo_host(servo_host.ServoHost(
+                    **servo_host.get_servo_args_for_host(host)
+                ))
+            except Exception as err:
+                logging.error("fail to init servo host: %s", err)
+                return RETURN_CODES.OTHER_FAILURES
+
         for action in opts.actions:
             if opts.dry_run:
                 logging.info('DRY RUN: Would have run actions %s', action)
@@ -90,15 +107,6 @@
     return RETURN_CODES.OK
 
 
-def _need_servo(actions=[]):
-    need_servo = bool(set(actions) & ACTIONS_REQUIRED_SERVO)
-    if need_servo:
-        logging.debug('The servo required by the process!')
-    else:
-        logging.debug('The servo does not required by the process!')
-    return need_servo
-
-
 def _verify(action, host):
     """Run verifier for the action with targeted host.
 
diff --git a/site_utils/admin_audit/verifiers.py b/site_utils/admin_audit/verifiers.py
index 25c9ab2..42655d1 100644
--- a/site_utils/admin_audit/verifiers.py
+++ b/site_utils/admin_audit/verifiers.py
@@ -9,6 +9,7 @@
 import base
 import constants
 import servo_updater
+
 from autotest_lib.server.cros.storage import storage_validate as storage
 from autotest_lib.client.common_lib import utils as client_utils
 
@@ -41,6 +42,9 @@
         self._state = None
 
     def _verify(self, set_label=True):
+        if not self.host_is_up():
+            logging.info('Host is down; Skipping the verification')
+            return
         try:
             validator = storage.StorageStateValidator(self.get_host())
             storage_type = validator.get_type()
@@ -88,6 +92,9 @@
     No such device or address while trying to determine device size
     """
     def _verify(self):
+        if not self.servo_is_up():
+            logging.info('Servo not initialized; Skipping the verification')
+            return
         servo = self.get_host().get_servo()
         usb = servo.probe_host_usb_dev()
         if not usb:
@@ -157,6 +164,9 @@
     ]
 
     def _verify(self):
+        if not self.servo_host_is_up():
+            logging.info('Servo host is down; Skipping the verification')
+            return
         host = self.get_host()
         # create all updater
         updaters = [updater(host) for updater in self.UPDATERS]
@@ -165,7 +175,7 @@
             supported = updater.check_needs()
             logging.debug('The board %s is supported: %s',
                           updater.get_board(), supported)
-        # to run updater we need stop servod
+        # to run updater we need make sure the servod is not running
         host.stop_servod()
         #  run update
         for updater in updaters:
@@ -179,5 +189,3 @@
                              updater.get_board())
                 logging.debug('Fail update firmware for %s: %s',
                               updater.get_board(), str(e))
-        # starting servod to restore previous state
-        host.start_servod()