autotest: Set rpm_state after check RPM configs

rpm_state can set states: MISSING_CONFIG, WRONG_CONFIG, WORKING

BUG=b:159957113
TEST=run local deployment action

./site_utils/deployment/prepare/main.py --results-dir /tr --hostname chromeos1-row4-rack8-host3 --host-info-file /tr/host_info_store/chromeos1-row4-rack8-host3.store run-pre-deploy-verification

./site_utils/deployment/prepare/main.py --results-dir /tr --hostname chromeos2-row4-rack10-host6 --host-info-file /tr/host_info_store/chromeos2-row4-rack10-host6.store run-pre-deploy-verification

Change-Id: Id95e6fc278920751365729c5629accfb670aa51b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/2593721
Tested-by: Otabek Kasimov <otabek@google.com>
Reviewed-by: Garry Wang <xianuowang@chromium.org>
Commit-Queue: Otabek Kasimov <otabek@google.com>
diff --git a/site_utils/admin_audit/constants.py b/site_utils/admin_audit/constants.py
index cbf3b95..0bb746d 100644
--- a/site_utils/admin_audit/constants.py
+++ b/site_utils/admin_audit/constants.py
@@ -13,3 +13,19 @@
 # Labels for hardware parts
 DUT_STORAGE_STATE_PREFIX = 'storage_state'
 SERVO_USB_STATE_PREFIX = 'servo_usb_state'
+
+# RPM states
+RPM_STATE_LABEL_PREFIX = 'rpm_state'
+RPM_STATE_UNKNOWN = 'UNKNOWN'
+# Config not provided
+RPM_STATE_MISSING_CONFIG = 'MISSING_CONFIG'
+# Config is incorrect or not working
+RPM_STATE_WRONG_CONFIG = 'WRONG_CONFIG'
+# Config present and working as expected
+RPM_STATE_WORKING = 'WORKING'
+RPM_STATES_SUPPORTED = (
+        RPM_STATE_UNKNOWN,
+        RPM_STATE_MISSING_CONFIG,
+        RPM_STATE_WRONG_CONFIG,
+        RPM_STATE_WORKING,
+)
diff --git a/site_utils/admin_audit/rpm_validator.py b/site_utils/admin_audit/rpm_validator.py
index 782675e..5453378 100644
--- a/site_utils/admin_audit/rpm_validator.py
+++ b/site_utils/admin_audit/rpm_validator.py
@@ -16,6 +16,7 @@
 import common
 from autotest_lib.client.common_lib import error
 from autotest_lib.site_utils.rpm_control_system import rpm_client
+from autotest_lib.site_utils.admin_audit import constants
 
 
 def _is_rpm_config_present(host):
@@ -25,10 +26,6 @@
 
     @raises: error.AutoservError if config present partially.
     """
-    if not hasattr(host, 'host_info_store'):
-        logging.info('Host:%s does not have host_info_store attribute',
-                     host.hostname)
-        return False
     host_info = host.host_info_store.get()
     powerunit_hostname = host_info.attributes.get('powerunit_hostname')
     powerunit_outlet = host_info.attributes.get('powerunit_outlet')
@@ -38,8 +35,10 @@
     if powerunit_hasinfo == (True, True):
         return True
     elif powerunit_hasinfo == (False, False):
+        set_rpm_state(host, constants.RPM_STATE_MISSING_CONFIG)
         return False
     else:
+        set_rpm_state(host, constants.RPM_STATE_WRONG_CONFIG)
         msg = "inconsistent power info: %s %s" % (powerunit_hostname,
                                                   powerunit_outlet)
         logging.error(msg)
@@ -147,42 +146,74 @@
                                 and device.
     """
     logging.info("Start RPM check for: %s", host.hostname)
+    if not hasattr(host, 'host_info_store'):
+        logging.info('Host:%s does not have host_info_store attribute',
+                     host.hostname)
+        return
+    if not _is_rpm_config_present(host):
+        logging.info("RPM config is not present. Skipping check.")
+        return
+
+    # In the lab we need trust that host-info will be correct.
+    power_info = host.host_info_store.get().get_label_value('power')
+    if not power_info:
+        raise error.AutoservError(
+                'Could not detect power-info in host-info. The information'
+                ' has to be provided by manufacture configs. Please file'
+                ' the bug agains Fleet Inventory')
+    has_battery = power_info == 'battery'
+
+    # Verify host-info against manufactory configs
     try:
-        if not _is_rpm_config_present(host):
-            logging.info("RPM config is not present. Skipping check.")
-            return
-
-        # Deploy is working only for device in the lab so we can trust that
-        # host-info will be present.
-        power_info = host.host_info_store.get().get_label_value('power')
-        if not power_info:
+        info = host.get_power_supply_info()
+    except Exception as e:
+        logging.debug('(Not critical) %s', e)
+        raise error.AutoservError('Could not detect power supply info')
+    if 'Battery' in info:
+        if not has_battery:
             raise error.AutoservError(
-                    'Could not detect power-info in host-info. The information'
-                    ' has to be provided by manufacture configs. Please file'
-                    ' the bug agains Fleet Inventory')
-        has_battery = power_info == 'battery'
-
-        # Verify host-info against manufactory configs
-        try:
-            info = host.get_power_supply_info()
-        except:
-            raise error.AutoservError('Could not detect power supply info')
-        if 'Battery' in info:
-            if not has_battery:
-                raise error.AutoservError(
-                        'Unexpected detected battery on the device')
-        elif has_battery:
-            raise error.AutoservError(
-                    'Battery is not detected on the device. But expected')
-
+                    'Unexpected detected battery on the device')
+    elif has_battery:
+        raise error.AutoservError(
+                'Battery is not detected on the device. But expected')
+    # Try to use RPM config to confirm tha information is correct.
+    try:
         if has_battery:
             _check_rpm_power_delivery_with_battery(host)
         else:
             _check_rpm_power_delivery_without_battery(host)
     except Exception as e:
+        set_rpm_state(host, constants.RPM_STATE_WRONG_CONFIG)
         logging.debug('(Not critical) %s', e)
         msg = getattr(e, 'message') if hasattr(e, 'message') else str(e)
         logging.info('RPM check fails! %s', msg)
         six.reraise(error.AutoservError, e)
     else:
+        set_rpm_state(host, constants.RPM_STATE_WORKING)
         logging.info("The host passed RPM config check!")
+
+
+def set_rpm_state(host, new_state):
+    """Set RPM state info labels to dut host_info.
+
+    @param host:        Any host with has host_info_store field
+    @param new_state:   New RPM state. Possible values are
+                        listed in RPM_STATES_SUPPORTED.
+    """
+    if not new_state:
+        logging.debug('RPM state is not specified.')
+        return
+    if new_state not in constants.RPM_STATES_SUPPORTED:
+        logging.debug('Not supported Incorrect RPM state.')
+        return
+    host_info = host.host_info_store.get()
+    prefix = constants.RPM_STATE_LABEL_PREFIX
+    old_state = host_info.get_label_value(prefix)
+    if old_state == new_state:
+        # do not need update
+        logging.debug('RPM state not changed. Skiping update')
+        return
+    host_info.set_version_label(prefix, new_state)
+    host.host_info_store.commit(host_info)
+    logging.info('Rpm state updated to %s (previous: %s)', new_state,
+                 old_state)