Add JSON output support to channel programs

The changes piggyback JSON output support on top of channel programs 
(#6558).  This way the JSON output support is targeted to scripting 
use cases and is easily maintainable since it really only touches 
one function (zfs_do_channel_program()).

This patch ports Joyent's JSON nvlist library from illumos to enable 
easy JSON printing of channel program output nvlist.  To keep the 
delta small I also took advantage of the fact that printing in
zfs_do_channel_program() was almost always done before exiting 
the program.

Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alek Pinchuk <apinchuk@datto.com>
Closes #7281
This commit is contained in:
Alek P
2018-03-19 15:40:58 -04:00
committed by Brian Behlendorf
parent a76f3d0437
commit 272b5d730f
13 changed files with 639 additions and 11 deletions
+4
View File
@@ -177,6 +177,10 @@ tests = ['zfs_mount_001_pos', 'zfs_mount_002_pos', 'zfs_mount_003_pos',
'zfs_mount_encrypted', 'zfs_mount_remount']
tags = ['functional', 'cli_root', 'zfs_mount']
[tests/functional/cli_root/zfs_program]
tests = ['zfs_program_json']
tags = ['functional', 'cli_root', 'zfs_program']
[tests/functional/cli_root/zfs_promote]
tests = ['zfs_promote_001_pos', 'zfs_promote_002_pos', 'zfs_promote_003_pos',
'zfs_promote_004_pos', 'zfs_promote_005_pos', 'zfs_promote_006_neg',
@@ -16,6 +16,7 @@ SUBDIRS = \
zfs_inherit \
zfs_load-key \
zfs_mount \
zfs_program \
zfs_promote \
zfs_property \
zfs_receive \
@@ -0,0 +1,5 @@
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_program
dist_pkgdata_SCRIPTS = \
setup.ksh \
cleanup.ksh \
zfs_program_json.ksh
@@ -0,0 +1,30 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
. $STF_SUITE/include/libtest.shlib
default_cleanup
@@ -0,0 +1,32 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
. $STF_SUITE/include/libtest.shlib
DISK=${DISKS%% *}
default_setup $DISK
@@ -0,0 +1,132 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# 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 is of the CDDL is also available via the Internet
# at http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2018 Datto Inc.
#
. $STF_SUITE/include/libtest.shlib
#
# DESCRIPTION:
#
# STRATEGY:
# 1. Compare JSON output formatting for a channel program to template
# 2. Using bad command line option (-Z) gives correct error output
#
verify_runnable "both"
function cleanup
{
log_must zfs destroy $TESTDS
return 0
}
log_onexit cleanup
log_assert "Channel programs output valid JSON"
TESTDS="$TESTPOOL/zcp-json"
log_must zfs create $TESTDS
TESTZCP="/$TESTDS/zfs_rlist.zcp"
cat > "$TESTZCP" << EOF
succeeded = {}
failed = {}
function list_recursive(root, prop)
for child in zfs.list.children(root) do
list_recursive(child, prop)
end
val, src = zfs.get_prop(root, prop)
if (val == nil) then
failed[root] = val
else
succeeded[root] = val
end
end
args = ...
argv = args["argv"]
list_recursive(argv[1], argv[2])
results = {}
results["succeeded"] = succeeded
results["failed"] = failed
return results
EOF
# 1. Compare JSON output formatting for a channel program to template
typeset -a pos_cmds=("recordsize" "type")
typeset -a pos_cmds_out=(
"{
\"return\": {
\"failed\": {},
\"succeeded\": {
\"$TESTDS\": 131072
}
}
}"
"{
\"return\": {
\"failed\": {},
\"succeeded\": {
\"$TESTDS\": \"filesystem\"
}
}
}")
typeset -i cnt=0
typeset cmd
for cmd in ${pos_cmds[@]}; do
log_must zfs program $TESTPOOL $TESTZCP $TESTDS $cmd 2>&1
log_must zfs program $TESTPOOL -j $TESTZCP $TESTDS $cmd 2>&1
# json.tool is needed to guarantee consistent ordering of fields
# sed is needed to trim trailing space in CentOS 6's json.tool output
OUTPUT=$(zfs program $TESTPOOL -j $TESTZCP $TESTDS $cmd 2>&1 | python -m json.tool | sed 's/[[:space:]]*$//')
if [ "$OUTPUT" != "${pos_cmds_out[$cnt]}" ]; then
log_note "Got :$OUTPUT"
log_note "Expected:${pos_cmds_out[$cnt]}"
log_fail "Unexpected channel program output";
fi
cnt=$((cnt + 1))
done
# 2. Using bad command line option (-Z) gives correct error output
typeset -a neg_cmds=("-Z")
typeset -a neg_cmds_out=(
"invalid option 'Z'
usage:
program [-jn] [-t <instruction limit>] [-m <memory limit (b)>] <pool> <program file> [lua args...]
For the property list, run: zfs set|get
For the delegated permission list, run: zfs allow|unallow")
cnt=0
for cmd in ${neg_cmds[@]}; do
log_mustnot zfs program $TESTPOOL $TESTZCP $TESTDS $cmd 2>&1
log_mustnot zfs program $TESTPOOL -j $TESTZCP $TESTDS $cmd 2>&1
OUTPUT=$(zfs program $TESTPOOL -j $TESTZCP $TESTDS $cmd 2>&1)
if [ "$OUTPUT" != "${neg_cmds_out[$cnt]}" ]; then
log_note "Got :$OUTPUT"
log_note "Expected:${neg_cmds_out[$cnt]}"
log_fail "Unexpected channel program error output";
fi
cnt=$((cnt + 1))
done
log_pass "Channel programs output valid JSON"