Revert "Refactor the way we track the devserver in vm tests and kill it harder."
Looks like not all builders have psutil
This reverts commit 1e565adc53903af7f39bc992de4aa8d4a3b50b0e
Change-Id: I391fe85ba6080010d412a05098d5af3929ec09cb
Reviewed-on: https://gerrit.chromium.org/gerrit/66913
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: Chris Sosa <sosa@chromium.org>
diff --git a/au_test_harness/cros_au_test_harness.py b/au_test_harness/cros_au_test_harness.py
index 363737c..fc6a2f8 100755
--- a/au_test_harness/cros_au_test_harness.py
+++ b/au_test_harness/cros_au_test_harness.py
@@ -205,14 +205,10 @@
with sudo.SudoKeepAlive():
au_worker.AUWorker.SetUpdateCache(update_cache)
- my_server = None
+ my_server = dev_server_wrapper.DevServerWrapper(options.test_results_root)
+ my_server.start()
try:
- # Only start a devserver if we'll need it.
- if update_cache:
- my_server = dev_server_wrapper.DevServerWrapper(
- options.test_results_root)
- my_server.Start()
-
+ my_server.WaitUntilStarted()
if options.type == 'vm':
_RunTestsInParallel(options)
else:
@@ -224,8 +220,7 @@
cros_build_lib.Die('Test harness failed.')
finally:
- if my_server:
- my_server.Stop()
+ my_server.Stop()
if __name__ == '__main__':
diff --git a/devmode-test/devinstall_test.py b/devmode-test/devinstall_test.py
index 82d32f8..c9a36c8 100755
--- a/devmode-test/devinstall_test.py
+++ b/devmode-test/devinstall_test.py
@@ -175,8 +175,9 @@
if not self.binhost:
logging.info('Starting the devserver.')
- self.devserver = dev_server_wrapper.DevServerWrapper()
- self.devserver.Start()
+ self.devserver = dev_server_wrapper.DevServerWrapper(self.tmpdir)
+ self.devserver.start()
+ self.devserver.WaitUntilStarted()
self.binhost = dev_server_wrapper.DevServerWrapper.GetDevServerURL(
sub_dir='static/pkgroot/%s/packages' % self.board)
diff --git a/lib/constants.py b/lib/constants.py
index f684452..be4bf21 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -8,8 +8,6 @@
CROS_PLATFORM_ROOT = os.path.join(os.path.dirname(_TEST_LIB_PATH), '..', '..')
-DEFAULT_CHROOT_DIR = 'chroot'
-
SOURCE_ROOT = os.path.realpath(os.path.join(
os.path.dirname(_TEST_LIB_PATH), '..', '..', '..', '..'))
diff --git a/lib/dev_server_wrapper.py b/lib/dev_server_wrapper.py
index 8505475..8f0f270 100644
--- a/lib/dev_server_wrapper.py
+++ b/lib/dev_server_wrapper.py
@@ -5,15 +5,11 @@
"""Module containing methods and classes to interact with a devserver instance.
"""
-import logging
-import multiprocessing
import os
-import psutil
+import multiprocessing
import re
import sys
-import tempfile
import time
-import urllib2
import constants
from chromite.lib import cros_build_lib
@@ -21,8 +17,6 @@
# Wait up to 15 minutes for the dev server to start. It can take a while to
# start when generating payloads in parallel.
DEV_SERVER_TIMEOUT = 900
-CHECK_HEALTH_URL = 'http://127.0.0.1:8080/check_health'
-KILL_TIMEOUT = 10
def GetIPAddress(device='eth0'):
@@ -58,111 +52,55 @@
class DevServerWrapper(multiprocessing.Process):
"""A Simple wrapper around a dev server instance."""
- def __init__(self, test_root=None):
- super(DevServerWrapper, self).__init__()
- self.test_root = test_root or DevServerWrapper.MkChrootTemp(is_dir=True)
- self._log_filename = os.path.join(self.test_root, 'dev_server.log')
- self._pid_file = DevServerWrapper.MkChrootTemp(is_dir=False)
- self._pid = None
-
- # Chroot helper methods. Since we call a script into the chroot with paths
- # created outside the chroot, translation back and forth is needed. These
- # methods all assume the default chroot dir.
-
- @staticmethod
- def MkChrootTemp(is_dir):
- """Returns a temp(dir if is_dir, file otherwise) in the chroot."""
- chroot_tmp = os.path.join(constants.SOURCE_ROOT, 'chroot', 'tmp')
- if is_dir:
- return tempfile.mkdtemp(prefix='devserver_wrapper', dir=chroot_tmp)
- else:
- return tempfile.NamedTemporaryFile(prefix='devserver_wrapper',
- dir=chroot_tmp, delete=False).name
-
- @staticmethod
- def ToChrootPath(path):
- """Converts the path outside the chroot to one that can be used inside."""
- path = os.path.abspath(path)
- if '/chroot/' not in path:
- raise ValueError('Path %s is not a path that points inside the chroot' %
- path)
-
- return '/' + path.partition('/chroot/')[2]
-
- def _WaitUntilStarted(self):
- """Wait until the devserver has started."""
- current_time = time.time()
- deadline = current_time + DEV_SERVER_TIMEOUT
- while current_time <= deadline:
- try:
- urllib2.urlopen(CHECK_HEALTH_URL, timeout=0.05)
- return
- except IOError:
- # urlopen errors will throw a subclass of IOError if we can't connect.
- pass
- finally:
- # Let's not churn needlessly in this loop as the devserver starts up.
- time.sleep(1)
-
- current_time = time.time()
- else:
- self.terminate()
- raise DevServerException('Devserver did not start')
+ def __init__(self, test_root):
+ self.proc = None
+ self.test_root = test_root
+ self._log_filename = os.path.join(test_root, 'dev_server.log')
+ multiprocessing.Process.__init__(self)
def run(self):
- """Kicks off devserver in a separate process and waits for it to finish."""
- cmd = ['start_devserver',
- '--pidfile', DevServerWrapper.ToChrootPath(self._pid_file),
- '--logfile', DevServerWrapper.ToChrootPath(self._log_filename)]
- return_obj = cros_build_lib.SudoRunCommand(
- cmd, enter_chroot=True, debug_level=logging.DEBUG,
- cwd=constants.SOURCE_ROOT, error_code_ok=True,
- redirect_stdout=True, combine_stdout_stderr=True)
- if return_obj.returncode != 0:
- logging.error('Devserver terminated unexpectedly!')
- logging.error(return_obj.output)
-
- def Start(self):
- """Starts a background devserver and waits for it to start.
-
- Starts a background devserver and waits for it to start. Will only return
- once devserver has started and running pid has been read.
- """
- self.start()
- self._WaitUntilStarted()
- # Pid file was passed into the chroot.
- with open(self._pid_file, 'r') as f:
- self._pid = int(f.read())
+ # Kill previous running instance of devserver if it exists.
+ self.Stop()
+ cmd = ['start_devserver']
+ cros_build_lib.SudoRunCommand(cmd, enter_chroot=True, print_cmd=False,
+ log_stdout_to_file=self._log_filename,
+ combine_stdout_stderr=True,
+ cwd=constants.SOURCE_ROOT)
def Stop(self):
- """Kills the devserver instance with SIGTERM and SIGKILL if SIGTERM fails"""
- if not self._pid:
- logging.error('No devserver running.')
- return
-
- logging.debug('Stopping devserver instance with pid %s', self._pid)
- process = psutil.Process(self._pid)
- if process.is_running():
- cros_build_lib.SudoRunCommand(['kill', str(self._pid)])
- else:
- logging.error('Devserver not running!')
- return
-
- try:
- process.wait(KILL_TIMEOUT)
- except psutil.error.TimeoutExpired:
- logging.warning('Devserver is unstoppable. Killing with SIGKILL')
- cros_build_lib.SudoRunCommand(['kill', '-9', str(self._pid)])
+ """Kills the devserver instance if it exists."""
+ cros_build_lib.SudoRunCommand(['pkill', '-f', 'devserver.py'],
+ error_code_ok=True, print_cmd=False)
def PrintLog(self):
- """Print devserver output to stdout."""
+ """Print devserver output."""
print '--- Start output from %s ---' % self._log_filename
# Open in update mode in case the child process hasn't opened the file yet.
with open(self._log_filename) as log:
sys.stdout.writelines(log)
-
print '--- End output from %s ---' % self._log_filename
+ def WaitUntilStarted(self):
+ """Wait until the devserver has started."""
+ # Open in update mode in case the child process hasn't opened the file yet.
+ pos = 0
+ with open(self._log_filename, 'w+') as log:
+ for _ in range(DEV_SERVER_TIMEOUT * 2):
+ log.seek(pos)
+ for line in log:
+ # When the dev server has started, it will print a line stating
+ # 'Bus STARTED'. Wait for that line to appear.
+ if 'Bus STARTED' in line:
+ return
+ # If we've read a complete line, and it doesn't contain the magic
+ # phrase, move on to the next line.
+ if line.endswith('\n'):
+ pos = log.tell()
+ # Looks like it hasn't started yet. Keep waiting...
+ time.sleep(0.5)
+ self.PrintLog()
+ raise DevServerException('Timeout waiting for the devserver to startup.')
+
@classmethod
def GetDevServerURL(cls, port=None, sub_dir=None):
"""Returns the dev server url for a given port and sub directory."""
diff --git a/lib/dev_server_wrapper_stress_test.py b/lib/dev_server_wrapper_stress_test.py
index b10b907..0b75c3b 100755
--- a/lib/dev_server_wrapper_stress_test.py
+++ b/lib/dev_server_wrapper_stress_test.py
@@ -6,33 +6,27 @@
"""Stress test for dev_server_wrapper.
-Test script runs a long time stressing the ability to start and stop the
+Test script runs forever stressing the ability to start and stop the
dev_server_wrapper. Even very rare hangs will cause significant build flake.
"""
-import logging
import sys
import constants
+sys.path.append(constants.CROSUTILS_LIB_DIR)
sys.path.append(constants.CROS_PLATFORM_ROOT)
sys.path.append(constants.SOURCE_ROOT)
from crostestutils.lib import dev_server_wrapper
-
-_ITERATIONS = 10000
-
-
-def main():
- logging.getLogger().setLevel(logging.DEBUG)
- for i in range(_ITERATIONS):
- print 'Iteration {}'.format(i)
- wrapper = dev_server_wrapper.DevServerWrapper()
- print 'Starting'
- wrapper.Start()
- print 'Stopping'
- wrapper.Stop()
-
-
-if __name__ == '__main__':
- main()
+i = 0
+while True:
+ i += 1
+ print 'Iteration {}'.format(i)
+ wrapper = dev_server_wrapper.DevServerWrapper('/tmp')
+ print 'Starting'
+ wrapper.start()
+ print 'Waiting for Started'
+ wrapper.WaitUntilStarted()
+ print 'Stopping'
+ wrapper.Stop()