Whamcloud - gitweb
b=24037 Changes of 2.6.32 kernel.
[fs/lustre-release.git] / lustre / scripts / lc_net.in
1 #!/bin/bash
2
3 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
4
5 #
6 # lc_net - script for Lustre cluster network verification
7 #
8 ###############################################################################
9
10 # Usage
11 usage() {
12         cat >&2 <<EOF
13
14 Usage:  `basename $0` [options] <csv file>
15
16         Options:
17         -a              select all the nodes from the csv file to operate on
18         -w hostname,hostname,...
19                         select the specified list of nodes (separated by commas)
20         -x hostname,hostname,...
21                         exclude the specified list of nodes (separated by commas)
22         -v              verbose mode
23         csv file        a spreadsheet that contains configuration parameters 
24                         (separated by commas) for each target in a Lustre cl-
25                         uster, the first field of each line is the host name 
26                         of the cluster node
27
28 EOF
29         exit 1
30 }
31
32 # Get the library of functions
33 . @scriptlibdir@/lc_common
34
35 VERBOSE_OUTPUT=false
36 # Get and check the positional parameters
37 while getopts "aw:x:v" OPTION; do
38         case $OPTION in
39         a)
40                 [ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ]\
41                 && USE_ALLNODES=true
42                 ;;
43         w)
44                 USE_ALLNODES=false
45                 SPECIFIED_NODELIST=$OPTARG
46                 ;;
47         x)
48                 USE_ALLNODES=false
49                 EXCLUDED_NODELIST=$OPTARG
50                 ;;
51         v) 
52                 VERBOSE_OUTPUT=true
53                 ;;
54         ?) 
55                 usage 
56         esac
57 done
58
59 # Toss out the parameters we've already processed
60 shift  `expr $OPTIND - 1`
61
62 # Here we expect the csv file
63 if [ $# -eq 0 ]; then
64         error_output "Missing csv file!"
65         usage
66 fi
67
68 # Global variables
69 CSV_FILE=$1
70 declare -a HOST_NAMES
71 declare -a HOST_IPADDRS
72
73 # Get the hosts to be operated on
74 get_hostnames() {
75         local NODES_TO_USE
76
77         # Initialize the HOST_NAMES array
78         unset HOST_NAMES
79
80         # Get the list of nodes to be operated on
81         NODES_TO_USE=$(get_nodelist)
82         [ ${PIPESTATUS[0]} -ne 0 ] && error_output "${NODES_TO_USE}" && return 1
83
84         # Check the node list
85         if [ -z "${NODES_TO_USE}" ]; then
86                 echo "`basename $0`: There are no hosts to be operated on."\
87                 "Check the node selection options (-a, -w or -x)."
88                 return 1
89         fi
90
91         # Load the hostnames in the nodelist into the array
92         HOST_NAMES=( $(echo ${NODES_TO_USE//,/ }) )
93
94         return 0
95 }
96
97 # ping_host host_name
98 # Check whether host $host_name is reachable. 
99 # If it is, then return the IP address of this host.
100 ping_host() {
101         local host_name=$1
102         local ip_addr=
103         local ret_str
104
105         if [ -z "${host_name}" ]; then
106                 echo "`basename $0`: ping_host() error: Missing hostname!"
107                 return 1
108         fi
109
110         # Run ping command
111         ret_str=$(ping -c1 ${host_name} 2>&1)
112         if [ ${PIPESTATUS[0]} -ne 0 ]; then
113                 if [ -n "${ret_str}" ]; then
114                         echo "`basename $0`: ping_host() error: ${ret_str}!"
115                 else
116                         echo "`basename $0`: ping_host() error:"\
117                         "Host ${host_name} does not respond to ping!"
118                 fi
119                 return 1
120         fi
121
122         # Get the IP address
123         ip_addr=`echo "${ret_str}" | head -1 | awk '{print $3}' | \
124                 sed -e 's/^(//' -e 's/)$//'`
125
126         echo "${ip_addr}"
127         return 0
128 }
129
130 # local_check index
131 # Check the network connectivity between local host and ${HOST_NAMES[index]}.
132 local_check() {
133         declare -i i=$1
134
135         # Check whether ${HOST_NAMES[i]} is reachable
136         # and get the IP address of this host from ping
137         HOST_IPADDRS[i]=$(ping_host ${HOST_NAMES[i]})
138         if [ ${PIPESTATUS[0]} -ne 0 ]; then
139                 error_output "${HOST_IPADDRS[i]}"
140                 return 1
141         fi
142
143         return 0
144 }
145
146 # remote_check index
147 # Check whether ${HOST_NAMES[index]} can resolve its own name and whether
148 # this host agrees with the local host about what its name is resolved to.
149 remote_check() {
150         declare -i i=$1
151         local cmd ret_str
152         local ip_addr=          # the IP address got from remote ping
153
154         # Execute remote command to check whether ${HOST_NAMES[i]}
155         # can resolve its own name
156         cmd="ping -c1 ${HOST_NAMES[i]} 2>&1"
157         ret_str=$(${REMOTE} ${HOST_NAMES[i]} "${cmd}" 2>&1)
158         if [ ${PIPESTATUS[0]} -ne 0 -a -n "${ret_str}" ]; then
159                 error_output "remote_check():"\
160                 "remote to ${HOST_NAMES[i]} error: ${ret_str}!"
161                 return 1
162         fi
163
164         if [ -z "${ret_str}" ]; then
165                 error_output "remote_check():"\
166                 "No results from ${HOST_NAMES[i]}! Check the network"\
167                 "connectivity between local host and ${HOST_NAMES[i]}!"
168                 return 1
169         fi
170
171         # Get the IP address of ${HOST_NAMES[i]} from its own ping
172        ip_pattern="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
173        ip_addr=`echo "${ret_str}" | egrep -o "${ip_pattern}"`
174         ip_addr=`echo "${ip_addr}" | sed -e 's/^(//' -e 's/)$//'`
175
176         # Compare IP addresses
177         # Check whether ${HOST_NAMES[i]} agrees with the local host
178         # about what its name is resolved to.
179         if [ "${ip_addr}" != "${HOST_IPADDRS[i]}" ]; then
180                 error_output "remote_check():"\
181                 "Local host resolves ${HOST_NAMES[i]} to IP address"\
182                 "\"${HOST_IPADDRS[i]}\", while its own resolution is"\
183                 "\"${ip_addr}\". They are not the same!"
184                 return 1
185         fi
186         
187         return 0
188 }
189
190 # network_verify
191 # Verify name resolution and network connectivity of the Lustre cluster
192 network_verify() {
193         declare -i i
194
195         # Initialize the HOST_IPADDRS array
196         unset HOST_IPADDRS
197
198         # Get all the host names to be operated on 
199         ! get_hostnames && return 1
200
201         # Check the network connectivity between local host 
202         # and other cluster nodes
203         for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
204                 [ "${HOST_NAMES[i]}" = "`hostname`" ] && continue
205
206                 verbose_output "Verifying network connectivity between"\
207                                "\"`hostname`\" and \"${HOST_NAMES[i]}\"..."
208                 ! local_check $i && return 1
209                 ! remote_check $i && return 1
210                 verbose_output "OK"
211         done
212
213         return 0
214 }
215
216 # Main flow
217 if ! check_file ${CSV_FILE}; then
218         exit 1  
219 fi
220
221 # Cluster network verification
222 if ! network_verify; then
223         exit 1  
224 fi
225
226 exit 0