Bluetooth: allow tester IP to be specified in --args

Normally the tester hostname is derived from the DUT hostname by
appending '-router' to the first part. This requires manual /etc/hosts
entries on your workstation when dealing with machines by IP address.

Allowing the IP (or hostname) of the tester to be specified on the
command-line with '--args tester=IP' makes this much easier to handle.

BUG=none
TEST=test_that $DUT_IP bluetooth_Sanity_Discovery --args tester=$TESTER_IP

Change-Id: Ic113cb73a2de95e60b75931d95f2b1ea7ba4a2cf
Reviewed-on: https://chromium-review.googlesource.com/233492
Reviewed-by: Michael Janssen <jamuraa@chromium.org>
Commit-Queue: Scott James Remnant <keybuk@chromium.org>
Tested-by: Scott James Remnant <keybuk@chromium.org>
diff --git a/server/cros/bluetooth/bluetooth_tester.py b/server/cros/bluetooth/bluetooth_tester.py
index 581b451..1fdffd3 100644
--- a/server/cros/bluetooth/bluetooth_tester.py
+++ b/server/cros/bluetooth/bluetooth_tester.py
@@ -4,7 +4,9 @@
 
 import base64
 import json
+import socket
 
+from autotest_lib.client.common_lib import error
 from autotest_lib.client.cros import constants
 from autotest_lib.server import autotest, hosts
 
@@ -197,21 +199,40 @@
                                                             invalid_request)
 
 
-def create_host_from(device_host):
+def create_host_from(device_host, args=None):
     """Creates a host object for the Tester associated with a DUT.
 
-    Will raise an exception if there isn't a tester for the DUT.
+    The IP address or the hostname can be specified in the 'tester' member of
+    the argument dictionary. When not present it is derived from the hostname
+    of the DUT by appending '-router' to the first part.
+
+    Will raise an exception if there isn't a tester for the DUT, or if the DUT
+    is specified as an IP address and thus the hostname cannot be derived.
 
     @param device_host: Autotest host object for the DUT.
+    @param args: Dictionary of arguments passed to the test.
 
     @return Autotest host object for the Tester.
 
     """
 
-    device_hostname = device_host.hostname
+    def is_ip_address(hostname):
+        try:
+            socket.inet_aton(hostname)
+            return True
+        except socket.error:
+            return False
 
-    parts = device_hostname.split('.')
-    parts[0] = parts[0] + '-router'
-    tester_hostname = '.'.join(parts)
+    try:
+        tester_hostname = args['tester']
+    except KeyError:
+        device_hostname = device_host.hostname
+        if is_ip_address(device_hostname):
+            raise error.TestError("Remote host cannot be an IP address unless "
+                                  "tester specified with --args tester=IP")
+
+        parts = device_hostname.split('.')
+        parts[0] = parts[0] + '-router'
+        tester_hostname = '.'.join(parts)
 
     return hosts.create_host(tester_hostname)