1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python 2*800a58d9SAndroid Build Coastguard Worker# 3*800a58d9SAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project 4*800a58d9SAndroid Build Coastguard Worker# 5*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*800a58d9SAndroid Build Coastguard Worker# 9*800a58d9SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*800a58d9SAndroid Build Coastguard Worker# 11*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*800a58d9SAndroid Build Coastguard Worker# limitations under the License. 16*800a58d9SAndroid Build Coastguard Worker"""Common operations to create remote devices.""" 17*800a58d9SAndroid Build Coastguard Worker 18*800a58d9SAndroid Build Coastguard Workerimport logging 19*800a58d9SAndroid Build Coastguard Workerimport os 20*800a58d9SAndroid Build Coastguard Worker 21*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors 22*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import avd 23*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import report 24*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants 25*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils 26*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib.adb_tools import AdbTools 27*800a58d9SAndroid Build Coastguard Worker 28*800a58d9SAndroid Build Coastguard Worker 29*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 30*800a58d9SAndroid Build Coastguard Worker_GCE_QUOTA_ERROR_KEYWORDS = [ 31*800a58d9SAndroid Build Coastguard Worker "Quota exceeded for quota", 32*800a58d9SAndroid Build Coastguard Worker "ZONE_RESOURCE_POOL_EXHAUSTED", 33*800a58d9SAndroid Build Coastguard Worker "ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS"] 34*800a58d9SAndroid Build Coastguard Worker_DICT_ERROR_TYPE = { 35*800a58d9SAndroid Build Coastguard Worker constants.STAGE_INIT: constants.ACLOUD_INIT_ERROR, 36*800a58d9SAndroid Build Coastguard Worker constants.STAGE_GCE: constants.ACLOUD_CREATE_GCE_ERROR, 37*800a58d9SAndroid Build Coastguard Worker constants.STAGE_SSH_CONNECT: constants.ACLOUD_SSH_CONNECT_ERROR, 38*800a58d9SAndroid Build Coastguard Worker constants.STAGE_ARTIFACT: constants.ACLOUD_DOWNLOAD_ARTIFACT_ERROR, 39*800a58d9SAndroid Build Coastguard Worker constants.STAGE_BOOT_UP: constants.ACLOUD_BOOT_UP_ERROR, 40*800a58d9SAndroid Build Coastguard Worker} 41*800a58d9SAndroid Build Coastguard Worker 42*800a58d9SAndroid Build Coastguard Worker 43*800a58d9SAndroid Build Coastguard Workerdef CreateSshKeyPairIfNecessary(cfg): 44*800a58d9SAndroid Build Coastguard Worker """Create ssh key pair if necessary. 45*800a58d9SAndroid Build Coastguard Worker 46*800a58d9SAndroid Build Coastguard Worker Args: 47*800a58d9SAndroid Build Coastguard Worker cfg: An Acloudconfig instance. 48*800a58d9SAndroid Build Coastguard Worker 49*800a58d9SAndroid Build Coastguard Worker Raises: 50*800a58d9SAndroid Build Coastguard Worker error.DriverError: If it falls into an unexpected condition. 51*800a58d9SAndroid Build Coastguard Worker """ 52*800a58d9SAndroid Build Coastguard Worker if not cfg.ssh_public_key_path: 53*800a58d9SAndroid Build Coastguard Worker logger.warning( 54*800a58d9SAndroid Build Coastguard Worker "ssh_public_key_path is not specified in acloud config. " 55*800a58d9SAndroid Build Coastguard Worker "Project-wide public key will " 56*800a58d9SAndroid Build Coastguard Worker "be used when creating AVD instances. " 57*800a58d9SAndroid Build Coastguard Worker "Please ensure you have the correct private half of " 58*800a58d9SAndroid Build Coastguard Worker "a project-wide public key if you want to ssh into the " 59*800a58d9SAndroid Build Coastguard Worker "instances after creation.") 60*800a58d9SAndroid Build Coastguard Worker elif cfg.ssh_public_key_path and not cfg.ssh_private_key_path: 61*800a58d9SAndroid Build Coastguard Worker logger.warning( 62*800a58d9SAndroid Build Coastguard Worker "Only ssh_public_key_path is specified in acloud config, " 63*800a58d9SAndroid Build Coastguard Worker "but ssh_private_key_path is missing. " 64*800a58d9SAndroid Build Coastguard Worker "Please ensure you have the correct private half " 65*800a58d9SAndroid Build Coastguard Worker "if you want to ssh into the instances after creation.") 66*800a58d9SAndroid Build Coastguard Worker elif cfg.ssh_public_key_path and cfg.ssh_private_key_path: 67*800a58d9SAndroid Build Coastguard Worker utils.CreateSshKeyPairIfNotExist(cfg.ssh_private_key_path, 68*800a58d9SAndroid Build Coastguard Worker cfg.ssh_public_key_path) 69*800a58d9SAndroid Build Coastguard Worker else: 70*800a58d9SAndroid Build Coastguard Worker # Should never reach here. 71*800a58d9SAndroid Build Coastguard Worker raise errors.DriverError( 72*800a58d9SAndroid Build Coastguard Worker "Unexpected error in CreateSshKeyPairIfNecessary") 73*800a58d9SAndroid Build Coastguard Worker 74*800a58d9SAndroid Build Coastguard Worker 75*800a58d9SAndroid Build Coastguard Workerclass DevicePool: 76*800a58d9SAndroid Build Coastguard Worker """A class that manages a pool of virtual devices. 77*800a58d9SAndroid Build Coastguard Worker 78*800a58d9SAndroid Build Coastguard Worker Attributes: 79*800a58d9SAndroid Build Coastguard Worker devices: A list of devices in the pool. 80*800a58d9SAndroid Build Coastguard Worker """ 81*800a58d9SAndroid Build Coastguard Worker 82*800a58d9SAndroid Build Coastguard Worker def __init__(self, device_factory, devices=None): 83*800a58d9SAndroid Build Coastguard Worker """Constructs a new DevicePool. 84*800a58d9SAndroid Build Coastguard Worker 85*800a58d9SAndroid Build Coastguard Worker Args: 86*800a58d9SAndroid Build Coastguard Worker device_factory: A device factory capable of producing a goldfish or 87*800a58d9SAndroid Build Coastguard Worker cuttlefish device. The device factory must expose an attribute with 88*800a58d9SAndroid Build Coastguard Worker the credentials that can be used to retrieve information from the 89*800a58d9SAndroid Build Coastguard Worker constructed device. 90*800a58d9SAndroid Build Coastguard Worker devices: List of devices managed by this pool. 91*800a58d9SAndroid Build Coastguard Worker """ 92*800a58d9SAndroid Build Coastguard Worker self._devices = devices or [] 93*800a58d9SAndroid Build Coastguard Worker self._device_factory = device_factory 94*800a58d9SAndroid Build Coastguard Worker self._compute_client = device_factory.GetComputeClient() 95*800a58d9SAndroid Build Coastguard Worker 96*800a58d9SAndroid Build Coastguard Worker def CreateDevices(self, num): 97*800a58d9SAndroid Build Coastguard Worker """Creates |num| devices for given build_target and build_id. 98*800a58d9SAndroid Build Coastguard Worker 99*800a58d9SAndroid Build Coastguard Worker Args: 100*800a58d9SAndroid Build Coastguard Worker num: Number of devices to create. 101*800a58d9SAndroid Build Coastguard Worker """ 102*800a58d9SAndroid Build Coastguard Worker # Create host instances for cuttlefish/goldfish device. 103*800a58d9SAndroid Build Coastguard Worker # Currently one instance supports only 1 device. 104*800a58d9SAndroid Build Coastguard Worker for _ in range(num): 105*800a58d9SAndroid Build Coastguard Worker instance = self._device_factory.CreateInstance() 106*800a58d9SAndroid Build Coastguard Worker ip = self._compute_client.GetInstanceIP(instance) 107*800a58d9SAndroid Build Coastguard Worker time_info = { 108*800a58d9SAndroid Build Coastguard Worker stage: round(exec_time, 2) for stage, exec_time in 109*800a58d9SAndroid Build Coastguard Worker getattr(self._compute_client, "execution_time", {}).items()} 110*800a58d9SAndroid Build Coastguard Worker stage = self._compute_client.stage if hasattr( 111*800a58d9SAndroid Build Coastguard Worker self._compute_client, "stage") else 0 112*800a58d9SAndroid Build Coastguard Worker openwrt = self._compute_client.openwrt if hasattr( 113*800a58d9SAndroid Build Coastguard Worker self._compute_client, "openwrt") else False 114*800a58d9SAndroid Build Coastguard Worker gce_hostname = self._compute_client.gce_hostname if hasattr( 115*800a58d9SAndroid Build Coastguard Worker self._compute_client, "gce_hostname") else None 116*800a58d9SAndroid Build Coastguard Worker self.devices.append( 117*800a58d9SAndroid Build Coastguard Worker avd.AndroidVirtualDevice(ip=ip, instance_name=instance, 118*800a58d9SAndroid Build Coastguard Worker time_info=time_info, stage=stage, 119*800a58d9SAndroid Build Coastguard Worker openwrt=openwrt, gce_hostname=gce_hostname)) 120*800a58d9SAndroid Build Coastguard Worker 121*800a58d9SAndroid Build Coastguard Worker @utils.TimeExecute(function_description="Waiting for AVD(s) to boot up", 122*800a58d9SAndroid Build Coastguard Worker result_evaluator=utils.BootEvaluator) 123*800a58d9SAndroid Build Coastguard Worker def WaitForBoot(self, boot_timeout_secs): 124*800a58d9SAndroid Build Coastguard Worker """Waits for all devices to boot up. 125*800a58d9SAndroid Build Coastguard Worker 126*800a58d9SAndroid Build Coastguard Worker Args: 127*800a58d9SAndroid Build Coastguard Worker boot_timeout_secs: Integer, the maximum time in seconds used to 128*800a58d9SAndroid Build Coastguard Worker wait for the AVD to boot. 129*800a58d9SAndroid Build Coastguard Worker 130*800a58d9SAndroid Build Coastguard Worker Returns: 131*800a58d9SAndroid Build Coastguard Worker A dictionary that contains all the failures. 132*800a58d9SAndroid Build Coastguard Worker The key is the name of the instance that fails to boot, 133*800a58d9SAndroid Build Coastguard Worker and the value is an errors.DeviceBootError object. 134*800a58d9SAndroid Build Coastguard Worker """ 135*800a58d9SAndroid Build Coastguard Worker failures = {} 136*800a58d9SAndroid Build Coastguard Worker for device in self._devices: 137*800a58d9SAndroid Build Coastguard Worker try: 138*800a58d9SAndroid Build Coastguard Worker self._compute_client.WaitForBoot(device.instance_name, boot_timeout_secs) 139*800a58d9SAndroid Build Coastguard Worker except errors.DeviceBootError as e: 140*800a58d9SAndroid Build Coastguard Worker failures[device.instance_name] = e 141*800a58d9SAndroid Build Coastguard Worker return failures 142*800a58d9SAndroid Build Coastguard Worker 143*800a58d9SAndroid Build Coastguard Worker def UpdateReport(self, reporter): 144*800a58d9SAndroid Build Coastguard Worker """Update report from compute client. 145*800a58d9SAndroid Build Coastguard Worker 146*800a58d9SAndroid Build Coastguard Worker Args: 147*800a58d9SAndroid Build Coastguard Worker reporter: Report object. 148*800a58d9SAndroid Build Coastguard Worker """ 149*800a58d9SAndroid Build Coastguard Worker reporter.UpdateData(self._compute_client.dict_report) 150*800a58d9SAndroid Build Coastguard Worker 151*800a58d9SAndroid Build Coastguard Worker def CollectSerialPortLogs(self, output_file, 152*800a58d9SAndroid Build Coastguard Worker port=constants.DEFAULT_SERIAL_PORT): 153*800a58d9SAndroid Build Coastguard Worker """Tar the instance serial logs into specified output_file. 154*800a58d9SAndroid Build Coastguard Worker 155*800a58d9SAndroid Build Coastguard Worker Args: 156*800a58d9SAndroid Build Coastguard Worker output_file: String, the output tar file path 157*800a58d9SAndroid Build Coastguard Worker port: The serial port number to be collected 158*800a58d9SAndroid Build Coastguard Worker """ 159*800a58d9SAndroid Build Coastguard Worker # For emulator, the serial log is the virtual host serial log. 160*800a58d9SAndroid Build Coastguard Worker # For GCE AVD device, the serial log is the AVD device serial log. 161*800a58d9SAndroid Build Coastguard Worker with utils.TempDir() as tempdir: 162*800a58d9SAndroid Build Coastguard Worker src_dict = {} 163*800a58d9SAndroid Build Coastguard Worker for device in self._devices: 164*800a58d9SAndroid Build Coastguard Worker logger.info("Store instance %s serial port %s output to %s", 165*800a58d9SAndroid Build Coastguard Worker device.instance_name, port, output_file) 166*800a58d9SAndroid Build Coastguard Worker serial_log = self._compute_client.GetSerialPortOutput( 167*800a58d9SAndroid Build Coastguard Worker instance=device.instance_name, port=port) 168*800a58d9SAndroid Build Coastguard Worker file_name = "%s_serial_%s.log" % (device.instance_name, port) 169*800a58d9SAndroid Build Coastguard Worker file_path = os.path.join(tempdir, file_name) 170*800a58d9SAndroid Build Coastguard Worker src_dict[file_path] = file_name 171*800a58d9SAndroid Build Coastguard Worker with open(file_path, "w") as f: 172*800a58d9SAndroid Build Coastguard Worker f.write(serial_log.encode("utf-8")) 173*800a58d9SAndroid Build Coastguard Worker utils.MakeTarFile(src_dict, output_file) 174*800a58d9SAndroid Build Coastguard Worker 175*800a58d9SAndroid Build Coastguard Worker def SetDeviceBuildInfo(self): 176*800a58d9SAndroid Build Coastguard Worker """Add devices build info.""" 177*800a58d9SAndroid Build Coastguard Worker for device in self._devices: 178*800a58d9SAndroid Build Coastguard Worker device.build_info = self._device_factory.GetBuildInfoDict() 179*800a58d9SAndroid Build Coastguard Worker 180*800a58d9SAndroid Build Coastguard Worker @property 181*800a58d9SAndroid Build Coastguard Worker def devices(self): 182*800a58d9SAndroid Build Coastguard Worker """Returns a list of devices in the pool. 183*800a58d9SAndroid Build Coastguard Worker 184*800a58d9SAndroid Build Coastguard Worker Returns: 185*800a58d9SAndroid Build Coastguard Worker A list of devices in the pool. 186*800a58d9SAndroid Build Coastguard Worker """ 187*800a58d9SAndroid Build Coastguard Worker return self._devices 188*800a58d9SAndroid Build Coastguard Worker 189*800a58d9SAndroid Build Coastguard Workerdef _GetErrorType(error): 190*800a58d9SAndroid Build Coastguard Worker """Get proper error type from the exception error. 191*800a58d9SAndroid Build Coastguard Worker 192*800a58d9SAndroid Build Coastguard Worker Args: 193*800a58d9SAndroid Build Coastguard Worker error: errors object. 194*800a58d9SAndroid Build Coastguard Worker 195*800a58d9SAndroid Build Coastguard Worker Returns: 196*800a58d9SAndroid Build Coastguard Worker String of error type. e.g. "ACLOUD_BOOT_UP_ERROR". 197*800a58d9SAndroid Build Coastguard Worker """ 198*800a58d9SAndroid Build Coastguard Worker if isinstance(error, errors.CheckGCEZonesQuotaError): 199*800a58d9SAndroid Build Coastguard Worker return constants.GCE_QUOTA_ERROR 200*800a58d9SAndroid Build Coastguard Worker if isinstance(error, errors.DownloadArtifactError): 201*800a58d9SAndroid Build Coastguard Worker return constants.ACLOUD_DOWNLOAD_ARTIFACT_ERROR 202*800a58d9SAndroid Build Coastguard Worker if isinstance(error, errors.DeviceConnectionError): 203*800a58d9SAndroid Build Coastguard Worker return constants.ACLOUD_SSH_CONNECT_ERROR 204*800a58d9SAndroid Build Coastguard Worker for keyword in _GCE_QUOTA_ERROR_KEYWORDS: 205*800a58d9SAndroid Build Coastguard Worker if keyword in str(error): 206*800a58d9SAndroid Build Coastguard Worker return constants.GCE_QUOTA_ERROR 207*800a58d9SAndroid Build Coastguard Worker return constants.ACLOUD_UNKNOWN_ERROR 208*800a58d9SAndroid Build Coastguard Worker 209*800a58d9SAndroid Build Coastguard Worker# pylint: disable=too-many-locals,unused-argument,too-many-branches,too-many-statements 210*800a58d9SAndroid Build Coastguard Workerdef CreateDevices(command, cfg, device_factory, num, avd_type, 211*800a58d9SAndroid Build Coastguard Worker report_internal_ip=False, autoconnect=False, 212*800a58d9SAndroid Build Coastguard Worker serial_log_file=None, client_adb_port=None, 213*800a58d9SAndroid Build Coastguard Worker boot_timeout_secs=None, unlock_screen=False, 214*800a58d9SAndroid Build Coastguard Worker wait_for_boot=True, connect_webrtc=False, 215*800a58d9SAndroid Build Coastguard Worker ssh_private_key_path=None, 216*800a58d9SAndroid Build Coastguard Worker ssh_user=constants.GCE_USER): 217*800a58d9SAndroid Build Coastguard Worker """Create a set of devices using the given factory. 218*800a58d9SAndroid Build Coastguard Worker 219*800a58d9SAndroid Build Coastguard Worker Main jobs in create devices. 220*800a58d9SAndroid Build Coastguard Worker 1. Create GCE instance: Launch instance in GCP(Google Cloud Platform). 221*800a58d9SAndroid Build Coastguard Worker 2. Starting up AVD: Wait device boot up. 222*800a58d9SAndroid Build Coastguard Worker 223*800a58d9SAndroid Build Coastguard Worker Args: 224*800a58d9SAndroid Build Coastguard Worker command: The name of the command, used for reporting. 225*800a58d9SAndroid Build Coastguard Worker cfg: An AcloudConfig instance. 226*800a58d9SAndroid Build Coastguard Worker device_factory: A factory capable of producing a single device. 227*800a58d9SAndroid Build Coastguard Worker num: The number of devices to create. 228*800a58d9SAndroid Build Coastguard Worker avd_type: String, the AVD type(cuttlefish, goldfish...). 229*800a58d9SAndroid Build Coastguard Worker report_internal_ip: Boolean to report the internal ip instead of 230*800a58d9SAndroid Build Coastguard Worker external ip. 231*800a58d9SAndroid Build Coastguard Worker serial_log_file: String, the file path to tar the serial logs. 232*800a58d9SAndroid Build Coastguard Worker autoconnect: Boolean, whether to auto connect to device. 233*800a58d9SAndroid Build Coastguard Worker client_adb_port: Integer, Specify port for adb forwarding. 234*800a58d9SAndroid Build Coastguard Worker boot_timeout_secs: Integer, boot timeout secs. 235*800a58d9SAndroid Build Coastguard Worker unlock_screen: Boolean, whether to unlock screen after invoke vnc client. 236*800a58d9SAndroid Build Coastguard Worker wait_for_boot: Boolean, True to check serial log include boot up 237*800a58d9SAndroid Build Coastguard Worker message. 238*800a58d9SAndroid Build Coastguard Worker connect_webrtc: Boolean, whether to auto connect webrtc to device. 239*800a58d9SAndroid Build Coastguard Worker ssh_private_key_path: String, the private key for SSH tunneling. 240*800a58d9SAndroid Build Coastguard Worker ssh_user: String, the user name for SSH tunneling. 241*800a58d9SAndroid Build Coastguard Worker 242*800a58d9SAndroid Build Coastguard Worker Raises: 243*800a58d9SAndroid Build Coastguard Worker errors: Create instance fail. 244*800a58d9SAndroid Build Coastguard Worker 245*800a58d9SAndroid Build Coastguard Worker Returns: 246*800a58d9SAndroid Build Coastguard Worker A Report instance. 247*800a58d9SAndroid Build Coastguard Worker """ 248*800a58d9SAndroid Build Coastguard Worker reporter = report.Report(command=command) 249*800a58d9SAndroid Build Coastguard Worker try: 250*800a58d9SAndroid Build Coastguard Worker CreateSshKeyPairIfNecessary(cfg) 251*800a58d9SAndroid Build Coastguard Worker device_pool = DevicePool(device_factory) 252*800a58d9SAndroid Build Coastguard Worker device_pool.CreateDevices(num) 253*800a58d9SAndroid Build Coastguard Worker device_pool.SetDeviceBuildInfo() 254*800a58d9SAndroid Build Coastguard Worker if wait_for_boot: 255*800a58d9SAndroid Build Coastguard Worker failures = device_pool.WaitForBoot(boot_timeout_secs) 256*800a58d9SAndroid Build Coastguard Worker else: 257*800a58d9SAndroid Build Coastguard Worker failures = device_factory.GetFailures() 258*800a58d9SAndroid Build Coastguard Worker 259*800a58d9SAndroid Build Coastguard Worker if failures: 260*800a58d9SAndroid Build Coastguard Worker reporter.SetStatus(report.Status.BOOT_FAIL) 261*800a58d9SAndroid Build Coastguard Worker else: 262*800a58d9SAndroid Build Coastguard Worker reporter.SetStatus(report.Status.SUCCESS) 263*800a58d9SAndroid Build Coastguard Worker 264*800a58d9SAndroid Build Coastguard Worker # Collect logs 265*800a58d9SAndroid Build Coastguard Worker logs = device_factory.GetLogs() 266*800a58d9SAndroid Build Coastguard Worker if serial_log_file: 267*800a58d9SAndroid Build Coastguard Worker device_pool.CollectSerialPortLogs( 268*800a58d9SAndroid Build Coastguard Worker serial_log_file, port=constants.DEFAULT_SERIAL_PORT) 269*800a58d9SAndroid Build Coastguard Worker 270*800a58d9SAndroid Build Coastguard Worker device_pool.UpdateReport(reporter) 271*800a58d9SAndroid Build Coastguard Worker # Write result to report. 272*800a58d9SAndroid Build Coastguard Worker for device in device_pool.devices: 273*800a58d9SAndroid Build Coastguard Worker ip = (device.ip.internal if report_internal_ip 274*800a58d9SAndroid Build Coastguard Worker else device.ip.external) 275*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel 276*800a58d9SAndroid Build Coastguard Worker # TODO(b/154175542): Report multiple devices. 277*800a58d9SAndroid Build Coastguard Worker vnc_ports = device_factory.GetVncPorts() 278*800a58d9SAndroid Build Coastguard Worker adb_ports = device_factory.GetAdbPorts() 279*800a58d9SAndroid Build Coastguard Worker if not vnc_ports[0] and not adb_ports[0]: 280*800a58d9SAndroid Build Coastguard Worker vnc_ports[0], adb_ports[0] = utils.AVD_PORT_DICT[avd_type] 281*800a58d9SAndroid Build Coastguard Worker 282*800a58d9SAndroid Build Coastguard Worker device_dict = { 283*800a58d9SAndroid Build Coastguard Worker "ip": ip + (":" + str(adb_ports[0]) if adb_ports[0] else ""), 284*800a58d9SAndroid Build Coastguard Worker "instance_name": device.instance_name 285*800a58d9SAndroid Build Coastguard Worker } 286*800a58d9SAndroid Build Coastguard Worker if device.build_info: 287*800a58d9SAndroid Build Coastguard Worker device_dict.update(device.build_info) 288*800a58d9SAndroid Build Coastguard Worker if device.time_info: 289*800a58d9SAndroid Build Coastguard Worker device_dict.update(device.time_info) 290*800a58d9SAndroid Build Coastguard Worker if device.openwrt: 291*800a58d9SAndroid Build Coastguard Worker device_dict.update(device_factory.GetOpenWrtInfoDict()) 292*800a58d9SAndroid Build Coastguard Worker if device.gce_hostname: 293*800a58d9SAndroid Build Coastguard Worker device_dict[constants.GCE_HOSTNAME] = device.gce_hostname 294*800a58d9SAndroid Build Coastguard Worker logger.debug( 295*800a58d9SAndroid Build Coastguard Worker "To connect with hostname, erase the extra_args_ssh_tunnel: %s", 296*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel) 297*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel="" 298*800a58d9SAndroid Build Coastguard Worker if autoconnect and reporter.status == report.Status.SUCCESS: 299*800a58d9SAndroid Build Coastguard Worker forwarded_ports = _EstablishAdbVncConnections( 300*800a58d9SAndroid Build Coastguard Worker device.gce_hostname or ip, vnc_ports, adb_ports, 301*800a58d9SAndroid Build Coastguard Worker client_adb_port, ssh_user, 302*800a58d9SAndroid Build Coastguard Worker ssh_private_key_path=(ssh_private_key_path or 303*800a58d9SAndroid Build Coastguard Worker cfg.ssh_private_key_path), 304*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel=extra_args_ssh_tunnel, 305*800a58d9SAndroid Build Coastguard Worker unlock_screen=unlock_screen) 306*800a58d9SAndroid Build Coastguard Worker if forwarded_ports: 307*800a58d9SAndroid Build Coastguard Worker forwarded_port = forwarded_ports[0] 308*800a58d9SAndroid Build Coastguard Worker device_dict[constants.VNC_PORT] = forwarded_port.vnc_port 309*800a58d9SAndroid Build Coastguard Worker device_dict[constants.ADB_PORT] = forwarded_port.adb_port 310*800a58d9SAndroid Build Coastguard Worker device_dict[constants.DEVICE_SERIAL] = ( 311*800a58d9SAndroid Build Coastguard Worker constants.REMOTE_INSTANCE_ADB_SERIAL % 312*800a58d9SAndroid Build Coastguard Worker forwarded_port.adb_port) 313*800a58d9SAndroid Build Coastguard Worker if connect_webrtc and reporter.status == report.Status.SUCCESS: 314*800a58d9SAndroid Build Coastguard Worker webrtc_local_port = utils.PickFreePort() 315*800a58d9SAndroid Build Coastguard Worker device_dict[constants.WEBRTC_PORT] = webrtc_local_port 316*800a58d9SAndroid Build Coastguard Worker utils.EstablishWebRTCSshTunnel( 317*800a58d9SAndroid Build Coastguard Worker ip_addr=device.gce_hostname or ip, 318*800a58d9SAndroid Build Coastguard Worker webrtc_local_port=webrtc_local_port, 319*800a58d9SAndroid Build Coastguard Worker rsa_key_file=(ssh_private_key_path or 320*800a58d9SAndroid Build Coastguard Worker cfg.ssh_private_key_path), 321*800a58d9SAndroid Build Coastguard Worker ssh_user=ssh_user, 322*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel=extra_args_ssh_tunnel) 323*800a58d9SAndroid Build Coastguard Worker if device.instance_name in logs: 324*800a58d9SAndroid Build Coastguard Worker device_dict[constants.LOGS] = logs[device.instance_name] 325*800a58d9SAndroid Build Coastguard Worker if hasattr(device_factory, 'GetFetchCvdWrapperLogIfExist'): 326*800a58d9SAndroid Build Coastguard Worker fetch_cvd_wrapper_log = device_factory.GetFetchCvdWrapperLogIfExist() 327*800a58d9SAndroid Build Coastguard Worker if fetch_cvd_wrapper_log: 328*800a58d9SAndroid Build Coastguard Worker device_dict["fetch_cvd_wrapper_log"] = fetch_cvd_wrapper_log 329*800a58d9SAndroid Build Coastguard Worker if device.instance_name in failures: 330*800a58d9SAndroid Build Coastguard Worker reporter.SetErrorType(constants.ACLOUD_BOOT_UP_ERROR) 331*800a58d9SAndroid Build Coastguard Worker if device.stage: 332*800a58d9SAndroid Build Coastguard Worker reporter.SetErrorType(_DICT_ERROR_TYPE[device.stage]) 333*800a58d9SAndroid Build Coastguard Worker reporter.AddData(key="devices_failing_boot", value=device_dict) 334*800a58d9SAndroid Build Coastguard Worker reporter.AddError(str(failures[device.instance_name])) 335*800a58d9SAndroid Build Coastguard Worker else: 336*800a58d9SAndroid Build Coastguard Worker reporter.AddData(key="devices", value=device_dict) 337*800a58d9SAndroid Build Coastguard Worker except (errors.DriverError, errors.CheckGCEZonesQuotaError) as e: 338*800a58d9SAndroid Build Coastguard Worker reporter.SetErrorType(_GetErrorType(e)) 339*800a58d9SAndroid Build Coastguard Worker reporter.AddError(str(e)) 340*800a58d9SAndroid Build Coastguard Worker reporter.SetStatus(report.Status.FAIL) 341*800a58d9SAndroid Build Coastguard Worker return reporter 342*800a58d9SAndroid Build Coastguard Worker 343*800a58d9SAndroid Build Coastguard Worker 344*800a58d9SAndroid Build Coastguard Workerdef _EstablishAdbVncConnections(ip, vnc_ports, adb_ports, client_adb_port, 345*800a58d9SAndroid Build Coastguard Worker ssh_user, ssh_private_key_path, 346*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel, unlock_screen): 347*800a58d9SAndroid Build Coastguard Worker """Establish the adb and vnc connections. 348*800a58d9SAndroid Build Coastguard Worker 349*800a58d9SAndroid Build Coastguard Worker Create the ssh tunnels with adb ports and vnc ports. Then unlock the device 350*800a58d9SAndroid Build Coastguard Worker screen via the adb port. 351*800a58d9SAndroid Build Coastguard Worker 352*800a58d9SAndroid Build Coastguard Worker Args: 353*800a58d9SAndroid Build Coastguard Worker ip: String, the IPv4 address. 354*800a58d9SAndroid Build Coastguard Worker vnc_ports: List of integer, the vnc ports. 355*800a58d9SAndroid Build Coastguard Worker adb_ports: List of integer, the adb ports. 356*800a58d9SAndroid Build Coastguard Worker client_adb_port: Integer, Specify port for adb forwarding. 357*800a58d9SAndroid Build Coastguard Worker ssh_user: String, the user name for SSH tunneling. 358*800a58d9SAndroid Build Coastguard Worker ssh_private_key_path: String, the private key for SSH tunneling. 359*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel: String, extra args for ssh tunnel connection. 360*800a58d9SAndroid Build Coastguard Worker unlock_screen: Boolean, whether to unlock screen after invoking vnc client. 361*800a58d9SAndroid Build Coastguard Worker 362*800a58d9SAndroid Build Coastguard Worker Returns: 363*800a58d9SAndroid Build Coastguard Worker A list of namedtuple of (vnc_port, adb_port) 364*800a58d9SAndroid Build Coastguard Worker """ 365*800a58d9SAndroid Build Coastguard Worker forwarded_ports = [] 366*800a58d9SAndroid Build Coastguard Worker for vnc_port, adb_port in zip(vnc_ports, adb_ports): 367*800a58d9SAndroid Build Coastguard Worker forwarded_port = utils.AutoConnect( 368*800a58d9SAndroid Build Coastguard Worker ip_addr=ip, 369*800a58d9SAndroid Build Coastguard Worker rsa_key_file=ssh_private_key_path, 370*800a58d9SAndroid Build Coastguard Worker target_vnc_port=vnc_port, 371*800a58d9SAndroid Build Coastguard Worker target_adb_port=adb_port, 372*800a58d9SAndroid Build Coastguard Worker ssh_user=ssh_user, 373*800a58d9SAndroid Build Coastguard Worker client_adb_port=client_adb_port, 374*800a58d9SAndroid Build Coastguard Worker extra_args_ssh_tunnel=extra_args_ssh_tunnel) 375*800a58d9SAndroid Build Coastguard Worker forwarded_ports.append(forwarded_port) 376*800a58d9SAndroid Build Coastguard Worker if unlock_screen: 377*800a58d9SAndroid Build Coastguard Worker AdbTools(forwarded_port.adb_port).AutoUnlockScreen() 378*800a58d9SAndroid Build Coastguard Worker return forwarded_ports 379