You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-06-20 01:17:49 +02:00
Fixed an issue retrieving WAL for old database versions.
After a stanza-upgrade it should still be possible to restore backups from the previous version and perform recovery with archive-get. However, archive-get only checked the most recent db version/id and failed. Also clean up some issues when the same db version/id appears multiple times in the history. Fixed by Cynthia Shang. Reported by Clinton Adams.
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
####################################################################################################################################
|
||||
# Archive Get and Base Tests
|
||||
####################################################################################################################################
|
||||
package pgBackRestTest::Module::Archive::ArchiveGetTest;
|
||||
use parent 'pgBackRestTest::Env::ConfigEnvTest';
|
||||
|
||||
####################################################################################################################################
|
||||
# Perl includes
|
||||
####################################################################################################################################
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
|
||||
use Storable qw(dclone);
|
||||
use Digest::SHA qw(sha1_hex);
|
||||
|
||||
use pgBackRest::Archive::Common;
|
||||
use pgBackRest::Archive::Get::Get;
|
||||
use pgBackRest::Archive::Info;
|
||||
use pgBackRest::Common::Exception;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::DbVersion;
|
||||
use pgBackRest::Manifest;
|
||||
use pgBackRest::Protocol::Storage::Helper;
|
||||
|
||||
use pgBackRestTest::Env::HostEnvTest;
|
||||
use pgBackRestTest::Common::ExecuteTest;
|
||||
use pgBackRestTest::Common::RunTest;
|
||||
|
||||
####################################################################################################################################
|
||||
# initModule
|
||||
####################################################################################################################################
|
||||
sub initModule
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
$self->{strDbPath} = $self->testPath() . '/db';
|
||||
$self->{strRepoPath} = $self->testPath() . '/repo';
|
||||
$self->{strArchivePath} = "$self->{strRepoPath}/archive/" . $self->stanza();
|
||||
$self->{strBackupPath} = "$self->{strRepoPath}/backup/" . $self->stanza();
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# initTest
|
||||
####################################################################################################################################
|
||||
sub initTest
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Clear cache from the previous test
|
||||
storageRepoCacheClear($self->stanza());
|
||||
|
||||
# Load options
|
||||
$self->configTestClear();
|
||||
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
||||
$self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo');
|
||||
$self->optionTestSet(CFGOPT_DB_PATH, $self->{strDbPath});
|
||||
$self->configTestLoad(CFGCMD_ARCHIVE_GET);
|
||||
|
||||
# Create archive info path
|
||||
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
|
||||
# Create backup info path
|
||||
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
|
||||
# Create pg_control path
|
||||
storageTest()->pathCreate($self->{strDbPath} . '/' . DB_PATH_GLOBAL, {bCreateParent => true});
|
||||
|
||||
# Copy a pg_control file into the pg_control path
|
||||
executeTest(
|
||||
'cp ' . $self->dataPath() . '/backup.pg_control_' . WAL_VERSION_94 . '.bin ' . $self->{strDbPath} . '/' .
|
||||
DB_FILE_PGCONTROL);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# run
|
||||
####################################################################################################################################
|
||||
sub run
|
||||
{
|
||||
my $self = shift;
|
||||
my $oArchiveBase = new pgBackRest::Archive::Base();
|
||||
|
||||
# Define test file
|
||||
my $strFileContent = 'TESTDATA';
|
||||
my $strFileHash = sha1_hex($strFileContent);
|
||||
my $iFileSize = length($strFileContent);
|
||||
|
||||
my $strDestinationPath = $self->{strDbPath} . "/pg_xlog";
|
||||
my $strDestinationFile = $strDestinationPath . "/RECOVERYXLOG";
|
||||
my $strWalSegment = '000000010000000100000001';
|
||||
my $strArchivePath;
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Archive::Base::getCheck()"))
|
||||
{
|
||||
# Create and save archive.info file
|
||||
my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false,
|
||||
{bLoad => false, bIgnoreMissing => true});
|
||||
$oArchiveInfo->create(PG_VERSION_92, WAL_VERSION_92_SYS_ID, false);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_93, WAL_VERSION_93_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 1);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_92, WAL_VERSION_92_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 1);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_94, WAL_VERSION_94_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 10);
|
||||
$oArchiveInfo->save();
|
||||
|
||||
# db-version, db-sys-id passed but combination doesn't exist in archive.info history
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testException(sub {$oArchiveBase->getCheck(PG_VERSION_95, WAL_VERSION_94_SYS_ID, undef, false)}, ERROR_UNKNOWN,
|
||||
"unable to retrieve the archive id for database version '" . PG_VERSION_95 . "' and system-id '" .
|
||||
WAL_VERSION_94_SYS_ID . "'");
|
||||
|
||||
# db-version, db-sys-id and wal passed all undefined
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
my ($strArchiveId, $strArchiveFile, $strCipherPass) = $oArchiveBase->getCheck(undef, undef, undef, false);
|
||||
$self->testResult(sub {($strArchiveId eq PG_VERSION_94 . '-13') && !defined($strArchiveFile) && !defined($strCipherPass)},
|
||||
true, 'undef db-version, db-sys-id and wal returns only current db archive-id');
|
||||
|
||||
# db-version defined, db-sys-id and wal undefined
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
($strArchiveId, $strArchiveFile, $strCipherPass) = $oArchiveBase->getCheck(PG_VERSION_92, undef, undef, false);
|
||||
$self->testResult(sub {($strArchiveId eq PG_VERSION_94 . '-13') && !defined($strArchiveFile) && !defined($strCipherPass)},
|
||||
true, 'old db-version, db-sys-id and wal undefined returns only current db archive-id');
|
||||
|
||||
# db-version undefined, db-sys-id defined and wal undefined
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
($strArchiveId, $strArchiveFile, $strCipherPass) = $oArchiveBase->getCheck(undef, WAL_VERSION_93_SYS_ID, undef, false);
|
||||
$self->testResult(sub {($strArchiveId eq PG_VERSION_94 . '-13') && !defined($strArchiveFile) && !defined($strCipherPass)},
|
||||
true, 'undef db-version, old db-sys-id and wal undef returns only current db archive-id');
|
||||
|
||||
# old db-version, db-sys-id and wal undefined, check = true (default)
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
($strArchiveId, $strArchiveFile, $strCipherPass) = $oArchiveBase->getCheck(PG_VERSION_92, undef, undef);
|
||||
$self->testResult(sub {($strArchiveId eq PG_VERSION_94 . '-13') && !defined($strArchiveFile) && !defined($strCipherPass)},
|
||||
true, 'old db-version, db-sys-id and wal undefined, check = true returns only current db archive-id');
|
||||
|
||||
# old db-version, old db-sys-id and wal undefined, check = true (default)
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testException(sub {$oArchiveBase->getCheck(PG_VERSION_93, WAL_VERSION_93_SYS_ID, undef)}, ERROR_ARCHIVE_MISMATCH,
|
||||
"WAL segment version " . PG_VERSION_93 . " does not match archive version " . PG_VERSION_94 . "\n" .
|
||||
"WAL segment system-id " . WAL_VERSION_93_SYS_ID . " does not match archive system-id " . WAL_VERSION_94_SYS_ID .
|
||||
"\nHINT: are you archiving to the correct stanza?");
|
||||
|
||||
# db-version, db-sys-id undefined, wal requested is stored in old archive
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$strArchivePath = $self->{strArchivePath} . "/" . PG_VERSION_92 . "-1/";
|
||||
my $strWalMajorPath = "${strArchivePath}/" . substr($strWalSegment, 0, 16);
|
||||
my $strWalSegmentName = "${strWalSegment}-${strFileHash}";
|
||||
|
||||
storageRepo()->pathCreate($strWalMajorPath, {bCreateParent => true});
|
||||
storageRepo()->put("${strWalMajorPath}/${strWalSegmentName}");
|
||||
|
||||
($strArchiveId, $strArchiveFile, $strCipherPass) = $oArchiveBase->getCheck(undef, undef, $strWalSegment, false);
|
||||
|
||||
$self->testResult(sub {($strArchiveId eq PG_VERSION_94 . '-13') && !defined($strArchiveFile) && !defined($strCipherPass)},
|
||||
true, 'undef db-version, db-sys-id with a requested wal not in current db archive returns only current db archive-id');
|
||||
|
||||
# Pass db-version and db-sys-id where WAL is actually located
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
($strArchiveId, $strArchiveFile, $strCipherPass) =
|
||||
$oArchiveBase->getCheck(PG_VERSION_92, WAL_VERSION_92_SYS_ID, $strWalSegment, false);
|
||||
|
||||
$self->testResult(sub {($strArchiveId eq PG_VERSION_92 . '-1') && ($strArchiveFile eq $strWalSegmentName) && !defined($strCipherPass)},
|
||||
true, 'db-version, db-sys-id with a requested wal in requested db archive');
|
||||
|
||||
# Put same WAL segment in more recent archive for same DB
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$strArchivePath = $self->{strArchivePath} . "/" . PG_VERSION_92 . "-3/";
|
||||
$strWalMajorPath = "${strArchivePath}/" . substr($strWalSegment, 0, 16);
|
||||
$strWalSegmentName = "${strWalSegment}-${strFileHash}";
|
||||
|
||||
# Store with actual data that will match the hash check
|
||||
storageRepo()->pathCreate($strWalMajorPath, {bCreateParent => true});
|
||||
storageRepo()->put("${strWalMajorPath}/${strWalSegmentName}", $strFileContent);
|
||||
|
||||
($strArchiveId, $strArchiveFile, $strCipherPass) =
|
||||
$oArchiveBase->getCheck(PG_VERSION_92, WAL_VERSION_92_SYS_ID, $strWalSegment, false);
|
||||
|
||||
# Using the returned values, confirm the correct file is read
|
||||
$self->testResult(sub {sha1_hex(${storageRepo()->get($self->{strArchivePath} . "/" . $strArchiveId . "/" .
|
||||
substr($strWalSegment, 0, 16) . "/" . $strArchiveFile)})}, $strFileHash,
|
||||
'check correct WAL archiveID when in multiple locations');
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Archive::Get::Get::get()"))
|
||||
{
|
||||
# archive.info missing
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testException(sub {new pgBackRest::Archive::Get::Get()->get($strWalSegment, $strDestinationFile)},
|
||||
ERROR_FILE_MISSING,
|
||||
ARCHIVE_INFO_FILE . " does not exist but is required to push/get WAL segments\n" .
|
||||
"HINT: is archive_command configured in postgresql.conf?\n" .
|
||||
"HINT: has a stanza-create been performed?\n" .
|
||||
"HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving scheme.");
|
||||
|
||||
# Create and save archive.info file
|
||||
my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false,
|
||||
{bLoad => false, bIgnoreMissing => true});
|
||||
$oArchiveInfo->create(PG_VERSION_94, WAL_VERSION_94_SYS_ID, false);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_93, WAL_VERSION_93_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 1);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_94, WAL_VERSION_94_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 10);
|
||||
$oArchiveInfo->save();
|
||||
|
||||
# file not found
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testResult(sub {new pgBackRest::Archive::Get::Get()->get($strWalSegment, $strDestinationFile)}, 1,
|
||||
"unable to find ${strWalSegment} in the archive");
|
||||
|
||||
# file found but is not a WAL segment
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$strArchivePath = $self->{strArchivePath} . "/" . PG_VERSION_94 . "-1/";
|
||||
|
||||
storageRepo()->pathCreate($strArchivePath);
|
||||
storageRepo()->put($strArchivePath . BOGUS, BOGUS);
|
||||
my $strBogusHash = sha1_hex(BOGUS);
|
||||
|
||||
# Create path to copy file
|
||||
storageRepo()->pathCreate($strDestinationPath);
|
||||
|
||||
$self->testResult(sub {new pgBackRest::Archive::Get::Get()->get(BOGUS, $strDestinationFile)}, 0,
|
||||
"non-WAL segment copied");
|
||||
|
||||
# Confirm the correct file is copied
|
||||
$self->testResult(sub {sha1_hex(${storageRepo()->get($strDestinationFile)})}, $strBogusHash,
|
||||
' check correct non-WAL copied from older archiveId');
|
||||
|
||||
# create same WAL segment in same DB but different archives and different has values. Confirm latest one copied.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
my $strWalMajorPath = "${strArchivePath}/" . substr($strWalSegment, 0, 16);
|
||||
my $strWalSegmentName = "${strWalSegment}-${strFileHash}";
|
||||
|
||||
# Put zero byte file in old archive
|
||||
storageRepo()->pathCreate($strWalMajorPath);
|
||||
storageRepo()->put("${strWalMajorPath}/${strWalSegmentName}");
|
||||
|
||||
# Create newest archive path
|
||||
$strArchivePath = $self->{strArchivePath} . "/" . PG_VERSION_94 . "-12/";
|
||||
$strWalMajorPath = "${strArchivePath}/" . substr($strWalSegment, 0, 16);
|
||||
$strWalSegmentName = "${strWalSegment}-${strFileHash}";
|
||||
|
||||
# Store with actual data that will match the hash check
|
||||
storageRepo()->pathCreate($strWalMajorPath, {bCreateParent => true});
|
||||
storageRepo()->put("${strWalMajorPath}/${strWalSegmentName}", $strFileContent);
|
||||
|
||||
$self->testResult(sub {new pgBackRest::Archive::Get::Get()->get($strWalSegmentName, $strDestinationFile)}, 0,
|
||||
"WAL segment copied");
|
||||
|
||||
# Confirm the correct file is copied
|
||||
$self->testResult(sub {sha1_hex(${storageRepo()->get($strDestinationFile)})}, $strFileHash,
|
||||
' check correct WAL copied when in multiple locations');
|
||||
|
||||
# get files from an older DB version to simulate restoring from an old backup set to a database that is of that same version
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
# Create same WAL name in older DB archive but with different data to ensure it is copied
|
||||
$strArchivePath = $self->{strArchivePath} . "/" . PG_VERSION_93 . "-2/";
|
||||
$strWalMajorPath = "${strArchivePath}/" . substr($strWalSegment, 0, 16);
|
||||
$strWalSegmentName = "${strWalSegment}-${strFileHash}";
|
||||
|
||||
my $strWalContent = 'WALTESTDATA';
|
||||
my $strWalHash = sha1_hex($strWalContent);
|
||||
|
||||
# Store with actual data that will match the hash check
|
||||
storageRepo()->pathCreate($strWalMajorPath, {bCreateParent => true});
|
||||
storageRepo()->put("${strWalMajorPath}/${strWalSegmentName}", $strWalContent);
|
||||
|
||||
# Remove the destination file to ensure it is copied
|
||||
storageTest()->remove($strDestinationFile);
|
||||
|
||||
# Remove the current pg_control file and copy the older db pg_control file into the pg_control path
|
||||
storageTest()->remove($self->{strDbPath} . '/' . DB_FILE_PGCONTROL);
|
||||
executeTest(
|
||||
'cp ' . $self->dataPath() . '/backup.pg_control_' . WAL_VERSION_93 . '.bin ' . $self->{strDbPath} . '/' .
|
||||
DB_FILE_PGCONTROL);
|
||||
|
||||
$self->testResult(sub {new pgBackRest::Archive::Get::Get()->get($strWalSegmentName, $strDestinationFile)}, 0,
|
||||
"WAL segment copied from older db backupset to same version older db");
|
||||
|
||||
# Confirm the correct file is copied
|
||||
$self->testResult(sub {sha1_hex(${storageRepo()->get($strDestinationFile)})}, $strWalHash,
|
||||
' check correct WAL copied from older db');
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -74,6 +74,16 @@ sub run
|
||||
|
||||
my $strArchiveTestFile = $self->dataPath() . '/backup.wal1_';
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Archive::Info::new()"))
|
||||
{
|
||||
$self->testException(sub {new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, ERROR_FILE_MISSING,
|
||||
ARCHIVE_INFO_FILE . " does not exist but is required to push/get WAL segments\n" .
|
||||
"HINT: is archive_command configured in postgresql.conf?\n" .
|
||||
"HINT: has a stanza-create been performed?\n" .
|
||||
"HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving scheme.");
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Archive::Info::reconstruct()"))
|
||||
{
|
||||
@@ -130,6 +140,48 @@ sub run
|
||||
' new archive info encrypted');
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Archive::Info::archiveIdList(), check(), archiveId()"))
|
||||
{
|
||||
my @stryArchiveId;
|
||||
my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false,
|
||||
{bLoad => false, bIgnoreMissing => true});
|
||||
|
||||
$oArchiveInfo->create(PG_VERSION_92, WAL_VERSION_92_SYS_ID, false);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_93, WAL_VERSION_93_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 1);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_94, WAL_VERSION_94_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 10);
|
||||
$oArchiveInfo->dbSectionSet(PG_VERSION_93, WAL_VERSION_93_SYS_ID, $oArchiveInfo->dbHistoryIdGet(false) + 1);
|
||||
$oArchiveInfo->save();
|
||||
|
||||
# Check gets only the latest DB and returns only that archiveId
|
||||
push(@stryArchiveId, $oArchiveInfo->check(PG_VERSION_93, WAL_VERSION_93_SYS_ID));
|
||||
$self->testResult(sub {(@stryArchiveId == 1) && ($stryArchiveId[0] eq PG_VERSION_93 . "-13")}, true,
|
||||
'check - return only newest archiveId');
|
||||
|
||||
$self->testResult(sub {$oArchiveInfo->archiveId({strDbVersion => PG_VERSION_93, ullDbSysId => WAL_VERSION_93_SYS_ID})},
|
||||
PG_VERSION_93 . "-13", 'archiveId - return only newest archiveId for multiple histories');
|
||||
|
||||
$self->testException(sub {$oArchiveInfo->archiveId({strDbVersion => PG_VERSION_94, ullDbSysId => BOGUS})}, ERROR_UNKNOWN,
|
||||
"unable to retrieve the archive id for database version '" . PG_VERSION_94 . "' and system-id '" . BOGUS . "'");
|
||||
|
||||
$self->testException(sub {$oArchiveInfo->check(PG_VERSION_94, WAL_VERSION_94_SYS_ID)}, ERROR_ARCHIVE_MISMATCH,
|
||||
"WAL segment version " . PG_VERSION_94 . " does not match archive version " . PG_VERSION_93 .
|
||||
"\nWAL segment system-id " . WAL_VERSION_94_SYS_ID . " does not match archive system-id " . WAL_VERSION_93_SYS_ID .
|
||||
"\nHINT: are you archiving to the correct stanza?");
|
||||
|
||||
@stryArchiveId = $oArchiveInfo->archiveIdList(PG_VERSION_93, WAL_VERSION_93_SYS_ID);
|
||||
$self->testResult(sub {(@stryArchiveId == 2) && ($stryArchiveId[0] eq PG_VERSION_93 . "-13") &&
|
||||
($stryArchiveId[1] eq PG_VERSION_93 . "-2")}, true, 'archiveIdList - returns multiple archiveId - newest first');
|
||||
|
||||
@stryArchiveId = $oArchiveInfo->archiveIdList(PG_VERSION_94, WAL_VERSION_94_SYS_ID);
|
||||
$self->testResult(sub {(@stryArchiveId == 1) && ($stryArchiveId[0] eq PG_VERSION_94 . "-12")}, true,
|
||||
'archiveIdList - returns older archiveId');
|
||||
|
||||
$self->testException(sub {$oArchiveInfo->archiveIdList(PG_VERSION_95, WAL_VERSION_94_SYS_ID)}, ERROR_UNKNOWN,
|
||||
"unable to retrieve the archive id for database version '" . PG_VERSION_95 . "' and system-id '" .
|
||||
WAL_VERSION_94_SYS_ID . "'");
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("encryption"))
|
||||
{
|
||||
|
||||
@@ -248,7 +248,7 @@ sub run
|
||||
storageTest()->remove($oHostDbMaster->spoolPath() . '/archive/' . $self->stanza() . "/out/${strSourceFile}.ok");
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
&log(INFO, ' db version mismatch error');
|
||||
&log(INFO, ' db version mismatch in db section only - archive-push errors but archive-get succeeds');
|
||||
|
||||
$oHostBackup->infoMunge(
|
||||
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE),
|
||||
@@ -258,16 +258,50 @@ sub run
|
||||
$strCommandPush . " ${strWalPath}/${strSourceFile}",
|
||||
{iExpectedExitStatus => ERROR_ARCHIVE_MISMATCH, oLogTest => $self->expect()});
|
||||
|
||||
# Remove RECOVERYXLOG so it can be recovered
|
||||
storageTest()->remove("${strWalPath}/RECOVERYXLOG", {bIgnoreMissing => false});
|
||||
|
||||
$oHostDbMaster->executeSimple(
|
||||
$strCommandGet . " ${strSourceFile1} ${strWalPath}/RECOVERYXLOG",
|
||||
{iExpectedExitStatus => ERROR_ARCHIVE_MISMATCH, oLogTest => $self->expect()});
|
||||
{oLogTest => $self->expect()});
|
||||
|
||||
# Check that the destination file exists
|
||||
if (storageDb()->exists("${strWalPath}/RECOVERYXLOG"))
|
||||
{
|
||||
my ($strActualChecksum) = storageDb()->hashSize("${strWalPath}/RECOVERYXLOG");
|
||||
|
||||
if ($strActualChecksum ne $strArchiveChecksum)
|
||||
{
|
||||
confess "recovered file hash '${strActualChecksum}' does not match expected '${strArchiveChecksum}'";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
confess "archive file '${strWalPath}/RECOVERYXLOG' is not in destination";
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
&log(INFO, ' db version mismatch error - archive-get unable to retrieve archiveId');
|
||||
|
||||
# db section and corresponding history munged
|
||||
$oHostBackup->infoMunge(
|
||||
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE),
|
||||
{&INFO_ARCHIVE_SECTION_DB_HISTORY => {'1' => {&INFO_ARCHIVE_KEY_DB_VERSION => '8.0'}}});
|
||||
|
||||
$oHostDbMaster->executeSimple(
|
||||
$strCommandGet . " ${strSourceFile1} ${strWalPath}/RECOVERYXLOG",
|
||||
{iExpectedExitStatus => ERROR_UNKNOWN, oLogTest => $self->expect()});
|
||||
|
||||
# Restore the file to its original condition
|
||||
$oHostBackup->infoRestore(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE));
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
&log(INFO, ' db system-id mismatch error');
|
||||
|
||||
$oHostBackup->infoMunge(
|
||||
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE),
|
||||
{&INFO_ARCHIVE_SECTION_DB => {&INFO_BACKUP_KEY_SYSTEM_ID => 5000900090001855000}});
|
||||
{&INFO_ARCHIVE_SECTION_DB => {&INFO_BACKUP_KEY_SYSTEM_ID => 5000900090001855000},
|
||||
&INFO_ARCHIVE_SECTION_DB_HISTORY => {'1' => {&INFO_ARCHIVE_KEY_DB_ID => 5000900090001855000}}});
|
||||
|
||||
$oHostDbMaster->executeSimple(
|
||||
$strCommandPush . " ${strWalPath}/${strSourceFile}",
|
||||
@@ -275,7 +309,7 @@ sub run
|
||||
|
||||
$oHostDbMaster->executeSimple(
|
||||
$strCommandGet . " ${strSourceFile1} ${strWalPath}/RECOVERYXLOG",
|
||||
{iExpectedExitStatus => ERROR_ARCHIVE_MISMATCH, oLogTest => $self->expect()});
|
||||
{iExpectedExitStatus => ERROR_UNKNOWN, oLogTest => $self->expect()});
|
||||
|
||||
# Restore the file to its original condition
|
||||
$oHostBackup->infoRestore(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE));
|
||||
|
||||
@@ -227,8 +227,6 @@ sub run
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
}
|
||||
|
||||
# Fail on archive push due to mismatch of DB since stanza not upgraded
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Encrypted info files could not be reconstructed above so just copy them back
|
||||
if ($bRepoEncrypt)
|
||||
{
|
||||
@@ -236,6 +234,13 @@ sub run
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyOldFile, $strArchiveInfoCopyFile, {bRecurse => false});
|
||||
}
|
||||
|
||||
# Just before upgrading push one last WAL on the old version to ensure it can be retrieved later
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
($strArchiveFile, $strSourceFile) = $self->archiveGenerate($strWalPath, 1, 2, WAL_VERSION_93);
|
||||
$oHostDbMaster->executeSimple($strCommand . " ${strSourceFile}", {oLogTest => $self->expect()});
|
||||
|
||||
# Fail on archive push due to mismatch of DB since stanza not upgraded
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
my $strArchiveTestFile = $self->dataPath() . '/backup.wal1_';
|
||||
|
||||
# Upgrade the DB by copying new pg_control
|
||||
@@ -252,6 +257,25 @@ sub run
|
||||
$oHostBackup->stanzaUpgrade('successful upgrade creates additional history', {strOptionalParam => '--no-' .
|
||||
cfgOptionName(CFGOPT_ONLINE)});
|
||||
|
||||
# Make sure that WAL from the old version can still be retrieved
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Copy the old pg_control back so it looks like the original db has been restored
|
||||
storageDb()->copy(
|
||||
$self->dataPath() . '/backup.pg_control_' . WAL_VERSION_93 . '.bin',
|
||||
$oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL);
|
||||
|
||||
# Attempt to get the last archive log that was pushed to this repo
|
||||
$oHostDbMaster->executeSimple(
|
||||
$oHostDbMaster->backrestExe() . ' --config=' . $oHostDbMaster->backrestConfig() .
|
||||
" --stanza=db archive-get ${strArchiveFile} " . $oHostDbMaster->dbBasePath() . '/pg_xlog/RECOVERYXLOG',
|
||||
{oLogTest => $self->expect()});
|
||||
|
||||
# Copy the new pg_control back so the tests can continue with the upgraded stanza
|
||||
storageDb()->copy(
|
||||
$self->dataPath() . '/backup.pg_control_' . WAL_VERSION_94 . '.bin',
|
||||
$oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL);
|
||||
forceStorageMode(storageDb(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
|
||||
# After stanza upgrade, make sure archives are pushed to the new db verion-id directory (9.4-2)
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Push a WAL segment so have a valid file in the latest DB archive dir only
|
||||
|
||||
Reference in New Issue
Block a user