blob: d761493737c80ec1a0ad54a5efe45b043e5417e5 [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 expect mkisofs
set -e
function download_image() {
local release_url=ftp://ftp.freebsd.org/pub/FreeBSD/releases/VM-IMAGES/${VERSION:?}-RELEASE/amd64/Latest
local img_filename=FreeBSD-${VERSION:?}-RELEASE-amd64${VERSION_TRAILER}.raw.xz
curl -O ${release_url}/${img_filename}
echo "${SHA256} ${img_filename}" | sha256sum -c -
xz -d FreeBSD-${VERSION:?}-RELEASE-amd64${VERSION_TRAILER}.raw.xz
}
case $1 in
9.3)
readonly VERSION=9.3
readonly VERSION_TRAILER="-20140711-r268512"
readonly DNS_LOOKUP=dig
readonly SHA256=4737218995ae056207c68f3105c0fbe655c32e8b76d2160ebfb1bba56dd5196f
;;
10.3)
readonly VERSION=10.3
readonly VERSION_TRAILER=
# BIND replaced by unbound on FreeBSD 10, so drill(1) is the new dig(1)
readonly DNS_LOOKUP=drill
readonly SHA256=1d710ba643bf6a8ce5bff5a9d69b1657ccff83dd1f2df711d9b4e02f9aab7d06
;;
11.0)
readonly VERSION=11.0
readonly VERSION_TRAILER=
readonly DNS_LOOKUP=drill
readonly SHA256=f9f7fcac1acfe210979a72e0642a70fcf9c9381cc1884e966eac8381c724158c
;;
*)
echo "Usage: $0 <version>"
echo " version - FreeBSD version to build. Valid choices: 9.3 10.3 11.0"
exit 1
esac
readonly IMAGE=freebsd-amd64-${VERSION/\./}.tar.gz
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:?}-RELEASE-amd64.raw ]; then
download_image
fi
cp FreeBSD-${VERSION:?}-RELEASE-amd64${VERSION_TRAILER}.raw disk.raw
mkdir -p iso/etc iso/usr/local/etc/rc.d
cat >iso/etc/rc.conf <<EOF
hostname="buildlet"
ifconfig_vtnet0="SYNCDHCP mtu 1460"
sshd_enable="YES"
buildlet_enable="YES"
EOF
cat >iso/usr/local/etc/rc.d/buildlet <<EOF
#!/bin/sh
# PROVIDE: buildlet
# REQUIRE: sshd
# BEFORE: securelevel
. /etc/rc.subr
name="buildlet"
start_cmd="\${name}_start"
stop_cmd=""
buildlet_start()
{
PATH=/bin:/usr/bin:/usr/local/bin; export PATH
echo "starting buildlet script"
netstat -rn
cat /etc/resolv.conf
${DNS_LOOKUP:?} metadata.google.internal
(
set -e
export PATH="\$PATH:/usr/local/bin"
/usr/local/bin/curl -o /buildlet \$(/usr/local/bin/curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/attributes/buildlet-binary-url)
chmod +x /buildlet
exec /buildlet
echo "giving up"
sleep 10
)
poweroff
}
load_rc_config \$name
run_rc_command "\$1"
EOF
cat >iso/install.sh <<EOF
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/etc/rc.conf /etc/rc.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
echo 'console="comconsole"' >> /boot/loader.conf
EOF
mkisofs -r -o config.iso iso/
# TODO(wathiede): remove sleep
sleep 2
# TODO(wathiede): set serial output so we can track boot on GCE.
expect <<EOF
set timeout 600
spawn qemu-system-x86_64 -display curses -smp 2 -drive if=virtio,file=disk.raw,cache=none -cdrom config.iso -net nic,model=virtio -net user
# Speed-up boot by going in to single user mode.
expect "Welcome to FreeBSD"
sleep 2
send "\n"
expect "login:"
sleep 1
send "root\n"
expect "root@:~ # "
sleep 1
send "dhclient vtnet0\n"
expect "root@:~ # "
sleep 1
send "mount_cd9660 /dev/cd0 /mnt\nsh /mnt/install.sh\n"
expect "root@:~ # "
sleep 1
send "pkg install bash curl git\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 "root@:~ # "
sleep 1
send "poweroff\n"
expect "All buffers synced."
sleep 5
EOF
# Create Compute Engine disk image.
echo "Archiving disk.raw as ${IMAGE:?}... (this may take a while)"
tar -Szcf ${IMAGE:?} disk.raw
echo "Done. GCE image is ${IMAGE:?}"