ctdb-tests: Remove case statement in ctdb stub
[metze/samba/wip.git] / ctdb / tests / eventscripts / stubs / ctdb
1 #!/bin/sh
2
3 prog="ctdb"
4
5 # Print a message and exit.
6 die ()
7 {
8     echo "$1" >&2 ; exit ${2:-1}
9 }
10
11 not_implemented_exit_code=1
12
13 usage ()
14 {
15     cat >&2 <<EOF
16 Usage: $prog [-X] cmd
17
18 A fake CTDB stub that prints items depending on the variables
19 FAKE_CTDB_PNN (default 0) depending on command-line options.
20 EOF
21     exit 1
22 }
23
24 not_implemented ()
25 {
26     echo "${prog}: command \"$1\" not implemented in stub" >&2
27     exit $not_implemented_exit_code
28 }
29
30 # Don't set $POSIXLY_CORRECT here.
31 _temp=$(getopt -n "$prog" -o "Xvhn:" -l help -- "$@") || \
32     usage
33
34 eval set -- "$_temp"
35
36 verbose=false
37 machine_readable=false
38 nodespec=""
39
40 args="$*"
41
42 while true ; do
43     case "$1" in
44         -X) machine_readable=true ; shift ;;
45         -v) verbose=true ; shift ;;
46         -n) nodespec="$2" ; shift 2 ;;
47         --) shift ; break ;;
48         -h|--help|*) usage ;; # * shouldn't happen, so this is reasonable.
49     esac
50 done
51
52 [ $# -ge 1 ] || usage
53
54 setup_tickles ()
55 {
56     # Make sure tickles file exists.
57     tickles_file="$EVENTSCRIPTS_TESTS_VAR_DIR/fake-ctdb/tickles"
58     mkdir -p $(dirname "$tickles_file")
59     touch "$tickles_file"
60 }
61
62 ctdb_gettickles ()
63 {
64     _ip="$1"
65     _port="$2"
66
67     setup_tickles
68
69     echo "|source ip|port|destination ip|port|"
70     while read _src _dst ; do
71         if [ -z "$_ip" -o "$_ip" = "${_dst%:*}" ] ; then
72             if [ -z "$_port" -o "$_port" = "${_dst##*:}" ] ; then
73                 echo "|${_src%:*}|${_src##*:}|${_dst%:*}|${_dst##*:}|"
74             fi
75         fi
76     done <"$tickles_file"
77 }
78
79 ctdb_addtickle ()
80 {
81     _src="$1"
82     _dst="$2"
83
84     setup_tickles
85
86     if [ -n "$_dst" ] ; then
87         echo "${_src} ${_dst}" >>"$tickles_file"
88     else
89         cat >>"$tickles_file"
90     fi
91 }
92
93 ctdb_deltickle ()
94 {
95     _src="$1"
96     _dst="$2"
97
98     setup_tickles
99
100     if [ -n "$_dst" ] ; then
101         _t=$(grep -F -v "${_src} $${_dst}" "$tickles_file")
102     else
103         _t=$(cat "$tickles_file")
104         while read _src _dst ; do
105             _t=$(echo "$_t" | grep -F -v "${_src} ${_dst}")
106         done
107     fi
108     echo "$_t" >"$tickles_file"
109 }
110
111 parse_nodespec ()
112 {
113     if [ "$nodespec" = "all" ] ; then
114         nodes="$(seq 0 $((FAKE_CTDB_NUMNODES - 1)) )"
115     elif [ -n "$nodespec" ] ; then
116         nodes="$(echo $nodespec | sed -e 's@,@ @g')"
117     else
118         node=$(ctdb_pnn)
119     fi
120 }
121
122 # For testing backward compatibility...
123 for i in $CTDB_NOT_IMPLEMENTED ; do
124     if [ "$i" = "$1" ] ; then
125         not_implemented "$i"
126     fi
127 done
128
129 ctdb_pnn ()
130 {
131     # Defaults to 0
132     echo "${FAKE_CTDB_PNN:-0}"
133 }
134
135 ######################################################################
136
137 FAKE_CTDB_NODE_STATE="$FAKE_CTDB_STATE/node-state"
138 FAKE_CTDB_NODES_DISABLED="$FAKE_CTDB_NODE_STATE/0x4"
139
140 ######################################################################
141
142 # NOTE: all nodes share public addresses file
143
144 FAKE_CTDB_IP_LAYOUT="$FAKE_CTDB_STATE/ip-layout"
145
146 ip_reallocate ()
147 {
148     touch "$FAKE_CTDB_IP_LAYOUT"
149
150     (
151         flock 0
152
153         _pa="${CTDB_BASE}/public_addresses"
154
155         if [ ! -s "$FAKE_CTDB_IP_LAYOUT" ] ; then
156             sed -n -e 's@^\([^#][^/]*\)/.*@\1 -1@p' \
157                 "$_pa" >"$FAKE_CTDB_IP_LAYOUT"
158         fi
159
160         _t="${FAKE_CTDB_IP_LAYOUT}.new"
161
162         _flags=""
163         for _i in $(seq 0 $((FAKE_CTDB_NUMNODES - 1)) ) ; do
164             if ls "$FAKE_CTDB_STATE/node-state/"*"/$_i" >/dev/null 2>&1 ; then
165                 # Have non-zero flags
166                 _this=0
167                 for _j in "$FAKE_CTDB_STATE/node-state/"*"/$_i" ; do
168                     _tf="${_j%/*}" # dirname
169                     _f="${_tf##*/}" # basename
170                     _this=$(( $_this | $_f ))
171                 done
172             else
173                 _this="0"
174             fi
175             _flags="${_flags}${_flags:+,}${_this}"
176         done
177         CTDB_TEST_LOGLEVEL=NOTICE \
178             "ctdb_takeover_tests" \
179             "ipalloc" "$_flags" <"$FAKE_CTDB_IP_LAYOUT" |
180             sort >"$_t"
181         mv "$_t" "$FAKE_CTDB_IP_LAYOUT"
182     ) <"$FAKE_CTDB_IP_LAYOUT"
183 }
184
185 ctdb_ip ()
186 {
187     # If nobody has done any IP-fu then generate a layout.
188     [ -f "$FAKE_CTDB_IP_LAYOUT" ] || ip_reallocate
189
190     _mypnn=$(ctdb_pnn)
191
192     if $machine_readable ; then
193         if $verbose ; then
194             echo "|Public IP|Node|ActiveInterface|AvailableInterfaces|ConfiguredInterfaces|"
195         else
196             echo "|Public IP|Node|"
197         fi
198     else
199         echo "Public IPs on node ${_mypnn}"
200     fi
201
202     # Join public addresses file with $FAKE_CTDB_IP_LAYOUT, and
203     # process output line by line...
204     _pa="${CTDB_BASE}/public_addresses"
205     sed -e 's@/@ @' "$_pa" | sort | join - "$FAKE_CTDB_IP_LAYOUT" |
206     while read _ip _bit _ifaces _pnn ; do
207         if $verbose ; then
208             # If more than 1 interface, assume all addresses are on the 1st.
209             _first_iface="${_ifaces%%,*}"
210             # Only show interface if address is on this node.
211             _my_iface=""
212             if [ "$_pnn" = "$_mypnn" ]; then
213                 _my_iface="$_first_iface"
214             fi
215             if $machine_readable ; then
216                 echo "|${_ip}|${_pnn}|${_my_iface}|${_first_iface}|${_ifaces}|"
217             else
218                 echo "${_ip} node[${_pnn}] active[${_my_iface}] available[${_first_iface}] configured[[${_ifaces}]"
219             fi
220         else
221             if $machine_readable ; then
222                 echo "|${_ip}|${_pnn}|"
223             else
224                 echo "${_ip} ${_pnn}"
225             fi
226         fi
227     done
228 }
229
230 ctdb_moveip ()
231 {
232     _ip="$1"
233     _target="$2"
234
235     ip_reallocate  # should be harmless and ensures we have good state
236
237     (
238         flock 0
239
240         _t="${FAKE_CTDB_IP_LAYOUT}.new"
241
242         while read _i _pnn ; do
243             if [ "$_ip" = "$_i" ] ; then
244                 echo "$_i $_target"
245             else
246                 echo "$_i $_pnn"
247             fi
248         done | sort >"$_t"
249         mv "$_t" "$FAKE_CTDB_IP_LAYOUT"
250     ) <"$FAKE_CTDB_IP_LAYOUT"
251 }
252
253 ######################################################################
254
255 ctdb_enable ()
256 {
257     parse_nodespec
258     
259     for _i in $nodes ; do
260         rm -f "${FAKE_CTDB_NODES_DISABLED}/${_i}"
261     done
262
263     ip_reallocate
264 }
265
266 ctdb_disable ()
267 {
268     parse_nodespec
269
270     for _i in $nodes ; do
271         mkdir -p "$FAKE_CTDB_NODES_DISABLED"
272         touch "${FAKE_CTDB_NODES_DISABLED}/${_i}"
273     done
274
275     ip_reallocate
276 }
277
278 ######################################################################
279
280 ctdb_shutdown ()
281 {
282     echo "CTDB says BYE!"
283 }
284
285 ######################################################################
286
287 # This is only used by the NAT and LVS gateway code at the moment, so
288 # use a hack.  Assume that $CTDB_NATGW_NODES or $CTDB_LVS_NODES
289 # contains all nodes in the cluster (which is what current tests
290 # assume).  Use the PNN to find the address from this file.  The NAT
291 # gateway code only used the address, so just mark the node healthy.
292 ctdb_nodestatus ()
293 {
294     echo '|Node|IP|Disconnected|Banned|Disabled|Unhealthy|Stopped|Inactive|PartiallyOnline|ThisNode|'
295     _line=$(( $FAKE_CTDB_PNN + 1 ))
296     _ip=$(sed -e "${_line}p" "${CTDB_NATGW_NODES:-${CTDB_LVS_NODES}}")
297     echo "|${FAKE_CTDB_PNN}|${_ip}|0|0|0|0|0|0|0|Y|"
298 }
299
300 ######################################################################
301
302 ctdb_setvar ()
303 {
304     _var="$1"
305
306     for _i in $FAKE_CTDB_TUNABLES_OK ; do
307         if [ "$_var" = "$_i" ] ; then
308             return 0
309         fi
310     done
311
312     for _i in $FAKE_CTDB_TUNABLES_OBSOLETE ; do
313         if [ "$_var" = "$_i" ] ; then
314             echo "Setting obsolete tunable variable '${_var}'"
315             return 0
316         fi
317     done
318
319     echo "Unable to set tunable variable '${_var}'"
320     return 1
321 }
322
323 ######################################################################
324
325 _t_setup ()
326 {
327     _t_dir="$EVENTSCRIPTS_TESTS_VAR_DIR/fake-ctdb/fake-tdb/$1"
328     mkdir -p "$_t_dir"
329 }
330
331 _t_put ()
332 {
333     echo "$2" >"${_t_dir}/$1"
334 }
335
336 _t_get ()
337 {
338     cat "${_t_dir}/$1"
339 }
340
341 _t_del ()
342 {
343     rm -f "${_t_dir}/$1"
344 }
345
346 ctdb_pstore ()
347 {
348     _t_setup "$1"
349     _t_put "$2" "$3"
350 }
351
352 ctdb_pdelete ()
353 {
354     _t_setup "$1"
355     _t_del "$2"
356 }
357
358 ctdb_pfetch ()
359 {
360     _t_setup "$1"
361     _t_get "$2" >"$3" 2>/dev/null
362 }
363
364 ctdb_ptrans ()
365 {
366     _t_setup "$1"
367
368     while IFS="" read _line ; do
369         _k=$(echo "$_line" | sed -n -e 's@^"\([^"]*\)" "[^"]*"$@\1@p')
370         _v=$(echo "$_line" | sed -e 's@^"[^"]*" "\([^"]*\)"$@\1@')
371         [ -n "$_k" ] || die "ctdb ptrans: bad line \"${line}\""
372         if [ -n "$_v" ] ; then
373             _t_put "$_k" "$_v"
374         else
375             _t_del "$_k"
376         fi
377     done
378 }
379
380 ctdb_catdb ()
381 {
382     _t_setup "$1"
383
384     # This will break on keys with spaces but we don't have any of
385     # those yet.
386     _count=0
387     for _i in "${_t_dir}/"* ; do
388         [ -r "$_i" ] || continue
389         _k="${_i##*/}" # basename
390         _v=$(_t_get "$_k")
391         _kn=$(echo -n "$_k" | wc -c)
392         _vn=$(echo -n "$_v" | wc -c)
393         cat <<EOF
394 key(${_kn}) = "${_k}"
395 dmaster: 0
396 rsn: 1
397 data(${_vn}) = "${_v}"
398
399 EOF
400         _count=$(($_count + 1))
401     done
402
403     echo "Dumped ${_count} records"
404 }
405
406 ######################################################################
407
408 ctdb_ifaces()
409 {
410         _f="${CTDB_BASE}/public_addresses"
411
412         if [ ! -f "$_f" ] ; then
413                 die "Public addresses file \"${_f}\" not found"
414         fi
415
416         # Assume -Y.
417         echo "|Name|LinkStatus|References|"
418         while read _ip _iface ; do
419                 case "_$ip" in
420                 \#*) : ;;
421                 *)
422                         _status=1
423                         # For now assume _iface contains only 1.
424                         if [ -f "{FAKE_CTDB_IFACES_DOWN}/${_iface}" ] ; then
425                                 _status=0
426                         fi
427                         # Nobody looks at references
428                         echo "|${_iface}|${_status}|0|"
429                 esac
430         done <"$_f" |
431         sort -u
432 }
433
434 ctdb_setifacelink ()
435 {
436         _iface="$1"
437         _state="$2"
438
439         # Existence of file means CTDB thinks interface is down.
440         _f="${FAKE_CTDB_IFACES_DOWN}/${_iface}"
441
442         case "$_state" in
443         up)   rm -f "$_f" ;;
444         down) touch "$_f" ;;
445         *) die "ctdb setifacelink: unsupported interface status ${_state}" ;;
446         esac
447 }
448
449 ######################################################################
450
451 ctdb_checktcpport ()
452 {
453         _port="$1"
454
455         for _i in $FAKE_TCP_LISTEN ; do
456                 if [ "$_port" = "${_i##*:}" ] ; then
457                         exit 98
458                 fi
459         done
460
461         exit 0
462 }
463
464 ctdb_gratarp ()
465 {
466         # Do nothing for now
467         :
468 }
469
470 ######################################################################
471
472 cmd="$1"
473 shift
474
475 func="ctdb_${cmd}"
476
477 # This could inadvertently run an external function instead of a local
478 # function.  However, this can only happen if testing a script
479 # containing a new ctdb command that is not implemented, so this is
480 # unlikely to do harm.
481 if type "$func" >/dev/null 2>&1 ; then
482         "$func" "$@"
483 else
484         not_implemented "$cmd"
485 fi