Make the servo object a property of the host.

This adds a 'servo' member to instances of SiteHost, when the
target hostname has an associated "-servo" hostname as well.

Additionally, in order to support run_remote_tests, an optional
parameter to the host initialize() method can be used to specify
that servod should be started on the local host if no "-servo"
host can be found.

Not all test control files are updated to use the new scheme,
so class ServoTest retains the ability to create and start
servod itself, when necessary.

BUG=chromium-os:29209
TEST=run all the changed tests using a locally attached Servo
TEST=same test with servo debug header detached to force failure

Change-Id: Ibbd521ee5f90450fd5fa30629a020ba3fd45937d
Reviewed-on: https://gerrit.chromium.org/gerrit/20657
Tested-by: Richard Barnette <jrbarnette@chromium.org>
Reviewed-by: Chris Masone <cmasone@chromium.org>
Commit-Ready: Richard Barnette <jrbarnette@chromium.org>
diff --git a/server/cros/servo_test.py b/server/cros/servo_test.py
index dbbafa4..2138b1a 100644
--- a/server/cros/servo_test.py
+++ b/server/cros/servo_test.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 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.
 
@@ -22,8 +22,7 @@
         If use_faft flag is Ture, a remote FAFT client will be launched.
     """
     version = 2
-    # Abstracts access to all Servo functions.
-    servo = None
+
     # Exposes RPC access to a remote PyAuto client.
     pyauto = None
     # Exposes RPC access to a remote FAFT client.
@@ -71,13 +70,19 @@
         },
     }
 
-    def initialize(self, host, cmdline_args, use_pyauto=False, use_faft=False):
-        """Create a Servo object and install the dependency.
+    def _init_servo(self, host, cmdline_args):
+        """Initialize `self.servo`.
 
-        If use_pyauto/use_faft is True the PyAuto/FAFTClient dependency is
-        installed on the client and a remote PyAuto/FAFTClient server is
-        launched and connected.
+        If the host has an attached servo object, use that.
+        Otherwise assume that there's a locally attached servo
+        device, and start servod on localhost.
+
         """
+        if host.servo:
+            self.servo = host.servo
+            self._servo_is_local = False
+            return
+
         # Assign default arguments for servo invocation.
         args = {
             'servo_host': 'localhost', 'servo_port': 9999,
@@ -102,21 +107,40 @@
                 else:
                     args[key] = val
 
+        self.servo = servo.Servo(
+            args['servo_host'], args['servo_port'], args['xml_config'],
+            args['servo_vid'], args['servo_pid'], args['servo_serial'])
+        self._servo_is_local = True
+
+
+    def _release_servo(self):
+        """Clean up `self.servo` if it is locally attached."""
+        if self._servo_is_local:
+            del self.servo
+        self._servo_is_local = False
+
+
+    def initialize(self, host, cmdline_args, use_pyauto=False, use_faft=False):
+        """Create a Servo object and install the dependency.
+
+        If use_pyauto/use_faft is True the PyAuto/FAFTClient dependency is
+        installed on the client and a remote PyAuto/FAFTClient server is
+        launched and connected.
+        """
         # Initialize servotest args.
         self._client = host;
         self._remote_infos['pyauto']['used'] = use_pyauto
         self._remote_infos['faft']['used'] = use_faft
 
-        self.servo = servo.Servo(
-            args['servo_host'], args['servo_port'], args['xml_config'],
-            args['servo_vid'], args['servo_pid'], args['servo_serial'])
+        self._init_servo(host, cmdline_args)
+
         # Initializes dut, may raise AssertionError if pre-defined gpio
         # sequence to set GPIO's fail.  Autotest does not handle exception
         # throwing in initialize and will cause a test to hang.
         try:
             self.servo.initialize_dut()
         except (AssertionError, xmlrpclib.Fault) as e:
-            del self.servo
+            self._release_servo()
             raise error.TestFail(e)
 
         # Install PyAuto/FAFTClient dependency.
@@ -241,8 +265,7 @@
 
     def cleanup(self):
         """Delete the Servo object, call remote cleanup, and kill ssh."""
-        if self.servo:
-            del self.servo
+        self._release_servo()
         for info in self._remote_infos.itervalues():
             if info['remote_process'] and info['remote_process'].poll() is None:
                 remote_object = getattr(self, info['ref_name'])