diff --git a/bin/pg_backrest.pl b/bin/pg_backrest.pl index 03763d231..46932ec2f 100755 --- a/bin/pg_backrest.pl +++ b/bin/pg_backrest.pl @@ -19,6 +19,7 @@ use BackRest::Utility; use BackRest::Config; use BackRest::File; use BackRest::Backup; +use BackRest::Restore; use BackRest::Db; #################################################################################################################################### @@ -493,6 +494,19 @@ if (operation_get() eq OP_BACKUP) operation_set(OP_EXPIRE); } +#################################################################################################################################### +# RESTORE +#################################################################################################################################### +if (operation_get() eq OP_RESTORE) +{ + new BackRest::Restore + ( + config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH), + undef, + $oFile + )->restore; +} + #################################################################################################################################### # EXPIRE #################################################################################################################################### diff --git a/lib/BackRest/Config.pm b/lib/BackRest/Config.pm index d5516e8d8..3bc10b53b 100644 --- a/lib/BackRest/Config.pm +++ b/lib/BackRest/Config.pm @@ -18,7 +18,7 @@ use Exporter qw(import); our @EXPORT = qw(config_load config_key_load operation_get operation_set param_get - OP_ARCHIVE_GET OP_ARCHIVE_PUSH OP_BACKUP OP_EXPIRE + OP_ARCHIVE_GET OP_ARCHIVE_PUSH OP_BACKUP OP_RESTORE OP_EXPIRE BACKUP_TYPE_FULL BACKUP_TYPE_DIFF BACKUP_TYPE_INCR @@ -46,10 +46,11 @@ our @EXPORT = qw(config_load config_key_load operation_get operation_set param_g #################################################################################################################################### use constant { - OP_ARCHIVE_GET => 'archive-get', - OP_ARCHIVE_PUSH => 'archive-push', - OP_BACKUP => 'backup', - OP_EXPIRE => 'expire' + OP_ARCHIVE_GET => 'archive-get', + OP_ARCHIVE_PUSH => 'archive-push', + OP_BACKUP => 'backup', + OP_RESTORE => 'restore', + OP_EXPIRE => 'expire' }; #################################################################################################################################### @@ -163,6 +164,7 @@ sub config_load if ($strOperation ne OP_ARCHIVE_GET && $strOperation ne OP_ARCHIVE_PUSH && $strOperation ne OP_BACKUP && + $strOperation ne OP_RESTORE && $strOperation ne OP_EXPIRE) { confess &log(ERROR, "invalid operation ${strOperation}"); diff --git a/lib/BackRest/Restore.pm b/lib/BackRest/Restore.pm new file mode 100644 index 000000000..19e846fa0 --- /dev/null +++ b/lib/BackRest/Restore.pm @@ -0,0 +1,85 @@ +#################################################################################################################################### +# RESTORE MODULE +#################################################################################################################################### +package BackRest::Restore; + +use threads; +use strict; +use warnings; +use Carp; + +use File::Basename; +#use File::Path qw(remove_tree); +#use Scalar::Util qw(looks_like_number); +#use Thread::Queue; + +use lib dirname($0); +use BackRest::Utility; +use BackRest::Config; +use BackRest::File; +use BackRest::Db; + +#################################################################################################################################### +# CONSTRUCTOR +#################################################################################################################################### +sub new +{ + my $class = shift; # Class name + my $strDbClusterPath = shift; # Database cluster path + my $strBackupPath = shift; # Backup to restore + my $oFile = shift; # Default file object + + # Create the class hash + my $self = {}; + bless $self, $class; + + # Initialize variables + $self->{strDbClusterPath} = $strDbClusterPath; + + if (defined($strBackupPath)) + { + $self->{strBackupPath} = $strBackupPath; + } + else + { + $self->{strBackupPath} = 'latest'; + } + + $self->{oFile} = $oFile; + + return $self; +} + +#################################################################################################################################### +# RESTORE +#################################################################################################################################### +sub restore +{ + my $self = shift; # Class hash + + # Make sure that Postgres is not running + if ($self->{oFile}->exists(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/postmaster.pid')) + { + confess &log(ERROR, 'unable to restore while Postgres is running'); + } + + # Make sure the backup path is valid and load the manifest + if ($self->{oFile}->exists(PATH_BACKUP_CLUSTER, $self->{strBackupPath})) + { + # Copy the backup manifest to the db cluster path + $self->{oFile}->copy(PATH_BACKUP_CLUSTER, $self->{strBackupPath} . '/backup.manifest', + PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/backup.manifest'); + + # Load the manifest into a hash + ini_load($self->{oFile}->path_get(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/backup.manifest')); + + # Remove the manifest now that it is in memory + $self->{oFile}->remove(PATH_DB_ABSOLUTE, $self->{strDbClusterPath} . '/backup.manifest'); + } + else + { + confess &log(ERROR, 'backup ' . $self->{strBackupPath} . ' does not exist'); + } +} + +1; diff --git a/test/lib/BackRestTest/BackupTest.pm b/test/lib/BackRestTest/BackupTest.pm index 12c7cf2b9..8c0ef490a 100755 --- a/test/lib/BackRestTest/BackupTest.pm +++ b/test/lib/BackRestTest/BackupTest.pm @@ -528,6 +528,22 @@ sub BackRestTestBackup_CompareBackup $oFile->remove(PATH_ABSOLUTE, "${strTestPath}/actual.manifest"); } + +#################################################################################################################################### +# BackRestTestBackup_CompareRestore +#################################################################################################################################### +sub BackRestTestBackup_CompareRestore +{ + my $oFile = shift; + my $strBackup = shift; + my $strStanza = shift; + my $oExpectedManifestRef = shift; + + # Create the backup command + BackRestTestCommon_Execute(BackRestTestCommon_CommandMainGet() . ' --config=' . BackRestTestCommon_DbPathGet() . + "/pg_backrest.conf --stanza=${strStanza} restore"); +} + #################################################################################################################################### # BackRestTestBackup_Test #################################################################################################################################### @@ -943,6 +959,7 @@ sub BackRestTestBackup_Test my $strFullBackup = BackRestTestBackup_LastBackup($oFile); BackRestTestBackup_CompareBackup($oFile, $bRemote, $strFullBackup, \%oManifest); + BackRestTestBackup_CompareRestore($oFile, $strFullBackup, $strStanza, \%oManifest); # Perform first incr backup BackRestTestBackup_ManifestReference(\%oManifest, $strFullBackup);