1#!/bin/bash 2 3# Copyright 2018 Google Inc. All rights reserved. 4 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8 9# http://www.apache.org/licenses/LICENSE-2.0 10 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17# Common code to build a host image on GCE 18 19# INTERNAL_IP can be set to --internal-ip run on a GCE instance 20# The instance will need --scope compute-rw 21 22source "${ANDROID_BUILD_TOP}/external/shflags/shflags" 23 24DEFINE_string build_instance \ 25 "${USER}-build" "Instance name to create for the build" "i" 26DEFINE_string build_project "$(gcloud config get-value project)" \ 27 "Project to use for scratch" 28DEFINE_string build_zone "$(gcloud config get-value compute/zone)" \ 29 "Zone to use for scratch resources" 30DEFINE_string dest_image "vsoc-host-scratch-${USER}" "Image to create" "o" 31DEFINE_string dest_family "" "Image family to add the image to" "f" 32DEFINE_string dest_project "$(gcloud config get-value project)" \ 33 "Project to use for the new image" "p" 34DEFINE_string launch_instance "" \ 35 "Name of the instance to launch with the new image" "l" 36DEFINE_string source_image_family "debian-11" \ 37 "Image familty to use as the base" "s" 38DEFINE_string source_image_project debian-cloud \ 39 "Project holding the base image" "m" 40DEFINE_string repository_url \ 41 "https://github.com/google/android-cuttlefish.git" \ 42 "URL to the repository with host changes" "u" 43DEFINE_string repository_branch main \ 44 "Branch to check out" "b" 45 46 47SSH_FLAGS=(${INTERNAL_IP}) 48 49fatal_echo() { 50 echo "$1" 51 exit 1 52} 53 54wait_for_instance() { 55 alive="" 56 while [[ -z "${alive}" ]]; do 57 sleep 5 58 alive="$(gcloud compute ssh "${SSH_FLAGS[@]}" "$@" -- uptime || true)" 59 done 60} 61 62package_source() { 63 local url="$1" 64 local branch="$2" 65 local repository_dir="${url/*\//}" 66 repository_dir="$(basename "${repository_dir}" .git)" 67 local debian_dir="${repository_dir}" 68 if [[ $# -eq 4 ]]; then 69 debian_dir="${repository_dir}/$4" 70 fi 71 git clone "${url}" -b "${branch}" 72 dpkg-source -b "${debian_dir}" 73 rm -rf "${repository_dir}" 74} 75 76main() { 77 set -o errexit 78 set -x 79 PZ=(--project=${FLAGS_build_project} --zone=${FLAGS_build_zone}) 80 if [[ -n "${FLAGS_dest_family}" ]]; then 81 dest_family_flag=("--family=${FLAGS_dest_family}") 82 else 83 dest_family_flag=() 84 fi 85 scratch_dir="$(mktemp -d)" 86 pushd "${scratch_dir}" 87 package_source "${FLAGS_repository_url}" "${FLAGS_repository_branch}" \ 88 "cuttlefish-common_${FLAGS_version}" "base" 89 package_source "${FLAGS_repository_url}" "${FLAGS_repository_branch}" \ 90 "cuttlefish-frontend_${FLAGS_version}" "frontend" 91 popd 92 source_files=( 93 "${ANDROID_BUILD_TOP}/device/google/cuttlefish/tools/create_base_image_gce.sh" 94 ${scratch_dir}/* 95 ) 96 97 delete_instances=("${FLAGS_build_instance}" "${FLAGS_dest_image}") 98 if [[ -n "${FLAGS_launch_instance}" ]]; then 99 delete_instances+=("${FLAGS_launch_instance}") 100 fi 101 gcloud compute instances delete -q \ 102 "${PZ[@]}" "${delete_instances[@]}" || \ 103 echo Not running 104 gcloud compute disks delete -q \ 105 "${PZ[@]}" "${FLAGS_dest_image}" || echo No scratch disk 106 gcloud compute images delete -q \ 107 --project="${FLAGS_build_project}" "${FLAGS_dest_image}" || echo Not respinning 108 gcloud compute disks create \ 109 "${PZ[@]}" \ 110 --image-family="${FLAGS_source_image_family}" \ 111 --image-project="${FLAGS_source_image_project}" \ 112 "${FLAGS_dest_image}" 113 local gpu_type="nvidia-tesla-p100-vws" 114 gcloud compute accelerator-types describe "${gpu_type}" "${PZ[@]}" || \ 115 fatal_echo "Please use a zone with ${gpu_type} GPUs available." 116 gcloud compute instances create \ 117 "${PZ[@]}" \ 118 --machine-type=n1-standard-16 \ 119 --image-family="${FLAGS_source_image_family}" \ 120 --image-project="${FLAGS_source_image_project}" \ 121 --boot-disk-size=200GiB \ 122 --accelerator="type=${gpu_type},count=1" \ 123 --maintenance-policy=TERMINATE \ 124 "${FLAGS_build_instance}" 125 wait_for_instance "${PZ[@]}" "${FLAGS_build_instance}" 126 # Ubuntu tends to mount the wrong disk as root, so help it by waiting until 127 # it has booted before giving it access to the clean image disk 128 gcloud compute instances attach-disk \ 129 "${PZ[@]}" \ 130 "${FLAGS_build_instance}" --disk="${FLAGS_dest_image}" 131 # beta for the --internal-ip flag that may be passed via SSH_FLAGS 132 gcloud beta compute scp "${SSH_FLAGS[@]}" "${PZ[@]}" \ 133 "${source_files[@]}" \ 134 "${FLAGS_build_instance}:" 135 gcloud compute ssh "${SSH_FLAGS[@]}" \ 136 "${PZ[@]}" "${FLAGS_build_instance}" -- \ 137 ./create_base_image_gce.sh 138 gcloud compute instances delete -q \ 139 "${PZ[@]}" "${FLAGS_build_instance}" 140 gcloud compute images create \ 141 --project="${FLAGS_build_project}" \ 142 --source-disk="${FLAGS_dest_image}" \ 143 --source-disk-zone="${FLAGS_build_zone}" \ 144 --licenses=https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx \ 145 "${dest_family_flag[@]}" \ 146 "${FLAGS_dest_image}" 147 gcloud compute disks delete -q "${PZ[@]}" \ 148 "${FLAGS_dest_image}" 149 if [[ -n "${FLAGS_launch_instance}" ]]; then 150 gcloud compute instances create "${PZ[@]}" \ 151 --image-project="${FLAGS_build_project}" \ 152 --image="${FLAGS_dest_image}" \ 153 --machine-type=n1-standard-4 \ 154 --scopes storage-ro \ 155 --accelerator="type=${gpu_type},count=1" \ 156 --maintenance-policy=TERMINATE \ 157 --boot-disk-size=200GiB \ 158 "${FLAGS_launch_instance}" 159 fi 160 cat <<EOF 161 echo Test and if this looks good, consider releasing it via: 162 163 gcloud compute images create \ 164 --project="${FLAGS_dest_project}" \ 165 --source-image="${FLAGS_dest_image}" \ 166 --source-image-project="${FLAGS_build_project}" \ 167 "${dest_family_flag[@]}" \ 168 "${FLAGS_dest_image}" 169EOF 170} 171 172FLAGS "$@" || exit 1 173if [[ "${FLAGS_help}" -eq 0 ]]; then 174 echo ${FLAGS_help} 175 exit 1 176fi 177 178main "${FLAGS_ARGV[@]}" 179