Home | History | Annotate | Download | only in tradefed
      1 #
      2 # Copyright (C) 2017 The Android Open Source Project
      3 #
      4 # Licensed under the Apache License, Version 2.0 (the "License");
      5 # you may not use this file except in compliance with the License.
      6 # You may obtain a copy of the License at
      7 #
      8 #      http://www.apache.org/licenses/LICENSE-2.0
      9 #
     10 # Unless required by applicable law or agreed to in writing, software
     11 # distributed under the License is distributed on an "AS IS" BASIS,
     12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 # See the License for the specific language governing permissions and
     14 # limitations under the License.
     15 #
     16 
     17 import logging
     18 import socket
     19 import time
     20 
     21 from host_controller.tradefed import remote_operation
     22 
     23 LOCALHOST = "localhost"
     24 DEFAULT_PORT = 30103
     25 
     26 
     27 class RemoteClient(object):
     28     """The class for sending remote operations to TradeFed."""
     29 
     30     def __init__(self, host=LOCALHOST, port=DEFAULT_PORT, timeout=None):
     31         """Initializes the client of TradeFed remote manager.
     32 
     33         Args:
     34             _host: The host name of the remote manager.
     35             _port: The port of the remote manager.
     36             _timeout: The connect and receive timeout in seconds
     37         """
     38         self._host = host
     39         self._port = port
     40         self._timeout = timeout if timeout else socket.getdefaulttimeout()
     41 
     42     def SendOperations(self, *operations):
     43         """Sends a list of operations and waits for each response.
     44 
     45         Args:
     46             *operations: A list of remote_operation.RemoteOperation objects.
     47 
     48         Returns:
     49             A list of JSON objects.
     50 
     51         Raises:
     52             socket.error if fails to communicate with remote manager.
     53             remote_operation.RemoteOperationException if any operation fails or
     54             has no response.
     55         """
     56         op_socket = socket.create_connection((self._host, self._port),
     57                                              self._timeout)
     58         logging.info("Connect to %s:%d", self._host, self._port)
     59         try:
     60             if self._timeout is not None:
     61                 op_socket.settimeout(self._timeout)
     62             ops_str = "\n".join(str(op) for op in operations)
     63             logging.info("Send: %s", ops_str)
     64             op_socket.send(ops_str)
     65             op_socket.shutdown(socket.SHUT_WR)
     66             resp_str = ""
     67             while True:
     68                 buf = op_socket.recv(4096)
     69                 if not buf:
     70                     break
     71                 resp_str += buf
     72         finally:
     73             op_socket.close()
     74         logging.info("Receive: %s", resp_str)
     75         resp_lines = [x for x in resp_str.split("\n") if x]
     76         if len(resp_lines) != len(operations):
     77             raise remote_operation.RemoteOperationException(
     78                     "Unexpected number of responses: %d" % len(resp_lines))
     79         return [operations[i].ParseResponse(resp_lines[i])
     80                 for i in range(len(resp_lines))]
     81 
     82     def SendOperation(self, operation):
     83         """Sends one operation and waits for its response.
     84 
     85         Args:
     86             operation: A remote_operation.RemoteOperation object.
     87 
     88         Returns:
     89             A JSON object.
     90 
     91         Raises:
     92             socket.error if fails to communicate with remote manager.
     93             remote_operation.RemoteOperationException if the operation fails or
     94             has no response.
     95         """
     96         return self.SendOperations(operation)[0]
     97 
     98     def ListDevices(self):
     99         """Sends ListDevices operation.
    100 
    101         Returns:
    102             A list of device_info.DeviceInfo which are the devices connected to
    103             the host.
    104         """
    105         json_obj = self.SendOperation(remote_operation.ListDevices())
    106         return remote_operation.ParseListDevicesResponse(json_obj)
    107 
    108     def WaitForCommandResult(self, serial, timeout, poll_interval=5):
    109         """Sends a series of operations to wait until a command finishes.
    110 
    111         Args:
    112             serial: The serial number of the device.
    113             timeout: A float, the timeout in seconds.
    114             poll_interval: A float, the interval of each GetLastCommandResult
    115                            operation in seconds.
    116 
    117         Returns:
    118             A JSON object which is the result of the command.
    119             None if timeout.
    120 
    121             Sample
    122             {'status': 'INVOCATION_SUCCESS',
    123              'free_device_state': 'AVAILABLE'}
    124         """
    125         deadline = time.time() + timeout
    126         get_result_op = remote_operation.GetLastCommandResult(serial)
    127         while True:
    128             result = self.SendOperation(get_result_op)
    129             if result["status"] != "EXECUTING":
    130                 return result
    131             if time.time() > deadline:
    132                 return None
    133             time.sleep(poll_interval)
    134             if time.time() > deadline:
    135                 return None
    136