#!/bin/sh
source ./standby_env.sh
function check_dn_state() {
sleep 1
echo "query $1 $2 $3 is $4"
if [ $(gs_ctl query -D $data_dir/$1 | grep "$2" | grep "$3" | wc -l) -eq $4 ]; then
echo "query $1 $2 $3 is $4 success!"
else
sleep 3
if [ $(gs_ctl query -D $data_dir/$1 | grep "$2" | grep "$3" | wc -l) -eq $4 ]; then
echo "query $1 $2 $3 is $4 success!"
else
echo "$failed_keyword, check_dn_state $1 failed, the query result is display as follows: "
gs_ctl query -D $data_dir/$1
exit 1
fi
fi
}
function check_dn_no_need_repair() {
check_dn_state $1 "" "Need repair" 0
}
function check_detailed_instance(){
sleep 2
echo query ps check
if [ $(ps -ef | grep $data_dir | grep -v grep | wc -l) -eq 5 ]; then
echo "ps check process success!"
else
sleep 2
if [ $(ps -ef | grep $data_dir | grep -v grep | wc -l) -eq 5 ]; then
echo "ps check process success!"
else
echo "$failed_keyword, ps check process failure, process info is displayed as: "
ps -ef | grep $data_dir | grep -v grep
exit 2
fi
fi
sleep 1
check_dn_no_need_repair "datanode1"
check_dn_no_need_repair "datanode1_standby"
check_dn_no_need_repair "datanode2_standby"
check_dn_no_need_repair "datanode3_standby"
check_dn_no_need_repair "datanode4_standby"
check_dn_state "datanode1" "db_state" "Normal" 1
check_dn_state "datanode1_standby" "db_state" "Normal" 1
check_dn_state "datanode2_standby" "db_state" "Normal" 1
check_dn_state "datanode3_standby" "db_state" "Normal" 1
check_dn_state "datanode4_standby" "db_state" "Normal" 1
}
function check_primary() {
check_dn_no_need_repair $1
check_dn_state $1 "db_state" "Normal" 1
check_dn_state $1 peer_role "Standby" $2
check_dn_state $1 peer_state "Normal" $2
}
function check_synchronous_commit() {
check_dn_state $1 "sync_state" "Sync" $2
}
function check_quorum_synchronous_commit() {
check_dn_state $1 "sync_state" "Quorum" $2
}
function check_asynchronous_commit() {
check_dn_state $1 "sync_state" "Async" $2
}
function check_most_available() {
check_dn_state $1 "sync_most_available" $2 $3
}
function build_primary_as_standby() {
echo "start building primary as standby"
gs_ctl build -D $data_dir/datanode1 -Z single_node -b full
if [ $? -eq 0 ]; then
echo "standby built"
else
echo "$failed_keyword, build primary as standby failed"
exit 1
fi
}
function build_standby_as_standby() {
echo "start building standby as standby"
gs_ctl build -D $data_dir/datanode1_standby -Z single_node -b full
if [ $? -eq 0 ]; then
echo "standby built"
else
echo "$failed_keyword, build standby as standby failed"
exit 1
fi
}
function build_standby2_as_standby() {
echo "start building standby2 as standby"
gs_ctl build -D $data_dir/datanode2_standby -Z single_node -b full
if [ $? -eq 0 ]; then
echo "standby built"
else
echo "$failed_keyword, build standby2 as standby failed"
exit 1
fi
}
function build_standby3_as_standby() {
echo "start building standby3 as standby"
gs_ctl build -D $data_dir/datanode3_standby -Z single_node -b full
if [ $? -eq 0 ]; then
echo "standby built"
else
echo "$failed_keyword, build standby3 as standby failed"
exit 1
fi
}
function build_standby4_as_standby() {
echo "start building standby4 as standby"
gs_ctl build -D $data_dir/datanode4_standby -Z single_node -b full
if [ $? -eq 0 ]; then
echo "standby built"
else
echo "$failed_keyword, build standby4 as standby failed"
exit 1
fi
}
function build_standbys() {
build_standby_as_standby
build_standby2_as_standby
build_standby3_as_standby
build_standby4_as_standby
}
function kill_cluster() {
kill_primary
kill_standby
kill_standby2
kill_standby3
kill_standby4
}
function start_cluster() {
start_primary
start_standby
start_standby2
start_standby3
start_standby4
}
function set_data_replicate() {
kill_cluster
set_data_replicate_helper
start_cluster
}
function set_most_available_sync() {
kill_cluster
set_most_available_sync_helper
start_cluster
}
function set_default() {
kill_cluster
set_default_helper
start_cluster
switchover_to_primary
build_standbys
}
function set_default_paxos()
{
kill_cluster
set_default_helper
start_paxos $1
}
function set_default_helper() {
cluster_dns=($primary_data_dir $standby_data_dir $standby2_data_dir $standby3_data_dir)
for element in ${cluster_dns[@]}
do
gs_guc set -Z datanode -D $element -c "synchronous_commit = on"
gs_guc set -Z datanode -D $element -c "synchronous_standby_names = '*'"
gs_guc set -Z datanode -D $element -c "most_available_sync = on"
done
}
function set_enable_mix_replication() {
cluster_dns=($primary_data_dir $standby_data_dir $standby2_data_dir $standby3_data_dir $standby4_data_dir)
}
function set_most_available_sync_helper() {
gs_guc set -Z datanode -D $primary_data_dir -c "most_available_sync = on"
gs_guc set -Z datanode -D $standby_data_dir -c "most_available_sync = on"
for((i=2;i<$node_num+1;i++))
do
tmp_data_dir="datanode"$i"_standby"
gs_guc set -Z datanode -D $tmp_data_dir -c "most_available_sync = on"
done
}
function start_node() {
gs_ctl start -D $1 -M standby
sleep 2s
gs_ctl query -D $1
if [ ! $? -eq 0 ]; then
echo "$failed_keyword, start $1 failed!"
exit 1
fi
}
function switchover_to_primary() {
check_old_primary_dir
if [ -z ${current_primary} ];then
echo "get old primary dir failed!"
exit 1
fi
gs_ctl switchover -w -t $gsctl_wait_time -D $data_dir/datanode1
if [ $? -eq 0 ]; then
echo "switchover to primary success!"
if [ "$data_dir/datanode1" != ${current_primary} ]; then
start_node ${current_primary}
fi
else
echo "$failed_keyword, switchover to primary fail!"
exit 1
fi
}
function switchover_to_standby() {
check_old_primary_dir
if [ -z ${current_primary} ];then
echo "get old primary dir failed!"
exit 1
fi
gs_ctl switchover -w -t $gsctl_wait_time -D $data_dir/datanode1_standby
if [ $? -eq 0 ]; then
echo "switchover to standby1 success!"
if [ "$data_dir/datanode1_standby" != ${current_primary} ]; then
start_node ${current_primary}
fi
else
echo "$failed_keyword, switchover to standby1 fail!"
exit 1
fi
}
function switchover_to_standby2() {
check_old_primary_dir
if [ -z ${current_primary} ];then
echo "get old primary dir failed!"
exit 1
fi
gs_ctl switchover -w -t $gsctl_wait_time -D $data_dir/datanode2_standby
if [ $? -eq 0 ]; then
echo "switchover to standby2 success!"
if [ "$data_dir/datanode2_standby" != ${current_primary} ]; then
start_node ${current_primary}
fi
else
echo "$failed_keyword, switchover to standby2 fail!"
exit 1
fi
}
function switchover_to_standby3() {
check_old_primary_dir
if [ -z ${current_primary} ];then
echo "get old primary dir failed!"
exit 1
fi
gs_ctl switchover -w -t $gsctl_wait_time -D $data_dir/datanode3_standby
if [ $? -eq 0 ]; then
echo "switchover to standby3 success!"
if [ "$data_dir/datanode3_standby" != ${current_primary} ]; then
start_node ${current_primary}
fi
else
echo "$failed_keyword, switchover to standby3 fail!"
exit 1
fi
}
function switchover_to_standby4() {
check_old_primary_dir
if [ -z ${current_primary} ];then
echo "get old primary dir failed!"
exit 1
fi
gs_ctl switchover -w -t $gsctl_wait_time -D $data_dir/datanode4_standby
if [ $? -eq 0 ]; then
echo "switchover to standby4 success!"
if [ "$data_dir/datanode4_standby" != ${current_primary} ]; then
start_node ${current_primary}
fi
else
echo "$failed_keyword, switchover to standby4 fail!"
exit 1
fi
}
function kill_current_primary() {
nodes=($primary_data_dir $standby_data_dir $standby2_data_dir $standby3_data_dir $standby4_data_dir)
for((i = 0;i<=${node_num};i++))
do
gs_ctl query -D ${nodes[$i]} | grep -o -E "Primary"
if [ $? -eq 0 ];then
if [ $i == 0 ];then
current_primary=$primary_data_dir
kill_primary
break
fi
if [ $i == 1 ];then
current_primary=$standby_data_dir
kill_standby
break
fi
if [ $i == 2 ];then
current_primary=$standby2_data_dir
kill_standby2
break
fi
if [ $i == 3 ];then
current_primary=$standby3_data_dir
kill_standby3
break
fi
if [ $i == 4 ];then
current_primary=$standby4_data_dir
kill_standby4
break
fi
fi
done
sleep 5
if [ -z ${current_primary} ];then
echo "get old primary dir failed!"
exit 1
fi
gs_ctl start -D ${current_primary} -M standby -Z single_node
}
function print_time() {
cur_time=`date +"%F %T.%N" | cut -c1-23`
echo -n "[${cur_time}] "
}
function wait_recovery_done() {
recovery_done=0
node_data_dir=$1
wait_time_seconds=$2
last_log=`ls -ltr ${node_data_dir}/pg_log/postgresql-* | tail -1 | awk '{print $9}'`
for i in `seq 1 $wait_time_seconds`;
do
recovery_done=`grep "database system is ready to accept read only connections" $last_log | wc -l`
if [ $recovery_done -eq 1 ]; then
print_time
echo "Recovery done on node detected after $i seconds at: $node_data_dir"
break
fi
sleep 1
done
if [ $recovery_done -eq 0 ]; then
print_time
echo "Failed to find recovery done message after $wait_time_seconds seconds in node log at: $node_data_dir"
fi
}
function run_change_role() {
role=$1
tmp_data_dir=$2
timeout=10
gs_ctl changerole -R ${role} -D ${tmp_data_dir} -t ${timeout}
}
function set_run_mode_cmd() {
retry=3
runmode=$1
tmp_data_dir=$2
for((i=0; i<${retry}; i++))
do
echo "begin to set ${runmode} mode for ${tmp_data_dir}"
if [ "${runmode}" = "minority" ]; then
votenum=$3
gs_ctl setrunmode -x ${runmode} -v ${votenum} -D ${tmp_data_dir}
elif [ "${runmode}" = "normal" ]; then
gs_ctl setrunmode -x ${runmode} -D ${tmp_data_dir}
else
echo "${failed_keyword}, Run mode is not supported!"
exit 1
fi
if [ $? != 0 ]; then
echo "Change run mode of ${tmp_data_dir} to ${runmode} failed and retry!"
continue
fi
return 0
done
echo "${failed_keyword}, change run mode of ${tmp_data_dir} to ${runmode} failed after three times of retry!"
exit 1
}
function remove_member() {
node_id=$1
gs_ctl member --operation=remove --nodeid=${node_id} -D ${current_primary}
if [ ! $? -eq 0 ]; then
echo "${failed_keyword}, Run remove member cmd failed"
exit 1
fi
sleep 3s
gs_ctl query -D ${current_primary} | grep "\"node_id\":${node_id}"
if [ $? -eq 0 ]; then
echo "${failed_keyword}, remove member failed"
exit 1
fi
}
function add_member() {
node_id=$1
ip=$2
port=$3
gs_ctl member --operation=add --nodeid=${node_id} --ip=${ip} --port=${port} -D ${current_primary}
if [ ! $? -eq 0 ]; then
echo "${failed_keyword}, Run add member cmd failed"
exit 1
fi
gs_ctl query -D ${current_primary} | grep "\"node_id\":${node_id}"
if [ ! $? -eq 0 ]; then
echo "${failed_keyword}, add member failed"
exit 1
fi
}