@@ -15,6 +15,10 @@ HA_NETWORK_V6_ARRAY[1]="2001:db8:20::/64"
1515BEHAVE_CASE_DIR=" $( dirname $0 ) /features/"
1616BEHAVE_CASE_EXCLUDE=" sbd"
1717
18+ declare -a hanode_list_to_form_cluster
19+ declare -a hanode_list_new_members
20+ declare -a hanode_list_current_cluster
21+
1822read -r -d ' ' SSHD_CONFIG_AZURE << EOM
1923PermitRootLogin no
2024AuthorizedKeysFile .ssh/authorized_keys
@@ -110,22 +114,28 @@ Users can make the code change under crmsh.git including test cases. This tool w
110114
111115OPTIONS:
112116 -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}'
115119 -x Don't config corosync on containers(with -n option)
116120 -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' )
119123
120124EXAMPLES:
121125To launch 2 nodes with the running cluster with the very basic corosync.conf
122126# crmsh.git/test/run-functional-tests -n 2
123127
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
126136
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
129139
130140To list the existing test cases. Users could add his own new test cases.
131141# crmsh.git/test/run-functional-tests -l
@@ -190,7 +200,11 @@ deploy_ha_node() {
190200
191201 info " Deploying \" $node_name \" ..."
192202 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
194208
195209 if [ " $node_name " != " qnetd-node" ]; then
196210 rm_qnetd_cmd=" rpm -q corosync-qnetd && rpm -e corosync-qnetd"
@@ -253,43 +267,77 @@ is_podman5_or_newer() {
253267 fi
254268}
255269
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+
256281config_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+
258290 insert_str=" "
259291 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+ ) )
261296 else
297+ # FIXME: to grow nodes, the result need sort by the container name numerically
262298 container_ip_array=(` podman network inspect $HA_NETWORK_ARRAY -f ' {{range .Containers}}{{printf "%s " .IPv4Address}}{{end}}' ` )
263299 fi
264300
265- for i in $( seq $node_num -1 1) ; do
301+ for i in $( seq ${ # hanode_list_to_form_cluster[@]} -1 1) ; do
266302 ip=` echo ${container_ip_array[$((i-1))]} | awk -F/ ' {print $1}' `
267303 insert_str+=" \\ n\\ tnode {\n\t\tring0_addr: $ip \n\t\tnodeid: $i \n\t}"
268304 done
269305 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
271307 corosync_conf_str=$( sed " /corosync_votequorum/a \\\\ ttwo_node: 1" <( echo " $corosync_conf_str " ) )
272308 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
273314
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"
279320 else
280321 while :
281322 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
283324 sleep 1
284325 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 " ."
286328 fi
287329 done
330+ echo " Done"
288331}
289332
290333
291334start_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
293341 podman_exec $node " crm cluster enable && crm cluster start" 1> /dev/null
294342 if [ " $? " -eq 0 ]; then
295343 info " Cluster service started on \" $node \" "
@@ -300,34 +348,47 @@ start_cluster() {
300348}
301349
302350
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 $"
308353}
309354
310355
311356setup_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
318376 else
319- hanodes_arry=($* )
377+ num_of_new_nodes=$#
378+ hanodes_array=($* )
320379 fi
321380
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"
324383 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[@]}
326387 fi
327388
328389 [ " $CONFIG_COROSYNC_FLAG " -eq 0 ] && return
329- config_cluster ${hanodes_arry[@]}
330- start_cluster ${hanodes_arry[@]}
390+ config_cluster
391+ start_cluster
331392 podman_exec " hanode1" " crm configure property stonith-enabled=false" 1> /dev/null
332393}
333394
0 commit comments