5 export CTDB_TEST_MODE
="yes"
7 # Following 2 lines may be modified by installation script
8 CTDB_TESTS_ARE_INSTALLED
=false
9 CTDB_TEST_DIR
=$
(dirname "$0")
10 export CTDB_TESTS_ARE_INSTALLED CTDB_TEST_DIR
12 export TEST_SCRIPTS_DIR
="${CTDB_TEST_DIR}/scripts"
14 .
"${TEST_SCRIPTS_DIR}/common.sh"
16 if ! $CTDB_TESTS_ARE_INSTALLED ; then
17 hdir
="$CTDB_SCRIPTS_HELPER_BINDIR"
18 export CTDB_EVENTD
="${hdir}/ctdb-eventd"
19 export CTDB_EVENT_HELPER
="${hdir}/ctdb-event"
20 export CTDB_LOCK_HELPER
="${hdir}/ctdb_lock_helper"
21 export CTDB_RECOVERY_HELPER
="${hdir}/ctdb_recovery_helper"
22 export CTDB_TAKEOVER_HELPER
="${hdir}/ctdb_takeover_helper"
23 export CTDB_CLUSTER_MUTEX_HELPER
="${hdir}/ctdb_mutex_fcntl_helper"
26 ########################################
28 # If the given IP is hosted then print 2 items: maskbits and iface
38 _t
=$
(ip addr show to
"${_addr}/${_bits}")
48 for _i
in $
(seq 0 $
((_num_nodes
- 1)) ) ; do
50 _j
=$
(printf "%04x" $
((0x5f00 + 1 + _i
)) )
51 _node_ip
="fd00::5357:${_j}"
52 if have_ip
"$_node_ip" ; then
56 ERROR: ${_node_ip} not on an interface, please add it
62 _d
=$
(( 1 + (_i
% 100) ))
63 echo "127.0.${_c}.${_d}"
67 # Fail if we don't have all of the IPv6 addresses assigned
71 setup_public_addresses
()
77 for _i
in $
(seq 0 $
((_num_nodes
- 1)) ) ; do
78 if [ "$_i" -eq "$_node_no_ips" ] ; then
82 # 2 public addresses on most nodes, just to make
85 printf 'fc00:10::1:%x/64 lo\n' $
((1 + _i
))
86 printf 'fc00:10::2:%x/64 lo\n' $
((1 + _i
))
88 _c1
=$
(( 100 + (_i
/ 100) ))
89 _c2
=$
(( 200 + (_i
/ 100) ))
90 _d
=$
(( 1 + (_i
% 100) ))
91 printf '192.168.%d.%d/24 lo\n' "$_c1" "$_d"
92 printf '192.168.%d.%d/24 lo\n' "$_c2" "$_d"
97 setup_socket_wrapper
()
99 _socket_wrapper_so
="$1"
101 _so
="${directory}/libsocket-wrapper.so"
102 if [ ! -f "$_socket_wrapper_so" ] ; then
103 die
"$0 setup: Unable to find ${_socket_wrapper_so}"
106 # Find absolute path if only relative is given
107 case "$_socket_wrapper_so" in
109 *) _socket_wrapper_so
="${PWD}/${_socket_wrapper_so}" ;;
113 ln -s "$_socket_wrapper_so" "$_so"
120 local_daemons_setup_usage
()
123 $0 <directory> setup [ <options>... ]
126 -F Disable failover (default: failover enabled)
127 -N <file> Nodes file (default: automatically generated)
128 -n <num> Number of nodes (default: 3)
129 -P <file> Public addresses file (default: automatically generated)
130 -R Use a command for the recovery lock (default: use a file)
131 -r <time> Like -R and set recheck interval to <time> (default: use a file)
132 -S <library> Socket wrapper shared library to preload (default: none)
133 -6 Generate IPv6 IPs for nodes, public addresses (default: IPv4)
139 local_daemons_setup
()
141 _disable_failover
=false
144 _public_addresses_file
=""
145 _recovery_lock_use_command
=false
146 _recovery_lock_recheck_interval
=""
152 while getopts "FN:n:P:Rr:S:6h?" _opt
; do
154 F
) _disable_failover
=true
;;
155 N
) _nodes_file
="$OPTARG" ;;
156 n
) _num_nodes
="$OPTARG" ;;
157 P
) _public_addresses_file
="$OPTARG" ;;
158 R
) _recovery_lock_use_command
=true
;;
159 r
) _recovery_lock_use_command
=true
160 _recovery_lock_recheck_interval
="$OPTARG"
162 S
) _socket_wrapper
="$OPTARG" ;;
164 \?|h
) local_daemons_setup_usage
;;
167 shift $
((OPTIND
- 1))
169 mkdir
-p "$directory"
171 _nodes_all
="${directory}/nodes"
172 if [ -n "$_nodes_file" ] ; then
173 cp "$_nodes_file" "$_nodes_all"
175 setup_nodes
"$_num_nodes" $_use_ipv6 >"$_nodes_all"
178 # If there are (strictly) greater than 2 nodes then we'll
179 # "randomly" choose a node to have no public addresses
181 if [ "$_num_nodes" -gt 2 ] ; then
182 _node_no_ips
=$
(($$
% _num_nodes
))
185 _public_addresses_all
="${directory}/public_addresses"
186 if [ -n "$_public_addresses_file" ] ; then
187 cp "$_public_addresses_file" "$_public_addresses_all"
189 setup_public_addresses
"$_num_nodes" \
191 $_use_ipv6 >"$_public_addresses_all"
194 _recovery_lock_dir
="${directory}/shared/.ctdb"
195 mkdir
-p "$_recovery_lock_dir"
196 _recovery_lock
="${_recovery_lock_dir}/rec.lock"
197 if $_recovery_lock_use_command ; then
198 _helper
="${CTDB_SCRIPTS_HELPER_BINDIR}/ctdb_mutex_fcntl_helper"
199 _t
="! ${_helper} ${_recovery_lock}"
200 if [ -n "$_recovery_lock_recheck_interval" ] ; then
201 _t
="${_t} ${_recovery_lock_recheck_interval}"
206 if [ -n "$_socket_wrapper" ] ; then
207 setup_socket_wrapper
"$_socket_wrapper"
210 for _n
in $
(seq 0 $
((_num_nodes
- 1))) ; do
211 # CTDB_TEST_SUITE_DIR needs to be correctly set so
212 # setup_ctdb_base() finds the etc-ctdb/ subdirectory
213 # and the test event script is correctly installed
214 # shellcheck disable=SC2034
215 CTDB_TEST_SUITE_DIR
="$CTDB_TEST_DIR" \
216 setup_ctdb_base
"$directory" "node.${_n}" \
217 functions notify.sh debug-hung-script.sh
219 cp "$_nodes_all" "${CTDB_BASE}/nodes"
221 _public_addresses
="${CTDB_BASE}/public_addresses"
223 if [ -z "$_public_addresses_file" ] && \
224 [ $_node_no_ips -eq "$_n" ] ; then
225 echo "Node ${_n} will have no public IPs."
226 : >"$_public_addresses"
228 cp "$_public_addresses_all" "$_public_addresses"
231 _node_ip
=$
(sed -n -e "$((_n + 1))p" "$_nodes_all")
233 _db_dir
="${CTDB_BASE}/db"
234 for _d
in "volatile" "persistent" "state" ; do
235 mkdir
-p "${_db_dir}/${_d}"
238 cat >"${CTDB_BASE}/ctdb.conf" <<EOF
240 location = file:${CTDB_BASE}/log.ctdb
244 recovery lock = ${_recovery_lock}
245 node address = ${_node_ip}
248 volatile database directory = ${_db_dir}/volatile
249 persistent database directory = ${_db_dir}/persistent
250 state database directory = ${_db_dir}/state
253 disabled = ${_disable_failover}
256 debug script = debug-hung-script.sh
261 local_daemons_ssh_usage
()
264 usage: $0 <directory> ssh [ -n ] <ip> <command>
272 if [ $# -lt 2 ] ; then
273 local_daemons_ssh_usage
276 # Only try to respect ssh -n option, others can't be used so discard them
278 while getopts "nh?" _opt
; do
280 n
) _close_stdin
=true
;;
281 \?|h
) local_daemons_ssh_usage
;;
285 shift $
((OPTIND
- 1))
287 if [ $# -lt 2 ] ; then
288 local_daemons_ssh_usage
291 _nodes
="${directory}/nodes"
293 # IP adress of node. onnode can pass hostnames but not in these tests
298 # Determine the correct CTDB base directory
299 _num
=$
(awk -v ip
="$_ip" '$1 == ip { print NR }' "$_nodes")
301 export CTDB_BASE
="${directory}/node.${_node}"
303 if [ ! -d "$CTDB_BASE" ] ; then
304 die
"$0 ssh: Unable to find base for node ${_ip}"
307 if $_close_stdin ; then
308 exec sh
-c "$*" </dev
/null
316 # onnode will execute this, which fakes ssh against local daemons
317 export ONNODE_SSH
="${0} ${directory} ssh"
319 # onnode just needs the nodes file, so use the common one
320 export CTDB_BASE
="$directory"
323 local_daemons_generic_usage
()
326 usage: $0 <directory> ${1} <nodes>
328 <nodes> can be "all", a node number or any specification supported by onnode
334 local_daemons_start_socket_wrapper
()
336 _so
="${directory}/libsocket-wrapper.so"
339 if [ -d "$_d" ] && [ -f "$_so" ] ; then
340 export SOCKET_WRAPPER_DIR
="$_d"
341 export LD_PRELOAD
="$_so"
345 local_daemons_start
()
347 if [ $# -ne 1 ] ||
[ "$1" = "-h" ] ; then
348 local_daemons_generic_usage
"start"
351 local_daemons_start_socket_wrapper
357 onnode
-i "$_nodes" "${VALGRIND:-} ctdbd"
360 local_daemons_stop
()
362 if [ $# -ne 1 ] ||
[ "$1" = "-h" ] ; then
363 local_daemons_generic_usage
"stop"
370 onnode
-p "$_nodes" \
371 "if [ -e \"\${CTDB_BASE}/run/ctdbd.pid\" ] ; then \
372 ${CTDB:-${VALGRIND:-} ctdb} shutdown ; \
376 local_daemons_onnode_usage
()
379 usage: $0 <directory> onnode <nodes> <command>...
381 <nodes> can be "all", a node number or any specification supported by onnode
387 local_daemons_onnode
()
389 if [ $# -lt 2 ] ||
[ "$1" = "-h" ] ; then
390 local_daemons_onnode_usage
398 onnode
"$_nodes" "$@"
401 local_daemons_print_socket
()
403 if [ $# -ne 1 ] ||
[ "$1" = "-h" ] ; then
404 local_daemons_generic_usage
"print-socket"
412 _path
="${CTDB_SCRIPTS_HELPER_BINDIR}/ctdb-path"
413 onnode
-q "$_nodes" "${VALGRIND:-} ${_path} socket ctdbd"
416 local_daemons_print_log
()
418 if [ $# -ne 1 ] ||
[ "$1" = "-h" ] ; then
419 local_daemons_generic_usage
"print-log"
427 # shellcheck disable=SC2016
428 # $CTDB_BASE must only be expanded under onnode, not in top-level shell
429 onnode
-q "$_nodes" 'echo ${CTDB_BASE}/log.ctdb' |
430 while IFS
='' read -r _l
; do
431 _dir
=$
(dirname "$_l")
432 _node
=$
(basename "$_dir")
433 # Add fake hostname after date and time, which are the
434 # first 2 words on each line
435 sed -e "s|^\\([^ ][^ ]* [^ ][^ ]*\\)|\\1 ${_node}|" "$_l"
441 local_daemons_tail_log
()
443 if [ $# -ne 1 ] ||
[ "$1" = "-h" ] ; then
444 local_daemons_generic_usage
"tail-log"
452 # shellcheck disable=SC2016,SC2046
453 # $CTDB_BASE must only be expanded under onnode, not in top-level shell
454 # Intentional word splitting to separate log filenames
455 tail -f $
(onnode
-q "$_nodes" 'echo ${CTDB_BASE}/log.ctdb')
461 usage: $0 <directory> <command> [ <options>... ]
464 setup Set up daemon configuration according to given options
465 start Start specified daemon(s)
466 stop Stop specified daemon(s)
467 onnode Run a command in the environment of specified daemon(s)
468 print-socket Print the Unix domain socket used by specified daemon(s)
469 print-log Print logs for specified daemon(s) to stdout
470 tail-log Follow logs for specified daemon(s) to stdout
472 All commands use <directory> for daemon configuration
474 Run command with -h option to see per-command usage
480 if [ $# -lt 2 ] ; then
489 setup
) local_daemons_setup
"$@" ;;
490 ssh) local_daemons_ssh
"$@" ;; # Internal, not shown by usage()
491 start
) local_daemons_start
"$@" ;;
492 stop
) local_daemons_stop
"$@" ;;
493 onnode
) local_daemons_onnode
"$@" ;;
494 print-socket
) local_daemons_print_socket
"$@" ;;
495 print-log
) local_daemons_print_log
"$@" ;;
496 tail-log
) local_daemons_tail_log
"$@" ;;