#!/usr/bin/perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#(C)IBM Corp

#

BEGIN
{
    $::XCATROOT =
      $ENV{'XCATROOT'} ? $ENV{'XCATROOT'}
      : -d '/opt/xcat' ? '/opt/xcat'
      :                  '/usr';
}
use lib "$::XCATROOT/lib/perl";
use Getopt::Long;
use xCAT::MsgUtils;
use xCAT::Utils;
use strict;

#-----------------------------------------------------------------------------

=head1  dumpxCATdb



 dumpxCATdb  -p <directory to place database dump>
 See man page.

=cut

#-----------------------------------------------------------------------------
# Main
my $rc = 0;
my $cmd;
&parse_args;
if ($::BINARY) {    # not using xCAT to dump, using the database utility
    my $DBname = xCAT::Utils->get_DBName;
    if ($DBname eq "DB2") {
        $rc = &DB2_bindump;
        if ($rc == 0) {
            xCAT::MsgUtils->message("I", "Backup Complete.");
        } else {
            xCAT::MsgUtils->message("I", "Backup Failed.");
        }
        exit $rc;
    } else {
        if ($DBname eq "PG") {
            $rc = &PG_bindump;
            if ($rc == 0) {
                xCAT::MsgUtils->message("I", "Backup Complete.");
            } else {
                xCAT::MsgUtils->message("I", "Backup Failed.");
            }
            exit $rc;
        } else {
            xCAT::MsgUtils->message("E",
                "Binary dump (-b) is not supported for $DBname");
            exit 1;
        }
    }
}


# Dump using xCAT utilities
my @output = xCAT::Utils->runcmd("tabdump", 0);
if ($::RUNCMD_RC != 0)
{    # error
    xCAT::MsgUtils->message("E",
        "Error running tabdump to get list of tables");
    exit 1;
}

# Determine which table to skip
my @output2;
if ($ENV{'XCAT_SKIPTABLES'}) {
    @output2 = $ENV{'XCAT_SKIPTABLES'};
} else {

    # read tables to skip  from site.skiptables attribute
    @output2 = xCAT::TableUtils->get_site_attribute('skiptables');
}
my @skiptbls;
if (@output2) {
    @skiptbls = split(/\,/, $output2[0]);
}
foreach my $table (@output)
{
    # if not -a request , skip eventlog and auditlog
    if ((!$::ALL) && (($table =~ /^eventlog/) || ($table =~ /^auditlog/))) {
        if ($::DUMPVERBOSE) {
            xCAT::MsgUtils->message("I", "Skipping $table\n");
        }
        next;
    }

    # skip teal tables
    if ($table =~ /^x_teal/) {
        if ($::DUMPVERBOSE) {
            xCAT::MsgUtils->message("I", "Skipping $table\n");
        }
        next;
    }

    # skip ISNM tables except isnm_config
    if ($table =~ /^isnm_perf/) {
        if ($::DUMPVERBOSE) {
            xCAT::MsgUtils->message("I", "Skipping $table\n");
        }
        next;
    }

    # skip any table in the site.skiptables attribute
    if (grep(/^$table$/, @skiptbls)) {
        if ($::DUMPVERBOSE) {
            xCAT::MsgUtils->message("I", "Skipping $table\n");
        }
        next;
    }

    $cmd = "tabdump -f $::PATH/$table.csv $table";
    my @errout = xCAT::Utils->runcmd($cmd, 0);
    if ($::RUNCMD_RC != 0)
    {    # error
        xCAT::MsgUtils->message("E", "Error running $cmd, @errout");
    } else {
        if ($::DUMPVERBOSE) {
            xCAT::MsgUtils->message("I", "Dumping $table");
        }
    }

}
xCAT::MsgUtils->message("I", "Backup Complete.");
exit $rc;

#-----------------------------------------------------------------------------

=head3 parse_args

  Parses for  input

=cut

#-----------------------------------------------------------------------------
sub parse_args
{
    my $msg;
    my $usagemsg =
" dumpxCATdb -h \n dumpxCATdb -v \n dumpxCATdb [-a] [-V] <-p> [path to backup directory] \n dumpxCATdb -b [-V] <-p> [path to backup directory]";
    Getopt::Long::Configure("posix_default");
    Getopt::Long::Configure("no_gnu_compat");
    Getopt::Long::Configure("bundling");
    if (
        !GetOptions(
            'a|all'     => \$::ALL,
            'b|bin'     => \$::BINARY,
            'p|path=s'  => \$::PATH,
            'h|help'    => \$::HELP,
            'V|verbose' => \$::DUMPVERBOSE,
            'v|version' => \$::VERSION

        )
      )
    {
        xCAT::MsgUtils->message("E", $usagemsg);
        exit 1;
    }
    if ($::HELP)
    {
        xCAT::MsgUtils->message("I", $usagemsg);
        exit 0;
    }
    if ($::VERSION)
    {
        my $version = xCAT::Utils->Version();
        xCAT::MsgUtils->message("N", $version);
        exit 0;
    }
    if (!($::PATH))
    {
        my $msg = " Requires -p with path to directory to hold db files.";
        xCAT::MsgUtils->message("E", $msg);
        exit 1;
    }
    if (!(-e $::PATH)) {
        my $msg = " Creating $::PATH for database dump";
        xCAT::MsgUtils->message("I", $msg);
        my @output = xCAT::Utils->runcmd("mkdir -p $::PATH", 0);
        if ($::RUNCMD_RC != 0)
        {    # error
            xCAT::MsgUtils->message("E",
                "Error running mkdir -p $::PATH");
            exit 1;
        }
    }

}

#-----------------------------------------------------------------------------

=head3 DB2_bindump

    Uses the DB2 Database supplied backup utility to backup the database

=cut

#-----------------------------------------------------------------------------
sub DB2_bindump
{
    my $msg;
    my $rc = 0;

    # check to see if they are setup to do an online dump
    # Database has to have defined logretain RECOVERY and there
    # must already been taken an offline backup.
    my $cmd = "db2 get database configuration for xcatdb > /tmp/db2output";
    $rc = &rundb2cmd($cmd);    # must su to xcatdb
    if ($rc != 0)
    {
        xCAT::MsgUtils->message("E", " $cmd error.");
        return 1;
    }

    # check to see if they setup log recover
    $cmd = " egrep -i \"Log retain for recovery enabled\" /tmp/db2output";
    my @output = xCAT::Utils->runcmd($cmd, -1);
    if ($::RUNCMD_RC != 0) {
        xCAT::MsgUtils->message("E", "Log retain for recovery enabled (LOGRETAIN) = RECOVERY must be set to perform ONLINE Backups and one ONLINE backup must have been taken. See  xCAT DB2 documentation. The section - Backup/Restore the database with DB2 Commands.");
        return 1;
    } else {    # check to see if LOGRETAIN is ON
        if (!grep(/ = RECOVERY/, @output)) {
            xCAT::MsgUtils->message("E", "Log retain for recovery enabled (LOGRETAIN) = RECOVERY  must be set to perform ONLINE Backups and one ONLINE backup must have been taken. See  xCAT DB2 documentation. The section - Backup/Restore the database with DB2 Commands.");
            return 1;
        }
    }

    # check to see if they have one backup
    $cmd = " ls $::PATH";
    @output = xCAT::Utils->runcmd($cmd, -1);
    if ($::RUNCMD_RC != 0) {
        xCAT::MsgUtils->message("E", "One ONLINE backup must have been taken and exist in $::PATH. See  xCAT DB2 documentation. The section - Backup/Restore the database with DB2 Commands.");
        return 1;
    } else {    # check to see if LOGRETAIN is ON
        if (!grep(/XCATDB/, @output)) {
            xCAT::MsgUtils->message("E", "One ONLINE backup must have been taken and exist in $::PATH. See  xCAT DB2 documentation. The section - Backup/Restore the database with DB2 Commands.");
            return 1;
        }
    }

    # finally all checks ok, can take an ONLINE backup
    # get password from cfgloc

    my $cmd = "cat /etc/xcat/cfgloc";
    my $info = xCAT::Utils->runcmd($cmd, -1);
    if ($::RUNCMD_RC != 0) {
        xCAT::MsgUtils->message("E", "Cannot read /etc/xcat/cfgloc.");
        return 1;
    }
    chomp($info);
    my ($db, $inst, $pw) = split(/\|/, $info);

    my $cmd = " db2 backup db xcatdb user xcatdb using $pw ONLINE to $::PATH";
    $rc = &rundb2cmd($cmd);    # must su to xcatdb
    if ($rc != 0)
    {
        xCAT::MsgUtils->message("E", " $cmd error.");
        return 1;
    }
    return 0;

}

#-----------------------------------------------------------------------------

=head3 PG_bindump

    Uses the PostgreSQL Database supplied backup utility to backup the database

=cut

#-----------------------------------------------------------------------------
sub PG_bindump
{
    my $msg;
    my $rc       = 0;
    my $pgcmddir = "/usr/bin";

    # get path to Postgresql commands if running 9.X version
    my $cmd = "rpm -qa | grep postgresql";
    my @output = xCAT::Utils->runcmd($cmd, 0);
    if ($::RUNCMD_RC != 0)
    {
        my $message =
"\nPostgreSQL is not installed.  If on AIX, it should be first obtained from the xcat dependency tarballs and installed before running this command.\n If on Linux, install from the OS CDs.";
        xCAT::MsgUtils->message("E", " $cmd failed. $message");
        exit(1);
    }

    # check if 9.X release,  setup different
    if (grep(/postgresql9/, @output)) {    # postgresql 9.x
            # figure out which 9.x release  and build path
            # for example 9.x release /usr/pgsql-9.x/bin
        my @parseout = split(/\-/,          $output[0]);
        my @ptflevel = split("postgresql9", $parseout[0]);
        my $postgres9 = @ptflevel[1];    # set it to the PTF level
        $pgcmddir = "/usr/pgsql-9.$postgres9/bin";    # pg cmds location
    }

    # Get database, admin from cfgloc file
    my $cmd = "cat /etc/xcat/cfgloc";
    my $info = xCAT::Utils->runcmd($cmd, -1);
    if ($::RUNCMD_RC != 0) {
        xCAT::MsgUtils->message("E", "Cannot read /etc/xcat/cfgloc.");
        return 1;
    }
    chomp($info);
    my ($db, $admin, $pw) = split(/\|/, $info);
    my ($info1,  $info2) = split(/=/, $db);
    my ($dbname, $host)  = split(/;/, $info2);

    # create backup file name
    my $backupfile = "$::PATH/pgbackup.$$";
    my $cmd = "$pgcmddir/pg_dump $dbname -f $backupfile -U postgres -F custom";
    my $info = xCAT::Utils->runcmd($cmd, -1);
    if ($::RUNCMD_RC != 0) {
        xCAT::MsgUtils->message("E", "$cmd failed");
        return 1;
    }
    return 0;

}

#-----------------------------------------------------------------------------

=head3   rundb2cmd


  Run a commmand as the xcatdb instance id
  Input: command

=cut

#-----------------------------------------------------------------------------
sub rundb2cmd
{
    my $orgcmd = shift;
    my $rc     = 0;
    my $cmd    = "\'";
    $cmd .= $orgcmd;
    $cmd .= ' 2>&1';
    $cmd .= "\'";
    system("su - xcatdb -c $cmd");
    if ($? > 0)    # error
    {
        $rc = $? >> 8;
    }
    return ($rc);
}

