blob: 16007ffdcd9e738d5acf25e1b29bbd4c6f4bdeb0 [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 16.04.
# Requires packages: qemu qemu-img expect sgabios 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
;;
12.0)
readonly VERSION=12.0-RELEASE
readonly VERSION_TRAILER=
readonly SHA256=9eb70a552f5395819904ed452a02e5805743459dbb1912ebafe4c9ae5de5eb53
;;
*)
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 12.0"
exit 1
esac
IMAGE=freebsd-amd64-${VERSION/-RELEASE/}.tar.gz
readonly IMAGE=${IMAGE/\./}
if [ $(tput cols) -lt 80 ]; then
echo "Running qemu with curses display requires a window 80 columns or larger or expect(1) won't work correctly."
exit 1
fi
if ! [ -e FreeBSD-${VERSION:?}-amd64.raw ]; then
download_image
fi
qemu-img create -f qcow2 -b FreeBSD-${VERSION:?}-amd64${VERSION_TRAILER}.raw disk.qcow2
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)) expect <<'EOF'
set prompt "root@.*:~ #[ ]"
set timeout -1
spawn qemu-system-x86_64 -nographic -option-rom sgabios.bin -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
# boot with serial console enabled
expect -ex "Welcome to FreeBSD"
sleep 2
expect -ex "ape to loader prompt"
send "3\n"
expect -ex "Type '?' for a list of commands, 'help' for more detailed help."
send "set console=\"comconsole\"\n"
sleep 1
send "boot\n"
# wait for login prompt
set timeout 120
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... 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 bash curl git gdb\n"
expect "Do you want to fetch and install it now"
sleep 1
send "y\n"
expect "Proceed with this action"
sleep 1
send "y\n"
expect -re $prompt
sleep 1
send "poweroff\n"
expect "All buffers synced."
wait -i $qemu_pid
EOF
# Create Compute Engine disk 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:?}"