cros_update: Migrate to chromite

This is mostly uses the cros_update files in the chromite.

BUG=chromium:1003986
TEST=./devserver_integration_test.py

Cq-Depend: chromium:1866027
Change-Id: Id9c3f6e4c6b8e08889ec96942f37f3e084380e9a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/1894676
Tested-by: Amin Hassani <ahassani@chromium.org>
Tested-by: Achuith Bhandarkar <achuith@chromium.org>
Commit-Queue: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/Makefile b/Makefile
index b8100a5..99c3309 100644
--- a/Makefile
+++ b/Makefile
@@ -17,9 +17,6 @@
 		autoupdate.py \
 		builder.py \
 		cherrypy_ext.py \
-		cros_update.py \
-		cros_update_logging.py \
-		cros_update_progress.py \
 		health_checker.py \
 		nebraska/nebraska.py \
 		setup_chromite.py \
diff --git a/cros_update.py b/cros_update.py
deleted file mode 100644
index 10cd6fd..0000000
--- a/cros_update.py
+++ /dev/null
@@ -1,392 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2016 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.
-
-"""An executable function cros-update for auto-update of a CrOS host.
-
-The reason to create this file is to let devserver to trigger a background
-process for CrOS auto-update. Therefore, when devserver service is restarted
-sometimes, the CrOS auto-update process is still running and the corresponding
-provision task won't claim failure.
-
-It includes two classes:
-  a. CrOSUpdateTrigger:
-    1. Includes all logics which identify which types of update need to be
-       performed in the current DUT.
-    2. Responsible for write current status of CrOS auto-update process into
-       progress_tracker.
-
-  b. CrOSAUParser:
-    1. Pre-setup the required args for CrOS auto-update.
-    2. Parse the input parameters for cmd that runs 'cros_update.py'.
-"""
-
-from __future__ import print_function
-
-import os
-import re
-import sys
-import time
-import traceback
-import logging  # pylint: disable=cros-logging-import
-
-import cros_update_logging
-import cros_update_progress
-
-import setup_chromite  # pylint: disable=unused-import
-from chromite.lib import auto_updater
-from chromite.lib import commandline
-from chromite.lib import cros_build_lib
-from chromite.lib import remote_access
-from chromite.lib import timeout_util
-
-
-# The build channel for recovering host's stateful partition
-STABLE_BUILD_CHANNEL = 'stable-channel'
-
-# Timeout for CrOS auto-update process.
-CROS_UPDATE_TIMEOUT_MIN = 30
-
-# The preserved path in remote device, won't be deleted after rebooting.
-CROS_PRESERVED_PATH = ('/mnt/stateful_partition/unencrypted/'
-                       'preserve/cros-update')
-
-# Standard error tmeplate to be written into status tracking log.
-CROS_ERROR_TEMPLATE = cros_update_progress.ERROR_TAG + ' %s'
-
-# How long after a quick provision fails to wait before falling back to the
-# standard provisioning flow.
-QUICK_PROVISION_FAILURE_DELAY_SEC = 45
-
-# Setting logging level
-logConfig = cros_update_logging.loggingConfig()
-logConfig.ConfigureLogging()
-
-
-class CrOSUpdateTrigger(object):
-  """The class for CrOS auto-updater trigger.
-
-  This class is used for running all CrOS auto-update trigger logic.
-  """
-  def __init__(self, host_name, build_name, static_dir, progress_tracker=None,
-               log_file=None, au_tempdir=None, force_update=False,
-               full_update=False, original_build=None, payload_filename=None,
-               clobber_stateful=True, quick_provision=False,
-               devserver_url=None, static_url=None):
-    self.host_name = host_name
-    self.build_name = build_name
-    self.static_dir = static_dir
-    self.progress_tracker = progress_tracker
-    self.log_file = log_file
-    self.au_tempdir = au_tempdir
-    self.force_update = force_update
-    self.full_update = full_update
-    self.original_build = original_build
-    self.payload_filename = payload_filename
-    self.clobber_stateful = clobber_stateful
-    self.quick_provision = quick_provision
-    self.devserver_url = devserver_url
-    self.static_url = static_url
-
-  def _WriteAUStatus(self, content):
-    if self.progress_tracker:
-      self.progress_tracker.WriteStatus(content)
-
-  def _StatefulUpdate(self, cros_updater):
-    """The detailed process in stateful update.
-
-    Args:
-      cros_updater: The CrOS auto updater for auto-update.
-    """
-    self._WriteAUStatus('pre-setup stateful update')
-    cros_updater.PreSetupStatefulUpdate()
-    self._WriteAUStatus('perform stateful update')
-    cros_updater.UpdateStateful()
-    self._WriteAUStatus('post-check stateful update')
-    cros_updater.PostCheckStatefulUpdate()
-
-  def _RootfsUpdate(self, cros_updater):
-    """The detailed process in rootfs update.
-
-    Args:
-      cros_updater: The CrOS auto updater for auto-update.
-    """
-    self._WriteAUStatus('Check whether devserver can run before rootfs update')
-    cros_updater.CheckDevserverRun()
-    self._WriteAUStatus('transfer rootfs update package')
-    cros_updater.TransferRootfsUpdate()
-    self._WriteAUStatus('pre-setup rootfs update')
-    cros_updater.PreSetupRootfsUpdate()
-    self._WriteAUStatus('rootfs update')
-    cros_updater.UpdateRootfs()
-    self._WriteAUStatus('post-check rootfs update')
-    cros_updater.PostCheckRootfsUpdate()
-
-  def _GetOriginalPayloadDir(self):
-    """Get the directory of original payload.
-
-    Returns:
-      The directory of original payload, whose format is like:
-          'static/stable-channel/link/3428.210.0'
-    """
-    if self.original_build:
-      return os.path.join(self.static_dir, '%s/%s' % (STABLE_BUILD_CHANNEL,
-                                                      self.original_build))
-    else:
-      return None
-
-  def _MakeStatusUrl(self, devserver_url, host_name, pid):
-    """Generates a URL to post auto update status to.
-
-    Args:
-      devserver_url: URL base for devserver RPCs.
-      host_name: Host to post status for.
-      pid: pid of the update process.
-
-    Returns:
-      An unescaped URL.
-    """
-    return '%s/post_au_status?host_name=%s&pid=%d' % (devserver_url, host_name,
-                                                      pid)
-
-  def _QuickProvision(self, device):
-    """Performs a quick provision of device.
-
-    Returns:
-      A dictionary of extracted key-value pairs returned from the script
-      execution.
-
-    Raises:
-      cros_build_lib.RunCommandError: error executing command or script
-      remote_access.SSHConnectionError: SSH connection error
-    """
-    pid = os.getpid()
-    pgid = os.getpgid(pid)
-    if self.progress_tracker is None:
-      self.progress_tracker = cros_update_progress.AUProgress(self.host_name,
-                                                              pgid)
-
-    dut_script = '/tmp/quick-provision'
-    status_url = self._MakeStatusUrl(self.devserver_url, self.host_name, pgid)
-    cmd = ('curl -o %s %s && bash '
-           '%s --status_url %s %s %s') % (
-               dut_script, os.path.join(self.static_url, 'quick-provision'),
-               dut_script, cros_build_lib.ShellQuote(status_url),
-               self.build_name, self.static_url
-           )
-    # Quick provision script issues a reboot and might result in the SSH
-    # connection being terminated so set ssh_error_ok so that output can
-    # still be captured.
-    results = device.RunCommand(cmd, log_output=True, capture_output=True,
-                                ssh_error_ok=True)
-    key_re = re.compile(r'^KEYVAL: ([^\d\W]\w*)=(.*)$')
-    matches = [key_re.match(l) for l in results.output.splitlines()]
-    keyvals = {m.group(1): m.group(2) for m in matches if m}
-    logging.info('DUT returned keyvals: %s', keyvals)
-
-    # If there was an SSH error, check the keyvals to see if it actually
-    # completed and suppress the error if so.
-    if results.returncode == remote_access.SSH_ERROR_CODE:
-      if 'COMPLETED' in keyvals:
-        logging.warning('Quick provision completed with ssh error, ignoring...')
-      else:
-        logging.error('Incomplete quick provision failed with ssh error')
-        raise remote_access.SSHConnectionError(results.error)
-
-    return keyvals
-
-  def TriggerAU(self):
-    """Execute auto update for cros_host.
-
-    The auto update includes 4 steps:
-    1. if devserver cannot run, restore the stateful partition.
-    2. if possible, do stateful update first, but never raise errors, except
-       for timeout_util.TimeoutError caused by system.signal.
-    3. If required or stateful_update fails, first do rootfs update, then do
-       stateful_update.
-    4. Post-check for the whole update.
-    """
-    try:
-      with remote_access.ChromiumOSDeviceHandler(
-          self.host_name, port=None,
-          base_dir=CROS_PRESERVED_PATH,
-          ping=False) as device:
-
-        logging.debug('Remote device %s is connected', self.host_name)
-        payload_dir = os.path.join(self.static_dir, self.build_name)
-        original_payload_dir = self._GetOriginalPayloadDir()
-
-        chromeos_AU = auto_updater.ChromiumOSUpdater(
-            device, self.build_name, payload_dir,
-            dev_dir=os.path.abspath(os.path.dirname(__file__)),
-            tempdir=self.au_tempdir,
-            log_file=self.log_file,
-            original_payload_dir=original_payload_dir,
-            yes=True,
-            payload_filename=self.payload_filename,
-            clobber_stateful=self.clobber_stateful)
-
-        # Allow fall back if the quick provision does not succeed.
-        invoke_autoupdate = True
-
-        if (self.quick_provision and self.clobber_stateful and
-            not self.full_update):
-          try:
-            logging.debug('Start CrOS quick provision process...')
-            self._WriteAUStatus('Start Quick Provision')
-            keyvals = self._QuickProvision(device)
-            logging.debug('Start CrOS check process...')
-            self._WriteAUStatus('Finish Quick Provision, reboot')
-            chromeos_AU.AwaitReboot(keyvals.get('BOOT_ID'))
-            self._WriteAUStatus('Finish Quick Provision, post-check')
-            chromeos_AU.PostCheckCrOSUpdate()
-            self._WriteAUStatus(cros_update_progress.FINISHED)
-            invoke_autoupdate = False
-          except (cros_build_lib.RunCommandError,
-                  remote_access.SSHConnectionError,
-                  auto_updater.RebootVerificationError) as e:
-            logging.warning(
-                'Error during quick provision, falling back to legacy: %s: %s',
-                type(e).__name__, e)
-            time.sleep(QUICK_PROVISION_FAILURE_DELAY_SEC)
-
-        if invoke_autoupdate:
-          chromeos_AU.CheckPayloads()
-
-          version_match = chromeos_AU.PreSetupCrOSUpdate()
-          self._WriteAUStatus('Transfer Devserver/Stateful Update Package')
-          chromeos_AU.TransferDevServerPackage()
-          chromeos_AU.TransferStatefulUpdate()
-
-          restore_stateful = chromeos_AU.CheckRestoreStateful()
-          do_stateful_update = (not self.full_update) and (
-              version_match and self.force_update)
-          stateful_update_complete = False
-          logging.debug('Start CrOS update process...')
-          try:
-            if restore_stateful:
-              self._WriteAUStatus('Restore Stateful Partition')
-              chromeos_AU.RestoreStateful()
-              stateful_update_complete = True
-            else:
-              # Whether to execute stateful update depends on:
-              # a. full_update=False: No full reimage is required.
-              # b. The update version is matched to the current version, And
-              #    force_update=True: Update is forced even if the version
-              #    installed is the same.
-              if do_stateful_update:
-                self._StatefulUpdate(chromeos_AU)
-                stateful_update_complete = True
-
-          except timeout_util.TimeoutError:
-            raise
-          except Exception as e:
-            logging.debug('Error happens in stateful update: %r', e)
-
-          # Whether to execute rootfs update depends on:
-          # a. stateful update is not completed, or completed by
-          #    update action 'restore_stateful'.
-          # b. force_update=True: Update is forced no matter what the current
-          #    version is. Or, the update version is not matched to the current
-          #    version.
-          require_rootfs_update = self.force_update or (
-              not chromeos_AU.CheckVersion())
-          if (not (do_stateful_update and stateful_update_complete)
-              and require_rootfs_update):
-            self._RootfsUpdate(chromeos_AU)
-            self._StatefulUpdate(chromeos_AU)
-
-          self._WriteAUStatus('post-check for CrOS auto-update')
-          chromeos_AU.PostCheckCrOSUpdate()
-          self._WriteAUStatus(cros_update_progress.FINISHED)
-
-        logging.debug('Provision successfully completed (%s)',
-                      'legacy' if invoke_autoupdate else 'quick provision')
-    except Exception as e:
-      logging.debug('Error happens in CrOS auto-update: %r', e)
-      self._WriteAUStatus(CROS_ERROR_TEMPLATE % str(traceback.format_exc()))
-      raise
-
-
-def ParseArguments(argv):
-  """Returns a namespace for the CLI arguments."""
-  parser = commandline.ArgumentParser(description=__doc__)
-  parser.add_argument('-d', action='store', type=str, dest='host_name',
-                      help='host_name of a DUT')
-  parser.add_argument('-b', action='store', type=str, dest='build_name',
-                      help='build name to be auto-updated')
-  parser.add_argument('--static_dir', action='store', type='path',
-                      help='static directory of the devserver')
-  parser.add_argument('--force_update', action='store_true', default=False,
-                      help=('force an update even if the version installed is '
-                            'the same'))
-  parser.add_argument('--full_update', action='store_true', default=False,
-                      help='force a rootfs update, skip stateful update')
-  parser.add_argument('--original_build', action='store', type=str, default='',
-                      help=('force stateful update with the same version of '
-                            'previous rootfs partition'))
-  parser.add_argument('--payload_filename', action='store', type=str,
-                      default=None, help='A custom payload filename')
-  parser.add_argument('--clobber_stateful', action='store_true', default=False,
-                      help='Whether to clobber stateful')
-  parser.add_argument('--quick_provision', action='store_true', default=False,
-                      help='Whether to attempt quick provisioning path')
-  parser.add_argument('--devserver_url', action='store', type=str, default=None,
-                      help='Devserver URL base for RPCs')
-  parser.add_argument('--static_url', action='store', type=str, default=None,
-                      help='Devserver URL base for static files')
-
-  opts = parser.parse_args(argv)
-  opts.Freeze()
-
-  return opts
-
-
-def main(argv):
-  options = ParseArguments(argv)
-
-  # Use process group id as the unique id in track and log files, since
-  # os.setsid is executed before the current process is run.
-  pid = os.getpid()
-  pgid = os.getpgid(pid)
-
-  # Setting log files for CrOS auto-update process.
-  # Log file:  file to record every details of CrOS auto-update process.
-  log_file = cros_update_progress.GetExecuteLogFile(options.host_name, pgid)
-  logging.info('Writing executing logs into file: %s', log_file)
-  logConfig.SetFileHandler(log_file)
-
-  # Create a progress_tracker for tracking CrOS auto-update progress.
-  progress_tracker = cros_update_progress.AUProgress(options.host_name, pgid)
-
-  # Create a dir for temporarily storing devserver codes and logs.
-  au_tempdir = cros_update_progress.GetAUTempDirectory(options.host_name, pgid)
-
-  # Create cros_update instance to run CrOS auto-update.
-  cros_updater_trigger = CrOSUpdateTrigger(
-      options.host_name, options.build_name, options.static_dir,
-      progress_tracker=progress_tracker,
-      log_file=log_file,
-      au_tempdir=au_tempdir,
-      force_update=options.force_update,
-      full_update=options.full_update,
-      original_build=options.original_build,
-      payload_filename=options.payload_filename,
-      clobber_stateful=options.clobber_stateful,
-      quick_provision=options.quick_provision,
-      devserver_url=options.devserver_url,
-      static_url=options.static_url)
-
-  # Set timeout the cros-update process.
-  try:
-    with timeout_util.Timeout(CROS_UPDATE_TIMEOUT_MIN*60):
-      cros_updater_trigger.TriggerAU()
-  except timeout_util.TimeoutError as e:
-    error_msg = ('%s. The CrOS auto-update process is timed out, thus will be '
-                 'terminated' % str(e))
-    progress_tracker.WriteStatus(CROS_ERROR_TEMPLATE % error_msg)
-
-
-if __name__ == '__main__':
-  main(sys.argv[1:])
diff --git a/cros_update_logging.py b/cros_update_logging.py
deleted file mode 100644
index 9cc6dd8..0000000
--- a/cros_update_logging.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2016 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.
-
-"""A logging strategy for cros-update.
-
-1. Logging format is set as the same as autoserv.
-2. Globally, set log level of output as 'DEBUG'.
-3. For control output, set LEVEL as 'INFO', to avoid unnecessary logs in
-   cherrypy logs.
-4. Add file handler to record all logs above level 'DEBUG' into file.
-"""
-
-from __future__ import print_function
-
-import logging  # pylint: disable=cros-logging-import
-import sys
-
-
-class loggingConfig(object):
-  """Configuration for auto-update logging."""
-
-  LOGGING_FORMAT = ('%(asctime)s.%(msecs)03d %(levelname)-5.5s|%(module)18.18s:'
-                    '%(lineno)4.4d| %(message)s')
-
-  def __init__(self):
-    self.logger = logging.getLogger()
-    self.GLOBAL_LEVEL = logging.DEBUG
-    self.CONSOLE_LEVEL = logging.INFO
-    self.FILE_LEVEL = logging.DEBUG
-    self.ENABLE_CONSOLE_LOGGING = False
-
-  def SetControlHandler(self, stream):
-    """Set console handler for logging.
-
-    Args:
-      stream: The input stream, could be stdout/stderr.
-    """
-    handler = logging.StreamHandler(stream)
-    handler.setLevel(self.CONSOLE_LEVEL)
-    file_formatter = logging.Formatter(fmt=self.LOGGING_FORMAT,
-                                       datefmt='%Y/%m/%d %H:%M:%S')
-    handler.setFormatter(file_formatter)
-    self.logger.addHandler(handler)
-    return handler
-
-
-  def SetFileHandler(self, file_name):
-    """Set file handler for logging.
-
-    Args:
-      file_name: The file to save logs into.
-    """
-    handler = logging.FileHandler(file_name)
-    handler.setLevel(self.FILE_LEVEL)
-    # file format is set as same as concole format
-    file_formatter = logging.Formatter(fmt=self.LOGGING_FORMAT,
-                                       datefmt='%Y/%m/%d %H:%M:%S')
-    handler.setFormatter(file_formatter)
-    self.logger.addHandler(handler)
-
-
-  def ConfigureLogging(self):
-    self.logger.setLevel(self.GLOBAL_LEVEL)
-    if self.ENABLE_CONSOLE_LOGGING:
-      self.SetControlHandler(sys.stdout)
diff --git a/cros_update_progress.py b/cros_update_progress.py
deleted file mode 100644
index 9a288c2..0000000
--- a/cros_update_progress.py
+++ /dev/null
@@ -1,248 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2016 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.
-
-"""A progress class for tracking CrOS auto-update process.
-
-This class is mainly designed for:
-  1. Set the pattern for generating the filenames of
-     track_status_file/execute_log_file.
-     track_status_file: Used for record the current step of CrOS auto-update
-                        process. Only has one line.
-     execute_log_file: Used for record the whole logging info of the CrOS
-                       auto-update process, including any debug information.
-  2. Write current auto-update process into the track_status_file.
-  3. Read current auto-update process from the track_status_file.
-
-This file also offers external functions that are related to add/check/delete
-the progress of the CrOS auto-update process.
-"""
-
-from __future__ import print_function
-
-import datetime
-import glob
-import logging  # pylint: disable=cros-logging-import
-import os
-import re
-
-import setup_chromite  # pylint: disable=unused-import
-from chromite.lib import osutils
-from chromite.lib.xbuddy import cherrypy_log_util
-
-
-# Module-local log function.
-def _Log(message, *args):
-  return cherrypy_log_util.LogWithTag('CROS_UPDATE_PROGRESS', message, *args)
-
-# Path for status tracking log.
-_TRACK_LOG_FILE_PATH = '/tmp/auto-update/tracking_log/%s_%s.log'
-
-# Pattern for status tracking log filename.
-_TRACK_LOG_FILE_NAME_PATTERN = r'([^_]+)_([^_]+).log'
-
-# The gap hour used in checking AU processes' count.
-AU_PROCESS_HOUR_GAP = 3
-
-# Path for executing log.
-_EXECUTE_LOG_FILE_PATH = '/tmp/auto-update/executing_log/%s_%s.log'
-
-# Path and files for temporarily saving devserver codes, devserver and
-# update engine log.
-_CROS_UPDATE_TEMP_PATH = '/tmp/cros-update_%s_%s'
-
-_CROS_HOSTLOG_PATTERN = 'devserver_hostlog*'
-
-# The string for update process finished
-FINISHED = 'Completed'
-ERROR_TAG = 'Error'
-
-
-def ReadOneLine(filename):
-  """Read one line from file.
-
-  Args:
-    filename: The file to be read.
-  """
-  return open(filename, 'r').readline().rstrip('\n')
-
-
-def IsProcessAlive(pid):
-  """Detect whether a process is alive or not.
-
-  Args:
-    pid: The process id.
-  """
-  path = '/proc/%s/stat' % pid
-  try:
-    stat = ReadOneLine(path)
-  except IOError:
-    if not os.path.exists(path):
-      return False
-
-    raise
-
-  return stat.split()[2] != 'Z'
-
-
-def GetExecuteLogFile(host_name, pid):
-  """Return the whole path of execute log file."""
-  if not os.path.exists(os.path.dirname(_EXECUTE_LOG_FILE_PATH)):
-    osutils.SafeMakedirs(os.path.dirname(_EXECUTE_LOG_FILE_PATH))
-
-  return _EXECUTE_LOG_FILE_PATH % (host_name, pid)
-
-
-def GetTrackStatusFile(host_name, pid):
-  """Return the whole path of track status file."""
-  if not os.path.exists(os.path.dirname(_TRACK_LOG_FILE_PATH)):
-    osutils.SafeMakedirs(os.path.dirname(_TRACK_LOG_FILE_PATH))
-
-  return _TRACK_LOG_FILE_PATH % (host_name, pid)
-
-
-def GetAllTrackStatusFileByTime():
-  """Return all track status files existing in TRACK_LOG_FILE_PATH.
-
-  Returns:
-    A track status file list ordered by created time reversely.
-  """
-  return sorted(glob.glob(_TRACK_LOG_FILE_PATH % ('*', '*')),
-                key=os.path.getctime, reverse=True)
-
-
-def ParsePidFromTrackLogFileName(track_log_filename):
-  """Parse pid from a given track log file's name.
-
-  The track log file's name for auto-update is fixed:
-      hostname_pid.log
-
-  This func is used to parse pid from a given track log file.
-
-  Args:
-    track_log_filename: the filename of the track log to be parsed.
-
-  Returns:
-    the parsed pid (int).
-  """
-  match = re.match(_TRACK_LOG_FILE_NAME_PATTERN, track_log_filename)
-  try:
-    return int(match.groups()[1])
-  except (AttributeError, IndexError, ValueError) as e:
-    _Log('Cannot parse pid from track log file %s: %s', track_log_filename, e)
-    return None
-
-
-def GetAllTrackStatusFileByHostName(host_name):
-  """Return a list of existing track status files generated for a host."""
-  return glob.glob(_TRACK_LOG_FILE_PATH % (host_name, '*'))
-
-
-def GetAllRunningAUProcess():
-  """Get all the ongoing AU processes' pids from tracking logs.
-
-  This func only checks the tracking logs generated in latest several hours,
-  which is for avoiding the case that 'there's a running process whose id is
-  as the same as a previous AU process'.
-
-  Returns:
-    A list of background AU processes' pids.
-  """
-  pids = []
-  now = datetime.datetime.now()
-  track_log_list = GetAllTrackStatusFileByTime()
-  # Only check log file created in 3 hours.
-  for track_log in track_log_list:
-    try:
-      created_time = datetime.datetime.fromtimestamp(
-          os.path.getctime(track_log))
-      if now - created_time >= datetime.timedelta(hours=AU_PROCESS_HOUR_GAP):
-        break
-
-      pid = ParsePidFromTrackLogFileName(os.path.basename(track_log))
-      if pid and IsProcessAlive(pid):
-        pids.append(pid)
-    except (ValueError, os.error) as e:
-      _Log('Error happened in getting pid from %s: %s', track_log, e)
-
-  return pids
-
-
-def GetAUTempDirectory(host_name, pid):
-  """Return the temp dir for storing codes and logs during auto-update."""
-  au_tempdir = _CROS_UPDATE_TEMP_PATH % (host_name, pid)
-  if not os.path.exists(au_tempdir):
-    osutils.SafeMakedirs(au_tempdir)
-
-  return au_tempdir
-
-
-def ReadExecuteLogFile(host_name, pid):
-  """Return the content of execute log file."""
-  return osutils.ReadFile(GetExecuteLogFile(host_name, pid))
-
-
-def ReadAUHostLogFiles(host_name, pid):
-  """Returns a dictionary containing the devserver host log files."""
-  au_dir = GetAUTempDirectory(host_name, pid)
-  hostlog_filenames = glob.glob(os.path.join(au_dir, _CROS_HOSTLOG_PATTERN))
-  hostlog_files = {}
-  for f in hostlog_filenames:
-    hostlog_files[os.path.basename(f)] = osutils.ReadFile(f)
-  return hostlog_files
-
-
-def DelTrackStatusFile(host_name, pid):
-  """Delete the track status log."""
-  osutils.SafeUnlink(GetTrackStatusFile(host_name, pid))
-
-
-def DelExecuteLogFile(host_name, pid):
-  """Delete the track status log."""
-  osutils.SafeUnlink(GetExecuteLogFile(host_name, pid))
-
-
-def DelAUTempDirectory(host_name, pid):
-  """Delete the directory including auto-update-related logs."""
-  osutils.RmDir(GetAUTempDirectory(host_name, pid))
-
-
-class AUProgress(object):
-  """Used for tracking the CrOS auto-update progress."""
-
-  def __init__(self, host_name, pid):
-    """Initialize a CrOS update progress instance.
-
-    Args:
-      host_name: The name of host, should be in the file_name of the status
-        tracking file of auto-update process.
-      pid: The process id, should be in the file_name too.
-    """
-    self.host_name = host_name
-    self.pid = pid
-
-  @property
-  def track_status_file(self):
-    """The track status file to record the CrOS auto-update progress."""
-    return GetTrackStatusFile(self.host_name, self.pid)
-
-  def WriteStatus(self, content):
-    """Write auto-update progress into status tracking file.
-
-    Args:
-      content: The content to be recorded.
-    """
-    if not self.track_status_file:
-      return
-
-    try:
-      with open(self.track_status_file, 'w') as out_log:
-        out_log.write(content)
-    except Exception as e:
-      logging.error('Cannot write au status: %r', e)
-
-  def ReadStatus(self):
-    """Read auto-update progress from status tracking file."""
-    with open(self.track_status_file, 'r') as out_log:
-      return out_log.read().rstrip('\n')
diff --git a/devserver.py b/devserver.py
index 3b89260..8478a44 100755
--- a/devserver.py
+++ b/devserver.py
@@ -49,14 +49,13 @@
 
 import autoupdate
 import cherrypy_ext
-import cros_update
-import cros_update_progress
 import health_checker
 
 # This must happen before any local modules get a chance to import
 # anything from chromite.  Otherwise, really bad things will happen, and
 # you will _not_ understand why.
 import setup_chromite  # pylint: disable=unused-import
+from chromite.lib import cros_update_progress
 from chromite.lib.xbuddy import android_build
 from chromite.lib.xbuddy import artifact_info
 from chromite.lib.xbuddy import build_artifact
@@ -65,7 +64,7 @@
 from chromite.lib.xbuddy import devserver_constants
 from chromite.lib.xbuddy import downloader
 from chromite.lib.xbuddy import xbuddy
-
+from chromite.scripts import cros_update
 
 # Module-local log function.
 def _Log(message, *args):
@@ -779,10 +778,8 @@
 
     if is_async:
       # Command of running auto-update.
-      path = os.path.dirname(os.path.abspath(__file__))
-      execute_file = os.path.join(path, 'cros_update.py')
-      cmd = ['/usr/bin/python', '-u', execute_file, '-d', host_name,
-             '-b', build_name, '--static_dir', updater.static_dir]
+      cmd = ['cros_update', '--hostname', host_name, '-b', build_name,
+             '--static_dir', updater.static_dir]
 
       # The original_build's format is like: link/3428.210.0
       # The corresponding release_archive_url's format is like:
diff --git a/devserver_integration_test.py b/devserver_integration_test.py
index 502da78..c1cca8c 100755
--- a/devserver_integration_test.py
+++ b/devserver_integration_test.py
@@ -33,10 +33,9 @@
 
 import psutil  # pylint: disable=import-error
 
-import cros_update_progress
-
 import setup_chromite  # pylint: disable=unused-import
 from chromite.lib import cros_logging as logging
+from chromite.lib import cros_update_progress
 from chromite.lib.xbuddy import devserver_constants
 
 
diff --git a/health_checker.py b/health_checker.py
index d978fdb..5d9ce20 100644
--- a/health_checker.py
+++ b/health_checker.py
@@ -15,26 +15,12 @@
 import time
 
 import cherrypy  # pylint: disable=import-error
-
-import cros_update_progress
+import psutil  # pylint: disable=import-error
 
 import setup_chromite  # pylint: disable=unused-import
+from chromite.lib import cros_update_progress
 from chromite.lib.xbuddy import cherrypy_log_util
 
-try:
-  import psutil
-except ImportError:
-  # Ignore psutil import failure. This is for backwards compatibility, so
-  # "cros flash" can still update duts with build without psutil installed.
-  # The reason is that, during cros flash, local devserver code is copied over
-  # to DUT, and devserver will be running inside DUT to stage the build.
-  psutil = None
-except OSError:
-  # Ignore error like following. psutil may not work properly in builder. Ignore
-  # the error as load information of devserver is not used in builder.
-  # OSError: [Errno 2] No such file or directory: '/dev/pts/0'
-  psutil = None
-
 
 def _Log(message, *args):
   """Module-local log function."""