@@ -15,6 +15,10 @@ HA_NETWORK_V6_ARRAY[1]="2001:db8:20::/64"
15
15
BEHAVE_CASE_DIR=" $( dirname $0 ) /features/"
16
16
BEHAVE_CASE_EXCLUDE=" sbd"
17
17
18
+ declare -a hanode_list_to_form_cluster
19
+ declare -a hanode_list_new_members
20
+ declare -a hanode_list_current_cluster
21
+
18
22
read -r -d ' ' SSHD_CONFIG_AZURE << EOM
19
23
PermitRootLogin no
20
24
AuthorizedKeysFile .ssh/authorized_keys
@@ -110,22 +114,28 @@ Users can make the code change under crmsh.git including test cases. This tool w
110
114
111
115
OPTIONS:
112
116
-h, --help Show this help message and exit
113
- -l List existing functional test cases and exit
114
- -n NUM Only setup a cluster with NUM nodes(containers)
117
+ -l List existing functional test cases and exit
118
+ -n NUM NUM of nodes(containers) with the node name 'hanode{1.. $ NUM}'
115
119
-x Don't config corosync on containers(with -n option)
116
120
-d Cleanup the cluster containers
117
- -u Create normal users, and Azure like ssh environment
118
- -q Create a qnetd node(with -n and -x option)
121
+ -u Run test as a normal user like in Public Cloud, eg. Azure
122
+ -q Create a qnetd node(with -n and -x option, and named 'qnetd-node' )
119
123
120
124
EXAMPLES:
121
125
To launch 2 nodes with the running cluster with the very basic corosync.conf
122
126
# crmsh.git/test/run-functional-tests -n 2
123
127
124
- To launch 2 nodes without the cluster stack running to play with "crm cluster init/join"
125
- # crmsh.git/run-functional-tests -n 2 -x
128
+ To grow more cluster nodes with a bigger number than '2' in the above example
129
+ # crmsh.git/test/run-functional-tests -n 5
130
+
131
+ To launch 2 bare nodes, eg. to play with "crm cluster init/join"
132
+ # crmsh.git/test/run-functional-tests -n 2 -x
133
+
134
+ To grow more bare nodes
135
+ # crmsh.git/test/run-functional-tests -n 7 -x
126
136
127
- To launch 2 nodes without the cluster stack running, and a qnetd node(named 'qnetd-node')
128
- # crmsh.git/run-functional-tests -n 2 -x -q
137
+ To launch 2 bare nodes besides a qnetd node(named 'qnetd-node')
138
+ # crmsh.git/test/ run-functional-tests -n 2 -x -q
129
139
130
140
To list the existing test cases. Users could add his own new test cases.
131
141
# crmsh.git/test/run-functional-tests -l
@@ -190,7 +200,11 @@ deploy_ha_node() {
190
200
191
201
info " Deploying \" $node_name \" ..."
192
202
podman run --rm -d $podman_options $podman_capabilties $podman_security $CONTAINER_IMAGE > /dev/null
193
- podman network connect ha_network_second $node_name
203
+ if [ $? -ne 0 ]; then
204
+ warning Likely $node_name already exists.
205
+ return
206
+ fi
207
+ podman network connect ha_network_second $node_name
194
208
195
209
if [ " $node_name " != " qnetd-node" ]; then
196
210
rm_qnetd_cmd=" rpm -q corosync-qnetd && rpm -e corosync-qnetd"
@@ -253,43 +267,77 @@ is_podman5_or_newer() {
253
267
fi
254
268
}
255
269
270
+ get_cluster_new_nodes () {
271
+ hanode_list_to_form_cluster=($( podman ps -a --format ' {{.Names}}' | grep hanode| sort -n -k1.7| tr ' \r' ' ' ) )
272
+ hanode_list_current_cluster=($( podman_exec hanode1 " crm node server 2>/dev/null" 2> /dev/null| sort -n -k1.7| tr ' \r' ' ' ) )
273
+ hanode_list_new_members=()
274
+ for element in " ${hanode_list_to_form_cluster[@]} " ; do
275
+ if ! [[ " ${hanode_list_current_cluster[@]} " =~ " $element " ]]; then
276
+ hanode_list_new_members+=(" $element " )
277
+ fi
278
+ done
279
+ }
280
+
256
281
config_cluster () {
257
- node_num=$#
282
+ get_cluster_new_nodes
283
+
284
+ if [ ${# hanode_list_new_members[@]} -eq 0 ]; then
285
+ return
286
+ else
287
+ info ${# hanode_list_new_members[@]} new node\( s\) " '${hanode_list_new_members[@]} '"
288
+ fi
289
+
258
290
insert_str=" "
259
291
if [[ is_podman5_or_newer ]]; then
260
- container_ip_array=($( podman network inspect $HA_NETWORK_ARRAY | jq -r ' .[] | .containers[] | .interfaces[] | .subnets[] | select(.ipnet | test("^(\\d{1,3}\\.){3}\\d{1,3}\\/\\d+$")) | .ipnet | split("/") | .[0]' ) )
292
+ container_ip_array=($( podman network inspect $HA_NETWORK_ARRAY | jq -r '
293
+ .[] | .containers | to_entries | sort_by(.value.name | capture("hanode(?<num>\\d+)").num | tonumber) |
294
+ .[] | .value.interfaces[] | .subnets[] | select(.ipnet | test("^(\\d{1,3}\\.){3}\\d{1,3}\\/\\d+$")) | .ipnet '
295
+ ) )
261
296
else
297
+ # TODO: to grow nodes, the result need sort by the container name numerically
262
298
container_ip_array=(` podman network inspect $HA_NETWORK_ARRAY -f ' {{range .Containers}}{{printf "%s " .IPv4Address}}{{end}}' ` )
263
299
fi
264
300
265
- for i in $( seq $node_num -1 1) ; do
301
+ for i in $( seq ${ # hanode_list_to_form_cluster[@]} -1 1) ; do
266
302
ip=` echo ${container_ip_array[$((i-1))]} | awk -F/ ' {print $1}' `
267
303
insert_str+=" \\ n\\ tnode {\n\t\tring0_addr: $ip \n\t\tnodeid: $i \n\t}"
268
304
done
269
305
corosync_conf_str=$( sed " /nodelist/a \\ ${insert_str} " <( echo " $COROSYNC_CONF_TEMPLATE " ) )
270
- if [ $node_num -eq 2 ]; then
306
+ if [ ${ # hanode_list_to_form_cluster[@]} -eq 2 ]; then
271
307
corosync_conf_str=$( sed " /corosync_votequorum/a \\\\ ttwo_node: 1" <( echo " $corosync_conf_str " ) )
272
308
fi
309
+ if search_running_container_by_name " qnetd-node" ; then
310
+ info " Generate corosync.conf without qdevice/qnetd for the cluster hanode{1..${# hanode_list_to_form_cluster[@]} }"
311
+ else
312
+ info " Generate corosync.conf for the cluster hanode{1..${# hanode_list_to_form_cluster[@]} }"
313
+ fi
273
314
274
- info " Copy corosync.conf to $* "
275
- for node in $* ; do
276
- if [ $node == $1 ]; then
277
- podman_exec $1 " echo \" $corosync_conf_str \" > > $COROSYNC_CONF "
278
- podman_exec $1 " corosync-keygen -l -k $COROSYNC_AUTH &> /dev/null"
315
+ echo -n " INFO: Copy corosync.conf to all cluster nodes hanode{1.. ${ # hanode_list_to_form_cluster[@]} } "
316
+ for node in ${hanode_list_to_form_cluster[@]} ; do
317
+ if [ $node == " hanode1 " ]; then
318
+ podman_exec " hanode1 " " echo \" $corosync_conf_str \" > $COROSYNC_CONF "
319
+ podman_exec " hanode1 " " corosync-keygen -l -k $COROSYNC_AUTH &> /dev/null"
279
320
else
280
321
while :
281
322
do
282
- podman_exec $1 " ssh -T -o Batchmode=yes $node true &> /dev/null" && break
323
+ podman_exec " hanode1 " " ssh -T -o Batchmode=yes $node true &> /dev/null" && break
283
324
sleep 1
284
325
done
285
- podman_exec $1 " scp -p $COROSYNC_CONF $COROSYNC_AUTH $node :/etc/corosync &> /dev/null"
326
+ podman_exec " hanode1" " scp -p $COROSYNC_CONF $COROSYNC_AUTH $node :/etc/corosync &> /dev/null"
327
+ echo -n " ."
286
328
fi
287
329
done
330
+ echo " Done"
288
331
}
289
332
290
333
291
334
start_cluster () {
292
- for node in $* ; do
335
+ if [ ${# hanode_list_current_cluster[@]} -ne 0 ] && [ ${# hanode_list_new_members[@]} -ne 0 ]; then
336
+ podman_exec hanode1 " corosync-cfgtool -R > /dev/null"
337
+ info On the existing cluster hanode{1..${# hanode_list_current_cluster[@]} }: reloading corosync.conf ... Done
338
+ fi
339
+
340
+ for node in ${hanode_list_new_members[@]} ; do
293
341
podman_exec $node " crm cluster enable && crm cluster start" 1> /dev/null
294
342
if [ " $? " -eq 0 ]; then
295
343
info " Cluster service started on \" $node \" "
@@ -300,34 +348,47 @@ start_cluster() {
300
348
}
301
349
302
350
303
- container_already_exists () {
304
- podman ps -a| grep -q " $1 "
305
- if [ " $? " -eq 0 ]; then
306
- fatal " Container \" $1 \" already running"
307
- fi
351
+ search_running_container_by_name () {
352
+ podman ps -a --format ' {{.Names}}' | grep -q " ^$1 $"
308
353
}
309
354
310
355
311
356
setup_cluster () {
312
- hanodes_arry=()
313
- is_number $1
314
- if [ " $? " -eq 0 ]; then
315
- for i in $( seq 1 $1 ) ; do
316
- hanodes_arry+=(" hanode$i " )
317
- done
357
+ get_cluster_new_nodes
358
+
359
+ hanodes_array=()
360
+ if is_number " $1 " ; then
361
+ # add more nodes after the last node, ordered by the node name
362
+ if [ ${# hanode_list_to_form_cluster[@]} -gt 0 ]; then
363
+ last_node_num=" ${hanode_list_to_form_cluster[-1]: 6} "
364
+ warning Skip creating cluster nodes. Here are the existing ones: hanode{1..${# hanode_list_to_form_cluster[@]} }
365
+ else
366
+ last_node_num=0
367
+ fi
368
+ num_of_new_nodes=$(( $1 - ${# hanode_list_to_form_cluster[@]} ))
369
+ if [ " $num_of_new_nodes " -gt 0 ]; then
370
+ for i in $( seq $(( last_node_num + 1 )) $(( last_node_num + num_of_new_nodes )) ) ; do
371
+ hanodes_array+=(" hanode$i " )
372
+ done
373
+ elif [ " $WITH_QNETD_NODE " -eq 0 ]; then
374
+ return
375
+ fi
318
376
else
319
- hanodes_arry=($* )
377
+ num_of_new_nodes=$#
378
+ hanodes_array=($* )
320
379
fi
321
380
322
- if [ $WITH_QNETD_NODE -eq 1 ]; then
323
- create_node ${hanodes_arry [@]} " qnetd-node"
381
+ if [ " $WITH_QNETD_NODE " -eq 1 ] && ! search_running_container_by_name " qnetd-node " ; then
382
+ create_node ${hanodes_array [@]} " qnetd-node"
324
383
else
325
- create_node ${hanodes_arry[@]}
384
+ [ " $WITH_QNETD_NODE " -eq 1 ] && warning Skip creating the existing qnetd-node
385
+ [ " $num_of_new_nodes " -eq 0 ] && return
386
+ create_node ${hanodes_array[@]}
326
387
fi
327
388
328
389
[ " $CONFIG_COROSYNC_FLAG " -eq 0 ] && return
329
- config_cluster ${hanodes_arry[@]}
330
- start_cluster ${hanodes_arry[@]}
390
+ config_cluster
391
+ start_cluster
331
392
podman_exec " hanode1" " crm configure property stonith-enabled=false" 1> /dev/null
332
393
}
333
394
0 commit comments