1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python 2*800a58d9SAndroid Build Coastguard Worker# 3*800a58d9SAndroid Build Coastguard Worker# Copyright 2016 - 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 17*800a58d9SAndroid Build Coastguard Worker"""A client that talks to Android Build APIs.""" 18*800a58d9SAndroid Build Coastguard Worker 19*800a58d9SAndroid Build Coastguard Workerimport collections 20*800a58d9SAndroid Build Coastguard Workerimport io 21*800a58d9SAndroid Build Coastguard Workerimport json 22*800a58d9SAndroid Build Coastguard Workerimport logging 23*800a58d9SAndroid Build Coastguard Workerimport os 24*800a58d9SAndroid Build Coastguard Workerimport ssl 25*800a58d9SAndroid Build Coastguard Workerimport stat 26*800a58d9SAndroid Build Coastguard Worker 27*800a58d9SAndroid Build Coastguard Workerimport apiclient 28*800a58d9SAndroid Build Coastguard Worker 29*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors 30*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants 31*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import base_cloud_client 32*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils 33*800a58d9SAndroid Build Coastguard Worker 34*800a58d9SAndroid Build Coastguard Worker 35*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 36*800a58d9SAndroid Build Coastguard Worker 37*800a58d9SAndroid Build Coastguard Worker# The BuildInfo namedtuple data structure. 38*800a58d9SAndroid Build Coastguard Worker# It will be the data structure returned by GetBuildInfo method. 39*800a58d9SAndroid Build Coastguard WorkerBuildInfo = collections.namedtuple("BuildInfo", [ 40*800a58d9SAndroid Build Coastguard Worker "branch", # The branch name string 41*800a58d9SAndroid Build Coastguard Worker "build_id", # The build id string 42*800a58d9SAndroid Build Coastguard Worker "build_target", # The build target string 43*800a58d9SAndroid Build Coastguard Worker "release_build_id"]) # The release build id string 44*800a58d9SAndroid Build Coastguard Worker_DEFAULT_BRANCH = "aosp-master" 45*800a58d9SAndroid Build Coastguard Worker 46*800a58d9SAndroid Build Coastguard Worker 47*800a58d9SAndroid Build Coastguard Workerclass AndroidBuildClient(base_cloud_client.BaseCloudApiClient): 48*800a58d9SAndroid Build Coastguard Worker """Client that manages Android Build.""" 49*800a58d9SAndroid Build Coastguard Worker 50*800a58d9SAndroid Build Coastguard Worker # API settings, used by BaseCloudApiClient. 51*800a58d9SAndroid Build Coastguard Worker API_NAME = "androidbuildinternal" 52*800a58d9SAndroid Build Coastguard Worker API_VERSION = "v2beta1" 53*800a58d9SAndroid Build Coastguard Worker SCOPE = "https://www.googleapis.com/auth/androidbuild.internal" 54*800a58d9SAndroid Build Coastguard Worker 55*800a58d9SAndroid Build Coastguard Worker # other variables. 56*800a58d9SAndroid Build Coastguard Worker DEFAULT_RESOURCE_ID = "0" 57*800a58d9SAndroid Build Coastguard Worker # TODO(b/27269552): We should use "latest". 58*800a58d9SAndroid Build Coastguard Worker DEFAULT_ATTEMPT_ID = "0" 59*800a58d9SAndroid Build Coastguard Worker DEFAULT_CHUNK_SIZE = 20 * 1024 * 1024 60*800a58d9SAndroid Build Coastguard Worker NO_ACCESS_ERROR_PATTERN = "does not have storage.objects.create access" 61*800a58d9SAndroid Build Coastguard Worker # LKGB variables. 62*800a58d9SAndroid Build Coastguard Worker BUILD_STATUS_COMPLETE = "complete" 63*800a58d9SAndroid Build Coastguard Worker BUILD_TYPE_SUBMITTED = "submitted" 64*800a58d9SAndroid Build Coastguard Worker ONE_RESULT = 1 65*800a58d9SAndroid Build Coastguard Worker BUILD_SUCCESSFUL = True 66*800a58d9SAndroid Build Coastguard Worker LATEST = "latest" 67*800a58d9SAndroid Build Coastguard Worker # FETCH_CVD variables. 68*800a58d9SAndroid Build Coastguard Worker FETCHER_NAME = "fetch_cvd" 69*800a58d9SAndroid Build Coastguard Worker FETCHER_BUILD_TARGET = "aosp_cf_x86_64_phone-trunk_staging-userdebug" 70*800a58d9SAndroid Build Coastguard Worker FETCHER_BUILD_TARGET_ARM = "aosp_cf_arm64_only_phone-trunk_staging-userdebug" 71*800a58d9SAndroid Build Coastguard Worker # TODO(b/297085994): cvd fetch is migrating from AOSP to github artifacts, so 72*800a58d9SAndroid Build Coastguard Worker # temporary returning hardcoded values instead of LKGB 73*800a58d9SAndroid Build Coastguard Worker FETCHER_BUILD_ID = 11559438 74*800a58d9SAndroid Build Coastguard Worker FETCHER_BUILD_ID_ARM = 11559085 75*800a58d9SAndroid Build Coastguard Worker MAX_RETRY = 3 76*800a58d9SAndroid Build Coastguard Worker RETRY_SLEEP_SECS = 3 77*800a58d9SAndroid Build Coastguard Worker 78*800a58d9SAndroid Build Coastguard Worker # Message constant 79*800a58d9SAndroid Build Coastguard Worker COPY_TO_MSG = ("build artifact (target: %s, build_id: %s, " 80*800a58d9SAndroid Build Coastguard Worker "artifact: %s, attempt_id: %s) to " 81*800a58d9SAndroid Build Coastguard Worker "google storage (bucket: %s, path: %s)") 82*800a58d9SAndroid Build Coastguard Worker # pylint: disable=invalid-name 83*800a58d9SAndroid Build Coastguard Worker def DownloadArtifact(self, 84*800a58d9SAndroid Build Coastguard Worker build_target, 85*800a58d9SAndroid Build Coastguard Worker build_id, 86*800a58d9SAndroid Build Coastguard Worker resource_id, 87*800a58d9SAndroid Build Coastguard Worker local_dest, 88*800a58d9SAndroid Build Coastguard Worker attempt_id=None): 89*800a58d9SAndroid Build Coastguard Worker """Get Android build attempt information. 90*800a58d9SAndroid Build Coastguard Worker 91*800a58d9SAndroid Build Coastguard Worker Args: 92*800a58d9SAndroid Build Coastguard Worker build_target: Target name, e.g. "aosp_cf_x86_64_phone-userdebug" 93*800a58d9SAndroid Build Coastguard Worker build_id: Build id, a string, e.g. "2263051", "P2804227" 94*800a58d9SAndroid Build Coastguard Worker resource_id: Id of the resource, e.g "avd-system.tar.gz". 95*800a58d9SAndroid Build Coastguard Worker local_dest: A local path where the artifact should be stored. 96*800a58d9SAndroid Build Coastguard Worker e.g. "/tmp/avd-system.tar.gz" 97*800a58d9SAndroid Build Coastguard Worker attempt_id: String, attempt id, will default to DEFAULT_ATTEMPT_ID. 98*800a58d9SAndroid Build Coastguard Worker """ 99*800a58d9SAndroid Build Coastguard Worker attempt_id = attempt_id or self.DEFAULT_ATTEMPT_ID 100*800a58d9SAndroid Build Coastguard Worker api = self.service.buildartifact().get_media( 101*800a58d9SAndroid Build Coastguard Worker buildId=build_id, 102*800a58d9SAndroid Build Coastguard Worker target=build_target, 103*800a58d9SAndroid Build Coastguard Worker attemptId=attempt_id, 104*800a58d9SAndroid Build Coastguard Worker resourceId=resource_id) 105*800a58d9SAndroid Build Coastguard Worker logger.info("Downloading artifact: target: %s, build_id: %s, " 106*800a58d9SAndroid Build Coastguard Worker "resource_id: %s, dest: %s", build_target, build_id, 107*800a58d9SAndroid Build Coastguard Worker resource_id, local_dest) 108*800a58d9SAndroid Build Coastguard Worker try: 109*800a58d9SAndroid Build Coastguard Worker with io.FileIO(local_dest, mode="wb") as fh: 110*800a58d9SAndroid Build Coastguard Worker downloader = apiclient.http.MediaIoBaseDownload( 111*800a58d9SAndroid Build Coastguard Worker fh, api, chunksize=self.DEFAULT_CHUNK_SIZE) 112*800a58d9SAndroid Build Coastguard Worker done = False 113*800a58d9SAndroid Build Coastguard Worker while not done: 114*800a58d9SAndroid Build Coastguard Worker _, done = downloader.next_chunk() 115*800a58d9SAndroid Build Coastguard Worker logger.info("Downloaded artifact: %s", local_dest) 116*800a58d9SAndroid Build Coastguard Worker except (OSError, apiclient.errors.HttpError) as e: 117*800a58d9SAndroid Build Coastguard Worker logger.error("Downloading artifact failed: %s", str(e)) 118*800a58d9SAndroid Build Coastguard Worker raise errors.DriverError(str(e)) 119*800a58d9SAndroid Build Coastguard Worker 120*800a58d9SAndroid Build Coastguard Worker def DownloadFetchcvd( 121*800a58d9SAndroid Build Coastguard Worker self, 122*800a58d9SAndroid Build Coastguard Worker local_dest, 123*800a58d9SAndroid Build Coastguard Worker fetch_cvd_version, 124*800a58d9SAndroid Build Coastguard Worker is_arm_version=False): 125*800a58d9SAndroid Build Coastguard Worker """Get fetch_cvd from Android Build. 126*800a58d9SAndroid Build Coastguard Worker 127*800a58d9SAndroid Build Coastguard Worker Args: 128*800a58d9SAndroid Build Coastguard Worker local_dest: A local path where the artifact should be stored. 129*800a58d9SAndroid Build Coastguard Worker e.g. "/tmp/fetch_cvd" 130*800a58d9SAndroid Build Coastguard Worker fetch_cvd_version: String of fetch_cvd version. 131*800a58d9SAndroid Build Coastguard Worker is_arm_version: is ARM version fetch_cvd. 132*800a58d9SAndroid Build Coastguard Worker """ 133*800a58d9SAndroid Build Coastguard Worker if fetch_cvd_version == constants.LKGB: 134*800a58d9SAndroid Build Coastguard Worker fetch_cvd_version = self.GetFetcherVersion(is_arm_version) 135*800a58d9SAndroid Build Coastguard Worker fetch_cvd_build_target = ( 136*800a58d9SAndroid Build Coastguard Worker self.FETCHER_BUILD_TARGET_ARM if is_arm_version 137*800a58d9SAndroid Build Coastguard Worker else self.FETCHER_BUILD_TARGET) 138*800a58d9SAndroid Build Coastguard Worker try: 139*800a58d9SAndroid Build Coastguard Worker utils.RetryExceptionType( 140*800a58d9SAndroid Build Coastguard Worker exception_types=(ssl.SSLError, errors.DriverError), 141*800a58d9SAndroid Build Coastguard Worker max_retries=self.MAX_RETRY, 142*800a58d9SAndroid Build Coastguard Worker functor=self.DownloadArtifact, 143*800a58d9SAndroid Build Coastguard Worker sleep_multiplier=self.RETRY_SLEEP_SECS, 144*800a58d9SAndroid Build Coastguard Worker retry_backoff_factor=utils.DEFAULT_RETRY_BACKOFF_FACTOR, 145*800a58d9SAndroid Build Coastguard Worker build_target=fetch_cvd_build_target, 146*800a58d9SAndroid Build Coastguard Worker build_id=fetch_cvd_version, 147*800a58d9SAndroid Build Coastguard Worker resource_id=self.FETCHER_NAME, 148*800a58d9SAndroid Build Coastguard Worker local_dest=local_dest, 149*800a58d9SAndroid Build Coastguard Worker attempt_id=self.LATEST) 150*800a58d9SAndroid Build Coastguard Worker except Exception: 151*800a58d9SAndroid Build Coastguard Worker logger.debug("Download fetch_cvd with build id: %s", 152*800a58d9SAndroid Build Coastguard Worker constants.FETCH_CVD_SECOND_VERSION) 153*800a58d9SAndroid Build Coastguard Worker utils.RetryExceptionType( 154*800a58d9SAndroid Build Coastguard Worker exception_types=(ssl.SSLError, errors.DriverError), 155*800a58d9SAndroid Build Coastguard Worker max_retries=self.MAX_RETRY, 156*800a58d9SAndroid Build Coastguard Worker functor=self.DownloadArtifact, 157*800a58d9SAndroid Build Coastguard Worker sleep_multiplier=self.RETRY_SLEEP_SECS, 158*800a58d9SAndroid Build Coastguard Worker retry_backoff_factor=utils.DEFAULT_RETRY_BACKOFF_FACTOR, 159*800a58d9SAndroid Build Coastguard Worker build_target=fetch_cvd_build_target, 160*800a58d9SAndroid Build Coastguard Worker build_id=constants.FETCH_CVD_SECOND_VERSION, 161*800a58d9SAndroid Build Coastguard Worker resource_id=self.FETCHER_NAME, 162*800a58d9SAndroid Build Coastguard Worker local_dest=local_dest, 163*800a58d9SAndroid Build Coastguard Worker attempt_id=self.LATEST) 164*800a58d9SAndroid Build Coastguard Worker fetch_cvd_stat = os.stat(local_dest) 165*800a58d9SAndroid Build Coastguard Worker os.chmod(local_dest, fetch_cvd_stat.st_mode | stat.S_IEXEC) 166*800a58d9SAndroid Build Coastguard Worker 167*800a58d9SAndroid Build Coastguard Worker @staticmethod 168*800a58d9SAndroid Build Coastguard Worker def ProcessBuild(build_info, ignore_artifact=False): 169*800a58d9SAndroid Build Coastguard Worker """Create a Cuttlefish fetch_cvd build string. 170*800a58d9SAndroid Build Coastguard Worker 171*800a58d9SAndroid Build Coastguard Worker Args: 172*800a58d9SAndroid Build Coastguard Worker build_info: The dictionary that contains build information. 173*800a58d9SAndroid Build Coastguard Worker ignore_artifact: Avoid adding artifact part to fetch_cvd build string 174*800a58d9SAndroid Build Coastguard Worker 175*800a58d9SAndroid Build Coastguard Worker Returns: 176*800a58d9SAndroid Build Coastguard Worker A string, used in the fetch_cvd cmd or None if all args are None. 177*800a58d9SAndroid Build Coastguard Worker """ 178*800a58d9SAndroid Build Coastguard Worker build_id = build_info.get(constants.BUILD_ID) 179*800a58d9SAndroid Build Coastguard Worker build_target = build_info.get(constants.BUILD_TARGET) 180*800a58d9SAndroid Build Coastguard Worker branch = build_info.get(constants.BUILD_BRANCH) 181*800a58d9SAndroid Build Coastguard Worker artifact = build_info.get(constants.BUILD_ARTIFACT) 182*800a58d9SAndroid Build Coastguard Worker 183*800a58d9SAndroid Build Coastguard Worker result = build_id or branch 184*800a58d9SAndroid Build Coastguard Worker if build_target is not None: 185*800a58d9SAndroid Build Coastguard Worker result = result or _DEFAULT_BRANCH 186*800a58d9SAndroid Build Coastguard Worker result += "/" + build_target 187*800a58d9SAndroid Build Coastguard Worker 188*800a58d9SAndroid Build Coastguard Worker if not ignore_artifact and artifact: 189*800a58d9SAndroid Build Coastguard Worker result += "{" + artifact + "}" 190*800a58d9SAndroid Build Coastguard Worker 191*800a58d9SAndroid Build Coastguard Worker return result 192*800a58d9SAndroid Build Coastguard Worker 193*800a58d9SAndroid Build Coastguard Worker def GetFetchBuildArgs(self, default_build_info, system_build_info, 194*800a58d9SAndroid Build Coastguard Worker kernel_build_info, boot_build_info, 195*800a58d9SAndroid Build Coastguard Worker bootloader_build_info, android_efi_loader_build_info, 196*800a58d9SAndroid Build Coastguard Worker ota_build_info, host_package_build_info): 197*800a58d9SAndroid Build Coastguard Worker """Get args from build information for fetch_cvd. 198*800a58d9SAndroid Build Coastguard Worker 199*800a58d9SAndroid Build Coastguard Worker Each build_info is a dictionary that contains 3 items, for example, 200*800a58d9SAndroid Build Coastguard Worker { 201*800a58d9SAndroid Build Coastguard Worker constants.BUILD_ID: "2263051", 202*800a58d9SAndroid Build Coastguard Worker constants.BUILD_TARGET: "aosp_cf_x86_64_phone-userdebug", 203*800a58d9SAndroid Build Coastguard Worker constants.BUILD_BRANCH: "aosp-master", 204*800a58d9SAndroid Build Coastguard Worker } 205*800a58d9SAndroid Build Coastguard Worker 206*800a58d9SAndroid Build Coastguard Worker Args: 207*800a58d9SAndroid Build Coastguard Worker default_build_info: The build that provides full cuttlefish images. 208*800a58d9SAndroid Build Coastguard Worker system_build_info: The build that provides the system image. 209*800a58d9SAndroid Build Coastguard Worker kernel_build_info: The build that provides the kernel. 210*800a58d9SAndroid Build Coastguard Worker boot_build_info: The build that provides the boot image. This 211*800a58d9SAndroid Build Coastguard Worker dictionary may contain an additional key 212*800a58d9SAndroid Build Coastguard Worker constants.BUILD_ARTIFACT which is mapped to the 213*800a58d9SAndroid Build Coastguard Worker boot image name. 214*800a58d9SAndroid Build Coastguard Worker bootloader_build_info: The build that provides the bootloader. 215*800a58d9SAndroid Build Coastguard Worker android_efi_loader_build_info: The build that provides the Android EFI loader. 216*800a58d9SAndroid Build Coastguard Worker ota_build_info: The build that provides the OTA tools. 217*800a58d9SAndroid Build Coastguard Worker host_package_build_info: The build that provides the host package. 218*800a58d9SAndroid Build Coastguard Worker 219*800a58d9SAndroid Build Coastguard Worker Returns: 220*800a58d9SAndroid Build Coastguard Worker List of string args for fetch_cvd. 221*800a58d9SAndroid Build Coastguard Worker """ 222*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args = [] 223*800a58d9SAndroid Build Coastguard Worker 224*800a58d9SAndroid Build Coastguard Worker default_build = self.ProcessBuild(default_build_info) 225*800a58d9SAndroid Build Coastguard Worker if default_build: 226*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-default_build={default_build}") 227*800a58d9SAndroid Build Coastguard Worker system_build = self.ProcessBuild(system_build_info) 228*800a58d9SAndroid Build Coastguard Worker if system_build: 229*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-system_build={system_build}") 230*800a58d9SAndroid Build Coastguard Worker bootloader_build = self.ProcessBuild(bootloader_build_info) 231*800a58d9SAndroid Build Coastguard Worker if bootloader_build: 232*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-bootloader_build={bootloader_build}") 233*800a58d9SAndroid Build Coastguard Worker android_efi_loader_build = self.ProcessBuild(android_efi_loader_build_info) 234*800a58d9SAndroid Build Coastguard Worker if android_efi_loader_build: 235*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-android_efi_loader_build {android_efi_loader_build}") 236*800a58d9SAndroid Build Coastguard Worker kernel_build = self.GetKernelBuild(kernel_build_info) 237*800a58d9SAndroid Build Coastguard Worker if kernel_build: 238*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-kernel_build={kernel_build}") 239*800a58d9SAndroid Build Coastguard Worker boot_build = self.ProcessBuild(boot_build_info, ignore_artifact=True) 240*800a58d9SAndroid Build Coastguard Worker if boot_build: 241*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-boot_build={boot_build}") 242*800a58d9SAndroid Build Coastguard Worker boot_artifact = boot_build_info.get(constants.BUILD_ARTIFACT) 243*800a58d9SAndroid Build Coastguard Worker if boot_artifact: 244*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-boot_artifact={boot_artifact}") 245*800a58d9SAndroid Build Coastguard Worker ota_build = self.ProcessBuild(ota_build_info) 246*800a58d9SAndroid Build Coastguard Worker if ota_build: 247*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-otatools_build={ota_build}") 248*800a58d9SAndroid Build Coastguard Worker host_package_build = self.ProcessBuild(host_package_build_info) 249*800a58d9SAndroid Build Coastguard Worker if host_package_build: 250*800a58d9SAndroid Build Coastguard Worker fetch_cvd_args.append(f"-host_package_build={host_package_build}") 251*800a58d9SAndroid Build Coastguard Worker 252*800a58d9SAndroid Build Coastguard Worker return fetch_cvd_args 253*800a58d9SAndroid Build Coastguard Worker 254*800a58d9SAndroid Build Coastguard Worker def GetFetcherVersion(self, is_arm_version=False): 255*800a58d9SAndroid Build Coastguard Worker """Get fetch_cvd build id from LKGB. 256*800a58d9SAndroid Build Coastguard Worker 257*800a58d9SAndroid Build Coastguard Worker Returns: 258*800a58d9SAndroid Build Coastguard Worker The build id of fetch_cvd. 259*800a58d9SAndroid Build Coastguard Worker """ 260*800a58d9SAndroid Build Coastguard Worker # TODO(b/297085994): currently returning hardcoded values 261*800a58d9SAndroid Build Coastguard Worker # For more information, please check the BUILD_ID constant definition 262*800a58d9SAndroid Build Coastguard Worker # comment section 263*800a58d9SAndroid Build Coastguard Worker return self.FETCHER_BUILD_ID_ARM if is_arm_version else self.FETCHER_BUILD_ID 264*800a58d9SAndroid Build Coastguard Worker 265*800a58d9SAndroid Build Coastguard Worker @staticmethod 266*800a58d9SAndroid Build Coastguard Worker # pylint: disable=broad-except 267*800a58d9SAndroid Build Coastguard Worker def GetFetchCertArg(certification_file): 268*800a58d9SAndroid Build Coastguard Worker """Get cert arg from certification file for fetch_cvd. 269*800a58d9SAndroid Build Coastguard Worker 270*800a58d9SAndroid Build Coastguard Worker Parse the certification file to get access token of the latest 271*800a58d9SAndroid Build Coastguard Worker credential data and pass it to fetch_cvd command. 272*800a58d9SAndroid Build Coastguard Worker Example of certification file: 273*800a58d9SAndroid Build Coastguard Worker { 274*800a58d9SAndroid Build Coastguard Worker "data": [ 275*800a58d9SAndroid Build Coastguard Worker { 276*800a58d9SAndroid Build Coastguard Worker "credential": { 277*800a58d9SAndroid Build Coastguard Worker "_class": "OAuth2Credentials", 278*800a58d9SAndroid Build Coastguard Worker "_module": "oauth2client.client", 279*800a58d9SAndroid Build Coastguard Worker "access_token": "token_strings", 280*800a58d9SAndroid Build Coastguard Worker "client_id": "179485041932", 281*800a58d9SAndroid Build Coastguard Worker } 282*800a58d9SAndroid Build Coastguard Worker }] 283*800a58d9SAndroid Build Coastguard Worker } 284*800a58d9SAndroid Build Coastguard Worker 285*800a58d9SAndroid Build Coastguard Worker 286*800a58d9SAndroid Build Coastguard Worker Args: 287*800a58d9SAndroid Build Coastguard Worker certification_file: String of certification file path. 288*800a58d9SAndroid Build Coastguard Worker 289*800a58d9SAndroid Build Coastguard Worker Returns: 290*800a58d9SAndroid Build Coastguard Worker String of certificate arg for fetch_cvd. If there is no 291*800a58d9SAndroid Build Coastguard Worker certification file, return empty string for aosp branch. 292*800a58d9SAndroid Build Coastguard Worker """ 293*800a58d9SAndroid Build Coastguard Worker cert_arg = "" 294*800a58d9SAndroid Build Coastguard Worker try: 295*800a58d9SAndroid Build Coastguard Worker with open(certification_file) as cert_file: 296*800a58d9SAndroid Build Coastguard Worker auth_token = json.load(cert_file).get("data")[-1].get( 297*800a58d9SAndroid Build Coastguard Worker "credential").get("access_token") 298*800a58d9SAndroid Build Coastguard Worker if auth_token: 299*800a58d9SAndroid Build Coastguard Worker cert_arg = f"-credential_source={auth_token}" 300*800a58d9SAndroid Build Coastguard Worker except Exception as e: 301*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString( 302*800a58d9SAndroid Build Coastguard Worker f"Fail to open the certification file " 303*800a58d9SAndroid Build Coastguard Worker f"({certification_file}): {e}", 304*800a58d9SAndroid Build Coastguard Worker utils.TextColors.WARNING) 305*800a58d9SAndroid Build Coastguard Worker return cert_arg 306*800a58d9SAndroid Build Coastguard Worker 307*800a58d9SAndroid Build Coastguard Worker def GetKernelBuild(self, kernel_build_info): 308*800a58d9SAndroid Build Coastguard Worker """Get kernel build args for fetch_cvd. 309*800a58d9SAndroid Build Coastguard Worker 310*800a58d9SAndroid Build Coastguard Worker Args: 311*800a58d9SAndroid Build Coastguard Worker kernel_build_info: The dictionary that contains build information. 312*800a58d9SAndroid Build Coastguard Worker 313*800a58d9SAndroid Build Coastguard Worker Returns: 314*800a58d9SAndroid Build Coastguard Worker String of kernel build args for fetch_cvd. 315*800a58d9SAndroid Build Coastguard Worker If no kernel build then return None. 316*800a58d9SAndroid Build Coastguard Worker """ 317*800a58d9SAndroid Build Coastguard Worker # kernel_target have default value "kernel". If user provide kernel_build_id 318*800a58d9SAndroid Build Coastguard Worker # or kernel_branch, then start to process kernel image. 319*800a58d9SAndroid Build Coastguard Worker if (kernel_build_info.get(constants.BUILD_ID) or 320*800a58d9SAndroid Build Coastguard Worker kernel_build_info.get(constants.BUILD_BRANCH)): 321*800a58d9SAndroid Build Coastguard Worker return self.ProcessBuild(kernel_build_info) 322*800a58d9SAndroid Build Coastguard Worker return None 323*800a58d9SAndroid Build Coastguard Worker 324*800a58d9SAndroid Build Coastguard Worker def CopyTo(self, 325*800a58d9SAndroid Build Coastguard Worker build_target, 326*800a58d9SAndroid Build Coastguard Worker build_id, 327*800a58d9SAndroid Build Coastguard Worker artifact_name, 328*800a58d9SAndroid Build Coastguard Worker destination_bucket, 329*800a58d9SAndroid Build Coastguard Worker destination_path, 330*800a58d9SAndroid Build Coastguard Worker attempt_id=None): 331*800a58d9SAndroid Build Coastguard Worker """Copy an Android Build artifact to a storage bucket. 332*800a58d9SAndroid Build Coastguard Worker 333*800a58d9SAndroid Build Coastguard Worker Args: 334*800a58d9SAndroid Build Coastguard Worker build_target: Target name, e.g. "aosp_cf_x86_64_phone-userdebug" 335*800a58d9SAndroid Build Coastguard Worker build_id: Build id, a string, e.g. "2263051", "P2804227" 336*800a58d9SAndroid Build Coastguard Worker artifact_name: Name of the artifact, e.g "avd-system.tar.gz". 337*800a58d9SAndroid Build Coastguard Worker destination_bucket: String, a google storage bucket name. 338*800a58d9SAndroid Build Coastguard Worker destination_path: String, "path/inside/bucket" 339*800a58d9SAndroid Build Coastguard Worker attempt_id: String, attempt id, will default to DEFAULT_ATTEMPT_ID. 340*800a58d9SAndroid Build Coastguard Worker """ 341*800a58d9SAndroid Build Coastguard Worker attempt_id = attempt_id or self.DEFAULT_ATTEMPT_ID 342*800a58d9SAndroid Build Coastguard Worker copy_msg = "Copying %s" % self.COPY_TO_MSG 343*800a58d9SAndroid Build Coastguard Worker logger.info(copy_msg, build_target, build_id, artifact_name, 344*800a58d9SAndroid Build Coastguard Worker attempt_id, destination_bucket, destination_path) 345*800a58d9SAndroid Build Coastguard Worker api = self.service.buildartifact().copyTo( 346*800a58d9SAndroid Build Coastguard Worker buildId=build_id, 347*800a58d9SAndroid Build Coastguard Worker target=build_target, 348*800a58d9SAndroid Build Coastguard Worker attemptId=attempt_id, 349*800a58d9SAndroid Build Coastguard Worker artifactName=artifact_name, 350*800a58d9SAndroid Build Coastguard Worker destinationBucket=destination_bucket, 351*800a58d9SAndroid Build Coastguard Worker destinationPath=destination_path) 352*800a58d9SAndroid Build Coastguard Worker try: 353*800a58d9SAndroid Build Coastguard Worker self.Execute(api) 354*800a58d9SAndroid Build Coastguard Worker finish_msg = "Finished copying %s" % self.COPY_TO_MSG 355*800a58d9SAndroid Build Coastguard Worker logger.info(finish_msg, build_target, build_id, artifact_name, 356*800a58d9SAndroid Build Coastguard Worker attempt_id, destination_bucket, destination_path) 357*800a58d9SAndroid Build Coastguard Worker except errors.HttpError as e: 358*800a58d9SAndroid Build Coastguard Worker if e.code == 503: 359*800a58d9SAndroid Build Coastguard Worker if self.NO_ACCESS_ERROR_PATTERN in str(e): 360*800a58d9SAndroid Build Coastguard Worker error_msg = "Please grant android build team's service account " 361*800a58d9SAndroid Build Coastguard Worker error_msg += "write access to bucket %s. Original error: %s" 362*800a58d9SAndroid Build Coastguard Worker error_msg %= (destination_bucket, str(e)) 363*800a58d9SAndroid Build Coastguard Worker raise errors.HttpError(e.code, message=error_msg) 364*800a58d9SAndroid Build Coastguard Worker raise 365*800a58d9SAndroid Build Coastguard Worker 366*800a58d9SAndroid Build Coastguard Worker def GetBranch(self, build_target, build_id): 367*800a58d9SAndroid Build Coastguard Worker """Derives branch name. 368*800a58d9SAndroid Build Coastguard Worker 369*800a58d9SAndroid Build Coastguard Worker Args: 370*800a58d9SAndroid Build Coastguard Worker build_target: Target name, e.g. "aosp_cf_x86_64_phone-userdebug" 371*800a58d9SAndroid Build Coastguard Worker build_id: Build ID, a string, e.g. "2263051", "P2804227" 372*800a58d9SAndroid Build Coastguard Worker 373*800a58d9SAndroid Build Coastguard Worker Returns: 374*800a58d9SAndroid Build Coastguard Worker A string, the name of the branch 375*800a58d9SAndroid Build Coastguard Worker """ 376*800a58d9SAndroid Build Coastguard Worker api = self.service.build().get(buildId=build_id, target=build_target) 377*800a58d9SAndroid Build Coastguard Worker build = self.Execute(api) 378*800a58d9SAndroid Build Coastguard Worker return build.get("branch", "") 379*800a58d9SAndroid Build Coastguard Worker 380*800a58d9SAndroid Build Coastguard Worker def GetLKGB(self, build_target, build_branch): 381*800a58d9SAndroid Build Coastguard Worker """Get latest successful build id. 382*800a58d9SAndroid Build Coastguard Worker 383*800a58d9SAndroid Build Coastguard Worker From branch and target, we can use api to query latest successful build id. 384*800a58d9SAndroid Build Coastguard Worker e.g. {u'nextPageToken':..., u'builds': [{u'completionTimestamp':u'1534157869286', 385*800a58d9SAndroid Build Coastguard Worker ... u'buildId': u'4949805', u'machineName'...}]} 386*800a58d9SAndroid Build Coastguard Worker 387*800a58d9SAndroid Build Coastguard Worker Args: 388*800a58d9SAndroid Build Coastguard Worker build_target: String, target name, e.g. "aosp_cf_x86_64_phone-userdebug" 389*800a58d9SAndroid Build Coastguard Worker build_branch: String, git branch name, e.g. "aosp-master" 390*800a58d9SAndroid Build Coastguard Worker 391*800a58d9SAndroid Build Coastguard Worker Returns: 392*800a58d9SAndroid Build Coastguard Worker A string, string of build id number. 393*800a58d9SAndroid Build Coastguard Worker 394*800a58d9SAndroid Build Coastguard Worker Raises: 395*800a58d9SAndroid Build Coastguard Worker errors.CreateError: Can't get build id. 396*800a58d9SAndroid Build Coastguard Worker """ 397*800a58d9SAndroid Build Coastguard Worker api = self.service.build().list( 398*800a58d9SAndroid Build Coastguard Worker branch=build_branch, 399*800a58d9SAndroid Build Coastguard Worker target=build_target, 400*800a58d9SAndroid Build Coastguard Worker buildAttemptStatus=self.BUILD_STATUS_COMPLETE, 401*800a58d9SAndroid Build Coastguard Worker buildType=self.BUILD_TYPE_SUBMITTED, 402*800a58d9SAndroid Build Coastguard Worker maxResults=self.ONE_RESULT, 403*800a58d9SAndroid Build Coastguard Worker successful=self.BUILD_SUCCESSFUL) 404*800a58d9SAndroid Build Coastguard Worker build = self.Execute(api) 405*800a58d9SAndroid Build Coastguard Worker logger.info("GetLKGB build API response: %s", build) 406*800a58d9SAndroid Build Coastguard Worker if build: 407*800a58d9SAndroid Build Coastguard Worker return str(build.get("builds")[0].get("buildId")) 408*800a58d9SAndroid Build Coastguard Worker raise errors.GetBuildIDError( 409*800a58d9SAndroid Build Coastguard Worker "No available good builds for branch: %s target: %s" 410*800a58d9SAndroid Build Coastguard Worker % (build_branch, build_target) 411*800a58d9SAndroid Build Coastguard Worker ) 412*800a58d9SAndroid Build Coastguard Worker 413*800a58d9SAndroid Build Coastguard Worker def GetBuildInfo(self, build_target, build_id, branch): 414*800a58d9SAndroid Build Coastguard Worker """Get build info namedtuple. 415*800a58d9SAndroid Build Coastguard Worker 416*800a58d9SAndroid Build Coastguard Worker Args: 417*800a58d9SAndroid Build Coastguard Worker build_target: Target name. 418*800a58d9SAndroid Build Coastguard Worker build_id: Build id, a string or None, e.g. "2263051", "P2804227" 419*800a58d9SAndroid Build Coastguard Worker If None or latest, the last green build id will be 420*800a58d9SAndroid Build Coastguard Worker returned. 421*800a58d9SAndroid Build Coastguard Worker branch: Branch name, a string or None, e.g. git_master. If None, the 422*800a58d9SAndroid Build Coastguard Worker returned branch will be searched by given build_id. 423*800a58d9SAndroid Build Coastguard Worker 424*800a58d9SAndroid Build Coastguard Worker Returns: 425*800a58d9SAndroid Build Coastguard Worker A build info namedtuple with keys build_target, build_id, branch and 426*800a58d9SAndroid Build Coastguard Worker gcs_bucket_build_id 427*800a58d9SAndroid Build Coastguard Worker """ 428*800a58d9SAndroid Build Coastguard Worker if build_id and build_id != self.LATEST: 429*800a58d9SAndroid Build Coastguard Worker # Get build from build_id and build_target 430*800a58d9SAndroid Build Coastguard Worker api = self.service.build().get(buildId=build_id, 431*800a58d9SAndroid Build Coastguard Worker target=build_target) 432*800a58d9SAndroid Build Coastguard Worker build = self.Execute(api) or {} 433*800a58d9SAndroid Build Coastguard Worker elif branch: 434*800a58d9SAndroid Build Coastguard Worker # Get last green build in the branch 435*800a58d9SAndroid Build Coastguard Worker api = self.service.build().list( 436*800a58d9SAndroid Build Coastguard Worker branch=branch, 437*800a58d9SAndroid Build Coastguard Worker target=build_target, 438*800a58d9SAndroid Build Coastguard Worker successful=True, 439*800a58d9SAndroid Build Coastguard Worker maxResults=1, 440*800a58d9SAndroid Build Coastguard Worker buildType="submitted") 441*800a58d9SAndroid Build Coastguard Worker builds = self.Execute(api).get("builds", []) 442*800a58d9SAndroid Build Coastguard Worker build = builds[0] if builds else {} 443*800a58d9SAndroid Build Coastguard Worker else: 444*800a58d9SAndroid Build Coastguard Worker build = {} 445*800a58d9SAndroid Build Coastguard Worker 446*800a58d9SAndroid Build Coastguard Worker build_id = build.get("buildId") 447*800a58d9SAndroid Build Coastguard Worker build_target = build_target if build_id else None 448*800a58d9SAndroid Build Coastguard Worker return BuildInfo(build.get("branch"), build_id, build_target, 449*800a58d9SAndroid Build Coastguard Worker build.get("releaseCandidateName")) 450