blob: 39b8e443a2212e0b56306832ba9b6aeb90fcc4b2 [file] [log] [blame]
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +08001# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4#
5
6"""This file provides core logic for connecting a Chameleon Daemon."""
7
Cheng-Yi Chiang630179d2015-08-20 20:43:39 +08008import logging
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +08009
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +080010from autotest_lib.client.bin import utils
Nicolas Boichat4eee8012015-10-21 19:13:41 +080011from autotest_lib.client.common_lib import global_config
Tom Wai-Hong Tam2588ce12014-08-21 06:24:05 +080012from autotest_lib.client.cros.chameleon import chameleon
Cheng-Yi Chiang22612862015-08-20 20:39:57 +080013from autotest_lib.server.cros import dnsname_mangler
Nicolas Boichatacfcf232015-10-20 16:29:12 +080014from autotest_lib.server.cros.dynamic_suite import frontend_wrappers
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +080015from autotest_lib.server.hosts import ssh_host
16
Nicolas Boichatacfcf232015-10-20 16:29:12 +080017
18# Names of the host attributes in the database that represent the values for
19# the chameleon_host and chameleon_port for a servo connected to the DUT.
20CHAMELEON_HOST_ATTR = 'chameleon_host'
21CHAMELEON_PORT_ATTR = 'chameleon_port'
22
Nicolas Boichat4eee8012015-10-21 19:13:41 +080023_CONFIG = global_config.global_config
xixuan6cf6d2f2016-01-29 15:29:00 -080024ENABLE_SSH_TUNNEL_FOR_CHAMELEON = _CONFIG.get_config_value(
25 'CROS', 'enable_ssh_tunnel_for_chameleon', type=bool, default=False)
Nicolas Boichat4eee8012015-10-21 19:13:41 +080026
Cheng-Yi Chiang630179d2015-08-20 20:43:39 +080027class ChameleonHostError(Exception):
28 """Error in ChameleonHost."""
29 pass
30
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +080031
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +080032class ChameleonHost(ssh_host.SSHHost):
33 """Host class for a host that controls a Chameleon."""
34
35 # Chameleond process name.
36 CHAMELEOND_PROCESS = 'chameleond'
37
38
39 # TODO(waihong): Add verify and repair logic which are required while
40 # deploying to Cros Lab.
41
42
43 def _initialize(self, chameleon_host='localhost', chameleon_port=9992,
44 *args, **dargs):
45 """Initialize a ChameleonHost instance.
46
47 A ChameleonHost instance represents a host that controls a Chameleon.
48
49 @param chameleon_host: Name of the host where the chameleond process
50 is running.
Cheng-Yi Chiang22612862015-08-20 20:39:57 +080051 If this is passed in by IP address, it will be
52 treated as not in lab.
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +080053 @param chameleon_port: Port the chameleond process is listening on.
54
55 """
56 super(ChameleonHost, self)._initialize(hostname=chameleon_host,
57 *args, **dargs)
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +080058
Cheng-Yi Chiang22612862015-08-20 20:39:57 +080059 self._is_in_lab = None
60 self._check_if_is_in_lab()
61
Cheng-Yi Chiang630179d2015-08-20 20:43:39 +080062 self._chameleon_port = chameleon_port
63 self._local_port = None
64 self._tunneling_process = None
65
xixuan5492f3d2016-04-25 16:35:05 -070066 try:
67 if self._is_in_lab and not ENABLE_SSH_TUNNEL_FOR_CHAMELEON:
68 self._chameleon_connection = chameleon.ChameleonConnection(
69 self.hostname, chameleon_port)
70 else:
Joseph Hwangd3e32002016-08-26 15:23:08 +080071 # A proxy generator is passed as an argument so that a proxy
72 # could be re-created on demand in ChameleonConnection
73 # whenever needed, e.g., after a reboot.
74 proxy_generator = (
75 lambda: self.rpc_server_tracker.xmlrpc_connect(
76 None, chameleon_port,
77 ready_test_name=chameleon.CHAMELEON_READY_TEST,
78 timeout_seconds=60))
xixuan5492f3d2016-04-25 16:35:05 -070079 self._chameleon_connection = chameleon.ChameleonConnection(
Joseph Hwangd3e32002016-08-26 15:23:08 +080080 None, proxy_generator=proxy_generator)
81
xixuan5492f3d2016-04-25 16:35:05 -070082 except Exception as e:
83 raise ChameleonHostError('Can not connect to Chameleon: %s(%s)',
84 e.__class__, e)
Cheng-Yi Chiang630179d2015-08-20 20:43:39 +080085
Cheng-Yi Chiang22612862015-08-20 20:39:57 +080086
87 def _check_if_is_in_lab(self):
88 """Checks if Chameleon host is in lab and set self._is_in_lab.
89
90 If self.hostname is an IP address, we treat it as is not in lab zone.
91
92 """
93 self._is_in_lab = (False if dnsname_mangler.is_ip_address(self.hostname)
94 else utils.host_is_in_lab_zone(self.hostname))
95
96
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +080097 def is_in_lab(self):
98 """Check whether the chameleon host is a lab device.
99
100 @returns: True if the chameleon host is in Cros Lab, otherwise False.
101
102 """
103 return self._is_in_lab
104
105
Tom Wai-Hong Tamefe1c7f2014-01-02 14:00:11 +0800106 def get_wait_up_processes(self):
107 """Get the list of local processes to wait for in wait_up.
108
109 Override get_wait_up_processes in
110 autotest_lib.client.common_lib.hosts.base_classes.Host.
111 Wait for chameleond process to go up. Called by base class when
112 rebooting the device.
113
114 """
115 processes = [self.CHAMELEOND_PROCESS]
116 return processes
117
Tom Wai-Hong Tameaee3402014-01-22 08:52:10 +0800118
119 def create_chameleon_board(self):
Moja Hsu57d93a12017-01-13 17:57:52 +0800120 """Create a ChameleonBoard object with error recovery.
121
122 This function will reboot the chameleon board once and retry if we can't
123 create chameleon board.
124
125 @return A ChameleonBoard object.
126 """
Tom Wai-Hong Tameaee3402014-01-22 08:52:10 +0800127 # TODO(waihong): Add verify and repair logic which are required while
128 # deploying to Cros Lab.
Moja Hsu57d93a12017-01-13 17:57:52 +0800129 chameleon_board = None
130 try:
131 chameleon_board = chameleon.ChameleonBoard(
132 self._chameleon_connection, self)
133 return chameleon_board
134 except:
135 self.reboot()
136 chameleon_board = chameleon.ChameleonBoard(
137 self._chameleon_connection, self)
138 return chameleon_board
Tom Wai-Hong Tam3d6790d2014-04-14 16:15:47 +0800139
140
141def create_chameleon_host(dut, chameleon_args):
142 """Create a ChameleonHost object.
143
144 There three possible cases:
145 1) If the DUT is in Cros Lab and has a chameleon board, then create
146 a ChameleonHost object pointing to the board. chameleon_args
147 is ignored.
148 2) If not case 1) and chameleon_args is neither None nor empty, then
149 create a ChameleonHost object using chameleon_args.
150 3) If neither case 1) or 2) applies, return None.
151
152 @param dut: host name of the host that chameleon connects. It can be used
153 to lookup the chameleon in test lab using naming convention.
Cheng-Yi Chiang22612862015-08-20 20:39:57 +0800154 If dut is an IP address, it can not be used to lookup the
155 chameleon in test lab.
Tom Wai-Hong Tam3d6790d2014-04-14 16:15:47 +0800156 @param chameleon_args: A dictionary that contains args for creating
157 a ChameleonHost object,
158 e.g. {'chameleon_host': '172.11.11.112',
159 'chameleon_port': 9992}.
160
161 @returns: A ChameleonHost object or None.
162
163 """
Nicolas Boichat4eee8012015-10-21 19:13:41 +0800164 if not utils.is_in_container():
165 is_moblab = utils.is_moblab()
166 else:
167 is_moblab = _CONFIG.get_config_value(
168 'SSP', 'is_moblab', type=bool, default=False)
169
Nicolas Boichatacfcf232015-10-20 16:29:12 +0800170 if not is_moblab:
171 dut_is_hostname = not dnsname_mangler.is_ip_address(dut)
172 if dut_is_hostname:
173 chameleon_hostname = chameleon.make_chameleon_hostname(dut)
174 if utils.host_is_in_lab_zone(chameleon_hostname):
Cheng-Yi Chiang8d3cbbb2016-10-20 15:54:40 +0800175 # Be more tolerant on chameleon in the lab because
176 # we don't want dead chameleon blocks non-chameleon tests.
177 if utils.ping(chameleon_hostname, deadline=3):
178 logging.warning(
179 'Chameleon %s is not accessible. Please file a bug'
180 ' to test lab', chameleon_hostname)
181 return None
Prathmesh Prabhufd49f0d2018-09-20 21:02:38 +0000182 return ChameleonHost(chameleon_host=chameleon_hostname)
Nicolas Boichatacfcf232015-10-20 16:29:12 +0800183 if chameleon_args:
184 return ChameleonHost(**chameleon_args)
185 else:
186 return None
Tom Wai-Hong Tam3d6790d2014-04-14 16:15:47 +0800187 else:
Nicolas Boichatacfcf232015-10-20 16:29:12 +0800188 afe = frontend_wrappers.RetryingAFE(timeout_min=5, delay_sec=10)
189 hosts = afe.get_hosts(hostname=dut)
190 if hosts and CHAMELEON_HOST_ATTR in hosts[0].attributes:
Prathmesh Prabhufd49f0d2018-09-20 21:02:38 +0000191 return ChameleonHost(
Nicolas Boichatacfcf232015-10-20 16:29:12 +0800192 chameleon_host=hosts[0].attributes[CHAMELEON_HOST_ATTR],
193 chameleon_port=hosts[0].attributes.get(
194 CHAMELEON_PORT_ATTR, 9992)
195 )
196 else:
197 return None