#!/usr/bin/perl
#####################################################################
# Function: pg-rex_slave_start
#
#
# 概要:
# PG-REX での Slave 起動実行ツール。
# 手順の簡易化を目的として作成している。
# 
# 特記事項:
# なし
#
# Copyright (c) 2012-2015, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
#
#####################################################################
package PGRex;

use warnings;
use strict;
use File::Compare;
use Getopt::Long;
use PGRex::command;
use PGRex::common qw(pacemaker_online pgrex_failed_action network_running master_running
                     slave_running vip_running stonith_running ping_running diskd_running
                     read_config read_cib read_hacf get_ssh_passwd exec_command 
                     ssh_exec_command scp_exec_command get_pg_command_path check_user
                     printlog get_node get_another_iclan_netaddr get_iclan_ipaddr
                     rsync_exec_command check_support_version ifcheckd_running
                     get_pg_version get_controldata_value get_xlog_filename compare_lsn
                     get_pg_dir_state get_restore_archivewal_num get_start_wal_filename);

BEGIN {
    if ($ENV{'LANG'} =~ m/ja/i){
        eval qq{
            use PGRex::Po::ja;
        };
    }
    else{
        eval qq{
            use PGRex::Po::en;
        }
    }
};

$SIG{INT} = sub {
    printlog("LOG", SLAVESTART_MS0001);
};

main();

1;

sub main{
    my $help_mode = 0;
    my $version_mode = 0;
    my $nobasebackup_mode = 0;
    my $force_mode = 0;
    my $check_only_mode = 0;
    my $shared_archive_directory_mode = 0;
    my $basebackup_options = "";
    my $config_path = CONFIG_PATH.CONFIG_FILENAME;
    my %config_value;
    my $cib_path = CIB_PATH.CIB_FILENAME;
    my %master_cib_value;
    my $hacf_path = HACF_PATH.HACF_FILENAME;
    my %hacf_value;
    my $authkey_path = HACF_PATH.AUTHKEY_FILENAME;
    my $copy_dir = "/tmp/";
    my $copy_cib_path = $copy_dir."cib.xml";
    my %node_value;
    my %command_path;
    my $pg_command_user = "postgres";
    my $pg_xlog_dir;
    my $symbolic_link = 0;
    my $timeout = 300;
    my $monitor_delay = 10;
    my $monitor_interval = 2;
    my $wait_time = 0;
    my $lock_file = "";
    my $exit_code;
    my $ssh_pass;
    my $starting_resource = "";
    my $result;
    my @results;
    my $kill_when_no_data = 1;
    my $operation_num = 1;
    my $myself;
    my @another_iclan_netaddr = ();
    my %iclan_ipaddr;
    my @my_controldata_strings;
    my %my_controldata_value;
    my @another_controldata_strings;
    my %another_controldata_value;
    my $command;

    # 標準出力が途中で停止するのを防ぐ為に
    # 標準出力のオートフラッシュを有効化
    $| = 1;

    # 実行ユーザの確認
    check_user();

    # 環境設定ファイルの読み込み
    %config_value = read_config($config_path);

    # PostgreSQL のコマンドパスを取得
    %command_path = get_pg_command_path($config_value{'PGPATH'});

    # Pacemaker と PostgreSQL がサポート対象バージョンであるかを確認
    check_support_version($command_path{'postgres'});

    ### スクリプト実行準備 ###

    # オプション解析
    foreach ( @ARGV ){
        if ( "$_" eq "-" || "$_" eq "--" ){
            $help_mode = 1;
        }
    }
    $exit_code = GetOptions('help'                  => \$help_mode,
                         'nobasebackup'             => \$nobasebackup_mode,
                         'force'                    => \$force_mode,
                         'check-only'               => \$check_only_mode,
                         'shared-archive-directory' => \$shared_archive_directory_mode,
                         'options=s'                => \$basebackup_options,
                         'version'                  => \$version_mode);
    $myself = $0;
    $myself =~ s/.*\///g;
    if ($help_mode || !$exit_code){
        printlog("VERSION", VERSIONINFO, $myself, VERSIONNUM);
        print "\n";
        printlog("USAGE", SLAVESTART_USAGE);
        exit(0);
    }
    if ($version_mode){
        printlog("VERSION", VERSIONINFO, $myself, VERSIONNUM);
        exit(0);
    }
    if ($check_only_mode) {
        $nobasebackup_mode = 1;
    }

    # pg_basebackupのオプションの確定
    if ($basebackup_options ne "") {
        $config_value{'PG_BASEBACKUP_opt'} = $basebackup_options;
    }

    # ssh 接続の為の情報の取得
    $ssh_pass = get_ssh_passwd($config_value{'Another_D-LAN_IPAddress'}, $config_value{'PEER_NODE_SSH_PASS_MODE'}, $config_value{'PEER_NODE_SSH_PASS_FILE'});
    my $ssh_info = new Ssh_info();
    $ssh_info->address("$config_value{'Another_D-LAN_IPAddress'}");
    $ssh_info->user("root");
    $ssh_info->pass("$ssh_pass");

    # 自身のノードと相手のノードで ifcheckd が起動していることを確認
    ifcheckd_running($ssh_info);

    # コマンドを実行しているマシンのノード名ともう一台のノード名を取得
    %node_value = get_node($ssh_info);

    # 相手のノードと同じクラスタ認証ファイルが配置されていること
    my $copy_authkey_path = $copy_dir.AUTHKEY_FILENAME;
    scp_exec_command($ssh_info, $authkey_path, $copy_dir);
    if (compare($authkey_path, $copy_authkey_path)){
        printlog("ERROR", SLAVESTART_MS0002, $authkey_path);
    }
    exec_command("$RM -f $copy_authkey_path");

    # corosync.conf の読み込み
    %hacf_value = read_hacf($hacf_path, "start");

    # 相手先のノードの corosync.conf に設定されている bindnetaddr を取得する 
    @another_iclan_netaddr = get_another_iclan_netaddr($hacf_path, $ssh_info);

    ### Pacemaker 起動の為の準備 ###
    # 自身のノードの Pacemaker 及び corosync の稼働確認
    printlog("LOG", SLAVESTART_MS0004, $operation_num++);
    if (pacemaker_running()){
        printlog("LOG", SLAVESTART_MS0005);
        printlog("ERROR", SLAVESTART_MS0006);
    }
    printlog("LOG", SLAVESTART_MS0007);

    ### 稼働中の Master の存在確認 ###
    printlog("LOG", SLAVESTART_MS0008, $operation_num++);
    if (!master_running($node_value{'another_node'}, $config_value{'PG-REX_Master_ResourceID'}, $config_value{'PG-REX_Primitive_ResourceID'}, $ssh_info)){
        printlog("LOG", SLAVESTART_MS0005);
        printlog("ERROR", SLAVESTART_MS0010);
    }
    printlog("LOG", SLAVESTART_MS0007);

    ### IC-LAN が接続されていることを確認 ###
    # 自身のノードと相手先のノードの IC-LAN IP アドレスを取得して接続確認を行う
    printlog("LOG", SLAVESTART_MS0011, $operation_num++);

    %iclan_ipaddr = get_iclan_ipaddr(\@{$hacf_value{iclan_netaddr}}, \@another_iclan_netaddr, \%node_value, $ssh_info);

    foreach my $ipaddr (@{$iclan_ipaddr{'another_node'}}){
        `$PING -c 5 $ipaddr`;
        $exit_code = $? >> 8;
        if ($exit_code){
            printlog("LOG", SLAVESTART_MS0005);
            printlog("ERROR", SLAVESTART_MS0012);
        }
    }
    printlog("LOG", SLAVESTART_MS0007);

    ### 起動禁止フラグの存在確認 ###
    printlog("LOG", SLAVESTART_MS0013, $operation_num++);

    # Master マシンにある cib.xml をコピーし読み込む
    scp_exec_command($ssh_info, $cib_path, $copy_dir);
    %master_cib_value = read_cib($copy_cib_path, $config_value{'PG-REX_Primitive_ResourceID'}, $kill_when_no_data, $config_path, $config_value{'ARCHIVE_DELETE_DBCLUSTER_DIR'});
    exec_command("$RM -f $copy_cib_path");

    # 起動禁止フラグが存在することを確認
    $lock_file = $master_cib_value{'tmpdir'}."/".LOCK_FILENAME;
    if (-e $lock_file){
        printlog("LOG", SLAVESTART_MS0005);
        printlog("ERROR", SLAVESTART_MS0014, $lock_file);
    }

    printlog("LOG", SLAVESTART_MS0007);

    ## DB クラスタの状態を収集する
    # DB クラスタの及びアーカイブディレクトリの状態を収集する
    my $pg_dir_state = new Pg_dir_state();
    $pg_dir_state = get_pg_dir_state($master_cib_value{'pgdata'}, $config_value{'Archive_dir'});

    # 自身のノードと相手のノードの pg_control の情報を収集する
    if ($pg_dir_state->pgdata_exist){
        $result = exec_command("$SU - $pg_command_user -c \"export LANG=C; $command_path{'pg_controldata'} $master_cib_value{'pgdata'}\"");
        @my_controldata_strings = split(/\n/, $result);
        %my_controldata_value = get_controldata_value(@my_controldata_strings);

        @results = ssh_exec_command($ssh_info, "$SU - $pg_command_user -c \"export LANG=C; $command_path{'pg_controldata'} $master_cib_value{'pgdata'}\"");
        @another_controldata_strings = split(/\n/, $results[0]);
        %another_controldata_value = get_controldata_value(@another_controldata_strings);
    }

    ### Master からベースバックアップ取得・展開 ###
    # ベースバックアップを取得・展開するかどうかをユーザに確認
    if (!$nobasebackup_mode){
        printlog("LOG", SLAVESTART_MS0015, $operation_num++);

        if (!$force_mode){
            printlog("LOG", SLAVESTART_MS0016);
            my $input = <STDIN>;
            chomp $input;
            if ($input =~ m/^n$/i){
                # 以降 --nobasebackup オプション付与時と同じ動作を行う
                $nobasebackup_mode = 1;
            }
            elsif ($input !~ m/^y$/i){
                printlog("LOG", SLAVESTART_MS0017);
                exit(0);
            }
        }
    }

    # ベースバックアップを取得する場合、pg_basebackup を実行し、pg_xlog のシンボリックリンク作成を行なう
    if (!$nobasebackup_mode){
        # アーカイブディレクトリ共有モードの場合はアーカイブ WAL の存在確認は行わない
        if (!$shared_archive_directory_mode){
            if ($pg_dir_state->pgdata_exist){
                # Master 側と DB 識別子が一致していない、かつアーカイブ WAL が存在する場合は異常終了する
                # NOTE: 適用不可のアーカイブ WAL が残存している可能性があるため
                if ($my_controldata_value{'database'} ne $another_controldata_value{'database'} &&
                    !$pg_dir_state->pgarch_empty){
                    printlog("LOG", SLAVESTART_MS0005);
                    printlog("ERROR", SLAVESTART_MS0032, $config_value{'Archive_dir'});
                }
            }
            else {
                # DB クラスタが存在せず、かつアーカイブ WAL が存在する場合は異常終了する
                # NOTE: Slave 初回起動時に不要のアーカイブ WAL が残存しているため
                if (!$pg_dir_state->pgarch_empty){
                    printlog("LOG", SLAVESTART_MS0005);
                    printlog("ERROR", SLAVESTART_MS0032, $config_value{'Archive_dir'});
                }
            }
        }

        # Slave 側の DB クラスタを削除
        exec_command("$SU - $pg_command_user -c \"$RM -rf $master_cib_value{'pgdata'} \"");

        # Master の pg_xlog の場所を取得し、Slave の pg_xlog を削除
        # ※readlink コマンドは、引数に指定されたファイルにシンボリックリンクが存在する場合、コマンドの戻り値に"0"を返す
        # ※戻り値が"0"の場合のみ、pg_xlog を削除する
        @results = ssh_exec_command($ssh_info, "$READLINK $master_cib_value{'pgdata'}/pg_xlog ");
        $exit_code = $results[1];
        if ($exit_code != 0 && $exit_code != 1){
            printlog("LOG", SLAVESTART_MS0005);
            printlog("ERROR", SLAVESTART_MS0018);
        }
        elsif (!$exit_code){
            chomp $results[0];
            # pg_xlog format : ~/pg_xlog
            $results[0] =~ s/\/pg_xlog$//;
            $pg_xlog_dir = $results[0];
            exec_command("$SU - $pg_command_user -c \"$RM -rf $pg_xlog_dir/pg_xlog\"");
            $symbolic_link = 1;
        }

        exec_command("$SU - $pg_command_user -c \" $command_path{'pg_basebackup'} -h $config_value{'Another_D-LAN_IPAddress'} -U $master_cib_value{'repuser'} -D $master_cib_value{'pgdata'} $config_value{'PG_BASEBACKUP_opt'} -P \"");

        # pg_xlog のシンボリックリンクを作成
        if ($symbolic_link){
            exec_command("$SU - $pg_command_user -c \"$MV $master_cib_value{'pgdata'}/pg_xlog $pg_xlog_dir \"");
            exec_command("$SU - $pg_command_user -c \"$LN -s $pg_xlog_dir/pg_xlog $master_cib_value{'pgdata'}/pg_xlog \"");
        }
        printlog("LOG", SLAVESTART_MS0007);
    }

    ### 自身のノードの DB クラスタの状態を確認 ###
    # DB クラスタの状態確認はベースバックアップを取得しない場合のみ行う
    if ($nobasebackup_mode){
        printlog("LOG", SLAVESTART_MS0034, $operation_num++);

        # (STEP 1)DB クラスタが存在していることを確認
        if (!$pg_dir_state->pgdata_exist){
            printlog("LOG", SLAVESTART_MS0033);
            ng_result();
        }

        # (STEP 2)DB クラスタのバージョンと PostgreSQL サーバのバージョンが一致していることを確認
        # DB クラスタのバージョンチェックについては、自身のノードと相手ノードの DB クラスタのバージョンが
        # 一致しないケースも考えられるが、PG-REXの運用上起こり得ないケースであるため当該ケースはチェックしない。
        # なお、運用補助ツールにおける PostgreSQL のバージョンチェックの方針は以下とする。
        #  (a) 運用補助ツールの機能に必要なチェックのみ行う
        #  (b) PG-REXの運用上起こり得ない環境(状態)まで考慮しない
        #  (c) PostgreSQL は RPM によりインストールされた環境を前提とする
        my $pg_version_file = $master_cib_value{'pgdata'}."/PG_VERSION";
        my $dbcluster_version = `$SU $pg_command_user -c "$CAT $pg_version_file"`;
        chomp $dbcluster_version;
        if (! $dbcluster_version) {
            printlog("LOG", SLAVESTART_MS0035);
            ng_result();
        }
        my @version_factor = split(/\./, get_pg_version($command_path{'postgres'}));
        my $pg_major_version = $version_factor[0].".".$version_factor[1];
        if ($dbcluster_version ne $pg_major_version){
                printlog("LOG", SLAVESTART_MS0036, $dbcluster_version, $pg_major_version);
                ng_result();
        }

        # (STEP 3)自身のノードと相手のノードのデータベース識別子が一致していることを確認
        if ($my_controldata_value{'database'} ne $another_controldata_value{'database'}){
            printlog("LOG", SLAVESTART_MS0037, $my_controldata_value{'database'}, $another_controldata_value{'database'});
            ng_result();
        }

        # (STEP 4)自身のノードの TLI が相手のノードを超過していないことを確認
        if ($my_controldata_value{'time_line_id'} > $another_controldata_value{'time_line_id'}){
            printlog("LOG", SLAVESTART_MS0038, $my_controldata_value{'time_line_id'}, $another_controldata_value{'time_line_id'});
            ng_result();
        }

        # (STEP 5)自身のノードの XLOG 位置が相手のノードを超過していないことを確認
        # 両系における現在のWALファイル名を特定する
        my $my_current_xlog_filename;
        my $another_current_xlog_filename;
        $command = "$LS -l $master_cib_value{'pgdata'}/pg_xlog/ | $GREP -P \"[0-9A-F]{24}\$\" | $TAIL -1";
        $result = exec_command($command);
        if ($result =~ /.*([0-9A-F]{24})$/){
                $my_current_xlog_filename = $1;
        } else {
            printlog("ERROR", SLAVESTART_MS0039, $master_cib_value{'pgdata'}."/pg_xlog");
        }

        @results = ssh_exec_command($ssh_info, $command);
        if ($results[0] =~ /.*([0-9A-F]{24})$/){
                $another_current_xlog_filename = $1;
        } else {
            printlog("ERROR", SLAVESTART_MS0040, $master_cib_value{'pgdata'}."/pg_xlog");
        }

        # pg_xlogdump の出力結果から現在の XLOG 位置を取得
        my $my_current_xlog_location;
        my $another_current_xlog_location;
        $command = "$SU - $pg_command_user -c \"$command_path{'pg_xlogdump'} $master_cib_value{'pgdata'}/pg_xlog/$my_controldata_value{'wal_filename'} $master_cib_value{'pgdata'}/pg_xlog/$my_current_xlog_filename 2> /dev/null | $TAIL -1\"";
        $result = exec_command($command);
        if ($result =~ /.*lsn:\s+([0-9A-F\/]+).*/){
            $my_current_xlog_location = $1;
        }

        $command = "$SU - $pg_command_user -c \"$command_path{'pg_xlogdump'} $master_cib_value{'pgdata'}/pg_xlog/$another_controldata_value{'wal_filename'} $master_cib_value{'pgdata'}/pg_xlog/$another_current_xlog_filename 2> /dev/null | $TAIL -1\"";
        @results = ssh_exec_command($ssh_info, $command);
        if ($results[0] =~ /.*lsn:\s+([0-9A-F\/]+).*/){
            $another_current_xlog_location = $1;
        }

        # 取得した XLOG 位置を比較(自身のノードの XLOG 位置の方が進んでいないか確認)
        $result = compare_lsn($my_current_xlog_location, $another_current_xlog_location);
        if ($result > 0){
            printlog("LOG", SLAVESTART_MS0041, $my_current_xlog_location, $another_current_xlog_location);
            ng_result();
        }

        # STEP6 以降は STEP4 で両系の TLI が同じでないときに確認する
        if ($my_controldata_value{'time_line_id'} < $another_controldata_value{'time_line_id'}){

            # (STEP6)相手ノードのアーカイブから、相手ノードの TLI の時系列履歴ファイルを取得
            # 時系列履歴ファイルの拡張子から圧縮形式を判定し、圧縮形式に応じて展開を行う
            # NOTE: 時系列履歴ファイルが複数存在する場合には、最初に見つかったファイルを参照する
            my $another_tli_historyfile = sprintf("%08X.history", $another_controldata_value{'time_line_id'});
            my $another_tli_history_path = $config_value{'Archive_dir'}."/".$another_tli_historyfile;
            @results = ssh_exec_command($ssh_info, "$LS $another_tli_history_path* 2> /dev/null");
            if ($results[0] eq "") {
                printlog("ERROR", SLAVESTART_MS0042, $another_tli_history_path);
            }
            my @history_files = split(/\n/, $results[0]);
            my $history_file = $history_files[0];
            (my $ext=$history_file) =~ s/^.*\.(.*)$/$1/;
            if ($ext eq "history"){ # 圧縮なし
                @results = ssh_exec_command($ssh_info, "$CAT $history_file");
            }
            elsif ($ext eq "gz"){ # GZIP圧縮
                @results = ssh_exec_command($ssh_info, "$GZIP -dc $history_file");
            }
            elsif ($ext eq "bz2"){ # BZIP2圧縮
                @results = ssh_exec_command($ssh_info, "$BZIP2 -dc $history_file");
            }
            else{  # 未サポートの拡張子
                printlog("ERROR", SLAVESTART_MS0049, $ext);
            }

            # (STEP7)自身ノードの TLI が過去に通っていることを確認
            # NOTE: 相手ノードの TLI の時系列履歴ファイルの内容を見て確認する
            my $my_tli_promote_xloglocation = '';
            my @another_tli_history_strings = split(/\n/, $results[0]);

            foreach my $line (@another_tli_history_strings){
                if ($line =~ /^(\d+)\s+([0-9A-F\/]+)/){
                     if ($my_controldata_value{'time_line_id'} eq $1){
                         $my_tli_promote_xloglocation = $2;
                     }
                }
            }

            if (!$my_tli_promote_xloglocation){
                printlog("LOG", SLAVESTART_MS0043, $another_tli_historyfile);
                ng_result();
            }

            # (STEP8) 自身ノードの現在の LSN よりも先に promote されていないことを確認
            $result = compare_lsn($my_current_xlog_location, $my_tli_promote_xloglocation);
            if ($result >= 0){
                printlog("LOG", SLAVESTART_MS0044, $another_tli_historyfile);
                ng_result();
            }
        }
        printlog("LOG", SLAVESTART_MS0007);
    }

    # check-only オプションが指定されている場合はここで終了する
    if ($check_only_mode) {
        exit(0);
    }

    ### Master のアーカイブディレクトリと同期 ###
    # su コマンドとリモート先を指定する rsync コマンドを併用するとマシンによっては実行できないため、
    # ここでは root ユーザで実行する
    # shared-archive-directory オプションが指定されている場合は実行しない
    if (!$shared_archive_directory_mode) {
        printlog("LOG", SLAVESTART_MS0019, $operation_num++);
        rsync_exec_command($ssh_info, $config_value{'Archive_dir'}."/", $config_value{'Archive_dir'}."/");
        printlog("LOG", SLAVESTART_MS0007);
    }

    ### /var/lib/pacemaker/cib 配下のファイルの削除 ###
    my $cib_dir = CIB_PATH;
    $cib_dir =~ s/\/$//g;
    printlog("LOG", SLAVESTART_MS0020, $operation_num++, $cib_dir);
    $cib_dir = CIB_PATH;
    exec_command("$RM -f $cib_dir"."*");
    printlog("LOG", SLAVESTART_MS0007);

    ### アーカイブリカバリ対象の WAL セグメント数を算出
    # backup_label が存在する場合は backup_label からリカバリが開始される WAL ファイル名を取得する
    my $start_wal_filename;
    my $backup_label_path = $master_cib_value{'pgdata'}."/backup_label";
    if (-f $backup_label_path){
        $result = `$CAT $backup_label_path`;
        my @backup_label_string = split(/\n/, $result);
        $start_wal_filename = get_start_wal_filename($backup_label_path, @backup_label_string);
    }
    # backup_label が存在しない場合は pg_control から取得する
    else {
        $start_wal_filename = $my_controldata_value{'wal_filename'};
    }

    my $wal_segment_num = get_restore_archivewal_num($master_cib_value{'pgdata'}, $config_value{'Archive_dir'}, $start_wal_filename);

    ### Pacemaker 起動 ###
    printlog("LOG", SLAVESTART_MS0021, $operation_num++, $wal_segment_num);
    exec_command("$PMSTART");
    printlog("LOG", SLAVESTART_MS0007);

    ### Slave の起動確認 ###
    printlog("LOG", SLAVESTART_MS0022, $operation_num++);

    # Pacemaker 及び リソースの起動確認
    # 前回起動中に自ノードで PostgreSQL の制御エラーが発生していた場合、Pacemaker 起動から暫くの間は
    # crm_monの結果に PostgreSQL の制御エラー情報(Failed actions)が残っている可能性がある。そのため、
    # 起動確認の前にRA(pgsql) のモニタ間隔以上のディレイをおき、誤検知しないようにする。
    my $error_code = 0;
    sleep $monitor_delay;
    while (1){
        if ($wait_time >= $timeout){
            printlog("LOG", SLAVESTART_MS0005);
            printlog("LOG", SLAVESTART_MS0046, $timeout);
            if ($starting_resource eq "PostgreSQL" && $error_code == 2){
                printlog("ERROR", SLAVESTART_MS0047, $starting_resource);
            }
            else {
                printlog("ERROR", SLAVESTART_MS0048, $starting_resource);
            }
        }
        sleep $monitor_interval;
        $wait_time += $monitor_interval;

        if (!pacemaker_online($node_value{'my_node'})){
            $starting_resource = "Pacemaker";
            next;
        }

        if (pgrex_failed_action($node_value{'my_node'}, $config_value{'PG-REX_Primitive_ResourceID'})){
            printlog("LOG", SLAVESTART_MS0005);
            printlog("ERROR", SLAVESTART_MS0024);
        }

        if (!network_running($node_value{'my_node'}, $node_value{'another_node'}, \%iclan_ipaddr)){
            $starting_resource = "IC-LAN monitor";
            next;
        }

        # PING のリソース ID 指定有りの場合、起動確認を行なう
        if ($config_value{'PING_ResourceID'} && !ping_running($node_value{'my_node'}, $config_value{'PING_ResourceID'})){
            $starting_resource = "PING";
            next;
        }

        # DISKD のリソース ID 指定有りの場合、起動確認を行なう
        if ($config_value{'DISKD_ResourceID'} && !diskd_running($node_value{'my_node'}, $config_value{'DISKD_ResourceID'})){
            $starting_resource = "DISKD";
            next;
        }

        # STONITH 環境有りかつリソース ID 指定有りの場合、起動確認を行なう
        if ($config_value{'STONITH_ResourceID'} && !stonith_running($node_value{'my_node'}, $config_value{'STONITH_ResourceID'})){
            $starting_resource = "STONITH";
            next;
        }

        if (!slave_running($node_value{'my_node'}, $config_value{'PG-REX_Master_ResourceID'}, $config_value{'PG-REX_Primitive_ResourceID'}, \$error_code)){
            $starting_resource = "PostgreSQL";
            next;
        }

        # VIP-SLAVE 環境有りかつリソース ID 指定有りの場合、起動確認を行なう
        if ($config_value{'VIP-SLAVE_ResourceID'} && !vip_running($node_value{'my_node'}, $config_value{'VIP-SLAVE_ResourceID'})){
            $starting_resource = "VIP-SLAVE";
            next;
        }

        # crm_mon の結果が全て揃ったら無限ループを抜ける
        last;
    }

    printlog("LOG", SLAVESTART_MS0007);
    printlog("LOG", SLAVESTART_MS0029, $node_value{'my_node'});
    exit(0);
}

sub ng_result {

    printlog("LOG", SLAVESTART_MS0005);
    printlog("ERROR", SLAVESTART_MS0045);

}

