#!/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 { if ($DBname eq "PG") { $rc=&PG_binrestore; if ($rc == 0) { xCAT::MsgUtils->message("I", "Restore Complete."); } else { xCAT::MsgUtils->message("I", "Restore Failed."); } exit $rc; } else { xCAT::MsgUtils->message("E", "Binary dump (-b) is not supported for $DBname"); 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::TableUtils->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 PG_binrestore Uses the PostgreSQL Database supplied backup utility to restore the database =cut #----------------------------------------------------------------------------- sub PG_binrestore { 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); # restore from backup file my $cmd="$pgcmddir/pg_restore $::PATH -U postgres -d $dbname -c "; 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); }