From 279bd07623be81d9197e5612ac8a85b2d57c5335 Mon Sep 17 00:00:00 2001 From: David Steele Date: Sun, 19 Apr 2015 17:29:52 -0400 Subject: [PATCH] Each option is assigned a source to designate where it came from (param, config, default). operationWrite() created to easily pass parameters on to a new process. --- lib/BackRest/Config.pm | 87 ++++++++++++++++++++++++----- lib/BackRest/Restore.pm | 4 +- lib/BackRest/RestoreFile.pm | 3 +- test/lib/BackRestTest/ConfigTest.pm | 19 +++++++ 4 files changed, 94 insertions(+), 19 deletions(-) diff --git a/lib/BackRest/Config.pm b/lib/BackRest/Config.pm index 735b0ef53..46d96c6e8 100644 --- a/lib/BackRest/Config.pm +++ b/lib/BackRest/Config.pm @@ -19,7 +19,8 @@ use BackRest::Utility; # Export functions #################################################################################################################################### our @EXPORT = qw(configLoad optionGet optionTest optionRuleGet optionRequired optionDefault operationGet operationTest - operationSet optionRemoteType optionRemoteTypeTest optionRemote optionRemoteTest remoteDestroy); + operationSet operationWrite optionRemoteType optionRemoteTypeTest optionRemote optionRemoteTest + remoteDestroy); #################################################################################################################################### # DB/BACKUP Constants @@ -59,6 +60,17 @@ use constant push @EXPORT, qw(BACKUP_TYPE_FULL BACKUP_TYPE_DIFF BACKUP_TYPE_INCR); + +#################################################################################################################################### +# SOURCE Constants +#################################################################################################################################### +use constant +{ + SOURCE_CONFIG => 'config', + SOURCE_PARAM => 'param', + SOURCE_DEFAULT => 'default' +}; + #################################################################################################################################### # RECOVERY Type Constants #################################################################################################################################### @@ -360,7 +372,7 @@ my %oOptionRule = { &OP_RESTORE => { - &OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_TYPE, + &OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_SET, } } }, @@ -1035,13 +1047,13 @@ sub configLoad # Replace command psql options if set if (optionTest(OPTION_COMMAND_PSQL) && optionTest(OPTION_COMMAND_PSQL_OPTION)) { - $oOption{&OPTION_COMMAND_PSQL} =~ s/\%option\%/$oOption{&OPTION_COMMAND_PSQL_OPTION}/g; + $oOption{&OPTION_COMMAND_PSQL}{value} =~ s/\%option\%/$oOption{&OPTION_COMMAND_PSQL_OPTION}{value}/g; } # Set repo-remote-path to repo-path if it is not set if (optionTest(OPTION_REPO_PATH) && !optionTest(OPTION_REPO_REMOTE_PATH)) { - $oOption{&OPTION_REPO_REMOTE_PATH} = optionGet(OPTION_REPO_PATH); + $oOption{&OPTION_REPO_REMOTE_PATH}{value} = optionGet(OPTION_REPO_PATH); } # Check if the backup host is remote @@ -1163,7 +1175,7 @@ sub optionValid { # Check if the depend option has a value $strDependOption = $$oDepend{&OPTION_RULE_DEPEND_OPTION}; - $strDependValue = $oOption{$strDependOption}; + $strDependValue = $oOption{$strDependOption}{value}; # Make sure the depend option has been resolved, otherwise skip this option for now if (!defined($oOptionResolved{$strDependOption})) @@ -1207,12 +1219,12 @@ sub optionValid } # If the config option is defined try to get the option from the config file - if ($bConfigExists && defined($oOption{&OPTION_CONFIG})) + if ($bConfigExists && defined($oOption{&OPTION_CONFIG}{value})) { # Attempt to load the config file if it has not been loaded if (!defined($oConfig)) { - my $strConfigFile = $oOption{&OPTION_CONFIG}; + my $strConfigFile = $oOption{&OPTION_CONFIG}{value}; $bConfigExists = -e $strConfigFile; if ($bConfigExists) @@ -1295,6 +1307,8 @@ sub optionValid ERROR_OPTION_INVALID_VALUE); } } + + $oOption{$strOption}{source} = SOURCE_CONFIG; } } } @@ -1404,18 +1418,24 @@ sub optionValid # Check that the key has not already been set my $strKey = substr($strItem, 0, $iEqualPos); - if (defined($oOption{$strOption}{$strKey})) + if (defined($oOption{$strOption}{$strKey}{value})) { confess &log(ERROR, "'${$strItem}' already defined for '${strOption}' option", ERROR_OPTION_DUPLICATE_KEY); } - $oOption{$strOption}{$strKey} = substr($strItem, $iEqualPos + 1); + $oOption{$strOption}{value}{$strKey} = substr($strItem, $iEqualPos + 1); } } else { - $oOption{$strOption} = $strValue; + $oOption{$strOption}{value} = $strValue; + } + + # If not config sourced then it must be a param + if (!defined($oOption{$strOption}{source})) + { + $oOption{$strOption}{source} = SOURCE_PARAM; } } # Else try to set a default @@ -1423,6 +1443,9 @@ sub optionValid (!defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}) || defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}))) { + # Source is default for this option + $oOption{$strOption}{source} = SOURCE_DEFAULT; + # Check for default in operation then option my $strDefault = optionDefault($strOption, $strOperation); @@ -1430,7 +1453,7 @@ sub optionValid if (defined($strDefault)) { # Only set default if dependency is resolved - $oOption{$strOption} = $strDefault if !$bNegate; + $oOption{$strOption}{value} = $strDefault if !$bNegate; } # Else check required elsif (optionRequired($strOption, $strOperation)) @@ -1551,16 +1574,50 @@ sub optionGet my $strOption = shift; my $bRequired = shift; - if (!defined($oOption{$strOption}) && (!defined($bRequired) || $bRequired)) + if (!defined($oOption{$strOption}{value}) && (!defined($bRequired) || $bRequired)) { confess &log(ASSERT, "option ${strOption} is required"); } - return $oOption{$strOption}; + return $oOption{$strOption}{value}; } #################################################################################################################################### -# optionTest +# operationWrite +# +# Using the options that were passed to the current operations, write the command string for another operation. For example, this +# can be used to write the archive-get command for recovery.conf during a restore. +#################################################################################################################################### +sub operationWrite +{ + my $strNewOperation = shift; + + my $strCommand = "$0"; + + foreach my $strOption (sort(keys(%oOption))) + { + if ((!defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}) || + defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strNewOperation})) && + $oOption{$strOption}{source} eq SOURCE_PARAM) + { + my $strParam = "--${strOption}=$oOption{$strOption}{value}"; + + if (index($oOption{$strOption}{value}, " ") != -1) + { + $strCommand .= " \"${strParam}\""; + } + else + { + $strCommand .= " ${strParam}"; + } + } + } + + $strCommand .= " ${strNewOperation}"; +} + +#################################################################################################################################### +# commandWrite # # Test a option value. #################################################################################################################################### @@ -1574,7 +1631,7 @@ sub optionTest return optionGet($strOption) eq $strValue; } - return defined($oOption{$strOption}); + return defined($oOption{$strOption}{value}); } #################################################################################################################################### diff --git a/lib/BackRest/Restore.pm b/lib/BackRest/Restore.pm index fcd6c5ec5..2c07cac42 100644 --- a/lib/BackRest/Restore.pm +++ b/lib/BackRest/Restore.pm @@ -497,9 +497,7 @@ sub recovery # Write the restore command if (!$bRestoreCommandOverride) { - $strRecovery .= "restore_command = '$self->{strBackRestBin} --stanza=$self->{strStanza}" . - (defined($self->{strConfigFile}) ? " --config=$self->{strConfigFile}" : '') . - " archive-get %f \"%p\"'\n"; + $strRecovery .= "restore_command = '" . operationWrite(OP_ARCHIVE_GET) . " %f \"%p\"'\n"; } # If RECOVERY_TYPE_DEFAULT do not write target options diff --git a/lib/BackRest/RestoreFile.pm b/lib/BackRest/RestoreFile.pm index bbcbed892..ea9f1ea63 100644 --- a/lib/BackRest/RestoreFile.pm +++ b/lib/BackRest/RestoreFile.pm @@ -76,9 +76,10 @@ sub restoreFile else { my ($strChecksum, $lSize) = $oFile->hash_size(PATH_DB_ABSOLUTE, $strDestinationFile); + my $strManifestChecksum = $oManifest->get($strSection, $strFileName, MANIFEST_SUBKEY_CHECKSUM, false, 'INVALID'); if (($lSize == $oManifest->get($strSection, $strFileName, MANIFEST_SUBKEY_SIZE) && $lSize == 0) || - ($strChecksum eq $oManifest->get($strSection, $strFileName, MANIFEST_SUBKEY_CHECKSUM))) + ($strChecksum eq $strManifestChecksum)) { &log(DEBUG, "${strDestinationFile} exists and is zero size or matches backup checksum"); diff --git a/test/lib/BackRestTest/ConfigTest.pm b/test/lib/BackRestTest/ConfigTest.pm index 252856657..1e9e935d7 100755 --- a/test/lib/BackRestTest/ConfigTest.pm +++ b/test/lib/BackRestTest/ConfigTest.pm @@ -507,6 +507,25 @@ sub BackRestTestConfig_Test optionTestExpect(OPTION_RESTORE_RECOVERY_SETTING, 'db.domain.net', 'primary-conn-info'); } + if (BackRestTestCommon_Run(++$iRun, OP_RESTORE . ' values passed to ' . OP_ARCHIVE_GET)) + { + optionSetTest($oOption, OPTION_STANZA, $strStanza); + optionSetTest($oOption, OPTION_DB_PATH, '/db path/main'); + optionSetTest($oOption, OPTION_REPO_PATH, '/repo'); + optionSetTest($oOption, OPTION_BACKUP_HOST, 'db.mydomain.com'); + + configLoadExpect($oOption, OP_RESTORE); + + my $strCommand = operationWrite(OP_ARCHIVE_GET); + my $strExpectedCommand = "$0 --backup-host=db.mydomain.com \"--db-path=/db path/main\"" . + " --repo-path=/repo --stanza=main " . OP_ARCHIVE_GET; + + if ($strCommand ne $strExpectedCommand) + { + confess "expected command '${strExpectedCommand}' but got '${strCommand}'"; + } + } + if (BackRestTestCommon_Run(++$iRun, OP_BACKUP . ' valid value ' . OPTION_COMMAND_PSQL)) { optionSetTest($oOption, OPTION_STANZA, $strStanza);