@@ -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
@@ -194,7 +204,11 @@ deploy_ha_node() {
194204
195205 info " Deploying \" $node_name \" ..."
196206 podman run --rm -d $podman_options $podman_capabilties $podman_security $CONTAINER_IMAGE > /dev/null
197- podman network connect ha_network_second $node_name
207+ if [ $? -ne 0 ]; then
208+ warning Likely $node_name already exists.
209+ return
210+ fi
211+ podman network connect ha_network_second $node_name
198212
199213 if [ " $node_name " != " qnetd-node" ]; then
200214 rm_qnetd_cmd=" rpm -q corosync-qnetd && rpm -e corosync-qnetd"
@@ -257,43 +271,77 @@ is_podman5_or_newer() {
257271 fi
258272}
259273
274+ get_cluster_new_nodes () {
275+ hanode_list_to_form_cluster=($( podman ps -a --format ' {{.Names}}' | grep hanode| sort -n -k1.7| tr ' \r' ' ' ) )
276+ hanode_list_current_cluster=($( podman_exec hanode1 " crm node server 2>/dev/null" 2> /dev/null| sort -n -k1.7| tr ' \r' ' ' ) )
277+ hanode_list_new_members=()
278+ for element in " ${hanode_list_to_form_cluster[@]} " ; do
279+ if ! [[ " ${hanode_list_current_cluster[@]} " =~ " $element " ]]; then
280+ hanode_list_new_members+=(" $element " )
281+ fi
282+ done
283+ }
284+
260285config_cluster () {
261- node_num=$#
286+ get_cluster_new_nodes
287+
288+ if [ ${# hanode_list_new_members[@]} -eq 0 ]; then
289+ return
290+ else
291+ info ${# hanode_list_new_members[@]} new node\( s\) " '${hanode_list_new_members[@]} '"
292+ fi
293+
262294 insert_str=" "
263295 if [[ is_podman5_or_newer ]]; then
264- 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]' ) )
296+ container_ip_array=($( podman network inspect $HA_NETWORK_ARRAY | jq -r '
297+ .[] | .containers | to_entries | sort_by(.value.name | capture("hanode(?<num>\\d+)").num | tonumber) |
298+ .[] | .value.interfaces[] | .subnets[] | select(.ipnet | test("^(\\d{1,3}\\.){3}\\d{1,3}\\/\\d+$")) | .ipnet '
299+ ) )
265300 else
301+ # FIXME: to grow nodes, the result need sort by the container name numerically
266302 container_ip_array=(` podman network inspect $HA_NETWORK_ARRAY -f ' {{range .Containers}}{{printf "%s " .IPv4Address}}{{end}}' ` )
267303 fi
268304
269- for i in $( seq $node_num -1 1) ; do
305+ for i in $( seq ${ # hanode_list_to_form_cluster[@]} -1 1) ; do
270306 ip=` echo ${container_ip_array[$((i-1))]} | awk -F/ ' {print $1}' `
271307 insert_str+=" \\ n\\ tnode {\n\t\tring0_addr: $ip \n\t\tnodeid: $i \n\t}"
272308 done
273309 corosync_conf_str=$( sed " /nodelist/a \\ ${insert_str} " <( echo " $COROSYNC_CONF_TEMPLATE " ) )
274- if [ $node_num -eq 2 ]; then
310+ if [ ${ # hanode_list_to_form_cluster[@]} -eq 2 ]; then
275311 corosync_conf_str=$( sed " /corosync_votequorum/a \\\\ ttwo_node: 1" <( echo " $corosync_conf_str " ) )
276312 fi
313+ if search_running_container_by_name " qnetd-node" ; then
314+ info " Generate corosync.conf without qdevice/qnetd for the cluster hanode{1..${# hanode_list_to_form_cluster[@]} }"
315+ else
316+ info " Generate corosync.conf for the cluster hanode{1..${# hanode_list_to_form_cluster[@]} }"
317+ fi
277318
278- info " Copy corosync.conf to $* "
279- for node in $* ; do
280- if [ $node == $1 ]; then
281- podman_exec $1 " echo \" $corosync_conf_str \" > > $COROSYNC_CONF "
282- podman_exec $1 " corosync-keygen -l -k $COROSYNC_AUTH &> /dev/null"
319+ echo -n " INFO: Copy corosync.conf to all cluster nodes hanode{1.. ${ # hanode_list_to_form_cluster[@]} } "
320+ for node in ${hanode_list_to_form_cluster[@]} ; do
321+ if [ $node == " hanode1 " ]; then
322+ podman_exec " hanode1 " " echo \" $corosync_conf_str \" > $COROSYNC_CONF "
323+ podman_exec " hanode1 " " corosync-keygen -l -k $COROSYNC_AUTH &> /dev/null"
283324 else
284325 while :
285326 do
286- podman_exec $1 " ssh -T -o Batchmode=yes $node true &> /dev/null" && break
327+ podman_exec " hanode1 " " ssh -T -o Batchmode=yes $node true &> /dev/null" && break
287328 sleep 1
288329 done
289- podman_exec $1 " scp -p $COROSYNC_CONF $COROSYNC_AUTH $node :/etc/corosync &> /dev/null"
330+ podman_exec " hanode1" " scp -p $COROSYNC_CONF $COROSYNC_AUTH $node :/etc/corosync &> /dev/null"
331+ echo -n " ."
290332 fi
291333 done
334+ echo " Done"
292335}
293336
294337
295338start_cluster () {
296- for node in $* ; do
339+ if [ ${# hanode_list_current_cluster[@]} -ne 0 ] && [ ${# hanode_list_new_members[@]} -ne 0 ]; then
340+ podman_exec hanode1 " corosync-cfgtool -R > /dev/null"
341+ info On the existing cluster hanode{1..${# hanode_list_current_cluster[@]} }: reloading corosync.conf ... Done
342+ fi
343+
344+ for node in ${hanode_list_new_members[@]} ; do
297345 podman_exec $node " crm cluster enable && crm cluster start" 1> /dev/null
298346 if [ " $? " -eq 0 ]; then
299347 info " Cluster service started on \" $node \" "
@@ -304,34 +352,47 @@ start_cluster() {
304352}
305353
306354
307- container_already_exists () {
308- podman ps -a| grep -q " $1 "
309- if [ " $? " -eq 0 ]; then
310- fatal " Container \" $1 \" already running"
311- fi
355+ search_running_container_by_name () {
356+ podman ps -a --format ' {{.Names}}' | grep -q " ^$1 $"
312357}
313358
314359
315360setup_cluster () {
316- hanodes_arry=()
317- is_number $1
318- if [ " $? " -eq 0 ]; then
319- for i in $( seq 1 $1 ) ; do
320- hanodes_arry+=(" hanode$i " )
321- done
361+ get_cluster_new_nodes
362+
363+ hanodes_array=()
364+ if is_number " $1 " ; then
365+ # add more nodes after the last node, ordered by the node name
366+ if [ ${# hanode_list_to_form_cluster[@]} -gt 0 ]; then
367+ last_node_num=" ${hanode_list_to_form_cluster[-1]: 6} "
368+ warning Skip creating cluster nodes. Here are the existing ones: hanode{1..${# hanode_list_to_form_cluster[@]} }
369+ else
370+ last_node_num=0
371+ fi
372+ num_of_new_nodes=$(( $1 - ${# hanode_list_to_form_cluster[@]} ))
373+ if [ " $num_of_new_nodes " -gt 0 ]; then
374+ for i in $( seq $(( last_node_num + 1 )) $(( last_node_num + num_of_new_nodes )) ) ; do
375+ hanodes_array+=(" hanode$i " )
376+ done
377+ elif [ " $WITH_QNETD_NODE " -eq 0 ]; then
378+ return
379+ fi
322380 else
323- hanodes_arry=($* )
381+ num_of_new_nodes=$#
382+ hanodes_array=($* )
324383 fi
325384
326- if [ $WITH_QNETD_NODE -eq 1 ]; then
327- create_node ${hanodes_arry [@]} " qnetd-node"
385+ if [ " $WITH_QNETD_NODE " -eq 1 ] && ! search_running_container_by_name " qnetd-node " ; then
386+ create_node ${hanodes_array [@]} " qnetd-node"
328387 else
329- create_node ${hanodes_arry[@]}
388+ [ " $WITH_QNETD_NODE " -eq 1 ] && warning Skip creating the existing qnetd-node
389+ [ " $num_of_new_nodes " -eq 0 ] && return
390+ create_node ${hanodes_array[@]}
330391 fi
331392
332393 [ " $CONFIG_COROSYNC_FLAG " -eq 0 ] && return
333- config_cluster ${hanodes_arry[@]}
334- start_cluster ${hanodes_arry[@]}
394+ config_cluster
395+ start_cluster
335396 podman_exec " hanode1" " crm configure property stonith-enabled=false" 1> /dev/null
336397}
337398
0 commit comments