Whamcloud - gitweb
LU-12639 tests: initialize variable sanity 317
[fs/lustre-release.git] / lustre / tests / recovery-mds-scale.sh
1 #!/bin/bash
2 # vim:shiftwidth=4:softtabstop=4:tabstop=4:
3
4 # Was Test 11 in cmd3.
5 # For duration of 24 hours repeatedly failover a random MDS at
6 # 10 minute intervals and verify that no application errors occur.
7
8 # Test runs one of CLIENT_LOAD progs on remote clients.
9 set -e
10
11 ONLY=${ONLY:-"$*"}
12
13 # bug number for skipped test:
14 ALWAYS_EXCEPT="$RECOVERY_MDS_SCALE_EXCEPT"
15 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
16
17 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
18 . $LUSTRE/tests/test-framework.sh
19 init_test_env $@
20 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
21 init_logging
22
23 remote_mds_nodsh && skip_env "remote MDS with nodsh" && exit 0
24 remote_ost_nodsh && skip_env "remote OST with nodsh" && exit 0
25
26 [ -z "$CLIENTS" -o $CLIENTCOUNT -lt 3 ] &&
27     skip_env "need three or more clients" && exit 0
28
29 if [ -z "$SHARED_DIRECTORY" ] || ! check_shared_dir $SHARED_DIRECTORY; then
30     skip_env "SHARED_DIRECTORY should be specified with a shared directory \
31 which is accessable on all of the nodes"
32     exit 0
33 fi
34
35 ERRORS_OK=""    # No application failures should occur during this test.
36
37 if [ "$SLOW" = "no" ]; then
38     DURATION=${DURATION:-$((60 * 30))}
39 else
40     DURATION=${DURATION:-$((60 * 60 * 24))}
41 fi
42 SERVER_FAILOVER_PERIOD=${SERVER_FAILOVER_PERIOD:-$((60 * 10))} # 10 minutes
43
44 MINSLEEP=${MINSLEEP:-120}
45 REQFAIL_PERCENT=${REQFAIL_PERCENT:-3}    # bug17839 comment 62
46 # round up the result of integer division: C=(A + (B - 1)) / B
47 REQFAIL=${REQFAIL:-$(((DURATION * REQFAIL_PERCENT + (SERVER_FAILOVER_PERIOD *
48         100 - 1 )) / SERVER_FAILOVER_PERIOD / 100))}
49
50 END_RUN_FILE=${END_RUN_FILE:-$SHARED_DIRECTORY/end_run_file}
51 LOAD_PID_FILE=${LOAD_PID_FILE:-$TMP/client-load.pid}
52 VMSTAT_PID_FILE=${VMSTAT_PID_FILE:-$TMP/vmstat.pid}
53
54 server_numfailovers () {
55     local facet=$1
56     local var=${facet}_numfailovers
57     local val=0
58
59     [[ ${!var} ]] && val=${!var}
60     echo $val
61 }
62
63 servers_numfailovers () {
64     local facet
65     local var
66
67     for facet in ${MDTS//,/ } ${OSTS//,/ }; do
68         echo "$facet: $(server_numfailovers $facet) times"
69     done
70 }
71
72 summary_and_cleanup () {
73     local rc=$?
74     trap 0
75
76     # Having not empty END_RUN_FILE means the failed loads only
77     if [ -s $END_RUN_FILE ]; then
78         print_end_run_file $END_RUN_FILE
79         rc=1
80     fi
81
82     echo $(date +'%F %H:%M:%S') Terminating clients loads ...
83     echo "$0" >> $END_RUN_FILE
84     local result=PASS
85     [ $rc -eq 0 ] || result=FAIL
86
87     log "Duration:               $DURATION
88 Server failover period: $SERVER_FAILOVER_PERIOD seconds
89 Exited after:           $ELAPSED seconds
90 Number of failovers before exit:
91 $(servers_numfailovers)
92 Status: $result: rc=$rc"
93
94     # stop vmstat on OSS nodes
95     [ "$VMSTAT" ] && stop_process $(comma_list $(osts_nodes)) $VMSTAT_PID_FILE
96
97     # stop the client loads
98     stop_client_loads $NODES_TO_USE $LOAD_PID_FILE
99
100         if [ $rc -ne 0 ]; then
101                 # we are interested in only on failed clients and servers
102                 local failedclients=$(cat $END_RUN_FILE | grep -v $0)
103                 gather_logs $(comma_list $(all_server_nodes) $failedclients)
104         fi
105
106     exit $rc
107 }
108
109 failover_target() {
110     local flavor=${1:-"MDS"}
111     local servers
112     local serverfacet
113     local var
114
115     [ "$flavor" = "MDS" ] && servers=$MDTS || servers=$OSTS
116
117     trap summary_and_cleanup EXIT INT
118
119     # start vmstat on OSS nodes
120     [ "$VMSTAT" ] && start_vmstat $(comma_list $(osts_nodes)) $VMSTAT_PID_FILE
121
122     # start client loads
123     rm -f $END_RUN_FILE
124     start_client_loads $NODES_TO_USE
125
126     echo client loads pids:
127     do_nodesv $NODES_TO_USE "cat $LOAD_PID_FILE" || exit 3
128
129     ELAPSED=0
130     local sleep=0
131     local reqfail=0
132     local it_time_start
133     local start_ts=$(date +%s)
134     local current_ts=$start_ts
135
136     while [ $ELAPSED -lt $DURATION -a ! -e $END_RUN_FILE ]; do
137         # In order to perform the
138         # expected number of failovers, we need to account the following:
139         # 1) the time that has elapsed during the client load checking
140         # 2) time takes for failover
141         it_time_start=$(date +%s)
142
143         serverfacet=$(get_random_entry $servers)
144         var=${serverfacet}_numfailovers
145
146         # Check that our client loads are still running. If any have died,
147         # that means they have died outside of recovery, which is unacceptable.
148         log "==== Checking the clients loads BEFORE failover -- failure NOT OK \
149              ELAPSED=$ELAPSED DURATION=$DURATION PERIOD=$SERVER_FAILOVER_PERIOD"
150         check_client_loads $NODES_TO_USE || exit 4
151
152         log "Wait $serverfacet recovery complete before doing next failover..."
153         if ! wait_recovery_complete $serverfacet; then
154             echo "$serverfacet recovery is not completed!"
155             exit 7
156         fi
157
158         log "Checking clients are in FULL state before doing next failover..."
159         if ! wait_clients_import_state $NODES_TO_USE $serverfacet FULL; then
160             echo "Clients import not FULL, please consider to increase \
161 SERVER_FAILOVER_PERIOD=$SERVER_FAILOVER_PERIOD!"
162         fi
163
164         log "Starting failover on $serverfacet"
165         facet_failover "$serverfacet" || exit 1
166
167         # Check that our client loads are still running during failover.
168         # No application failures should occur.
169         log "==== Checking the clients loads AFTER failover -- failure NOT OK"
170         if ! check_client_loads $NODES_TO_USE; then
171             log "Client load failed during failover. Exiting..."
172             exit 5
173         fi
174
175         # Increment the number of failovers.
176         val=$((${!var} + 1))
177         eval $var=$val
178
179         current_ts=$(date +%s)
180         ELAPSED=$((current_ts - start_ts))
181
182         sleep=$((SERVER_FAILOVER_PERIOD - (current_ts - it_time_start)))
183
184         # Keep counting the number of iterations when
185         # time spent to failover and two client loads check exceeded
186         # the value ( SERVER_FAILOVER_PERIOD - MINSLEEP ).
187         if [ $sleep -lt $MINSLEEP ]; then
188             reqfail=$((reqfail + 1))
189             log "WARNING: failover and two check_client_loads time exceeded \
190 SERVER_FAILOVER_PERIOD - MINSLEEP!
191 Failed to load the filesystem with I/O for a minimum period of \
192 $MINSLEEP $reqfail times ( REQFAIL=$REQFAIL ).
193 This iteration, the load was only applied for sleep=$sleep seconds.
194 Estimated max recovery time: $MAX_RECOV_TIME
195 Probably the hardware is taking excessively long time to boot.
196 Try to increase SERVER_FAILOVER_PERIOD (current is $SERVER_FAILOVER_PERIOD), \
197 bug 20918"
198             [ $reqfail -gt $REQFAIL ] && exit 6
199         fi
200
201         log "$serverfacet has failed over ${!var} times, and counting..."
202
203         [ $((ELAPSED + sleep)) -ge $DURATION ] && break
204
205         if [ $sleep -gt 0 ]; then
206             echo "sleeping $sleep seconds... "
207             sleep $sleep
208         fi
209     done
210     exit 0
211 }
212
213 ################################## Main Flow ###################################
214 build_test_filter
215
216 check_and_setup_lustre
217 rm -rf $DIR/[Rdfs][0-9]*
218
219 MAX_RECOV_TIME=$(max_recovery_time)
220
221 # The test node needs to be insulated from a lustre failure as much as possible,
222 # so not even loading the lustre modules is ideal.
223 # -- umount lustre
224 # -- remove hostname from clients list
225 zconf_umount $HOSTNAME $MOUNT
226 NODES_TO_USE=${NODES_TO_USE:-$CLIENTS}
227 NODES_TO_USE=$(exclude_items_from_list $NODES_TO_USE $HOSTNAME)
228
229 check_progs_installed $NODES_TO_USE ${CLIENT_LOADS[@]}
230
231 MDTS=$(get_facets MDS)
232 OSTS=$(get_facets OST)
233
234 test_failover_mds() {
235     # failover a random MDS
236     failover_target MDS
237 }
238 run_test failover_mds "failover MDS"
239
240 test_failover_ost() {
241     # failover a random OST
242     failover_target OST
243 }
244 run_test failover_ost "failover OST"
245
246 zconf_mount $HOSTNAME $MOUNT || error "mount $MOUNT on $HOSTNAME failed"
247 client_up || error "start client on $HOSTNAME failed"
248
249 complete $SECONDS
250 check_and_cleanup_lustre
251 exit_status