From 36e0c88e7a3912c8a2e6594841172adb9c14525b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 8 Apr 2017 14:14:26 +0200 Subject: Implement machine enumeration --- tests/agent/btrfs-cpdir | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/agent/btrfs-rmdir | 66 ++++++++++++++++++++++++++++ tests/agent/buildfile | 8 ++++ tests/agent/testscript | 112 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 299 insertions(+) create mode 100755 tests/agent/btrfs-cpdir create mode 100755 tests/agent/btrfs-rmdir create mode 100644 tests/agent/buildfile create mode 100644 tests/agent/testscript (limited to 'tests/agent') diff --git a/tests/agent/btrfs-cpdir b/tests/agent/btrfs-cpdir new file mode 100755 index 0000000..d2dbd43 --- /dev/null +++ b/tests/agent/btrfs-cpdir @@ -0,0 +1,113 @@ +#! /usr/bin/env bash + +# Copy a directory on (the same) btrfs filesystem. Inside, subvolumes +# are copied with btrfs subvolume snapshot and everything else with +# cp --reflink=always. +# +# If the -f option is specified and exists, it is first removed by +# calling btrfs-rmdir (which is expected to be found next to btrfs-cpdir). +# +# Notes: +# +# 1. should not be a subvolume (use snapshot directly in this case). +# +# 2. Copying of symlinks is not supported (symlinks in submodules are ok). +# +# 3. Read-only subvolumes are snapshotted as read-only. +# +# Note also that is clones as , not into (i.e., like cp -T). +# +usage="usage: $0 [-f] / /" + +owd="$(pwd)" +trap "{ cd '$owd'; exit 1; }" ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +force= + +while [ "$#" -gt 0 ]; do + case "$1" in + -f) + shift + force="true" + ;; + --) + break + ;; + -*) + error "unknown option: $1" + ;; + *) + break + ;; + esac +done + +src="${1%/}" +dst="${2%/}" + +if [ -z "$src" -o -z "$dst" ]; then + error "$usage" +fi + +shopt -s nullglob dotglob + +function cp_dir () # +{ + local src="$1" + local dst="$2" + + mkdir "$dst" + + local s d + for s in "$src"/*; do + + d="$dst/${s#$src/}" + + if [ -f "$s" ]; then + cp -p --reflink=always "$s" "$d" + continue + fi + + if [ -d "$s" ]; then + + # See if this is a subvolume: btrfs subvolume list requires root + # priviliges so we use the inode number which for subvolumes is always + # 256. + # + if [ "$(stat --format=%i "$s")" -eq 256 ]; then + cp_subvol "$s" "$d" + else + cp_dir "$s" "$d" + fi + continue + fi + + error "$s is not a file/directory, not supported" + done + + chmod --reference="$src" "$dst" + chown --reference="$src" "$dst" +} + +function cp_subvol () # +{ + local src="$1" + local dst="$2" + + local o=() + if [ "$(btrfs property get -ts "$src" ro)" = "ro=true" ]; then + o+=(-r) + fi + + btrfs subvolume snapshot "${o[@]}" "$src" "$dst" >/dev/null +} + +if [ -d "$dst" -a -n "$force" ]; then + "$(dirname "$(realpath ${BASH_SOURCE[0]})")/btrfs-rmdir" "$dst" +fi + +cp_dir "$src" "$dst" diff --git a/tests/agent/btrfs-rmdir b/tests/agent/btrfs-rmdir new file mode 100755 index 0000000..cc51dc2 --- /dev/null +++ b/tests/agent/btrfs-rmdir @@ -0,0 +1,66 @@ +#! /usr/bin/env bash + +# Remove a directory on a btrfs filesystem. Inside, subvolumes are removed +# with btrfs subvolume delete and everything else with rm. +# +# Notes: +# +# 1. should not be a subvolume (use delete directly in this case). +# +# 2. Read-only subvolumes are changed to read-write before deleting. +# +usage="usage: $0 /" + +owd="$(pwd)" +trap "{ cd '$owd'; exit 1; }" ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +dir="${1%/}" + +if [ -z "$dir" ]; then + error "$usage" +fi + +shopt -s nullglob dotglob + +function rm_dir () # +{ + local dir="$1" + + local p + for p in "$dir"/*; do + + if [ -d "$p" -a ! -L "$p" ]; then + + # See if this is a subvolume: btrfs subvolume list requires root + # priviliges so we use the inode number which for subvolumes is always + # 256. + # + if [ "$(stat --format=%i "$p")" -eq 256 ]; then + rm_subvol "$p" + else + rm_dir "$p" + fi + else + rm "$p" + fi + done + + rmdir "$dir" +} + +function rm_subvol () # +{ + local dir="$1" + + if [ "$(btrfs property get -ts "$dir" ro)" = "ro=true" ]; then + btrfs property set -ts "$dir" ro false >/dev/null + fi + + btrfs subvolume delete "$dir" >/dev/null +} + +rm_dir "$dir" diff --git a/tests/agent/buildfile b/tests/agent/buildfile new file mode 100644 index 0000000..1c6d59b --- /dev/null +++ b/tests/agent/buildfile @@ -0,0 +1,8 @@ +# file : tests/agent/buildfile +# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +./: ../../bbot/exe{bbot-agent} test{testscript} file{btrfs-cpdir btrfs-rmdir} +dir{./}: test = ../../bbot/exe{bbot-agent} + +include ../../bbot/ diff --git a/tests/agent/testscript b/tests/agent/testscript new file mode 100644 index 0000000..fa465a4 --- /dev/null +++ b/tests/agent/testscript @@ -0,0 +1,112 @@ +# file : tests/agent/testscript +# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +# The /build/machines directory should be on a btrfs filesystem and have the +# following layout and contents: +# +# /build/machines/ +# └── default/ +# └── linux-gcc/ +# ├── linux-gcc-1.0/ +# │ └── manifest +# └── linux-gcc-1.1/ +# └── manifest +# +# Notes: +# +# - The test must be run serially (@@ TODO: serial directive) + +test.options = --verbose 2 +test.arguments = stage 1 + +cp = $src_base/btrfs-cpdir -f /build/machines.orig /build/machines +rm = $src_base/btrfs-rmdir /build/machines + +: dump-machines +: +{ + m = /build/machines/default/linux-gcc + + test.options += --dump-machines --fake-bootstrap + + +$cp + + : no-current-machine-symlink + : + $* 123 2>>"EOE" + trace: enumerate_machines: skipping $m/: no subvolume link + EOE + + ln -T -s linux-gcc-1.0 $m/linux-gcc-1 + + : bootstrap + : + $* 123 >>EOO 2>>~"%EOE%d" + : 1 + id: linux-gcc-1.0 + name: linux-gcc + summary: Linux with GCC + EOO + %trace: enumerate_machines: btrfs subvolume snapshot $m/linux-gcc-1.0 $m/linux-gcc-stage-\\.+% + trace: enumerate_machines: bootstrapping $m/linux-gcc-stage/ + EOE + + ln -T -f -s linux-gcc-1.1 $m/linux-gcc-1 + + : re-bootstrap-machine + : + $* 123 >>EOO 2>>~"%EOE%d" + : 1 + id: linux-gcc-1.1 + name: linux-gcc + summary: Linux with GCC + EOO + %trace: enumerate_machines: btrfs subvolume snapshot $m/linux-gcc-1.1 $m/linux-gcc-stage-\\.+% + trace: enumerate_machines: re-bootstrapping $m/linux-gcc-stage/: new machine + trace: enumerate_machines: btrfs property set -ts $m/linux-gcc-stage ro false + trace: enumerate_machines: btrfs subvolume delete $m/linux-gcc-stage + EOE + + : re-bootstrap-toolchain + : + $* 124 >>EOO 2>>~"%EOE%d" + : 1 + id: linux-gcc-1.1 + name: linux-gcc + summary: Linux with GCC + EOO + %trace: enumerate_machines: btrfs subvolume snapshot $m/linux-gcc-1.1 $m/linux-gcc-stage-\\.+% + trace: enumerate_machines: re-bootstrapping $m/linux-gcc-stage/: new toolchain + trace: enumerate_machines: btrfs property set -ts $m/linux-gcc-stage ro false + trace: enumerate_machines: btrfs subvolume delete $m/linux-gcc-stage + EOE + + sed -i -e 's/^(bbot-version):.*/\1: 0/' $m/linux-gcc-stage/manifest + + : re-bootstrap-bbot + : + $* 124 >>EOO 2>>~"%EOE%d" + : 1 + id: linux-gcc-1.1 + name: linux-gcc + summary: Linux with GCC + EOO + %trace: enumerate_machines: btrfs subvolume snapshot $m/linux-gcc-1.1 $m/linux-gcc-stage-\\.+% + trace: enumerate_machines: re-bootstrapping $m/linux-gcc-stage/: new bbot + trace: enumerate_machines: btrfs property set -ts $m/linux-gcc-stage ro false + trace: enumerate_machines: btrfs subvolume delete $m/linux-gcc-stage + EOE + + sed -i -e 's/^(bbot-version):.*/\1: 99999900/' $m/linux-gcc-stage/manifest + + : re-bootstrap-bbot-newer + : + $* 124 2>>~"%EOE%d" + %trace: enumerate_machines: btrfs subvolume snapshot $m/linux-gcc-1.1 $m/linux-gcc-stage-\\.+% + trace: enumerate_machines: ignoring $m/linux-gcc-stage/: old bbot + %trace: enumerate_machines: btrfs subvolume delete $m/linux-gcc-stage-\\.+% + EOE + + -$rm +} -- cgit v1.1