summaryrefslogtreecommitdiffstats
path: root/vircmd
blob: 0cc9f960f8c7008752f73b78b1cd6c4cdd89dda5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/bin/bash
#make running virsh commands on a cluster easier

####################
# show program usage
usage ()
{
    cat >&2 <<EOF
Usage: vircmd [OPTION] ... <COMMAND>
  options:
    -x         enable script debugging 
    -n         don't include the TSM node (if any)

  commands:
     start CLUSTERNAME
           start cluster nodes

     destroy CLUSTERNAME
           power off cluster nodes (may cause data loss)

     shutdown CLUSTERNAME
           shutdown cluster nodes

     undefine CLUSTERNAME
           remove cluster

  CLUSTERNAME can be a glob-style pattern that specifies cluster nodes
EOF
    exit 1
}

############################
# parse command line options
temp=$(getopt -n "$prog" -o "xn" -l help -- "$@")

[ $? != 0 ] && usage

eval set -- "$temp"

no_tsm=0

while true ; do
    case "$1" in
	-x) set -x; shift ;;
	-n) no_tsm=1; shift ;;
	--) shift ; break ;;
	-h|--help|*) usage ;; # Shouldn't happen, so this is reasonable.
    esac
done

if [ $# -lt 2 ]; then
    echo "Usage: vircmd COMMAND CLUSTERNAME"
    exit 1
fi

cmd="$1"
cluster="$2"
count=0

export VIRSH_DEFAULT_CONNECT_URI=qemu:///system

get_nodes ()
{
    for i in $domains ; do
	case "$i" in
	    ($1)
            # If we're not skipping the TSM node or this isn't the TSM node...
            if [ "$no_tsm" = 0 -o "${i/tsm/}" = "$i" ] ; then
		nodes="${nodes} ${i}"
	    fi
	esac
    done
}

domains=$(virsh list --all | awk '{print $2}' | tail -n +3)
nodes=""

# If the cluster name doesn't have a wildcard then we need to be inventive.
if [ "${cluster/[\[\]\?\*]/}" = "$cluster" ] ; then
    get_nodes "${cluster}n[0-9]"
    get_nodes "${cluster}n[0-9][0-9]"
    get_nodes "${cluster}base[0-9]"
    get_nodes "${cluster}base[0-9][0-9]"
    get_nodes "${cluster}storage[0-9]"
    get_nodes "${cluster}storage[0-9][0-9]"
    get_nodes "${cluster}tsm"
    get_nodes "${cluster}tsm[0-9]"
    get_nodes "${cluster}tsm[0-9][0-9]"
else
    get_nodes "$cluster"
fi

[ -n "$nodes" ] || {
    echo "No nodes in cluster $2"
    exit 1
}

rc=0

for i in $nodes ; do
    # We want to retry the command when we see an internal error.
    for x in $(seq 1 5) ; do
	out=$(virsh $cmd "$i" 2>&1)
	ret=$? # Hard to avoid this since we always want to echo $out :-(
	echo "$out"
	if [ $ret -ne 0 ] ; then
	    case "$out" in
		*internal\ error*)
		    echo "Retrying \"virsh $cmd $i\" due to internal error"
		    sleep 3
		    continue
	    esac
	fi
	break
    done
    [ $ret  = 0 ] || rc=$ret
done

exit $rc