Changeset View
Standalone View
release/tools/vmimage.subr
Show All 33 Lines | cleanup() { | ||||
if [ -c "${DESTDIR}/dev/null" ]; then | if [ -c "${DESTDIR}/dev/null" ]; then | ||||
umount_loop ${DESTDIR}/dev 2>/dev/null | umount_loop ${DESTDIR}/dev 2>/dev/null | ||||
fi | fi | ||||
return 0 | return 0 | ||||
} | } | ||||
vm_create_base() { | vm_create_base() { | ||||
# Creates the UFS root filesystem for the virtual machine disk, | |||||
# written to the formatted disk image with mkimg(1). | |||||
mkdir -p ${DESTDIR} | mkdir -p ${DESTDIR} | ||||
return 0 | return 0 | ||||
} | } | ||||
vm_copy_base() { | vm_copy_base() { | ||||
# Defunct | # Defunct | ||||
} | } | ||||
vm_install_base() { | vm_install_base() { | ||||
imp: what happens if this fails? | |||||
Done Inline ActionsSee my comment in the review description about error handling. I think a separate pass through these scripts is needed to fix up error handling; I hit a lot of issues due to this while figuring out how to use the release scripts, even before I started making changes. I think we should start by setting -e and running through all the possible options to see if anything breaks. There is a cleanup handler that runs upon SIGINT etc. but it also gets called normally as part of mk-vmimage.sh. For that reason I can't destroy the pool there. markj: See my comment in the review description about error handling. I think a separate pass through… | |||||
# Installs the FreeBSD userland/kernel to the virtual machine disk. | # Installs the FreeBSD userland/kernel to the virtual machine disk. | ||||
Not Done Inline ActionsI am uncomfortable with the pool being named 'zroot', as that conflicts with the name of the pool on the build machines, even if the 'tmppool' name is random. gjb: I am uncomfortable with the pool being named 'zroot', as that conflicts with the name of the… | |||||
Done Inline ActionsThis scenario is exactly the purpose of -t, to handle such conflicts. All of my testing was done on a system that already has a pool called zroot. markj@nuc> zpool list NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT release.187959379 4.50G 3.93M 4.50G - - 0% 0% 1.00x ONLINE /usr/obj/usr/home/markj/src/freebsd/dev/projects/release/arm64.aarch64/release/cw-ec2 zroot 912G 327G 585G - - 27% 35% 1.00x ONLINE - markj: This scenario is exactly the purpose of `-t`, to handle such conflicts. All of my testing was… | |||||
Not Done Inline ActionsYou are correct, my apologies. I misread the usage. gjb: You are correct, my apologies. I misread the usage. | |||||
Not Done Inline ActionsWhere is this cleaned up if something goes terribly wrong? imp: Where is this cleaned up if something goes terribly wrong? | |||||
cd ${WORLDDIR} && \ | cd ${WORLDDIR} && \ | ||||
make DESTDIR=${DESTDIR} \ | make DESTDIR=${DESTDIR} \ | ||||
installworld installkernel distribution || \ | installworld installkernel distribution || \ | ||||
err "\n\nCannot install the base system to ${DESTDIR}." | err "\n\nCannot install the base system to ${DESTDIR}." | ||||
# Bootstrap etcupdate(8) and mergemaster(8) databases. | # Bootstrap etcupdate(8) and mergemaster(8) databases. | ||||
mkdir -p ${DESTDIR}/var/db/etcupdate | mkdir -p ${DESTDIR}/var/db/etcupdate | ||||
Not Done Inline Actionsexec=on is the default, did you mean exec=off? If the default value is to be used, the exec=on should be removed. delphij: exec=on is the default, did you mean exec=off? If the default value is to be used, the exec=on… | |||||
Done Inline ActionsThis was copied from bsdinstall (see usr.sbin/bsdinstall/scripts/zfsboot), which also specifies exec=on for some reason. I'll try removing it. In general I'd expect that /tmp and /var/tmp need to permit execution of files: it's not uncommon for something to write a generated script there and run it. markj: This was copied from bsdinstall (see usr.sbin/bsdinstall/scripts/zfsboot), which also specifies… | |||||
etcupdate extract -B \ | etcupdate extract -B \ | ||||
Not Done Inline ActionsIn this setup, /usr and /var are actually using /'s dataset (and these ZFS datasets were mainly for inheritance purposes). Is this intentional (maybe to make sure that the boot environment contained both /usr and /var)? BTW. Personally I'd create a container dataset with mountpoint=/ and canmount=off for both usr and var instead of setting mountpoint in two datasets. Something like: sysroot -o mountpoint=/ -o canmount=off So it gives a clear separation between the "system" datasets and user's datasets, and not setting mountpoint makes it easier to do zfs send -R | zfs receive, but these are just personal preferences. delphij: In this setup, /usr and /var are actually using /'s dataset (and these ZFS datasets were mainly… | |||||
Done Inline ActionsI believe it's intentional, yes. Per my other comments I'm a bit reluctant to deviate from the layout we use elsewhere (the fact that it's now hard-coded in three places is a problem on its own...). Perhaps we want a standalone script in the base system which creates datasets for a FreeBSD installation in a standard way? markj: I believe it's intentional, yes.
Per my other comments I'm a bit reluctant to deviate from the… | |||||
-M "TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH}" \ | -M "TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH}" \ | ||||
-s ${WORLDDIR} -d ${DESTDIR}/var/db/etcupdate | -s ${WORLDDIR} -d ${DESTDIR}/var/db/etcupdate | ||||
sh ${WORLDDIR}/release/scripts/mm-mtree.sh -m ${WORLDDIR} \ | sh ${WORLDDIR}/release/scripts/mm-mtree.sh -m ${WORLDDIR} \ | ||||
-F "TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH}" \ | -F "TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH}" \ | ||||
-D ${DESTDIR} | -D ${DESTDIR} | ||||
Not Done Inline Actions[OPTIONAL] Personally I'd set setuid=off and possibly also exec=off for the whole /var as the default feature set instead of setting it on individual file systems. delphij: [OPTIONAL] Personally I'd set setuid=off and possibly also exec=off for the whole /var as the… | |||||
Done Inline ActionsI think I agree, but I'm not sure it's a good idea to deviate from what bsdinstall and poudriere do. Perhaps we should change the defaults there too? I suspect that at least var/tmp needs exec=on, not sure about var/mail. markj: I think I agree, but I'm not sure it's a good idea to deviate from what bsdinstall and… | |||||
echo '# Custom /etc/fstab for FreeBSD VM images' \ | echo '# Custom /etc/fstab for FreeBSD VM images' \ | ||||
> ${DESTDIR}/etc/fstab | > ${DESTDIR}/etc/fstab | ||||
echo "/dev/${ROOTLABEL}/rootfs / ufs rw 1 1" \ | if [ "${VMFS}" != zfs ]; then | ||||
echo "/dev/${ROOTLABEL}/rootfs / ${VMFS} rw 1 1" \ | |||||
>> ${DESTDIR}/etc/fstab | >> ${DESTDIR}/etc/fstab | ||||
fi | |||||
if [ -z "${NOSWAP}" ]; then | if [ -z "${NOSWAP}" ]; then | ||||
echo '/dev/gpt/swapfs none swap sw 0 0' \ | echo '/dev/gpt/swapfs none swap sw 0 0' \ | ||||
>> ${DESTDIR}/etc/fstab | >> ${DESTDIR}/etc/fstab | ||||
fi | fi | ||||
local hostname | local hostname | ||||
hostname="$(echo $(uname -o) | tr '[:upper:]' '[:lower:]')" | hostname="$(echo $(uname -o) | tr '[:upper:]' '[:lower:]')" | ||||
echo "hostname=\"${hostname}\"" >> ${DESTDIR}/etc/rc.conf | echo "hostname=\"${hostname}\"" >> ${DESTDIR}/etc/rc.conf | ||||
if [ "${VMFS}" = zfs ]; then | |||||
echo "zfs_enable=\"YES\"" >> ${DESTDIR}/etc/rc.conf | |||||
echo "zpool_reguid=\"zroot\"" >> ${DESTDIR}/etc/rc.conf | |||||
fi | |||||
if ! [ -z "${QEMUSTATIC}" ]; then | if ! [ -z "${QEMUSTATIC}" ]; then | ||||
export EMULATOR=/qemu | export EMULATOR=/qemu | ||||
cp ${QEMUSTATIC} ${DESTDIR}/${EMULATOR} | cp ${QEMUSTATIC} ${DESTDIR}/${EMULATOR} | ||||
fi | fi | ||||
mkdir -p ${DESTDIR}/dev | mkdir -p ${DESTDIR}/dev | ||||
mount -t devfs devfs ${DESTDIR}/dev | mount -t devfs devfs ${DESTDIR}/dev | ||||
chroot ${DESTDIR} ${EMULATOR} /usr/bin/newaliases | chroot ${DESTDIR} ${EMULATOR} /usr/bin/newaliases | ||||
chroot ${DESTDIR} ${EMULATOR} /bin/sh /etc/rc.d/ldconfig forcestart | chroot ${DESTDIR} ${EMULATOR} /bin/sh /etc/rc.d/ldconfig forcestart | ||||
umount_loop ${DESTDIR}/dev | umount_loop ${DESTDIR}/dev | ||||
cp /etc/resolv.conf ${DESTDIR}/etc/resolv.conf | cp /etc/resolv.conf ${DESTDIR}/etc/resolv.conf | ||||
if [ "${VMFS}" = zfs ]; then | |||||
echo "kern.geom.label.disk_ident.enable=0" >> ${DESTDIR}/boot/loader.conf | |||||
Not Done Inline ActionsAside, I wonder if there's a better way to deal with this emaste: Aside, I wonder if there's a better way to deal with this | |||||
Not Done Inline ActionsThat is, dealing with ZFS vs disk_ident, not about setting variables in the release scripts etc. emaste: That is, dealing with ZFS vs disk_ident, not about setting variables in the release scripts etc. | |||||
Done Inline ActionsDo you know if the underlying problem is documented somewhere? Is it just that we want to make sure we have a consistent provider name for vdevs? markj: Do you know if the underlying problem is documented somewhere? Is it just that we want to make… | |||||
echo "zfs_load=YES" >> ${DESTDIR}/boot/loader.conf | |||||
fi | |||||
return 0 | return 0 | ||||
} | } | ||||
vm_extra_install_base() { | vm_extra_install_base() { | ||||
# Prototype. When overridden, runs extra post-installworld commands | # Prototype. When overridden, runs extra post-installworld commands | ||||
# as needed, based on the target virtual machine image or cloud | # as needed, based on the target virtual machine image or cloud | ||||
# provider image target. | # provider image target. | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | vm_extra_pkg_rmcache() { | ||||
if [ -e ${DESTDIR}/usr/local/sbin/pkg ]; then | if [ -e ${DESTDIR}/usr/local/sbin/pkg ]; then | ||||
chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ | chroot ${DESTDIR} ${EMULATOR} env ASSUME_ALWAYS_YES=yes \ | ||||
/usr/local/sbin/pkg clean -y -a | /usr/local/sbin/pkg clean -y -a | ||||
fi | fi | ||||
return 0 | return 0 | ||||
} | } | ||||
buildfs() { | |||||
local md tmppool | |||||
case "${VMFS}" in | |||||
ufs) | |||||
makefs ${MAKEFSARGS} -o label=rootfs -o version=2 -o softupdates=1 \ | |||||
${VMBASE} ${DESTDIR} | |||||
Not Done Inline ActionsWe could explicitly check for "${VMFS} = zfs here and have an error else case. (Noticed as I have some crazy thoughts about creating FAT images.) emaste: We could explicitly check for `"${VMFS} = zfs` here and have an error else case. (Noticed as I… | |||||
Done Inline ActionsYes, I'll add that. markj: Yes, I'll add that. | |||||
;; | |||||
zfs) | |||||
makefs -t zfs ${MAKEFSARGS} \ | |||||
-o poolname=zroot -o bootfs=zroot/ROOT/default -o rootpath=/ \ | |||||
-o fs=zroot\;mountpoint=none \ | |||||
-o fs=zroot/ROOT\;mountpoint=none \ | |||||
-o fs=zroot/ROOT/default\;mountpoint=/ \ | |||||
-o fs=zroot/tmp\;mountpoint=/tmp\;exec=on\;setuid=off \ | |||||
-o fs=zroot/usr\;mountpoint=/usr\;canmount=off \ | |||||
-o fs=zroot/usr/home \ | |||||
-o fs=zroot/usr/ports\;setuid=off \ | |||||
-o fs=zroot/usr/src \ | |||||
-o fs=zroot/usr/obj \ | |||||
-o fs=zroot/var\;mountpoint=/var\;canmount=off \ | |||||
-o fs=zroot/var/audit\;setuid=off\;exec=off \ | |||||
-o fs=zroot/var/log\;setuid=off\;exec=off \ | |||||
-o fs=zroot/var/mail\;atime=on \ | |||||
-o fs=zroot/var/tmp\;setuid=off \ | |||||
${VMBASE} ${DESTDIR} | |||||
;; | |||||
*) | |||||
echo "Unexpected VMFS value '${VMFS}'" | |||||
exit 1 | |||||
;; | |||||
esac | |||||
} | |||||
umount_loop() { | umount_loop() { | ||||
DIR=$1 | DIR=$1 | ||||
i=0 | i=0 | ||||
sync | sync | ||||
while ! umount ${DIR}; do | while ! umount ${DIR}; do | ||||
i=$(( $i + 1 )) | i=$(( $i + 1 )) | ||||
if [ $i -ge 10 ]; then | if [ $i -ge 10 ]; then | ||||
# This should never happen. But, it has happened. | # This should never happen. But, it has happened. | ||||
echo "Cannot umount(8) ${DIR}" | echo "Cannot umount(8) ${DIR}" | ||||
echo "Something has gone horribly wrong." | echo "Something has gone horribly wrong." | ||||
return 1 | return 1 | ||||
fi | fi | ||||
sleep 1 | sleep 1 | ||||
done | done | ||||
return 0 | return 0 | ||||
} | } | ||||
vm_create_disk() { | vm_create_disk() { | ||||
echo "Creating image... Please wait." | local BOOTFILES BOOTPARTSOFFSET FSPARTTYPE X86GPTBOOTFILE | ||||
echo | |||||
if [ -z "${NOSWAP}" ]; then | if [ -z "${NOSWAP}" ]; then | ||||
SWAPOPT="-p freebsd-swap/swapfs::${SWAPSIZE}" | SWAPOPT="-p freebsd-swap/swapfs::${SWAPSIZE}" | ||||
fi | fi | ||||
if [ -n "${VM_BOOTPARTSOFFSET}" ]; then | if [ -n "${VM_BOOTPARTSOFFSET}" ]; then | ||||
BOOTPARTSOFFSET=":${VM_BOOTPARTSOFFSET}" | BOOTPARTSOFFSET=":${VM_BOOTPARTSOFFSET}" | ||||
fi | fi | ||||
case "${VMFS}" in | |||||
ufs) | |||||
FSPARTTYPE=freebsd-ufs | |||||
Not Done Inline ActionsI was a bit confused by this at first, before finding that it is only used for x86 below. Maybe X86GPTBOOTFILE? emaste: I was a bit confused by this at first, before finding that it is only used for x86 below. Maybe… | |||||
Done Inline ActionsYeah, I'll change that. markj: Yeah, I'll change that. | |||||
X86GPTBOOTFILE=i386/gptboot/gptboot | |||||
;; | |||||
zfs) | |||||
FSPARTTYPE=freebsd-zfs | |||||
X86GPTBOOTFILE=i386/gptzfsboot/gptzfsboot | |||||
;; | |||||
*) | |||||
echo "Unexpected VMFS value '${VMFS}'" | |||||
return 1 | |||||
;; | |||||
esac | |||||
echo "Creating image... Please wait." | |||||
echo | |||||
BOOTFILES="$(env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ | BOOTFILES="$(env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ | ||||
WITH_UNIFIED_OBJDIR=yes \ | WITH_UNIFIED_OBJDIR=yes \ | ||||
make -C ${WORLDDIR}/stand -V .OBJDIR)" | make -C ${WORLDDIR}/stand -V .OBJDIR)" | ||||
BOOTFILES="$(realpath ${BOOTFILES})" | BOOTFILES="$(realpath ${BOOTFILES})" | ||||
MAKEFSARGS="-s ${VMSIZE}" | |||||
case "${TARGET}:${TARGET_ARCH}" in | case "${TARGET}:${TARGET_ARCH}" in | ||||
amd64:amd64 | i386:i386) | amd64:amd64 | i386:i386) | ||||
ESP=yes | ESP=yes | ||||
BOOTPARTS="-b ${BOOTFILES}/i386/pmbr/pmbr \ | BOOTPARTS="-b ${BOOTFILES}/i386/pmbr/pmbr \ | ||||
-p freebsd-boot/bootfs:=${BOOTFILES}/i386/gptboot/gptboot${BOOTPARTSOFFSET}" | -p freebsd-boot/bootfs:=${BOOTFILES}/${X86GPTBOOTFILE}${BOOTPARTSOFFSET}" | ||||
ROOTFSPART="-p freebsd-ufs/rootfs:=${VMBASE}" | ROOTFSPART="-p ${FSPARTTYPE}/rootfs:=${VMBASE}" | ||||
MAKEFSARGS="-B little" | MAKEFSARGS="$MAKEFSARGS -B little" | ||||
;; | ;; | ||||
arm64:aarch64 | riscv:riscv64*) | arm64:aarch64 | riscv:riscv64*) | ||||
ESP=yes | ESP=yes | ||||
BOOTPARTS= | BOOTPARTS= | ||||
ROOTFSPART="-p freebsd-ufs/rootfs:=${VMBASE}" | ROOTFSPART="-p ${FSPARTTYPE}/rootfs:=${VMBASE}" | ||||
MAKEFSARGS="-B little" | MAKEFSARGS="$MAKEFSARGS -B little" | ||||
;; | ;; | ||||
powerpc:powerpc*) | powerpc:powerpc*) | ||||
ESP=no | ESP=no | ||||
BOOTPARTS="-p prepboot:=${BOOTFILES}/powerpc/boot1.chrp/boot1.elf -a 1" | BOOTPARTS="-p prepboot:=${BOOTFILES}/powerpc/boot1.chrp/boot1.elf -a 1" | ||||
ROOTFSPART="-p freebsd:=${VMBASE}" | ROOTFSPART="-p freebsd:=${VMBASE}" | ||||
if [ ${TARGET_ARCH} = powerpc64le ]; then | if [ ${TARGET_ARCH} = powerpc64le ]; then | ||||
MAKEFSARGS="-B little" | MAKEFSARGS="$MAKEFSARGS -B little" | ||||
else | else | ||||
MAKEFSARGS="-B big" | MAKEFSARGS="$MAKEFSARGS -B big" | ||||
fi | fi | ||||
;; | ;; | ||||
*) | *) | ||||
echo "vmimage.subr: unsupported target '${TARGET}:${TARGET_ARCH}'" >&2 | echo "vmimage.subr: unsupported target '${TARGET}:${TARGET_ARCH}'" >&2 | ||||
exit 1 | exit 1 | ||||
;; | ;; | ||||
esac | esac | ||||
if [ ${ESP} = "yes" ]; then | if [ ${ESP} = "yes" ]; then | ||||
# Create an ESP | # Create an ESP | ||||
espfilename=$(mktemp /tmp/efiboot.XXXXXX) | espfilename=$(mktemp /tmp/efiboot.XXXXXX) | ||||
make_esp_file ${espfilename} ${fat32min} ${BOOTFILES}/efi/loader_lua/loader_lua.efi | make_esp_file ${espfilename} ${fat32min} ${BOOTFILES}/efi/loader_lua/loader_lua.efi | ||||
BOOTPARTS="${BOOTPARTS} -p efi/efiesp:=${espfilename}" | BOOTPARTS="${BOOTPARTS} -p efi/efiesp:=${espfilename}" | ||||
# Add this to fstab | # Add this to fstab | ||||
mkdir -p ${DESTDIR}/boot/efi | mkdir -p ${DESTDIR}/boot/efi | ||||
echo "/dev/${ROOTLABEL}/efiesp /boot/efi msdosfs rw 2 2" \ | echo "/dev/${ROOTLABEL}/efiesp /boot/efi msdosfs rw 2 2" \ | ||||
>> ${DESTDIR}/etc/fstab | >> ${DESTDIR}/etc/fstab | ||||
fi | fi | ||||
echo "Building filesystem... Please wait." | echo "Building filesystem... Please wait." | ||||
makefs ${MAKEFSARGS} -o label=rootfs -o version=2 -o softupdates=1 \ | buildfs | ||||
-s ${VMSIZE} ${VMBASE} ${DESTDIR} | |||||
echo "Building final disk image... Please wait." | echo "Building final disk image... Please wait." | ||||
mkimg -s ${PARTSCHEME} -f ${VMFORMAT} \ | mkimg -s ${PARTSCHEME} -f ${VMFORMAT} \ | ||||
${BOOTPARTS} \ | ${BOOTPARTS} \ | ||||
${SWAPOPT} \ | ${SWAPOPT} \ | ||||
${ROOTFSPART} \ | ${ROOTFSPART} \ | ||||
-o ${VMIMAGE} | -o ${VMIMAGE} | ||||
Show All 12 Lines |
what happens if this fails?