#!/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 restorexCATdb -b -p =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); }