4ed99102e5607e6216ed041ae357c882c1c1f9aa
[ambi/samba-autobuild/.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_killtcp ()
63 {
64     while read _src _dst ; do
65         sed -i -e "/^$_dst $_src\$/d" "$FAKE_NETSTAT_TCP_ESTABLISHED_FILE"
66     done
67 }
68
69 parse_nodespec ()
70 {
71     if [ "$nodespec" = "all" ] ; then
72         nodes="$(seq 0 $((FAKE_CTDB_NUMNODES - 1)) )"
73     elif [ -n "$nodespec" ] ; then
74         nodes="$(echo $nodespec | sed -e 's@,@ @g')"
75     else
76         _t=$(ctdb_pnn)
77         nodes="${_t#PNN:}"
78     fi
79 }
80
81 # For testing backward compatibility...
82 for i in $CTDB_NOT_IMPLEMENTED ; do
83     if [ "$i" = "$1" ] ; then
84         not_implemented "$i"
85     fi
86 done
87
88 ctdb_pnn ()
89 {
90     # Defaults to 0
91     echo "PNN:${FAKE_CTDB_PNN:-0}"
92 }
93
94 ######################################################################
95
96 FAKE_CTDB_NODE_STATE="$FAKE_CTDB_STATE/node-state"
97 FAKE_CTDB_NODES_DISABLED="$FAKE_CTDB_NODE_STATE/0x4"
98
99 ######################################################################
100
101 # NOTE: all nodes share $CTDB_PUBLIC_ADDRESSES
102
103 FAKE_CTDB_IP_LAYOUT="$FAKE_CTDB_STATE/ip-layout"
104
105 ip_reallocate ()
106 {
107     touch "$FAKE_CTDB_IP_LAYOUT"
108
109     (
110         flock 0
111
112         _pa="${CTDB_PUBLIC_ADDRESSES:-${CTDB_BASE}/public_addresses}"
113
114         if [ ! -s "$FAKE_CTDB_IP_LAYOUT" ] ; then
115             sed -n -e 's@^\([^#][^/]*\)/.*@\1 -1@p' \
116                 "$_pa" >"$FAKE_CTDB_IP_LAYOUT"
117         fi
118
119         _t="${FAKE_CTDB_IP_LAYOUT}.new"
120
121         _flags=""
122         for _i in $(seq 0 $((FAKE_CTDB_NUMNODES - 1)) ) ; do
123             if ls "$FAKE_CTDB_STATE/node-state/"*"/$_i" >/dev/null 2>&1 ; then
124                 # Have non-zero flags
125                 _this=0
126                 for _j in "$FAKE_CTDB_STATE/node-state/"*"/$_i" ; do
127                     _tf="${_j%/*}" # dirname
128                     _f="${_tf##*/}" # basename
129                     _this=$(( $_this | $_f ))
130                 done
131             else
132                 _this="0"
133             fi
134             _flags="${_flags}${_flags:+,}${_this}"
135         done
136         CTDB_TEST_LOGLEVEL=2 \
137             "ctdb_takeover_tests" \
138             "ipalloc" "$_flags" <"$FAKE_CTDB_IP_LAYOUT" |
139             sort >"$_t"
140         mv "$_t" "$FAKE_CTDB_IP_LAYOUT"
141     ) <"$FAKE_CTDB_IP_LAYOUT"
142 }
143
144 ctdb_ip ()
145 {
146     # If nobody has done any IP-fu then generate a layout.
147     [ -f "$FAKE_CTDB_IP_LAYOUT" ] || ip_reallocate
148
149     _mypnn=$(ctdb_pnn | sed -e 's@PNN:@@')
150
151     if $machine_readable ; then
152         if $verbose ; then
153             echo "|Public IP|Node|ActiveInterface|AvailableInterfaces|ConfiguredInterfaces|"
154         else
155             echo "|Public IP|Node|"
156         fi
157     else
158         echo "Public IPs on node ${_mypnn}"
159     fi
160
161     # Join public addresses file with $FAKE_CTDB_IP_LAYOUT, and
162     # process output line by line...
163     _pa="${CTDB_PUBLIC_ADDRESSES:-${CTDB_BASE}/public_addresses}"
164     sed -e 's@/@ @' "$_pa" | sort | join - "$FAKE_CTDB_IP_LAYOUT" |
165     while read _ip _bit _ifaces _pnn ; do
166         if $verbose ; then
167             # If more than 1 interface, assume all addresses are on the 1st.
168             _first_iface="${_ifaces%%,*}"
169             # Only show interface if address is on this node.
170             _my_iface=""
171             if [ "$_pnn" = "$_mypnn" ]; then
172                 _my_iface="$_first_iface"
173             fi
174             if $machine_readable ; then
175                 echo "|${_ip}|${_pnn}|${_my_iface}|${_first_iface}|${_ifaces}|"
176             else
177                 echo "${_ip} node[${_pnn}] active[${_my_iface}] available[${_first_iface}] configured[[${_ifaces}]"
178             fi
179         else
180             if $machine_readable ; then
181                 echo "|${_ip}|${_pnn}|"
182             else
183                 echo "${_ip} ${_pnn}"
184             fi
185         fi
186     done
187 }
188
189 ctdb_moveip ()
190 {
191     _ip="$1"
192     _target="$2"
193
194     ip_reallocate  # should be harmless and ensures we have good state
195
196     (
197         flock 0
198
199         _t="${FAKE_CTDB_IP_LAYOUT}.new"
200
201         while read _i _pnn ; do
202             if [ "$_ip" = "$_i" ] ; then
203                 echo "$_ip $_target"
204             else
205                 echo "$_ip $_pnn"
206             fi
207         done | sort >"$_t"
208         mv "$_t" "$FAKE_CTDB_IP_LAYOUT"
209     ) <"$FAKE_CTDB_IP_LAYOUT"
210 }
211
212 ######################################################################
213
214 ctdb_enable ()
215 {
216     parse_nodespec
217     
218     for _i in $nodes ; do
219         rm -f "${FAKE_CTDB_NODES_DISABLED}/${_i}"
220     done
221
222     ip_reallocate
223 }
224
225 ctdb_disable ()
226 {
227     parse_nodespec
228
229     for _i in $nodes ; do
230         mkdir -p "$FAKE_CTDB_NODES_DISABLED"
231         touch "${FAKE_CTDB_NODES_DISABLED}/${_i}"
232     done
233
234     ip_reallocate
235 }
236
237 ######################################################################
238
239 ctdb_shutdown ()
240 {
241     echo "CTDB says BYE!"
242 }
243
244 ######################################################################
245
246 FAKE_CTDB_NATGW_STATE="${FAKE_CTDB_STATE}/natgw_state"
247
248 ctdb_setnatgwstate ()
249 {
250     echo "$2" >"$FAKE_CTDB_NATGW_STATE"
251 }
252
253 # This is only used by the NAT gateway code at the moment, so use a
254 # hack.  Assume that $CTDB_NATGW_NODES contains all nodes in the
255 # cluster (which is what current tests assume).  Use the PNN to find
256 # the address from this file.  The NAT gateway code only used the
257 # address, so just mark the node healthy.
258 ctdb_nodestatus ()
259 {
260     echo '|Node|IP|Disconnected|Banned|Disabled|Unhealthy|Stopped|Inactive|PartiallyOnline|ThisNode|'
261     _line=$(( $FAKE_CTDB_PNN + 1 ))
262     _ip=$(sed -e "${_line}p" "$CTDB_NATGW_NODES")
263     echo "|${FAKE_CTDB_PNN}|${_ip}|0|0|0|0|0|0|0|Y|"
264 }
265
266 ######################################################################
267
268 ctdb_setvar ()
269 {
270     shift
271     _var="$1"
272
273     for _i in $FAKE_CTDB_TUNABLES_OK ; do
274         if [ "$_var" = "$_i" ] ; then
275             return 0
276         fi
277     done
278
279     for _i in $FAKE_CTDB_TUNABLES_OBSOLETE ; do
280         if [ "$_var" = "$_i" ] ; then
281             echo "Setting obsolete tunable variable '${_var}'"
282             return 0
283         fi
284     done
285
286     echo "Unable to set tunable variable '${_var}'"
287     return 1
288 }
289
290 ######################################################################
291
292 _t_setup ()
293 {
294     _t_dir="$EVENTSCRIPTS_TESTS_VAR_DIR/fake-ctdb/fake-tdb/$1"
295     mkdir -p "$_t_dir"
296 }
297
298 _t_put ()
299 {
300     echo "$2" >"${_t_dir}/$1"
301 }
302
303 _t_get ()
304 {
305     cat "${_t_dir}/$1"
306 }
307
308 _t_del ()
309 {
310     rm -f "${_t_dir}/$1"
311 }
312
313 ctdb_pstore ()
314 {
315     _t_setup "$2"
316     _t_put "$3" "$4"
317 }
318
319 ctdb_pdelete ()
320 {
321     _t_setup "$2"
322     _t_del "$3"
323 }
324
325 ctdb_pfetch ()
326 {
327     _t_setup "$2"
328     _t_get "$3" >"$4" 2>/dev/null
329 }
330
331 ctdb_ptrans ()
332 {
333     _t_setup "$2"
334
335     while IFS="" read _line ; do
336         _k=$(echo "$_line" | sed -n -e 's@^"\([^"]*\)" "[^"]*"$@\1@p')
337         _v=$(echo "$_line" | sed -e 's@^"[^"]*" "\([^"]*\)"$@\1@')
338         [ -n "$_k" ] || die "ctdb ptrans: bad line \"${line}\""
339         if [ -n "$_v" ] ; then
340             _t_put "$_k" "$_v"
341         else
342             _t_del "$_k"
343         fi
344     done
345 }
346
347 ctdb_catdb ()
348 {
349     _t_setup "$2"
350
351     # This will break on keys with spaces but we don't have any of
352     # those yet.
353     _count=0
354     for _i in "${_t_dir}/"* ; do
355         [ -r "$_i" ] || continue
356         _k="${_i##*/}" # basename
357         _v=$(_t_get "$_k")
358         _kn=$(echo -n "$_k" | wc -c)
359         _vn=$(echo -n "$_v" | wc -c)
360         cat <<EOF
361 key(${_kn}) = "${_k}"
362 dmaster: 0
363 rsn: 1
364 data(${_vn}) = "${_v}"
365
366 EOF
367         _count=$(($_count + 1))
368     done
369
370     echo "Dumped ${_count} records"
371 }
372
373 ######################################################################
374
375 case "$1" in
376     gettickles)
377         setup_tickles
378         echo "|source ip|port|destination ip|port|"
379         while read src dst ; do
380             echo "|${src}|${dst}|"
381         done <"$tickles_file"
382         ;;
383     addtickle)
384         setup_tickles
385         echo "$2 $3" >>"$tickles_file"
386         ;;
387     deltickle)
388         setup_tickles
389         _t=$(grep -F -v "$2 $3" "$tickles_file")
390         echo "$_t" >"$tickles_file"
391         ;;
392     pstore)  ctdb_pstore  "$@" ;;
393     pdelete) ctdb_pdelete "$@" ;;
394     pfetch)  ctdb_pfetch  "$@" ;;
395     ptrans)  ctdb_ptrans  "$@" ;;
396     catdb)   ctdb_catdb   "$@" ;;
397     ifaces)
398         # Assume -Y.
399         echo "|Name|LinkStatus|References|"
400         _f="${CTDB_PUBLIC_ADDRESSES:-${CTDB_BASE}/public_addresses}"
401         if [ -r "$_f" ] ; then
402             while read _ip _iface ; do
403                 case "_$ip" in
404                     \#*) : ;;
405                     *)
406                         _status=1
407                         # For now assume _iface contains only 1.
408                         if [ -f "{FAKE_CTDB_IFACES_DOWN}/${_iface}" ] ; then
409                             _status=0
410                         fi
411                         # Nobody looks at references
412                         echo "|${_iface}|${_status}|0|"
413                 esac
414             done <"$_f" |
415             sort -u
416         fi
417         ;;
418     setifacelink)
419         # Existence of file means CTDB thinks interface is down.
420         _f="${FAKE_CTDB_IFACES_DOWN}/$2"
421         case "$3" in
422             up)   rm -f "$_f" ;;
423             down) touch "$_f" ;;
424             *)
425                 echo "ctdb setifacelink: unsupported interface status $3"
426                 exit 1
427         esac
428         ;;
429     checktcpport)
430         for _i in $FAKE_TCP_LISTEN ; do
431             if [ "$2" = "${_i##*:}" ] ; then
432                 exit 98
433             fi
434         done
435
436         exit 0
437         ;;
438     scriptstatus)
439         $machine_readable || not_implemented "$1, without -X"
440         [ "$2" != "all" ] || not_implemented "scriptstatus all"
441         # For now just assume everything is good.
442         echo "|Type|Name|Code|Status|Start|End|Error Output...|"
443         for _i in "$CTDB_BASE/events.d/"*.* ; do
444             _d1=$(date '+%s.%N')
445             _b="${_i##*/}" # basename
446
447             _f="$FAKE_CTDB_SCRIPTSTATUS/$_b"
448             if [ -r "$_f" ] ; then
449                 read _code _status _err_out <"$_f"
450             else
451                 _code="0"
452                 _status="OK"
453                 if [ ! -x "$_i" ] ; then
454                     _status="DISABLED"
455                     _code="-8"
456                 fi
457                 _err_out=""
458             fi
459             _d2=$(date '+%s.%N')
460             echo "|${2:-monitor}|${_b}|${_code}|${_status}|${_d1}|${_d2}|${_err_out}|"
461         done
462         ;;
463     gratiousarp) : ;;  # Do nothing for now
464     killtcp)       ctdb_killtcp "$@" ;;
465     ip)            ctdb_ip "$@" ;;
466     pnn|xpnn)      ctdb_pnn ;;
467     enable)        ctdb_enable "$@";;
468     disable)       ctdb_disable "$@";;
469     moveip)        ctdb_moveip "$@";;
470     shutdown)      ctdb_shutdown "$@";;
471     setnatgwstate) ctdb_setnatgwstate "$@" ;;
472     setvar)        ctdb_setvar "$@" ;;
473     nodestatus)    ctdb_nodestatus "$@" ;;
474     *) not_implemented "$1" ;;
475 esac