#!/usr/bin/perl
use strict;
use warnings;

# -----------------------------------------------------------------------------
#  Proxy script introduced due to security requirements
#  Performs database recovery via pg_restore using "postgres" DB user account
#  Must be run by root
# -----------------------------------------------------------------------------
#  Author: Alexey Tsibulnik
#  Modified by: 
#  QA by:  
#  Copyright: videoNEXT Network solutions, Inc.
# -----------------------------------------------------------------------------

# CONS
my $APL = $ENV{APL};
my $DB_USER = $ENV{APL_DB_USR};
my $PSQL = $^O =~ /darwin/i ? "$APL/imp/bin/pgsql" : "/usr/bin/psql";;
my $PG_RESTORE = $^O =~ /darwin/i ? "$APL/imp/bin/pg_restore" : "/usr/bin/pg_restore";
my $PG_DUMP = $^O =~ /darwin/i ? "$APL/imp/bin/pg_dump" : "/usr/bin/pg_dump";
my $TMP_PATH = "/tmp";

# VARS
my %DB;
my %args = map {/^(\w+)=(.*)$/} grep {/^\w+=/} @ARGV;
my $ConfDBPath = $args{CONFDB};
my $TransDBPath = $args{TRANSDB};
my $TransDBSchemaPath = $args{TRANSDB_SCHEMA};
my $AplDBPath = $args{APLDB};
my $Update = $args{UPDATE};
my $Errors = 0;

# SUB
sub log_msg
{
    my $msg = shift;
    chomp $msg;
    print "$msg\n";
}

sub validate_args
{
    die "Must be run by root\n" unless $> == 0;
    die "Environment not set\n" unless defined $APL and defined $DB_USER;
    # Check confdb backup
    die "ConfDB path not specified\n" unless $ConfDBPath;
    die "Invalid path to ConfDB backup\n" unless -f $ConfDBPath;
    die "Invalid ConfDB backup format\n" unless system("$PG_RESTORE -l $ConfDBPath &>/dev/null") == 0;
    # Check apldb backup
    die "AplDB path not specified\n" unless $AplDBPath;
    die "Invalid path to AplDB backup\n" unless -f $AplDBPath;
    die "Invalid AplDB backup format\n" unless system("$PG_RESTORE -l $AplDBPath &>/dev/null") == 0;
    if ($TransDBPath) { # Check transdb backup if specified
        die "Invalid path to TransDB backup\n" unless -f $TransDBPath;
        die "Invalid TransDB backup format\n" unless system("$PG_RESTORE -l $TransDBPath &>/dev/null") == 0;
    }
    elsif ($TransDBSchemaPath) { # Check transdb schema backup if specified
        die "Invalid path to TransDB schema backup\n" unless -f $TransDBSchemaPath;
    }
}

sub read_db_conf
{
    # Read DB conf
    my $dbConfFile = "$ENV{APL}/etc/skm_master.db.conf";
    open(DB_CONF_FILE, "<$dbConfFile")
    	or die "unable to open configuration file $dbConfFile\n";
    %DB = map{/(^.+?)=(.*)/} grep {/^.+=.*/} <DB_CONF_FILE>;
    close(DB_CONF_FILE);
}

sub pg_cmd
{
    my ($cmd) = @_;
    my $out = `$PSQL -d '$DB{name}' -h '$DB{host}' -U '$DB_USER' -c \"$cmd\" 2>&1`;
    $Errors++ if $?;
    log_msg("> pg_cmd: $cmd");
    log_msg($out);
    return $out;
}

sub pg_dump
{
    my ($db, $path) = @_;
    system("$PG_DUMP -h '$DB{host}' -U '$DB_USER' -n $db -F c $DB{name} > $path 2>/dev/null");
}

sub pg_restore
{
    my ($db, $path, $plain) = @_;
    my $out;
    if ($plain) {
        $out = `$PSQL -d '$DB{name}' -h '$DB{host}' -U '$DB_USER' -f $path 2>&1`;
    }
    else {
        $out = `$PG_RESTORE -v -d '$DB{name}' -h '$DB{host}' -U '$DB_USER' --schema=$db  --disable-triggers -F c $path 2>&1`;
    }
    log_msg("> pg_restore: schema=$db path=$path");
    log_msg($out);
    return $out;
}

sub restore
{
    print "======= Starting db_restore =======\n";
    print "args: @ARGV\n";
    # Drop 'apl' schema
    pg_cmd("DROP SCHEMA apl CASCADE;");

    # Restore confdb
    print "================= CONFDB RESTORE =====================\n";
    pg_cmd("DROP SCHEMA confdb CASCADE;");
    pg_cmd("CREATE SCHEMA confdb;");
    my $out = pg_restore("confdb", $ConfDBPath);
    my ($err) = $out =~ /^WARNING: errors ignored on restore: (\d+)$/smi;
    warn "Restore confdb: $err errors\n" if $err;
    $Errors++ if $?;
    
    # Restore transdb if specified
    if ($TransDBPath) {
        print "================= TRANSDB RESTORE =====================\n";
        pg_cmd("DROP SCHEMA transdb CASCADE;");
        pg_cmd("CREATE SCHEMA transdb;");
        my $out = pg_restore("transdb", $TransDBPath);
        my ($err) = $out =~ /^WARNING: errors ignored on restore: (\d+)$/smi;
        warn "Restore transdb: $err errors\n" if $err;
        $Errors++ if $?;
    }
    elsif ($TransDBSchemaPath) {
        # Special case for migration from 3.7
        print "================= TRANSDB SCHEMA RESTORE =====================\n";
        pg_cmd("DROP SCHEMA transdb CASCADE;");
        my $out = pg_restore("transdb", $TransDBSchemaPath, 1);
        warn "Restore transdb schema finished with erros!\n" if $?;
        $Errors++ if $?;
    }
    
    # Finally, restore apl schema and user permissions
    pg_cmd("CREATE SCHEMA apl;");
    $out = pg_restore("apl", $AplDBPath);
    ($err) = $out =~ /^WARNING: errors ignored on restore: (\d+)$/smi;
    warn "Restore apl: $err errors\n" if $err;
    $Errors++ if $?;

    pg_cmd("GRANT USAGE ON SCHEMA apl TO apl");
    
    # Run update scripts if specified in command line
    if ($Update) {
	$Errors++ if system("$APL/db/bin/db_update confdb") != 0;
	$Errors++ if system("$APL/db/bin/db_update transdb") != 0;
    }
}

sub main
{
    validate_args;
	
    read_db_conf;
    
    restore;
    
    exit $Errors;
}

# MAIN
main;
