From 59fd92fdd5c39f0c48897513a2d01205efa278e4 Mon Sep 17 00:00:00 2001 From: David Steele Date: Sun, 3 Dec 2017 17:08:49 -0500 Subject: [PATCH] Move restore test infrastructure to HostBackup.pm. Required to test restores on the backup server, a fairly common scenario. Improve the restore function to accept optional parameters rather than a long list of parameters. In passing, clean up extraneous use of strType and strComment variables. --- doc/xml/release.xml | 4 + .../pgBackRestTest/Env/Host/HostBackupTest.pm | 575 ++++++++++++++++++ .../Env/Host/HostDbCommonTest.pm | 551 ----------------- .../pgBackRestTest/Module/Mock/MockAllTest.pm | 126 ++-- .../pgBackRestTest/Module/Real/RealAllTest.pm | 231 ++----- 5 files changed, 690 insertions(+), 797 deletions(-) diff --git a/doc/xml/release.xml b/doc/xml/release.xml index afa67dc34..0713a51a7 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -86,6 +86,10 @@

Add unit tests for the Manifest module.

+ + +

Move restore test infrastructure to HostBackup.pm. Required to test restores on the backup server, a fairly common scenario. Improve the restore function to accept optional parameters rather than a long list of parameters. In passing, clean up extraneous use of strType and strComment variables.

+
diff --git a/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm b/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm index e7e8fbfc6..78524ff42 100644 --- a/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm +++ b/test/lib/pgBackRestTest/Env/Host/HostBackupTest.pm @@ -13,6 +13,7 @@ use Carp qw(confess); use Exporter qw(import); our @EXPORT = qw(); +use Fcntl ':mode'; use File::Basename qw(dirname); use Storable qw(dclone); @@ -23,6 +24,7 @@ use pgBackRest::Common::Exception; use pgBackRest::Common::Ini; use pgBackRest::Common::Log; use pgBackRest::Config::Config; +use pgBackRest::DbVersion; use pgBackRest::Manifest; use pgBackRest::Protocol::Storage::Helper; use pgBackRest::Storage::Posix::Driver; @@ -1407,6 +1409,579 @@ sub infoRestore return logDebugReturn($strOperation); } +#################################################################################################################################### +# configRecovery +#################################################################################################################################### +sub configRecovery +{ + my $self = shift; + my $oHostBackup = shift; + my $oRecoveryHashRef = shift; + + # Get stanza + my $strStanza = $self->stanza(); + + # Load db config file + my $oConfig = iniParse(${storageTest->get($self->backrestConfig())}, {bRelaxed => true}); + + # Rewrite recovery options + my @stryRecoveryOption; + + foreach my $strOption (sort(keys(%$oRecoveryHashRef))) + { + push (@stryRecoveryOption, "${strOption}=${$oRecoveryHashRef}{$strOption}"); + } + + if (@stryRecoveryOption) + { + $oConfig->{$strStanza}{cfgOptionName(CFGOPT_RECOVERY_OPTION)} = \@stryRecoveryOption; + } + + # Save db config file + storageTest()->put($self->backrestConfig(), iniRender($oConfig, true)); +} + +#################################################################################################################################### +# configRemap +#################################################################################################################################### +sub configRemap +{ + my $self = shift; + my $oRemapHashRef = shift; + my $oManifestRef = shift; + + # Get stanza name + my $strStanza = $self->stanza(); + + # Load db config file + my $oConfig = iniParse(${storageTest()->get($self->backrestConfig())}, {bRelaxed => true}); + + # Load backup config file + my $oRemoteConfig; + my $oHostBackup = + !$self->standby() && !$self->nameTest($self->backupDestination()) ? + hostGroupGet()->hostGet($self->backupDestination()) : undef; + + if (defined($oHostBackup)) + { + $oRemoteConfig = iniParse(${storageTest()->get($oHostBackup->backrestConfig())}, {bRelaxed => true}); + } + + # Rewrite recovery section + delete($oConfig->{"${strStanza}:restore"}{cfgOptionName(CFGOPT_TABLESPACE_MAP)}); + my @stryTablespaceMap; + + foreach my $strRemap (sort(keys(%$oRemapHashRef))) + { + my $strRemapPath = ${$oRemapHashRef}{$strRemap}; + + if ($strRemap eq MANIFEST_TARGET_PGDATA) + { + $oConfig->{$strStanza}{$self->optionIndexName(CFGOPT_DB_PATH, 1)} = $strRemapPath; + + ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} = $strRemapPath; + + if (defined($oHostBackup)) + { + my $bForce = $oHostBackup->nameTest(HOST_BACKUP) && defined(hostGroupGet()->hostGet(HOST_DB_STANDBY, true)); + $oRemoteConfig->{$strStanza}{$self->optionIndexName(CFGOPT_DB_PATH, 1, $bForce)} = $strRemapPath; + } + } + else + { + my $strTablespaceOid = (split('\/', $strRemap))[1]; + push (@stryTablespaceMap, "${strTablespaceOid}=${strRemapPath}"); + + ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strRemap}{&MANIFEST_SUBKEY_PATH} = $strRemapPath; + ${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{MANIFEST_TARGET_PGDATA . "/${strRemap}"}{destination} = $strRemapPath; + } + } + + if (@stryTablespaceMap) + { + $oConfig->{"${strStanza}:restore"}{cfgOptionName(CFGOPT_TABLESPACE_MAP)} = \@stryTablespaceMap; + } + + # Save db config file + storageTest()->put($self->backrestConfig(), iniRender($oConfig, true)); + + # Save backup config file (but not if this is the standby which is not the source of backups) + if (defined($oHostBackup)) + { + # Modify the file permissions so it can be read/saved by all test users + executeTest( + 'sudo chmod 660 ' . $oHostBackup->backrestConfig() . ' && sudo chmod 770 ' . dirname($oHostBackup->backrestConfig())); + + storageTest()->put($oHostBackup->backrestConfig(), iniRender($oRemoteConfig, true)); + + # Fix permissions + executeTest( + 'sudo chmod 660 ' . $oHostBackup->backrestConfig() . ' && sudo chmod 770 ' . dirname($oHostBackup->backrestConfig()) . + ' && sudo chown ' . $oHostBackup->userGet() . ' ' . $oHostBackup->backrestConfig()); + } +} + +#################################################################################################################################### +# restore +#################################################################################################################################### +sub restore +{ + my $self = shift; + + # Assign function parameters, defaults, and log debug info + my + ( + $strOperation, + $strComment, + $strBackup, + $rhExpectedManifest, + $rhRemapHash, + $bDelta, + $bForce, + $strType, + $strTarget, + $bTargetExclusive, + $strTargetAction, + $strTargetTimeline, + $rhRecoveryHash, + $iExpectedExitStatus, + $strOptionalParam, + $bTablespace, + $strUser, + ) = + logDebugParam + ( + __PACKAGE__ . '->restore', \@_, + {name => 'strComment', required => false}, + {name => 'strBackup'}, + {name => 'rhExpectedManifest', optional => true}, + {name => 'rhRemapHash', optional => true}, + {name => 'bDelta', optional => true, default => false}, + {name => 'bForce', optional => true, default => false}, + {name => 'strType', optional => true}, + {name => 'strTarget', optional => true}, + {name => 'bTargetExclusive', optional => true, default => false}, + {name => 'strTargetAction', optional => true}, + {name => 'strTargetTimeline', optional => true}, + {name => 'rhRecoveryHash', optional => true}, + {name => 'iExpectedExitStatus', optional => true}, + {name => 'strOptionalParam', optional => true}, + {name => 'bTablespace', optional => true}, + {name => 'strUser', optional => true}, + ); + + # Build link map options + my $strLinkMap; + + foreach my $strTarget (sort(keys(%{$self->{hLinkRemap}}))) + { + $strLinkMap .= " --link-map=\"${strTarget}=${$self->{hLinkRemap}}{$strTarget}\""; + } + + $strComment = 'restore' . + ($bDelta ? ' delta' : '') . + ($bForce ? ', force' : '') . + ($strBackup ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET) ? ", backup '${strBackup}'" : '') . + # This does not output 'default' for synthetic tests to make expect logs match up (may change later) + ($strType ? ", type '${strType}'" : (defined($rhExpectedManifest) ? '' : ", type 'default'")) . + ($strTarget ? ", target '${strTarget}'" : '') . + ($strTargetTimeline ? ", timeline '${strTargetTimeline}'" : '') . + ($bTargetExclusive ? ', exclusive' : '') . + (defined($strTargetAction) && $strTargetAction ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_TARGET_ACTION) + ? ', ' . cfgOptionName(CFGOPT_TARGET_ACTION) . "=${strTargetAction}" : '') . + (defined($rhRemapHash) ? ', remap' : '') . + (defined($iExpectedExitStatus) ? ", expect exit ${iExpectedExitStatus}" : '') . + (defined($strComment) ? " - ${strComment}" : '') . + ' (' . $self->nameGet() . ' host)'; + &log(INFO, " ${strComment}"); + + # Get the backup host + my $oHostGroup = hostGroupGet(); + my $oHostBackup = defined($oHostGroup->hostGet(HOST_BACKUP, true)) ? $oHostGroup->hostGet(HOST_BACKUP) : $self; + + # Load the expected manifest if it was not defined + my $oExpectedManifest = undef; + + if (!defined($rhExpectedManifest)) + { + # Load the manifest + my $oExpectedManifest = new pgBackRest::Manifest( + storageRepo()->pathGet( + STORAGE_REPO_BACKUP . qw{/} . ($strBackup eq 'latest' ? $oHostBackup->backupLast() : $strBackup) . qw{/} . + FILE_MANIFEST), + {strCipherPass => $oHostBackup->cipherPassManifest()}); + + $rhExpectedManifest = $oExpectedManifest->{oContent}; + + # Remap links in the expected manifest + foreach my $strTarget (sort(keys(%{$self->{hLinkRemap}}))) + { + my $strDestination = ${$self->{hLinkRemap}}{$strTarget}; + my $strTarget = 'pg_data/' . $strTarget; + my $strTargetPath = $strDestination; + + # If this link is to a file then the specified path must be split into file and path parts + if ($oExpectedManifest->isTargetFile($strTarget)) + { + $strTargetPath = dirname($strTargetPath); + + # Error when the path is not deep enough to be valid + if (!defined($strTargetPath)) + { + confess &log(ERROR, "${strDestination} is not long enough to be target for ${strTarget}"); + } + + # Set the file part + $oExpectedManifest->set( + MANIFEST_SECTION_BACKUP_TARGET, $strTarget, MANIFEST_SUBKEY_FILE, + substr($strDestination, length($strTargetPath) + 1)); + + # Set the link target + $oExpectedManifest->set( + MANIFEST_SECTION_TARGET_LINK, $strTarget, MANIFEST_SUBKEY_DESTINATION, $strDestination); + } + else + { + # Set the link target + $oExpectedManifest->set(MANIFEST_SECTION_TARGET_LINK, $strTarget, MANIFEST_SUBKEY_DESTINATION, $strTargetPath); + } + + # Set the target path + $oExpectedManifest->set(MANIFEST_SECTION_BACKUP_TARGET, $strTarget, MANIFEST_SUBKEY_PATH, $strTargetPath); + } + } + + # Get the backup host + if (defined($rhRemapHash)) + { + $self->configRemap($rhRemapHash, $rhExpectedManifest); + } + + if (defined($rhRecoveryHash)) + { + $self->configRecovery($oHostBackup, $rhRecoveryHash); + } + + # Create the restore command + $self->executeSimple( + $self->backrestExe() . + ' --config=' . $self->backrestConfig() . + ($bDelta ? ' --delta' : '') . + ($bForce ? ' --force' : '') . + ($strBackup ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET) ? " --set=${strBackup}" : '') . + (defined($strOptionalParam) ? " ${strOptionalParam} " : '') . + (defined($strType) && $strType ne CFGOPTVAL_RESTORE_TYPE_DEFAULT ? " --type=${strType}" : '') . + (defined($strTarget) ? " --target=\"${strTarget}\"" : '') . + (defined($strTargetTimeline) ? " --target-timeline=\"${strTargetTimeline}\"" : '') . + ($bTargetExclusive ? ' --target-exclusive' : '') . + (defined($strLinkMap) ? $strLinkMap : '') . + ($self->synthetic() ? '' : ' --link-all') . + (defined($strTargetAction) && $strTargetAction ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_TARGET_ACTION) + ? ' --' . cfgOptionName(CFGOPT_TARGET_ACTION) . "=${strTargetAction}" : '') . + ' --stanza=' . $self->stanza() . ' restore', + {strComment => $strComment, iExpectedExitStatus => $iExpectedExitStatus, oLogTest => $self->{oLogTest}, + bLogOutput => $self->synthetic()}, + $strUser); + + if (!defined($iExpectedExitStatus)) + { + $self->restoreCompare($strBackup, dclone($rhExpectedManifest), $bTablespace); + + if (defined($self->{oLogTest})) + { + $self->{oLogTest}->supplementalAdd( + $rhExpectedManifest->{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} . + "/recovery.conf"); + } + } +} + +#################################################################################################################################### +# restoreCompare +#################################################################################################################################### +sub restoreCompare +{ + my $self = shift; + my $strBackup = shift; + my $oExpectedManifestRef = shift; + my $bTablespace = shift; + + my $strTestPath = $self->testPath(); + + # Get the backup host + my $oHostGroup = hostGroupGet(); + my $oHostBackup = defined($oHostGroup->hostGet(HOST_BACKUP, true)) ? $oHostGroup->hostGet(HOST_BACKUP) : $self; + + # Load the last manifest if it exists + my $oLastManifest = undef; + + if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR})) + { + my $oExpectedManifest = + new pgBackRest::Manifest( + storageRepo()->pathGet( + STORAGE_REPO_BACKUP . qw{/} . ($strBackup eq 'latest' ? $oHostBackup->backupLast() : $strBackup) . + '/'. FILE_MANIFEST), + {strCipherPass => $oHostBackup->cipherPassManifest()}); + + $oLastManifest = + new pgBackRest::Manifest( + storageRepo()->pathGet( + STORAGE_REPO_BACKUP . qw{/} . + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR} . qw{/} . FILE_MANIFEST), + {strCipherPass => $oHostBackup->cipherPassManifest()}); + } + + # Generate the tablespace map for real backups + my $oTablespaceMap = undef; + + if (!$self->synthetic()) + { + # Tablespace_map file is not restored in versions >= 9.5 because it interferes with internal remapping features. + if (${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_95) + { + delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{MANIFEST_TARGET_PGDATA . '/tablespace_map'}); + } + + foreach my $strTarget (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}})) + { + if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID})) + { + my $iTablespaceId = + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}; + + $$oTablespaceMap{$iTablespaceId} = + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME}; + } + } + } + + # Generate the actual manifest + my $strDbClusterPath = + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH}; + + if (defined($bTablespace) && !$bTablespace) + { + foreach my $strTarget (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}})) + { + if ($$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TYPE} eq + MANIFEST_VALUE_LINK && + defined($$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID})) + { + my $strRemapPath; + my $iTablespaceName = + $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME}; + + $strRemapPath = "../../tablespace/${iTablespaceName}"; + + $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH} = $strRemapPath; + $$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK}{MANIFEST_TARGET_PGDATA . "/${strTarget}"} + {&MANIFEST_SUBKEY_DESTINATION} = $strRemapPath; + } + } + } + + my $oActualManifest = new pgBackRest::Manifest( + "${strTestPath}/" . FILE_MANIFEST, + {bLoad => false, strDbVersion => $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION}, + oStorage => storageTest()}); + + $oActualManifest->set( + MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, + $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION}); + $oActualManifest->numericSet( + MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, + $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG}); + + $oActualManifest->build(storageTest(), $strDbClusterPath, $oLastManifest, false, $oTablespaceMap); + + my $strSectionPath = $oActualManifest->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH); + + foreach my $strName ($oActualManifest->keys(MANIFEST_SECTION_TARGET_FILE)) + { + # If synthetic match checksum errors since they can't be verified here + if ($self->synthetic) + { + my $bChecksumPage = $oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE}; + + if (defined($bChecksumPage)) + { + $oActualManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE, $bChecksumPage); + + if (!$bChecksumPage && + defined($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR})) + { + $oActualManifest->set( + MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR, + $oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR}); + } + } + } + # Else if page checksums are enabled make sure the correct files are being checksummed + else + { + if ($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_CHECKSUM_PAGE}) + { + if (defined($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE}) != + isChecksumPage($strName)) + { + confess + "check-page actual for ${strName} is " . + ($oActualManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, + MANIFEST_SUBKEY_CHECKSUM_PAGE) ? 'set' : '[undef]') . + ' but isChecksumPage() says it should be ' . + (isChecksumPage($strName) ? 'set' : '[undef]') . '.'; + } + + # Because the page checksum flag is copied to incr and diff from the previous backup but further processing is not + # done, they can't be expected to match so delete them. + delete($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE}); + $oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE); + } + } + + if (!$self->synthetic()) + { + $oActualManifest->set( + MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{size}); + } + + # Remove repo-size from the manifest. ??? This could be improved to get actual sizes from the backup. + $oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE); + delete($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_REPO_SIZE}); + + if ($oActualManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) != 0) + { + my $oStat = storageTest()->info($oActualManifest->dbPathGet($strSectionPath, $strName)); + + if ($oStat->blocks > 0 || S_ISLNK($oStat->mode)) + { + my ($strHash) = storageTest()->hashSize($oActualManifest->dbPathGet($strSectionPath, $strName)); + + $oActualManifest->set( + MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM, $strHash); + } + else + { + $oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM); + delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM}); + } + } + } + + # If the link section is empty then delete it and the default section + if (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_LINK}}) == 0) + { + delete($$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK}); + delete($$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK . ':default'}); + } + + # Set actual to expected for settings that always change from backup to backup + $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ARCHIVE_CHECK}); + $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_COPY, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ARCHIVE_COPY}); + $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_BACKUP_STANDBY, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_BACKUP_STANDBY}); + $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_COMPRESS}); + $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_HARDLINK, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_HARDLINK}); + $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ONLINE}); + + $oActualManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION}); + $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CONTROL}); + $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG}); + $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_SYSTEM_ID}); + $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_ID}); + + $oActualManifest->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, + ${$oExpectedManifestRef}{&INI_SECTION_BACKREST}{&INI_KEY_VERSION}); + + # Copy passphrase if one exists + if (defined($oExpectedManifestRef->{&INI_SECTION_CIPHER}) && + defined($oExpectedManifestRef->{&INI_SECTION_CIPHER}{&INI_KEY_CIPHER_PASS})) + { + $oActualManifest->set(INI_SECTION_CIPHER, INI_KEY_CIPHER_PASS, undef, + $oExpectedManifestRef->{&INI_SECTION_CIPHER}{&INI_KEY_CIPHER_PASS}); + } + + # This option won't be set in the actual manifest + delete($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_CHECKSUM_PAGE}); + + if ($self->synthetic()) + { + $oActualManifest->remove(MANIFEST_SECTION_BACKUP); + delete($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}); + } + else + { + $oActualManifest->set( + INI_SECTION_BACKREST, INI_KEY_CHECKSUM, undef, $oExpectedManifestRef->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM}); + $oActualManifest->set( + MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef, + $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LABEL}); + $oActualManifest->set( + MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START, undef, + $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_COPY_START}); + $oActualManifest->set( + MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_START, undef, + $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_START}); + $oActualManifest->set( + MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP, undef, + $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_STOP}); + $oActualManifest->set( + MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE, undef, + $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TYPE}); + + $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LSN_START, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LSN_START}); + $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LSN_STOP, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LSN_STOP}); + + if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_START})) + { + $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_START, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_START}); + } + + if (${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_STOP}) + { + $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_STOP, undef, + ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_STOP}); + } + } + + # Check that archive status exists in the manifest for an online backup + my $strArchiveStatusPath = MANIFEST_TARGET_PGDATA . qw{/} . $oActualManifest->walPath() . qw{/} . DB_PATH_ARCHIVESTATUS; + + if ($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ONLINE} && + !defined($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_PATH}{$strArchiveStatusPath})) + { + confess &log(ERROR, "${strArchiveStatusPath} expected for online backup", ERROR_ASSERT); + } + + # Delete the list of DBs + delete($$oExpectedManifestRef{&MANIFEST_SECTION_DB}); + + $self->manifestDefault($oExpectedManifestRef); + + storageTest()->put("${strTestPath}/actual.manifest", iniRender($oActualManifest->{oContent})); + storageTest()->put("${strTestPath}/expected.manifest", iniRender($oExpectedManifestRef)); + + executeTest("diff ${strTestPath}/expected.manifest ${strTestPath}/actual.manifest"); + + storageTest()->remove("${strTestPath}/expected.manifest"); + storageTest()->remove("${strTestPath}/actual.manifest"); +} + #################################################################################################################################### # Getters #################################################################################################################################### diff --git a/test/lib/pgBackRestTest/Env/Host/HostDbCommonTest.pm b/test/lib/pgBackRestTest/Env/Host/HostDbCommonTest.pm index 8b2abca73..c70c80d0b 100644 --- a/test/lib/pgBackRestTest/Env/Host/HostDbCommonTest.pm +++ b/test/lib/pgBackRestTest/Env/Host/HostDbCommonTest.pm @@ -14,7 +14,6 @@ use Carp qw(confess); use DBI; use Exporter qw(import); our @EXPORT = qw(); -use Fcntl ':mode'; use File::Basename qw(dirname); use Storable qw(dclone); @@ -155,118 +154,6 @@ sub archivePush return logDebugReturn($strOperation); } -#################################################################################################################################### -# configRecovery -#################################################################################################################################### -sub configRecovery -{ - my $self = shift; - my $oHostBackup = shift; - my $oRecoveryHashRef = shift; - - # Get stanza - my $strStanza = $self->stanza(); - - # Load db config file - my $oConfig = iniParse(${storageTest->get($self->backrestConfig())}, {bRelaxed => true}); - - # Rewrite recovery options - my @stryRecoveryOption; - - foreach my $strOption (sort(keys(%$oRecoveryHashRef))) - { - push (@stryRecoveryOption, "${strOption}=${$oRecoveryHashRef}{$strOption}"); - } - - if (@stryRecoveryOption) - { - $oConfig->{$strStanza}{cfgOptionName(CFGOPT_RECOVERY_OPTION)} = \@stryRecoveryOption; - } - - # Save db config file - storageTest()->put($self->backrestConfig(), iniRender($oConfig, true)); -} - -#################################################################################################################################### -# configRemap -#################################################################################################################################### -sub configRemap -{ - my $self = shift; - my $oRemapHashRef = shift; - my $oManifestRef = shift; - - # Get stanza name - my $strStanza = $self->stanza(); - - # Load db config file - my $oConfig = iniParse(${storageTest()->get($self->backrestConfig())}, {bRelaxed => true}); - - # Load backup config file - my $oRemoteConfig; - my $oHostBackup = - !$self->standby() && !$self->nameTest($self->backupDestination()) ? - hostGroupGet()->hostGet($self->backupDestination()) : undef; - - if (defined($oHostBackup)) - { - $oRemoteConfig = iniParse(${storageTest()->get($oHostBackup->backrestConfig())}, {bRelaxed => true}); - } - - # Rewrite recovery section - delete($oConfig->{"${strStanza}:restore"}{cfgOptionName(CFGOPT_TABLESPACE_MAP)}); - my @stryTablespaceMap; - - foreach my $strRemap (sort(keys(%$oRemapHashRef))) - { - my $strRemapPath = ${$oRemapHashRef}{$strRemap}; - - if ($strRemap eq MANIFEST_TARGET_PGDATA) - { - $oConfig->{$strStanza}{$self->optionIndexName(CFGOPT_DB_PATH, 1)} = $strRemapPath; - - ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} = $strRemapPath; - - if (defined($oHostBackup)) - { - my $bForce = $oHostBackup->nameTest(HOST_BACKUP) && defined(hostGroupGet()->hostGet(HOST_DB_STANDBY, true)); - $oRemoteConfig->{$strStanza}{$self->optionIndexName(CFGOPT_DB_PATH, 1, $bForce)} = $strRemapPath; - } - } - else - { - my $strTablespaceOid = (split('\/', $strRemap))[1]; - push (@stryTablespaceMap, "${strTablespaceOid}=${strRemapPath}"); - - ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strRemap}{&MANIFEST_SUBKEY_PATH} = $strRemapPath; - ${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{MANIFEST_TARGET_PGDATA . "/${strRemap}"}{destination} = $strRemapPath; - } - } - - if (@stryTablespaceMap) - { - $oConfig->{"${strStanza}:restore"}{cfgOptionName(CFGOPT_TABLESPACE_MAP)} = \@stryTablespaceMap; - } - - # Save db config file - storageTest()->put($self->backrestConfig(), iniRender($oConfig, true)); - - # Save backup config file (but not if this is the standby which is not the source of backups) - if (defined($oHostBackup)) - { - # Modify the file permissions so it can be read/saved by all test users - executeTest( - 'sudo chmod 660 ' . $oHostBackup->backrestConfig() . ' && sudo chmod 770 ' . dirname($oHostBackup->backrestConfig())); - - storageTest()->put($oHostBackup->backrestConfig(), iniRender($oRemoteConfig, true)); - - # Fix permissions - executeTest( - 'sudo chmod 660 ' . $oHostBackup->backrestConfig() . ' && sudo chmod 770 ' . dirname($oHostBackup->backrestConfig()) . - ' && sudo chown ' . $oHostBackup->userGet() . ' ' . $oHostBackup->backrestConfig()); - } -} - #################################################################################################################################### # linkRemap #################################################################################################################################### @@ -294,444 +181,6 @@ sub linkRemap return logDebugReturn($strOperation); } -#################################################################################################################################### -# restore -#################################################################################################################################### -sub restore -{ - my $self = shift; - my $strBackup = shift; - my $oExpectedManifestRef = shift; - my $oRemapHashRef = shift; - my $bDelta = shift; - my $bForce = shift; - my $strType = shift; - my $strTarget = shift; - my $bTargetExclusive = shift; - my $strTargetAction = shift; - my $strTargetTimeline = shift; - my $oRecoveryHashRef = shift; - my $strComment = shift; - my $iExpectedExitStatus = shift; - my $strOptionalParam = shift; - my $bTablespace = shift; - my $strUser = shift; - - # Set defaults - $bDelta = defined($bDelta) ? $bDelta : false; - $bForce = defined($bForce) ? $bForce : false; - - # Build link map options - my $strLinkMap; - - foreach my $strTarget (sort(keys(%{$self->{hLinkRemap}}))) - { - $strLinkMap .= " --link-map=\"${strTarget}=${$self->{hLinkRemap}}{$strTarget}\""; - } - - $strComment = 'restore' . - ($bDelta ? ' delta' : '') . - ($bForce ? ', force' : '') . - ($strBackup ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET) ? ", backup '${strBackup}'" : '') . - ($strType ? ", type '${strType}'" : '') . - ($strTarget ? ", target '${strTarget}'" : '') . - ($strTargetTimeline ? ", timeline '${strTargetTimeline}'" : '') . - (defined($bTargetExclusive) && $bTargetExclusive ? ', exclusive' : '') . - (defined($strTargetAction) && $strTargetAction ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_TARGET_ACTION) - ? ', ' . cfgOptionName(CFGOPT_TARGET_ACTION) . "=${strTargetAction}" : '') . - (defined($oRemapHashRef) ? ', remap' : '') . - (defined($iExpectedExitStatus) ? ", expect exit ${iExpectedExitStatus}" : '') . - (defined($strComment) ? " - ${strComment}" : '') . - ' (' . $self->nameGet() . ' host)'; - &log(INFO, " ${strComment}"); - - # Get the backup host - my $oHostGroup = hostGroupGet(); - my $oHostBackup = defined($oHostGroup->hostGet(HOST_BACKUP, true)) ? $oHostGroup->hostGet(HOST_BACKUP) : $self; - - # Load the expected manifest if it was not defined - my $oExpectedManifest = undef; - - if (!defined($oExpectedManifestRef)) - { - # Load the manifest - my $oExpectedManifest = new pgBackRest::Manifest( - storageRepo()->pathGet( - STORAGE_REPO_BACKUP . qw{/} . ($strBackup eq 'latest' ? $oHostBackup->backupLast() : $strBackup) . qw{/} . - FILE_MANIFEST), - {strCipherPass => $oHostBackup->cipherPassManifest()}); - - $oExpectedManifestRef = $oExpectedManifest->{oContent}; - - # Remap links in the expected manifest - foreach my $strTarget (sort(keys(%{$self->{hLinkRemap}}))) - { - my $strDestination = ${$self->{hLinkRemap}}{$strTarget}; - my $strTarget = 'pg_data/' . $strTarget; - my $strTargetPath = $strDestination; - - # If this link is to a file then the specified path must be split into file and path parts - if ($oExpectedManifest->isTargetFile($strTarget)) - { - $strTargetPath = dirname($strTargetPath); - - # Error when the path is not deep enough to be valid - if (!defined($strTargetPath)) - { - confess &log(ERROR, "${strDestination} is not long enough to be target for ${strTarget}"); - } - - # Set the file part - $oExpectedManifest->set( - MANIFEST_SECTION_BACKUP_TARGET, $strTarget, MANIFEST_SUBKEY_FILE, - substr($strDestination, length($strTargetPath) + 1)); - - # Set the link target - $oExpectedManifest->set( - MANIFEST_SECTION_TARGET_LINK, $strTarget, MANIFEST_SUBKEY_DESTINATION, $strDestination); - } - else - { - # Set the link target - $oExpectedManifest->set(MANIFEST_SECTION_TARGET_LINK, $strTarget, MANIFEST_SUBKEY_DESTINATION, $strTargetPath); - } - - # Set the target path - $oExpectedManifest->set(MANIFEST_SECTION_BACKUP_TARGET, $strTarget, MANIFEST_SUBKEY_PATH, $strTargetPath); - } - } - - # Get the backup host - if (defined($oRemapHashRef)) - { - $self->configRemap($oRemapHashRef, $oExpectedManifestRef); - } - - if (defined($oRecoveryHashRef)) - { - $self->configRecovery($oHostBackup, $oRecoveryHashRef); - } - - # Create the restore command - $self->executeSimple( - $self->backrestExe() . - ' --config=' . $self->backrestConfig() . - (defined($bDelta) && $bDelta ? ' --delta' : '') . - (defined($bForce) && $bForce ? ' --force' : '') . - ($strBackup ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET) ? " --set=${strBackup}" : '') . - (defined($strOptionalParam) ? " ${strOptionalParam} " : '') . - (defined($strType) && $strType ne CFGOPTVAL_RESTORE_TYPE_DEFAULT ? " --type=${strType}" : '') . - (defined($strTarget) ? " --target=\"${strTarget}\"" : '') . - (defined($strTargetTimeline) ? " --target-timeline=\"${strTargetTimeline}\"" : '') . - (defined($bTargetExclusive) && $bTargetExclusive ? ' --target-exclusive' : '') . - (defined($strLinkMap) ? $strLinkMap : '') . - ($self->synthetic() ? '' : ' --link-all') . - (defined($strTargetAction) && $strTargetAction ne cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_TARGET_ACTION) - ? ' --' . cfgOptionName(CFGOPT_TARGET_ACTION) . "=${strTargetAction}" : '') . - ' --stanza=' . $self->stanza() . ' restore', - {strComment => $strComment, iExpectedExitStatus => $iExpectedExitStatus, oLogTest => $self->{oLogTest}, - bLogOutput => $self->synthetic()}, - $strUser); - - if (!defined($iExpectedExitStatus)) - { - $self->restoreCompare($strBackup, dclone($oExpectedManifestRef), $bTablespace); - - if (defined($self->{oLogTest})) - { - $self->{oLogTest}->supplementalAdd( - $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} . - "/recovery.conf"); - } - } -} - -#################################################################################################################################### -# restoreCompare -#################################################################################################################################### -sub restoreCompare -{ - my $self = shift; - my $strBackup = shift; - my $oExpectedManifestRef = shift; - my $bTablespace = shift; - - my $strTestPath = $self->testPath(); - - # Get the backup host - my $oHostGroup = hostGroupGet(); - my $oHostBackup = defined($oHostGroup->hostGet(HOST_BACKUP, true)) ? $oHostGroup->hostGet(HOST_BACKUP) : $self; - - # Load the last manifest if it exists - my $oLastManifest = undef; - - if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR})) - { - my $oExpectedManifest = - new pgBackRest::Manifest( - storageRepo()->pathGet( - STORAGE_REPO_BACKUP . qw{/} . ($strBackup eq 'latest' ? $oHostBackup->backupLast() : $strBackup) . - '/'. FILE_MANIFEST), - {strCipherPass => $oHostBackup->cipherPassManifest()}); - - $oLastManifest = - new pgBackRest::Manifest( - storageRepo()->pathGet( - STORAGE_REPO_BACKUP . qw{/} . - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR} . qw{/} . FILE_MANIFEST), - {strCipherPass => $oHostBackup->cipherPassManifest()}); - } - - # Generate the tablespace map for real backups - my $oTablespaceMap = undef; - - if (!$self->synthetic()) - { - # Tablespace_map file is not restored in versions >= 9.5 because it interferes with internal remapping features. - if (${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_95) - { - delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{MANIFEST_TARGET_PGDATA . '/tablespace_map'}); - } - - foreach my $strTarget (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}})) - { - if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID})) - { - my $iTablespaceId = - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}; - - $$oTablespaceMap{$iTablespaceId} = - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME}; - } - } - } - - # Generate the actual manifest - my $strDbClusterPath = - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH}; - - if (defined($bTablespace) && !$bTablespace) - { - foreach my $strTarget (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}})) - { - if ($$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TYPE} eq - MANIFEST_VALUE_LINK && - defined($$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID})) - { - my $strRemapPath; - my $iTablespaceName = - $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME}; - - $strRemapPath = "../../tablespace/${iTablespaceName}"; - - $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH} = $strRemapPath; - $$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK}{MANIFEST_TARGET_PGDATA . "/${strTarget}"} - {&MANIFEST_SUBKEY_DESTINATION} = $strRemapPath; - } - } - } - - my $oActualManifest = new pgBackRest::Manifest( - "${strTestPath}/" . FILE_MANIFEST, - {bLoad => false, strDbVersion => $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION}, - oStorage => storageTest()}); - - $oActualManifest->set( - MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, - $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION}); - $oActualManifest->numericSet( - MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - $$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG}); - - $oActualManifest->build(storageTest(), $strDbClusterPath, $oLastManifest, false, $oTablespaceMap); - - my $strSectionPath = $oActualManifest->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH); - - foreach my $strName ($oActualManifest->keys(MANIFEST_SECTION_TARGET_FILE)) - { - # If synthetic match checksum errors since they can't be verified here - if ($self->synthetic) - { - my $bChecksumPage = $oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE}; - - if (defined($bChecksumPage)) - { - $oActualManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE, $bChecksumPage); - - if (!$bChecksumPage && - defined($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR})) - { - $oActualManifest->set( - MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR, - $oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR}); - } - } - } - # Else if page checksums are enabled make sure the correct files are being checksummed - else - { - if ($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_CHECKSUM_PAGE}) - { - if (defined($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE}) != - isChecksumPage($strName)) - { - confess - "check-page actual for ${strName} is " . - ($oActualManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, - MANIFEST_SUBKEY_CHECKSUM_PAGE) ? 'set' : '[undef]') . - ' but isChecksumPage() says it should be ' . - (isChecksumPage($strName) ? 'set' : '[undef]') . '.'; - } - - # Because the page checksum flag is copied to incr and diff from the previous backup but further processing is not - # done, they can't be expected to match so delete them. - delete($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM_PAGE}); - $oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE); - } - } - - if (!$self->synthetic()) - { - $oActualManifest->set( - MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{size}); - } - - # Remove repo-size from the manifest. ??? This could be improved to get actual sizes from the backup. - $oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE); - delete($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_REPO_SIZE}); - - if ($oActualManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) != 0) - { - my $oStat = storageTest()->info($oActualManifest->dbPathGet($strSectionPath, $strName)); - - if ($oStat->blocks > 0 || S_ISLNK($oStat->mode)) - { - my ($strHash) = storageTest()->hashSize($oActualManifest->dbPathGet($strSectionPath, $strName)); - - $oActualManifest->set( - MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM, $strHash); - } - else - { - $oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM); - delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM}); - } - } - } - - # If the link section is empty then delete it and the default section - if (keys(%{${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_LINK}}) == 0) - { - delete($$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK}); - delete($$oExpectedManifestRef{&MANIFEST_SECTION_TARGET_LINK . ':default'}); - } - - # Set actual to expected for settings that always change from backup to backup - $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ARCHIVE_CHECK}); - $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_COPY, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ARCHIVE_COPY}); - $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_BACKUP_STANDBY, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_BACKUP_STANDBY}); - $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_COMPRESS}); - $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_HARDLINK, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_HARDLINK}); - $oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ONLINE}); - - $oActualManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION}); - $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CONTROL}); - $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG}); - $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_SYSTEM_ID}); - $oActualManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_ID}); - - $oActualManifest->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, - ${$oExpectedManifestRef}{&INI_SECTION_BACKREST}{&INI_KEY_VERSION}); - - # Copy passphrase if one exists - if (defined($oExpectedManifestRef->{&INI_SECTION_CIPHER}) && - defined($oExpectedManifestRef->{&INI_SECTION_CIPHER}{&INI_KEY_CIPHER_PASS})) - { - $oActualManifest->set(INI_SECTION_CIPHER, INI_KEY_CIPHER_PASS, undef, - $oExpectedManifestRef->{&INI_SECTION_CIPHER}{&INI_KEY_CIPHER_PASS}); - } - - # This option won't be set in the actual manifest - delete($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_CHECKSUM_PAGE}); - - if ($self->synthetic()) - { - $oActualManifest->remove(MANIFEST_SECTION_BACKUP); - delete($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}); - } - else - { - $oActualManifest->set( - INI_SECTION_BACKREST, INI_KEY_CHECKSUM, undef, $oExpectedManifestRef->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM}); - $oActualManifest->set( - MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef, - $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LABEL}); - $oActualManifest->set( - MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START, undef, - $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_COPY_START}); - $oActualManifest->set( - MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_START, undef, - $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_START}); - $oActualManifest->set( - MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP, undef, - $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TIMESTAMP_STOP}); - $oActualManifest->set( - MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE, undef, - $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_TYPE}); - - $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LSN_START, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LSN_START}); - $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LSN_STOP, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_LSN_STOP}); - - if (defined(${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_START})) - { - $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_START, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_START}); - } - - if (${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_STOP}) - { - $oActualManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_STOP, undef, - ${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_ARCHIVE_STOP}); - } - } - - # Check that archive status exists in the manifest for an online backup - my $strArchiveStatusPath = MANIFEST_TARGET_PGDATA . qw{/} . $oActualManifest->walPath() . qw{/} . DB_PATH_ARCHIVESTATUS; - - if ($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ONLINE} && - !defined($oExpectedManifestRef->{&MANIFEST_SECTION_TARGET_PATH}{$strArchiveStatusPath})) - { - confess &log(ERROR, "${strArchiveStatusPath} expected for online backup", ERROR_ASSERT); - } - - # Delete the list of DBs - delete($$oExpectedManifestRef{&MANIFEST_SECTION_DB}); - - $self->manifestDefault($oExpectedManifestRef); - - storageTest()->put("${strTestPath}/actual.manifest", iniRender($oActualManifest->{oContent})); - storageTest()->put("${strTestPath}/expected.manifest", iniRender($oExpectedManifestRef)); - - executeTest("diff ${strTestPath}/expected.manifest ${strTestPath}/actual.manifest"); - - storageTest()->remove("${strTestPath}/expected.manifest"); - storageTest()->remove("${strTestPath}/actual.manifest"); -} - #################################################################################################################################### # Getters #################################################################################################################################### diff --git a/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm b/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm index 8fbef9514..fbe526602 100644 --- a/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm +++ b/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm @@ -499,9 +499,6 @@ sub run # Restore - tests various mode, extra files/paths, missing files/paths #--------------------------------------------------------------------------------------------------------------------------- - my $bDelta = true; - my $bForce = false; - # Munge permissions/modes on files that will be fixed by the restore if (!$bRemote) { @@ -532,9 +529,9 @@ sub run } $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'add and delete files', undef, ' --link-all' . ($bRemote ? ' --cmd-ssh=/usr/bin/ssh' : ''), - undef, !$bRemote ? 'root' : undef); + 'add and delete files', $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, strUser => !$bRemote ? 'root' : undef, + strOptionalParam => ' --link-all' . ($bRemote ? ' --cmd-ssh=/usr/bin/ssh' : '')}); # Run again to fix permissions if (!$bRemote) @@ -560,8 +557,9 @@ sub run {&MANIFEST_SUBKEY_GROUP}); $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'fix permissions', undef, ' --link-all --log-level-console=detail', undef, 'root'); + 'fix permissions', $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, strUser => 'root', + strOptionalParam => ' --link-all --log-level-console=detail'}); # Fix and remove files that are now owned by root executeTest('sudo chown -R ' . TEST_USER . ':' . TEST_GROUP . ' ' . $oHostBackup->logPath()); @@ -573,69 +571,70 @@ sub run $oHostDbMaster->dbLinkCreate(\%oManifest, MANIFEST_TARGET_PGDATA, 'pg_stat', '../wrong'); $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'fix broken symlink', undef, " --link-all ${strLogReduced}" . ($bRemote ? ' --compress-level-network=0' : '')); + 'fix broken symlink', $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, + strOptionalParam => " --link-all ${strLogReduced}" . ($bRemote ? ' --compress-level-network=0' : '')}); # Additional restore tests that don't need to be performed for every permutation if (!$bRemote) { # This time manually restore all links $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'restore all links by mapping', undef, $strLogReduced . - ' --link-map=pg_stat=../pg_stat --link-map=postgresql.conf=../pg_config/postgresql.conf'); + 'restore all links by mapping', $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, + strOptionalParam => + $strLogReduced . ' --link-map=pg_stat=../pg_stat --link-map=postgresql.conf=../pg_config/postgresql.conf'}); # Error when links overlap $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'restore all links by mapping', ERROR_LINK_DESTINATION, '--log-level-console=warn' . - ' --link-map=pg_stat=../pg_stat --link-map=postgresql.conf=../pg_stat/postgresql.conf'); + 'restore all links by mapping', $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, iExpectedExitStatus => ERROR_LINK_DESTINATION, + strOptionalParam => + '--log-level-console=warn --link-map=pg_stat=../pg_stat ' . + '--link-map=postgresql.conf=../pg_stat/postgresql.conf'}); # Error when links still exist on non-delta restore - $bDelta = false; - executeTest('rm -rf ' . $oHostDbMaster->dbBasePath() . "/*"); $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'error on existing linked path', ERROR_PATH_NOT_EMPTY, '--log-level-console=warn --link-all'); + 'error on existing linked path', $strFullBackup, + {rhExpectedManifest => \%oManifest, iExpectedExitStatus => ERROR_PATH_NOT_EMPTY, + strOptionalParam => '--log-level-console=warn --link-all'}); executeTest('rm -rf ' . $oHostDbMaster->dbPath() . "/pg_stat/*"); $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'error on existing linked file', ERROR_PATH_NOT_EMPTY, '--log-level-console=warn --link-all'); + 'error on existing linked file', $strFullBackup, + {rhExpectedManifest => \%oManifest, iExpectedExitStatus => ERROR_PATH_NOT_EMPTY, + strOptionalParam => '--log-level-console=warn --link-all'}); # Error when postmaster.pid is present executeTest('touch ' . $oHostDbMaster->dbBasePath() . qw(/) . DB_FILE_POSTMASTERPID); $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'error on postmaster.pid exists', ERROR_POSTMASTER_RUNNING, '--log-level-console=warn'); + 'error on postmaster.pid exists', $strFullBackup, + {rhExpectedManifest => \%oManifest, iExpectedExitStatus => ERROR_POSTMASTER_RUNNING, + strOptionalParam => '--log-level-console=warn'}); executeTest('rm ' . $oHostDbMaster->dbBasePath() . qw(/) . DB_FILE_POSTMASTERPID); # Now a combination of remapping - $bDelta = true; - $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'restore all links --link-all and mapping', undef, - "${strLogReduced} --link-map=pg_stat=../pg_stat --link-all"); + 'restore all links --link-all and mapping', $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, + strOptionalParam => "${strLogReduced} --link-map=pg_stat=../pg_stat --link-all"}); } # Restore - test errors when $PGDATA cannot be verified #--------------------------------------------------------------------------------------------------------------------------- - $bDelta = true; - $bForce = true; - # Remove PG_VERSION $oHostDbMaster->dbFileRemove(\%oManifest, MANIFEST_TARGET_PGDATA, DB_FILE_PGVERSION); # Attempt the restore $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'fail on missing ' . DB_FILE_PGVERSION, ERROR_PATH_NOT_EMPTY, $strLogReduced); + 'fail on missing ' . DB_FILE_PGVERSION, $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, bForce => true, iExpectedExitStatus => ERROR_PATH_NOT_EMPTY, + strOptionalParam => $strLogReduced}); # Write a backup.manifest file to make $PGDATA valid testFileCreate($oHostDbMaster->dbBasePath() . '/backup.manifest', 'BOGUS'); @@ -652,8 +651,9 @@ sub run $oHostDbMaster->manifestLinkMap(\%oManifest, MANIFEST_TARGET_PGDATA . '/postgresql.conf'); $oHostDbMaster->restore( - $strFullBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'restore succeeds with backup.manifest file', undef, $strLogReduced); + 'restore succeeds with backup.manifest file', $strFullBackup, + {rhExpectedManifest => \%oManifest, bDelta => true, bForce => true, + strOptionalParam => $strLogReduced}); # Various broken info tests #--------------------------------------------------------------------------------------------------------------------------- @@ -898,13 +898,11 @@ sub run # Restore #--------------------------------------------------------------------------------------------------------------------------- - $bDelta = false; - $bForce = false; - # Fail on used path $oHostDbMaster->restore( - $strBackup, \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'fail on used path', ERROR_PATH_NOT_EMPTY, $strLogReduced); + 'fail on used path', $strBackup, + {rhExpectedManifest => \%oManifest, iExpectedExitStatus => ERROR_PATH_NOT_EMPTY, + strOptionalParam => $strLogReduced}); # Remap the base and tablespace paths my %oRemapHash; @@ -920,16 +918,15 @@ sub run } $oHostDbMaster->restore( - $strBackup, \%oManifest, \%oRemapHash, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'remap all paths', undef, $strLogReduced); + 'remap all paths', $strBackup, + {rhExpectedManifest => \%oManifest, rhRemapHash => \%oRemapHash, strOptionalParam => $strLogReduced}); # Restore (make sure file in root tablespace path is not deleted by --delta) #--------------------------------------------------------------------------------------------------------------------------- - $bDelta = true; - $oHostDbMaster->restore( - $strBackup, \%oManifest, \%oRemapHash, $bDelta, $bForce, undef, undef, undef, undef, undef, undef, - 'ensure file in tblspc root remains after --delta', undef, $strLogReduced); + 'ensure file in tblspc root remains after --delta', $strBackup, + {rhExpectedManifest => \%oManifest, rhRemapHash => \%oRemapHash, bDelta => true, + strOptionalParam => $strLogReduced}); if (!-e $strDoNotDeleteFile) { @@ -1132,8 +1129,6 @@ sub run # Selective Restore #--------------------------------------------------------------------------------------------------------------------------- - $bDelta = true; - # Remove mapping for tablespace 1 delete($oRemapHash{&MANIFEST_TARGET_PGTBLSPC . '/1'}); @@ -1146,8 +1141,9 @@ sub run {&MANIFEST_SUBKEY_CHECKSUM}); $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), \%oManifest, \%oRemapHash, $bDelta, $bForce, undef, undef, undef, - undef, undef, undef, 'selective restore 16384', undef, "${strLogReduced} --db-include=16384"); + 'selective restore 16384', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {rhExpectedManifest => \%oManifest, rhRemapHash => \%oRemapHash, bDelta => true, + strOptionalParam => "${strLogReduced} --db-include=16384"}); # Restore checksum values for next test $oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/base/32768/33000'}{&MANIFEST_SUBKEY_CHECKSUM} = @@ -1163,24 +1159,25 @@ sub run delete($oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/base/16384/17000'}{&MANIFEST_SUBKEY_CHECKSUM}); $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), \%oManifest, \%oRemapHash, $bDelta, $bForce, undef, undef, undef, - undef, undef, undef, 'selective restore 32768', undef, "${strLogReduced} --db-include=32768"); + 'selective restore 32768', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {rhExpectedManifest => \%oManifest, rhRemapHash => \%oRemapHash, bDelta => true, + strOptionalParam => "${strLogReduced} --db-include=32768"}); $oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/base/16384/17000'}{&MANIFEST_SUBKEY_CHECKSUM} = '7579ada0808d7f98087a0a586d0df9de009cdc33'; $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), \%oManifest, \%oRemapHash, $bDelta, $bForce, undef, undef, undef, - undef, undef, undef, 'error on invalid id', ERROR_DB_MISSING, '--log-level-console=warn --db-include=7777'); + 'error on invalid id', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {rhExpectedManifest => \%oManifest, rhRemapHash => \%oRemapHash, bDelta => true, + iExpectedExitStatus => ERROR_DB_MISSING, strOptionalParam => '--log-level-console=warn --db-include=7777'}); $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), \%oManifest, \%oRemapHash, $bDelta, $bForce, undef, undef, undef, - undef, undef, undef, 'error on system id', ERROR_DB_INVALID, '--log-level-console=warn --db-include=1'); + 'error on system id', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {rhExpectedManifest => \%oManifest, rhRemapHash => \%oRemapHash, bDelta => true, + iExpectedExitStatus => ERROR_DB_INVALID, strOptionalParam => '--log-level-console=warn --db-include=1'}); # Compact Restore #--------------------------------------------------------------------------------------------------------------------------- - $bDelta = false; - executeTest('rm -rf ' . $oHostDbMaster->dbBasePath(2) . "/*"); my $strDbPath = $oHostDbMaster->dbBasePath(2) . '/base'; @@ -1190,15 +1187,16 @@ sub run delete($oRemapHash{&MANIFEST_TARGET_PGTBLSPC . '/2'}); $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), \%oManifest, \%oRemapHash, $bDelta, $bForce, undef, undef, undef, - undef, undef, undef, 'no tablespace remap - error when tablespace dir does not exist', ERROR_PATH_MISSING, - "${strLogReduced} --tablespace-map-all=../../tablespace", false); + 'no tablespace remap - error when tablespace dir does not exist', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {rhExpectedManifest => \%oManifest, rhRemapHash => \%oRemapHash, iExpectedExitStatus => ERROR_PATH_MISSING, + bTablespace => false, strOptionalParam => "${strLogReduced} --tablespace-map-all=../../tablespace"}); storageTest()->pathCreate($oHostDbMaster->dbBasePath(2) . '/tablespace', {strMode => '0700'}); $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), \%oManifest, undef, $bDelta, $bForce, undef, undef, undef, undef, - undef, undef, 'no tablespace remap', undef, "--tablespace-map-all=../../tablespace ${strLogReduced}", false); + 'no tablespace remap', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {rhExpectedManifest => \%oManifest, bTablespace => false, + strOptionalParam => "--tablespace-map-all=../../tablespace ${strLogReduced}"}); $oManifest{&MANIFEST_SECTION_BACKUP_TARGET}{'pg_tblspc/2'}{&MANIFEST_SUBKEY_PATH} = '../../tablespace/ts2'; $oManifest{&MANIFEST_SECTION_TARGET_LINK}{'pg_data/pg_tblspc/2'}{&MANIFEST_SUBKEY_DESTINATION} = '../../tablespace/ts2'; diff --git a/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm b/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm index 0ad08f121..39078799e 100644 --- a/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm +++ b/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm @@ -124,18 +124,6 @@ sub run # Static backup parameters my $fTestDelay = 1; - # Variable backup parameters - my $bDelta = true; - my $bForce = false; - my $strType = undef; - my $strTarget = undef; - my $bTargetExclusive = false; - my $strTargetAction; - my $strTargetTimeline = undef; - my $oRecoveryHashRef = undef; - my $strComment = undef; - my $iExpectedExitStatus = undef; - # Restore test string my $strDefaultMessage = 'default'; my $strFullMessage = 'full'; @@ -157,7 +145,8 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bTestExtra) { - $strType = CFGOPTVAL_BACKUP_TYPE_FULL; + # 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}); @@ -173,7 +162,7 @@ sub run $strComment = 'fail on archive_mode=off'; $oHostDbMaster->clusterRestart({bIgnoreLogError => true, bArchiveEnabled => false}); - $oHostBackup->backup($strType, $strComment, {iExpectedExitStatus => ERROR_ARCHIVE_DISABLED}); + $oHostBackup->backup(CFGOPTVAL_BACKUP_TYPE_FULL, $strComment, {iExpectedExitStatus => ERROR_ARCHIVE_DISABLED}); $oHostDbMaster->check($strComment, {iTimeout => 0.1, iExpectedExitStatus => ERROR_ARCHIVE_DISABLED}); # If running the remote tests then also need to run check locally @@ -186,7 +175,7 @@ sub run $strComment = 'fail on invalid archive_command'; $oHostDbMaster->clusterRestart({bIgnoreLogError => true, bArchive => false}); - $oHostBackup->backup($strType, $strComment, {iExpectedExitStatus => ERROR_ARCHIVE_COMMAND_INVALID}); + $oHostBackup->backup(CFGOPTVAL_BACKUP_TYPE_FULL, $strComment, {iExpectedExitStatus => ERROR_ARCHIVE_COMMAND_INVALID}); $oHostDbMaster->check($strComment, {iTimeout => 0.1, iExpectedExitStatus => ERROR_ARCHIVE_COMMAND_INVALID}); # If running the remote tests then also need to run check locally @@ -373,8 +362,6 @@ sub run # Full backup #--------------------------------------------------------------------------------------------------------------------------- - $strType = CFGOPTVAL_BACKUP_TYPE_FULL; - # Create the table where test messages will be stored $oHostDbMaster->sqlExecute("create table test (message text not null)"); $oHostDbMaster->sqlWalRotate(); @@ -388,7 +375,8 @@ sub run confess 'unable to acquire advisory lock for testing'; } - $oHostBackup->backup($strType, 'fail on backup lock exists', {iExpectedExitStatus => ERROR_LOCK_ACQUIRE}); + $oHostBackup->backup( + CFGOPTVAL_BACKUP_TYPE_FULL, 'fail on backup lock exists', {iExpectedExitStatus => ERROR_LOCK_ACQUIRE}); # Release the backup advisory lock so the next backup will succeed if (!$oHostDbMaster->sqlSelectOne('select pg_advisory_unlock(' . DB_BACKUP_ADVISORY_LOCK . ')')) @@ -398,7 +386,7 @@ sub run } my $oExecuteBackup = $oHostBackup->backupBegin( - $strType, 'update during backup', + CFGOPTVAL_BACKUP_TYPE_FULL, 'update during backup', {strTest => TEST_MANIFEST_BUILD, fTestDelay => $fTestDelay, strOptionalParam => ' --' . cfgOptionName(CFGOPT_BUFFER_SIZE) . '=16384'}); @@ -407,7 +395,7 @@ sub run # Required to set hint bits to be sent to the standby to make the heap match on both sides $oHostDbMaster->sqlSelectOneTest('select message from test', $strFullMessage); - my $strFullBackup = $oHostBackup->backupEnd($strType, $oExecuteBackup); + my $strFullBackup = $oHostBackup->backupEnd(CFGOPTVAL_BACKUP_TYPE_FULL, $oExecuteBackup); # Enabled async archiving $oHostBackup->configUpdate({&CFGDEF_SECTION_GLOBAL => {cfgOptionName(CFGOPT_ARCHIVE_ASYNC) => 'y'}}); @@ -433,19 +421,6 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bHostStandby) { - $bDelta = false; - $bForce = false; - $strType = CFGOPTVAL_RESTORE_TYPE_DEFAULT; - $strTarget = undef; - $bTargetExclusive = undef; - $strTargetAction = undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - $strComment = 'restore backup on replica'; - my %oRemapHash; $oRemapHash{&MANIFEST_TARGET_PGDATA} = $oHostDbStandby->dbBasePath(); @@ -455,11 +430,11 @@ sub run } $oHostDbStandby->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), undef, \%oRemapHash, $bDelta, $bForce, $strType, $strTarget, - $bTargetExclusive, $strTargetAction, $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus, - ' --recovery-option=standby_mode=on' . - ' --recovery-option="primary_conninfo=host=' . HOST_DB_MASTER . - ' port=' . $oHostDbMaster->pgPort() . ' user=replicator"'); + 'restore backup on replica', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {rhRemapHash => \%oRemapHash, + strOptionalParam => + ' --recovery-option=standby_mode=on --recovery-option="primary_conninfo=host=' . HOST_DB_MASTER . + ' port=' . $oHostDbMaster->pgPort() . ' user=replicator"'}); $oHostDbStandby->clusterStart({bHotStandby => true}); @@ -521,13 +496,11 @@ sub run # the logs will to be deleted to avoid causing issues further down the line. if ($bTestExtra && !$bS3) { - $strType = CFGOPTVAL_BACKUP_TYPE_INCR; - $oHostDbMaster->clusterRestart(); $oHostDbMaster->stop(); - $oHostBackup->backup($strType, 'attempt backup when stopped', {iExpectedExitStatus => ERROR_STOP}); + $oHostBackup->backup(CFGOPTVAL_BACKUP_TYPE_INCR, 'attempt backup when stopped', {iExpectedExitStatus => ERROR_STOP}); $oHostDbMaster->start(); } @@ -543,12 +516,11 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bTestLocal && $oHostDbMaster->pgVersion() >= PG_VERSION_95) { - $strType = CFGOPTVAL_BACKUP_TYPE_INCR; - # Set archive_mode=always $oHostDbMaster->clusterRestart({bArchiveAlways => true}); - $oHostBackup->backup($strType, 'fail on archive_mode=always', {iExpectedExitStatus => ERROR_FEATURE_NOT_SUPPORTED}); + $oHostBackup->backup( + CFGOPTVAL_BACKUP_TYPE_INCR, 'fail on archive_mode=always', {iExpectedExitStatus => ERROR_FEATURE_NOT_SUPPORTED}); # Reset the cluster to a normal state so the next test will work $oHostDbMaster->clusterRestart(); @@ -556,8 +528,6 @@ sub run # Incr backup #--------------------------------------------------------------------------------------------------------------------------- - $strType = CFGOPTVAL_BACKUP_TYPE_INCR; - # Create a tablespace directory storageTest()->pathCreate($oHostDbMaster->tablespacePath(1), {strMode => '0700', bCreateParent => true}); @@ -587,7 +557,8 @@ sub run $oHostDbMaster->sqlSelectOne("select pg_start_backup('test backup that will cause an error', true)"); # Verify that an error is returned if the backup is already running - $oHostBackup->backup($strType, 'fail on backup already running', {iExpectedExitStatus => ERROR_DB_QUERY}); + $oHostBackup->backup( + CFGOPTVAL_BACKUP_TYPE_INCR, 'fail on backup already running', {iExpectedExitStatus => ERROR_DB_QUERY}); # Restart the cluster ignoring any errors in the postgresql log $oHostDbMaster->clusterRestart({bIgnoreLogError => true}); @@ -597,7 +568,7 @@ sub run } $oExecuteBackup = $oHostBackup->backupBegin( - $strType, 'update during backup', + CFGOPTVAL_BACKUP_TYPE_INCR, 'update during backup', {strTest => TEST_MANIFEST_BUILD, fTestDelay => $fTestDelay, strOptionalParam => '--' . cfgOptionName(CFGOPT_STOP_AUTO) . ' --no-' . cfgOptionName(CFGOPT_ARCHIVE_CHECK) . ' --' . cfgOptionName(CFGOPT_BUFFER_SIZE) . '=32768'}); @@ -622,7 +593,7 @@ sub run } } - my $strIncrBackup = $oHostBackup->backupEnd($strType, $oExecuteBackup); + my $strIncrBackup = $oHostBackup->backupEnd(CFGOPTVAL_BACKUP_TYPE_INCR, $oExecuteBackup); # Setup the xid target #--------------------------------------------------------------------------------------------------------------------------- @@ -669,26 +640,12 @@ sub run # Restore (type = default) #--------------------------------------------------------------------------------------------------------------------------- - $bDelta = false; - $bForce = false; - $strType = CFGOPTVAL_RESTORE_TYPE_DEFAULT; - $strTarget = undef; - $bTargetExclusive = undef; - $strTargetAction = undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - if ($bTestLocal) { # Expect failure because postmaster.pid exists - $strComment = 'postmaster running'; - $iExpectedExitStatus = ERROR_POSTMASTER_RUNNING; - $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), undef, undef, $bDelta, $bForce, $strType, $strTarget, - $bTargetExclusive, $strTargetAction, $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus); + 'postmaster running', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {iExpectedExitStatus => ERROR_POSTMASTER_RUNNING}); } $oHostDbMaster->clusterStop(); @@ -696,12 +653,8 @@ sub run if ($bTestLocal) { # Expect failure because db path is not empty - $strComment = 'path not empty'; - $iExpectedExitStatus = ERROR_PATH_NOT_EMPTY; - $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), undef, undef, $bDelta, $bForce, $strType, $strTarget, - $bTargetExclusive, $strTargetAction, $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus); + 'path not empty', cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), {iExpectedExitStatus => ERROR_PATH_NOT_EMPTY}); } # Drop and recreate db path @@ -713,13 +666,9 @@ sub run storageTest()->pathCreate($oHostDbMaster->tablespacePath(1), {strMode => '0700'}); # Now the restore should work - $strComment = undef; - $iExpectedExitStatus = undef; - $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), undef, undef, $bDelta, $bForce, $strType, $strTarget, - $bTargetExclusive, $strTargetAction, $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus, - ($bTestLocal ? ' --db-include=test1' : '') . ' --buffer-size=16384'); + undef, cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {strOptionalParam => ($bTestLocal ? ' --db-include=test1' : '') . ' --buffer-size=16384'}); $oHostDbMaster->clusterStart(); $oHostDbMaster->sqlSelectOneTest('select message from test', $bTestLocal ? $strNameMessage : $strIncrMessage); @@ -789,24 +738,11 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if (($bTestLocal || $bHostStandby) && $oHostDbMaster->pgVersion() >= PG_VERSION_94) { - $bDelta = false; - $bForce = true; - $strType = CFGOPTVAL_RESTORE_TYPE_IMMEDIATE; - $strTarget = undef; - $bTargetExclusive = undef; - $strTargetAction = undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - &log(INFO, " testing recovery type = ${strType}"); + &log(INFO, ' testing recovery type = ' . CFGOPTVAL_RESTORE_TYPE_IMMEDIATE); $oHostDbMaster->clusterStop(); - $oHostDbMaster->restore( - $strFullBackup, undef, undef, $bDelta, $bForce, $strType, $strTarget, $bTargetExclusive, $strTargetAction, - $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus, undef); + $oHostDbMaster->restore(undef, $strFullBackup, {bForce => true, strType => CFGOPTVAL_RESTORE_TYPE_IMMEDIATE}); $oHostDbMaster->clusterStart(); $oHostDbMaster->sqlSelectOneTest( @@ -817,18 +753,7 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bTestLocal) { - $bDelta = false; - $bForce = true; - $strType = CFGOPTVAL_RESTORE_TYPE_XID; - $strTarget = $strXidTarget; - $bTargetExclusive = undef; - $strTargetAction = $oHostDbMaster->pgVersion() >= PG_VERSION_91 ? 'promote' : undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - &log(INFO, " testing recovery type = ${strType}"); + &log(INFO, ' testing recovery type = ' . CFGOPTVAL_RESTORE_TYPE_XID); $oHostDbMaster->clusterStop(); @@ -836,9 +761,10 @@ sub run executeTest('rm -rf ' . $oHostDbMaster->dbPath() . qw{/} . $oManifest->walPath() . '/*'); $oHostDbMaster->restore( - $strIncrBackup, undef, undef, $bDelta, $bForce, $strType, $strTarget, $bTargetExclusive, $strTargetAction, - $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus, - '--tablespace-map-all=../../tablespace', false); + undef, $strIncrBackup, + {bForce => true, strType => CFGOPTVAL_RESTORE_TYPE_XID, strTarget => $strXidTarget, + strTargetAction => $oHostDbMaster->pgVersion() >= PG_VERSION_91 ? 'promote' : undef, + strOptionalParam => '--tablespace-map-all=../../tablespace', bTablespace => false}); # Save recovery file to test so we can use it in the next test storageDb()->copy( @@ -854,18 +780,7 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bTestLocal) { - $bDelta = false; - $bForce = false; - $strType = CFGOPTVAL_RESTORE_TYPE_PRESERVE; - $strTarget = undef; - $bTargetExclusive = undef; - $strTargetAction = undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - &log(INFO, " testing recovery type = ${strType}"); + &log(INFO, ' testing recovery type = ' . CFGOPTVAL_RESTORE_TYPE_PRESERVE); $oHostDbMaster->clusterStop(); @@ -877,8 +792,7 @@ sub run storageDb()->move($self->testPath . '/recovery.conf', $oHostDbMaster->dbBasePath() . '/recovery.conf'); $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), undef, undef, $bDelta, $bForce, $strType, $strTarget, - $bTargetExclusive, $strTargetAction, $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus); + undef, cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), {strType => CFGOPTVAL_RESTORE_TYPE_PRESERVE}); $oHostDbMaster->clusterStart(); $oHostDbMaster->sqlSelectOneTest('select message from test', $strXidMessage); @@ -889,24 +803,12 @@ sub run # Restore (restore type = time, inclusive) - there is no exclusive time test because I can't find a way to find the # exact commit time of a transaction. #--------------------------------------------------------------------------------------------------------------------------- - $bDelta = true; - $bForce = false; - $strType = CFGOPTVAL_RESTORE_TYPE_TIME; - $strTarget = $strTimeTarget; - $bTargetExclusive = undef; - $strTargetAction = undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - &log(INFO, " testing recovery type = ${strType}"); + &log(INFO, ' testing recovery type = ' . CFGOPTVAL_RESTORE_TYPE_TIME); $oHostDbMaster->clusterStop(); $oHostDbMaster->restore( - $strFullBackup, undef, undef, $bDelta, $bForce, $strType, $strTarget, $bTargetExclusive, $strTargetAction, - $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus); + undef, $strFullBackup, {bDelta => true, strType => CFGOPTVAL_RESTORE_TYPE_TIME, strTarget => $strTimeTarget}); $oHostDbMaster->clusterStart(); $oHostDbMaster->sqlSelectOneTest('select message from test', $strTimeMessage); @@ -915,24 +817,13 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bTestLocal) { - $bDelta = true; - $bForce = false; - $strType = CFGOPTVAL_RESTORE_TYPE_XID; - $strTarget = $strXidTarget; - $bTargetExclusive = true; - $strTargetAction = undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - &log(INFO, " testing recovery type = ${strType}"); + &log(INFO, ' testing recovery type = ' . CFGOPTVAL_RESTORE_TYPE_XID); $oHostDbMaster->clusterStop(); $oHostDbMaster->restore( - $strIncrBackup, undef, undef, $bDelta, $bForce, $strType, $strTarget, $bTargetExclusive, $strTargetAction, - $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus); + undef, $strIncrBackup, + {bDelta => true, strType => CFGOPTVAL_RESTORE_TYPE_XID, strTarget => $strXidTarget, bTargetExclusive => true}); $oHostDbMaster->clusterStart(); $oHostDbMaster->sqlSelectOneTest('select message from test', $strIncrMessage); @@ -942,24 +833,13 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bTestLocal && $oHostDbMaster->pgVersion() >= PG_VERSION_91) { - $bDelta = true; - $bForce = true; - $strType = CFGOPTVAL_RESTORE_TYPE_NAME; - $strTarget = $strNameTarget; - $bTargetExclusive = undef; - $strTargetAction = undef; - $strTargetTimeline = undef; - $oRecoveryHashRef = undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - &log(INFO, " testing recovery type = ${strType}"); + &log(INFO, ' testing recovery type = ' . CFGOPTVAL_RESTORE_TYPE_NAME); $oHostDbMaster->clusterStop(); $oHostDbMaster->restore( - cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), undef, undef, $bDelta, $bForce, $strType, $strTarget, - $bTargetExclusive, $strTargetAction, $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus); + undef, cfgDefOptionDefault(CFGCMD_RESTORE, CFGOPT_SET), + {bDelta => true, bForce => true, strType => CFGOPTVAL_RESTORE_TYPE_NAME, strTarget => $strNameTarget}); $oHostDbMaster->clusterStart(); $oHostDbMaster->sqlSelectOneTest('select message from test', $strNameMessage); @@ -969,24 +849,14 @@ sub run #--------------------------------------------------------------------------------------------------------------------------- if ($bTestLocal && $oHostDbMaster->pgVersion() >= PG_VERSION_84) { - $bDelta = true; - $bForce = false; - $strType = CFGOPTVAL_RESTORE_TYPE_DEFAULT; - $strTarget = undef; - $bTargetExclusive = undef; - $strTargetAction = undef; - $strTargetTimeline = 4; - $oRecoveryHashRef = $oHostDbMaster->pgVersion() >= PG_VERSION_90 ? {'standby-mode' => 'on'} : undef; - $strComment = undef; - $iExpectedExitStatus = undef; - - &log(INFO, " testing recovery type = ${strType}"); + &log(INFO, ' testing recovery type = ' . CFGOPTVAL_RESTORE_TYPE_DEFAULT); $oHostDbMaster->clusterStop(); $oHostDbMaster->restore( - $strIncrBackup, undef, undef, $bDelta, $bForce, $strType, $strTarget, $bTargetExclusive, $strTargetAction, - $strTargetTimeline, $oRecoveryHashRef, $strComment, $iExpectedExitStatus); + undef, $strIncrBackup, + {bDelta => true, strType => CFGOPTVAL_RESTORE_TYPE_DEFAULT, strTargetTimeline => 4, + rhRecoveryHash => $oHostDbMaster->pgVersion() >= PG_VERSION_90 ? {'standby-mode' => 'on'} : undef}); $oHostDbMaster->clusterStart({bHotStandby => true}); $oHostDbMaster->sqlSelectOneTest('select message from test', $strTimelineMessage, {iTimeout => 120}); @@ -1005,18 +875,15 @@ sub run # Incr backup - make sure a --no-online backup fails #----------------------------------------------------------------------------------------------------------------------- - $strType = CFGOPTVAL_BACKUP_TYPE_INCR; - $oHostBackup->backup( - $strType, 'fail on --no-' . cfgOptionName(CFGOPT_ONLINE), + CFGOPTVAL_BACKUP_TYPE_INCR, 'fail on --no-' . cfgOptionName(CFGOPT_ONLINE), {iExpectedExitStatus => ERROR_POSTMASTER_RUNNING, strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)}); # Incr backup - allow --no-online backup to succeed with --force #----------------------------------------------------------------------------------------------------------------------- - $strType = CFGOPTVAL_BACKUP_TYPE_INCR; - $oHostBackup->backup( - $strType, 'succeed on --no-' . cfgOptionName(CFGOPT_ONLINE) . ' with --' . cfgOptionName(CFGOPT_FORCE), + CFGOPTVAL_BACKUP_TYPE_INCR, + 'succeed on --no-' . cfgOptionName(CFGOPT_ONLINE) . ' with --' . cfgOptionName(CFGOPT_FORCE), {strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_FORCE)}); } }