#!/bin/sh # This script generates FreeBSD images for OpenNebula, being heavily inspired # from srht's FreeBSD build image definition. It assumes running on a FreeBSD host. # ZFS installation as documented by the FreeBSD project # https://wiki.freebsd.org/RootOnZFS/GPTZFSBoot set -e set -x # XXX: Handle command-line arguments? RELEASE=13.0-RELEASE ARCH=amd64 IMAGE_PATH=freebsd-zfs-$RELEASE-$(date -I).img.qcow2 IMAGE_SIZE=10G DIST_BASE="https://download.freebsd.org/ftp/releases/$ARCH/$RELEASE" ZPOOL=zroot ONE_CONTEXT_PKG_URL="https://github.com/OpenNebula/addon-context-linux/releases/download/v6.2.0/one-context-6.2.0_1.txz" if zpool list -Ho name $ZPOOL 2>/dev/null; then echo "The pool $ZPOOL is already imported." >&2 exit 1 fi cleanup() { sync || true umount /mnt/dev || true zpool export $ZPOOL || true mdconfig -du md0 || true } trap cleanup EXIT if [ "$(whoami)" != 'root' ]; then echo "This script must be run as root." >&2 exit 1 fi env ASSUME_ALWAYS_YES=YES pkg install -y qemu-tools # Allocate and partition/format disk image. # We use "legacy boot", aka BIOS boot # Preferably, we'd use EFI boot here, check the FreeBSD wiki link in the header # to see how to make that change, but make the EFI partition larger disk=$(mktemp) truncate -s 6G $disk mdconfig -a -t vnode -f $disk -u md0 gpart create -s gpt /dev/md0 gpart add -t freebsd-boot -l bootfs -b 40 -s 512K md0 gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 md0 gpart add -t freebsd-zfs -l zfs0 -b 1M -s 5G md0 zpool create -O compression=on -o ashift=12 -o altroot=/mnt -m none $ZPOOL md0p2 zfs create -o mountpoint=none $ZPOOL/ROOT # We set zstd-19 so our image will become smaller, at the cost of a longer build time # At the end, we remove zstd-19 again, but all files already written will remain zstd-19 compressed zfs create -o mountpoint=/ -o canmount=noauto -o compression=zstd-19 $ZPOOL/ROOT/default mount -t zfs $ZPOOL/ROOT/default /mnt zpool set bootfs=$ZPOOL/ROOT/default $ZPOOL zfs create -o mountpoint=/tmp -o exec=on -o setuid=off $ZPOOL/tmp zfs create -o canmount=off -o mountpoint=/usr $ZPOOL/usr zfs create $ZPOOL/usr/home zfs create -o exec=off -o setuid=off $ZPOOL/usr/src zfs create -o mountpoint=/usr/ports -o setuid=off $ZPOOL/usr/ports zfs create -o canmount=off -o mountpoint=/var $ZPOOL/var zfs create -o exec=off -o setuid=off $ZPOOL/var/audit zfs create -o exec=off -o setuid=off $ZPOOL/var/crash zfs create -o exec=off -o setuid=off $ZPOOL/var/log zfs create -o atime=on -o exec=off -o setuid=off $ZPOOL/var/mail zfs create -o exec=on -o setuid=off $ZPOOL/var/tmp ln -s /usr/home /mnt/home chmod 1777 /mnt/var/tmp chmod 1777 /mnt/tmp # Mount allocated image. mkdir -p /mnt/dev mount -t devfs devfs /mnt/dev # Download and extract base system. dist_files="kernel.txz base.txz" dist_dir="/usr/freebsd-dist/$ARCH/$RELEASE" mkdir -p "$dist_dir" for f in $dist_files do fetch -m -o "$dist_dir/$f" "$DIST_BASE/$f" tar -C /mnt -xJf "$dist_dir/$f" done # Configure new system. printf '# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n' >/mnt/etc/fstab touch /mnt/firstboot sysrc -f /mnt/boot/loader.conf zfs_load=YES autoboot_delay=-1 sysrc -f /mnt/etc/rc.conf ntpd_enable=YES sshd_enable=YES growfs_enable=YES hostname=freebsd cp /etc/resolv.conf /mnt/etc/resolv.conf tzsetup -s -C /mnt UTC cat >>/mnt/etc/ssh/sshd_config </mnt/usr/local/etc/pkg/repos/FreeBSD.conf # freebsd-update is only supported for RELEASE if [ "${release%-RELEASE}" != "$RELEASE" ] then env PAGER=true /usr/sbin/freebsd-update \ -b /mnt \ --currently-running "$RELEASE" \ --not-running-from-cron -F \ fetch install rm -rf /mnt/var/db/freebsd-update/* fi env ASSUME_ALWAYS_YES=YES pkg -c /mnt bootstrap -f fetch -m -o /mnt/one-context.txz "$ONE_CONTEXT_PKG_URL" # OpenNebula has dependencies, but these are not included in the package for some reason # https://github.com/OpenNebula/addon-context-linux/blob/40efc929487b2955e6f32643853a5cdc93c548da/targets.sh#L25 # It would be useful to see if there is an alternative to OpenNebula without so many dependencies, # so we can run on FreeBSD base, and avoid breaking OpenNebula when the admin removes a dependency. env ASSUME_ALWAYS_YES=YES pkg -c /mnt install sudo bash curl base64 ruby open-vm-tools-nox11 gawk virt-what one-context.txz env ASSUME_ALWAYS_YES=YES pkg -c /mnt clean --all rm /mnt/one-context.txz # Remove zstd-19 again, as it would be too slow for daily use. # But all files that were already writtne will remain zstd-19 compressed. # zstd-19 is slow to compress but fast to read. zfs inherit compression $ZPOOL/ROOT/default trap : EXIT cleanup mkdir -p "$ARCH" qemu-img convert -f raw -O qcow2 "$disk" "$IMAGE_PATH" rm "$disk" # Filesystem will be enlarged by growfs(7) on next startup qemu-img resize "$IMAGE_PATH" "$IMAGE_SIZE"