ctdb-tests: Ensure notify.sh is available to local daemons
[samba.git] / ctdb / tests / simple / scripts / local_daemons.bash
1 # If we're not running on a real cluster then we need a local copy of
2 # ctdb (and other stuff) in $PATH and we will use local daemons.
3
4 # Use in-tree binaries if running against local daemons.
5 # Otherwise CTDB need to be installed on all nodes.
6 if [ -n "$ctdb_dir" -a -d "${ctdb_dir}/bin" ] ; then
7         # ctdbd_wrapper is in config/ directory
8         PATH="${ctdb_dir}/bin:${ctdb_dir}/config:${PATH}"
9         hdir="${ctdb_dir}/bin"
10         export CTDB_EVENTD="${hdir}/ctdb_eventd"
11         export CTDB_EVENT_HELPER="${hdir}/ctdb_event"
12         export CTDB_LOCK_HELPER="${hdir}/ctdb_lock_helper"
13         export CTDB_RECOVERY_HELPER="${hdir}/ctdb_recovery_helper"
14         export CTDB_TAKEOVER_HELPER="${hdir}/ctdb_takeover_helper"
15         export CTDB_CLUSTER_MUTEX_HELPER="${hdir}/ctdb_mutex_fcntl_helper"
16 fi
17
18 if [ -n "$TEST_SOCKET_WRAPPER_SO_PATH" ] ; then
19         export LD_PRELOAD="$TEST_SOCKET_WRAPPER_SO_PATH"
20         export SOCKET_WRAPPER_DIR="${SIMPLE_TESTS_VAR_DIR}/sw"
21         mkdir -p "$SOCKET_WRAPPER_DIR"
22 fi
23
24 # onnode will execute this, which fakes ssh against local daemons
25 export ONNODE_SSH="${TEST_SUBDIR}/scripts/ssh_local_daemons.sh"
26
27 #######################################
28
29 # If the given IP is hosted then print 2 items: maskbits and iface
30 have_ip ()
31 {
32         local addr="$1"
33         local bits t
34
35         case "$addr" in
36         *:*) bits=128 ;;
37         *)   bits=32  ;;
38         esac
39
40         t=$(ip addr show to "${addr}/${bits}")
41         [ -n "$t" ]
42 }
43
44 setup_nodes ()
45 {
46         local have_all_ips=true
47         local i
48         for i in $(seq 1 $TEST_LOCAL_DAEMONS) ; do
49                 if [ -n "$CTDB_USE_IPV6" ]; then
50                         local j=$(printf "%02x" $i)
51                         local node_ip="fd00::5357:5f${j}"
52                         if have_ip "$node_ip" ; then
53                                 echo "$node_ip"
54                         else
55                                 cat >&2 <<EOF
56 ERROR: ${node_ip} not on an interface, please add it
57 EOF
58                                 have_all_ips=false
59                         fi
60                 else
61                         local j=$((i + 10))
62                         echo "127.0.0.${j}"
63                 fi
64         done
65
66         # Fail if we don't have all of the IPv6 addresses assigned
67         $have_all_ips
68 }
69
70 setup_public_addresses ()
71 {
72         local pnn_no_ips="$1"
73
74         local i
75         for i in $(seq 1 $TEST_LOCAL_DAEMONS) ; do
76                 if  [ $((i - 1)) -eq $pnn_no_ips ] ; then
77                         continue
78                 fi
79
80                 # 2 public addresses on most nodes, just to make
81                 # things interesting
82                 local j=$((i + TEST_LOCAL_DAEMONS))
83                 if [ -n "$CTDB_USE_IPV6" ]; then
84                         printf "fc00:10::1:%x/64 lo\n" "$i"
85                         printf "fc00:10::1:%x/64 lo\n" "$j"
86                 else
87                         printf "192.168.234.%x/24 lo\n" "$i"
88                         printf "192.168.234.%x/24 lo\n" "$j"
89                 fi
90         done
91 }
92
93 setup_ctdb ()
94 {
95         local no_public_addresses=false
96         local no_event_scripts=false
97         case "$1" in
98         --no-public-addresses) no_public_addresses=true ;;
99         --no-event-scripts)    no_event_scripts=true    ;;
100         esac
101
102         nodes_file="${SIMPLE_TESTS_VAR_DIR}/nodes"
103         setup_nodes >"$nodes_file" || return 1
104
105         # If there are (strictly) greater than 2 nodes then we'll
106         # randomly choose a node to have no public addresses
107         local pnn_no_ips=-1
108         if [ $TEST_LOCAL_DAEMONS -gt 2 ] ; then
109                 pnn_no_ips=$((RANDOM % TEST_LOCAL_DAEMONS))
110         fi
111
112         local public_addresses_all="${SIMPLE_TESTS_VAR_DIR}/public_addresses"
113         setup_public_addresses $pnn_no_ips >"$public_addresses_all"
114
115         local pnn
116         for pnn in $(seq 0 $(($TEST_LOCAL_DAEMONS - 1))) ; do
117                 setup_ctdb_base "$SIMPLE_TESTS_VAR_DIR" "node.${pnn}" \
118                                 functions notify.sh
119
120                 cp "$nodes_file" "${CTDB_BASE}/nodes"
121
122                 local public_addresses="${CTDB_BASE}/public_addresses"
123
124                 if  $no_public_addresses || [ $pnn_no_ips -eq $pnn ] ; then
125                         echo "Node ${pnn} will have no public IPs."
126                         : >"$public_addresses"
127                 else
128                         cp "$public_addresses_all" "$public_addresses"
129                 fi
130
131                 local node_ip=$(sed -n -e "$(($pnn + 1))p" "$nodes_file")
132
133                 local db_dir="${CTDB_BASE}/db"
134                 mkdir -p "${db_dir}/persistent"
135
136                 if $no_event_scripts ; then
137                         rm -vf "${CTDB_BASE}/events.d/"*
138                 fi
139
140                 cat >"${CTDB_BASE}/ctdbd.conf" <<EOF
141 CTDB_RECOVERY_LOCK="${SIMPLE_TESTS_VAR_DIR}/rec.lock"
142 CTDB_NODE_ADDRESS="${node_ip}"
143 CTDB_LOGGING="file:${CTDB_BASE}/log.ctdb"
144 CTDB_DEBUGLEVEL=INFO
145 CTDB_DBDIR="${db_dir}"
146 CTDB_DBDIR_PERSISTENT="${db_dir}/persistent"
147 CTDB_DBDIR_STATE="${db_dir}/state"
148 CTDB_NOSETSCHED=yes
149 EOF
150         done
151 }
152
153 start_ctdb_1 ()
154 {
155         local pnn="$1"
156
157         CTDBD="${VALGRIND} ctdbd --sloppy-start --nopublicipcheck" \
158              onnode "$pnn" ctdbd_wrapper start
159 }
160
161 daemons_start ()
162 {
163     echo "Starting $TEST_LOCAL_DAEMONS ctdb daemons..."
164
165     local pnn
166     for pnn in $(seq 0 $(($TEST_LOCAL_DAEMONS - 1))) ; do
167         start_ctdb_1 "$pnn"
168     done
169 }
170
171 stop_ctdb_1 ()
172 {
173         local pnn="$1"
174
175         onnode "$pnn" ctdbd_wrapper stop
176 }
177
178 daemons_stop ()
179 {
180     echo "Stopping $TEST_LOCAL_DAEMONS ctdb daemons..."
181
182     local pnn
183     for pnn in $(seq 0 $(($TEST_LOCAL_DAEMONS - 1))) ; do
184         stop_ctdb_1 "$pnn"
185     done
186
187     rm -rf "${SIMPLE_TESTS_VAR_DIR}/test.db"
188 }
189
190 restart_ctdb_1 ()
191 {
192         stop_ctdb_1 "$1"
193         start_ctdb_1 "$1"
194 }
195
196 maybe_stop_ctdb ()
197 {
198     daemons_stop
199 }
200
201 ctdb_stop_all ()
202 {
203         daemons_stop
204 }
205
206 _ctdb_start_all ()
207 {
208         daemons_start
209 }
210
211 ps_ctdbd ()
212 {
213         # If this fails to find processes then the tests fails, so
214         # look at full command-line so this will work with valgrind.
215         # Note that the output could be generated with pgrep's -a
216         # option but it doesn't exist in older versions.
217         ps -p $(pgrep -f '\<ctdbd\>' | xargs | sed -e 's| |,|g') -o args ww
218         echo
219 }
220
221 # onnode will use CTDB_BASES to help the ctdb tool connection to each
222 # daemon
223 export CTDB_BASES=""
224 for i in $(seq 0 $(($TEST_LOCAL_DAEMONS - 1))) ; do
225         b="${SIMPLE_TESTS_VAR_DIR}/node.${i}"
226         CTDB_BASES="${CTDB_BASES}${CTDB_BASES:+ }${b}"
227 done
228
229 # Need a default CTDB_BASE for onnode (to find the functions file).
230 # Any node will do, so pick the 1st...
231 export CTDB_BASE="${CTDB_BASES%% *}"