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