#!/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 {
    xCAT::MsgUtils->message("E",
                            "Binary dump (-b) is only supported for DB2");
    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::Utils->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   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);
}

