#!/bin/sh # client-side script to claim a chroot # usage: claim-chroot ${arch} ${branch} ${pkgname} ${buildid} # Care needs to be taken with the output of this script, it cannot # output anything except space-separated pairs of "keyword value". # # Keywords: # chroot : successfully claimed a chroot # setup : we own the rights to setup the build env # wait : someone else is setting up the build env # In case of other error, just exit. # XXX if the setupnode process was a single process invocation we # could use a lockf lock, and be able to tell if the setup process was # still running or died prematurely pb=/var/portbuild usage () { echo "usage: claim-chroot arch branch buildid" exit 1 } if [ $# -ne 4 ]; then usage fi arch=$1 branch=$2 buildid=$3 pkgname=$4 shift 4 # If client has just rebooted it may not have any files yet if [ ! -f /tmp/.boot_finished ]; then echo "wait boot" exit 1 fi # Do we need to set up the client after cold boot? # # NB: mkdir is being used as an atomic test-and-set operation to # provide mutual exclusion against other callers, since we only want # one of them to perform setup builddir=${pb}/${arch}/${branch}/builds/${buildid} # Is the build environment populated? Again we only want a single # instance to gain setup rights if not. if (mkdir /tmp/.setup-${buildid} 2> /dev/null); then # The buildenv is not set up, tell the caller to do it echo "setup ${builddir}" exit 1 fi if [ ! -f ${builddir}/.ready ]; then # The buildenv is still being set up echo "wait ${builddir}" exit 1 fi . ${pb}/${arch}/client.conf . ${pb}/${arch}/common.conf . ${pb}/${arch}/portbuild.conf . ${pb}/${arch}/portbuild.$(hostname) buildroot=${scratchdir} pkgname=${pkgname%.${PKGSUFFIX}} chrootdir=${buildroot}/${branch}/${buildid}/chroot # Perform initial sanity checks # Check squid is running if [ ! -z "${squid_dir}" ]; then /usr/local/sbin/squid -k check 2> /dev/null status=$? if [ "${status}" != "0" ]; then touch ${scratchdir}/.squid /usr/local/etc/rc.d/squid start > /dev/null & echo "error squid" exit 1 else rm -f ${scratchdir}/.squid fi fi # Check for enough disk space df=$(df -k ${scratchdir} | tail -1 | awk '{print $4}') if [ ${df} -lt 102400 ]; then touch ${scratchdir}/.disk echo "error disk" exit 1 else rm -f ${scratchdir}/.disk fi found=0 # Look for pre-existing chroot directories that are populated and unused for dir in ${chrootdir}/*; do if [ -f ${dir}/.ready -o -f ${dir}/.dirty ]; then # Atomically claim the directory mkdir ${dir}/used 2>/dev/null || continue touch ${dir}/used/${pkgname} if [ -f ${dir}/.dirty ]; then ${pb}/scripts/clean-chroot ${arch} ${branch} ${buildid} ${dir} 2 >/dev/null 2>/dev/null & continue fi found=1 chroot=${dir} break fi done chrootnum=$$ # If we didn't find a pre-existing directory, create and claim a new one. while [ ${found} != 1 ]; do if [ "${use_zfs}" = "1" ]; then chroot=${chrootdir}/${chrootnum} # XXX deal with failure zfs clone ${scratchdir#/}/${branch}/${buildid}/world@base ${chroot#/} mkdir ${chroot}/used elif [ "${use_md_swap}" = "1" ]; then unit=$(mdconfig -a -t swap -s ${md_size}) if [ -z "${unit}" ]; then echo "error mdconfig" exit 1 fi newfs /dev/${unit} > /dev/null chrootnum=$(echo ${unit} | sed 's,md,,') chroot=${chrootdir}/${chrootnum} mkdir -p ${chroot}/used 2>/dev/null || continue # Need to make sure that used/ is also present after mounting # the fresh md so as to not leave open any races mount -o async /dev/${unit} ${chroot}/used mkdir ${chroot}/used/used touch ${chroot}/used/used/${pkgname} umount -f ${chroot}/used mount -o async /dev/${unit} ${chroot}/ touch ${chroot}/.notready else chrootnum=$(($chrootnum+1)) chroot=${chrootdir}/${chrootnum} mkdir -p ${chrootdir} 2> /dev/null || continue mkdir ${chroot} 2>/dev/null || continue mkdir ${chroot}/used 2>/dev/null || continue touch ${chroot}/.notready fi if [ "${use_tmpfs}" = "1" ]; then mount -t tmpfs -o "size=${tmpfs_size}" foo ${chroot} mkdir ${chroot}/used 2>/dev/null || echo "ERROR: mkdir race" touch ${chroot}/.notready fi touch ${chroot}/used/${pkgname} found=1 done echo "chroot ${chroot}"