Refactor server side code a bit ahead of last few AU tests.

We want to share common code between the client and server base classes.
To do this I have introduced a new class update_engine_util. It will
hold common variables and methods.

The client and server base classes will then use multiple inheritance.
To inherit from update_engine_util and the standard autotest test class.

The differences between the client and server is the run() function
used: either utils.run for client or host.run for server. The will be
defined in the initialize() function of each base class.

BUG=chromium:831034
BUG=chromium:817913
TEST=OOBE regular test, OOBE interrupt, new interrupt test, bad sha256

Change-Id: I4c22a8485c0ec30e27518de153371ec0cffba84d
Reviewed-on: https://chromium-review.googlesource.com/1010884
Commit-Ready: David Haddock <dhaddock@chromium.org>
Tested-by: David Haddock <dhaddock@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
diff --git a/server/site_tests/autoupdate_ForcedOOBEUpdate/autoupdate_ForcedOOBEUpdate.py b/server/site_tests/autoupdate_ForcedOOBEUpdate/autoupdate_ForcedOOBEUpdate.py
index 5036527..59e90b0 100644
--- a/server/site_tests/autoupdate_ForcedOOBEUpdate/autoupdate_ForcedOOBEUpdate.py
+++ b/server/site_tests/autoupdate_ForcedOOBEUpdate/autoupdate_ForcedOOBEUpdate.py
@@ -1,16 +1,13 @@
 # Copyright 2017 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-import json
+
 import logging
-import os
 import random
 import time
 
 from autotest_lib.client.common_lib import error
-from autotest_lib.client.common_lib import lsbrelease_utils
 from autotest_lib.client.common_lib.cros import tpm_utils
-from autotest_lib.server import autotest
 from autotest_lib.server.cros.update_engine import update_engine_test
 from chromite.lib import retry_util
 
@@ -18,132 +15,38 @@
     """Runs a forced autoupdate during OOBE."""
     version = 1
 
-    # We override the default lsb-release file.
-    _CUSTOM_LSB_RELEASE = '/mnt/stateful_partition/etc/lsb-release'
-
-    # Version we tell the DUT it is on before update.
-    _CUSTOM_LSB_VERSION = '0.0.0.0'
-
-    # Expected hostlog events during update: 4 during rootfs
-    _ROOTFS_HOSTLOG_EVENTS = 4
-
 
     def cleanup(self):
         self._host.run('rm %s' % self._CUSTOM_LSB_RELEASE, ignore_status=True)
 
         # Get the last two update_engine logs: before and after reboot.
-        files = self._host.run('ls -t -1 '
-                               '/var/log/update_engine/').stdout.splitlines()
+        files = self._host.run('ls -t -1 %s' %
+                               self._UPDATE_ENGINE_LOG_DIR).stdout.splitlines()
         for i in range(2):
-            self._host.get_file('/var/log/update_engine/%s' % files[i],
-                                self.resultsdir)
+            self._host.get_file('%s%s' % (self._UPDATE_ENGINE_LOG_DIR,
+                                          files[i]), self.resultsdir)
         cmd = 'update_engine_client --update_over_cellular=no'
         retry_util.RetryException(error.AutoservRunError, 2, self._host.run,
                                   cmd)
         super(autoupdate_ForcedOOBEUpdate, self).cleanup()
 
-    def _get_chromeos_version(self):
-        """Read the ChromeOS version from /etc/lsb-release."""
-        lsb = self._host.run('cat /etc/lsb-release').stdout
-        return lsbrelease_utils.get_chromeos_release_version(lsb)
 
-
-    def _create_hostlog_files(self):
-        """Create the two hostlog files for the update.
-
-        To ensure the update was succesful we need to compare the update
-        events against expected update events. There is a hostlog for the
-        rootfs update and for the post reboot update check.
-        """
-        hostlog = self._omaha_devserver.get_hostlog(self._host.ip,
-                                                    wait_for_reboot_events=True)
-        logging.info('Hostlog: %s', hostlog)
-
-        # File names to save the hostlog events to.
-        rootfs_hostlog = os.path.join(self.resultsdir, 'hostlog_rootfs')
-        reboot_hostlog = os.path.join(self.resultsdir, 'hostlog_reboot')
-
-        # Each time we reboot in the middle of an update we ping omaha again
-        # for each update event. So parse the list backwards to get the final
-        # events.
-        with open(reboot_hostlog, 'w') as outfile:
-            json.dump(hostlog[-1:], outfile)
-        with open(rootfs_hostlog, 'w') as outfile:
-            json.dump(hostlog[len(hostlog)-1-self._ROOTFS_HOSTLOG_EVENTS:-1],
-                      outfile)
-
-        return rootfs_hostlog, reboot_hostlog
-
-
-    def _get_update_percentage(self):
-        """Returns the current payload downloaded percentage."""
-        while True:
-            status = self._host.run('update_engine_client --status',
-                                    ignore_timeout=True,
-                                    timeout=10)
-            if not status:
-                continue
-            status = status.stdout.splitlines()
-            logging.debug(status)
-            if 'UPDATE_STATUS_IDLE' in status[2]:
-                raise error.TestFail('Update status was idle while trying to '
-                                     'get download status.')
-            # If we call this right after reboot it may not be downloading yet.
-            if 'UPDATE_STATUS_DOWNLOADING' not in status[2]:
-                time.sleep(1)
-                continue
-            return float(status[1].partition('=')[2])
-
-
-    def _update_continued_where_it_left_off(self, percentage):
-        """
-        Checks that the update did not restart after an interruption.
-
-        @param percentage: The percentage the last time we checked.
-
-        @returns True if update continued. False if update restarted.
-
-        """
-        completed = self._get_update_percentage()
-        logging.info('New value: %f, old value: %f', completed, percentage)
-        return completed >= percentage
-
-
-    def _wait_for_update_to_complete(self):
+    def _wait_for_oobe_update_to_complete(self):
         """Wait for the update that started to complete.
 
         Repeated check status of update. It should move from DOWNLOADING to
-        FINALIZING to COMPLETE to IDLE.
+        FINALIZING to COMPLETE (then reboot) to IDLE.
         """
         while True:
-            status = self._host.run('update_engine_client --status',
-                                    ignore_timeout=True,
-                                    timeout=10)
+            status = self._get_update_engine_status()
 
             # During reboot, status will be None
             if status is not None:
-                status = status.stdout.splitlines()
-                logging.debug(status)
-                if 'UPDATE_STATUS_IDLE' in status[2]:
+                if self._UPDATE_STATUS_IDLE == status[self._CURRENT_OP]:
                     break
             time.sleep(1)
 
 
-    def _wait_for_percentage(self, percent):
-        """
-        Waits until we reach the percentage passed as the input.
-
-        @param percent: The percentage we want to wait for.
-        """
-        while True:
-            completed = self._get_update_percentage()
-            logging.debug('Checking if %s is greater than %s', completed,
-                          percent)
-            if completed > percent:
-                break
-            time.sleep(1)
-
-
     def run_once(self, host, full_payload=True, cellular=False,
                  interrupt=False, max_updates=1, job_repo_url=None):
         """
@@ -173,7 +76,7 @@
         update_url = self.get_update_url_for_test(job_repo_url,
                                                   full_payload=full_payload,
                                                   critical_update=True,
-                                                  cellular=cellular,
+                                                  public=cellular,
                                                   max_updates=max_updates)
         logging.info('Update url: %s', update_url)
         before = self._get_chromeos_version()
@@ -190,49 +93,41 @@
             payload_info = self._get_staged_file_info(staged_url)
 
         # Call client test to start the forced OOBE update.
-        client_at = autotest.Autotest(self._host)
-        client_at.run_test('autoupdate_StartOOBEUpdate', image_url=update_url,
-                           cellular=cellular, payload_info=payload_info,
-                           full_payload=full_payload)
+        self._run_client_test_and_check_result('autoupdate_StartOOBEUpdate',
+                                               image_url=update_url,
+                                               public=cellular,
+                                               payload_info=payload_info,
+                                               full_payload=full_payload)
 
-        # Don't continue the test if the client failed for any reason.
-        client_at._check_client_test_result(self._host,
-                                            'autoupdate_StartOOBEUpdate')
 
         if interrupt:
-            # Choose a random downloaded percentage to interrupt the update.
-            percent = random.uniform(0.1, 0.7)
-            logging.debug('Percent when we will interrupt: %f', percent)
-            self._wait_for_percentage(percent)
+            # Choose a random downloaded progress to interrupt the update.
+            progress = random.uniform(0.1, 0.8)
+            logging.debug('Progress when we will interrupt: %f', progress)
+            self._wait_for_progress(progress)
             logging.info('We will start interrupting the update.')
-            completed = self._get_update_percentage()
+            completed = self._get_update_progress()
 
             # Reboot the DUT during the update.
             self._host.reboot()
             if not self._update_continued_where_it_left_off(completed):
                 raise error.TestFail('The update did not continue where it '
                                      'left off before rebooting.')
-            completed = self._get_update_percentage()
+            completed = self._get_update_progress()
 
-            # Disconnect and reconnect network.
-            reconnect_test_name = 'autoupdate_DisconnectReconnectNetwork'
-            client_at.run_test(reconnect_test_name, update_url=update_url)
-            client_at._check_client_test_result(self._host, reconnect_test_name)
+            self._disconnect_then_reconnect_network(update_url)
             if not self._update_continued_where_it_left_off(completed):
                 raise error.TestFail('The update did not continue where it '
                                      'left off before disconnecting network.')
-            completed = self._get_update_percentage()
+            completed = self._get_update_progress()
 
             # Suspend / Resume
-            try:
-                self._host.suspend(suspend_time=30)
-            except error.AutoservSuspendError:
-                logging.exception('Suspend did not last the entire time.')
+            self._suspend_then_resume()
             if not self._update_continued_where_it_left_off(completed):
                 raise error.TestFail('The update did not continue where it '
                                      'left off after suspend/resume.')
 
-        self._wait_for_update_to_complete()
+        self._wait_for_oobe_update_to_complete()
 
         if cellular:
             # We didn't have a devserver so we cannot check the hostlog to
@@ -240,15 +135,17 @@
             # that the second-to-last update engine log has the successful
             # update message. Second to last because its the one before OOBE
             # rebooted.
-            update_engine_files_cmd = 'ls -t -1 /var/log/update_engine/'
+            update_engine_files_cmd = 'ls -t -1 %s' % \
+                                      self._UPDATE_ENGINE_LOG_DIR
             files = self._host.run(update_engine_files_cmd).stdout.splitlines()
-            before_reboot_file = self._host.run('cat /var/log/update_engine/%s'
-                                                % files[1]).stdout
+            before_reboot_file = self._host.run('cat %s%s' % (
+                self._UPDATE_ENGINE_LOG_DIR, files[1])).stdout
             self._check_for_cellular_entries_in_update_log(before_reboot_file)
 
             success = 'Update successfully applied, waiting to reboot.'
-            update_ec = self._host.run('cat /var/log/update_engine/%s | grep '
-                                       '"%s"' % (files[1], success)).exit_status
+            update_ec = self._host.run('cat %s%s | grep '
+                                       '"%s"' % (self._UPDATE_ENGINE_LOG_DIR,
+                                                 files[1], success)).exit_status
             if update_ec != 0:
                 raise error.TestFail('We could not verify that the update '
                                      'completed successfully. Check the logs.')