#!/usr/bin/perl
#####################################################################
# Function: pg-rex_stop
#
#
# 概要:
# PG-REX での停止実行ツール。
# 手順の簡易化を目的として作成している。
# 
# 特記事項:
# なし
#
# Copyright (c) 2012,2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
#
#####################################################################
use warnings;
use strict;
use Getopt::Long;
use lib qw(/usr/local/share/pg-rex);
use include::command;
use common qw(postgres_running pacemaker_running slave_running
              read_config read_cib read_hacf exec_command get_pg_command_path
              check_user printlog);

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

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

main();

1;

sub main{
    my $kill_when_no_data = 1;
    my $help_mode = 0;
    my $my_node = "";
    my $another_node = "";
    my $result;
    my $stop_target = "Stopped";
    my $timeout = 300;
    my $monitor_time = 10;
    my $wait_time = 0;
    my $config_path = "/etc/pg-rex_tools.conf";
    my %config_value;
    my $cib_path = "/var/lib/heartbeat/crm/cib.xml";
    my $hacf_path = "/etc/ha.d/ha.cf";
    my %hacf_value;
    my @node;
    my %my_cib_value;
    my %command_path;

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

    ### スクリプト実行準備 ###
    # 実行ユーザの確認
    check_user();

    # オプション解析
    GetOptions('help' => \$help_mode);
    if ($help_mode){
        printlog("USAGE", STOP_USAGE);
        exit(0);
    }

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

    # コマンドを実行しているマシンのノード名ともう一台のノード名を取得
    $my_node = exec_command("$UNAME -n");
    chomp $my_node;
    %hacf_value = read_hacf($hacf_path);
    foreach my $line (@{$hacf_value{node}}){
        if ($line ne $my_node){
            $another_node = $line;
        }
    }

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

    # cib.xml ファイルを読み込む
    %my_cib_value = read_cib($cib_path, $command_path{'pg_basebackup'}, $config_value{"PG-REX_Primitive_ResourceID"}, $kill_when_no_data);

    ### Pacemaker 停止準備 ###
    # Pacemaker のプロセスを確認
    # Pacemaker のプロセスが無かったら、処理を終了
    # ※Pacemaker が停止していて、PostgreSQL が起動中の場合も処理を終了させる
    if (!pacemaker_running()){
        printlog("LOG", STOP_MS0004);
        exit(0);
    }

    # PostgreSQL のプロセスを確認i
    # DB クラスタの位置が確認できなかったら、PostgreSQL のプロセスの確認を行わずに Pacemaker を停止させる
    if (!exists($my_cib_value{"pgdata"})){
        printlog("LOG", STOP_MS0017, $config_value{"PG-REX_Primitive_ResourceID"});
    }
    elsif (!postgres_running($my_cib_value{"pgdata"})){
        printlog("LOG", STOP_MS0005);
    }
    else{
        $result = exec_command("$SU - postgres -c \" $command_path{'psql'} -t -c \\\"SELECT pg_is_in_recovery(); \\\" \" ");
        chomp $result;
        # SQL result format : <space><values>
        $result =~ s/\s//g;
        if ($result eq "f"){
            $stop_target = "Master";
            printlog("LOG", STOP_MS0006);
        }
        else {
            $stop_target = "Slave";
            printlog("LOG", STOP_MS0007);
        }
    }

    # Master を停止する場合でかつ Slave が起動中の場合、ユーザに確認
    if ($stop_target eq "Master" && slave_running($another_node, $config_value{"PG-REX_Master_ResourceID"}, $config_value{"PG-REX_Primitive_ResourceID"})){
        printlog("LOG", STOP_MS0008);
        my $check = <STDIN>;
        chomp $check;
        if ($check !~ m/^y$/i) {
            printlog("LOG", STOP_MS0009);
            exit(0);
        }
    }

    ### Pacemaker 停止 ###
    printlog("LOG", STOP_MS0010);
    exec_command("$SERVICE heartbeat stop");
    printlog("LOG", STOP_MS0011);

    ### Pacemaker 停止確認 ###
    printlog("LOG", STOP_MS0012);
    # プロセスの確認
    while (1){
        # Pacemaker 、PostgreSQL のプロセス確認ができた場合、無限ループを抜ける
        if (!pacemaker_running()){
            if (!exists($my_cib_value{"pgdata"})){
                last;
            }
            elsif (!postgres_running($my_cib_value{"pgdata"})){
                last;
            }
        }

        if ($wait_time >= $timeout){
            printlog("LOG", STOP_MS0013);
            printlog("ERROR", STOP_MS0014, $timeout);
        }

        sleep $monitor_time;
        $wait_time += $monitor_time;
    }
    printlog("LOG", STOP_MS0011);

    if ($stop_target eq "Stopped"){
        printlog("LOG", STOP_MS0015, $my_node);
    }
    else {
        printlog("LOG", STOP_MS0016, $stop_target, $my_node);
    }

    exit(0);
}