faft: Start devserver precisely

Original we used the start_devserver script to start a devserver. It is a
bash script and forks a separate python process for the devserver. It also
blocks the SIGTERM. So we can't terminate the devserver process actually.

This CL is to fork the devserve python process directly, instead of the bash
script.

An additional check is added to ensure the devserver startup correctly.

BUG=chrome-os-partner:14884,chromium-os:34395
TEST=run_remote_tests.sh --board daisy --remote dut -a \
     "image=/path/to/chromiumos_test_image.bin" TryFwB/control$

Change-Id: I4023e67dd5d09fb40e24f636ccbe1ddecfd32778
Reviewed-on: https://gerrit.chromium.org/gerrit/36424
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Commit-Ready: Tom Wai-Hong Tam <waihong@chromium.org>
Tested-by: Tom Wai-Hong Tam <waihong@chromium.org>
diff --git a/server/cros/faftsequence.py b/server/cros/faftsequence.py
index 94d9157..1fe8e34 100644
--- a/server/cros/faftsequence.py
+++ b/server/cros/faftsequence.py
@@ -108,6 +108,8 @@
     EC_BOOT_DELAY = 0.5
     # Duration of holding cold_reset to reset device
     COLD_RESET_DELAY = 0.1
+    # devserver startup time
+    DEVSERVER_DELAY = 10
 
     # The developer screen timeouts fit our spec.
     DEV_SCREEN_TIMEOUT = 30
@@ -405,6 +407,9 @@
         Args:
             image_path: An URL or a path on the host to the test image.
             firmware_update: Also update the firmware after installing.
+
+        Raises:
+          error.TestError: If devserver failed to start.
         """
         if not image_path:
             return
@@ -425,7 +430,7 @@
             # even we don't use them. Otherwise, the socket of devserve is
             # created as fd 1 (as no stdout) but it still thinks stdout is fd
             # 1 and dump the log to the socket. Wrong HTTP protocol happens.
-            devserver = subprocess.Popen(['start_devserver',
+            devserver = subprocess.Popen(['/usr/lib/devserver/devserver.py',
                         '--archive_dir=%s' % image_dir,
                         '--port=%s' % self._DEVSERVER_PORT],
                         stdout=subprocess.PIPE,
@@ -436,6 +441,14 @@
                         self._DEVSERVER_PORT,
                         image_base)
 
+            # Wait devserver startup completely
+            time.sleep(self.DEVSERVER_DELAY)
+            # devserver is a service running forever. If it is terminated,
+            # some error does happen.
+            if devserver.poll():
+                raise error.TestError('Starting devserver failed, '
+                                      'returning %d.' % devserver.returncode)
+
         logging.info('Ask Servo to install the image from %s' % image_url)
         self.servo.image_to_servo_usb(image_url)