392 lines
8.2 KiB
Bash
392 lines
8.2 KiB
Bash
#!/bin/bash
|
|
|
|
COLOR_FAIL='\033[0;31m' #RED
|
|
COLOR_WARN='\033[1;33m' #YELLOW
|
|
COLOR_SUCCESS='\033[0;32m' #GREEN
|
|
COLOR_NONE='\033[0m'
|
|
|
|
fail() {
|
|
printf "${COLOR_FAIL}$1${COLOR_NONE}"
|
|
}
|
|
|
|
warn() {
|
|
printf "${COLOR_WARN}$1${COLOR_NONE}"
|
|
}
|
|
|
|
succeed() {
|
|
printf "${COLOR_SUCCESS}$1${COLOR_NONE}"
|
|
}
|
|
|
|
check_ssh()
|
|
{
|
|
NODE1="$(grep '^NODE1' $CLUSTER_CONF | cut -d'=' -f2)"
|
|
NODE2="$(grep '^NODE2' $CLUSTER_CONF | cut -d'=' -f2)"
|
|
[ -z "$NODE1" -o -z "$NODE2" ] && {
|
|
echo "Please provide node-ip in $CLUSTER_CONF."
|
|
exit 1
|
|
}
|
|
for ip in $NODE1 $NODE2
|
|
do
|
|
ssh -o NumberOfPasswordPrompts=0 $ip -l root "pwd" > /dev/null
|
|
[ $? -ne 0 ] && {
|
|
echo "Please setup ssh-access with no-authorized mode."
|
|
exit 1
|
|
}
|
|
done
|
|
}
|
|
|
|
fetch_devlist()
|
|
{
|
|
ISCSI_ID="$(grep '^ISCSI_TARGET_ID' $CLUSTER_CONF | cut -d'=' -f2)"
|
|
devlist="$(grep '^devlist' $CLUSTER_CONF | cut -d'=' -f2)"
|
|
if [ ! -z "$ISCSI_ID" -a ! -z "$devlist" ]
|
|
then
|
|
echo "Config ISCSI_TARGET_ID or devlist in $CLUSTER_CONF."
|
|
exit 1
|
|
elif [ ! -z "$ISCSI_ID" -a -z "$devlist" ]
|
|
then
|
|
for ip in $NODE1 $NODE2
|
|
do
|
|
ssh $ip "ls /dev/disk/by-path/*$ISCSI_ID*" > /dev/null
|
|
[ $? -ne 0 ] && {
|
|
echo "$ip: No disks found in '$ISCSI_ID' connection."
|
|
exit 1
|
|
}
|
|
done
|
|
devlist=($(ls /dev/disk/by-path/*$ISCSI_ID*))
|
|
fi
|
|
# sbd disk cannot use in testing
|
|
# Init devlist as an array
|
|
i=''
|
|
devlist=(${devlist[@]#$i})
|
|
for i in ${devlist[@]}
|
|
do
|
|
sbd -d $i dump &> /dev/null
|
|
[ $? -eq '0' ] && devlist=(${devlist[@]#$i})
|
|
done
|
|
for i in $(seq 0 ${#devlist[@]})
|
|
do
|
|
eval "dev$i=${devlist[$i]}"
|
|
done
|
|
[ "${#devlist[@]}" -lt 6 ] && {
|
|
echo "Cluster-md testing requires 6 disks at least."
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
check_dlm()
|
|
{
|
|
if ! crm configure show | grep -q dlm
|
|
then
|
|
crm configure primitive dlm ocf:pacemaker:controld \
|
|
op monitor interval=60 timeout=60 \
|
|
meta target-role=Started &> /dev/null
|
|
crm configure group base-group dlm
|
|
crm configure clone base-clone base-group \
|
|
meta interleave=true
|
|
fi
|
|
sleep 2
|
|
for ip in $NODE1 $NODE2
|
|
do
|
|
ssh $ip "pgrep dlm_controld > /dev/null" || {
|
|
echo "$ip: dlm_controld daemon doesn't exist."
|
|
exit 1
|
|
}
|
|
done
|
|
crm_mon -r -n1 | grep -iq "fail\|not" && {
|
|
echo "Please clear cluster-resource errors."
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
check_env()
|
|
{
|
|
user=$(id -un)
|
|
[ "X$user" = "Xroot" ] || {
|
|
echo "testing can only be done as 'root'."
|
|
exit 1
|
|
}
|
|
[ \! -x $mdadm ] && {
|
|
echo "test: please run make everything before perform testing."
|
|
exit 1
|
|
}
|
|
check_ssh
|
|
commands=(mdadm iscsiadm bc modinfo dlm_controld
|
|
udevadm crm crm_mon lsblk pgrep sbd)
|
|
for ip in $NODE1 $NODE2
|
|
do
|
|
for cmd in ${commands[@]}
|
|
do
|
|
ssh $ip "which $cmd &> /dev/null" || {
|
|
echo "$ip: $cmd, command not found!"
|
|
exit 1
|
|
}
|
|
done
|
|
mods=(raid1 raid10 md_mod dlm md-cluster)
|
|
for mod in ${mods[@]}
|
|
do
|
|
ssh $ip "modinfo $mod > /dev/null" || {
|
|
echo "$ip: $mod, module doesn't exist."
|
|
exit 1
|
|
}
|
|
done
|
|
ssh $ip "lsblk -a | grep -iq raid"
|
|
[ $? -eq 0 ] && {
|
|
echo "$ip: Please run testing without running RAIDs environment."
|
|
exit 1
|
|
}
|
|
ssh $ip "modprobe md_mod"
|
|
done
|
|
fetch_devlist
|
|
check_dlm
|
|
[ -d $logdir ] || mkdir -p $logdir
|
|
}
|
|
|
|
# $1/node, $2/optional
|
|
stop_md()
|
|
{
|
|
if [ "$1" == "all" ]
|
|
then
|
|
NODES=($NODE1 $NODE2)
|
|
elif [ "$1" == "$NODE1" -o "$1" == "$NODE2" ]
|
|
then
|
|
NODES=$1
|
|
else
|
|
die "$1: unknown parameter."
|
|
fi
|
|
if [ -z "$2" ]
|
|
then
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip mdadm -Ssq
|
|
done
|
|
else
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip mdadm -S $2
|
|
done
|
|
fi
|
|
}
|
|
|
|
record_system_speed_limit() {
|
|
system_speed_limit_max=`cat /proc/sys/dev/raid/speed_limit_max`
|
|
system_speed_limit_min=`cat /proc/sys/dev/raid/speed_limit_min`
|
|
}
|
|
|
|
# To avoid sync action finishes before checking it, it needs to limit
|
|
# the sync speed
|
|
control_system_speed_limit() {
|
|
echo $test_speed_limit_min > /proc/sys/dev/raid/speed_limit_min
|
|
echo $test_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
|
|
}
|
|
|
|
restore_system_speed_limit() {
|
|
echo $system_speed_limit_min > /proc/sys/dev/raid/speed_limit_max
|
|
echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
|
|
}
|
|
|
|
record_selinux() {
|
|
# empty
|
|
return 0
|
|
}
|
|
|
|
restore_selinux() {
|
|
# empty
|
|
return 0
|
|
}
|
|
|
|
# $1/optional, it shows why to save log
|
|
save_log()
|
|
{
|
|
status=$1
|
|
logfile="$status""$_basename".log
|
|
|
|
cat $targetdir/stderr >> $targetdir/log
|
|
cp $targetdir/log $logdir/$_basename.log
|
|
|
|
for ip in $NODE1 $NODE2
|
|
do
|
|
echo "##$ip: saving dmesg." >> $logdir/$logfile
|
|
ssh $ip "dmesg -c" >> $logdir/$logfile
|
|
echo "##$ip: saving proc mdstat." >> $logdir/$logfile
|
|
ssh $ip "cat /proc/mdstat" >> $logdir/$logfile
|
|
array=($(ssh $ip "mdadm -Ds | cut -d' ' -f2"))
|
|
|
|
if [ ! -z "$array" -a ${#array[@]} -ge 1 ]
|
|
then
|
|
echo "##$ip: mdadm -D ${array[@]}" >> $logdir/$logfile
|
|
ssh $ip "mdadm -D ${array[@]}" >> $logdir/$logfile
|
|
md_disks=($(ssh $ip "mdadm -DY ${array[@]} | grep "/dev/" | cut -d'=' -f2"))
|
|
cat /proc/mdstat | grep -q "bitmap"
|
|
if [ $? -eq 0 ]
|
|
then
|
|
echo "##$ip: mdadm -X ${md_disks[@]}" >> $logdir/$logfile
|
|
ssh $ip "mdadm -X ${md_disks[@]}" >> $logdir/$logfile
|
|
echo "##$ip: mdadm -E ${md_disks[@]}" >> $logdir/$logfile
|
|
ssh $ip "mdadm -E ${md_disks[@]}" >> $logdir/$logfile
|
|
fi
|
|
else
|
|
echo "##$ip: no array assembled!" >> $logdir/$logfile
|
|
fi
|
|
done
|
|
[ "$1" == "fail" ] &&
|
|
echo "See $logdir/$_basename.log and $logdir/$logfile for details"
|
|
stop_md all
|
|
}
|
|
|
|
do_setup()
|
|
{
|
|
check_env
|
|
ulimit -c unlimited
|
|
}
|
|
|
|
do_clean()
|
|
{
|
|
for ip in $NODE1 $NODE2
|
|
do
|
|
ssh $ip "mdadm -Ssq; dmesg -c > /dev/null"
|
|
done
|
|
mdadm --zero ${devlist[@]} &> /dev/null
|
|
}
|
|
|
|
cleanup()
|
|
{
|
|
check_ssh
|
|
do_clean
|
|
}
|
|
|
|
# check: $1/cluster_node $2/feature $3/optional
|
|
check()
|
|
{
|
|
NODES=()
|
|
if [ "$1" == "all" ]
|
|
then
|
|
NODES=($NODE1 $NODE2)
|
|
elif [ "$1" == "$NODE1" -o "$1" == "$NODE2" ]
|
|
then
|
|
NODES=$1
|
|
else
|
|
die "$1: unknown parameter."
|
|
fi
|
|
case $2 in
|
|
spares )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
spares=$(ssh $ip "tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)'")
|
|
[ "$spares" -ne "$3" ] &&
|
|
die "$ip: expected $3 spares, but found $spares"
|
|
done
|
|
;;
|
|
raid* )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip "grep -sq "$2" /proc/mdstat" ||
|
|
die "$ip: check '$2' failed."
|
|
done
|
|
;;
|
|
recovery-remote )
|
|
cnt=5
|
|
for ip in ${NODES[@]}
|
|
do
|
|
while ! ssh $ip "grep -sqE 'recovery|REMOTE' /proc/mdstat"
|
|
do
|
|
if [ "$cnt" -gt '0' ]
|
|
then
|
|
sleep 0.2
|
|
cnt=$[cnt-1]
|
|
else
|
|
die "$ip: no '$2' happening!"
|
|
fi
|
|
done
|
|
done
|
|
;;
|
|
PENDING | recovery | resync | reshape )
|
|
cnt=5
|
|
for ip in ${NODES[@]}
|
|
do
|
|
while ! ssh $ip "grep -sq '$2' /proc/mdstat"
|
|
do
|
|
if [ "$cnt" -gt '0' ]
|
|
then
|
|
sleep 0.2
|
|
cnt=$[cnt-1]
|
|
else
|
|
die "$ip: no '$2' happening!"
|
|
fi
|
|
done
|
|
done
|
|
;;
|
|
wait )
|
|
local cnt=60
|
|
for ip in ${NODES[@]}
|
|
do
|
|
p=$(ssh $ip "cat /proc/sys/dev/raid/speed_limit_max")
|
|
ssh $ip "echo 200000 > /proc/sys/dev/raid/speed_limit_max"
|
|
while ssh $ip "grep -Esq '(resync|recovery|reshape|check|repair)' /proc/mdstat"
|
|
do
|
|
if [ "$cnt" -gt '0' ]
|
|
then
|
|
sleep 5
|
|
cnt=$[cnt-1]
|
|
else
|
|
die "$ip: Check '$2' timeout over 300 seconds."
|
|
fi
|
|
done
|
|
ssh $ip "echo $p > /proc/sys/dev/raid/speed_limit_max"
|
|
done
|
|
;;
|
|
bitmap )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip "grep -sq '$2' /proc/mdstat" ||
|
|
die "$ip: no '$2' found in /proc/mdstat."
|
|
done
|
|
;;
|
|
nobitmap )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip "grep -sq 'bitmap' /proc/mdstat" &&
|
|
die "$ip: 'bitmap' found in /proc/mdstat."
|
|
done
|
|
;;
|
|
chunk )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
chunk_size=`awk -F',' '/chunk/{print $2}' /proc/mdstat | awk -F'[a-z]' '{print $1}'`
|
|
[ "$chunk_size" -ne "$3" ] &&
|
|
die "$ip: chunksize should be $3, but it's $chunk_size"
|
|
done
|
|
;;
|
|
state )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip "grep -Esq 'blocks.*\[$3\]\$' /proc/mdstat" ||
|
|
die "$ip: no '$3' found in /proc/mdstat."
|
|
done
|
|
;;
|
|
nosync )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip "grep -Eq '(resync|recovery)' /proc/mdstat" &&
|
|
die "$ip: resync or recovery is happening!"
|
|
done
|
|
;;
|
|
readonly )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip "grep -sq "read-only" /proc/mdstat" ||
|
|
die "$ip: check '$2' failed!"
|
|
done
|
|
;;
|
|
dmesg )
|
|
for ip in ${NODES[@]}
|
|
do
|
|
ssh $ip "dmesg | grep -iq 'error\|call trace\|segfault'" &&
|
|
die "$ip: check '$2' prints errors!"
|
|
done
|
|
;;
|
|
* )
|
|
die "unknown parameter $2"
|
|
;;
|
|
esac
|
|
}
|