summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMike Gerdts <[email protected]>2019-07-16 13:19:24 -0500
committerBrian Behlendorf <[email protected]>2019-07-16 11:19:24 -0700
commitd45d7f08fa56f94fc9577a6578cb411071a42e8d (patch)
treef841ba287b8040cb4930a60dae553b897d1972d8 /tests
parent93e28d661e1d704a9cada86ef2bc4763a6ef3be7 (diff)
Add zfs create dryrun
Adds the ability to sanity check zfs create arguments and to see the value of any additional properties that will local to the dataset. For example, automation that may need to adjust quota on a parent filesystem before creating a volume may call `zfs create -nP -V <size> <volume>` to obtain the value of refreservation. This adds the following options to zfs create: - -n dry-run (no-op) - -v verbose - -P parseable (implies verbose) Reviewed-by: Ryan Moeller <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Matt Ahrens <[email protected]> Reviewed-by: Jerry Jelinek <[email protected]> Signed-off-by: Mike Gerdts <[email protected]> Closes #8974
Diffstat (limited to 'tests')
-rw-r--r--tests/runfiles/linux.run2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am4
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh169
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh165
4 files changed, 338 insertions, 2 deletions
diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run
index 36ab5ef22..4a0e151f4 100644
--- a/tests/runfiles/linux.run
+++ b/tests/runfiles/linux.run
@@ -143,7 +143,7 @@ tests = ['zfs_create_001_pos', 'zfs_create_002_pos', 'zfs_create_003_pos',
'zfs_create_007_pos', 'zfs_create_008_neg', 'zfs_create_009_neg',
'zfs_create_010_neg', 'zfs_create_011_pos', 'zfs_create_012_pos',
'zfs_create_013_pos', 'zfs_create_014_pos', 'zfs_create_encrypted',
- 'zfs_create_crypt_combos']
+ 'zfs_create_crypt_combos', 'zfs_create_dryrun', 'zfs_create_verbose']
tags = ['functional', 'cli_root', 'zfs_create']
[tests/functional/cli_root/zfs_destroy]
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am
index a36d02161..cb65507ae 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am
@@ -17,7 +17,9 @@ dist_pkgdata_SCRIPTS = \
zfs_create_013_pos.ksh \
zfs_create_014_pos.ksh \
zfs_create_encrypted.ksh \
- zfs_create_crypt_combos.ksh
+ zfs_create_crypt_combos.ksh \
+ zfs_create_dryrun.ksh \
+ zfs_create_verbose.ksh
dist_pkgdata_DATA = \
properties.kshlib \
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh
new file mode 100755
index 000000000..64b8296f4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh
@@ -0,0 +1,169 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs create -n should perform basic sanity checking but should never create a
+# dataset. If -v and/or -P are used, it should verbose about what would be
+# created if sanity checks pass.
+#
+# STRATEGY:
+# 1. Attempt to create a file system and a volume using various combinations of
+# -n with -v and -P.
+#
+
+verify_runnable "both"
+
+#
+# Verifies that valid commands with -n and without -[vP]:
+# - succeed
+# - do not create a dataset
+# - do not generate output
+#
+function dry_create_no_output
+{
+ typeset -a cmd=(zfs create -n "$@")
+
+ log_note "$0: ${cmd[@]}"
+ log_must "${cmd[@]}"
+ datasetexists "$TESTPOOL/$TESTFS1" &&
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ typeset out=$("${cmd[@]}" 2>&1)
+ [[ -z "$out" ]] ||
+ log_fail "unexpected output '$out' from '${cmd[@]}'"
+}
+
+#
+# Verifies that commands with invalid properties or invalid property values
+# - fail
+# - do not create a dataset
+# - generate a message on stderr
+#
+function dry_create_error
+{
+ typeset -a cmd=(zfs create -n "$@")
+
+ log_note "$0: ${cmd[@]}"
+ log_mustnot "${cmd[@]}"
+ datasetexists "$TESTPOOL/$TESTFS1" &&
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ typeset out=$("${cmd[@]}" 2>&1 >/dev/null)
+ [[ -z "$out" ]] &&
+ log_fail "expected an error message but got none from '${cmd[@]}'"
+}
+
+#
+# Verifies that dry-run commands with parseable output
+# - succeed
+# - do not create datasets
+# - generate parseable output on stdout
+# - output matches expectations
+#
+function dry_create_parseable
+{
+ typeset -n exp=$1
+ shift
+ typeset -a cmd=(zfs create -Pn "$@")
+ typeset ds=${cmd[${#cmd[@]} - 1]}
+ typeset out
+ typeset -a toks
+ typeset -a props
+ typeset found_create=false
+
+ log_note "$0: ${cmd[@]}"
+ out=$("${cmd[@]}")
+ (( $? == 0 )) ||
+ log_fail "unexpected failure getting stdout from '${cmd[@]}'"
+ datasetexists "$TESTPOOL/$TESTFS1" &&
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ echo "$out" | while IFS=$'\t' read -A toks; do
+ log_note "verifying ${toks[@]}"
+ case ${toks[0]} in
+ create)
+ log_must test "${#toks[@]}" -eq 2
+ log_must test "${toks[1]}" == "$ds"
+ found_create="yes, I found create"
+ ;;
+ property)
+ log_must test "${#toks[@]}" -eq 3
+ typeset prop=${toks[1]}
+ typeset val=${toks[2]}
+ if [[ -z "${exp[$prop]}" ]]; then
+ log_fail "unexpectedly got property '$prop'"
+ fi
+ # We may not know the exact value a property will take
+ # on. This is the case for at least refreservation.
+ if [[ ${exp[$prop]} != "*" ]]; then
+ log_must test "${exp[$prop]}" == "$val"
+ fi
+ unset exp[$prop]
+ ;;
+ *)
+ log_fail "Unexpected line ${toks[@]}"
+ ;;
+ esac
+ done
+
+ log_must test "$found_create" == "yes, I found create"
+ log_must test "extra props: ${!exp[@]}" == "extra props: "
+}
+
+function cleanup
+{
+ if datasetexists "$TESTPOOL/$TESTFS1"; then
+ log_must zfs destroy -r "$TESTPOOL/$TESTFS1"
+ fi
+}
+log_onexit cleanup
+
+log_assert "zfs create -n creates nothing but can describe what would be" \
+ "created"
+
+# Typical creations should succeed
+dry_create_no_output "$TESTPOOL/$TESTFS1"
+dry_create_no_output -V 10m "$TESTPOOL/$TESTFS1"
+# It shouldn't do a space check right now
+dry_create_no_output -V 100t "$TESTPOOL/$TESTFS1"
+# It shouldn't create parent datasets either
+dry_create_no_output -p "$TESTPOOL/$TESTFS1/$TESTFS2"
+dry_create_no_output -pV 10m "$TESTPOOL/$TESTFS1/$TESTFS2"
+
+# Various invalid properties should be recognized and result in an error
+dry_create_error -o nosuchprop=42 "$TESTPOOL/$TESTFS1"
+dry_create_error -b 1234 -V 10m "$TESTPOOL/$TESTFS1"
+
+# Parseable output should be parseable.
+typeset -A expect
+expect=([compression]=on)
+dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1"
+
+# Sparse volumes should not get a gratuitous refreservation
+expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10)))
+dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1"
+
+# Non-sparse volumes should have refreservation
+expect=(
+ [volblocksize]=4096
+ [volsize]=$((1024 * 1024 * 10))
+ [refreservation]="*"
+)
+dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1"
+
+log_pass "zfs create -n creates nothing but can describe what would be" \
+ "created"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh
new file mode 100755
index 000000000..a07ccc7e9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh
@@ -0,0 +1,165 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs create -P without -n should be verbose about dataset creation.
+#
+# STRATEGY:
+# 1. Attempt to create a file system and a volume using various properties
+# and -P
+# 2. Exercise the combination of -p and -P.
+#
+
+verify_runnable "both"
+
+#
+# Verifies that non dry-run commands with parseable output
+# - succeed
+# - create datasets
+# - generate parseable output on stdout
+# - output matches expectations
+#
+function dry_create_parseable
+{
+ typeset -n exp=$1
+ shift
+ typeset -a cmd=(zfs create -P "$@")
+ typeset ds=${cmd[${#cmd[@]} - 1]}
+ typeset out
+ typeset -a toks
+ typeset -a props
+ typeset found_create=false
+ typeset create_ancestors=
+ typeset opt
+
+ # Parse the arguments to see if -p was used.
+ while getopts :PV:b:ospv opt; do
+ case $opt in
+ p) create_ancestors=needed ;;
+ *) continue ;;
+ esac
+ done
+
+ log_note "$0: ${cmd[@]}"
+ out=$("${cmd[@]}")
+ (( $? == 0 )) ||
+ log_fail "unexpected failure getting stdout from '${cmd[@]}'"
+ datasetexists "$TESTPOOL/$TESTFS1" ||
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ echo "$out" | while IFS=$'\t' read -A toks; do
+ log_note "verifying ${toks[@]}"
+ case ${toks[0]} in
+ create_ancestors)
+ case "$create_ancestors" in
+ needed)
+ log_must test "${toks[1]}" == "$ds"
+ create_ancestors="found ${toks[1]}"
+ ;;
+ found*)
+ log_fail "multiple ancestor creation" \
+ "$create_ancestors and ${toks[1]}"
+ ;;
+ "")
+ log_fail "unexpected create_ancestors"
+ ;;
+ *)
+ log_fail "impossible error: fix the test"
+ ;;
+ esac
+ ;;
+ create)
+ log_must test "${#toks[@]}" -eq 2
+ log_must test "${toks[1]}" == "$ds"
+ found_create="yes, I found create"
+ ;;
+ property)
+ log_must test "${#toks[@]}" -eq 3
+ typeset prop=${toks[1]}
+ typeset val=${toks[2]}
+ if [[ -z "${exp[$prop]}" ]]; then
+ log_fail "unexpectedly got property '$prop'"
+ fi
+ # We may not know the exact value a property will take
+ # on. This is the case for at least refreservation.
+ if [[ ${exp[$prop]} != "*" ]]; then
+ log_must test "${exp[$prop]}" == "$val"
+ fi
+ unset exp[$prop]
+ ;;
+ *)
+ log_fail "Unexpected line ${toks[@]}"
+ ;;
+ esac
+ done
+
+ log_must test "$found_create" == "yes, I found create"
+ log_must test "extra props: ${!exp[@]}" == "extra props: "
+
+ case "$create_ancestors" in
+ "")
+ log_must_busy zfs destroy "$ds"
+ ;;
+ "found $ds")
+ log_must_busy zfs destroy -r "$(echo "$ds" | cut -d/ -f1-2)"
+ ;;
+ needed)
+ log_fail "Expected but did not find create_ancestors"
+ ;;
+ *)
+ log_fail "Unexpected value for create_ancestors:" \
+ "$create_ancestors"
+ ;;
+ esac
+}
+
+function cleanup
+{
+ if datasetexists "$TESTPOOL/$TESTFS1"; then
+ log_must_busy zfs destroy -r "$TESTPOOL/$TESTFS1"
+ fi
+}
+log_onexit cleanup
+
+log_assert "zfs create -v creates datasets verbosely"
+
+# Parseable output should be parseable.
+typeset -A expect
+expect=([compression]=on)
+dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1"
+
+# Ancestor creation with -p should emit relevant line
+expect=([compression]=on)
+dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1"
+expect=([compression]=on)
+dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1/$TESTVOL"
+
+# Sparse volumes should not get a gratuitous refreservation
+expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10)))
+dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1"
+
+# Non-sparse volumes should have refreservation
+expect=(
+ [volblocksize]=4096
+ [volsize]=$((1024 * 1024 * 10))
+ [refreservation]="*"
+)
+dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1"
+
+log_pass "zfs create -v creates datasets verbosely"