blob: 05ac920f782945dc71afa45b3483943060e63e14 [file] [log] [blame]
#!/bin/bash
# Copyright 2015 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Builds FreeBSD image based on raw disk images provided by FreeBSD.org
# This script boots the image once, side-loads GCE Go builder configuration via
# an ISO mounted as the CD-ROM, and customizes the system before powering down.
# SSH is enabled, and a user gopher, password gopher, is created.
# Only tested on Ubuntu 20.04.
# Requires packages: qemu-system-x86 qemu-img expect genisoimage
set -e
function download_image() {
local img_dir=releases
[ ${IS_SNAPSHOT:-0} -eq 1 ] && img_dir=snapshots
local url=ftp://ftp.freebsd.org/pub/FreeBSD/${img_dir}/VM-IMAGES/${VERSION:?}/amd64/Latest
local img_filename=FreeBSD-${VERSION:?}-amd64${VERSION_TRAILER}.raw.xz
curl -O ${url}/${img_filename}
echo "${SHA256} ${img_filename}" | sha256sum -c -
xz -d FreeBSD-${VERSION:?}-amd64${VERSION_TRAILER}.raw.xz
}
case $1 in
9.3)
readonly VERSION=9.3-RELEASE
readonly VERSION_TRAILER="-20140711-r268512"
readonly SHA256=4737218995ae056207c68f3105c0fbe655c32e8b76d2160ebfb1bba56dd5196f
;;
10.3)
readonly VERSION=10.3-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=1d710ba643bf6a8ce5bff5a9d69b1657ccff83dd1f2df711d9b4e02f9aab7d06
;;
10.4)
readonly VERSION=10.4-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=8d1ff92e74a70f1ec039a465467f19abd7892331403ef1d4952d271adddab625
;;
11.0)
readonly VERSION=11.0-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=f9f7fcac1acfe210979a72e0642a70fcf9c9381cc1884e966eac8381c724158c
;;
11.1)
readonly VERSION=11.1
readonly VERSION_TRAILER=
readonly SHA256=233c6b269a29c1ce38bb4eb861251d1c74643846c1de937b8e31cc0316632bc0
;;
11.2)
readonly VERSION=11.2-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=d8638aecbb13bdc891e17187f3932fe477f5655846bdaad8fecd60614de9312c
;;
11.3)
readonly VERSION=11.3-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=e5f7fb12b828f0af7edf9464a08e51effef05ca9eb5fb52dba6d23a3c7a39223
;;
11.4)
readonly VERSION=11.4-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=53a9db4dfd9c964d487d9f928754c964e2c3610c579c7f3558c745a75fa430f0
;;
12.0)
readonly VERSION=12.0-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=9eb70a552f5395819904ed452a02e5805743459dbb1912ebafe4c9ae5de5eb53
;;
12.1)
readonly VERSION=12.1-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=3750767f042ebf47a1e8e122b67d9cd48ec3cd2a4a60b724e64c4ff6ba33653a
;;
12.2)
readonly VERSION=12.2-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=0f8593382b6833658c6f6be532d4ffbedde7b75504452e27d912a0183f72ab56
;;
12.3-SNAPSHOT)
readonly IS_SNAPSHOT=1
readonly VERSION=12.3-STABLE
readonly VERSION_TRAILER=
readonly SHA256=e52ddb31b8f2ff7f8d03571b65e472cde3f92ef6b73ddaa5e7f5d4668ce4394c # https://lists.freebsd.org/archives/freebsd-snapshots/2021-December/000037.html
;;
13.0)
readonly VERSION=13.0-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=48288a693215a88b26ec81b2648de7433acec7db491aaeaed49c0ffd1612d345
readonly BLIND_SWITCH_CONSOLE=1
;;
13.0-SNAPSHOT)
readonly IS_SNAPSHOT=1
readonly VERSION=13.0-STABLE
readonly VERSION_TRAILER=
readonly SHA256=7b8fcc2330c8d9f66dd012c5859167d56c227ece39188c8f55b2bddbf688875f # https://lists.freebsd.org/archives/freebsd-snapshots/2021-December/000036.html
readonly BLIND_SWITCH_CONSOLE=1
;;
*)
echo "Usage: $0 <version>"
echo " version - FreeBSD version to build. Valid choices: 9.3 10.3 10.4 11.0 11.1 11.2 11.3 11.4 12.0 12.1 12.2 13.0 13.0-SNAPSHOT"
exit 1
esac
function cleanup() {
rm -rf iso \
*.iso \
*.raw \
*.qcow2
}
trap cleanup EXIT
if ! [ -e FreeBSD-${VERSION:?}-amd64.raw ]; then
download_image
fi
qemu-img create -f qcow2 -b FreeBSD-${VERSION:?}-amd64${VERSION_TRAILER}.raw -F raw disk.qcow2 16G
mkdir -p iso/boot iso/etc iso/usr/local/etc/rc.d
cp loader.conf iso/boot
cp rc.conf iso/etc
cp sysctl.conf iso/etc
cp buildlet iso/usr/local/etc/rc.d
cat >iso/install.sh <<'EOF'
#!/bin/sh
set -x
mkdir -p /usr/local/etc/rc.d/
cp /mnt/usr/local/etc/rc.d/buildlet /usr/local/etc/rc.d/buildlet
chmod +x /usr/local/etc/rc.d/buildlet
cp /mnt/boot/loader.conf /boot/loader.conf
cp /mnt/etc/rc.conf /etc/rc.conf
cat /mnt/etc/sysctl.conf >> /etc/sysctl.conf
adduser -f - <<ADDUSEREOF
gopher::::::Gopher Gopherson::/bin/sh:gopher
ADDUSEREOF
pw user mod gopher -G wheel
# Enable serial console early in boot process.
echo '-h' > /boot.conf
EOF
genisoimage -r -o config.iso iso/
# TODO(wathiede): remove sleep
sleep 2
env DOWNLOAD_UPDATES=$((1-IS_SNAPSHOT)) BLIND_SWITCH_CONSOLE=${BLIND_SWITCH_CONSOLE:=0} expect <<'EOF'
set prompt "root@.*:~ #[ ]"
set timeout -1
set send_human {.1 .3 1 .05 2}
spawn qemu-system-x86_64 -machine graphics=off -display none -serial stdio \
-fw_cfg name=opt/etc/sercon-port,string=0x3F8 \
-m 1G -drive if=virtio,file=disk.qcow2,format=qcow2,cache=none -cdrom config.iso -net nic,model=virtio -net user
set qemu_pid $spawn_id
if {$::env(BLIND_SWITCH_CONSOLE)} {
# simulate a user interacting with the boot menu:
# hit "5" (Cons: menu) to switch from Video (Video -> Dual (Serial primary) -> Dual (Video primary) -> Serial),
# to toggle the serial console, then hit "return" to boot
expect -ex "Booting from Hard Disk..."
expect -ex "/"
expect -ex "\n"
send -h " " ;# stop the autoboot timer
send -h 5
sleep 1
send -h "\r"
expect -ex "---<<BOOT>>---"
} else {
# boot with serial console enabled
expect -ex "Welcome to FreeBSD"
expect -re "Autoboot in \[0-9\]\+ seconds"
sleep 1
send -h "3" ;# escape to bootloader prompt
expect -ex "Type '?' for a list of commands, 'help' for more detailed help."
expect -ex "OK "
send -h "set console=\"comconsole\"\n"
expect -ex "OK "
send -h "boot\n"
}
# wait for login prompt
set timeout 180
expect {
"\nlogin: " {
send "root\n"
sleep 1
}
timeout { exit 2 }
}
expect -re $prompt
sleep 1
send "mount_cd9660 /dev/cd0 /mnt\nsh /mnt/install.sh\n"
expect -re $prompt
sleep 1
# generate SSH keys
send "service sshd keygen\n"
expect -re "Generating .+ host key."
sleep 1
expect -re $prompt
sleep 1
set timeout -1
# download updates
if {$::env(DOWNLOAD_UPDATES)} {
send "env PAGER=cat freebsd-update fetch --not-running-from-cron\n"
expect {
"The following files will be updated as part of updating to" {
sleep 2
expect -re $prompt
send "freebsd-update install\n"
expect "Installing updates..."
expect "done."
sleep 1
send "\n"
}
"No updates needed to update system to" {
sleep 1
send "\n"
}
"No mirrors remaining, giving up." { exit 3 }
}
} else {
puts "skipping updates"
send "\n"
}
expect -re $prompt
sleep 1
send "pkg install -y bash curl git gdb\n"
expect -re $prompt
send "sync\n"
expect -re $prompt
send "poweroff\n"
expect "All buffers synced."
wait -i $qemu_pid
EOF
# Create Compute Engine disk image.
IMAGE=freebsd-amd64-${VERSION/-RELEASE/}.tar.gz
readonly IMAGE=${IMAGE/\./}
echo "Archiving disk.raw as ${IMAGE:?}... (this may take a while)"
qemu-img convert -f qcow2 -O raw -t none -T none disk.qcow2 disk.raw
tar -Szcf ${IMAGE:?} disk.raw
echo "Done. GCE image is ${IMAGE:?}"