1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or https://opensource.org/licenses/CDDL-1.0.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
24# Use is subject to license terms.
25#
26# Copyright (c) 2020 by Delphix. All rights reserved.
27#
28
29. $STF_SUITE/include/libtest.shlib
30. $STF_SUITE/tests/functional/events/events.cfg
31
32#
33# wait for 'event' to show up in the log 'file'
34function file_wait_event # file event timeout
35{
36	file=$1
37	event=$2
38	timeout=${3:-120}
39
40	SECONDS=0
41
42	until grep -q "^ZEVENT_CLASS=$event" $ZED_DEBUG_LOG ; do
43		if [[ $SECONDS -gt $timeout ]]; then
44			echo file_wait_event exceeded $SECONDS seconds
45			return 1
46		fi
47
48		sleep 1
49	done
50
51	return 0;
52}
53
54#
55# Wait for up to 'timeout' seconds for the 'file' to settle, i.e.
56# not be updated for a period of 'delay' seconds.
57#
58function file_wait # file delay timeout
59{
60	file=$1
61	delay=${2:-3}
62	timeout=${3:-120}
63
64	SECONDS=0
65
66	while [ $(( $(date +%s) - $(stat -c %Y $file) )) -lt $delay ]; do
67		if [[ $SECONDS -gt $timeout ]]; then
68			echo file_wait exceeded $SECONDS seconds
69			return 1
70		fi
71
72		sleep 1
73	done
74
75	return 0;
76}
77
78function run_and_verify
79{
80	typeset event pool
81	set -A events
82
83	while getopts "e:p:" opt; do
84		case $opt in
85		e)
86			events+=("$OPTARG")
87			;;
88		p)
89			pool=$OPTARG
90			;;
91		esac
92	done
93	shift $(($OPTIND - 1))
94
95	pool=${pool:-$TESTPOOL}
96	fullcmd="$1"
97	read -r cmd _ <<<"$fullcmd"
98
99	# If we aren't running zpool or zfs, something is wrong
100	[[ $cmd == "zpool" || $cmd == "zfs" ]] || \
101	    log_fail "run_and_verify called with \"$cmd ($fullcmd)\""
102
103	log_note "Checking events for command: '$fullcmd'"
104
105	# Remove any previous events from the logs.
106	log_must zpool events -c
107	log_must truncate -s 0 $ZED_DEBUG_LOG
108
109	# Run the command as provided.
110	log_must eval "$fullcmd"
111
112	# Collect the new events and verify there are some.
113	sync_all_pools true
114	log_must eval "zpool events >$TMP_EVENTS 2>/dev/null"
115	log_must eval "zpool events -v > $TMP_EVENTS_FULL 2>/dev/null"
116
117	log_must test -s $TMP_EVENTS
118	log_must test -s $TMP_EVENTS_FULL
119
120	# If the only event is history then we don't observe zed debug log
121	if [[ "${events[0]}" != "sysevent.fs.zfs.history_event" ]]; then
122		# wait for all the non-history events to show up in the
123		# debug log, all-debug.sh filters history events.
124		for event in ${events[*]}; do
125			if [[ "$event" == \
126			    "sysevent.fs.zfs.history_event" ]]; then
127				continue
128			fi
129
130			log_must file_wait_event $ZED_DEBUG_LOG "$event"
131		done
132
133		log_must cp $ZED_DEBUG_LOG $TMP_EVENTS_ZED
134		log_must test -s $TMP_EVENTS_ZED
135
136		log_note "Events logged:"
137		grep "^ZEVENT_CLASS" $TMP_EVENTS_ZED
138	fi
139
140	log_note "Events generated:"
141	cat $TMP_EVENTS
142
143	# Verify all the expected events appear in the log.
144	for event in ${events[*]}; do
145
146		# Verify the event is in in the short output.
147		log_must grep -q "$event" $TMP_EVENTS
148
149		# Verify the event is in the verbose output with pool name.
150		log_mustnot awk -v event="$event" -v crit="pool = \"$pool\"" \
151		    'BEGIN{FS="\n"; RS=""} $0 ~ event && $0 ~ crit { exit 1 }' \
152		    $TMP_EVENTS_FULL
153
154		# all-debug.sh filters history events (seen in ZED_DEBUG_LOG)
155		if [ "$event" = "sysevent.fs.zfs.history_event" ]; then
156			continue
157		fi
158
159		# Verify the event was received by the ZED and logged.
160		log_mustnot awk -v event="$event" -v crit="\\nZEVENT_POOL=$pool" \
161		    'BEGIN{FS="\n"; RS=""} $0 ~ event && $0 ~ crit { exit 1 }' \
162		    $TMP_EVENTS_ZED
163	done
164
165	rm -f $TMP_EVENTS $TMP_EVENTS_FULL $TMP_EVENTS_ZED
166}
167