#!/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  restorexCATdb 



 restorexCATdb  -p <directory containing db restore .csv files> 
 restorexCATdb -b -p <directory binary database backup> 


=cut

#-----------------------------------------------------------------------------
# Main
my $rc = 0;

&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_binrestore;
     if ($rc == 0) {
       xCAT::MsgUtils->message("I", "Restore Complete. You can now restart the daemons.");
     } else {
       xCAT::MsgUtils->message("E", "Restore Failed.");
     }
     exit $rc;
   }  else {
    xCAT::MsgUtils->message("E",
                            "Binary restore (-b) is only supported for DB2");
    exit 1;
   }
}
# read all the *.csv files from the input directory and restore the database
opendir DIRPATH, $::PATH;
if ($? != 0)
{
    my $msg = " Unable to read directory $::PATH \n";
    xCAT::MsgUtils->message("E", $msg);
    exit 1;
}
# read tables to skip during restore from site.skiptables attribute
my @output2=xCAT::Utils->get_site_attribute('skiptables');
my @skiptbls;
if (@output2) {
  @skiptbls = split (/\,/,$output2[0]);
}

my @files = readdir(DIRPATH);
foreach my $table (@files)
{
    if ($table ne '.' and $table ne '..')
    {
        my $tablename = $::PATH;
        $tablename .= "/";
        $tablename .= $table;
        if ( (!$::ALL) && (($table =~ /^eventlog/) || ($table =~ /^auditlog/))) {
            
          if ($::VERBOSEREST) {
            xCAT::MsgUtils->message("I", "Skipping $table\n");
          }
          next;
        }
        # skip teal tables
        if ( $table =~ /^x_teal/ ) {
           if ($::VERBOSEREST) {
            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 and table in the site.skiptables attribute
        if (@skiptbls) {
          my ($tmptable,$suffix) = split(/\./,$table);
          chomp $tmptable;
          if (grep(/^$tmptable$/, @skiptbls)) {
            if ($::VERBOSEREST) {
             xCAT::MsgUtils->message("I", "Skipping $tmptable\n");
            }
             next;
          }
        }

        my $cmd = "tabrestore $tablename";
        my @errout = xCAT::Utils->runcmd($cmd, 0);
        if ($::RUNCMD_RC != 0)
        {    # error
            xCAT::MsgUtils->message("E", "Error running $cmd, @errout\n");
        } else {
          if ($::VERBOSEREST) {
            xCAT::MsgUtils->message("I", "Restoring $table.\n");
          }
        }
    }
}
closedir DIRPATH;
xCAT::MsgUtils->message("I", "Restore of Database Complete.");
exit $rc;

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

=head3 parse_args
  
  Parses for  input

=cut

#-----------------------------------------------------------------------------
sub parse_args
{
    my $msg;
    my    $usagemsg =
          " restorexCATdb  -h \n restorexCATdb -v \n restorexCATdb [-a] [-V] <-p> [path to restore .csv files]\n restorexCATdb -b [-V] <-t> [timestamp on restore backup file]  <-p> [path to restore backup file]";
    Getopt::Long::Configure("posix_default");
    Getopt::Long::Configure("no_gnu_compat");
    Getopt::Long::Configure("bundling");
    if (
        !GetOptions(
            'a|all'  => \$::ALL,
            'b|binary'  => \$::BINARY,
            'p|path=s'  => \$::PATH,
            't|timestamp=s'  => \$::TIMESTAMP,
            'h|help'    => \$::HELP,
            'V|verbose'    => \$::VERBOSEREST,
            '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 = " -p with path to database files is required \n";
        xCAT::MsgUtils->message("E", $msg);
        exit 1;
    }
    if (!(-e $::PATH))
    {
        my $msg = " Input path must exist \n";
        xCAT::MsgUtils->message("E", $msg);
        exit 1;
    }

}
#-----------------------------------------------------------------------------

=head3 DB2_binrestore

    Uses the DB2 Database supplied restore utility to restore the database

=cut

#-----------------------------------------------------------------------------
sub DB2_binrestore
{
    my $msg;
    my $rc=0;
    if (!($::TIMESTAMP)){
       xCAT::MsgUtils->message("E", "To restore from a binary backup, the timestamp of the backup must be provided with the -t option.");
          return 1;
    }
    # check to see if  xcatd running.   Cannot restore if it is
    my $cmd = "ps -ef | grep xcatd";
    my @output=xCAT::Utils->runcmd($cmd, -1);
    if ($::RUNCMD_RC == 0) {  # found something
       if (grep(/xcatd: SSL listener/, @output)) { # xcatd running
          xCAT::MsgUtils->message("E", "xcatd is still accessing the database. All applications accessing the DB2 database must be stopped before you can restore.");
          return 1;

       }
    }
    # 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);

    # Hopefully nothing else is accessing the database, so try restore
    $cmd="db2 restore db xcatdb user xcatdb using $pw from $::PATH taken at $::TIMESTAMP";
    $rc  = &rundb2cmd($cmd);  # must su to xcatdb
    if ($rc != 0)
    {
      xCAT::MsgUtils->message("E", " $cmd error.");
      return 1;
    }
    #  Now roll forward any tranactions since the backup
    $cmd="db2 rollforward database xcatdb to end of logs and complete";
    $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);
}