mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
The stanza-create/update/delete commands are implemented entirely in C.
Contributed by Cynthia Shang.
This commit is contained in:
parent
53f27da3a6
commit
c733319063
@ -25,6 +25,14 @@
|
||||
</release-bug-list>
|
||||
|
||||
<release-improvement-list>
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-contributor id="cynthia.shang"/>
|
||||
</release-item-contributor-list>
|
||||
|
||||
<p>The <cmd>stanza-create/update/delete</cmd> commands are implemented entirely in C.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-contributor id="cynthia.shang"/>
|
||||
|
@ -19,16 +19,6 @@ use pgBackRest::Common::Wait;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::Storage::Helper;
|
||||
|
||||
####################################################################################################################################
|
||||
# lockPathCreate
|
||||
#
|
||||
# Create the lock path if it does not exist.
|
||||
####################################################################################################################################
|
||||
sub lockPathCreate
|
||||
{
|
||||
storageLocal()->pathCreate(cfgOption(CFGOPT_LOCK_PATH), {strMode => '770', bIgnoreExists => true, bCreateParent => true});
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# lockStopFileName
|
||||
#
|
||||
@ -41,95 +31,6 @@ sub lockStopFileName
|
||||
return cfgOption(CFGOPT_LOCK_PATH) . (defined($strStanza) ? "/${strStanza}" : '/all') . '.stop';
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# lockStop
|
||||
#
|
||||
# Write a stop file that will prevent backrest processes from running. Optionally attempt to kill any processes that are currently
|
||||
# running.
|
||||
####################################################################################################################################
|
||||
sub lockStop
|
||||
{
|
||||
# Create the lock path
|
||||
lockPathCreate();
|
||||
|
||||
# Generate the stop file name
|
||||
my $strStopFile = lockStopFileName(cfgOption(CFGOPT_STANZA, false));
|
||||
|
||||
# If the stop file already exists then warn
|
||||
if (-e $strStopFile)
|
||||
{
|
||||
&log(WARN, 'stop file already exists' .
|
||||
(cfgOptionTest(CFGOPT_STANZA) ? ' for stanza ' . cfgOption(CFGOPT_STANZA) : ' for all stanzas'));
|
||||
return false;
|
||||
}
|
||||
|
||||
# Create the stop file
|
||||
sysopen(my $hStopHandle, $strStopFile, O_WRONLY | O_CREAT, oct(640))
|
||||
or confess &log(ERROR, "unable to open stop file ${strStopFile}", ERROR_FILE_OPEN);
|
||||
close($hStopHandle);
|
||||
|
||||
# If --force was specified then send term signals to running processes
|
||||
if (cfgOption(CFGOPT_FORCE))
|
||||
{
|
||||
my $strLockPath = cfgOption(CFGOPT_LOCK_PATH);
|
||||
|
||||
opendir(my $hPath, $strLockPath)
|
||||
or confess &log(ERROR, "unable to open lock path ${strLockPath}", ERROR_PATH_OPEN);
|
||||
|
||||
my @stryFileList = grep(!/^(\.)|(\.\.)$/i, readdir($hPath));
|
||||
|
||||
# Find each lock file and send term signals to the processes
|
||||
foreach my $strFile (sort(@stryFileList))
|
||||
{
|
||||
my $hLockHandle;
|
||||
my $strLockFile = "${strLockPath}/${strFile}";
|
||||
|
||||
# Skip if this is a stop file
|
||||
next if ($strFile =~ /\.stop$/);
|
||||
|
||||
# Open the lock file for read
|
||||
if (!sysopen($hLockHandle, $strLockFile, O_RDONLY))
|
||||
{
|
||||
&log(WARN, "unable to open lock file ${strLockFile}");
|
||||
next;
|
||||
}
|
||||
|
||||
# Attempt a lock on the file - if a lock can be acquired that means the original process died without removing the
|
||||
# lock file so we'll remove it now.
|
||||
if (flock($hLockHandle, LOCK_EX | LOCK_NB))
|
||||
{
|
||||
unlink($strLockFile);
|
||||
close($hLockHandle);
|
||||
next;
|
||||
}
|
||||
|
||||
# The file is locked so that means there is a running process - read the process id and send it a term signal
|
||||
my $iProcessId = trim(readline($hLockHandle));
|
||||
|
||||
# If the process id is defined then this is a valid lock file
|
||||
if (defined($iProcessId))
|
||||
{
|
||||
if (!kill('TERM', $iProcessId))
|
||||
{
|
||||
&log(WARN, "unable to send term signal to process ${iProcessId}");
|
||||
}
|
||||
|
||||
&log(INFO, "sent term signal to process ${iProcessId}");
|
||||
}
|
||||
# Else not a valid lock file so delete it
|
||||
{
|
||||
unlink($strLockFile);
|
||||
close($hLockHandle);
|
||||
next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
push @EXPORT, qw(lockStop);
|
||||
|
||||
####################################################################################################################################
|
||||
# lockStopTest
|
||||
#
|
||||
@ -193,30 +94,4 @@ sub lockStopTest
|
||||
|
||||
push @EXPORT, qw(lockStopTest);
|
||||
|
||||
####################################################################################################################################
|
||||
# lockStart
|
||||
#
|
||||
# Remove the stop file so processes can run.
|
||||
####################################################################################################################################
|
||||
sub lockStart
|
||||
{
|
||||
# Generate the stop file name
|
||||
my $strStopFile = lockStopFileName(cfgOption(CFGOPT_STANZA, false));
|
||||
|
||||
# If the stop file doesn't exist then warn
|
||||
if (!-e $strStopFile)
|
||||
{
|
||||
&log(WARN, 'stop file does not exist' . (cfgOptionTest(CFGOPT_STANZA) ? ' for stanza ' . cfgOption(CFGOPT_STANZA) : ''));
|
||||
return false;
|
||||
}
|
||||
|
||||
# Remove the stop file
|
||||
unlink($strStopFile)
|
||||
or confess &log(ERROR, "unable to remove ${strStopFile}: $!");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
push @EXPORT, qw(lockStart);
|
||||
|
||||
1;
|
||||
|
@ -134,19 +134,9 @@ sub main
|
||||
storageLocal(),
|
||||
cfgOption(CFGOPT_LOG_PATH) . '/' . cfgOption(CFGOPT_STANZA) . '-' . lc(cfgCommandName(cfgCommandGet())));
|
||||
|
||||
# Process delete command
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
if (cfgCommandTest(CFGCMD_STANZA_DELETE))
|
||||
{
|
||||
# Load module dynamically
|
||||
require pgBackRest::Stanza;
|
||||
pgBackRest::Stanza->import();
|
||||
|
||||
new pgBackRest::Stanza()->process();
|
||||
}
|
||||
# Process restore command
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
elsif (cfgCommandTest(CFGCMD_RESTORE))
|
||||
if (cfgCommandTest(CFGCMD_RESTORE))
|
||||
{
|
||||
# Check locality
|
||||
if (!isDbLocal())
|
||||
@ -174,20 +164,9 @@ sub main
|
||||
cfgCommandName(cfgCommandGet()) . ' command must be run on the repository host', ERROR_HOST_INVALID);
|
||||
}
|
||||
|
||||
# Process stanza-create and stanza-upgrade commands
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
if (cfgCommandTest(CFGCMD_STANZA_CREATE) || cfgCommandTest(CFGCMD_STANZA_UPGRADE))
|
||||
{
|
||||
# Load module dynamically
|
||||
require pgBackRest::Stanza;
|
||||
pgBackRest::Stanza->import();
|
||||
|
||||
$iResult = new pgBackRest::Stanza()->process();
|
||||
}
|
||||
|
||||
# Process backup command
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
elsif (cfgCommandTest(CFGCMD_BACKUP))
|
||||
if (cfgCommandTest(CFGCMD_BACKUP))
|
||||
{
|
||||
# Load module dynamically
|
||||
require pgBackRest::Backup::Backup;
|
||||
|
@ -1,794 +0,0 @@
|
||||
####################################################################################################################################
|
||||
# STANZA MODULE
|
||||
#
|
||||
# Contains functions for adding, upgrading and removing a stanza.
|
||||
####################################################################################################################################
|
||||
package pgBackRest::Stanza;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
use English '-no_match_vars';
|
||||
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
|
||||
use pgBackRest::Backup::Common;
|
||||
use pgBackRest::Common::Cipher;
|
||||
use pgBackRest::Common::Exception;
|
||||
use pgBackRest::Common::Ini;
|
||||
use pgBackRest::Common::Lock;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::Archive::Info;
|
||||
use pgBackRest::Backup::Info;
|
||||
use pgBackRest::Db;
|
||||
use pgBackRest::DbVersion;
|
||||
use pgBackRest::InfoCommon;
|
||||
use pgBackRest::Manifest;
|
||||
use pgBackRest::Protocol::Helper;
|
||||
use pgBackRest::Protocol::Storage::Helper;
|
||||
|
||||
####################################################################################################################################
|
||||
# Global variables
|
||||
####################################################################################################################################
|
||||
my $strHintForce = "\nHINT: use stanza-create --force to force the stanza data to be recreated.";
|
||||
my $strInfoMissing = " information missing";
|
||||
my $strStanzaCreateErrorMsg = "not empty";
|
||||
my $strRepoEncryptedMsg = " and repo is encrypted and info file(s) are missing, --force cannot be used";
|
||||
|
||||
####################################################################################################################################
|
||||
# CONSTRUCTOR
|
||||
####################################################################################################################################
|
||||
sub new
|
||||
{
|
||||
my $class = shift; # Class name
|
||||
|
||||
# Create the class hash
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my $strOperation = logDebugParam(__PACKAGE__ . '->new');
|
||||
|
||||
# Initialize the database object if not performing a stanza-delete
|
||||
if (!cfgCommandTest(CFGCMD_STANZA_DELETE))
|
||||
{
|
||||
($self->{oDb}) = dbObjectGet();
|
||||
$self->dbInfoGet();
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'self', value => $self}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Process Stanza Commands
|
||||
####################################################################################################################################
|
||||
sub process
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->process');
|
||||
|
||||
my $iResult = 0;
|
||||
|
||||
# Process stanza create
|
||||
if (cfgCommandTest(CFGCMD_STANZA_CREATE))
|
||||
{
|
||||
$iResult = $self->stanzaCreate();
|
||||
}
|
||||
# Process stanza upgrade
|
||||
elsif (cfgCommandTest(CFGCMD_STANZA_UPGRADE))
|
||||
{
|
||||
$self->stanzaUpgrade();
|
||||
}
|
||||
# Process stanza delete
|
||||
else
|
||||
{
|
||||
$self->stanzaDelete();
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'iResult', value => $iResult, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# stanzaCreate
|
||||
#
|
||||
# Creates the required data for the stanza.
|
||||
####################################################################################################################################
|
||||
sub stanzaCreate
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->stanzaCreate');
|
||||
|
||||
my $bContinue = true;
|
||||
|
||||
# Get the parent paths (create if not exist)
|
||||
my $strParentPathArchive = $self->parentPathGet(STORAGE_REPO_ARCHIVE);
|
||||
my $strParentPathBackup = $self->parentPathGet(STORAGE_REPO_BACKUP);
|
||||
|
||||
# Get a listing of files in the top-level repo directories, ignoring if any are missing
|
||||
my @stryFileListArchive = storageRepo()->list($strParentPathArchive, {bIgnoreMissing => true});
|
||||
my @stryFileListBackup = storageRepo()->list($strParentPathBackup, {bIgnoreMissing => true});
|
||||
|
||||
# If files exist force should be required since create must have already occurred and reissuing a create needs to be a consciuos
|
||||
# effort to rewrite the files.
|
||||
# If at least one directory is not empty, then check to see if the info files exist
|
||||
if (@stryFileListArchive || @stryFileListBackup)
|
||||
{
|
||||
my $strBackupInfoFile = &FILE_BACKUP_INFO;
|
||||
my $strArchiveInfoFile = &ARCHIVE_INFO_FILE;
|
||||
|
||||
# If .info exists, set to true.
|
||||
my $bBackupInfoFileExists = grep(/^$strBackupInfoFile$/i, @stryFileListBackup);
|
||||
my $bArchiveInfoFileExists = grep(/^$strArchiveInfoFile$/i, @stryFileListArchive);
|
||||
|
||||
# If .info does not exist, check for .info.copy
|
||||
if (!$bBackupInfoFileExists)
|
||||
{
|
||||
$strBackupInfoFile .= &INI_COPY_EXT;
|
||||
$bBackupInfoFileExists = grep(/^$strBackupInfoFile$/i, @stryFileListBackup);
|
||||
}
|
||||
|
||||
if (!$bArchiveInfoFileExists)
|
||||
{
|
||||
$strArchiveInfoFile .= &INI_COPY_EXT;
|
||||
$bArchiveInfoFileExists = grep(/^$strArchiveInfoFile$/i, @stryFileListArchive);
|
||||
}
|
||||
|
||||
# Determine if a file exists other than the info files
|
||||
my $strExistingFile = $self->existingFileName(STORAGE_REPO_BACKUP, $strParentPathBackup, &FILE_BACKUP_INFO);
|
||||
if (!defined($strExistingFile))
|
||||
{
|
||||
$strExistingFile = $self->existingFileName(STORAGE_REPO_ARCHIVE, $strParentPathArchive, &ARCHIVE_INFO_FILE);
|
||||
}
|
||||
|
||||
# If something other than the info files exist in the repo (maybe a backup is in progress) and the user is attempting to
|
||||
# change the repo encryption in anyway, then error
|
||||
if (defined($strExistingFile) && (!storageRepo()->encryptionValid(storageRepo()->encrypted($strExistingFile))))
|
||||
{
|
||||
confess &log(ERROR, 'files exist - the encryption type or passphrase cannot be changed', ERROR_PATH_NOT_EMPTY);
|
||||
}
|
||||
|
||||
# If the .info file exists in one directory but is missing from the other directory then there is clearly a mismatch
|
||||
# which requires force option so throw an error to indicate force is needed. If the repo is encrypted and something other
|
||||
# than the info files exist, then error that force cannot be used (the info files cannot be reconstructed since we no longer
|
||||
# have the passphrase that was in the info file to open the other files in the repo)
|
||||
if (!$bArchiveInfoFileExists && $bBackupInfoFileExists)
|
||||
{
|
||||
$self->errorForce('archive' . $strInfoMissing, ERROR_FILE_MISSING, $strExistingFile, $bArchiveInfoFileExists,
|
||||
$strParentPathArchive, $strParentPathBackup);
|
||||
}
|
||||
elsif (!$bBackupInfoFileExists && $bArchiveInfoFileExists)
|
||||
{
|
||||
$self->errorForce('backup' . $strInfoMissing, ERROR_FILE_MISSING, $strExistingFile, $bBackupInfoFileExists,
|
||||
$strParentPathArchive, $strParentPathBackup);
|
||||
}
|
||||
# If we get here then either both exist or neither exist so if neither file exists and something else exists in the
|
||||
# directories then need to use force option to recreate the missing info files - unless the repo is encrypted, then force
|
||||
# cannot be used if other than the info files exist. If only the info files exist then force must be used to overwrite the
|
||||
# files.
|
||||
else
|
||||
{
|
||||
$self->errorForce(
|
||||
(@stryFileListBackup ? 'backup directory ' : '') .
|
||||
((@stryFileListBackup && @stryFileListArchive) ? 'and/or ' : '') .
|
||||
(@stryFileListArchive ? 'archive directory ' : '') .
|
||||
$strStanzaCreateErrorMsg, ERROR_PATH_NOT_EMPTY,
|
||||
$strExistingFile, $bArchiveInfoFileExists, $strParentPathArchive, $strParentPathBackup);
|
||||
|
||||
# If no error was thrown, then do not continue without --force
|
||||
if (!cfgOption(CFGOPT_FORCE))
|
||||
{
|
||||
$bContinue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $iResult = 0;
|
||||
|
||||
if ($bContinue)
|
||||
{
|
||||
# Instantiate the info objects. Throws an error and aborts if force not used and an error occurs during instantiation.
|
||||
my $oArchiveInfo =
|
||||
$self->infoObject(STORAGE_REPO_ARCHIVE, $strParentPathArchive, {bRequired => false, bIgnoreMissing => true});
|
||||
my $oBackupInfo =
|
||||
$self->infoObject(STORAGE_REPO_BACKUP, $strParentPathBackup, {bRequired => false, bIgnoreMissing => true});
|
||||
|
||||
# Create the archive info object
|
||||
($iResult, my $strResultMessage) = $self->infoFileCreate($oArchiveInfo);
|
||||
|
||||
if ($iResult == 0)
|
||||
{
|
||||
# Create the backup.info file
|
||||
($iResult, $strResultMessage) = $self->infoFileCreate($oBackupInfo);
|
||||
}
|
||||
|
||||
if ($iResult != 0)
|
||||
{
|
||||
&log(WARN, "unable to create stanza '" . cfgOption(CFGOPT_STANZA) . "'");
|
||||
confess &log(ERROR, $strResultMessage, $iResult);
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'iResult', value => $iResult, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# stanzaUpgrade
|
||||
#
|
||||
# Updates stanza information to reflect new cluster information. Normally used for version upgrades, but could be used after a
|
||||
# cluster has been dumped and restored to the same version.
|
||||
####################################################################################################################################
|
||||
sub stanzaUpgrade
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->stanzaUpgrade');
|
||||
|
||||
# Get the archive info and backup info files; if either does not exist or cannot be opened an error will be thrown
|
||||
my $oArchiveInfo = $self->infoObject(STORAGE_REPO_ARCHIVE, storageRepo()->pathGet(STORAGE_REPO_ARCHIVE));
|
||||
my $oBackupInfo = $self->infoObject(STORAGE_REPO_BACKUP, storageRepo()->pathGet(STORAGE_REPO_BACKUP));
|
||||
my $bBackupUpgraded = false;
|
||||
my $bArchiveUpgraded = false;
|
||||
|
||||
# If the DB section does not match, then upgrade
|
||||
if ($self->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH))
|
||||
{
|
||||
# Reconstruct the file and save it
|
||||
my ($bReconstruct, $strWarningMsgArchive) = $oBackupInfo->reconstruct(false, false, $self->{oDb}{strDbVersion},
|
||||
$self->{oDb}{ullDbSysId}, $self->{oDb}{iControlVersion}, $self->{oDb}{iCatalogVersion});
|
||||
$oBackupInfo->save();
|
||||
$bBackupUpgraded = true;
|
||||
}
|
||||
|
||||
if ($self->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH))
|
||||
{
|
||||
# Reconstruct the file and save it
|
||||
my ($bReconstruct, $strWarningMsgArchive) = $oArchiveInfo->reconstruct($self->{oDb}{strDbVersion},
|
||||
$self->{oDb}{ullDbSysId});
|
||||
$oArchiveInfo->save();
|
||||
$bArchiveUpgraded = true;
|
||||
}
|
||||
|
||||
# If neither file needed upgrading then provide informational message that an upgrade was not necessary
|
||||
if (!($bBackupUpgraded || $bArchiveUpgraded))
|
||||
{
|
||||
&log(INFO, "the stanza data is already up to date");
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# stanzaDelete
|
||||
#
|
||||
# Delete a stanza. The stop file must exist and the db must be offline unless --force is used.
|
||||
####################################################################################################################################
|
||||
sub stanzaDelete
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->stanzaDelete');
|
||||
|
||||
my $strStanza = cfgOption(CFGOPT_STANZA);
|
||||
my $oStorageRepo = storageRepo();
|
||||
|
||||
# If at least an archive or backup directory exists for the stanza, then continue, else nothing to do
|
||||
if ($oStorageRepo->pathExists(STORAGE_REPO_ARCHIVE) || $oStorageRepo->pathExists(STORAGE_REPO_BACKUP))
|
||||
{
|
||||
# If the stop file does not exist, then error
|
||||
if (!lockStopTest({bStanzaStopRequired => true}))
|
||||
{
|
||||
confess &log(ERROR, "stop file does not exist for stanza '${strStanza}'" .
|
||||
"\nHINT: has the pgbackrest stop command been run on this server?", ERROR_FILE_MISSING);
|
||||
}
|
||||
|
||||
# If a force has not been issued, then check the database
|
||||
if (!cfgOption(CFGOPT_FORCE))
|
||||
{
|
||||
# Get the master database object and index
|
||||
my ($oDbMaster, $iMasterRemoteIdx) = dbObjectGet({bMasterOnly => true});
|
||||
|
||||
# Initialize the master file object and path
|
||||
my $oStorageDbMaster = storageDb({iRemoteIdx => $iMasterRemoteIdx});
|
||||
|
||||
# Check if Postgres is running and if so only continue when forced
|
||||
if ($oStorageDbMaster->exists(DB_FILE_POSTMASTERPID))
|
||||
{
|
||||
confess &log(ERROR, DB_FILE_POSTMASTERPID . " exists - looks like the postmaster is running. " .
|
||||
"To delete stanza '${strStanza}', shutdown the postmaster for stanza '${strStanza}' and try again, " .
|
||||
"or use --force.", ERROR_POSTMASTER_RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
# Delete the archive info files
|
||||
$oStorageRepo->remove(STORAGE_REPO_ARCHIVE . '/' . ARCHIVE_INFO_FILE, {bIgnoreMissing => true});
|
||||
$oStorageRepo->remove(STORAGE_REPO_ARCHIVE . '/' . ARCHIVE_INFO_FILE . INI_COPY_EXT, {bIgnoreMissing => true});
|
||||
|
||||
# Delete the backup info files
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . '/' . FILE_BACKUP_INFO, {bIgnoreMissing => true});
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . '/' . FILE_BACKUP_INFO . INI_COPY_EXT, {bIgnoreMissing => true});
|
||||
|
||||
# Invalidate the backups by removing the manifest files
|
||||
foreach my $strBackup ($oStorageRepo->list(
|
||||
STORAGE_REPO_BACKUP, {strExpression => backupRegExpGet(true, true, true), strSortOrder => 'reverse',
|
||||
bIgnoreMissing => true}))
|
||||
{
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . "/${strBackup}/" . FILE_MANIFEST, {bIgnoreMissing => true});
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . "/${strBackup}/" . FILE_MANIFEST_COPY, {bIgnoreMissing => true});
|
||||
}
|
||||
|
||||
# Recursively remove the stanza archive and backup directories
|
||||
$oStorageRepo->pathRemove(STORAGE_REPO_ARCHIVE, {bRecurse => true, bIgnoreMissing => true});
|
||||
$oStorageRepo->pathRemove(STORAGE_REPO_BACKUP, {bRecurse => true, bIgnoreMissing => true});
|
||||
|
||||
# Remove the stop file so processes can run.
|
||||
lockStart();
|
||||
}
|
||||
else
|
||||
{
|
||||
&log(INFO, "stanza ${strStanza} already deleted");
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# parentPathGet
|
||||
#
|
||||
# Creates the parent path if it doesn't exist and returns the path.
|
||||
####################################################################################################################################
|
||||
sub parentPathGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPathType,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->parentPathGet', \@_,
|
||||
{name => 'strPathType', trace => true},
|
||||
);
|
||||
|
||||
my $strParentPath = storageRepo()->pathGet($strPathType);
|
||||
|
||||
# If the info path does not exist, create it
|
||||
if (!storageRepo()->pathExists($strParentPath))
|
||||
{
|
||||
# Create the cluster repo path
|
||||
storageRepo()->pathCreate($strPathType, {bIgnoreExists => true, bCreateParent => true});
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strParentPath', value => $strParentPath},
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# existingFileName
|
||||
#
|
||||
# Get a name of a file in the specified storage
|
||||
####################################################################################################################################
|
||||
sub existingFileName
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPathType,
|
||||
$strParentPath,
|
||||
$strExcludeFile,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->existingFileName', \@_,
|
||||
{name => 'strPathType'},
|
||||
{name => 'strParentPath'},
|
||||
{name => 'strExcludeFile'},
|
||||
);
|
||||
|
||||
my $hFullList = storageRepo()->manifest(storageRepo()->pathGet($strPathType), {bIgnoreMissing => true});
|
||||
my $strExistingFile = undef;
|
||||
|
||||
foreach my $strName (keys(%{$hFullList}))
|
||||
{
|
||||
if (($hFullList->{$strName}{type} eq 'f') &&
|
||||
(substr($strName, 0, length($strExcludeFile)) ne $strExcludeFile))
|
||||
{
|
||||
$strExistingFile = $strParentPath . "/" . $strName;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strExistingFile', value => $strExistingFile},
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# errorForce
|
||||
#
|
||||
# Determines based on encryption or not and errors when force is required but not set.
|
||||
####################################################################################################################################
|
||||
sub errorForce
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strMessage,
|
||||
$iErrorCode,
|
||||
$strFileName,
|
||||
$bInfoFileExists,
|
||||
$strParentPathArchive,
|
||||
$strParentPathBackup,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->errorForce', \@_,
|
||||
{name => 'strMessage', trace => true},
|
||||
{name => 'iErrorCode', trace => true},
|
||||
{name => 'strFileName', required => false, trace => true},
|
||||
{name => 'bInfoFileExists', trace => true},
|
||||
{name => 'strParentPathArchive', trace => true},
|
||||
{name => 'strParentPathBackup', trace => true},
|
||||
);
|
||||
|
||||
my $bRepoEncrypted = false;
|
||||
|
||||
# Check if the file passed is encrypted (if one exists) else check the repo setting.
|
||||
if (defined($strFileName))
|
||||
{
|
||||
$bRepoEncrypted = storageRepo()->encrypted($strFileName);
|
||||
}
|
||||
elsif (defined(storageRepo()->cipherType()))
|
||||
{
|
||||
$bRepoEncrypted = true;
|
||||
}
|
||||
|
||||
# If the repo is encrypted and a file other than the info files exist yet the info file is missing then the --force option
|
||||
# cannot be used
|
||||
if ($bRepoEncrypted && defined($strFileName) && !$bInfoFileExists)
|
||||
{
|
||||
confess &log(ERROR, $strMessage . $strRepoEncryptedMsg, $iErrorCode);
|
||||
}
|
||||
elsif (!cfgOption(CFGOPT_FORCE))
|
||||
{
|
||||
# If info files exist, check to see if the DB sections match the database - else an upgrade is required
|
||||
if ($bInfoFileExists && $iErrorCode == ERROR_PATH_NOT_EMPTY)
|
||||
{
|
||||
if ($self->upgradeCheck(new pgBackRest::Backup::Info($strParentPathBackup), STORAGE_REPO_BACKUP,
|
||||
ERROR_BACKUP_MISMATCH) ||
|
||||
$self->upgradeCheck(new pgBackRest::Archive::Info($strParentPathArchive), STORAGE_REPO_ARCHIVE,
|
||||
ERROR_ARCHIVE_MISMATCH))
|
||||
{
|
||||
confess &log(ERROR, "backup info file or archive info file invalid\n" .
|
||||
'HINT: use stanza-upgrade if the database has been upgraded or use --force', ERROR_FILE_INVALID);
|
||||
}
|
||||
else
|
||||
{
|
||||
&log(INFO, "stanza-create was already performed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# If get here something is wrong so indicate force is required
|
||||
confess &log(ERROR, $strMessage . $strHintForce, $iErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# infoObject
|
||||
#
|
||||
# Attempt to load an info object. Ignores missing files if directed. Throws an error and aborts if force not used and an error
|
||||
# occurs during loading, else instatiates the object without loading it.
|
||||
####################################################################################################################################
|
||||
sub infoObject
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPathType,
|
||||
$strParentPath,
|
||||
$bRequired,
|
||||
$bIgnoreMissing,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->infoObject', \@_,
|
||||
{name => 'strPathType'},
|
||||
{name => 'strParentPath'},
|
||||
{name => 'bRequired', optional => true, default => true},
|
||||
{name => 'bIgnoreMissing', optional => true, default => false},
|
||||
);
|
||||
|
||||
my $iResult = 0;
|
||||
my $strResultMessage;
|
||||
my $oInfo;
|
||||
|
||||
# Turn off console logging to control when to display the error
|
||||
logDisable();
|
||||
|
||||
# Instantiate the info object in an eval block to trap errors. If force is not used and an error occurs, throw the error
|
||||
# along with a directive that force will need to be used to attempt to correct the issue
|
||||
eval
|
||||
{
|
||||
# Ignore missing files if directed but if the info or info.copy file exists the exists flag will still be set and data will
|
||||
# attempt to be loaded. If the info file is missing and the repo is encrypted, we can only get to this function if nothing
|
||||
# else existed in the repo so a passphrase is generated to store in the file. If it exists and the repo is encrypted then
|
||||
# the generated passphrase passed will not be used - the one from the info file will be read.
|
||||
my $oParamRef =
|
||||
{bIgnoreMissing => $bIgnoreMissing, strCipherPassSub => defined(storageRepo()->cipherType()) ? cipherPassGen() : undef};
|
||||
|
||||
$oInfo = ($strPathType eq STORAGE_REPO_BACKUP ?
|
||||
new pgBackRest::Backup::Info($strParentPath, false, $bRequired, $oParamRef) :
|
||||
new pgBackRest::Archive::Info($strParentPath, $bRequired, $oParamRef));
|
||||
|
||||
# Reset the console logging
|
||||
logEnable();
|
||||
return true;
|
||||
}
|
||||
or do
|
||||
{
|
||||
# Reset console logging and capture error information
|
||||
logEnable();
|
||||
$iResult = exceptionCode($EVAL_ERROR);
|
||||
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||
};
|
||||
|
||||
if ($iResult != 0)
|
||||
{
|
||||
# If force was not used, and the file is missing, then confess the error with hint to use force if the option is
|
||||
# configurable (force is not configurable for stanza-upgrade so this will always confess errors on stanza-upgrade)
|
||||
# else confess all other errors
|
||||
if ((cfgOptionValid(CFGOPT_FORCE) && !cfgOption(CFGOPT_FORCE)) ||
|
||||
(!cfgOptionValid(CFGOPT_FORCE)))
|
||||
{
|
||||
if ($iResult == ERROR_FILE_MISSING)
|
||||
{
|
||||
confess &log(ERROR, cfgOptionValid(CFGOPT_FORCE) ? $strResultMessage . $strHintForce : $strResultMessage, $iResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
confess &log(ERROR, $strResultMessage, $iResult);
|
||||
}
|
||||
}
|
||||
# Else instatiate the object without loading it so we can reconstruct and overwrite the invalid files
|
||||
else
|
||||
{
|
||||
# Confess unhandled exception
|
||||
if (($iResult != ERROR_FILE_MISSING) && ($iResult != ERROR_CRYPTO))
|
||||
{
|
||||
confess &log(ERROR, $strResultMessage, $iResult);
|
||||
}
|
||||
|
||||
my $oParamRef =
|
||||
{bLoad => false, strCipherPassSub => defined(storageRepo()->cipherType()) ? cipherPassGen() : undef};
|
||||
|
||||
$oInfo = ($strPathType eq STORAGE_REPO_BACKUP ?
|
||||
new pgBackRest::Backup::Info($strParentPath, false, false, $oParamRef) :
|
||||
new pgBackRest::Archive::Info($strParentPath, false, $oParamRef));
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'oInfo', value => $oInfo},
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# infoFileCreate
|
||||
#
|
||||
# Creates the info file based on the data passed to the function
|
||||
####################################################################################################################################
|
||||
sub infoFileCreate
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oInfo,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->infoFileCreate', \@_,
|
||||
{name => 'oInfo', trace => true},
|
||||
);
|
||||
|
||||
my $iResult = 0;
|
||||
my $strResultMessage = undef;
|
||||
my $strWarningMsgArchive = undef;
|
||||
|
||||
# Turn off console logging to control when to display the error
|
||||
logDisable();
|
||||
|
||||
eval
|
||||
{
|
||||
# Reconstruct the file from the data in the directory if there is any else initialize the file
|
||||
if (defined($oInfo->{strBackupClusterPath}))
|
||||
{
|
||||
$oInfo->reconstruct(false, false, $self->{oDb}{strDbVersion}, $self->{oDb}{ullDbSysId}, $self->{oDb}{iControlVersion},
|
||||
$self->{oDb}{iCatalogVersion});
|
||||
}
|
||||
# If this is the archive.info reconstruction then catch any warnings
|
||||
else
|
||||
{
|
||||
$strWarningMsgArchive = $oInfo->reconstruct($self->{oDb}{strDbVersion}, $self->{oDb}{ullDbSysId});
|
||||
}
|
||||
|
||||
# Reset the console logging
|
||||
logEnable();
|
||||
return true;
|
||||
}
|
||||
or do
|
||||
{
|
||||
# Reset console logging and capture error information
|
||||
logEnable();
|
||||
$iResult = exceptionCode($EVAL_ERROR);
|
||||
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||
};
|
||||
|
||||
# If we got here without error then save the reconstructed file
|
||||
if ($iResult == 0)
|
||||
{
|
||||
$oInfo->save();
|
||||
|
||||
# Sync path
|
||||
storageRepo()->pathSync(
|
||||
defined($oInfo->{strArchiveClusterPath}) ? $oInfo->{strArchiveClusterPath} : $oInfo->{strBackupClusterPath});
|
||||
}
|
||||
|
||||
# If a warning was issued, raise it
|
||||
if (defined($strWarningMsgArchive))
|
||||
{
|
||||
&log(WARN, $strWarningMsgArchive);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'iResult', value => $iResult},
|
||||
{name => 'strResultMessage', value => $strResultMessage},
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# dbInfoGet
|
||||
#
|
||||
# Gets the database information and store it in $self
|
||||
####################################################################################################################################
|
||||
sub dbInfoGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->dbInfoGet');
|
||||
|
||||
# Validate the database configuration. Do not require the database to be online before creating a stanza because the
|
||||
# archive_command will attempt to push an achive before the archive.info file exists which will result in an error in the
|
||||
# postgres logs.
|
||||
if (cfgOption(CFGOPT_ONLINE))
|
||||
{
|
||||
# If the pg-path in pgbackrest.conf does not match the pg_control then this will error alert the user to fix pgbackrest.conf
|
||||
$self->{oDb}->configValidate();
|
||||
}
|
||||
|
||||
($self->{oDb}{strDbVersion}, $self->{oDb}{iControlVersion}, $self->{oDb}{iCatalogVersion}, $self->{oDb}{ullDbSysId})
|
||||
= $self->{oDb}->info();
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# upgradeCheck
|
||||
#
|
||||
# Checks the info file to see if an upgrade is necessary.
|
||||
####################################################################################################################################
|
||||
sub upgradeCheck
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oInfo,
|
||||
$strPathType,
|
||||
$iExpectedError,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->upgradeCheck', \@_,
|
||||
{name => 'oInfo'},
|
||||
{name => 'strPathType'},
|
||||
{name => 'iExpectedError'},
|
||||
);
|
||||
|
||||
my $iResult = 0;
|
||||
my $strResultMessage = undef;
|
||||
|
||||
# Turn off console logging to control when to display the error
|
||||
logDisable();
|
||||
|
||||
eval
|
||||
{
|
||||
($strPathType eq STORAGE_REPO_BACKUP)
|
||||
? $oInfo->check($self->{oDb}{strDbVersion}, $self->{oDb}{iControlVersion}, $self->{oDb}{iCatalogVersion},
|
||||
$self->{oDb}{ullDbSysId}, true)
|
||||
: $oInfo->check($self->{oDb}{strDbVersion}, $self->{oDb}{ullDbSysId}, true);
|
||||
logEnable();
|
||||
return true;
|
||||
}
|
||||
or do
|
||||
{
|
||||
logEnable();
|
||||
|
||||
# Confess unhandled errors
|
||||
confess $EVAL_ERROR if (exceptionCode($EVAL_ERROR) != $iExpectedError);
|
||||
|
||||
# Capture the result which will be the expected error, meaning an upgrade is needed
|
||||
$iResult = exceptionCode($EVAL_ERROR);
|
||||
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||
};
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'bResult', value => ($iResult == $iExpectedError ? true : false)},
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
@ -68,6 +68,10 @@ SRCS = \
|
||||
command/restore/file.c \
|
||||
command/restore/protocol.c \
|
||||
command/remote/remote.c \
|
||||
command/stanza/common.c \
|
||||
command/stanza/create.c \
|
||||
command/stanza/delete.c \
|
||||
command/stanza/upgrade.c \
|
||||
command/storage/list.c \
|
||||
common/compress/gzip/common.c \
|
||||
common/compress/gzip/compress.c \
|
||||
@ -278,6 +282,18 @@ command/restore/file.o: command/restore/file.c build.auto.h command/restore/file
|
||||
command/restore/protocol.o: command/restore/protocol.c build.auto.h command/restore/file.h command/restore/protocol.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/io.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h protocol/server.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/restore/protocol.c -o command/restore/protocol.o
|
||||
|
||||
command/stanza/common.o: command/stanza/common.c build.auto.h command/check/common.h common/assert.h common/crypto/common.h common/debug.h common/encode.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h db/helper.h info/info.h info/infoPg.h postgres/client.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/common.c -o command/stanza/common.o
|
||||
|
||||
command/stanza/create.o: command/stanza/create.c build.auto.h command/control/common.h command/stanza/common.h command/stanza/create.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/create.c -o command/stanza/create.o
|
||||
|
||||
command/stanza/delete.o: command/stanza/delete.c build.auto.h command/backup/common.h command/control/common.h command/stanza/delete.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoManifest.h info/infoPg.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/delete.c -o command/stanza/delete.o
|
||||
|
||||
command/stanza/upgrade.o: command/stanza/upgrade.c build.auto.h command/control/common.h command/stanza/common.h command/stanza/upgrade.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/upgrade.c -o command/stanza/upgrade.o
|
||||
|
||||
command/storage/list.o: command/storage/list.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/handleWrite.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/storage/list.c -o command/storage/list.o
|
||||
|
||||
@ -473,7 +489,7 @@ info/infoManifest.o: info/infoManifest.c build.auto.h common/error.auto.h common
|
||||
info/infoPg.o: info/infoPg.c build.auto.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h info/infoPg.h postgres/interface.h postgres/version.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/infoPg.c -o info/infoPg.o
|
||||
|
||||
main.o: main.c build.auto.h command/archive/get/get.h command/archive/push/push.h command/check/check.h command/command.h command/control/start.h command/control/stop.h command/expire/expire.h command/help/help.h command/info/info.h command/local/local.h command/remote/remote.h command/storage/list.h common/assert.h common/debug.h common/error.auto.h common/error.h common/exit.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/interface.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h
|
||||
main.o: main.c build.auto.h command/archive/get/get.h command/archive/push/push.h command/check/check.h command/command.h command/control/start.h command/control/stop.h command/expire/expire.h command/help/help.h command/info/info.h command/local/local.h command/remote/remote.h command/stanza/create.h command/stanza/delete.h command/stanza/upgrade.h command/storage/list.h common/assert.h common/debug.h common/error.auto.h common/error.h common/exit.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/interface.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c main.c -o main.o
|
||||
|
||||
perl/config.o: perl/config.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h
|
||||
|
101
src/command/stanza/common.c
Normal file
101
src/command/stanza/common.c
Normal file
@ -0,0 +1,101 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Commands Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include "command/check/common.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/encode.h"
|
||||
#include "common/log.h"
|
||||
#include "config/config.h"
|
||||
#include "db/helper.h"
|
||||
#include "info/infoPg.h"
|
||||
#include "postgres/interface.h"
|
||||
#include "postgres/version.h"
|
||||
#include "storage/helper.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Generate a cipher
|
||||
***********************************************************************************************************************************/
|
||||
String *
|
||||
cipherPassGen(CipherType cipherType)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
if (cipherType != cipherTypeNone)
|
||||
{
|
||||
unsigned char buffer[48]; // 48 is the amount of entropy needed to get a 64 base key
|
||||
cryptoRandomBytes(buffer, sizeof(buffer));
|
||||
char cipherPassSubChar[64];
|
||||
encodeToStr(encodeBase64, buffer, sizeof(buffer), cipherPassSubChar);
|
||||
result = strNew(cipherPassSubChar);
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Validate the archive and backup info files
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoValidate(const InfoPgData *archiveInfo, const InfoPgData *backupInfo)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(INFO_PG_DATA, archiveInfo);
|
||||
FUNCTION_TEST_PARAM_P(INFO_PG_DATA, backupInfo);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(archiveInfo != NULL);
|
||||
ASSERT(backupInfo != NULL);
|
||||
|
||||
// Error if there is a mismatch between the archive and backup info files
|
||||
if (archiveInfo->id != backupInfo->id || archiveInfo->systemId != backupInfo->systemId ||
|
||||
archiveInfo->version != backupInfo->version)
|
||||
{
|
||||
THROW_FMT(
|
||||
FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = %u, version = %s, system-id = %" PRIu64 "\n"
|
||||
"backup : id = %u, version = %s, system-id = %" PRIu64 "\n"
|
||||
"HINT: this may be a symptom of repository corruption!",
|
||||
archiveInfo->id, strPtr(pgVersionToStr(archiveInfo->version)), archiveInfo->systemId, backupInfo->id,
|
||||
strPtr(pgVersionToStr(backupInfo->version)), backupInfo->systemId);
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Validate and return database information
|
||||
***********************************************************************************************************************************/
|
||||
PgControl
|
||||
pgValidate(void)
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
PgControl result = {0};
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
if (cfgOptionBool(cfgOptOnline))
|
||||
{
|
||||
// Check the connections of the master (and standby, if any) and return the master database object.
|
||||
DbGetResult dbObject = dbGet(false, true);
|
||||
|
||||
// Get the pgControl information from the pg*-path deemed to be the master
|
||||
result = pgControlFromFile(storagePgId(dbObject.primaryId), cfgOptionStr(cfgOptPgPath + dbObject.primaryId - 1));
|
||||
|
||||
// Check the user configured path and version against the database
|
||||
checkDbConfig(result.version, dbObject.primaryId, dbPgVersion(dbObject.primary), dbPgDataPath(dbObject.primary));
|
||||
}
|
||||
// If the database is not online, assume that pg1 is the master
|
||||
else
|
||||
result = pgControlFromFile(storagePg(), cfgOptionStr(cfgOptPgPath));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
17
src/command/stanza/common.h
Normal file
17
src/command/stanza/common.h
Normal file
@ -0,0 +1,17 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Commands Handler
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMAND_STANZA_COMMON_H
|
||||
#define COMMAND_STANZA_COMMON_H
|
||||
|
||||
#include "info/infoPg.h"
|
||||
#include "postgres/interface.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
String *cipherPassGen(CipherType cipherType);
|
||||
void infoValidate(const InfoPgData *archiveInfo, const InfoPgData *backupInfo);
|
||||
PgControl pgValidate(void);
|
||||
|
||||
#endif
|
164
src/command/stanza/create.c
Normal file
164
src/command/stanza/create.c
Normal file
@ -0,0 +1,164 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Create Command
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "command/control/common.h"
|
||||
#include "command/stanza/common.h"
|
||||
#include "command/stanza/create.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
#include "info/infoArchive.h"
|
||||
#include "info/infoBackup.h"
|
||||
#include "info/infoPg.h"
|
||||
#include "postgres/interface.h"
|
||||
#include "postgres/version.h"
|
||||
#include "protocol/helper.h"
|
||||
#include "storage/helper.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Process stanza-create
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cmdStanzaCreate(void)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelDebug);
|
||||
|
||||
// Verify the repo is local and that a stop was not issued before proceeding
|
||||
repoIsLocalVerify();
|
||||
lockStopTest();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
if (cfgOptionBool(cfgOptForce))
|
||||
LOG_WARN("option --force is no longer supported");
|
||||
|
||||
const Storage *storageRepoReadStanza = storageRepo();
|
||||
const Storage *storageRepoWriteStanza = storageRepoWrite();
|
||||
InfoArchive *infoArchive = NULL;
|
||||
InfoBackup *infoBackup = NULL;
|
||||
|
||||
// Get the version and system information - validating it if the database is online
|
||||
PgControl pgControl = pgValidate();
|
||||
|
||||
bool archiveInfoFileExists = storageExistsNP(storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR);
|
||||
bool archiveInfoFileCopyExists = storageExistsNP(storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_COPY_STR);
|
||||
bool backupInfoFileExists = storageExistsNP(storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR);
|
||||
bool backupInfoFileCopyExists = storageExistsNP(storageRepoReadStanza, INFO_BACKUP_PATH_FILE_COPY_STR);
|
||||
|
||||
// If neither archive info nor backup info files exist and nothing else exists in the stanza directory
|
||||
// then create the stanza
|
||||
if (!archiveInfoFileExists && !archiveInfoFileCopyExists && !backupInfoFileExists && !backupInfoFileCopyExists)
|
||||
{
|
||||
bool archiveNotEmpty = strLstSize(
|
||||
storageListNP(storageRepoReadStanza, STRDEF(STORAGE_REPO_ARCHIVE))) > 0 ? true : false;
|
||||
bool backupNotEmpty = strLstSize(
|
||||
storageListNP(storageRepoReadStanza, STRDEF(STORAGE_REPO_BACKUP))) > 0 ? true : false;
|
||||
|
||||
// If something else exists in the backup or archive directories for this stanza, then error
|
||||
if (archiveNotEmpty || backupNotEmpty)
|
||||
{
|
||||
THROW_FMT(
|
||||
PathNotEmptyError, "%s%s%snot empty", (backupNotEmpty ? "backup directory " : ""),
|
||||
(backupNotEmpty && archiveNotEmpty ? "and/or " : ""), (archiveNotEmpty ? "archive directory " : ""));
|
||||
}
|
||||
|
||||
// If the repo is encrypted, generate a cipher passphrase for encrypting subsequent archive files
|
||||
String *cipherPassSub = cipherPassGen(cipherType(cfgOptionStr(cfgOptRepoCipherType)));
|
||||
|
||||
// Create and save archive info
|
||||
infoArchive = infoArchiveNew(
|
||||
pgControl.version, pgControl.systemId, cipherType(cfgOptionStr(cfgOptRepoCipherType)), cipherPassSub);
|
||||
infoArchiveSave(
|
||||
infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
|
||||
// If the repo is encrypted, generate a cipher passphrase for encrypting subsequent backup files
|
||||
cipherPassSub = cipherPassGen(cipherType(cfgOptionStr(cfgOptRepoCipherType)));
|
||||
|
||||
// Create and save backup info
|
||||
infoBackup = infoBackupNew(
|
||||
pgControl.version, pgControl.systemId, pgControl.controlVersion, pgControl.catalogVersion,
|
||||
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cipherPassSub);
|
||||
infoBackupSave(
|
||||
infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
}
|
||||
// Else if at least one archive and one backup info file exists, then ensure both are valid
|
||||
else if ((archiveInfoFileExists || archiveInfoFileCopyExists) && (backupInfoFileExists || backupInfoFileCopyExists))
|
||||
{
|
||||
infoArchive = infoArchiveNewLoad(
|
||||
storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
|
||||
infoBackup = infoBackupNewLoad(
|
||||
storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
|
||||
// Error if there is a mismatch between the archive and backup info files
|
||||
infoValidate(&archiveInfo, &backupInfo);
|
||||
|
||||
// The archive and backup info files match so check if the versions or system ids match the current database,
|
||||
// if not, then an upgrade may be necessary
|
||||
if (pgControl.version != archiveInfo.version || pgControl.systemId != archiveInfo.systemId)
|
||||
{
|
||||
THROW(FileInvalidError, "backup and archive info files already exist but do not match the database\n"
|
||||
"HINT: is this the correct stanza?\n"
|
||||
"HINT: did an error occur during stanza-upgrade?");
|
||||
}
|
||||
// Else the files are valid
|
||||
else
|
||||
{
|
||||
const String *sourceFile = NULL;
|
||||
const String *destinationFile = NULL;
|
||||
|
||||
// If the existing files are valid, then, if a file is missing, copy the existing one to the missing one to ensure
|
||||
// there is both a .info and .info.copy
|
||||
if (!archiveInfoFileExists || !archiveInfoFileCopyExists)
|
||||
{
|
||||
sourceFile = archiveInfoFileExists ? INFO_ARCHIVE_PATH_FILE_STR : INFO_ARCHIVE_PATH_FILE_COPY_STR;
|
||||
destinationFile = !archiveInfoFileExists ? INFO_ARCHIVE_PATH_FILE_STR : INFO_ARCHIVE_PATH_FILE_COPY_STR;
|
||||
|
||||
storageCopyNP(
|
||||
storageNewReadNP(storageRepoReadStanza, sourceFile),
|
||||
storageNewWriteNP(storageRepoWriteStanza, destinationFile));
|
||||
}
|
||||
|
||||
if (!backupInfoFileExists || !backupInfoFileCopyExists)
|
||||
{
|
||||
sourceFile = backupInfoFileExists ? INFO_BACKUP_PATH_FILE_STR : INFO_BACKUP_PATH_FILE_COPY_STR;
|
||||
destinationFile = !backupInfoFileExists ? INFO_BACKUP_PATH_FILE_STR : INFO_BACKUP_PATH_FILE_COPY_STR;
|
||||
|
||||
storageCopyNP(
|
||||
storageNewReadNP(storageRepoReadStanza, sourceFile),
|
||||
storageNewWriteNP(storageRepoWriteStanza, destinationFile));
|
||||
}
|
||||
|
||||
// If no files copied, then the stanza was already valid
|
||||
if (sourceFile == NULL)
|
||||
LOG_INFO("stanza '%s' already exists and is valid", strPtr(cfgOptionStr(cfgOptStanza)));
|
||||
}
|
||||
}
|
||||
// Else if both .info and corresponding .copy file are missing for one but not the other, then error
|
||||
else
|
||||
{
|
||||
THROW_FMT(
|
||||
FileMissingError,
|
||||
"%s\n"
|
||||
"HINT: this may be a symptom of repository corruption!",
|
||||
((archiveInfoFileExists || archiveInfoFileCopyExists) ?
|
||||
"archive.info exists but backup.info is missing" : "backup.info exists but archive.info is missing"));
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
12
src/command/stanza/create.h
Normal file
12
src/command/stanza/create.h
Normal file
@ -0,0 +1,12 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Create Command
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMAND_STANZA_CREATE_H
|
||||
#define COMMAND_STANZA_CREATE_H
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void cmdStanzaCreate(void);
|
||||
|
||||
#endif
|
153
src/command/stanza/delete.c
Normal file
153
src/command/stanza/delete.c
Normal file
@ -0,0 +1,153 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Delete Command
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include "command/control/common.h"
|
||||
#include "command/stanza/delete.h"
|
||||
#include "command/backup/common.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
#include "info/infoArchive.h"
|
||||
#include "info/infoBackup.h"
|
||||
#include "info/infoManifest.h"
|
||||
#include "info/infoPg.h"
|
||||
#include "postgres/interface.h"
|
||||
#include "protocol/helper.h"
|
||||
#include "storage/helper.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper functions to assist with testing
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
manifestDelete(const Storage *storageRepoWriteStanza)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE, storageRepoWriteStanza);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(storageRepoWriteStanza != NULL);
|
||||
|
||||
// Get the list of backup directories from newest to oldest since don't want to invalidate a backup before
|
||||
// invalidating any backups that depend on it.
|
||||
StringList *backupList = strLstSort(
|
||||
storageListP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP), .expression = backupRegExpP(.full = true,
|
||||
.differential = true, .incremental = true)), sortOrderDesc);
|
||||
|
||||
// Delete all manifest files
|
||||
for (unsigned int idx = 0; idx < strLstSize(backupList); idx++)
|
||||
{
|
||||
storageRemoveNP(
|
||||
storageRepoWriteStanza,
|
||||
strNewFmt(STORAGE_REPO_BACKUP "/%s/" INFO_MANIFEST_FILE, strPtr(strLstGet(backupList, idx))));
|
||||
storageRemoveNP(
|
||||
storageRepoWriteStanza,
|
||||
strNewFmt(STORAGE_REPO_BACKUP "/%s/" INFO_MANIFEST_FILE INFO_COPY_EXT, strPtr(strLstGet(backupList, idx))));
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
static bool
|
||||
stanzaDelete(const Storage *storageRepoWriteStanza, const StringList *archiveList, const StringList *backupList)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE, storageRepoWriteStanza);
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, archiveList);
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, archiveList);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(storageRepoWriteStanza != NULL);
|
||||
|
||||
bool result = false;
|
||||
|
||||
// For most drivers, NULL indicates the directory does not exist at all. For those that do not support paths (e.g. S3) an
|
||||
// empty StringList will be returned; in such a case, the directory will attempt to be deleted (this is OK).
|
||||
if (archiveList != NULL || backupList != NULL)
|
||||
{
|
||||
bool archiveNotEmpty = (archiveList != NULL && strLstSize(archiveList) > 0) ? true : false;
|
||||
bool backupNotEmpty = (backupList != NULL && strLstSize(backupList) > 0) ? true : false;
|
||||
|
||||
// If something exists in either directory, then remove
|
||||
if (archiveNotEmpty || backupNotEmpty)
|
||||
{
|
||||
// If the stop file does not exist, then error. This check is required even when --force is issued.
|
||||
if (!storageExistsNP(storageLocal(), lockStopFileName(cfgOptionStr(cfgOptStanza))))
|
||||
{
|
||||
THROW_FMT(
|
||||
FileMissingError, "stop file does not exist for stanza '%s'\n"
|
||||
"HINT: has the pgbackrest stop command been run on this server for this stanza?",
|
||||
strPtr(cfgOptionStr(cfgOptStanza)));
|
||||
}
|
||||
|
||||
// If a force has not been issued and Postgres is running, then error
|
||||
if (!cfgOptionBool(cfgOptForce) && storageExistsNP(storagePg(), STRDEF(PG_FILE_POSTMASTERPID)))
|
||||
{
|
||||
THROW_FMT(
|
||||
PostmasterRunningError, PG_FILE_POSTMASTERPID " exists - looks like the postmaster is running. "
|
||||
"To delete stanza '%s', shutdown the postmaster for stanza '%s' and try again, or use --force.",
|
||||
strPtr(cfgOptionStr(cfgOptStanza)), strPtr(cfgOptionStr(cfgOptStanza)));
|
||||
}
|
||||
|
||||
// Delete the archive info files
|
||||
if (archiveNotEmpty)
|
||||
{
|
||||
storageRemoveNP(storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR);
|
||||
storageRemoveNP(storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_COPY_STR);
|
||||
}
|
||||
|
||||
// Delete the backup info files
|
||||
if (backupNotEmpty)
|
||||
{
|
||||
storageRemoveNP(storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR);
|
||||
storageRemoveNP(storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_COPY_STR);
|
||||
}
|
||||
|
||||
// Remove manifest files
|
||||
manifestDelete(storageRepoWriteStanza);
|
||||
}
|
||||
|
||||
// Recusively remove the entire stanza repo if exists. S3 will attempt to remove even if not.
|
||||
if (archiveList != NULL)
|
||||
storagePathRemoveP(storageRepoWriteStanza, STRDEF(STORAGE_REPO_ARCHIVE), .recurse = true);
|
||||
|
||||
if (backupList != NULL)
|
||||
storagePathRemoveP(storageRepoWriteStanza, STRDEF(STORAGE_REPO_BACKUP), .recurse = true);
|
||||
|
||||
// Remove the stop file - this will not error if the stop file does not exist. If the stanza directories existed but nothing
|
||||
// was in them, then no pgbackrest commands can be in progress without the info files so a stop is technically not necessary
|
||||
storageRemoveNP(storageLocalWrite(), lockStopFileName(cfgOptionStr(cfgOptStanza)));
|
||||
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
result = true;
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Process stanza-delete
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cmdStanzaDelete(void)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelDebug);
|
||||
|
||||
// Verify the repo is local before proceeding
|
||||
repoIsLocalVerify();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
const Storage *storageRepoReadStanza = storageRepo();
|
||||
|
||||
stanzaDelete(
|
||||
storageRepoWrite(),
|
||||
storageListP(storageRepoReadStanza, STRDEF(STORAGE_REPO_ARCHIVE), .nullOnMissing = true),
|
||||
storageListP(storageRepoReadStanza, STRDEF(STORAGE_REPO_BACKUP), .nullOnMissing = true));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
12
src/command/stanza/delete.h
Normal file
12
src/command/stanza/delete.h
Normal file
@ -0,0 +1,12 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Delete Command
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMAND_STANZA_DELETE_H
|
||||
#define COMMAND_STANZA_DELETE_H
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void cmdStanzaDelete(void);
|
||||
|
||||
#endif
|
102
src/command/stanza/upgrade.c
Normal file
102
src/command/stanza/upgrade.c
Normal file
@ -0,0 +1,102 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Update Command
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "command/control/common.h"
|
||||
#include "command/stanza/common.h"
|
||||
#include "command/stanza/upgrade.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
#include "info/infoArchive.h"
|
||||
#include "info/infoBackup.h"
|
||||
#include "info/infoPg.h"
|
||||
#include "postgres/interface.h"
|
||||
#include "postgres/version.h"
|
||||
#include "protocol/helper.h"
|
||||
#include "storage/helper.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Process stanza-upgrade
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cmdStanzaUpgrade(void)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelDebug);
|
||||
|
||||
// Verify the repo is local and that a stop was not issued before proceeding
|
||||
repoIsLocalVerify();
|
||||
lockStopTest();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
const Storage *storageRepoReadStanza = storageRepo();
|
||||
const Storage *storageRepoWriteStanza = storageRepoWrite();
|
||||
bool infoArchiveUpgrade = false;
|
||||
bool infoBackupUpgrade = false;
|
||||
|
||||
// Get the version and system information - validating it if the database is online
|
||||
PgControl pgControl = pgValidate();
|
||||
|
||||
// Load the info files (errors if missing)
|
||||
InfoArchive *infoArchive = infoArchiveNewLoad(
|
||||
storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
|
||||
InfoBackup *infoBackup = infoBackupNewLoad(
|
||||
storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
|
||||
// Since the file save of archive.info and backup.info are not atomic, then check and update each separately.
|
||||
// Update archive
|
||||
if (pgControl.version != archiveInfo.version || pgControl.systemId != archiveInfo.systemId)
|
||||
{
|
||||
infoArchivePgSet(infoArchive, pgControl.version, pgControl.systemId);
|
||||
infoArchiveUpgrade = true;
|
||||
}
|
||||
|
||||
// Update backup
|
||||
if (pgControl.version != backupInfo.version || pgControl.systemId != backupInfo.systemId)
|
||||
{
|
||||
infoBackupPgSet(
|
||||
infoBackup, pgControl.version, pgControl.systemId, pgControl.controlVersion, pgControl.catalogVersion);
|
||||
infoBackupUpgrade = true;
|
||||
}
|
||||
|
||||
// Get the backup and archive info pg data and throw an error if the ids do not match before saving (even if only one
|
||||
// needed to be updated)
|
||||
backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
infoValidate(&archiveInfo, &backupInfo);
|
||||
|
||||
// Save archive info
|
||||
if (infoArchiveUpgrade)
|
||||
{
|
||||
infoArchiveSave(
|
||||
infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
}
|
||||
|
||||
// Save backup info
|
||||
if (infoBackupUpgrade)
|
||||
{
|
||||
infoBackupSave(
|
||||
infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
}
|
||||
|
||||
if (!(infoArchiveUpgrade || infoBackupUpgrade))
|
||||
LOG_INFO("stanza '%s' is already up to date", strPtr(cfgOptionStr(cfgOptStanza)));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
12
src/command/stanza/upgrade.h
Normal file
12
src/command/stanza/upgrade.h
Normal file
@ -0,0 +1,12 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stanza Upgrade Command
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMAND_STANZA_UPGRADE_H
|
||||
#define COMMAND_STANZA_UPGRADE_H
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void cmdStanzaUpgrade(void);
|
||||
|
||||
#endif
|
@ -18,6 +18,9 @@ Main
|
||||
#include "command/info/info.h"
|
||||
#include "command/local/local.h"
|
||||
#include "command/remote/remote.h"
|
||||
#include "command/stanza/create.h"
|
||||
#include "command/stanza/delete.h"
|
||||
#include "command/stanza/upgrade.h"
|
||||
#include "command/storage/list.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
@ -195,7 +198,7 @@ main(int argListSize, const char *argList[])
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
case cfgCmdStanzaCreate:
|
||||
{
|
||||
perlExec();
|
||||
cmdStanzaCreate();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -203,7 +206,7 @@ main(int argListSize, const char *argList[])
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
case cfgCmdStanzaDelete:
|
||||
{
|
||||
perlExec();
|
||||
cmdStanzaDelete();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -211,7 +214,7 @@ main(int argListSize, const char *argList[])
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
case cfgCmdStanzaUpgrade:
|
||||
{
|
||||
perlExec();
|
||||
cmdStanzaUpgrade();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5207,89 +5207,12 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"use pgBackRest::Config::Config;\n"
|
||||
"use pgBackRest::Storage::Helper;\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub lockPathCreate\n"
|
||||
"{\n"
|
||||
"storageLocal()->pathCreate(cfgOption(CFGOPT_LOCK_PATH), {strMode => '770', bIgnoreExists => true, bCreateParent => true});\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub lockStopFileName\n"
|
||||
"{\n"
|
||||
"my $strStanza = shift;\n"
|
||||
"\n"
|
||||
"return cfgOption(CFGOPT_LOCK_PATH) . (defined($strStanza) ? \"/${strStanza}\" : '/all') . '.stop';\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n\n"
|
||||
"sub lockStop\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"lockPathCreate();\n"
|
||||
"\n\n"
|
||||
"my $strStopFile = lockStopFileName(cfgOption(CFGOPT_STANZA, false));\n"
|
||||
"\n\n"
|
||||
"if (-e $strStopFile)\n"
|
||||
"{\n"
|
||||
"&log(WARN, 'stop file already exists' .\n"
|
||||
"(cfgOptionTest(CFGOPT_STANZA) ? ' for stanza ' . cfgOption(CFGOPT_STANZA) : ' for all stanzas'));\n"
|
||||
"return false;\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"sysopen(my $hStopHandle, $strStopFile, O_WRONLY | O_CREAT, oct(640))\n"
|
||||
"or confess &log(ERROR, \"unable to open stop file ${strStopFile}\", ERROR_FILE_OPEN);\n"
|
||||
"close($hStopHandle);\n"
|
||||
"\n\n"
|
||||
"if (cfgOption(CFGOPT_FORCE))\n"
|
||||
"{\n"
|
||||
"my $strLockPath = cfgOption(CFGOPT_LOCK_PATH);\n"
|
||||
"\n"
|
||||
"opendir(my $hPath, $strLockPath)\n"
|
||||
"or confess &log(ERROR, \"unable to open lock path ${strLockPath}\", ERROR_PATH_OPEN);\n"
|
||||
"\n"
|
||||
"my @stryFileList = grep(!/^(\\.)|(\\.\\.)$/i, readdir($hPath));\n"
|
||||
"\n\n"
|
||||
"foreach my $strFile (sort(@stryFileList))\n"
|
||||
"{\n"
|
||||
"my $hLockHandle;\n"
|
||||
"my $strLockFile = \"${strLockPath}/${strFile}\";\n"
|
||||
"\n\n"
|
||||
"next if ($strFile =~ /\\.stop$/);\n"
|
||||
"\n\n"
|
||||
"if (!sysopen($hLockHandle, $strLockFile, O_RDONLY))\n"
|
||||
"{\n"
|
||||
"&log(WARN, \"unable to open lock file ${strLockFile}\");\n"
|
||||
"next;\n"
|
||||
"}\n"
|
||||
"\n\n\n"
|
||||
"if (flock($hLockHandle, LOCK_EX | LOCK_NB))\n"
|
||||
"{\n"
|
||||
"unlink($strLockFile);\n"
|
||||
"close($hLockHandle);\n"
|
||||
"next;\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"my $iProcessId = trim(readline($hLockHandle));\n"
|
||||
"\n\n"
|
||||
"if (defined($iProcessId))\n"
|
||||
"{\n"
|
||||
"if (!kill('TERM', $iProcessId))\n"
|
||||
"{\n"
|
||||
"&log(WARN, \"unable to send term signal to process ${iProcessId}\");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"&log(INFO, \"sent term signal to process ${iProcessId}\");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"{\n"
|
||||
"unlink($strLockFile);\n"
|
||||
"close($hLockHandle);\n"
|
||||
"next;\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"push @EXPORT, qw(lockStop);\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub lockStopTest\n"
|
||||
"{\n"
|
||||
@ -5345,25 +5268,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"}\n"
|
||||
"\n"
|
||||
"push @EXPORT, qw(lockStopTest);\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub lockStart\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"my $strStopFile = lockStopFileName(cfgOption(CFGOPT_STANZA, false));\n"
|
||||
"\n\n"
|
||||
"if (!-e $strStopFile)\n"
|
||||
"{\n"
|
||||
"&log(WARN, 'stop file does not exist' . (cfgOptionTest(CFGOPT_STANZA) ? ' for stanza ' . cfgOption(CFGOPT_STANZA) : ''));\n"
|
||||
"return false;\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"unlink($strStopFile)\n"
|
||||
"or confess &log(ERROR, \"unable to remove ${strStopFile}: $!\");\n"
|
||||
"\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"push @EXPORT, qw(lockStart);\n"
|
||||
"\n"
|
||||
"1;\n"
|
||||
},
|
||||
@ -8374,16 +8278,7 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"storageLocal(),\n"
|
||||
"cfgOption(CFGOPT_LOG_PATH) . '/' . cfgOption(CFGOPT_STANZA) . '-' . lc(cfgCommandName(cfgCommandGet())));\n"
|
||||
"\n\n\n"
|
||||
"if (cfgCommandTest(CFGCMD_STANZA_DELETE))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"require pgBackRest::Stanza;\n"
|
||||
"pgBackRest::Stanza->import();\n"
|
||||
"\n"
|
||||
"new pgBackRest::Stanza()->process();\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"elsif (cfgCommandTest(CFGCMD_RESTORE))\n"
|
||||
"if (cfgCommandTest(CFGCMD_RESTORE))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"if (!isDbLocal())\n"
|
||||
@ -8408,16 +8303,7 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"cfgCommandName(cfgCommandGet()) . ' command must be run on the repository host', ERROR_HOST_INVALID);\n"
|
||||
"}\n"
|
||||
"\n\n\n"
|
||||
"if (cfgCommandTest(CFGCMD_STANZA_CREATE) || cfgCommandTest(CFGCMD_STANZA_UPGRADE))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"require pgBackRest::Stanza;\n"
|
||||
"pgBackRest::Stanza->import();\n"
|
||||
"\n"
|
||||
"$iResult = new pgBackRest::Stanza()->process();\n"
|
||||
"}\n"
|
||||
"\n\n\n"
|
||||
"elsif (cfgCommandTest(CFGCMD_BACKUP))\n"
|
||||
"if (cfgCommandTest(CFGCMD_BACKUP))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"require pgBackRest::Backup::Backup;\n"
|
||||
@ -13464,657 +13350,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"\n"
|
||||
"1;\n"
|
||||
},
|
||||
{
|
||||
.name = "pgBackRest/Stanza.pm",
|
||||
.data =
|
||||
"\n\n\n\n\n"
|
||||
"package pgBackRest::Stanza;\n"
|
||||
"\n"
|
||||
"use strict;\n"
|
||||
"use warnings FATAL => qw(all);\n"
|
||||
"use Carp qw(confess);\n"
|
||||
"use English '-no_match_vars';\n"
|
||||
"\n"
|
||||
"use Exporter qw(import);\n"
|
||||
"our @EXPORT = qw();\n"
|
||||
"\n"
|
||||
"use pgBackRest::Backup::Common;\n"
|
||||
"use pgBackRest::Common::Cipher;\n"
|
||||
"use pgBackRest::Common::Exception;\n"
|
||||
"use pgBackRest::Common::Ini;\n"
|
||||
"use pgBackRest::Common::Lock;\n"
|
||||
"use pgBackRest::Common::Log;\n"
|
||||
"use pgBackRest::Config::Config;\n"
|
||||
"use pgBackRest::Archive::Info;\n"
|
||||
"use pgBackRest::Backup::Info;\n"
|
||||
"use pgBackRest::Db;\n"
|
||||
"use pgBackRest::DbVersion;\n"
|
||||
"use pgBackRest::InfoCommon;\n"
|
||||
"use pgBackRest::Manifest;\n"
|
||||
"use pgBackRest::Protocol::Helper;\n"
|
||||
"use pgBackRest::Protocol::Storage::Helper;\n"
|
||||
"\n\n\n\n"
|
||||
"my $strHintForce = \"\\nHINT: use stanza-create --force to force the stanza data to be recreated.\";\n"
|
||||
"my $strInfoMissing = \" information missing\";\n"
|
||||
"my $strStanzaCreateErrorMsg = \"not empty\";\n"
|
||||
"my $strRepoEncryptedMsg = \" and repo is encrypted and info file(s) are missing, --force cannot be used\";\n"
|
||||
"\n\n\n\n"
|
||||
"sub new\n"
|
||||
"{\n"
|
||||
"my $class = shift;\n"
|
||||
"\n\n"
|
||||
"my $self = {};\n"
|
||||
"bless $self, $class;\n"
|
||||
"\n\n"
|
||||
"my $strOperation = logDebugParam(__PACKAGE__ . '->new');\n"
|
||||
"\n\n"
|
||||
"if (!cfgCommandTest(CFGCMD_STANZA_DELETE))\n"
|
||||
"{\n"
|
||||
"($self->{oDb}) = dbObjectGet();\n"
|
||||
"$self->dbInfoGet();\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'self', value => $self}\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n"
|
||||
"sub process\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->process');\n"
|
||||
"\n"
|
||||
"my $iResult = 0;\n"
|
||||
"\n\n"
|
||||
"if (cfgCommandTest(CFGCMD_STANZA_CREATE))\n"
|
||||
"{\n"
|
||||
"$iResult = $self->stanzaCreate();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"elsif (cfgCommandTest(CFGCMD_STANZA_UPGRADE))\n"
|
||||
"{\n"
|
||||
"$self->stanzaUpgrade();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"$self->stanzaDelete();\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'iResult', value => $iResult, trace => true}\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub stanzaCreate\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->stanzaCreate');\n"
|
||||
"\n"
|
||||
"my $bContinue = true;\n"
|
||||
"\n\n"
|
||||
"my $strParentPathArchive = $self->parentPathGet(STORAGE_REPO_ARCHIVE);\n"
|
||||
"my $strParentPathBackup = $self->parentPathGet(STORAGE_REPO_BACKUP);\n"
|
||||
"\n\n"
|
||||
"my @stryFileListArchive = storageRepo()->list($strParentPathArchive, {bIgnoreMissing => true});\n"
|
||||
"my @stryFileListBackup = storageRepo()->list($strParentPathBackup, {bIgnoreMissing => true});\n"
|
||||
"\n\n\n\n"
|
||||
"if (@stryFileListArchive || @stryFileListBackup)\n"
|
||||
"{\n"
|
||||
"my $strBackupInfoFile = &FILE_BACKUP_INFO;\n"
|
||||
"my $strArchiveInfoFile = &ARCHIVE_INFO_FILE;\n"
|
||||
"\n\n"
|
||||
"my $bBackupInfoFileExists = grep(/^$strBackupInfoFile$/i, @stryFileListBackup);\n"
|
||||
"my $bArchiveInfoFileExists = grep(/^$strArchiveInfoFile$/i, @stryFileListArchive);\n"
|
||||
"\n\n"
|
||||
"if (!$bBackupInfoFileExists)\n"
|
||||
"{\n"
|
||||
"$strBackupInfoFile .= &INI_COPY_EXT;\n"
|
||||
"$bBackupInfoFileExists = grep(/^$strBackupInfoFile$/i, @stryFileListBackup);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"if (!$bArchiveInfoFileExists)\n"
|
||||
"{\n"
|
||||
"$strArchiveInfoFile .= &INI_COPY_EXT;\n"
|
||||
"$bArchiveInfoFileExists = grep(/^$strArchiveInfoFile$/i, @stryFileListArchive);\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"my $strExistingFile = $self->existingFileName(STORAGE_REPO_BACKUP, $strParentPathBackup, &FILE_BACKUP_INFO);\n"
|
||||
"if (!defined($strExistingFile))\n"
|
||||
"{\n"
|
||||
"$strExistingFile = $self->existingFileName(STORAGE_REPO_ARCHIVE, $strParentPathArchive, &ARCHIVE_INFO_FILE);\n"
|
||||
"}\n"
|
||||
"\n\n\n"
|
||||
"if (defined($strExistingFile) && (!storageRepo()->encryptionValid(storageRepo()->encrypted($strExistingFile))))\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, 'files exist - the encryption type or passphrase cannot be changed', ERROR_PATH_NOT_EMPTY);\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n"
|
||||
"if (!$bArchiveInfoFileExists && $bBackupInfoFileExists)\n"
|
||||
"{\n"
|
||||
"$self->errorForce('archive' . $strInfoMissing, ERROR_FILE_MISSING, $strExistingFile, $bArchiveInfoFileExists,\n"
|
||||
"$strParentPathArchive, $strParentPathBackup);\n"
|
||||
"}\n"
|
||||
"elsif (!$bBackupInfoFileExists && $bArchiveInfoFileExists)\n"
|
||||
"{\n"
|
||||
"$self->errorForce('backup' . $strInfoMissing, ERROR_FILE_MISSING, $strExistingFile, $bBackupInfoFileExists,\n"
|
||||
"$strParentPathArchive, $strParentPathBackup);\n"
|
||||
"}\n"
|
||||
"\n\n\n\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"$self->errorForce(\n"
|
||||
"(@stryFileListBackup ? 'backup directory ' : '') .\n"
|
||||
"((@stryFileListBackup && @stryFileListArchive) ? 'and/or ' : '') .\n"
|
||||
"(@stryFileListArchive ? 'archive directory ' : '') .\n"
|
||||
"$strStanzaCreateErrorMsg, ERROR_PATH_NOT_EMPTY,\n"
|
||||
"$strExistingFile, $bArchiveInfoFileExists, $strParentPathArchive, $strParentPathBackup);\n"
|
||||
"\n\n"
|
||||
"if (!cfgOption(CFGOPT_FORCE))\n"
|
||||
"{\n"
|
||||
"$bContinue = false;\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"my $iResult = 0;\n"
|
||||
"\n"
|
||||
"if ($bContinue)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"my $oArchiveInfo =\n"
|
||||
"$self->infoObject(STORAGE_REPO_ARCHIVE, $strParentPathArchive, {bRequired => false, bIgnoreMissing => true});\n"
|
||||
"my $oBackupInfo =\n"
|
||||
"$self->infoObject(STORAGE_REPO_BACKUP, $strParentPathBackup, {bRequired => false, bIgnoreMissing => true});\n"
|
||||
"\n\n"
|
||||
"($iResult, my $strResultMessage) = $self->infoFileCreate($oArchiveInfo);\n"
|
||||
"\n"
|
||||
"if ($iResult == 0)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"($iResult, $strResultMessage) = $self->infoFileCreate($oBackupInfo);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"if ($iResult != 0)\n"
|
||||
"{\n"
|
||||
"&log(WARN, \"unable to create stanza '\" . cfgOption(CFGOPT_STANZA) . \"'\");\n"
|
||||
"confess &log(ERROR, $strResultMessage, $iResult);\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'iResult', value => $iResult, trace => true}\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n\n"
|
||||
"sub stanzaUpgrade\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->stanzaUpgrade');\n"
|
||||
"\n\n"
|
||||
"my $oArchiveInfo = $self->infoObject(STORAGE_REPO_ARCHIVE, storageRepo()->pathGet(STORAGE_REPO_ARCHIVE));\n"
|
||||
"my $oBackupInfo = $self->infoObject(STORAGE_REPO_BACKUP, storageRepo()->pathGet(STORAGE_REPO_BACKUP));\n"
|
||||
"my $bBackupUpgraded = false;\n"
|
||||
"my $bArchiveUpgraded = false;\n"
|
||||
"\n\n"
|
||||
"if ($self->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"my ($bReconstruct, $strWarningMsgArchive) = $oBackupInfo->reconstruct(false, false, $self->{oDb}{strDbVersion},\n"
|
||||
"$self->{oDb}{ullDbSysId}, $self->{oDb}{iControlVersion}, $self->{oDb}{iCatalogVersion});\n"
|
||||
"$oBackupInfo->save();\n"
|
||||
"$bBackupUpgraded = true;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"if ($self->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"my ($bReconstruct, $strWarningMsgArchive) = $oArchiveInfo->reconstruct($self->{oDb}{strDbVersion},\n"
|
||||
"$self->{oDb}{ullDbSysId});\n"
|
||||
"$oArchiveInfo->save();\n"
|
||||
"$bArchiveUpgraded = true;\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"if (!($bBackupUpgraded || $bArchiveUpgraded))\n"
|
||||
"{\n"
|
||||
"&log(INFO, \"the stanza data is already up to date\");\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"return logDebugReturn($strOperation);\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub stanzaDelete\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->stanzaDelete');\n"
|
||||
"\n"
|
||||
"my $strStanza = cfgOption(CFGOPT_STANZA);\n"
|
||||
"my $oStorageRepo = storageRepo();\n"
|
||||
"\n\n"
|
||||
"if ($oStorageRepo->pathExists(STORAGE_REPO_ARCHIVE) || $oStorageRepo->pathExists(STORAGE_REPO_BACKUP))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"if (!lockStopTest({bStanzaStopRequired => true}))\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, \"stop file does not exist for stanza '${strStanza}'\" .\n"
|
||||
"\"\\nHINT: has the pgbackrest stop command been run on this server?\", ERROR_FILE_MISSING);\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"if (!cfgOption(CFGOPT_FORCE))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"my ($oDbMaster, $iMasterRemoteIdx) = dbObjectGet({bMasterOnly => true});\n"
|
||||
"\n\n"
|
||||
"my $oStorageDbMaster = storageDb({iRemoteIdx => $iMasterRemoteIdx});\n"
|
||||
"\n\n"
|
||||
"if ($oStorageDbMaster->exists(DB_FILE_POSTMASTERPID))\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, DB_FILE_POSTMASTERPID . \" exists - looks like the postmaster is running. \" .\n"
|
||||
"\"To delete stanza '${strStanza}', shutdown the postmaster for stanza '${strStanza}' and try again, \" .\n"
|
||||
"\"or use --force.\", ERROR_POSTMASTER_RUNNING);\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"$oStorageRepo->remove(STORAGE_REPO_ARCHIVE . '/' . ARCHIVE_INFO_FILE, {bIgnoreMissing => true});\n"
|
||||
"$oStorageRepo->remove(STORAGE_REPO_ARCHIVE . '/' . ARCHIVE_INFO_FILE . INI_COPY_EXT, {bIgnoreMissing => true});\n"
|
||||
"\n\n"
|
||||
"$oStorageRepo->remove(STORAGE_REPO_BACKUP . '/' . FILE_BACKUP_INFO, {bIgnoreMissing => true});\n"
|
||||
"$oStorageRepo->remove(STORAGE_REPO_BACKUP . '/' . FILE_BACKUP_INFO . INI_COPY_EXT, {bIgnoreMissing => true});\n"
|
||||
"\n\n"
|
||||
"foreach my $strBackup ($oStorageRepo->list(\n"
|
||||
"STORAGE_REPO_BACKUP, {strExpression => backupRegExpGet(true, true, true), strSortOrder => 'reverse',\n"
|
||||
"bIgnoreMissing => true}))\n"
|
||||
"{\n"
|
||||
"$oStorageRepo->remove(STORAGE_REPO_BACKUP . \"/${strBackup}/\" . FILE_MANIFEST, {bIgnoreMissing => true});\n"
|
||||
"$oStorageRepo->remove(STORAGE_REPO_BACKUP . \"/${strBackup}/\" . FILE_MANIFEST_COPY, {bIgnoreMissing => true});\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"$oStorageRepo->pathRemove(STORAGE_REPO_ARCHIVE, {bRecurse => true, bIgnoreMissing => true});\n"
|
||||
"$oStorageRepo->pathRemove(STORAGE_REPO_BACKUP, {bRecurse => true, bIgnoreMissing => true});\n"
|
||||
"\n\n"
|
||||
"lockStart();\n"
|
||||
"}\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"&log(INFO, \"stanza ${strStanza} already deleted\");\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn($strOperation);\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub parentPathGet\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"$strPathType,\n"
|
||||
") =\n"
|
||||
"logDebugParam\n"
|
||||
"(\n"
|
||||
"__PACKAGE__ . '->parentPathGet', \\@_,\n"
|
||||
"{name => 'strPathType', trace => true},\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"my $strParentPath = storageRepo()->pathGet($strPathType);\n"
|
||||
"\n\n"
|
||||
"if (!storageRepo()->pathExists($strParentPath))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"storageRepo()->pathCreate($strPathType, {bIgnoreExists => true, bCreateParent => true});\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'strParentPath', value => $strParentPath},\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub existingFileName\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"$strPathType,\n"
|
||||
"$strParentPath,\n"
|
||||
"$strExcludeFile,\n"
|
||||
") =\n"
|
||||
"logDebugParam\n"
|
||||
"(\n"
|
||||
"__PACKAGE__ . '->existingFileName', \\@_,\n"
|
||||
"{name => 'strPathType'},\n"
|
||||
"{name => 'strParentPath'},\n"
|
||||
"{name => 'strExcludeFile'},\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"my $hFullList = storageRepo()->manifest(storageRepo()->pathGet($strPathType), {bIgnoreMissing => true});\n"
|
||||
"my $strExistingFile = undef;\n"
|
||||
"\n"
|
||||
"foreach my $strName (keys(%{$hFullList}))\n"
|
||||
"{\n"
|
||||
"if (($hFullList->{$strName}{type} eq 'f') &&\n"
|
||||
"(substr($strName, 0, length($strExcludeFile)) ne $strExcludeFile))\n"
|
||||
"{\n"
|
||||
"$strExistingFile = $strParentPath . \"/\" . $strName;\n"
|
||||
"last;\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'strExistingFile', value => $strExistingFile},\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub errorForce\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"$strMessage,\n"
|
||||
"$iErrorCode,\n"
|
||||
"$strFileName,\n"
|
||||
"$bInfoFileExists,\n"
|
||||
"$strParentPathArchive,\n"
|
||||
"$strParentPathBackup,\n"
|
||||
") =\n"
|
||||
"logDebugParam\n"
|
||||
"(\n"
|
||||
"__PACKAGE__ . '->errorForce', \\@_,\n"
|
||||
"{name => 'strMessage', trace => true},\n"
|
||||
"{name => 'iErrorCode', trace => true},\n"
|
||||
"{name => 'strFileName', required => false, trace => true},\n"
|
||||
"{name => 'bInfoFileExists', trace => true},\n"
|
||||
"{name => 'strParentPathArchive', trace => true},\n"
|
||||
"{name => 'strParentPathBackup', trace => true},\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"my $bRepoEncrypted = false;\n"
|
||||
"\n\n"
|
||||
"if (defined($strFileName))\n"
|
||||
"{\n"
|
||||
"$bRepoEncrypted = storageRepo()->encrypted($strFileName);\n"
|
||||
"}\n"
|
||||
"elsif (defined(storageRepo()->cipherType()))\n"
|
||||
"{\n"
|
||||
"$bRepoEncrypted = true;\n"
|
||||
"}\n"
|
||||
"\n\n\n"
|
||||
"if ($bRepoEncrypted && defined($strFileName) && !$bInfoFileExists)\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, $strMessage . $strRepoEncryptedMsg, $iErrorCode);\n"
|
||||
"}\n"
|
||||
"elsif (!cfgOption(CFGOPT_FORCE))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"if ($bInfoFileExists && $iErrorCode == ERROR_PATH_NOT_EMPTY)\n"
|
||||
"{\n"
|
||||
"if ($self->upgradeCheck(new pgBackRest::Backup::Info($strParentPathBackup), STORAGE_REPO_BACKUP,\n"
|
||||
"ERROR_BACKUP_MISMATCH) ||\n"
|
||||
"$self->upgradeCheck(new pgBackRest::Archive::Info($strParentPathArchive), STORAGE_REPO_ARCHIVE,\n"
|
||||
"ERROR_ARCHIVE_MISMATCH))\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, \"backup info file or archive info file invalid\\n\" .\n"
|
||||
"'HINT: use stanza-upgrade if the database has been upgraded or use --force', ERROR_FILE_INVALID);\n"
|
||||
"}\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"&log(INFO, \"stanza-create was already performed\");\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"confess &log(ERROR, $strMessage . $strHintForce, $iErrorCode);\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn($strOperation);\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n\n"
|
||||
"sub infoObject\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"$strPathType,\n"
|
||||
"$strParentPath,\n"
|
||||
"$bRequired,\n"
|
||||
"$bIgnoreMissing,\n"
|
||||
") =\n"
|
||||
"logDebugParam\n"
|
||||
"(\n"
|
||||
"__PACKAGE__ . '->infoObject', \\@_,\n"
|
||||
"{name => 'strPathType'},\n"
|
||||
"{name => 'strParentPath'},\n"
|
||||
"{name => 'bRequired', optional => true, default => true},\n"
|
||||
"{name => 'bIgnoreMissing', optional => true, default => false},\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"my $iResult = 0;\n"
|
||||
"my $strResultMessage;\n"
|
||||
"my $oInfo;\n"
|
||||
"\n\n"
|
||||
"logDisable();\n"
|
||||
"\n\n\n"
|
||||
"eval\n"
|
||||
"{\n"
|
||||
"\n\n\n\n"
|
||||
"my $oParamRef =\n"
|
||||
"{bIgnoreMissing => $bIgnoreMissing, strCipherPassSub => defined(storageRepo()->cipherType()) ? cipherPassGen() : undef};\n"
|
||||
"\n"
|
||||
"$oInfo = ($strPathType eq STORAGE_REPO_BACKUP ?\n"
|
||||
"new pgBackRest::Backup::Info($strParentPath, false, $bRequired, $oParamRef) :\n"
|
||||
"new pgBackRest::Archive::Info($strParentPath, $bRequired, $oParamRef));\n"
|
||||
"\n\n"
|
||||
"logEnable();\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"or do\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"logEnable();\n"
|
||||
"$iResult = exceptionCode($EVAL_ERROR);\n"
|
||||
"$strResultMessage = exceptionMessage($EVAL_ERROR);\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"if ($iResult != 0)\n"
|
||||
"{\n"
|
||||
"\n\n\n"
|
||||
"if ((cfgOptionValid(CFGOPT_FORCE) && !cfgOption(CFGOPT_FORCE)) ||\n"
|
||||
"(!cfgOptionValid(CFGOPT_FORCE)))\n"
|
||||
"{\n"
|
||||
"if ($iResult == ERROR_FILE_MISSING)\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, cfgOptionValid(CFGOPT_FORCE) ? $strResultMessage . $strHintForce : $strResultMessage, $iResult);\n"
|
||||
"}\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, $strResultMessage, $iResult);\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"if (($iResult != ERROR_FILE_MISSING) && ($iResult != ERROR_CRYPTO))\n"
|
||||
"{\n"
|
||||
"confess &log(ERROR, $strResultMessage, $iResult);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"my $oParamRef =\n"
|
||||
"{bLoad => false, strCipherPassSub => defined(storageRepo()->cipherType()) ? cipherPassGen() : undef};\n"
|
||||
"\n"
|
||||
"$oInfo = ($strPathType eq STORAGE_REPO_BACKUP ?\n"
|
||||
"new pgBackRest::Backup::Info($strParentPath, false, false, $oParamRef) :\n"
|
||||
"new pgBackRest::Archive::Info($strParentPath, false, $oParamRef));\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'oInfo', value => $oInfo},\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub infoFileCreate\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"$oInfo,\n"
|
||||
") =\n"
|
||||
"logDebugParam\n"
|
||||
"(\n"
|
||||
"__PACKAGE__ . '->infoFileCreate', \\@_,\n"
|
||||
"{name => 'oInfo', trace => true},\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"my $iResult = 0;\n"
|
||||
"my $strResultMessage = undef;\n"
|
||||
"my $strWarningMsgArchive = undef;\n"
|
||||
"\n\n"
|
||||
"logDisable();\n"
|
||||
"\n"
|
||||
"eval\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"if (defined($oInfo->{strBackupClusterPath}))\n"
|
||||
"{\n"
|
||||
"$oInfo->reconstruct(false, false, $self->{oDb}{strDbVersion}, $self->{oDb}{ullDbSysId}, $self->{oDb}{iControlVersion},\n"
|
||||
"$self->{oDb}{iCatalogVersion});\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"$strWarningMsgArchive = $oInfo->reconstruct($self->{oDb}{strDbVersion}, $self->{oDb}{ullDbSysId});\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"logEnable();\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"or do\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"logEnable();\n"
|
||||
"$iResult = exceptionCode($EVAL_ERROR);\n"
|
||||
"$strResultMessage = exceptionMessage($EVAL_ERROR);\n"
|
||||
"};\n"
|
||||
"\n\n"
|
||||
"if ($iResult == 0)\n"
|
||||
"{\n"
|
||||
"$oInfo->save();\n"
|
||||
"\n\n"
|
||||
"storageRepo()->pathSync(\n"
|
||||
"defined($oInfo->{strArchiveClusterPath}) ? $oInfo->{strArchiveClusterPath} : $oInfo->{strBackupClusterPath});\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"if (defined($strWarningMsgArchive))\n"
|
||||
"{\n"
|
||||
"&log(WARN, $strWarningMsgArchive);\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'iResult', value => $iResult},\n"
|
||||
"{name => 'strResultMessage', value => $strResultMessage},\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub dbInfoGet\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->dbInfoGet');\n"
|
||||
"\n\n\n\n"
|
||||
"if (cfgOption(CFGOPT_ONLINE))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"$self->{oDb}->configValidate();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"($self->{oDb}{strDbVersion}, $self->{oDb}{iControlVersion}, $self->{oDb}{iCatalogVersion}, $self->{oDb}{ullDbSysId})\n"
|
||||
"= $self->{oDb}->info();\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn($strOperation);\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub upgradeCheck\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"$oInfo,\n"
|
||||
"$strPathType,\n"
|
||||
"$iExpectedError,\n"
|
||||
") =\n"
|
||||
"logDebugParam\n"
|
||||
"(\n"
|
||||
"__PACKAGE__ . '->upgradeCheck', \\@_,\n"
|
||||
"{name => 'oInfo'},\n"
|
||||
"{name => 'strPathType'},\n"
|
||||
"{name => 'iExpectedError'},\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"my $iResult = 0;\n"
|
||||
"my $strResultMessage = undef;\n"
|
||||
"\n\n"
|
||||
"logDisable();\n"
|
||||
"\n"
|
||||
"eval\n"
|
||||
"{\n"
|
||||
"($strPathType eq STORAGE_REPO_BACKUP)\n"
|
||||
"? $oInfo->check($self->{oDb}{strDbVersion}, $self->{oDb}{iControlVersion}, $self->{oDb}{iCatalogVersion},\n"
|
||||
"$self->{oDb}{ullDbSysId}, true)\n"
|
||||
": $oInfo->check($self->{oDb}{strDbVersion}, $self->{oDb}{ullDbSysId}, true);\n"
|
||||
"logEnable();\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"or do\n"
|
||||
"{\n"
|
||||
"logEnable();\n"
|
||||
"\n\n"
|
||||
"confess $EVAL_ERROR if (exceptionCode($EVAL_ERROR) != $iExpectedError);\n"
|
||||
"\n\n"
|
||||
"$iResult = exceptionCode($EVAL_ERROR);\n"
|
||||
"$strResultMessage = exceptionMessage($EVAL_ERROR);\n"
|
||||
"};\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'bResult', value => ($iResult == $iExpectedError ? true : false)},\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"1;\n"
|
||||
},
|
||||
{
|
||||
.name = "pgBackRest/Storage/Base.pm",
|
||||
.data =
|
||||
|
@ -14,6 +14,7 @@ PostgreSQL Interface
|
||||
Defines for various Postgres paths and files
|
||||
***********************************************************************************************************************************/
|
||||
#define PG_FILE_PGCONTROL "pg_control"
|
||||
#define PG_FILE_POSTMASTERPID "postmaster.pid"
|
||||
|
||||
#define PG_PATH_ARCHIVE_STATUS "archive_status"
|
||||
#define PG_PATH_GLOBAL "global"
|
||||
|
@ -685,6 +685,16 @@ unit:
|
||||
command/restore/file: full
|
||||
command/restore/protocol: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: stanza
|
||||
total: 5
|
||||
|
||||
coverage:
|
||||
command/stanza/common: full
|
||||
command/stanza/create: full
|
||||
command/stanza/upgrade: full
|
||||
command/stanza/delete: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: storage
|
||||
total: 1
|
||||
@ -712,14 +722,6 @@ unit:
|
||||
- name: all-perl
|
||||
total: 11
|
||||
|
||||
# ********************************************************************************************************************************
|
||||
- name: stanza
|
||||
|
||||
test:
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: all-perl
|
||||
total: 9
|
||||
|
||||
# **********************************************************************************************************************************
|
||||
# Integration tests
|
||||
#
|
||||
|
@ -2062,8 +2062,8 @@ stanza-create db - fail on backup directory missing backup.info (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [055]: backup information missing
|
||||
HINT: use stanza-create --force to force the stanza data to be recreated.
|
||||
P00 ERROR: [055]: archive.info exists but backup.info is missing
|
||||
HINT: this may be a symptom of repository corruption!
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
@ -2081,49 +2081,6 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
stanza-create db - create required data for stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2 --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[backup:current]
|
||||
[BACKUP-FULL-2]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"full","db-id":1,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":true,"option-compress":false,"option-hardlink":false,"option-online":false}
|
||||
[BACKUP-DIFF-2]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-prior":"[BACKUP-FULL-2]","backup-reference":["[BACKUP-FULL-2]"],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"diff","db-id":1,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":true,"option-compress":false,"option-hardlink":false,"option-online":false}
|
||||
[BACKUP-INCR-3]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-prior":"[BACKUP-DIFF-2]","backup-reference":["[BACKUP-FULL-2]","[BACKUP-DIFF-2]"],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"incr","db-id":1,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":true,"option-compress":false,"option-hardlink":false,"option-online":false}
|
||||
|
||||
[db]
|
||||
db-catalog-version=201409291
|
||||
db-control-version=942
|
||||
db-id=1
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
incr backup - update files (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -1576,29 +1576,6 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
stanza-create db - create required data for stanza (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 ERROR: [055]: backup information missing and repo is encrypted and info file(s) are missing, --force cannot be used
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[cipher]
|
||||
cipher-pass=[CIPHER-PASS-2]
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
incr backup - update files (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -26,9 +26,9 @@ P00 ERROR: [055]: unable to load info file '[TEST_PATH]/db-master/repo/archive/
|
||||
P00 INFO: archive-get command end: aborted with exception [055]
|
||||
|
||||
stanza-create db - stanza create (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
|
@ -26,9 +26,9 @@ P00 ERROR: [055]: unable to load info file 'archive/db/archive.info' or 'archiv
|
||||
P00 INFO: archive-get command end: aborted with exception [055]
|
||||
|
||||
stanza-create db - stanza create (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-2] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-2] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
@ -2,18 +2,21 @@ run 001 - remote 0, s3 0, enc 0
|
||||
===============================
|
||||
|
||||
stanza-create db - fail on missing control file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --log-level-file=info stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [041]: unable to open [TEST_PATH]/db-master/db/base/global/pg_control
|
||||
P00 INFO: stanza-create command end: aborted with exception [041]
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=info --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [055]: unable to open missing file '[TEST_PATH]/db-master/db/base/global/pg_control' for read
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
stanza-upgrade db - fail on stanza not initialized since archive.info is missing (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [055]: archive.info does not exist but is required to push/get WAL segments
|
||||
HINT: is archive_command configured in postgresql.conf?
|
||||
P00 ERROR: [055]: unable to load info file '[TEST_PATH]/db-master/repo/archive/db/archive.info' or '[TEST_PATH]/db-master/repo/archive/db/archive.info.copy':
|
||||
FileMissingError: unable to open missing file '[TEST_PATH]/db-master/repo/archive/db/archive.info' for read
|
||||
FileMissingError: unable to open missing file '[TEST_PATH]/db-master/repo/archive/db/archive.info.copy' for read
|
||||
HINT: archive.info cannot be opened but is required to push/get WAL segments.
|
||||
HINT: is archive_command configured correctly in postgresql.conf?
|
||||
HINT: has a stanza-create been performed?
|
||||
HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving scheme.
|
||||
P00 INFO: stanza-upgrade command end: aborted with exception [055]
|
||||
@ -60,7 +63,7 @@ stanza-create db - do not fail on rerun of stanza-create - info files exist and
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create was already performed
|
||||
P00 INFO: stanza 'db' already exists and is valid
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
@ -95,12 +98,14 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
stanza-create db - fail on database mismatch without force option (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
stanza-create db - fail on database mismatch and warn force option deprecated (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [028]: backup info file or archive info file invalid
|
||||
HINT: use stanza-upgrade if the database has been upgraded or use --force
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 WARN: option --force is no longer supported
|
||||
P00 ERROR: [028]: backup and archive info files already exist but do not match the database
|
||||
HINT: is this the correct stanza?
|
||||
HINT: did an error occur during stanza-upgrade?
|
||||
P00 INFO: stanza-create command end: aborted with exception [028]
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
@ -139,7 +144,7 @@ stanza-upgrade db - already up to date (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: the stanza data is already up to date
|
||||
P00 INFO: stanza 'db' is already up to date
|
||||
P00 INFO: stanza-upgrade command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
@ -184,8 +189,8 @@ stanza-create db - fail on archive info file missing from non-empty dir (db-mast
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [055]: archive information missing
|
||||
HINT: use stanza-create --force to force the stanza data to be recreated.
|
||||
P00 ERROR: [055]: backup.info exists but archive.info is missing
|
||||
HINT: this may be a symptom of repository corruption!
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
@ -205,183 +210,6 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
stanza-create db - gunzip fail on forced stanza-create (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [041]: unable to open file '[TEST_PATH]/db-master/repo/archive/db/9.3-1/0000000100000001/000000010000000100000001-488ba4b8b98acc510bce86b8f16e3c1ed9886a29.gz' for read: [13] Permission denied
|
||||
P00 INFO: stanza-create command end: aborted with exception [041]
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-catalog-version=201306121
|
||||
db-control-version=937
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
stanza-create db - force create archive.info from gz file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-catalog-version=201306121
|
||||
db-control-version=937
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
stanza-create db - force create archive.info from uncompressed file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-catalog-version=201306121
|
||||
db-control-version=937
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
stanza-create db - force with missing WAL archive file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-catalog-version=201306121
|
||||
db-control-version=937
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
stanza-create db - force with missing WAL archive directory (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 WARN: found empty directory [TEST_PATH]/db-master/repo/archive/db/9.3-1
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-catalog-version=201306121
|
||||
db-control-version=937
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
@ -442,85 +270,6 @@ P00 INFO: archive-get command end: completed successfully
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - use force to recreate the stanza producing mismatched info history but same current db-id (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-catalog-version=201409291
|
||||
db-control-version=942
|
||||
db-id=2
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=2
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
stanza-create db - use force to recreate the stanza producing mismatched db-id (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-catalog-version=201409291
|
||||
db-control-version=942
|
||||
db-id=1
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=2
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
full backup - create first full backup (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --repo1-retention-full=2 --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -535,123 +284,34 @@ P00 INFO: full backup size = 48MB
|
||||
P00 INFO: new backup label = [BACKUP-FULL-1]
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --repo1-retention-full=2 --stanza=db --start-fast --type=full
|
||||
P00 ERROR: [029]: archive expiration cannot continue - archive and backup history lists do not match
|
||||
P00 INFO: expire command end: aborted with exception [029]
|
||||
|
||||
stanza-create db - fail no force to recreate the stanza from backups (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [055]: backup information missing
|
||||
HINT: use stanza-create --force to force the stanza data to be recreated.
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
P00 INFO: remove archive path: [TEST_PATH]/db-master/repo/archive/db/9.3-1
|
||||
P00 INFO: full backup total < 2 - using oldest full backup for 9.4-2 archive retention
|
||||
P00 INFO: expire command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
[db]
|
||||
db-id=2
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
pg1-path=[TEST_PATH]/db-master/db/base
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
[global]
|
||||
compress-level=3
|
||||
db-timeout=45
|
||||
lock-path=[TEST_PATH]/db-master/lock
|
||||
log-level-console=detail
|
||||
log-level-file=trace
|
||||
log-level-stderr=off
|
||||
log-path=[TEST_PATH]/db-master/log
|
||||
log-subprocess=y
|
||||
log-timestamp=n
|
||||
protocol-timeout=60
|
||||
repo1-path=[TEST_PATH]/db-master/repo
|
||||
spool-path=[TEST_PATH]/db-master/spool
|
||||
|
||||
stanza-create db - use force to recreate the stanza from backups (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
[global:backup]
|
||||
archive-copy=y
|
||||
start-fast=y
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[backup:current]
|
||||
[BACKUP-FULL-1]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"full","db-id":1,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":false,"option-compress":true,"option-hardlink":false,"option-online":false}
|
||||
|
||||
[db]
|
||||
db-catalog-version=201409291
|
||||
db-control-version=942
|
||||
db-id=1
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=2
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
stanza-upgrade db - successfully upgrade with XX.Y-Z (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 WARN: backup [BACKUP-FULL-1] found in repository added to backup.info
|
||||
P00 INFO: stanza-upgrade command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[backup:current]
|
||||
[BACKUP-FULL-1]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"full","db-id":1,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":false,"option-compress":true,"option-hardlink":false,"option-online":false}
|
||||
|
||||
[db]
|
||||
db-catalog-version=201510051
|
||||
db-control-version=942
|
||||
db-id=3
|
||||
db-system-id=1000000000000000095
|
||||
db-version="9.5"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-catalog-version":201510051,"db-control-version":942,"db-system-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=4
|
||||
db-system-id=1000000000000000095
|
||||
db-version="9.5"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-id":1000000000000000100,"db-version":"10"}
|
||||
4={"db-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
stanza-upgrade db - successfully upgrade - no info file mismatch (db-master host)
|
||||
stanza-upgrade db - successfully upgrade (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
@ -665,7 +325,7 @@ backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[backup:current]
|
||||
[BACKUP-FULL-1]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"full","db-id":1,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":false,"option-compress":true,"option-hardlink":false,"option-online":false}
|
||||
[BACKUP-FULL-1]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"full","db-id":2,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":false,"option-compress":true,"option-hardlink":false,"option-online":false}
|
||||
|
||||
[db]
|
||||
db-catalog-version=201510051
|
||||
@ -696,6 +356,53 @@ db-version="9.5"
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
stanza-upgrade db - upgrade fails with mismatched db-ids (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [028]: backup info file and archive info file do not match
|
||||
archive: id = 2, version = 9.5, system-id = 1000000000000000095
|
||||
backup : id = 3, version = 9.5, system-id = 1000000000000000095
|
||||
HINT: this may be a symptom of repository corruption!
|
||||
P00 INFO: stanza-upgrade command end: aborted with exception [028]
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[backup:current]
|
||||
[BACKUP-FULL-1]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"full","db-id":2,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":false,"option-compress":true,"option-hardlink":false,"option-online":false}
|
||||
|
||||
[db]
|
||||
db-catalog-version=201510051
|
||||
db-control-version=942
|
||||
db-id=3
|
||||
db-system-id=1000000000000000095
|
||||
db-version="9.5"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-catalog-version":201510051,"db-control-version":942,"db-system-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -714,7 +421,6 @@ P00 INFO: full backup size = 48MB
|
||||
P00 INFO: new backup label = [BACKUP-FULL-2]
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --repo1-retention-full=2 --stanza=db --start-fast --type=diff
|
||||
P00 INFO: remove archive path: [TEST_PATH]/db-master/repo/archive/db/9.4-2
|
||||
P00 INFO: expire command end: completed successfully
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
@ -748,11 +454,11 @@ info all stanzas - db upgraded - db-1 and db-2 listed (db-master host)
|
||||
"archive" : [
|
||||
{
|
||||
"database" : {
|
||||
"id" : 1
|
||||
"id" : 2
|
||||
},
|
||||
"id" : "9.3-1",
|
||||
"max" : "000000010000000100000002",
|
||||
"min" : "000000010000000100000002"
|
||||
"id" : "9.4-2",
|
||||
"max" : "000000010000000100000001",
|
||||
"min" : "000000010000000100000001"
|
||||
},
|
||||
{
|
||||
"database" : {
|
||||
@ -774,7 +480,7 @@ info all stanzas - db upgraded - db-1 and db-2 listed (db-master host)
|
||||
"version" : "[VERSION-1]"
|
||||
},
|
||||
"database" : {
|
||||
"id" : 1
|
||||
"id" : 2
|
||||
},
|
||||
"info" : {
|
||||
"delta" : [DELTA],
|
||||
@ -854,7 +560,7 @@ stanza-delete db - fail on missing stop file (db-master host)
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-delete command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 ERROR: [055]: stop file does not exist for stanza 'db'
|
||||
HINT: has the pgbackrest stop command been run on this server?
|
||||
HINT: has the pgbackrest stop command been run on this server for this stanza?
|
||||
P00 INFO: stanza-delete command end: aborted with exception [055]
|
||||
|
||||
db must not exist for successful delete
|
||||
|
@ -2,18 +2,21 @@ run 002 - remote 1, s3 1, enc 1
|
||||
===============================
|
||||
|
||||
stanza-create db - fail on missing control file (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online --log-level-file=info stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [041]: raised from remote process on 'db-master': unable to open [TEST_PATH]/db-master/db/base/global/pg_control
|
||||
P00 INFO: stanza-create command end: aborted with exception [041]
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=info --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [055]: raised from remote-0 protocol on 'db-master': unable to open missing file '[TEST_PATH]/db-master/db/base/global/pg_control' for read
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
stanza-upgrade db - fail on stanza not initialized since archive.info is missing (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [055]: archive.info does not exist but is required to push/get WAL segments
|
||||
HINT: is archive_command configured in postgresql.conf?
|
||||
P00 ERROR: [055]: unable to load info file '/archive/db/archive.info' or '/archive/db/archive.info.copy':
|
||||
FileMissingError: unable to open '/archive/db/archive.info': No such file or directory
|
||||
FileMissingError: unable to open '/archive/db/archive.info.copy': No such file or directory
|
||||
HINT: archive.info cannot be opened but is required to push/get WAL segments.
|
||||
HINT: is archive_command configured correctly in postgresql.conf?
|
||||
HINT: has a stanza-create been performed?
|
||||
HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving scheme.
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
@ -70,7 +73,7 @@ stanza-create db - do not fail on rerun of stanza-create - info files exist and
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 INFO: stanza-create was already performed
|
||||
P00 INFO: stanza 'db' already exists and is valid
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-create command end: completed successfully
|
||||
@ -113,12 +116,14 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
stanza-create db - fail on database mismatch without force option (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
stanza-create db - fail on database mismatch and warn force option deprecated (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [028]: backup info file or archive info file invalid
|
||||
HINT: use stanza-upgrade if the database has been upgraded or use --force
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 WARN: option --force is no longer supported
|
||||
P00 ERROR: [028]: backup and archive info files already exist but do not match the database
|
||||
HINT: is this the correct stanza?
|
||||
HINT: did an error occur during stanza-upgrade?
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-create command end: aborted with exception [028]
|
||||
@ -165,7 +170,7 @@ stanza-upgrade db - already up to date (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 INFO: the stanza data is already up to date
|
||||
P00 INFO: stanza 'db' is already up to date
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-upgrade command end: completed successfully
|
||||
@ -214,35 +219,6 @@ P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-maste
|
||||
P00 INFO: pushed WAL file '000000010000000100000001' to the archive
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
|
||||
stanza-create db - force create archive.info from gz file (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [055]: archive information missing and repo is encrypted and info file(s) are missing, --force cannot be used
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[cipher]
|
||||
cipher-pass=[CIPHER-PASS-1]
|
||||
|
||||
[db]
|
||||
db-catalog-version=201306121
|
||||
db-control-version=937
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
@ -392,63 +368,7 @@ repo1-type=s3
|
||||
archive-copy=y
|
||||
start-fast=y
|
||||
|
||||
stanza-create db - fail no force to recreate the stanza from backups (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [055]: backup information missing and repo is encrypted and info file(s) are missing, --force cannot be used
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[cipher]
|
||||
cipher-pass=[CIPHER-PASS-2]
|
||||
|
||||
[db]
|
||||
db-id=2
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
stanza-create db - use force to recreate the stanza from backups (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [055]: backup information missing and repo is encrypted and info file(s) are missing, --force cannot be used
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[cipher]
|
||||
cipher-pass=[CIPHER-PASS-2]
|
||||
|
||||
[db]
|
||||
db-id=2
|
||||
db-system-id=1000000000000000094
|
||||
db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
stanza-upgrade db - successfully upgrade - no info file mismatch (backup host)
|
||||
stanza-upgrade db - successfully upgrade (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
@ -501,6 +421,61 @@ db-version="9.5"
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
stanza-upgrade db - upgrade fails with mismatched db-ids (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-upgrade command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [028]: backup info file and archive info file do not match
|
||||
archive: id = 2, version = 9.5, system-id = 1000000000000000095
|
||||
backup : id = 3, version = 9.5, system-id = 1000000000000000095
|
||||
HINT: this may be a symptom of repository corruption!
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-upgrade command end: aborted with exception [028]
|
||||
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[backup:current]
|
||||
[BACKUP-FULL-1]={"backrest-format":5,"backrest-version":"[VERSION-1]","backup-archive-start":null,"backup-archive-stop":null,"backup-info-repo-size":[SIZE],"backup-info-repo-size-delta":[DELTA],"backup-info-size":[SIZE],"backup-info-size-delta":[DELTA],"backup-timestamp-start":[TIMESTAMP],"backup-timestamp-stop":[TIMESTAMP],"backup-type":"full","db-id":2,"option-archive-check":true,"option-archive-copy":true,"option-backup-standby":false,"option-checksum-page":false,"option-compress":true,"option-hardlink":false,"option-online":false}
|
||||
|
||||
[cipher]
|
||||
cipher-pass=[CIPHER-PASS-1]
|
||||
|
||||
[db]
|
||||
db-catalog-version=201510051
|
||||
db-control-version=942
|
||||
db-id=3
|
||||
db-system-id=1000000000000000095
|
||||
db-version="9.5"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-catalog-version":201510051,"db-control-version":942,"db-system-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
[cipher]
|
||||
cipher-pass=[CIPHER-PASS-2]
|
||||
|
||||
[db]
|
||||
db-id=1
|
||||
db-system-id=1000000000000000093
|
||||
db-version="9.3"
|
||||
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -698,7 +673,9 @@ stanza-delete db - fail on missing stop file (backup host)
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-delete command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 ERROR: [055]: stop file does not exist for stanza 'db'
|
||||
HINT: has the pgbackrest stop command been run on this server?
|
||||
HINT: has the pgbackrest stop command been run on this server for this stanza?
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
P00 INFO: http statistics:[HTTP-STATISTICS]
|
||||
P00 INFO: stanza-delete command end: aborted with exception [055]
|
||||
|
||||
db must not exist for successful delete
|
||||
|
@ -9,10 +9,6 @@ check db - fail on missing archive.info file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=0.1 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - force create stanza info files (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
full backup - fail on archive_mode=off (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -61,10 +57,6 @@ stanza-create db - fail on backup info file missing from non-empty dir (db-maste
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - verify success with force (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - fail on database mismatch with directory (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --pg1-path=[TEST_PATH]/db-master/db/testbase/ stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -9,10 +9,6 @@ check db - fail on missing archive.info file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=0.1 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - force create stanza info files (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
full backup - fail on archive_mode=off (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -89,6 +85,10 @@ stanza-create db - fail on backup info file missing from non-empty dir (backup h
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - fail on database mismatch with directory (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --pg1-path=[TEST_PATH]/db-master/db/testbase/ stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - successfully create stanza files to be upgraded (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --pg1-path=[TEST_PATH]/db-master/db/testbase/ --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -9,10 +9,6 @@ check db - fail on missing archive.info file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=0.1 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - force create stanza info files (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
full backup - fail on archive_mode=off (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -85,8 +81,8 @@ check db - verify success after backup (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - verify success with force (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --force stanza-create
|
||||
stanza-create db - fail on backup info file missing from non-empty dir (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
stanza-create db - fail on database mismatch with directory (backup host)
|
||||
|
@ -19,10 +19,10 @@ use pgBackRest::Backup::Info;
|
||||
use pgBackRest::Common::Ini;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::Db;
|
||||
use pgBackRest::DbVersion;
|
||||
use pgBackRest::Manifest;
|
||||
use pgBackRest::Protocol::Storage::Helper;
|
||||
use pgBackRest::Stanza;
|
||||
use pgBackRest::Storage::Helper;
|
||||
use pgBackRest::Version;
|
||||
|
||||
@ -97,41 +97,57 @@ sub stanzaSet
|
||||
|
||||
# Assign variables
|
||||
my $oStanza = {};
|
||||
my $oArchiveInfo = {};
|
||||
my $oBackupInfo = {};
|
||||
my $bEncrypted = defined($self->{oStorageRepo}->cipherType());
|
||||
my $iArchiveDbId = 1;
|
||||
my $iBackupDbId = 1;
|
||||
|
||||
my $oStanzaCreate = new pgBackRest::Stanza();
|
||||
|
||||
# If we're not upgrading, then create the stanza
|
||||
# If we're not upgrading, then create the info files
|
||||
if (!$bStanzaUpgrade)
|
||||
{
|
||||
$oStanzaCreate->stanzaCreate();
|
||||
$oArchiveInfo =
|
||||
new pgBackRest::Archive::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_ARCHIVE), false,
|
||||
{bIgnoreMissing => true, strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_ARCHIVE : undef});
|
||||
$oBackupInfo =
|
||||
new pgBackRest::Backup::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_BACKUP), false, false,
|
||||
{bIgnoreMissing => true, strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_MANIFEST : undef});
|
||||
}
|
||||
# Else get the info data from disk
|
||||
else
|
||||
{
|
||||
$oArchiveInfo =
|
||||
new pgBackRest::Archive::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_ARCHIVE),
|
||||
{strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_ARCHIVE : undef});
|
||||
$oBackupInfo =
|
||||
new pgBackRest::Backup::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_BACKUP),
|
||||
{strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_MANIFEST : undef});
|
||||
}
|
||||
|
||||
my ($oDb) = dbObjectGet();
|
||||
if (cfgOption(CFGOPT_ONLINE))
|
||||
{
|
||||
# If the pg-path in pgbackrest.conf does not match the pg_control then this will error alert the user to fix pgbackrest.conf
|
||||
$oDb->configValidate();
|
||||
}
|
||||
|
||||
# Get the database info for the stanza
|
||||
(my $strVersion, $$oStanza{iControlVersion}, $$oStanza{iCatalogVersion}, $$oStanza{ullDbSysId}) = $oDb->info();
|
||||
$$oStanza{strDbVersion} = $strDbVersion;
|
||||
$$oStanza{ullDbSysId} = $oStanzaCreate->{oDb}{ullDbSysId};
|
||||
$$oStanza{iCatalogVersion} = $oStanzaCreate->{oDb}{iCatalogVersion};
|
||||
$$oStanza{iControlVersion} = $oStanzaCreate->{oDb}{iControlVersion};
|
||||
|
||||
my $bEncrypted = defined($self->{oStorageRepo}->cipherType());
|
||||
|
||||
my $oArchiveInfo =
|
||||
new pgBackRest::Archive::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_ARCHIVE),
|
||||
{strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_ARCHIVE : undef});
|
||||
my $oBackupInfo =
|
||||
new pgBackRest::Backup::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_BACKUP),
|
||||
{strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_MANIFEST : undef});
|
||||
|
||||
if ($bStanzaUpgrade)
|
||||
{
|
||||
# Upgrade the stanza
|
||||
$oArchiveInfo->dbSectionSet($$oStanza{strDbVersion}, $$oStanza{ullDbSysId}, $oArchiveInfo->dbHistoryIdGet() + 1);
|
||||
$oArchiveInfo->save();
|
||||
|
||||
$oBackupInfo->dbSectionSet($$oStanza{strDbVersion}, $$oStanza{iControlVersion}, $$oStanza{iCatalogVersion},
|
||||
$$oStanza{ullDbSysId}, $oBackupInfo->dbHistoryIdGet() + 1);
|
||||
$oBackupInfo->save();
|
||||
$iArchiveDbId = $oArchiveInfo->dbHistoryIdGet() + 1;
|
||||
$iBackupDbId = $oBackupInfo->dbHistoryIdGet() + 1;
|
||||
}
|
||||
|
||||
$oArchiveInfo->dbSectionSet($$oStanza{strDbVersion}, $$oStanza{ullDbSysId}, $iArchiveDbId);
|
||||
$oArchiveInfo->save();
|
||||
|
||||
$oBackupInfo->dbSectionSet($$oStanza{strDbVersion}, $$oStanza{iControlVersion}, $$oStanza{iCatalogVersion},
|
||||
$$oStanza{ullDbSysId}, $iBackupDbId);
|
||||
$oBackupInfo->save();
|
||||
|
||||
# Get the archive and directory paths for the stanza
|
||||
$$oStanza{strArchiveClusterPath} = $self->{oStorageRepo}->pathGet(STORAGE_REPO_ARCHIVE) . '/' . ($oArchiveInfo->archiveId());
|
||||
$$oStanza{strBackupClusterPath} = $self->{oStorageRepo}->pathGet(STORAGE_REPO_BACKUP);
|
||||
@ -176,6 +192,15 @@ sub stanzaCreate
|
||||
$self->controlGenerate($strDbPath, $strDbVersion);
|
||||
executeTest('sudo chmod 600 ' . $strDbPath . '/' . DB_FILE_PGCONTROL);
|
||||
|
||||
# Create the stanza repo paths if they don't exist
|
||||
if (!cfgOptionTest(CFGOPT_REPO_TYPE, CFGOPTVAL_REPO_TYPE_S3))
|
||||
{
|
||||
storageTest()->pathCreate(
|
||||
cfgOption(CFGOPT_REPO_PATH) . "/archive/$strStanza", {bIgnoreExists => true, bCreateParent => true});
|
||||
storageTest()->pathCreate(
|
||||
cfgOption(CFGOPT_REPO_PATH) . "/backup/$strStanza", {bIgnoreExists => true, bCreateParent => true});
|
||||
}
|
||||
|
||||
# Create the stanza and set the local stanza object
|
||||
$self->stanzaSet($strStanza, $strDbVersion, false);
|
||||
|
||||
|
@ -1119,23 +1119,15 @@ sub run
|
||||
$strType = CFGOPTVAL_BACKUP_TYPE_INCR;
|
||||
$oHostDbMaster->manifestReference(\%oManifest, $strBackup);
|
||||
|
||||
# Delete the backup.info and make sure the backup fails - the user must then run a stanza-create --force. If backup.info is
|
||||
# encrypted is cannot be deleted, so copy it to old instead.
|
||||
# Delete the backup.info and make sure the backup fails.
|
||||
my $strBackupInfoFile = STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO;
|
||||
my $strBackupInfoCopyFile = STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT;
|
||||
my $strBackupInfoOldFile = "${strBackupInfoFile}.old";
|
||||
my $strBackupInfoCopyOldFile = "${strBackupInfoCopyFile}.old";
|
||||
|
||||
if ($bEncrypt)
|
||||
{
|
||||
# Save the backup.info and copy files so they can be restored later
|
||||
forceStorageMove(storageRepo(), $strBackupInfoFile, $strBackupInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoCopyFile, $strBackupInfoCopyOldFile, {bRecurse => false});
|
||||
}
|
||||
else
|
||||
{
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoCopyFile);
|
||||
}
|
||||
|
||||
$oHostDbMaster->manifestFileCreate(
|
||||
\%oManifest, MANIFEST_TARGET_PGDATA, 'base/16384/17000', 'BASEUPDT', '9a53d532e27785e681766c98516a5e93f096a501',
|
||||
@ -1152,17 +1144,9 @@ sub run
|
||||
{iExpectedExitStatus => ERROR_FILE_MISSING, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
}
|
||||
|
||||
# Use force to create the stanza (this is expected to fail for encrypted repos)
|
||||
$oHostBackup->stanzaCreate('create required data for stanza',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE),
|
||||
iExpectedExitStatus => $bEncrypt ? ERROR_FILE_MISSING : undef});
|
||||
|
||||
# Copy encrypted backup info files back so testing can proceed
|
||||
if ($bEncrypt)
|
||||
{
|
||||
forceStorageMove(storageRepo(), $strBackupInfoOldFile, $strBackupInfoFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoCopyOldFile, $strBackupInfoCopyFile, {bRecurse => false});
|
||||
}
|
||||
# Copy backup info files back so testing can proceed
|
||||
forceStorageMove(storageRepo(), $strBackupInfoOldFile, $strBackupInfoFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoCopyOldFile, $strBackupInfoCopyFile, {bRecurse => false});
|
||||
|
||||
# Perform the backup
|
||||
$strBackup =$oHostBackup->backup($strType, 'update files', {oExpectedManifest => \%oManifest});
|
||||
|
@ -143,7 +143,7 @@ sub run
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$oHostBackup->stanzaCreate(
|
||||
'stanza create',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
&log(INFO, ' push first WAL');
|
||||
|
@ -79,8 +79,8 @@ sub run
|
||||
true, $self->expect(), {bHostBackup => $bRemote, bS3 => $bS3, bRepoEncrypt => $bEncrypt});
|
||||
|
||||
# Create the stanza
|
||||
$oHostBackup->stanzaCreate('fail on missing control file', {iExpectedExitStatus => ERROR_FILE_OPEN,
|
||||
strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
$oHostBackup->stanzaCreate('fail on missing control file', {iExpectedExitStatus => ERROR_FILE_MISSING,
|
||||
strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_LOG_LEVEL_FILE) . '=info'});
|
||||
|
||||
# Generate pg_control for stanza-create
|
||||
storageDb()->pathCreate(($oHostDbMaster->dbBasePath() . '/' . DB_PATH_GLOBAL), {bCreateParent => true});
|
||||
@ -106,8 +106,9 @@ sub run
|
||||
# Change the database version by copying a new pg_control file
|
||||
$self->controlGenerate($oHostDbMaster->dbBasePath(), PG_VERSION_94);
|
||||
|
||||
$oHostBackup->stanzaCreate('fail on database mismatch without force option',
|
||||
{iExpectedExitStatus => ERROR_FILE_INVALID, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
$oHostBackup->stanzaCreate('fail on database mismatch and warn force option deprecated',
|
||||
{iExpectedExitStatus => ERROR_FILE_INVALID, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) .
|
||||
' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
|
||||
# Restore pg_control
|
||||
$self->controlGenerate($oHostDbMaster->dbBasePath(), PG_VERSION_93);
|
||||
@ -130,17 +131,9 @@ sub run
|
||||
' --stanza=db archive-push';
|
||||
$oHostDbMaster->executeSimple($strCommand . " ${strSourceFile}", {oLogTest => $self->expect()});
|
||||
|
||||
# With data existing in the archive dir, remove the info files and confirm failure
|
||||
if ($bEncrypt)
|
||||
{
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoFile, $strArchiveInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyFile, $strArchiveInfoCopyOldFile, {bRecurse => false});
|
||||
}
|
||||
else
|
||||
{
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoCopyFile);
|
||||
}
|
||||
# With data existing in the archive dir, move the info files and confirm failure
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoFile, $strArchiveInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyFile, $strArchiveInfoCopyOldFile, {bRecurse => false});
|
||||
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
@ -148,96 +141,9 @@ sub run
|
||||
{iExpectedExitStatus => ERROR_FILE_MISSING, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
}
|
||||
|
||||
# Stanza Create fails using force - failure to unzip compressed file
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# S3 doesn't support filesystem-style permissions so skip these tests
|
||||
if (!$bS3)
|
||||
{
|
||||
# Change the permissions of the archive file so it cannot be read
|
||||
forceStorageMode(
|
||||
storageRepo(), STORAGE_REPO_ARCHIVE . qw{/} . PG_VERSION_93 . '-1/' . substr($strArchiveFile, 0, 16) . '/*.' .
|
||||
COMPRESS_EXT,
|
||||
'220');
|
||||
|
||||
# Force creation of the info file but fail on gunzip
|
||||
$oHostBackup->stanzaCreate('gunzip fail on forced stanza-create',
|
||||
{iExpectedExitStatus => ERROR_FILE_OPEN, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' .
|
||||
cfgOptionName(CFGOPT_FORCE)});
|
||||
|
||||
# Change permissions back
|
||||
forceStorageMode(
|
||||
storageRepo(), STORAGE_REPO_ARCHIVE . qw{/} . PG_VERSION_93 . '-1/' . substr($strArchiveFile, 0, 16) . '/*.' .
|
||||
COMPRESS_EXT,
|
||||
'640');
|
||||
}
|
||||
|
||||
# Stanza Create succeeds when using force - recreates archive.info from compressed archive file
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Force creation of archive info from the gz file
|
||||
$oHostBackup->stanzaCreate('force create archive.info from gz file',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE),
|
||||
iExpectedExitStatus => $bEncrypt ? ERROR_FILE_MISSING : undef});
|
||||
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
$self->testResult(sub {storageRepo()->exists($strArchiveInfoFile)}, true, " archive.info file was created");
|
||||
}
|
||||
|
||||
# Stanza Create succeeds when using force - recreates archive.info from uncompressed archive file
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Unzip the archive file and recreate the archive.info file from it
|
||||
my $strArchiveTest = PG_VERSION_93 . "-1/${strArchiveFile}-" . $self->walGenerateContentChecksum(PG_VERSION_93);
|
||||
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
forceStorageMode(
|
||||
storageRepo(), dirname(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/${strArchiveTest}.gz")), 'g+w',
|
||||
{bRecursive => true});
|
||||
|
||||
storageRepo()->copy(
|
||||
storageRepo()->openRead(
|
||||
STORAGE_REPO_ARCHIVE . "/${strArchiveTest}.gz",
|
||||
{rhyFilter => [{strClass => STORAGE_FILTER_GZIP, rxyParam => [STORAGE_DECOMPRESS, false]}]}),
|
||||
STORAGE_REPO_ARCHIVE . "/${strArchiveTest}");
|
||||
|
||||
$oHostBackup->stanzaCreate('force create archive.info from uncompressed file',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
}
|
||||
|
||||
# Stanza Create succeeds when using force - missing archive file
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Remove the uncompressed WAL archive file and archive.info
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . "/${strArchiveTest}");
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoCopyFile);
|
||||
|
||||
$oHostBackup->stanzaCreate('force with missing WAL archive file',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
}
|
||||
|
||||
# Stanza Create succeeds when using force - missing archive directory
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Remove the WAL archive directory
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
forceStorageRemove(
|
||||
storageRepo(),
|
||||
STORAGE_REPO_ARCHIVE . qw{/} . PG_VERSION_93 . '-1/' . substr($strArchiveFile, 0, 16), {bRecurse => true});
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoCopyFile);
|
||||
|
||||
$oHostBackup->stanzaCreate('force with missing WAL archive directory',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
}
|
||||
|
||||
# Encrypted info files could not be reconstructed above so just copy them back
|
||||
if ($bEncrypt)
|
||||
{
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoOldFile, $strArchiveInfoFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyOldFile, $strArchiveInfoCopyFile, {bRecurse => false});
|
||||
}
|
||||
# Restore info files from copy
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoOldFile, $strArchiveInfoFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyOldFile, $strArchiveInfoCopyFile, {bRecurse => false});
|
||||
|
||||
# Just before upgrading push one last WAL on the old version to ensure it can be retrieved later
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
@ -259,6 +165,9 @@ sub run
|
||||
|
||||
# Perform a successful stanza upgrade noting additional history lines in info files for new version of the database
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Save a pre-upgrade copy of archive info fo testing db-id mismatch
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyFile, $strArchiveInfoCopyOldFile, {bRecurse => false});
|
||||
|
||||
$oHostBackup->stanzaUpgrade('successful upgrade creates additional history', {strOptionalParam => '--no-' .
|
||||
cfgOptionName(CFGOPT_ONLINE)});
|
||||
|
||||
@ -286,104 +195,41 @@ sub run
|
||||
'000000010000000100000001-' . $self->walGenerateContentChecksum(PG_VERSION_94) . '.' . COMPRESS_EXT,
|
||||
'check that WAL is in the archive at -2');
|
||||
|
||||
# Create a DB history mismatch between the info files
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Remove the archive info file and force reconstruction
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoFile, $strArchiveInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyFile, $strArchiveInfoCopyOldFile, {bRecurse => false});
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoCopyFile);
|
||||
|
||||
$oHostBackup->stanzaCreate('use force to recreate the stanza producing mismatched info history but same current db-id',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
}
|
||||
|
||||
# Create a DB-ID mismatch between the info files
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
forceStorageMove(storageRepo(), $strBackupInfoFile, $strBackupInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoCopyFile, $strBackupInfoCopyOldFile, {bRecurse => false});
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoCopyFile);
|
||||
|
||||
$oHostBackup->stanzaCreate('use force to recreate the stanza producing mismatched db-id',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
}
|
||||
|
||||
# Confirm successful backup at db-1 although archive at db-2 and format error thrown by expire (if not encrypted) since
|
||||
# archive.info history and backup.info history are mismatched
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Create the tablespace directory and perform a backup
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
storageTest()->pathCreate($oHostDbMaster->dbBasePath() . '/' . DB_PATH_PGTBLSPC);
|
||||
$oHostBackup->backup(
|
||||
'full', 'create first full backup ',
|
||||
{iExpectedExitStatus => $bEncrypt ? undef : ERROR_FORMAT,
|
||||
strOptionalParam => '--repo1-retention-full=2 --no-' . cfgOptionName(CFGOPT_ONLINE)}, false);
|
||||
{strOptionalParam => '--repo1-retention-full=2 --no-' . cfgOptionName(CFGOPT_ONLINE)}, false);
|
||||
|
||||
# Stanza Create fails when not using force - no backup.info but backup exists
|
||||
# Upgrade the stanza
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
if ($bEncrypt)
|
||||
{
|
||||
forceStorageMove(storageRepo(), $strBackupInfoFile, $strBackupInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoCopyFile, $strBackupInfoCopyOldFile, {bRecurse => false});
|
||||
}
|
||||
else
|
||||
{
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoCopyFile);
|
||||
}
|
||||
|
||||
$oHostBackup->stanzaCreate('fail no force to recreate the stanza from backups',
|
||||
{iExpectedExitStatus => ERROR_FILE_MISSING, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
|
||||
# Stanza Create succeeds using force - reconstruct backup.info from backup
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
$oHostBackup->stanzaCreate('use force to recreate the stanza from backups',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE),
|
||||
iExpectedExitStatus => $bEncrypt ? ERROR_FILE_MISSING : undef});
|
||||
|
||||
# Copy old backup.info files back to avoid history mismatch
|
||||
forceStorageMove(storageRepo(), $strBackupInfoOldFile, $strBackupInfoFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoCopyOldFile, $strBackupInfoCopyFile, {bRecurse => false});
|
||||
|
||||
# Copy pg_control for 9.5
|
||||
$self->controlGenerate($oHostDbMaster->dbBasePath(), PG_VERSION_95);
|
||||
forceStorageMode(storageDb(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
|
||||
# Test archive dir version XX.Y-Z ensuring sort order of db ids is reconstructed correctly from the directory db-id value.
|
||||
# Not testing with encryption since unnecessary and copying files around in this case is burdensome.
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
if (!$bEncrypt)
|
||||
{
|
||||
# Create the 10-3 directory and copy a WAL file to it (with a different system id than what it will be upgraded to)
|
||||
forceStorageMode(storageRepo(), STORAGE_REPO_ARCHIVE, '770');
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . '/10-3/0000000100000001', {bCreateParent => true});
|
||||
storageRepo()->put(
|
||||
storageRepo()->openWrite(
|
||||
STORAGE_REPO_ARCHIVE . '/10-3/0000000100000001/000000010000000100000001',
|
||||
{strCipherPass => $oHostBackup->cipherPassArchive()}),
|
||||
$self->walGenerateContent(PG_VERSION_10));
|
||||
forceStorageOwner(storageRepo(), STORAGE_REPO_ARCHIVE . '/10-3', $oHostBackup->userGet(), {bRecurse => true});
|
||||
|
||||
# Make sure the archive.info has the history in the db-id order such that 10 is before 9.5.
|
||||
$oHostBackup->stanzaUpgrade(
|
||||
'successfully upgrade with XX.Y-Z',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
$oHostBackup->stanzaUpgrade('successfully upgrade', {strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
|
||||
# Remove the 10-3 directory and copy old archive.info file back. Recreate so archive.info and backup.info files match.
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . '/10-3', {bRecurse => true});
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile);
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoCopyFile);
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoOldFile, $strArchiveInfoFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyOldFile, $strArchiveInfoCopyFile, {bRecurse => false});
|
||||
}
|
||||
# Copy archive.info and restore really old version
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoFile, $strArchiveInfoOldFile, {bRecurse => false});
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoCopyFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyOldFile, $strArchiveInfoFile, {bRecurse => false});
|
||||
|
||||
# Confirm versions
|
||||
my $oAchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet('archive/' . $self->stanza()));
|
||||
my $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet('backup/' . $self->stanza()));
|
||||
$self->testResult(sub {$oAchiveInfo->test(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION, undef,
|
||||
PG_VERSION_93)}, true, 'archive at old pg version');
|
||||
$self->testResult(sub {$oBackupInfo->test(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_DB_VERSION, undef,
|
||||
PG_VERSION_95)}, true, 'backup at new pg version');
|
||||
|
||||
$oHostBackup->stanzaUpgrade(
|
||||
'successfully upgrade - no info file mismatch',
|
||||
{strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
'upgrade fails with mismatched db-ids',
|
||||
{iExpectedExitStatus => ERROR_FILE_INVALID, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
|
||||
# Restore archive.info
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoOldFile, $strArchiveInfoFile, {bRecurse => false});
|
||||
|
||||
# Push a WAL and create a backup in the new DB to confirm diff changed to full and info command displays the JSON correctly
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -151,15 +151,28 @@ sub run
|
||||
# In this section the same comment can be used multiple times so make it a variable that can be set once and reused
|
||||
my $strComment = undef;
|
||||
|
||||
# Remove the files in the archive directory
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE, {bRecurse => true});
|
||||
# Archive and backup info file names
|
||||
my $strArchiveInfoFile = STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE;
|
||||
my $strArchiveInfoCopyFile = STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE . INI_COPY_EXT;
|
||||
my $strArchiveInfoOldFile = "${strArchiveInfoFile}.old";
|
||||
my $strArchiveInfoCopyOldFile = "${strArchiveInfoCopyFile}.old";
|
||||
|
||||
my $strBackupInfoFile = STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO;
|
||||
my $strBackupInfoCopyFile = STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT;
|
||||
my $strBackupInfoOldFile = "${strBackupInfoFile}.old";
|
||||
my $strBackupInfoCopyOldFile = "${strBackupInfoCopyFile}.old";
|
||||
|
||||
# Move the archive.info files to simulate missing file
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoFile, $strArchiveInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyFile, $strArchiveInfoCopyOldFile, {bRecurse => false});
|
||||
|
||||
$oHostDbMaster->check(
|
||||
'fail on missing archive.info file',
|
||||
{iTimeout => 0.1, iExpectedExitStatus => ERROR_FILE_MISSING});
|
||||
|
||||
# Backup.info was created earlier so force stanza-create to create archive info file
|
||||
$oHostBackup->stanzaCreate('force create stanza info files', {strOptionalParam => ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
# Backup.info was created earlier so restore archive info files
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoOldFile, $strArchiveInfoFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyOldFile, $strArchiveInfoCopyFile, {bRecurse => false});
|
||||
|
||||
# Check ERROR_ARCHIVE_DISABLED error
|
||||
$strComment = 'fail on archive_mode=off';
|
||||
@ -292,27 +305,14 @@ sub run
|
||||
|
||||
# Stanza Create
|
||||
#-----------------------------------------------------------------------------------------------------------------------
|
||||
# With data existing in the archive and backup directory, remove info files and confirm failure
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO);
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT);
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE);
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE . INI_COPY_EXT);
|
||||
# With data existing in the archive and backup directory, move info files and confirm failure
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoFile, $strArchiveInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strArchiveInfoCopyFile, $strArchiveInfoCopyOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoFile, $strBackupInfoOldFile, {bRecurse => false});
|
||||
forceStorageMove(storageRepo(), $strBackupInfoCopyFile, $strBackupInfoCopyOldFile, {bRecurse => false});
|
||||
|
||||
if (!$bS3)
|
||||
{
|
||||
$oHostBackup->stanzaCreate('fail on backup info file missing from non-empty dir',
|
||||
{iExpectedExitStatus => ERROR_PATH_NOT_EMPTY});
|
||||
}
|
||||
|
||||
if (!$bRepoEncrypt)
|
||||
{
|
||||
# Force the backup.info file to be recreated
|
||||
$oHostBackup->stanzaCreate('verify success with force', {strOptionalParam => ' --' . cfgOptionName(CFGOPT_FORCE)});
|
||||
|
||||
# Remove the backup info file
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO);
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT);
|
||||
}
|
||||
$oHostBackup->stanzaCreate(
|
||||
'fail on backup info file missing from non-empty dir', {iExpectedExitStatus => ERROR_PATH_NOT_EMPTY});
|
||||
|
||||
# Change the database version by copying a new pg_control file to a new pg-path to use for db mismatch test
|
||||
storageDb()->pathCreate(
|
||||
@ -321,23 +321,18 @@ sub run
|
||||
$self->controlGenerate(
|
||||
$oHostDbMaster->dbPath() . '/testbase', $self->pgVersion() eq PG_VERSION_94 ? PG_VERSION_95 : PG_VERSION_94);
|
||||
|
||||
if (!$bRepoEncrypt)
|
||||
{
|
||||
# Run stanza-create online to confirm proper handling of configValidation error against new pg-path
|
||||
$oHostBackup->stanzaCreate('fail on database mismatch with directory',
|
||||
{strOptionalParam => ' --' . cfgOptionName(CFGOPT_PG_PATH) . '=' . $oHostDbMaster->dbPath() .
|
||||
'/testbase/', iExpectedExitStatus => ERROR_DB_MISMATCH});
|
||||
}
|
||||
# If encrypted, need to clean out repo and recreate
|
||||
else
|
||||
{
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP, {bRecurse => true});
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE, {bRecurse => true});
|
||||
}
|
||||
# Run stanza-create online to confirm proper handling of configValidation error against new pg-path
|
||||
$oHostBackup->stanzaCreate('fail on database mismatch with directory',
|
||||
{strOptionalParam => ' --' . cfgOptionName(CFGOPT_PG_PATH) . '=' . $oHostDbMaster->dbPath() .
|
||||
'/testbase/', iExpectedExitStatus => ERROR_DB_MISMATCH});
|
||||
|
||||
# Remove the directories to be able to create the stanza
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP, {bRecurse => true});
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE, {bRecurse => true});
|
||||
|
||||
# Stanza Upgrade - tests configValidate code - all other tests in synthetic integration tests
|
||||
#-----------------------------------------------------------------------------------------------------------------------
|
||||
# Run stanza-create offline with --force to create files needing to be upgraded (using new pg-path)
|
||||
# Run stanza-create offline to create files needing to be upgraded (using new pg-path)
|
||||
$oHostBackup->stanzaCreate('successfully create stanza files to be upgraded',
|
||||
{strOptionalParam =>
|
||||
' --' . cfgOptionName(CFGOPT_PG_PATH) . '=' . $oHostDbMaster->dbPath() .
|
||||
|
@ -1,825 +0,0 @@
|
||||
####################################################################################################################################
|
||||
# Unit tests for Stanza module
|
||||
####################################################################################################################################
|
||||
package pgBackRestTest::Module::Stanza::StanzaAllPerlTest;
|
||||
use parent 'pgBackRestTest::Env::HostEnvTest';
|
||||
|
||||
####################################################################################################################################
|
||||
# Perl includes
|
||||
####################################################################################################################################
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
use English '-no_match_vars';
|
||||
|
||||
use File::Basename qw(dirname);
|
||||
use Storable qw(dclone);
|
||||
|
||||
use pgBackRest::Archive::Common;
|
||||
use pgBackRest::Archive::Info;
|
||||
use pgBackRest::Backup::Common;
|
||||
use pgBackRest::Backup::Info;
|
||||
use pgBackRest::Common::Cipher;
|
||||
use pgBackRest::Common::Exception;
|
||||
use pgBackRest::Common::Ini;
|
||||
use pgBackRest::Common::Lock;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Common::String;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::DbVersion;
|
||||
use pgBackRest::InfoCommon;
|
||||
use pgBackRest::Manifest;
|
||||
use pgBackRest::Protocol::Helper;
|
||||
use pgBackRest::Stanza;
|
||||
use pgBackRest::Protocol::Storage::Helper;
|
||||
|
||||
use pgBackRestTest::Env::HostEnvTest;
|
||||
use pgBackRestTest::Common::ExecuteTest;
|
||||
use pgBackRestTest::Common::FileTest;
|
||||
use pgBackRestTest::Env::Host::HostBackupTest;
|
||||
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();
|
||||
$self->{strSpoolPath} = "$self->{strArchivePath}/out";
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# initTest
|
||||
####################################################################################################################################
|
||||
sub initTest
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Create archive info path
|
||||
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
|
||||
# Create backup info path
|
||||
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
|
||||
# Generate pg_control file
|
||||
storageTest()->pathCreate($self->{strDbPath} . '/' . DB_PATH_GLOBAL, {bCreateParent => true});
|
||||
$self->controlGenerate($self->{strDbPath}, PG_VERSION_94);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# run
|
||||
####################################################################################################################################
|
||||
sub run
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
||||
$self->optionTestSet(CFGOPT_PG_PATH, $self->{strDbPath});
|
||||
$self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath});
|
||||
$self->optionTestSet(CFGOPT_LOG_PATH, $self->testPath());
|
||||
|
||||
$self->optionTestSetBool(CFGOPT_ONLINE, false);
|
||||
|
||||
$self->optionTestSet(CFGOPT_DB_TIMEOUT, 5);
|
||||
$self->optionTestSet(CFGOPT_PROTOCOL_TIMEOUT, 6);
|
||||
|
||||
my $iDbControl = 942;
|
||||
my $iDbCatalog = 201409291;
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::new"))
|
||||
{
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->optionTestSetBool(CFGOPT_ONLINE, true);
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
|
||||
$self->testException(sub {(new pgBackRest::Stanza())}, ERROR_DB_CONNECT, "unable to connect to.*");
|
||||
|
||||
$self->optionTestSetBool(CFGOPT_ONLINE, false);
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::process()"))
|
||||
{
|
||||
$self->optionTestSetBool(CFGOPT_ONLINE, false);
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
|
||||
rmdir($self->{strArchivePath});
|
||||
rmdir($self->{strBackupPath});
|
||||
$self->testResult(sub {$oStanza->process()}, 0, 'parent paths recreated successfully');
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::stanzaCreate()"))
|
||||
{
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
|
||||
my $strBackupInfoFile = storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO);
|
||||
my $strBackupInfoFileCopy = storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT);
|
||||
my $strArchiveInfoFile = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE);
|
||||
|
||||
# No force. Archive dir not empty. No archive.info file. Backup directory empty.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/9.4-1");
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
|
||||
"archive directory not empty" .
|
||||
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
|
||||
|
||||
# No force. Archive dir not empty. No archive.info file. Backup directory not empty. No backup.info file.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/12345");
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
|
||||
"backup directory and/or archive directory not empty" .
|
||||
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
|
||||
|
||||
# No force. Archive dir empty. No archive.info file. Backup directory not empty. No backup.info file.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . "/9.4-1", {bRecurse => true});
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
|
||||
"backup directory not empty" .
|
||||
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
|
||||
|
||||
# No force. No archive.info file and no archive sub-directories or files. Backup.info exists and no backup sub-directories
|
||||
# or files
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . "/12345", {bRecurse => true});
|
||||
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_MISSING,
|
||||
"archive information missing" .
|
||||
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
|
||||
|
||||
# No force. No backup.info file (backup.info.copy only) and no backup sub-directories or files. Archive.info exists and no
|
||||
# archive sub-directories or files
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO);
|
||||
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94), true);
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
|
||||
"no error on missing backup.info since backup.info.copy exists and DB section OK");
|
||||
|
||||
# No force. No backup.info file (backup.info.copy only) and no backup sub-directories or files. No archive.info file
|
||||
# (archive.info.copy only) and no archive sub-directories or files
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE);
|
||||
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94), true);
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
|
||||
"no error on missing archive.info since archive.info.copy exists and DB section OK");
|
||||
|
||||
# No force. No backup.info files and no backup sub-directories or files. Archive.info exists and no
|
||||
# archive sub-directories or files
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT);
|
||||
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94), true);
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_MISSING,
|
||||
"backup information missing" .
|
||||
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
|
||||
|
||||
# No force. archive.info DB mismatch. backup.info correct DB.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile . "*");
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
|
||||
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_93,
|
||||
$self->dbSysId(PG_VERSION_93), true);
|
||||
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_INVALID,
|
||||
"backup info file or archive info file invalid\n" .
|
||||
"HINT: use stanza-upgrade if the database has been upgraded or use --force");
|
||||
|
||||
# No force. archive.info DB mismatch. backup.info DB mismatch.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
|
||||
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_93,
|
||||
$self->dbSysId(PG_VERSION_93), $iDbControl, $iDbCatalog, true);
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_INVALID,
|
||||
"backup info file or archive info file invalid\n" .
|
||||
"HINT: use stanza-upgrade if the database has been upgraded or use --force");
|
||||
|
||||
# No force. Create stanza.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile . "*");
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza without force');
|
||||
|
||||
# No force with .info and .info.copy files already existing
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
|
||||
"info files exist and check out ok - stanza create not needed");
|
||||
|
||||
# No force. Remove only backup.info.copy file - confirm stanza create does not throw an error since copy is still valid
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFileCopy);
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
|
||||
"info.copy file exists and check out ok - stanza create not needed");
|
||||
|
||||
# Force on. Valid archive.info exists. Invalid backup.info exists.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->optionTestSetBool(CFGOPT_FORCE, true);
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
|
||||
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_93), $iDbControl, $iDbCatalog, true);
|
||||
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force and existing info files');
|
||||
|
||||
$self->testResult(sub {(new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
|
||||
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))}, 2, ' backup.info reconstructed');
|
||||
|
||||
# Force on, Repo-Sync off. Archive dir empty. No archive.info file. Backup directory not empty. No backup.info file.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
|
||||
forceStorageRemove(storageRepo(), $strArchiveInfoFile . "*");
|
||||
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/12345");
|
||||
$oStanza = new pgBackRest::Stanza();
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force');
|
||||
$self->testResult(
|
||||
sub {(new pgBackRest::Archive::Info($self->{strArchivePath}))->check(
|
||||
PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94)) && (new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
|
||||
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))},
|
||||
1, ' new info files correct');
|
||||
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_BACKUP . "/12345"), {bRecurse => true});
|
||||
|
||||
# Force on. Attempt to change encryption on the repo
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
# Create unencrypted archive file
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1");
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001");
|
||||
my $strArchiveIdPath = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1");
|
||||
my $strArchivedFile = storageRepo()->pathGet($strArchiveIdPath .
|
||||
"/0000000100000001/000000010000000100000001-1e34fa1c833090d94b9bb14f2a8d3153dca6ea27");
|
||||
executeTest('cp ' . $self->dataPath() . "/filecopy.archive2.bin ${strArchivedFile}");
|
||||
|
||||
# Create unencrypted backup manifest file
|
||||
my $strBackupLabel = timestampFileFormat(undef, 1482000000) . 'F';
|
||||
my $strBackupPath = storageRepo->pathGet(STORAGE_REPO_BACKUP . "/${strBackupLabel}");
|
||||
|
||||
my $strBackupManifestFile = "$strBackupPath/" . FILE_MANIFEST;
|
||||
my $oBackupManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94,
|
||||
iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
|
||||
storageRepo()->pathCreate($strBackupPath);
|
||||
$oBackupManifest->save();
|
||||
|
||||
# Get the unencrypted content for later encryption
|
||||
my $tUnencryptedArchiveContent = ${storageRepo()->get($strArchivedFile)};
|
||||
my $tUnencryptedBackupContent = ${storageRepo()->get($strBackupManifestFile)};
|
||||
|
||||
# Change the permissions on the archived file so reconstruction fails
|
||||
executeTest('sudo chmod 220 ' . $strArchivedFile);
|
||||
$self->testException(sub {(new pgBackRest::Stanza())->stanzaCreate()}, ERROR_FILE_OPEN,
|
||||
"unable to open file '${strArchivedFile}' for read");
|
||||
executeTest('sudo chmod 644 ' . $strArchivedFile);
|
||||
|
||||
# Clear the cached repo settings and change repo settings to encrypted
|
||||
storageRepoCacheClear();
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
|
||||
$self->testException(sub {(new pgBackRest::Stanza())->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
|
||||
"files exist - the encryption type or passphrase cannot be changed");
|
||||
|
||||
# Remove the backup sub directories and files so that the archive file is attempted to be read
|
||||
forceStorageRemove(storageRepo(), $strBackupPath, {bRecurse => true});
|
||||
$self->testException(sub {(new pgBackRest::Stanza())->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
|
||||
"files exist - the encryption type or passphrase cannot be changed");
|
||||
|
||||
# Remove the archive sub directories and files so that only the info files exist - stanza create is allowed with force
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), $strArchiveIdPath, {bRecurse => true});
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force and new encrypted settings');
|
||||
|
||||
# Confirm encrypted
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
|
||||
. ARCHIVE_INFO_FILE)}, true, ' new archive info encrypted');
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
|
||||
. FILE_BACKUP_INFO)}, true, ' new backup info encrypted');
|
||||
|
||||
# Store the unencrypted archived file as encrypted and check stanza-create
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1");
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001");
|
||||
storageRepo()->put(
|
||||
storageRepo()->openWrite(
|
||||
$strArchivedFile, {strCipherPass => new pgBackRest::Archive::Info($self->{strArchivePath})->cipherPassSub()}),
|
||||
$tUnencryptedArchiveContent);
|
||||
storageRepo()->pathCreate($strBackupPath); # Empty backup path - no backup in progress
|
||||
|
||||
# Confirm encrypted and create the stanza with force
|
||||
$self->testResult(sub {storageRepo()->encrypted($strArchivedFile)}, true, 'new archive WAL encrypted');
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, ' successfully recreate stanza with force from encrypted WAL');
|
||||
|
||||
# Confirm the backup and archive info are encrypted and check the contents
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
|
||||
. ARCHIVE_INFO_FILE)}, true, ' new archive info encrypted');
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
|
||||
. FILE_BACKUP_INFO)}, true, ' new backup info encrypted');
|
||||
$self->testResult(
|
||||
sub {(new pgBackRest::Archive::Info($self->{strArchivePath}))->check(
|
||||
PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94)) && (new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
|
||||
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))},
|
||||
1, ' new archive.info and backup.info files correct');
|
||||
|
||||
# Store the unencrypted backup.manifest file as encrypted and check stanza-create
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
# Try to create a manifest without a passphrase in an encrypted storage
|
||||
$self->testException(sub {new pgBackRest::Manifest($strBackupManifestFile,
|
||||
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)})},
|
||||
ERROR_CRYPTO, 'passphrase is required when storage is encrypted');
|
||||
|
||||
# Get the encryption passphrase and create the new manifest
|
||||
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
|
||||
$oBackupManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94,
|
||||
iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94),
|
||||
strCipherPass => $oBackupInfo->cipherPassSub(), strCipherPassSub => cipherPassGen()});
|
||||
|
||||
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef, $strBackupLabel);
|
||||
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK, undef, true);
|
||||
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_COPY, undef, false);
|
||||
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_BACKUP_STANDBY, undef, false);
|
||||
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_START, undef, 1);
|
||||
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_STOP, undef, 1);
|
||||
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_CHECKSUM_PAGE, undef, true);
|
||||
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef, true);
|
||||
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_HARDLINK, undef, false);
|
||||
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, true);
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_START, undef, time());
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP, undef, time());
|
||||
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE, undef, CFGOPTVAL_BACKUP_TYPE_FULL);
|
||||
|
||||
$oBackupManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_94);
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL, undef, $iDbControl);
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, $iDbCatalog);
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID, undef, $self->dbSysId(PG_VERSION_94));
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID, undef, 1);
|
||||
$oBackupManifest->save();
|
||||
|
||||
# Confirm encrypted and create the stanza with force
|
||||
$self->testResult(sub {storageRepo()->encrypted($strBackupManifestFile)}, true, 'new backup manifest encrypted');
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
|
||||
' successfully recreate stanza with force from encrypted manifest and WAL');
|
||||
|
||||
# Confirm the backup and archive info are encrypted and check the contents
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
|
||||
. ARCHIVE_INFO_FILE)}, true, ' recreated archive info encrypted');
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
|
||||
. FILE_BACKUP_INFO)}, true, ' recreated backup info encrypted');
|
||||
$self->testResult(
|
||||
sub {(new pgBackRest::Archive::Info($self->{strArchivePath}))->check(
|
||||
PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94)) && (new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
|
||||
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))},
|
||||
1, ' recreated archive.info and backup.info files correct');
|
||||
|
||||
# Move the encrypted info files out of the repo so they are missing but backup exists. --force cannot be used
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
executeTest('sudo mv ' . storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/' . ARCHIVE_INFO_FILE . '* ' .
|
||||
$self->testPath() . '/');
|
||||
executeTest('sudo mv ' . storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/' . FILE_BACKUP_INFO . '* ' .
|
||||
$self->testPath() . '/');
|
||||
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
|
||||
"backup directory and/or archive directory not empty and repo is encrypted and info file(s) are missing," .
|
||||
" --force cannot be used");
|
||||
|
||||
# Move the files back for the next test
|
||||
executeTest('sudo mv ' . $self->testPath() . '/' . ARCHIVE_INFO_FILE . '* ' .
|
||||
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/');
|
||||
executeTest('sudo mv ' . $self->testPath() . '/' . FILE_BACKUP_INFO . '* ' .
|
||||
storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/');
|
||||
|
||||
# Change repo encryption settings to unencrypted - stanza create is not allowed even with force
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
# Clear the cached repo settings and change repo settings to unencrypted
|
||||
storageRepoCacheClear();
|
||||
$self->optionTestClear(CFGOPT_REPO_CIPHER_TYPE);
|
||||
$self->optionTestClear(CFGOPT_REPO_CIPHER_PASS);
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
|
||||
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
|
||||
"files exist - the encryption type or passphrase cannot be changed");
|
||||
|
||||
# With only info files - stanza create is allowed with force
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
forceStorageRemove(storageRepo(), $strArchiveIdPath, {bRecurse => true});
|
||||
forceStorageRemove(storageRepo(), $strBackupPath, {bRecurse => true});
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force and new unencrypted settings');
|
||||
|
||||
# Confirm unencrypted
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
|
||||
. ARCHIVE_INFO_FILE)}, false, ' new archive info unencrypted');
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
|
||||
. FILE_BACKUP_INFO)}, false, ' new backup info unencrypted');
|
||||
|
||||
# Clear --force
|
||||
$self->optionTestClear(CFGOPT_FORCE);
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::infoFileCreate"))
|
||||
{
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true});
|
||||
|
||||
# Archive dir not empty. Warning returned.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
storageTest()->pathCreate($self->{strArchivePath} . "/9.3-0", {bIgnoreExists => true, bCreateParent => true});
|
||||
$self->testResult(sub {$oStanza->infoFileCreate($oArchiveInfo)}, "(0, [undef])",
|
||||
'successful with archive.info file warning',
|
||||
{strLogExpect => "WARN: found empty directory " . $self->{strArchivePath} . "/9.3-0"});
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::infoObject()"))
|
||||
{
|
||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
|
||||
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, ERROR_FILE_MISSING,
|
||||
storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) .
|
||||
" does not exist and is required to perform a backup." .
|
||||
"\nHINT: has a stanza-create been performed?");
|
||||
|
||||
# Force valid but not set.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
$oStanza = new pgBackRest::Stanza();
|
||||
|
||||
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, ERROR_FILE_MISSING,
|
||||
storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) .
|
||||
" does not exist and is required to perform a backup." .
|
||||
"\nHINT: has a stanza-create been performed?" .
|
||||
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
|
||||
|
||||
# Force.
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->optionTestSetBool(CFGOPT_FORCE, true);
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
|
||||
$self->testResult(sub {$oStanza->infoObject(STORAGE_REPO_ARCHIVE, $self->{strArchivePath})}, "[object]",
|
||||
'archive force successful');
|
||||
$self->testResult(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, "[object]",
|
||||
'backup force successful');
|
||||
|
||||
# Cause an error to be thrown by changing the permissions of the archive directory so it cannot be read
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
executeTest('sudo chmod 220 ' . $self->{strArchivePath});
|
||||
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_ARCHIVE, $self->{strArchivePath})}, ERROR_FILE_OPEN,
|
||||
"unable to open file '" . $self->{strArchivePath} . "/archive.info' for read");
|
||||
executeTest('sudo chmod 640 ' . $self->{strArchivePath});
|
||||
|
||||
# Reset force option --------
|
||||
$self->optionTestClear(CFGOPT_FORCE);
|
||||
|
||||
# Cause an error to be thrown by changing the permissions of the backup file so it cannot be read
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
|
||||
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
|
||||
$self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
|
||||
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT));
|
||||
executeTest('sudo chmod 220 ' . storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO));
|
||||
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, ERROR_FILE_OPEN,
|
||||
"unable to open file '" . storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) .
|
||||
"' for read");
|
||||
executeTest('sudo chmod 640 ' . storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO));
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::stanzaUpgrade()"))
|
||||
{
|
||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
||||
|
||||
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true});
|
||||
$oArchiveInfo->create('9.3', '6999999999999999999', true);
|
||||
|
||||
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true});
|
||||
$oBackupInfo->create('9.3', '6999999999999999999', '937', '201306121', true);
|
||||
|
||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testResult(sub {$oStanza->stanzaUpgrade()}, undef, 'successfully upgraded');
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testResult(sub {$oStanza->stanzaUpgrade()}, undef, 'upgrade not required');
|
||||
|
||||
# Attempt to change the encryption settings
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
# Clear the cached repo settings and change repo settings to encrypted
|
||||
storageRepoCacheClear();
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
|
||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
||||
|
||||
$self->testException(sub {$oStanza->stanzaUpgrade()}, ERROR_CRYPTO,
|
||||
"unable to parse '" . $self->{strArchivePath} . "/archive.info'" .
|
||||
"\nHINT: Is or was the repo encrypted?");
|
||||
|
||||
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) . "*");
|
||||
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE) . "*");
|
||||
|
||||
# Create encrypted info files with prior passphrase then attempt to change
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true,
|
||||
strCipherPassSub => cipherPassGen()});
|
||||
$oArchiveInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), true);
|
||||
|
||||
$oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true,
|
||||
strCipherPassSub => cipherPassGen()});
|
||||
$oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), '937', '201306121', true);
|
||||
|
||||
# Attempt to upgrade with a different passphrase
|
||||
storageRepoCacheClear();
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'y');
|
||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
||||
|
||||
$self->testException(sub {$oStanza->stanzaUpgrade()}, ERROR_CRYPTO,
|
||||
"unable to parse '" . $self->{strArchivePath} . "/archive.info'" .
|
||||
"\nHINT: Is or was the repo encrypted?");
|
||||
|
||||
storageRepoCacheClear();
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
|
||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
||||
|
||||
# Create encrypted archived file
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1/0000000100000001");
|
||||
my $strArchiveIdPath = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
|
||||
my $strArchivedFile = storageRepo()->pathGet($strArchiveIdPath .
|
||||
"/0000000100000001/000000010000000100000001-" . $self->walGenerateContentChecksum(PG_VERSION_93));
|
||||
storageRepo()->put(
|
||||
$strArchivedFile, $self->walGenerateContent(PG_VERSION_93), {strCipherPass => $oArchiveInfo->cipherPassSub()});
|
||||
$self->testResult(sub {storageRepo()->encrypted($strArchivedFile)}, true, 'created encrypted archive WAL');
|
||||
|
||||
# Upgrade
|
||||
$self->testResult(sub {$oStanza->stanzaUpgrade()}, undef, ' successfully upgraded');
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
|
||||
. ARCHIVE_INFO_FILE)}, true, ' upgraded archive info encrypted');
|
||||
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
|
||||
. FILE_BACKUP_INFO)}, true, ' upgraded backup info encrypted');
|
||||
|
||||
$oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath});
|
||||
$oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
|
||||
my $hHistoryArchive = $oArchiveInfo->dbHistoryList();
|
||||
my $hHistoryBackup = $oBackupInfo->dbHistoryList();
|
||||
|
||||
$self->testResult(sub {($hHistoryArchive->{1}{&INFO_DB_VERSION} eq PG_VERSION_93) &&
|
||||
($hHistoryArchive->{1}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_93)) &&
|
||||
($hHistoryArchive->{2}{&INFO_DB_VERSION} eq PG_VERSION_94) &&
|
||||
($hHistoryArchive->{2}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_94)) &&
|
||||
($hHistoryBackup->{1}{&INFO_DB_VERSION} eq PG_VERSION_93) &&
|
||||
($hHistoryBackup->{1}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_93)) &&
|
||||
($hHistoryBackup->{2}{&INFO_DB_VERSION} eq PG_VERSION_94) &&
|
||||
($hHistoryBackup->{2}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_94)) &&
|
||||
($oArchiveInfo->check(PG_VERSION_94, $self->dbSysId(PG_VERSION_94)) eq PG_VERSION_94 . "-2") &&
|
||||
($oBackupInfo->check(PG_VERSION_94, $iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94)) == 2) }, true,
|
||||
' encrypted archive and backup info files upgraded');
|
||||
|
||||
# Clear configuration
|
||||
storageRepoCacheClear();
|
||||
$self->optionTestClear(CFGOPT_REPO_CIPHER_TYPE);
|
||||
$self->optionTestClear(CFGOPT_REPO_CIPHER_PASS);
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::upgradeCheck()"))
|
||||
{
|
||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
|
||||
# Create the archive file with current data
|
||||
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true});
|
||||
$oArchiveInfo->create(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), true);
|
||||
|
||||
# Create the backup file with outdated data
|
||||
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true});
|
||||
$oBackupInfo->create(PG_VERSION_93, 6999999999999999999, '937', '201306121', true);
|
||||
|
||||
# Confirm upgrade is needed for backup
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, true,
|
||||
'backup upgrade needed');
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, false,
|
||||
'archive upgrade not needed');
|
||||
|
||||
# Change archive file to contain outdated data
|
||||
$oArchiveInfo->create(PG_VERSION_93, 6999999999999999999, true);
|
||||
|
||||
# Confirm upgrade is needed for both
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, true,
|
||||
'archive upgrade needed');
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, true,
|
||||
'backup upgrade needed');
|
||||
|
||||
# Change the backup file to contain current data
|
||||
$oBackupInfo->create(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
|
||||
|
||||
# Confirm upgrade is needed for archive
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, false,
|
||||
'backup upgrade not needed');
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, true,
|
||||
'archive upgrade needed');
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
# Perform an upgrade and then confirm upgrade is not necessary
|
||||
$oStanza->process();
|
||||
|
||||
$oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath});
|
||||
$oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
|
||||
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, false,
|
||||
'archive upgrade not necessary');
|
||||
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, false,
|
||||
'backup upgrade not necessary');
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
# Change the DB data
|
||||
$oStanza->{oDb}{strDbVersion} = '9.3';
|
||||
$oStanza->{oDb}{ullDbSysId} = 6999999999999999999;
|
||||
|
||||
# Pass an expected error that is different than the actual error and confirm an error is thrown
|
||||
$self->testException(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ASSERT)},
|
||||
ERROR_ARCHIVE_MISMATCH,
|
||||
"WAL segment version 9.3 does not match archive version 9.4\n" .
|
||||
'WAL segment system-id 6999999999999999999 does not match archive system-id ' . $self->dbSysId(PG_VERSION_94) . "\n" .
|
||||
"HINT: are you archiving to the correct stanza?");
|
||||
$self->testException(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_ASSERT)}, ERROR_BACKUP_MISMATCH,
|
||||
"database version = 9.3, system-id 6999999999999999999 does not match backup version = 9.4, " .
|
||||
'system-id = ' . $self->dbSysId(PG_VERSION_94) . "\nHINT: is this the correct stanza?");
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::errorForce()"))
|
||||
{
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
|
||||
my $strMessage = "archive information missing" .
|
||||
"\nHINT: use stanza-create --force to force the stanza data to be recreated.";
|
||||
|
||||
$self->testException(sub {$oStanza->errorForce($strMessage, ERROR_FILE_MISSING, undef, true,
|
||||
$self->{strArchivePath}, $self->{strBackupPath})}, ERROR_FILE_MISSING, $strMessage);
|
||||
|
||||
my $strFile = $self->{strArchivePath} . qw{/} . 'file.txt';
|
||||
my $strFileContent = 'TESTDATA';
|
||||
|
||||
executeTest("echo -n '${strFileContent}' | tee ${strFile}");
|
||||
|
||||
$self->testException(sub {$oStanza->errorForce($strMessage, ERROR_FILE_MISSING, $strFile, true,
|
||||
$self->{strArchivePath}, $self->{strBackupPath})}, ERROR_FILE_MISSING, $strMessage);
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("Stanza::stanzaDelete()"))
|
||||
{
|
||||
# Create the stanza
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
my $oStanza = new pgBackRest::Stanza();
|
||||
$oStanza->stanzaCreate();
|
||||
|
||||
# Attempt to delete without running stop
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->optionTestClear(CFGOPT_ONLINE);
|
||||
$self->configTestLoad(CFGCMD_STANZA_DELETE);
|
||||
|
||||
$self->testException(sub {$oStanza->stanzaDelete()}, ERROR_FILE_MISSING,
|
||||
"stop file does not exist for stanza '" . $self->stanza() . "'" .
|
||||
"\nHINT: has the pgbackrest stop command been run on this server?");
|
||||
|
||||
# Create a stop file and attempt to delete with postgres running
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
lockStop();
|
||||
|
||||
# Simulate postgres still running
|
||||
executeTest('touch ' . $self->{strDbPath} . qw(/) . DB_FILE_POSTMASTERPID);
|
||||
|
||||
$self->testException(sub {$oStanza->stanzaDelete()}, ERROR_POSTMASTER_RUNNING,
|
||||
DB_FILE_POSTMASTERPID . " exists - looks like the postmaster is running. " .
|
||||
"To delete stanza '" . $self->stanza() . "', shutdown the postmaster for stanza '" . $self->stanza() .
|
||||
"' and try again, or use --force.");
|
||||
|
||||
# Force deletion
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->optionTestSetBool(CFGOPT_FORCE, true);
|
||||
$self->configTestLoad(CFGCMD_STANZA_DELETE);
|
||||
|
||||
$self->testResult(sub {$oStanza->stanzaDelete()}, undef, 'successfully delete stanza with force');
|
||||
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
|
||||
storageRepo()->pathExists($self->{strBackupPath})},
|
||||
false, ' neither archive nor backup repo paths for the stanza exist');
|
||||
|
||||
# Remove postmaster.pid and clear force
|
||||
storageTest()->remove($self->{strDbPath} . qw(/) . DB_FILE_POSTMASTERPID);
|
||||
$self->optionTestClear(CFGOPT_FORCE);
|
||||
|
||||
# Rerun stanza-delete without force and with missing stanza directories
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testResult(sub {$oStanza->stanzaDelete()}, undef, 'successful - stanza already deleted');
|
||||
|
||||
# Recursive dir delete with archive directory and stanza directory but missing info files
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1", {bCreateParent => true});
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001");
|
||||
executeTest('touch ' . $self->{strArchivePath} . "/" . PG_VERSION_94 . "-1/0000000100000001/" . BOGUS);
|
||||
|
||||
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
my $strFullLabel = backupLabelFormat(CFGOPTVAL_BACKUP_TYPE_FULL, undef, 1482000000);
|
||||
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/${strFullLabel}", {bCreateParent => true});
|
||||
executeTest('touch ' . $self->{strBackupPath} . "/${strFullLabel}/" . BOGUS);
|
||||
|
||||
# Create an inaccessible file
|
||||
executeTest("sudo chgrp 777 " . $self->{strBackupPath} . "/${strFullLabel}/" . BOGUS);
|
||||
executeTest("sudo chown 777 " . $self->{strBackupPath} . "/${strFullLabel}/" . BOGUS);
|
||||
|
||||
lockStop();
|
||||
$self->testResult(sub {$oStanza->stanzaDelete()}, undef,
|
||||
'successful - recursive delete with missing info files and inaccessible file');
|
||||
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
|
||||
storageRepo()->pathExists($self->{strBackupPath})},
|
||||
false, ' neither archive nor backup repo paths for the stanza exist');
|
||||
|
||||
# Make the archive directory inaccessible
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
|
||||
executeTest("sudo chgrp 7777 " . $self->{strArchivePath});
|
||||
executeTest("sudo chown 7777 " . $self->{strArchivePath});
|
||||
|
||||
lockStop();
|
||||
$self->testException(sub {$oStanza->stanzaDelete()}, ERROR_FILE_REMOVE,
|
||||
"unable to remove '" . $self->{strArchivePath} . "/" . ARCHIVE_INFO_FILE . "'");
|
||||
|
||||
# Remove the repo
|
||||
executeTest("sudo rm -rf " . $self->{strArchivePath});
|
||||
|
||||
# Clear the cached repo settings and change repo settings to encrypted
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
storageRepoCacheClear();
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
|
||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
||||
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created encrypted stanza');
|
||||
|
||||
# Create encrypted archived file
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
|
||||
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1/0000000100000001");
|
||||
my $strArchiveIdPath = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
|
||||
my $strArchivedFile = storageRepo()->pathGet($strArchiveIdPath .
|
||||
"/0000000100000001/000000010000000100000001-" . $self->walGenerateContentChecksum(PG_VERSION_93));
|
||||
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath});
|
||||
storageRepo()->put(
|
||||
$strArchivedFile, $self->walGenerateContent(PG_VERSION_93), {strCipherPass => $oArchiveInfo->cipherPassSub()});
|
||||
$self->testResult(sub {storageRepo()->encrypted($strArchivedFile)}, true, ' created encrypted archive WAL');
|
||||
|
||||
my $strBackupPath = storageRepo->pathGet(STORAGE_REPO_BACKUP . "/${strFullLabel}");
|
||||
my $strBackupManifestFile = "$strBackupPath/" . FILE_MANIFEST;
|
||||
my $iDbCatalogVersion = 201409291;
|
||||
|
||||
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/${strFullLabel}", {bCreateParent => true});
|
||||
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
|
||||
|
||||
$self->testResult(sub {(new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94,
|
||||
iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94),
|
||||
strCipherPass => $oBackupInfo->cipherPassSub(), strCipherPassSub => 'x'}))->save()},
|
||||
"[undef]", ' manifest saved');
|
||||
|
||||
lockStop();
|
||||
$self->testResult(sub {$oStanza->stanzaDelete()}, undef,
|
||||
' successful - recursive delete on encrypted repo');
|
||||
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
|
||||
storageRepo()->pathExists($self->{strBackupPath})},
|
||||
false, ' neither archive nor backup repo paths for the stanza exist');
|
||||
|
||||
# For test coverage: create new stanza with delete command, call process and remove only backup path
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
lockStop();
|
||||
$self->configTestLoad(CFGCMD_STANZA_DELETE);
|
||||
$oStanza = new pgBackRest::Stanza();
|
||||
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
|
||||
$self->testResult(sub {$oStanza->process()}, 0,
|
||||
'successfully remove backup path');
|
||||
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
|
||||
storageRepo()->pathExists($self->{strBackupPath})},
|
||||
false, ' neither archive nor backup repo paths for the stanza exist');
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
1109
test/src/module/command/stanzaTest.c
Normal file
1109
test/src/module/command/stanzaTest.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user