1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-01-06 08:01:21 +03:00

Add stanza-delete command to cleanup unused stanzas.

Contributed by Cynthia Shang.
This commit is contained in:
Cynthia Shang
2018-01-03 12:23:33 -05:00
committed by David Steele
parent 526acca5bd
commit 0e9ba98a50
27 changed files with 776 additions and 26 deletions

View File

@@ -13,8 +13,11 @@ 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;
@@ -22,6 +25,7 @@ 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;
@@ -48,9 +52,12 @@ sub new
# Assign function parameters, defaults, and log debug info
my $strOperation = logDebugParam(__PACKAGE__ . '->new');
# Initialize the database object
($self->{oDb}) = dbObjectGet();
$self->dbInfoGet();
# 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
@@ -82,6 +89,11 @@ sub process
{
$iResult = $self->stanzaUpgrade();
}
# Process stanza delete
elsif (cfgCommandTest(CFGCMD_STANZA_DELETE))
{
$iResult = $self->stanzaDelete();
}
# Else error if any other command is found
else
{
@@ -251,6 +263,82 @@ sub stanzaUpgrade
);
}
####################################################################################################################################
# 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({strStanza => $strStanza});
# 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);
}
# 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) && !cfgOption(CFGOPT_FORCE))
{
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->remove(STORAGE_REPO_ARCHIVE, {bRecurse => true, bIgnoreMissing => true});
$oStorageRepo->remove(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,
{name => 'iResult', value => 0, trace => true}
);
}
####################################################################################################################################
# parentPathGet
#
@@ -338,7 +426,7 @@ sub existingFileName
####################################################################################################################################
# errorForce
#
# Creates the parent path if it doesn't exist and returns the path.
# Determines based on encryption or not and errors when force is required but not set.
####################################################################################################################################
sub errorForce
{