/usr/sbin/lc_net is in lustre-utils 1.8.5+dfsg-3ubuntu1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | #!/bin/bash
# vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
#
# lc_net - script for Lustre cluster network verification
#
###############################################################################
# Usage
usage() {
cat >&2 <<EOF
Usage: `basename $0` [options] <csv file>
Options:
-a select all the nodes from the csv file to operate on
-w hostname,hostname,...
select the specified list of nodes (separated by commas)
-x hostname,hostname,...
exclude the specified list of nodes (separated by commas)
-v verbose mode
csv file a spreadsheet that contains configuration parameters
(separated by commas) for each target in a Lustre cl-
uster, the first field of each line is the host name
of the cluster node
EOF
exit 1
}
# Get the library of functions
. /usr/share/lustre/lc_common
VERBOSE_OUTPUT=false
# Get and check the positional parameters
while getopts "aw:x:v" OPTION; do
case $OPTION in
a)
[ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ]\
&& USE_ALLNODES=true
;;
w)
USE_ALLNODES=false
SPECIFIED_NODELIST=$OPTARG
;;
x)
USE_ALLNODES=false
EXCLUDED_NODELIST=$OPTARG
;;
v)
VERBOSE_OUTPUT=true
;;
?)
usage
esac
done
# Toss out the parameters we've already processed
shift `expr $OPTIND - 1`
# Here we expect the csv file
if [ $# -eq 0 ]; then
error_output "Missing csv file!"
usage
fi
# Global variables
CSV_FILE=$1
declare -a HOST_NAMES
declare -a HOST_IPADDRS
# Get the hosts to be operated on
get_hostnames() {
local NODES_TO_USE
# Initialize the HOST_NAMES array
unset HOST_NAMES
# Get the list of nodes to be operated on
NODES_TO_USE=$(get_nodelist)
[ ${PIPESTATUS[0]} -ne 0 ] && error_output "${NODES_TO_USE}" && return 1
# Check the node list
if [ -z "${NODES_TO_USE}" ]; then
echo "`basename $0`: There are no hosts to be operated on."\
"Check the node selection options (-a, -w or -x)."
return 1
fi
# Load the hostnames in the nodelist into the array
HOST_NAMES=( $(echo ${NODES_TO_USE//,/ }) )
return 0
}
# ping_host host_name
# Check whether host $host_name is reachable.
# If it is, then return the IP address of this host.
ping_host() {
local host_name=$1
local ip_addr=
local ret_str
if [ -z "${host_name}" ]; then
echo "`basename $0`: ping_host() error: Missing hostname!"
return 1
fi
# Run ping command
ret_str=$(ping -c1 ${host_name} 2>&1)
if [ ${PIPESTATUS[0]} -ne 0 ]; then
if [ -n "${ret_str}" ]; then
echo "`basename $0`: ping_host() error: ${ret_str}!"
else
echo "`basename $0`: ping_host() error:"\
"Host ${host_name} does not respond to ping!"
fi
return 1
fi
# Get the IP address
ip_addr=`echo "${ret_str}" | head -1 | awk '{print $3}' | \
sed -e 's/^(//' -e 's/)$//'`
echo "${ip_addr}"
return 0
}
# local_check index
# Check the network connectivity between local host and ${HOST_NAMES[index]}.
local_check() {
declare -i i=$1
# Check whether ${HOST_NAMES[i]} is reachable
# and get the IP address of this host from ping
HOST_IPADDRS[i]=$(ping_host ${HOST_NAMES[i]})
if [ ${PIPESTATUS[0]} -ne 0 ]; then
error_output "${HOST_IPADDRS[i]}"
return 1
fi
return 0
}
# remote_check index
# Check whether ${HOST_NAMES[index]} can resolve its own name and whether
# this host agrees with the local host about what its name is resolved to.
remote_check() {
declare -i i=$1
local cmd ret_str
local ip_addr= # the IP address got from remote ping
# Execute remote command to check whether ${HOST_NAMES[i]}
# can resolve its own name
cmd="ping -c1 ${HOST_NAMES[i]} 2>&1"
ret_str=$(${REMOTE} ${HOST_NAMES[i]} "${cmd}" 2>&1)
if [ ${PIPESTATUS[0]} -ne 0 -a -n "${ret_str}" ]; then
error_output "remote_check():"\
"remote to ${HOST_NAMES[i]} error: ${ret_str}!"
return 1
fi
if [ -z "${ret_str}" ]; then
error_output "remote_check():"\
"No results from ${HOST_NAMES[i]}! Check the network"\
"connectivity between local host and ${HOST_NAMES[i]}!"
return 1
fi
# Get the IP address of ${HOST_NAMES[i]} from its own ping
ip_pattern="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
ip_addr=`echo "${ret_str}" | egrep -o "${ip_pattern}"`
ip_addr=`echo "${ip_addr}" | sed -e 's/^(//' -e 's/)$//'`
# Compare IP addresses
# Check whether ${HOST_NAMES[i]} agrees with the local host
# about what its name is resolved to.
if [ "${ip_addr}" != "${HOST_IPADDRS[i]}" ]; then
error_output "remote_check():"\
"Local host resolves ${HOST_NAMES[i]} to IP address"\
"\"${HOST_IPADDRS[i]}\", while its own resolution is"\
"\"${ip_addr}\". They are not the same!"
return 1
fi
return 0
}
# network_verify
# Verify name resolution and network connectivity of the Lustre cluster
network_verify() {
declare -i i
# Initialize the HOST_IPADDRS array
unset HOST_IPADDRS
# Get all the host names to be operated on
! get_hostnames && return 1
# Check the network connectivity between local host
# and other cluster nodes
for ((i = 0; i < ${#HOST_NAMES[@]}; i++)); do
[ "${HOST_NAMES[i]}" = "`hostname`" ] && continue
verbose_output "Verifying network connectivity between"\
"\"`hostname`\" and \"${HOST_NAMES[i]}\"..."
! local_check $i && return 1
! remote_check $i && return 1
verbose_output "OK"
done
return 0
}
# Main flow
if ! check_file ${CSV_FILE}; then
exit 1
fi
# Cluster network verification
if ! network_verify; then
exit 1
fi
exit 0
|