blob: 9104adcd0c009b594fd219f1922984d979b86b91 [file] [log] [blame]
Jiyong Parka128bad2024-09-20 16:53:57 +09001#!/bin/bash
2
3# This is a script to build a Debian image that can run in a VM created via AVF.
4# TODOs:
Jiyong Parka128bad2024-09-20 16:53:57 +09005# - Add Android-specific packages via a new class
6# - Use a stable release from debian-cloud-images
7
8show_help() {
maciek swiech0fdd0512024-10-11 15:12:44 +00009 echo "Usage: sudo $0 [OPTION]... [FILE]"
10 echo "Builds a debian image and save it to FILE. [sudo is required]"
11 echo "Options:"
12 echo "-h Print usage and this help message and exit."
Saswat Padhibf8a9cb2024-12-04 02:32:33 +000013 echo "-a ARCH Architecture of the image [default is host arch: $(uname -m)]"
Jeongik Cha06f4ac52024-11-12 15:56:05 +090014 echo "-r Release mode build"
Saswat Padhibf8a9cb2024-12-04 02:32:33 +000015 echo "-w Save temp work directory [for debugging]"
Jiyong Parka128bad2024-09-20 16:53:57 +090016}
17
18check_sudo() {
19 if [ "$EUID" -ne 0 ]; then
Saswat Padhibf8a9cb2024-12-04 02:32:33 +000020 echo "Please run as root." ; exit 1
Jiyong Parka128bad2024-09-20 16:53:57 +090021 fi
22}
23
24parse_options() {
Saswat Padhi26c4ef32024-11-29 19:46:53 +000025 while getopts "a:hrw" option; do
Jiyong Parka128bad2024-09-20 16:53:57 +090026 case ${option} in
27 h)
Saswat Padhibf8a9cb2024-12-04 02:32:33 +000028 show_help ; exit
29 ;;
maciek swiech0fdd0512024-10-11 15:12:44 +000030 a)
maciek swiech0fdd0512024-10-11 15:12:44 +000031 arch="$OPTARG"
maciek swiech0fdd0512024-10-11 15:12:44 +000032 ;;
Jeongik Cha06f4ac52024-11-12 15:56:05 +090033 r)
34 mode=release
35 ;;
Saswat Padhi26c4ef32024-11-29 19:46:53 +000036 w)
37 save_workdir=1
38 ;;
maciek swiech0fdd0512024-10-11 15:12:44 +000039 *)
Saswat Padhibf8a9cb2024-12-04 02:32:33 +000040 echo "Invalid option: $OPTARG" ; exit 1
maciek swiech0fdd0512024-10-11 15:12:44 +000041 ;;
Jiyong Parka128bad2024-09-20 16:53:57 +090042 esac
43 done
Saswat Padhibf8a9cb2024-12-04 02:32:33 +000044 case "$arch" in
45 aarch64)
46 debian_arch="arm64"
47 ;;
48 x86_64)
49 debian_arch="amd64"
50 ;;
51 *)
52 echo "Invalid architecture: $arch" ; exit 1
53 ;;
54 esac
maciek swiech0fdd0512024-10-11 15:12:44 +000055 if [[ "${*:$OPTIND:1}" ]]; then
56 built_image="${*:$OPTIND:1}"
Jiyong Parka128bad2024-09-20 16:53:57 +090057 fi
58}
59
Jiyong Park879ee4a2024-11-29 14:00:47 +090060prepare_build_id() {
Jeongik Chae0fd9e62024-12-02 14:28:50 +090061 local filename=build_id
Jiyong Park879ee4a2024-11-29 14:00:47 +090062 if [ -z "${KOKORO_BUILD_NUMBER}" ]; then
Jeongik Chabf0373b2024-12-02 15:18:47 +090063 echo eng-$(hostname)-$(date --utc) > ${filename}
Jiyong Park879ee4a2024-11-29 14:00:47 +090064 else
Jeongik Chabf0373b2024-12-02 15:18:47 +090065 echo ${KOKORO_BUILD_NUMBER} > ${filename}
Jiyong Park879ee4a2024-11-29 14:00:47 +090066 fi
Jeongik Chae0fd9e62024-12-02 14:28:50 +090067 echo ${filename}
Jiyong Park879ee4a2024-11-29 14:00:47 +090068}
69
Jiyong Parka128bad2024-09-20 16:53:57 +090070install_prerequisites() {
Jiyong Park0e565ed2024-09-24 12:39:53 +090071 apt update
maciek swiech0fdd0512024-10-11 15:12:44 +000072 packages=(
Jeongik Cha1542d152024-12-04 13:22:09 +090073 apt-utils
Jeongik Cha7e7f19d2024-10-31 20:50:24 +090074 automake
maciek swiech0fdd0512024-10-11 15:12:44 +000075 binfmt-support
76 build-essential
77 ca-certificates
Jeongik Cha7e7f19d2024-10-31 20:50:24 +090078 cmake
maciek swiech0fdd0512024-10-11 15:12:44 +000079 curl
80 debsums
81 dosfstools
82 fai-server
83 fai-setup-storage
84 fdisk
Jeongik Cha7e7f19d2024-10-31 20:50:24 +090085 git
86 libjson-c-dev
87 libtool
88 libwebsockets-dev
maciek swiech0fdd0512024-10-11 15:12:44 +000089 make
Jeongik Chace3a3962024-10-12 03:47:23 +090090 protobuf-compiler
maciek swiech0fdd0512024-10-11 15:12:44 +000091 python3
92 python3-libcloud
93 python3-marshmallow
94 python3-pytest
95 python3-yaml
96 qemu-user-static
97 qemu-utils
98 sudo
99 udev
100 )
101 if [[ "$arch" == "aarch64" ]]; then
102 packages+=(
103 gcc-aarch64-linux-gnu
104 libc6-dev-arm64-cross
105 qemu-system-arm
106 )
107 else
108 packages+=(
Jeongik Cha904d9622024-10-21 11:16:37 +0900109 qemu-system
Jeongik Cha8e711982024-10-20 12:45:35 +0900110 )
111 fi
112
113 # TODO(b/365955006): remove these lines when uboot supports x86_64 EFI application
114 if [[ "$arch" == "x86_64" ]]; then
115 packages+=(
116 libguestfs-tools
Saswat Padhi79f52132024-11-27 03:56:40 +0000117 linux-image-generic
maciek swiech0fdd0512024-10-11 15:12:44 +0000118 )
119 fi
Jiyong Park44dd28f2024-09-20 18:47:40 +0900120 DEBIAN_FRONTEND=noninteractive \
maciek swiech0fdd0512024-10-11 15:12:44 +0000121 apt install --no-install-recommends --assume-yes "${packages[@]}"
Jeongik Chab137a5f2024-10-02 12:53:05 +0900122
maciek swiech0fdd0512024-10-11 15:12:44 +0000123 if [ ! -f $"HOME"/.cargo/bin/cargo ]; then
Seungjae Yoo198a0fb2024-10-04 16:29:12 +0900124 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
125 fi
126
maciek swiech0fdd0512024-10-11 15:12:44 +0000127 source "$HOME"/.cargo/env
128 rustup target add "${arch}"-unknown-linux-gnu
Jeongik Cha139ddfd2024-11-01 23:16:44 +0900129 cargo install cargo-license
Jiyong Parka128bad2024-09-20 16:53:57 +0900130}
131
132download_debian_cloud_image() {
133 local ver=master
134 local prj=debian-cloud-images
maciek swiech0fdd0512024-10-11 15:12:44 +0000135 local url="https://salsa.debian.org/cloud-team/${prj}/-/archive/${ver}/${prj}-${ver}.tar.gz"
136 local outdir="${debian_cloud_image}"
Jiyong Parka128bad2024-09-20 16:53:57 +0900137
maciek swiech0fdd0512024-10-11 15:12:44 +0000138 mkdir -p "${outdir}"
139 wget -O - "${url}" | tar xz -C "${outdir}" --strip-components=1
Jiyong Parka128bad2024-09-20 16:53:57 +0900140}
141
Seungjae Yoo1cfcb582024-10-17 14:06:58 +0900142build_rust_binary_and_copy() {
143 pushd "$(dirname "$0")/../../guest/$1" > /dev/null
Jeongik Cha06f4ac52024-11-12 15:56:05 +0900144 local release_flag=
145 local artifact_mode=debug
146 if [[ "$mode" == "release" ]]; then
147 release_flag="--release"
148 artifact_mode=release
149 fi
Seungjae Yoo1cfcb582024-10-17 14:06:58 +0900150 RUSTFLAGS="-C linker=${arch}-linux-gnu-gcc" cargo build \
151 --target "${arch}-unknown-linux-gnu" \
Jeongik Cha06f4ac52024-11-12 15:56:05 +0900152 --target-dir "${workdir}/$1" ${release_flag}
Seungjae Yoo1cfcb582024-10-17 14:06:58 +0900153 mkdir -p "${dst}/files/usr/local/bin/$1"
Jeongik Cha5d399fb2024-11-12 19:44:33 +0900154 cp "${workdir}/$1/${arch}-unknown-linux-gnu/${artifact_mode}/$1" "${dst}/files/usr/local/bin/$1/AVF"
Seungjae Yoo1cfcb582024-10-17 14:06:58 +0900155 chmod 777 "${dst}/files/usr/local/bin/$1/AVF"
Jeongik Cha139ddfd2024-11-01 23:16:44 +0900156
157 mkdir -p "${dst}/files/usr/share/doc/$1"
158 cargo license > "${dst}/files/usr/share/doc/$1/copyright"
Seungjae Yoo1cfcb582024-10-17 14:06:58 +0900159 popd > /dev/null
160}
161
Jeongik Cha7e7f19d2024-10-31 20:50:24 +0900162build_ttyd() {
163 local ttyd_version=1.7.7
164 local url="https://github.com/tsl0922/ttyd/archive/refs/tags/${ttyd_version}.tar.gz"
maciek swieche17e59f2024-11-25 20:13:23 +0000165 cp -r "$(dirname "$0")/ttyd" "${workdir}/ttyd"
Jeongik Cha7e7f19d2024-10-31 20:50:24 +0900166
167 pushd "${workdir}" > /dev/null
168 wget "${url}" -O - | tar xz
169 cp ttyd/* ttyd-${ttyd_version}/scripts
170 pushd "$workdir/ttyd-${ttyd_version}" > /dev/null
171 bash -c "env BUILD_TARGET=${arch} ./scripts/cross-build.sh"
172 mkdir -p "${dst}/files/usr/local/bin/ttyd"
maciek swieche17e59f2024-11-25 20:13:23 +0000173 cp "/tmp/stage/${arch}-linux-musl/bin/ttyd" "${dst}/files/usr/local/bin/ttyd/AVF"
Jeongik Cha7e7f19d2024-10-31 20:50:24 +0900174 chmod 777 "${dst}/files/usr/local/bin/ttyd/AVF"
Jeongik Cha139ddfd2024-11-01 23:16:44 +0900175 mkdir -p "${dst}/files/usr/share/doc/ttyd"
176 cp LICENSE "${dst}/files/usr/share/doc/ttyd/copyright"
Jeongik Cha7e7f19d2024-10-31 20:50:24 +0900177 popd > /dev/null
178 popd > /dev/null
179}
180
Jiyong Park44dd28f2024-09-20 18:47:40 +0900181copy_android_config() {
maciek swieche17e59f2024-11-25 20:13:23 +0000182 local src
183 local dst
184 src="$(dirname "$0")/fai_config"
185 dst="${config_space}"
Jiyong Park44dd28f2024-09-20 18:47:40 +0900186
maciek swiech0fdd0512024-10-11 15:12:44 +0000187 cp -R "${src}"/* "${dst}"
188 cp "$(dirname "$0")/image.yaml" "${resources_dir}"
Jeongik Cha50952062024-09-23 18:13:38 +0900189
Jeongik Cha1542d152024-12-04 13:22:09 +0900190 cp -R "$(dirname "$0")/localdebs/" "${debian_cloud_image}/"
Jeongik Cha7e7f19d2024-10-31 20:50:24 +0900191 build_ttyd
Seungjae Yoo1cfcb582024-10-17 14:06:58 +0900192 build_rust_binary_and_copy forwarder_guest
193 build_rust_binary_and_copy forwarder_guest_launcher
194 build_rust_binary_and_copy ip_addr_reporter
Jiyong Park44dd28f2024-09-20 18:47:40 +0900195}
196
Jiyong Parka128bad2024-09-20 16:53:57 +0900197run_fai() {
maciek swiech0fdd0512024-10-11 15:12:44 +0000198 local out="${built_image}"
199 make -C "${debian_cloud_image}" "image_bookworm_nocloud_${debian_arch}"
200 mv "${debian_cloud_image}/image_bookworm_nocloud_${debian_arch}.raw" "${out}"
Jiyong Parka128bad2024-09-20 16:53:57 +0900201}
202
Mu-Le Lee955b6582024-11-01 15:40:58 +0800203extract_partitions() {
204 root_partition_num=1
maciek swieche17e59f2024-11-25 20:13:23 +0000205 bios_partition_num=14
Mu-Le Lee955b6582024-11-01 15:40:58 +0800206 efi_partition_num=15
207
maciek swiech3919b8c2024-11-19 20:58:32 +0000208 loop=$(losetup -f --show --partscan $built_image)
maciek swieche17e59f2024-11-25 20:13:23 +0000209 dd if="${loop}p$root_partition_num" of=root_part
210 if [[ "$arch" == "x86_64" ]]; then
211 dd if="${loop}p$bios_partition_num" of=bios_part
212 fi
213 dd if="${loop}p$efi_partition_num" of=efi_part
214 losetup -d "${loop}"
Mu-Le Lee955b6582024-11-01 15:40:58 +0800215
maciek swiech3919b8c2024-11-19 20:58:32 +0000216 sed -i "s/{root_part_guid}/$(sfdisk --part-uuid $built_image $root_partition_num)/g" vm_config.json
maciek swieche17e59f2024-11-25 20:13:23 +0000217 if [[ "$arch" == "x86_64" ]]; then
218 sed -i "s/{bios_part_guid}/$(sfdisk --part-uuid $built_image $bios_partition_num)/g" vm_config.json
219 fi
maciek swiech3919b8c2024-11-19 20:58:32 +0000220 sed -i "s/{efi_part_guid}/$(sfdisk --part-uuid $built_image $efi_partition_num)/g" vm_config.json
Mu-Le Lee955b6582024-11-01 15:40:58 +0800221}
222
Jiyong Parka128bad2024-09-20 16:53:57 +0900223clean_up() {
Saswat Padhibf8a9cb2024-12-04 02:32:33 +0000224 [ "$save_workdir" -eq 1 ] || rm -rf "${workdir}"
Jiyong Parka128bad2024-09-20 16:53:57 +0900225}
226
227set -e
228trap clean_up EXIT
229
230built_image=image.raw
231workdir=$(mktemp -d)
Jiyong Park879ee4a2024-11-29 14:00:47 +0900232build_id=$(prepare_build_id)
Jiyong Parka128bad2024-09-20 16:53:57 +0900233debian_cloud_image=${workdir}/debian_cloud_image
Jiyong Park44dd28f2024-09-20 18:47:40 +0900234debian_version=bookworm
235config_space=${debian_cloud_image}/config_space/${debian_version}
Jeongik Cha37047c32024-09-20 23:09:16 +0900236resources_dir=${debian_cloud_image}/src/debian_cloud_images/resources
Saswat Padhibf8a9cb2024-12-04 02:32:33 +0000237arch="$(uname -m)"
Jeongik Cha06f4ac52024-11-12 15:56:05 +0900238mode=debug
Saswat Padhi26c4ef32024-11-29 19:46:53 +0000239save_workdir=0
Jiyong Park879ee4a2024-11-29 14:00:47 +0900240
maciek swiech0fdd0512024-10-11 15:12:44 +0000241parse_options "$@"
Jiyong Parka128bad2024-09-20 16:53:57 +0900242check_sudo
Jiyong Parka128bad2024-09-20 16:53:57 +0900243install_prerequisites
244download_debian_cloud_image
Jiyong Park44dd28f2024-09-20 18:47:40 +0900245copy_android_config
Jiyong Park0e565ed2024-09-24 12:39:53 +0900246run_fai
maciek swiech3919b8c2024-11-19 20:58:32 +0000247fdisk -l "${built_image}"
Mu-Le Lee955b6582024-11-01 15:40:58 +0800248images=()
249
maciek swieche17e59f2024-11-25 20:13:23 +0000250cp "$(dirname "$0")/vm_config.json.${arch}" vm_config.json
251
252extract_partitions
Mu-Le Lee955b6582024-11-01 15:40:58 +0800253
254if [[ "$arch" == "aarch64" ]]; then
Mu-Le Lee955b6582024-11-01 15:40:58 +0800255 images+=(
256 root_part
257 efi_part
258 )
Jeongik Cha8e711982024-10-20 12:45:35 +0900259# TODO(b/365955006): remove these lines when uboot supports x86_64 EFI application
maciek swieche17e59f2024-11-25 20:13:23 +0000260elif [[ "$arch" == "x86_64" ]]; then
Saswat Padhida6fb072024-11-27 23:07:31 +0000261 rm -f vmlinuz initrd.img
maciek swiech3919b8c2024-11-19 20:58:32 +0000262 virt-get-kernel -a "${built_image}"
Jeongik Cha8e711982024-10-20 12:45:35 +0900263 mv vmlinuz* vmlinuz
264 mv initrd.img* initrd.img
265 images+=(
Jeongik Cha53f696d2024-11-27 01:31:03 +0000266 bios_part
maciek swieche17e59f2024-11-25 20:13:23 +0000267 root_part
268 efi_part
Jeongik Cha8e711982024-10-20 12:45:35 +0900269 vmlinuz
270 initrd.img
271 )
272fi
Jeongik Cha904d9622024-10-21 11:16:37 +0900273
Jeongik Cha8e711982024-10-20 12:45:35 +0900274# --sparse option isn't supported in apache-commons-compress
Jiyong Park879ee4a2024-11-29 14:00:47 +0900275tar czv -f images.tar.gz ${build_id} "${images[@]}" vm_config.json