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"""A client that manages Goldfish Virtual Device on compute engine. 17*800a58d9SAndroid Build Coastguard Worker 18*800a58d9SAndroid Build Coastguard Worker** GoldfishComputeClient ** 19*800a58d9SAndroid Build Coastguard Worker 20*800a58d9SAndroid Build Coastguard WorkerGoldfishComputeClient derives from AndroidComputeClient. It manges a google 21*800a58d9SAndroid Build Coastguard Workercompute engine project that is setup for running Goldfish Virtual Devices. 22*800a58d9SAndroid Build Coastguard WorkerIt knows how to create a host instance from a Goldfish Stable Host Image, fetch 23*800a58d9SAndroid Build Coastguard WorkerAndroid build, an emulator build, and start Android within the host instance. 24*800a58d9SAndroid Build Coastguard Worker 25*800a58d9SAndroid Build Coastguard Worker** Class hierarchy ** 26*800a58d9SAndroid Build Coastguard Worker 27*800a58d9SAndroid Build Coastguard Worker base_cloud_client.BaseCloudApiClient 28*800a58d9SAndroid Build Coastguard Worker ^ 29*800a58d9SAndroid Build Coastguard Worker | 30*800a58d9SAndroid Build Coastguard Worker gcompute_client.ComputeClient 31*800a58d9SAndroid Build Coastguard Worker ^ 32*800a58d9SAndroid Build Coastguard Worker | 33*800a58d9SAndroid Build Coastguard Worker android_compute_client.AndroidComputeClient 34*800a58d9SAndroid Build Coastguard Worker ^ 35*800a58d9SAndroid Build Coastguard Worker | 36*800a58d9SAndroid Build Coastguard Worker goldfish_compute_client.GoldfishComputeClient 37*800a58d9SAndroid Build Coastguard Worker 38*800a58d9SAndroid Build Coastguard Worker 39*800a58d9SAndroid Build Coastguard WorkerTODO: This class should likely be merged with CvdComputeClient 40*800a58d9SAndroid Build Coastguard Worker""" 41*800a58d9SAndroid Build Coastguard Worker 42*800a58d9SAndroid Build Coastguard Workerimport getpass 43*800a58d9SAndroid Build Coastguard Workerimport logging 44*800a58d9SAndroid Build Coastguard Worker 45*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors 46*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants 47*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import android_compute_client 48*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import gcompute_client 49*800a58d9SAndroid Build Coastguard Worker 50*800a58d9SAndroid Build Coastguard Worker 51*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 52*800a58d9SAndroid Build Coastguard Worker 53*800a58d9SAndroid Build Coastguard Worker 54*800a58d9SAndroid Build Coastguard Workerclass GoldfishComputeClient(android_compute_client.AndroidComputeClient): 55*800a58d9SAndroid Build Coastguard Worker """Client that manages Goldfish based Android Virtual Device. 56*800a58d9SAndroid Build Coastguard Worker 57*800a58d9SAndroid Build Coastguard Worker Attributes: 58*800a58d9SAndroid Build Coastguard Worker acloud_config: An AcloudConfig object. 59*800a58d9SAndroid Build Coastguard Worker oauth2_credentials: An oauth2client.OAuth2Credentials instance. 60*800a58d9SAndroid Build Coastguard Worker """ 61*800a58d9SAndroid Build Coastguard Worker 62*800a58d9SAndroid Build Coastguard Worker # To determine if the boot failed 63*800a58d9SAndroid Build Coastguard Worker BOOT_FAILED_MSG = "VIRTUAL_DEVICE_FAILED" 64*800a58d9SAndroid Build Coastguard Worker 65*800a58d9SAndroid Build Coastguard Worker # To determine the failure reason 66*800a58d9SAndroid Build Coastguard Worker # If the emulator build is not available 67*800a58d9SAndroid Build Coastguard Worker EMULATOR_FETCH_FAILED_MSG = "EMULATOR_FETCH_FAILED" 68*800a58d9SAndroid Build Coastguard Worker # If the system image build is not available 69*800a58d9SAndroid Build Coastguard Worker ANDROID_FETCH_FAILED_MSG = "ANDROID_FETCH_FAILED" 70*800a58d9SAndroid Build Coastguard Worker # If the emulator could not boot in time 71*800a58d9SAndroid Build Coastguard Worker BOOT_TIMEOUT_MSG = "VIRTUAL_DEVICE_BOOT_FAILED" 72*800a58d9SAndroid Build Coastguard Worker 73*800a58d9SAndroid Build Coastguard Worker #pylint: disable=signature-differs 74*800a58d9SAndroid Build Coastguard Worker def _GetDiskArgs(self, disk_name, image_name, image_project, disk_size_gb): 75*800a58d9SAndroid Build Coastguard Worker """Helper to generate disk args that is used to create an instance. 76*800a58d9SAndroid Build Coastguard Worker 77*800a58d9SAndroid Build Coastguard Worker Args: 78*800a58d9SAndroid Build Coastguard Worker disk_name: String, the name of disk. 79*800a58d9SAndroid Build Coastguard Worker image_name: String, the name of the system image. 80*800a58d9SAndroid Build Coastguard Worker image_project: String, the name of the project where the image. 81*800a58d9SAndroid Build Coastguard Worker disk_size_gb: Integer, size of the blank data disk in GB. 82*800a58d9SAndroid Build Coastguard Worker 83*800a58d9SAndroid Build Coastguard Worker Returns: 84*800a58d9SAndroid Build Coastguard Worker A dictionary representing disk args. 85*800a58d9SAndroid Build Coastguard Worker """ 86*800a58d9SAndroid Build Coastguard Worker return [{ 87*800a58d9SAndroid Build Coastguard Worker "type": "PERSISTENT", 88*800a58d9SAndroid Build Coastguard Worker "boot": True, 89*800a58d9SAndroid Build Coastguard Worker "mode": "READ_WRITE", 90*800a58d9SAndroid Build Coastguard Worker "autoDelete": True, 91*800a58d9SAndroid Build Coastguard Worker "initializeParams": { 92*800a58d9SAndroid Build Coastguard Worker "diskName": 93*800a58d9SAndroid Build Coastguard Worker disk_name, 94*800a58d9SAndroid Build Coastguard Worker "sourceImage": 95*800a58d9SAndroid Build Coastguard Worker self.GetImage(image_name, image_project)["selfLink"], 96*800a58d9SAndroid Build Coastguard Worker "diskSizeGb": 97*800a58d9SAndroid Build Coastguard Worker disk_size_gb 98*800a58d9SAndroid Build Coastguard Worker }, 99*800a58d9SAndroid Build Coastguard Worker }] 100*800a58d9SAndroid Build Coastguard Worker #pylint: disable=signature-differs 101*800a58d9SAndroid Build Coastguard Worker 102*800a58d9SAndroid Build Coastguard Worker def CheckBootFailure(self, serial_out, instance): 103*800a58d9SAndroid Build Coastguard Worker """Overriding method from the parent class. 104*800a58d9SAndroid Build Coastguard Worker 105*800a58d9SAndroid Build Coastguard Worker Args: 106*800a58d9SAndroid Build Coastguard Worker serial_out: String 107*800a58d9SAndroid Build Coastguard Worker instance: String 108*800a58d9SAndroid Build Coastguard Worker 109*800a58d9SAndroid Build Coastguard Worker Raises: 110*800a58d9SAndroid Build Coastguard Worker errors.DownloadArtifactError: If it fails to download artifact. 111*800a58d9SAndroid Build Coastguard Worker errors.DeviceBootError: If it fails to boot up. 112*800a58d9SAndroid Build Coastguard Worker """ 113*800a58d9SAndroid Build Coastguard Worker if self.BOOT_FAILED_MSG in serial_out: 114*800a58d9SAndroid Build Coastguard Worker if self.EMULATOR_FETCH_FAILED_MSG in serial_out: 115*800a58d9SAndroid Build Coastguard Worker raise errors.DownloadArtifactError( 116*800a58d9SAndroid Build Coastguard Worker "Failed to download emulator build. Re-run with a newer build." 117*800a58d9SAndroid Build Coastguard Worker ) 118*800a58d9SAndroid Build Coastguard Worker if self.ANDROID_FETCH_FAILED_MSG in serial_out: 119*800a58d9SAndroid Build Coastguard Worker raise errors.DownloadArtifactError( 120*800a58d9SAndroid Build Coastguard Worker "Failed to download system image build. Re-run with a newer build." 121*800a58d9SAndroid Build Coastguard Worker ) 122*800a58d9SAndroid Build Coastguard Worker if self.BOOT_TIMEOUT_MSG in serial_out: 123*800a58d9SAndroid Build Coastguard Worker raise errors.DeviceBootError( 124*800a58d9SAndroid Build Coastguard Worker "Emulator timed out while booting.") 125*800a58d9SAndroid Build Coastguard Worker 126*800a58d9SAndroid Build Coastguard Worker @staticmethod 127*800a58d9SAndroid Build Coastguard Worker def GetKernelBuildArtifact(target): 128*800a58d9SAndroid Build Coastguard Worker """Get kernel build artifact name. 129*800a58d9SAndroid Build Coastguard Worker 130*800a58d9SAndroid Build Coastguard Worker Args: 131*800a58d9SAndroid Build Coastguard Worker target: String, kernel target name. 132*800a58d9SAndroid Build Coastguard Worker 133*800a58d9SAndroid Build Coastguard Worker Returns: 134*800a58d9SAndroid Build Coastguard Worker String of artifact name. 135*800a58d9SAndroid Build Coastguard Worker 136*800a58d9SAndroid Build Coastguard Worker Raises: 137*800a58d9SAndroid Build Coastguard Worker errors.DeviceBootError: If it fails to get artifact name. 138*800a58d9SAndroid Build Coastguard Worker """ 139*800a58d9SAndroid Build Coastguard Worker if target == "kernel": 140*800a58d9SAndroid Build Coastguard Worker return "bzImage" 141*800a58d9SAndroid Build Coastguard Worker if target == "kernel_x86_64": 142*800a58d9SAndroid Build Coastguard Worker return "bzImage" 143*800a58d9SAndroid Build Coastguard Worker if target == "kernel_aarch64": 144*800a58d9SAndroid Build Coastguard Worker return "Image.gz" 145*800a58d9SAndroid Build Coastguard Worker raise errors.DeviceBootError( 146*800a58d9SAndroid Build Coastguard Worker "Don't know the artifact name for '%s' target" % target) 147*800a58d9SAndroid Build Coastguard Worker 148*800a58d9SAndroid Build Coastguard Worker # pylint: disable=too-many-locals,arguments-differ 149*800a58d9SAndroid Build Coastguard Worker # TODO: Refactor CreateInstance to pass in an object instead of all these args. 150*800a58d9SAndroid Build Coastguard Worker def CreateInstance(self, 151*800a58d9SAndroid Build Coastguard Worker instance, 152*800a58d9SAndroid Build Coastguard Worker image_name, 153*800a58d9SAndroid Build Coastguard Worker image_project, 154*800a58d9SAndroid Build Coastguard Worker build_target, 155*800a58d9SAndroid Build Coastguard Worker branch, 156*800a58d9SAndroid Build Coastguard Worker build_id, 157*800a58d9SAndroid Build Coastguard Worker kernel_branch=None, 158*800a58d9SAndroid Build Coastguard Worker kernel_build_id=None, 159*800a58d9SAndroid Build Coastguard Worker kernel_build_target=None, 160*800a58d9SAndroid Build Coastguard Worker emulator_branch=None, 161*800a58d9SAndroid Build Coastguard Worker emulator_build_id=None, 162*800a58d9SAndroid Build Coastguard Worker emulator_build_target=None, 163*800a58d9SAndroid Build Coastguard Worker blank_data_disk_size_gb=None, 164*800a58d9SAndroid Build Coastguard Worker gpu=None, 165*800a58d9SAndroid Build Coastguard Worker avd_spec=None, 166*800a58d9SAndroid Build Coastguard Worker extra_scopes=None, 167*800a58d9SAndroid Build Coastguard Worker tags=None, 168*800a58d9SAndroid Build Coastguard Worker launch_args=None): 169*800a58d9SAndroid Build Coastguard Worker """Create a goldfish instance given a stable host image and a build id. 170*800a58d9SAndroid Build Coastguard Worker 171*800a58d9SAndroid Build Coastguard Worker Args: 172*800a58d9SAndroid Build Coastguard Worker instance: String, instance name. 173*800a58d9SAndroid Build Coastguard Worker image_name: String, the name of the system image. 174*800a58d9SAndroid Build Coastguard Worker image_project: String, name of the project where the image belongs. 175*800a58d9SAndroid Build Coastguard Worker Assume the default project if None. 176*800a58d9SAndroid Build Coastguard Worker build_target: String, target name, e.g. "sdk_phone_x86_64-sdk" 177*800a58d9SAndroid Build Coastguard Worker branch: String, branch name, e.g. "git_pi-dev" 178*800a58d9SAndroid Build Coastguard Worker build_id: String, build id, a string, e.g. "2263051", "P2804227" 179*800a58d9SAndroid Build Coastguard Worker kernel_branch: String, kernel branch name. 180*800a58d9SAndroid Build Coastguard Worker kernel_build_id: String, kernel build id. 181*800a58d9SAndroid Build Coastguard Worker kernel_build_target: kernel target, e.g. "kernel_x86_64" 182*800a58d9SAndroid Build Coastguard Worker emulator_branch: String, emulator branch name, e.g."aosp-emu-master-dev" 183*800a58d9SAndroid Build Coastguard Worker emulator_build_id: String, emulator build id, a string, e.g. "2263051", "P2804227" 184*800a58d9SAndroid Build Coastguard Worker emulator_build_target: String, emulator build target. 185*800a58d9SAndroid Build Coastguard Worker blank_data_disk_size_gb: Integer, size of the blank data disk in GB. 186*800a58d9SAndroid Build Coastguard Worker gpu: String, GPU that should be attached to the instance, or None of no 187*800a58d9SAndroid Build Coastguard Worker acceleration is needed. e.g. "nvidia-tesla-k80" 188*800a58d9SAndroid Build Coastguard Worker avd_spec: An AVDSpec instance. 189*800a58d9SAndroid Build Coastguard Worker extra_scopes: A list of extra scopes to be passed to the instance. 190*800a58d9SAndroid Build Coastguard Worker tags: A list of tags to associate with the instance. e.g. 191*800a58d9SAndroid Build Coastguard Worker ["http-server", "https-server"] 192*800a58d9SAndroid Build Coastguard Worker launch_args: String of args for launch command. 193*800a58d9SAndroid Build Coastguard Worker """ 194*800a58d9SAndroid Build Coastguard Worker self._VerifyZoneByQuota() 195*800a58d9SAndroid Build Coastguard Worker self._CheckMachineSize() 196*800a58d9SAndroid Build Coastguard Worker 197*800a58d9SAndroid Build Coastguard Worker # Add space for possible data partition. 198*800a58d9SAndroid Build Coastguard Worker boot_disk_size_gb = ( 199*800a58d9SAndroid Build Coastguard Worker int(self.GetImage(image_name, image_project)["diskSizeGb"]) + 200*800a58d9SAndroid Build Coastguard Worker blank_data_disk_size_gb) 201*800a58d9SAndroid Build Coastguard Worker disk_args = self._GetDiskArgs(instance, image_name, image_project, 202*800a58d9SAndroid Build Coastguard Worker boot_disk_size_gb) 203*800a58d9SAndroid Build Coastguard Worker 204*800a58d9SAndroid Build Coastguard Worker # Goldfish instances are metadata compatible with cuttlefish devices. 205*800a58d9SAndroid Build Coastguard Worker # See details goto/goldfish-deployment 206*800a58d9SAndroid Build Coastguard Worker metadata = self._metadata.copy() 207*800a58d9SAndroid Build Coastguard Worker metadata["user"] = getpass.getuser() 208*800a58d9SAndroid Build Coastguard Worker metadata[constants.INS_KEY_AVD_TYPE] = constants.TYPE_GF 209*800a58d9SAndroid Build Coastguard Worker 210*800a58d9SAndroid Build Coastguard Worker # Note that we use the same metadata naming conventions as cuttlefish 211*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_fetch_android_build_target"] = build_target 212*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_fetch_android_bid"] = "{branch}/{build_id}".format( 213*800a58d9SAndroid Build Coastguard Worker branch=branch, build_id=build_id) 214*800a58d9SAndroid Build Coastguard Worker if kernel_branch and kernel_build_id and kernel_build_target: 215*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_fetch_kernel_bid"] = "{branch}/{build_id}".format( 216*800a58d9SAndroid Build Coastguard Worker branch=kernel_branch, build_id=kernel_build_id) 217*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_fetch_kernel_build_target"] = kernel_build_target 218*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_fetch_kernel_build_artifact"] = ( 219*800a58d9SAndroid Build Coastguard Worker self.GetKernelBuildArtifact(kernel_build_target)) 220*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_use_custom_kernel"] = "true" 221*800a58d9SAndroid Build Coastguard Worker if emulator_branch and emulator_build_id: 222*800a58d9SAndroid Build Coastguard Worker metadata[ 223*800a58d9SAndroid Build Coastguard Worker "cvd_01_fetch_emulator_bid"] = "{branch}/{build_id}".format( 224*800a58d9SAndroid Build Coastguard Worker branch=emulator_branch, build_id=emulator_build_id) 225*800a58d9SAndroid Build Coastguard Worker if emulator_build_target: 226*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_fetch_emulator_build_target"] = emulator_build_target 227*800a58d9SAndroid Build Coastguard Worker if launch_args: 228*800a58d9SAndroid Build Coastguard Worker metadata["launch_args"] = launch_args 229*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_launch"] = "1" 230*800a58d9SAndroid Build Coastguard Worker 231*800a58d9SAndroid Build Coastguard Worker # Update metadata by avd_spec 232*800a58d9SAndroid Build Coastguard Worker # for legacy create_gf cmd, we will keep using resolution. 233*800a58d9SAndroid Build Coastguard Worker # And always use avd_spec for acloud create cmd. 234*800a58d9SAndroid Build Coastguard Worker if avd_spec: 235*800a58d9SAndroid Build Coastguard Worker metadata[constants.INS_KEY_AVD_FLAVOR] = avd_spec.flavor 236*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_x_res"] = avd_spec.hw_property[constants.HW_X_RES] 237*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_y_res"] = avd_spec.hw_property[constants.HW_Y_RES] 238*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_dpi"] = avd_spec.hw_property[constants.HW_ALIAS_DPI] 239*800a58d9SAndroid Build Coastguard Worker metadata[constants.INS_KEY_DISPLAY] = ("%sx%s (%s)" % ( 240*800a58d9SAndroid Build Coastguard Worker avd_spec.hw_property[constants.HW_X_RES], 241*800a58d9SAndroid Build Coastguard Worker avd_spec.hw_property[constants.HW_Y_RES], 242*800a58d9SAndroid Build Coastguard Worker avd_spec.hw_property[constants.HW_ALIAS_DPI])) 243*800a58d9SAndroid Build Coastguard Worker else: 244*800a58d9SAndroid Build Coastguard Worker resolution = self._resolution.split("x") 245*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_x_res"] = resolution[0] 246*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_y_res"] = resolution[1] 247*800a58d9SAndroid Build Coastguard Worker metadata["cvd_01_dpi"] = resolution[3] 248*800a58d9SAndroid Build Coastguard Worker 249*800a58d9SAndroid Build Coastguard Worker gcompute_client.ComputeClient.CreateInstance( 250*800a58d9SAndroid Build Coastguard Worker self, 251*800a58d9SAndroid Build Coastguard Worker instance=instance, 252*800a58d9SAndroid Build Coastguard Worker image_name=image_name, 253*800a58d9SAndroid Build Coastguard Worker image_project=image_project, 254*800a58d9SAndroid Build Coastguard Worker disk_args=disk_args, 255*800a58d9SAndroid Build Coastguard Worker metadata=metadata, 256*800a58d9SAndroid Build Coastguard Worker machine_type=self._machine_type, 257*800a58d9SAndroid Build Coastguard Worker network=self._network, 258*800a58d9SAndroid Build Coastguard Worker zone=self._zone, 259*800a58d9SAndroid Build Coastguard Worker gpu=gpu, 260*800a58d9SAndroid Build Coastguard Worker tags=tags, 261*800a58d9SAndroid Build Coastguard Worker extra_scopes=extra_scopes) 262