Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Dec 2013 17:26:07 +0000 (UTC)
From:      Julio Merino <jmmv@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r260090 - in user/jmmv: . autotest autotest/node autotest/node/configs autotest/node/rc.d
Message-ID:  <201312301726.rBUHQ7aH031122@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jmmv
Date: Mon Dec 30 17:26:06 2013
New Revision: 260090
URL: http://svnweb.freebsd.org/changeset/base/260090

Log:
  Add scripts to set up a single Kyua testing node.
  
  This new 'autotest' directory is intended to contain scripts and
  configuration files used to set up the Kyua testing cluster.  This
  specific commit brings in only the code used to bring up a single
  node in the cluster.
  
  Be aware that most of the code in here is only temporary glue until Kyua
  itself becomes a better test harness with support for multiple hosts and
  consolidated reports.  (All this stuff is planned but it's a non-trivial
  amount of work so, in the meantime, we get something ad hoc but useful.)
  
  It is also possible that parts of this code might end up in src (like the
  generation of VM disk images).  However, this whole thing is not intended
  to be part of src and is why it is being checked in the user/ hierarchy.
  
  And, finally: what's in the autotest name?  Nothing special.

Added:
  user/jmmv/
  user/jmmv/autotest/
  user/jmmv/autotest/README
  user/jmmv/autotest/node/Makefile   (contents, props changed)
  user/jmmv/autotest/node/configs/
  user/jmmv/autotest/node/configs/head.conf   (contents, props changed)
  user/jmmv/autotest/node/configs/stable-10.conf   (contents, props changed)
  user/jmmv/autotest/node/iterate.sh   (contents, props changed)
  user/jmmv/autotest/node/loop.sh   (contents, props changed)
  user/jmmv/autotest/node/rc.d/autotest-node.in   (contents, props changed)
  user/jmmv/autotest/node/setup   (contents, props changed)
Directory Properties:
  user/jmmv/autotest/node/   (props changed)
  user/jmmv/autotest/node/rc.d/   (props changed)

Added: user/jmmv/autotest/README
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/README	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,45 @@
+$FreeBSD$
+
+This directory contains a collection of scripts and their corresponding
+configurations to set up continuous testing hosts on the Kyua cluster.
+
+Be aware that most of the code in here exists only as temporary glue.  The
+goal is for Kyua itself to offer most or all of the functionality
+implemented in these scripts.  However, doing so in a generic manner will
+require a significant amount of effort; in the meantime, it is easier to
+just do all the work in relatively-straightforward scripts that are
+specific to FreeBSD.
+
+As weird as it may be, the code in here is designed to be executed, on
+purpose, from its source directory.  There is no way to install it under,
+say, /usr/local.  Doing so would require some minor changes to ensure the
+paths are valid but I did not see the point of supporting this.  In
+general, the machines will just "svn update" the code in this directory,
+run "make" again and go on their merry way while allowing the backgrounded
+jobs to pick up the new versions (if any).
+
+
+node directory
+--------------
+
+Scripts and configuration files to set up a single Kyua cluster node.
+
+To configure a machine as a node, just run "./node/setup".  This command
+will install any necessary prerequisites, build the scripts, enable the
+background processing loop in rc.d and start it.  Arguments to the "setup"
+script are passed directly to make, so they can be used to override
+settings for the particular host being configured (e.g. the path to shtk).
+
+Of special interest are:
+
+* node/iterate: Builds a release, creates a fresh disk image that runs the
+  tests on execution, executes the image in a VM and collects the test
+  results.
+
+* node/loop: Executes node/iterate in an infinite loop with one or more
+  release configurations.
+
+* node/configs/: Configuration files for node/iterate.  node/loop picks all
+  of them up and runs them in sequence.
+
+* node/rc.d/autotest-node: rc.d script to run node/loop as a daemon.

Added: user/jmmv/autotest/node/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/node/Makefile	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,34 @@
+# $FreeBSD$
+
+ROOT?= /kyua
+SHTK?= shtk
+
+BINDIR= ${.CURDIR}
+LOCALSTATEDIR= /var
+SHELL= /bin/sh
+SYSCONFDIR= ${.CURDIR}/configs
+
+SCRIPTS= iterate loop
+
+.PHONY: all
+all: ${SCRIPTS} rc.d/autotest-node
+
+.for script in ${SCRIPTS}
+${script}: ${script}.sh
+	sed -e 's,__AUTOTEST_BINDIR__,${BINDIR},g' \
+	    -e 's,__AUTOTEST_ETCDIR__,${SYSCONFDIR},g' \
+	    -e 's,__AUTOTEST_ROOT__,${ROOT},g' \
+	    "${script}.sh" | "${SHTK}" build -o "${script}" -s "${SHELL}" -
+.endfor
+
+rc.d/autotest-node: rc.d/autotest-node.in
+	sed -e "s,__AUTOTEST_BINDIR__,${BINDIR},g" \
+	    -e 's,__AUTOTEST_ETCDIR__,${SYSCONFDIR},g' \
+	    -e 's,__AUTOTEST_SHELL__,${SHELL},g' \
+	    -e "s,__AUTOTEST_VARBASE__,${LOCALSTATEDIR},g" \
+	    rc.d/autotest-node.in >rc.d/autotest-node
+	chmod +x rc.d/autotest-node
+
+.PHONY: clean
+clean:
+	rm -f ${SCRIPTS} rc.d/autotest-node

Added: user/jmmv/autotest/node/configs/head.conf
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/node/configs/head.conf	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,16 @@
+# $FreeBSD$
+#
+# autotest node configuration to test FreeBSD HEAD.
+#
+
+root=/kyua/head
+
+CHROOTDIR="${root}/build"
+IMAGE="${root}/image.disk"
+DATADIR="${root}/data"
+SRCBRANCH="base/head"
+MKVARS="NO_CLEAN=yes WITH_TESTS=yes"
+
+# TODO(jmmv): Remove this.  lib32 builds are currently broken in combination
+# with the test suite, so we ought to fix that instead of disabling lib32.
+MKVARS="${MKVARS} WITHOUT_LIB32=yes"

Added: user/jmmv/autotest/node/configs/stable-10.conf
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/node/configs/stable-10.conf	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,16 @@
+# $FreeBSD$
+#
+# autotest node configuration to test FreeBSD stable/10.
+#
+
+root=/kyua/stable-10
+
+CHROOTDIR="${root}/build"
+IMAGE="${root}/image.disk"
+DATADIR="${root}/data"
+SRCBRANCH="base/stable/10"
+MKVARS="NO_CLEAN=yes WITH_TESTS=yes"
+
+# TODO(jmmv): Remove this.  lib32 builds are currently broken in combination
+# with the test suite, so we ought to fix that instead of disabling lib32.
+MKVARS="${MKVARS} WITHOUT_LIB32=yes"

Added: user/jmmv/autotest/node/iterate.sh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/node/iterate.sh	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,393 @@
+# $FreeBSD$
+#
+# Copyright 2013 Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors
+#   may be used to endorse or promote products derived from this software
+#   without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# \file iterate.sh
+# Creates a FreeBSD release and executes its tests within a VM.
+
+shtk_import bool
+shtk_import cleanup
+shtk_import cli
+shtk_import config
+shtk_import process
+
+
+# List of valid configuration variables.
+#
+# Please remember to update sysbuild.conf(5) if you change this list.
+AUTOTEST_CONFIG_VARS="CHROOTDIR DATADIR IMAGE MKVARS SRCBRANCH SVNROOT"
+
+
+# Paths to installed files.
+#
+# Can be overriden for test purposes only.
+: ${AUTOTEST_ETCDIR="__AUTOTEST_ETCDIR__"}
+: ${AUTOTEST_ROOT="__AUTOTEST_ROOT__"}
+
+
+# Sets defaults for configuration variables and hooks that need to exist.
+#
+# This function should be before the configuration file has been loaded.  This
+# means that the user can undefine a required configuration variable, but we let
+# him shoot himself in the foot if he so desires.
+autotest_set_defaults() {
+    # Please remember to update autotest(1) if you change any default values.
+    shtk_config_set CHROOTDIR "${AUTOTEST_ROOT}/head/build"
+    shtk_config_set DATADIR "${AUTOTEST_ROOT}/data"
+    shtk_config_set IMAGE "${AUTOTEST_ROOT}/image.disk"
+    shtk_config_set SRCBRANCH "base/head"
+    shtk_config_set SVNROOT "svn://svn.freebsd.org"
+}
+
+
+# Dumps the loaded configuration.
+#
+# \params ... The options and arguments to the command.
+autotest_config() {
+    [ ${#} -eq 0 ] || shtk_cli_usage_error "config does not take any arguments"
+
+    for var in ${AUTOTEST_CONFIG_VARS}; do
+        if shtk_config_has "${var}"; then
+            echo "${var} = $(shtk_config_get "${var}")"
+        else
+            echo "${var} is undefined"
+        fi
+    done
+}
+
+
+# Prints the contents of the src.conf file.
+#
+# The output of this is the collection of variables and their values as defined
+# in MKVARS.
+_generate_src_conf() {
+    for varvalue in $(shtk_config_get MKVARS); do
+        echo "${varvalue}"
+    done
+}
+
+
+# Builds a full release for later testing.
+autotest_release() {
+    [ ${#} -eq 0 ] || shtk_cli_usage_error "release does not take any arguments"
+
+    local tmpdir="$(mktemp -d -t autotest)"
+    eval "remove_tmpdir() { rm -rf '${tmpdir}'; }"
+    shtk_cleanup_register remove_tmpdir
+
+    local src_conf="${tmpdir}/src.conf"
+    _generate_src_conf >"${src_conf}"
+
+    local release_conf="${tmpdir}/release.conf"
+    cat >"${release_conf}" <<EOF
+CHROOTDIR="$(shtk_config_get CHROOTDIR)"
+MAKE_FLAGS=  # Disable default silent mode.
+NODOC=yes
+NODVD=yes
+NOPORTS=yes
+SRCBRANCH="$(shtk_config_get SRCBRANCH)"
+SRC_CONF="${src_conf}"
+SVNROOT="$(shtk_config_get SVNROOT)"
+EOF
+
+    local svnroot="$(shtk_config_get SVNROOT)/$(shtk_config_get SRCBRANCH)"
+    shtk_cli_info "Fetching release.sh from ${svnroot}"
+    local release_sh="${tmpdir}/release.sh"
+    svn export "${svnroot}/release/release.sh" "${release_sh}" \
+        || shtk_cli_error "Fetch of release.sh failed"
+    chmod +x "${release_sh}"
+
+    local ret=0
+    shtk_process_run "${release_sh}" -c "${release_conf}" || ret=${?}
+    rm -rf "${tmpdir}"; eval "remove_tmpdir() { true; }"
+    [ ${ret} -eq 0 ] || shtk_cli_error "release build failed"
+}
+
+
+# Creates a disk image with an fresh FreeBSD installation to run Kyua.
+#
+# This uses the results of autotest_release, which must have been invoked
+# beforehand.
+#
+# When run, the image will automatically log in as root, execute the full test
+# suite from /usr/tests using Kyua, and shut the system down.
+autotest_mkimage() {
+    [ ${#} -eq 0 ] || shtk_cli_usage_error "mkimage does not take any arguments"
+
+    local chrootdir="$(shtk_config_get CHROOTDIR)"
+    local image="$(shtk_config_get IMAGE)"
+
+    rm -f "${image}"
+    touch "${image}"
+    truncate -s 4G "${image}"
+
+    cleanup_mkimage() {
+        # This is our function to clean up any system-wide resources that we
+        # acquire during the process.  Because we cannot get all of these
+        # atomically, and because the order in which they are released matters,
+        # we redefine this cleanup function as we go to cover all the needed
+        # details.
+        true
+    }
+    shtk_cleanup_register cleanup_mkimage
+
+    shtk_cli_info "Preparing image"
+    local mddev="$(mdconfig -a -t vnode -f "${image}")"
+    eval "cleanup_mkimage() {
+        mdconfig -d -u '${mddev}' || true;
+    }"
+    gpart create -s gpt "${mddev}"
+    gpart add -t freebsd-boot -s 512k -l bootfs "${mddev}"
+    gpart bootcode -b "${chrootdir}/boot/pmbr" -p "${chrootdir}/boot/gptboot" \
+        -i 1 "${mddev}"
+    gpart add -t freebsd-swap -s 1G -l swapfs "${mddev}"
+    gpart add -t freebsd-ufs -l rootfs "${mddev}"
+    newfs "${mddev}p3"
+
+    shtk_cli_info "Mounting image file systems"
+    mkdir -p "${chrootdir}/vmimage/mnt"
+    eval "cleanup_mkimage() {
+        umount '${chrootdir}/vmimage/mnt' || true; \
+        mdconfig -d -u '${mddev}' || true; \
+        umount '${chrootdir}/dev' || true; \
+    }"
+    mount "/dev/${mddev}p3" "${chrootdir}/vmimage/mnt"
+    mount -t devfs devfs "${chrootdir}/dev"
+
+    shtk_cli_info "Installing system into image"
+    _generate_src_conf >"${chrootdir}/etc/src.conf"
+    chroot "${chrootdir}" make -s -C /usr/src DESTDIR=/vmimage/mnt \
+        installworld installkernel distribution 2>&1 >/dev/null
+
+    shtk_cli_info "Setting up image configuration"
+    echo "-h" >"${chrootdir}/vmimage/mnt/boot.config"
+    sed -i .tmp \
+        '/^ttyv.*$/s/on/off/;/^ttyu0.*$/s/off/on/;/^ttyu0.*$/s/dialup/xterm/' \
+        "${chrootdir}/vmimage/mnt/etc/ttys"
+    sed -i .tmp '/^default:/s/:/:al=root:/' \
+        "${chrootdir}/vmimage/mnt/etc/gettytab"
+
+    cat >"${chrootdir}/vmimage/mnt/etc/fstab" <<EOF
+/dev/gpt/rootfs / ufs rw 2 2
+/dev/gpt/swapfs none swap sw 0 0
+EOF
+
+    cp /etc/resolv.conf "${chrootdir}/vmimage/mnt/etc"
+    pkg -c "${chrootdir}/vmimage/mnt" install -y kyua
+    rm "${chrootdir}/vmimage/mnt/etc/resolv.conf"
+
+    cat >>"${chrootdir}/vmimage/mnt/root/.cshrc" <<EOF
+cd /usr/tests
+/usr/local/bin/kyua test
+shutdown -p now
+EOF
+
+    shtk_cli_info "Unmounting image file systems"
+    cleanup_mkimage
+    eval "cleanup_mkimage() { true; }"  # Prevent double-execution on exit.
+}
+
+
+# Runs the image built by autotest_mkimage.
+autotest_execute() {
+    [ ${#} -eq 0 ] || shtk_cli_usage_error "execute does not take any arguments"
+
+    local chrootdir="$(shtk_config_get CHROOTDIR)"
+    local image="$(shtk_config_get IMAGE)"
+
+    # TODO(jmmv): Add support for bhyve.  Keep in mind that we must continue to
+    # support qemu so that we can test non-amd64 platforms from our test cluster
+    # machines.  In other words: the selection of the VMM has to be exposed in
+    # the configuration file.
+    shtk_process_run qemu-system-x86_64 -nographic -drive file="${image}"
+}
+
+
+# Extracts the test results from the image and puts them in the given directory.
+#
+# \param datadir Path to the directory to hold the results of this particular
+#     run.  This will contain the raw Kyua database as well as the formatted
+#     HTML output.
+autotest_publish() {
+    [ ${#} -eq 1 ] || shtk_cli_usage_error "publish expects one argument"
+    local datadir="${1}"; shift
+
+    local chrootdir="$(shtk_config_get CHROOTDIR)"
+    local image="$(shtk_config_get IMAGE)"
+
+    shtk_cli_info "Extracting test results from image"
+    local mddev="$(mdconfig -a -t vnode -f "${image}")"
+    mount -o ro "/dev/${mddev}p3" "${chrootdir}/vmimage/mnt"
+    mkdir -p "${datadir}"
+    cp "${chrootdir}/vmimage/mnt/root/.kyua/store.db" "${datadir}/store.db"
+    umount "${chrootdir}/vmimage/mnt"
+    mdconfig -d -u "${mddev}"
+
+    shtk_process_run /usr/local/bin/kyua report-html \
+        --output="${datadir}/results" \
+        --store="${datadir}/store.db" \
+        --results-filter=
+}
+
+
+# Performs a single release plus test execution pass.
+#
+# The full log of this is logged into DATADIR.
+autotest_all() {
+    local quiet=false
+    local OPTIND
+    while getopts ':q' arg "${@}"; do
+        case "${arg}" in
+            q)  # Suppress all output.
+                quiet=true
+                ;;
+
+            \?)
+                shtk_cli_usage_error "Unknown option -${OPTARG}"
+                ;;
+        esac
+    done
+    shift $((${OPTIND} - 1))
+
+    [ ${#} -eq 0 ] || shtk_cli_usage_error "all does not take any arguments"
+
+    local timestamp=$(date +%Y%m%d-%H%M%S)
+    local datadir="$(shtk_config_get DATADIR)/${timestamp}"
+
+    mkdir -p "${datadir}"
+    touch "${datadir}/output.log"
+    if ! shtk_bool_check "${quiet}"; then
+        tail -f "${datadir}/output.log" &
+        local tail_pid="${!}"
+        eval "kill_tail() { kill '${tail_pid}'; }"
+        shtk_cleanup_register kill_tail
+    fi
+    exec >>"${datadir}/output.log" 2>&1
+
+    (
+        autotest_release
+        autotest_mkimage
+        autotest_execute
+        autotest_publish "${datadir}"
+    )
+    ln -sf "${timestamp}" "$(shtk_config_get DATADIR)/0-LATEST"
+
+    exec >&- 2>&-
+    if ! shtk_bool_check "${quiet}"; then
+        kill "${tail_pid}"
+        eval "kill_tail() { true; }"
+    fi
+}
+
+
+# Loads the configuration file specified in the command line.
+#
+# \param config_name Name of the desired configuration.  It can be either a
+#     configuration name (no slashes) or a path.
+autotest_config_load() {
+    local config_name="${1}"; shift
+
+    local config_file=
+    case "${config_name}" in
+        */*|*.conf)
+            config_file="${config_name}"
+            ;;
+
+        *)
+            config_file="${AUTOTEST_ETCDIR}/${config_name}.conf"
+            [ ! -e "${config_file}" ] \
+                || shtk_cli_usage_error "Cannot locate configuration named" \
+                "'${config_name}'"
+            ;;
+    esac
+    shtk_config_load "${config_file}"
+}
+
+
+# Entry point to the program.
+#
+# \param ... Command-line arguments to be processed.
+#
+# \return An exit code to be returned to the user.
+main() {
+    local config_file="${AUTOTEST_ETCDIR}/head.conf"
+    local expert_mode=false
+
+    shtk_config_init ${AUTOTEST_CONFIG_VARS}
+
+    local OPTIND
+    while getopts ':c:o:X' arg "${@}"; do
+        case "${arg}" in
+            c)  # Name of the configuration to load.
+                config_file="${OPTARG}"
+                ;;
+
+            o)  # Override for a particular configuration variable.
+                shtk_config_override "${OPTARG}"
+                ;;
+
+            X)  # Enable expert-mode.
+                expert_mode=true
+                ;;
+
+            \?)
+                shtk_cli_usage_error "Unknown option -${OPTARG}"
+                ;;
+        esac
+    done
+    shift $((${OPTIND} - 1))
+
+    [ ${#} -ge 1 ] || shtk_cli_usage_error "No command specified"
+
+    local exit_code=0
+
+    local command="${1}"; shift
+    case "${command}" in
+        all|config)
+            autotest_set_defaults
+            shtk_config_load "${config_file}"
+            "autotest_${command}" "${@}" || exit_code="${?}"
+            ;;
+
+        execute|mkimage|publish|release)
+            shtk_bool_check "${expert_mode}" \
+                || shtk_cli_usage_error "Using ${command} requires expert" \
+                "mode; try passing -X"
+            autotest_set_defaults
+            shtk_config_load "${config_file}"
+            "autotest_${command}" "${@}" || exit_code="${?}"
+            ;;
+
+        *)
+            shtk_cli_usage_error "Unknown command ${command}"
+            ;;
+    esac
+
+    return "${exit_code}"
+}

Added: user/jmmv/autotest/node/loop.sh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/node/loop.sh	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,156 @@
+# $FreeBSD$
+#
+# Copyright 2013 Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors
+#   may be used to endorse or promote products derived from this software
+#   without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# \file loop.sh
+# Executes iterate.sh on one or more configurations in an infinite loop.
+#
+# This script implements a "daemon mode" so that it can easily be run from
+# within an rc.d script at system startup.
+
+shtk_import bool
+shtk_import cleanup
+shtk_import cli
+shtk_import process
+
+
+# Paths to installed files.
+#
+# Can be overriden for test purposes only.
+: ${AUTOTEST_BINDIR="__AUTOTEST_BINDIR__"}
+: ${AUTOTEST_ETCDIR="__AUTOTEST_ETCDIR__"}
+
+
+# Creates a pidfile for this shell interpreter.
+#
+# \param path Path to the pidfile to create.
+#
+# \post Installs a cleanup hook to remove the pidfile on exit.
+create_pidfile() {
+    local path="${1}"; shift
+
+    local pid="$(sh -c 'echo ${PPID}')"
+    echo "${pid}" >"${path}" || shtk_cli_error "Cannot create ${path}"
+    eval "remove_pidfile() { rm '${path}'; }"
+    shtk_cleanup_register remove_pidfile
+}
+
+
+# The main loop to iterate over all configs.
+#
+# This function does not return.
+#
+# \param delay Seconds to pause between iterations.
+# \param ... Configuration files to process.
+the_loop() {
+    local delay="${1}"; shift
+
+    local autoconfigs=false
+    [ ${#} -gt 0 ] || autoconfigs=true
+
+    while :; do
+        shtk_cli_info "Iteration started on $(date)"
+
+        if shtk_bool_check "${autoconfigs}"; then
+            set -- $(echo "${AUTOTEST_ETCDIR}/*.conf")
+            shtk_cli_info "Discovered config files: ${*}"
+        fi
+
+        for config in "${@}"; do
+            shtk_process_run "${AUTOTEST_BINDIR}/iterate" -c "${config}" \
+                all -q || true
+        done
+
+        shtk_cli_info "Iteration finished on $(date)"
+
+        if [ ${delay} -gt 0 ]; then
+            shtk_cli_info "Sleeping for ${delay} seconds until next iteration"
+            local remaining=${delay}
+            while [ ${remaining} -gt 0 ]; do
+                sleep 1
+                remaining=$((${remaining} - 1))
+            done
+        fi
+    done
+}
+
+
+# Entry point to the program.
+#
+# \param ... Command-line arguments to be processed.
+#
+# \return An exit code to be returned to the user.
+main() {
+    local background=false
+    local delay=0
+    local logfile=
+    local pidfile=
+
+    local OPTIND
+    while getopts ':bd:l:p:' arg "${@}"; do
+        case "${arg}" in
+            b)  # Enter background (daemon) mode.
+                [ -n "${_AUTOTEST_BACKGROUNDED}" ] || background=true
+                ;;
+
+            d)  # Delay, in seconds, between iterations.
+                delay="${OPTARG}"
+                ;;
+
+            l)  # Path to the log file; suppresses output.
+                [ -n "${_AUTOTEST_BACKGROUNDED}" ] || logfile="${OPTARG}"
+                ;;
+
+            p)  # Enable pidfile creation.
+                pidfile="${OPTARG}"
+                ;;
+
+            \?)
+                shtk_cli_usage_error "Unknown option -${OPTARG}"
+                ;;
+        esac
+    done
+
+    if shtk_bool_check "${background}"; then
+        if [ -n "${logfile}" ]; then
+            _AUTOTEST_BACKGROUNDED=true \
+                "$(shtk_cli_dirname)/$(shtk_cli_progname)" "${@}" \
+                >"${logfile}" 2>&1 &
+        else
+            _AUTOTEST_BACKGROUNDED=true \
+                "$(shtk_cli_dirname)/$(shtk_cli_progname)" "${@}" &
+        fi
+    else
+        shift $((${OPTIND} - 1))
+
+        [ -z "${logfile}" ] || exec >"${logfile}" 2>&1
+        [ -z "${pidfile}" ] || create_pidfile "${pidfile}"
+        the_loop "${delay}" "${@}"
+    fi
+}

Added: user/jmmv/autotest/node/rc.d/autotest-node.in
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/node/rc.d/autotest-node.in	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,33 @@
+#! /bin/sh
+#
+# $FreeBSD$
+#
+# rc.d script to run the autotest infinite node loop in the background.
+# Once started, the machine will continuously fetch, build and test one or more
+# release configurations -- so be wary of the load this will incur.
+#
+
+# PROVIDE: autotest_node
+# REQUIRE: DAEMON
+
+#
+# Add the following lines to /etc/rc.conf to enable autotest_node:
+#
+#local_startup="${local_startup} __AUTOTEST_BINDIR__/rc.d"
+#autotest_node_enable="YES"
+
+. /etc/rc.subr
+
+# We require access to installed packages.
+PATH="/usr/local/bin:/usr/local/sbin:${PATH}"
+
+name="autotest_node"
+rcvar="autotest_node_enable"
+logfile="__AUTOTEST_VARBASE__/log/autotest-node.log"
+pidfile="__AUTOTEST_VARBASE__/run/autotest-node.pid"
+command="__AUTOTEST_BINDIR__/loop"
+command_interpreter="__AUTOTEST_SHELL__"
+command_args="-b -d 60 -l '${logfile}' -p '${pidfile}'"
+
+load_rc_config $name
+run_rc_command "$1"

Added: user/jmmv/autotest/node/setup
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/jmmv/autotest/node/setup	Mon Dec 30 17:26:06 2013	(r260090)
@@ -0,0 +1,78 @@
+#! /bin/sh
+# $FreeBSD$
+#
+# Copyright 2013 Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors
+#   may be used to endorse or promote products derived from this software
+#   without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# \file setup
+# Configures the current machine as an autotest node.
+
+set -e -x
+
+PROGDIR="$(cd $(dirname ${0}) && pwd)"
+
+
+# Installs any required packages and ensures they are up-to-date.
+install_deps() {
+    pkg update
+    pkg install -y qemu-devel kyua shtk
+    pkg upgrade -y
+}
+
+
+# Builds the source code.
+#
+# \param ... Arguments to make.  Use to pass variable overrides for the host,
+#     such as the location of shtk(1).
+build() {
+    make -C "${PROGDIR}" clean
+    make -C "${PROGDIR}" all "${@}"
+}
+
+
+# Sets up rc.conf to start autotest_node on boot.
+enable_daemon() {
+    grep "local_startup.*${PROGDIR}/rc.d" /etc/rc.conf \
+        || echo "local_startup=\"\${local_startup} ${PROGDIR}/rc.d\"" \
+        >>/etc/rc.conf
+    grep "autotest_node_enable=yes" /etc/rc.conf \
+        || echo "autotest_node_enable=yes" >>/etc/rc.conf
+
+    "${PROGDIR}/rc.d/autotest_node" start
+}
+
+
+# Program entry.
+main() {
+    install_deps
+    build "${@}"
+    enable_daemon
+}
+
+
+main "${@}"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201312301726.rBUHQ7aH031122>