Sun Cluster データサービス開発ガイド (Solaris OS 版)

PROBE プログラムのコードリスト

PROBE プログラムは、nslookup コマンドを使用して、データサービスの可用性を検査します (nslookup(1M) のマニュアルページを参照)。このプログラムは Monitor_start コールバックメソッドによって起動され、Monitor_stop コールバックメソッドによって停止されます。


例 B–5 dns_probe プログラム

#!/bin/ksh
#pragma ident   “@(#)dns_probe   1.1   00/04/19 SMI”
#
# HA-DNS の Probe メソッド
#
# このプログラムは、nslookup を使用して、データサービスの可用性を検査
# する。nslookup は DNS サーバーに照会することによって、DNS
# サーバー自身を探す。サーバーが応答しない場合、あるいは、別のサー
# バーが照会に応答した場合、probe メソッドはデータサービスまたはク
# ラスタ内の別のノードになんらかの問題が発生したという結論を下す。
# 検証は、RTR ファイルの THOROUGH_PROBE_INTERVAL で設定さ
# れた間隔で行われる。

#pragma ident   “@(#)dns_probe   1.1   00/05/24 SMI”

###############################################################################
# プログラム引数を構文解析する。
function parse_args # [args ...]
{
        typeset opt

        while getopts `R:G:T:' opt
        do
                case “$opt” in
                R)
                        # DNS リソースの名前。
                        RESOURCE_NAME=$OPTARG
                        ;;
                G)
                        # リソースが構成されているリソース
                        # グループの名前。
                        RESOURCEGROUP_NAME=$OPTARG
                        ;;
                T)
                        # リソースタイプの名前。
                        RESOURCETYPE_NAME=$OPTARG
                        ;;
                *)
                    logger -p ${SYSLOG_FACILITY}.err \
                    -t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
                    “ERROR: Option $OPTARG unknown”
                     exit 1
                     ;;
                esac
        done
}

###############################################################################
# restart_service ()
#
# この関数は、まずデータサービスの Stop メソッドを呼び出し、
# 次に Start メソッドを呼び出すことによって、データサービスを再起動
# しようとする。データサービスがすでに起動しておらず、
# データサービスのタグが PMF に登録されていない場合、
# この関数はデータサービスをクラスタ内の
# 別のノードにフェイルオーバーする。
#
function restart_service
{
        # データサービスを再起動するには、まず、データサービス自身が
        # PMF 下に登録されているかどうかを確認する。
        pmfadm -q $PMF_TAG
        if [[ $? -eq 0 ]]; then
                # データサービスの TAG が PMF に登録されている場合、
                # データサービスを停止し、起動し直す。
                # 当該リソースの Stop メソッド名と STOP_TIMEOUT 値を取得する。
                STOP_TIMEOUT=`scha_resource_get -O STOP_TIMEOUT \
                        -R $RESOURCE_NAME -G $RESOURCEGROUP_NAMÈ
                STOP_METHOD=`scha_resource_get -O STOP \
                        -R $RESOURCE_NAME -G $RESOURCEGROUP_NAMÈ
                hatimerun -t $STOP_TIMEOUT $RT_BASEDIR/$STOP_METHOD \
                        -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
                        -T $RESOURCETYPE_NAME

                if [[ $? -ne 0 ]]; then
                        logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
                                “${ARGV0} Stop method failed.”
                        return 1
                fi

                # 当該リソースの Start メソッド名と START_TIMEOUT 値を取得する。
                START_TIMEOUT=`scha_resource_get -O START_TIMEOUT \
                        -R $RESOURCE_NAME -G $RESOURCEGROUP_NAMÈ
                START_METHOD=`scha_resource_get -O START \
                        -R $RESOURCE_NAME -G $RESOURCEGROUP_NAMÈ
                hatimerun -t $START_TIMEOUT $RT_BASEDIR/$START_METHOD \
                        -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
                        -T $RESOURCETYPE_NAME

                if [[ $? -ne 0 ]]; then
                        logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
                                “${ARGV0} Start method failed.”
                        return 1
                fi

        else
                # データサービスの TAG が PMF に登録されていない場合、
                # データサービスが PMF 下で許可されている再試行最大回数を
                # 超えていることを示す。したがって、データサービスを再起動
                # してはならない。その代わりに、同じクラスタ内にある別のノード
                # にフェイルオーバーを試みる。
                scha_control -O GIVEOVER -G $RESOURCEGROUP_NAME \
                        -R $RESOURCE_NAME
        fi

        return 0
}

###############################################################################
# decide_restart_or_failover ()
#
# この関数は、検証が失敗したときに行うべきアクション、つまり、デー
# タサービスをローカルで再起動するか、クラスタ内の別のノードに
# フェイルオーバーするかを決定する。
#
function decide_restart_or_failover
{
   
   # 最初の再起動の試行であるかどうかを検査する。
   if [ $retries -eq 0 ]; then
         # 最初の失敗である。
         # 最初の試行の時刻を記録する。
         start_time=`$RT_BASEDIR/gettimè
         retries=`expr $retries + 1`
         # 最初の失敗であるので、データサービスを
         # 再起動しようと試行する。
         restart_service
         if [ $? -ne 0 ]; then
            logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
                “${ARGV0} Failed to restart data service.”
            exit 1
         fi
   else
      # 最初の失敗ではない。
      current_time=`$RT_BASEDIR/gettimè
      time_diff=`expr $current_time - $start_timè
      if [ $time_diff -ge $RETRY_INTERVAL ]; then
         # この失敗は再試行最大期間後に発生した。
         # したがって、再試行カウンタをリセットし、
         # 再試行時間をリセットし、さらに再試行する。
         retries=1
         start_time=$current_time
         # 前回の失敗が Retry_interval よりも以前に発生しているので、
         # データサービスを再起動しようと試行する。
         restart_service
         if [ $? -ne 0 ]; then
            logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG \
                “${ARGV0} Failed to restart HA-DNS.”
            exit 1
         fi
      elif [ $retries -ge $RETRY_COUNT ]; then
         # 再試行最大期間内であり、再試行カウンタは満了
         # している。したがって、フェイルオーバーする。
         retries=0
         scha_control -O GIVEOVER -G $RESOURCEGROUP_NAME \
             -R $RESOURCE_NAME
         if [ $? -ne 0 ]; then
            logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
                “${ARGV0} Failover attempt failed.”
            exit 1
         fi
      else
         # 再試行最大期間内であり、再試行カウンタは満了
         # していない。したがって、さらに再試行する。
         retries=`expr $retries + 1`
         restart_service
         if [ $? -ne 0 ]; then
            logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
                “${ARGV0} Failed to restart HA-DNS.”
            exit 1
         fi
      fi
fi
}

###############################################################################
# MAIN
###############################################################################

export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH

# メッセージの記録に使用する syslog 機能番号を取得する。
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`

# このメソッドに渡された引数を構文解析する。
parse_args “$@”

PMF_TAG=$RESOURCE_NAME.named
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME

# 証が行われる間隔はシステム定義プロパティー THOROUGH_PROBE_INTERVAL
# に設定されている。scha_resource_get でこのプロパティーの値を取得する。
PROBE_INTERVAL=scha_resource_get -O THOROUGH_PROBE_INTERVAL \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAMÈ

# 検証用のタイムアウト値を取得する。この値は RTR ファイルの
# PROBE_TIMEOUT 拡張プロパティーに設定されている。nslookup のデフォル
# トのタイムアウトは 1.5 分。
probe_timeout_info=`scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Probe_timeout`
PROBE_TIMEOUT=`echo $probe_timeout_info | awk `{print $2}'`

# リソースの NETWORK_RESOURCES_USED プロパティーの値を取得して、
# DNS がサービスを提供するサーバーを見つける。
DNS_HOST=`scha_resource_get -O NETWORK_RESOURCES_USED -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAMÈ

# システム定義プロパティー Retry_count から再試行最大回数を取得する。
RETRY_COUNT =`scha_resource_get -O RETRY_COUNT -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAMÈ

# システム定義プロパティー Retry_interval から再試行最大期間を取得する。
Retry_interval
RETRY_INTERVAL=scha_resource_get -O RETRY_INTERVAL -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAMÈ

# リソースタイプの RT_basedir プロパティーから gettime ユーティリティーの
# 完全パスを取得する。
RT_BASEDIR=scha_resource_get -O RT_basedir -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAMÈ

# 検証は無限ループで動作し、nslookup コマンドを実行し続ける。
# nslookup 応答用の一時ファイルを設定する。
DNSPROBEFILE=/tmp/.$RESOURCE_NAME.probe
probefail=0
retries=0

while :
do
   # 検証が動作すべき期間は <THOROUGH_PROBE_INTERVAL> プロパティーに指
   # 定されている。したがって、THOROUGH_PROBE_INTERVAL の間、検証
   # プログラムが休眠するように設定する。
   sleep $PROBE_INTERVAL

   # DNS がサービスを提供しているIP アドレス上で nslookup コマンド
   # を実行する。
   hatimerun -t $PROBE_TIMEOUT /usr/sbin/nslookup $DNS_HOST $DNS_HOST \
           > $DNSPROBEFILE 2>&1
   
   retcode=$?
        if [ retcode -ne 0 ]; then
                probefail=1
        fi

      # nslookup への応答が HA-DNS サーバーから来ており、
      # /etc/resolv.conf ファイル内に指定されているほかのネームサーバー
      # から来ていないことを確認する。
      if [ $probefail -eq 0 ]; then
      # nslookup 照会に応答するサーバーの名前を取得する。
                   SERVER=` awk ` $1==”Server:” {print $2 }' \
                   $DNSPROBEFILE | awk -F. ` { print $1 } ` `
                if [ -z “$SERVER” ];
                then
                        probefail=1
                else
                        if [ $SERVER != $DNS_HOST ]; then
                                probefail=1
                        fi
                fi
        fi

   # probefail 変数が 0 以外である場合、nslookup コマンドがタイム
   # アウトしたか、あるいは、別のサーバー (/etc/resolv.conf ファイ
   # ルに指定されている) から照会への応答が来ていることを示す。
   # どちらの場合でも、DNS サーバーは応答していないので、
   # このメソッドは decide_restart_or_failover を呼び出して、
   # データサービスをローカルで起動するか、あるいは、別のノードに
   # フェイルオーバーするかを評価する。

   if [ $probefail -ne 0 ]; then
         decide_restart_or_failover
   else
         logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
         “${ARGV0} Probe for resource HA-DNS successful”
   fi
done