Whamcloud - gitweb
b=9853
authoryujian <yujian>
Fri, 2 Jun 2006 10:21:21 +0000 (10:21 +0000)
committeryujian <yujian>
Fri, 2 Jun 2006 10:21:21 +0000 (10:21 +0000)
Script to verify the service IP and the real interface IP in a remote host are in the same subnet.

lustre/scripts/lc_servip.sh [new file with mode: 0755]

diff --git a/lustre/scripts/lc_servip.sh b/lustre/scripts/lc_servip.sh
new file mode 100755 (executable)
index 0000000..779aa34
--- /dev/null
@@ -0,0 +1,250 @@
+#!/bin/bash
+#
+# lc_servip.sh - script for verifying the service IP and the real
+#               interface IP in a remote host are in the same subnet
+#
+###############################################################################
+
+# Usage
+usage() {
+       cat >&2 <<EOF
+
+Usage:  `basename $0` <service IPaddr> <hostname>
+       
+       service IPaddr          the IP address to failover
+       hostname                the hostname of the remote node
+
+EOF
+       exit 1
+}
+
+# Check arguments
+if [ $# -lt 2 ]; then
+        usage
+fi
+
+# Remote command
+REMOTE=${REMOTE:-"ssh -x -q"}
+
+# Check whether the reomte command is pdsh
+is_pdsh() {
+        if [ "${REMOTE}" = "${REMOTE#*pdsh}" ]; then
+                return 1
+        fi
+
+        return 0
+}
+
+#
+# inSameIPsubnet serviceIPaddr interfaceIPaddr mask
+#
+# Given two IP addresses and a subnet mask determine if these IP
+# addresses are in the same subnet. If they are, return 0, else return 1.
+#
+inSameIPsubnet() {
+       declare -i n
+       declare -ia mask 
+       declare -ia ip1 ip2             # IP addresses given
+       declare -i quad1 quad2          # calculated quad words
+
+       #
+       # Remove '.' characters from dotted decimal notation and save
+       # in arrays. i.e.
+       #
+       #       192.168.1.163 -> array[0] = 192
+       #                        array[1] = 168
+       #                        array[2] = 1
+       #                        array[3] = 163
+       #
+       let n=0
+       for quad in $(echo $1 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
+       do
+               ip1[n]=$quad
+               let n=n+1
+       done
+
+       let n=0
+       for quad in $(echo $2 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
+       do
+               ip2[n]=$quad
+               let n=n+1
+       done
+
+       let n=0
+       for quad in $(echo $3 | awk -F. '{print $1 " " $2 " " $3 " " $4}')
+       do
+               mask[n]=$quad
+               let n=n+1
+       done
+
+       #
+       # For each quad word, logically AND the IP address with the subnet
+       # mask to get the network/subnet quad word.  If the resulting
+       # quad words for both IP addresses are the same they are in the 
+       # same IP subnet.
+       #
+       for n in 0 1 2 3
+       do
+               let $((quad1=${ip1[n]} & ${mask[n]}))
+               let $((quad2=${ip2[n]} & ${mask[n]}))
+
+               if [ $quad1 != $quad2 ]; then
+                       echo >&2 $"`basename $0`: Service IP address $1 and"\
+                                 "real interface IP address $2 are in"\
+                                 "different subnets!"
+                       return 1        # in different subnets
+               fi
+       done
+
+       return 0        # in the same subnet, all quad words matched
+}
+
+#
+# findInterface IPaddr hostname
+#
+# Given a target IP address and a hostname, find the interface in which 
+# this address is configured.  If found return 0, if not return 1.  The
+# interface name is returned to stdout.
+#
+findInterface() {
+       declare ret_line
+       declare line
+       declare intf
+       declare addr
+       declare state
+
+       declare target=$1
+       declare hostname=$2
+
+       while read ret_line
+       do
+               set -- ${ret_line}
+               is_pdsh && shift
+               intf="$1"
+               shift
+               line="$*"
+
+               while read line
+               do
+                       if [ "$line" = "" ]; then       # go to next interface
+                               continue 2
+                       fi
+
+                       set - $line
+                       addr=
+                       while [ $# -gt 0 ]; do
+                               case $1 in
+                               addr:*)
+                                       addr=${1##addr:}
+                                       if [ -n "$addr" -a "$addr" = "$target" ]
+                                       then
+                                               echo $intf
+                                               return 0
+                                       fi
+                                       ;;
+                               esac
+                               shift
+                       done
+               done
+       done < <(${REMOTE} $hostname /sbin/ifconfig)
+
+       echo >&2 "`basename $0`: Cannot find the interface in which" \
+                 "$target is configured in the host $hostname!"
+       return 1
+}
+
+#
+# findNetmask interface hostname
+#
+# Given an interface find the netmask addresses associated with it.
+# Return 0 when found, else return 1. The netmask is returned to stdout.
+#
+findNetmask() {
+       declare ret_line
+       declare line
+       declare addr
+       declare target=$1
+       declare hostname=$2
+
+       while read ret_line
+       do
+               set -- ${ret_line}
+               is_pdsh && shift
+               line="$*"
+
+               set - $line
+
+               while [ $# -gt 0 ]; do
+                       case $1 in
+                       Mask:*)
+                               echo ${1##*:}   # return netmask addr
+                               return 0 
+                               ;;
+                       esac
+                       shift
+               done
+       done < <(${REMOTE} $hostname /sbin/ifconfig $target)
+
+       echo >&2 "`basename $0`: Cannot find the netmask associated with" \
+                 "the interface $target in the host $hostname!"
+       return 1 
+}
+
+#
+# check_srvIPaddr serviceIPaddr hostname
+#
+# Given a service IP address and hostname, check whether the service IP address
+# and the real interface IP address of hostname are in the same subnet. 
+# If they are, return 0, else return 1.
+#
+check_srvIPaddr() {
+       declare real_IPaddr
+       declare real_intf
+       declare netmask
+       declare srv_IPaddr=$1
+       declare hostname=$2
+
+       # Get the corresponding IP address of the hostname from /etc/hosts table
+       real_IPaddr=`egrep "[[:space:]]$hostname([[:space:]]|$)" /etc/hosts \
+                     | awk '{print $1}'`
+        if [ -z "$real_IPaddr" ]; then
+                echo >&2 "`basename $0`: Hostname $hostname does not exist in" \
+                         "the local /etc/hosts table!"
+                return 1
+        fi
+
+        if [ ${#real_IPaddr} -gt 15 ]; then
+                echo >&2 "`basename $0`: More than one IP address line" \
+                         "corresponding to $hostname in the local"  \
+                        "/etc/hosts table!"
+                return 1
+        fi
+
+       # Get the interface in which the real IP address is configured
+       real_intf=$(findInterface $real_IPaddr $hostname)
+       if [ $? -ne 0 ]; then
+               return 1
+       fi
+       real_intf=${real_intf%%:*}
+
+       # Get the netmask address associated with the real interface
+       netmask=$(findNetmask $real_intf $hostname)
+       if [ $? -ne 0 ]; then
+               return 1
+       fi
+
+       # Determine if the service IP address and the real IP address
+       # are in the same subnet
+       inSameIPsubnet $srv_IPaddr $real_IPaddr $netmask
+       if [ $? -ne 0 ]; then
+               return 1
+       fi
+
+       return 0
+}
+
+# Check service IP address
+if ! check_srvIPaddr $1 $2; then
+       exit 1
+fi
+exit 0