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