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