mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Split command-line parameter processing out into a separate file. This is in preparation allowing all parameters to be specified/overridden on the command line, with pg_backrest.conf being option.
This commit is contained in:
parent
f115e01b71
commit
ae6bdecfaf
@ -15,6 +15,7 @@ use Pod::Usage;
|
|||||||
|
|
||||||
use lib dirname($0) . '/../lib';
|
use lib dirname($0) . '/../lib';
|
||||||
use BackRest::Utility;
|
use BackRest::Utility;
|
||||||
|
use BackRest::Param;
|
||||||
use BackRest::Config;
|
use BackRest::Config;
|
||||||
use BackRest::Remote;
|
use BackRest::Remote;
|
||||||
use BackRest::File;
|
use BackRest::File;
|
||||||
@ -196,7 +197,7 @@ else
|
|||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# ARCHIVE-PUSH Command
|
# ARCHIVE-PUSH Command
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
if (operation_get() eq OP_ARCHIVE_PUSH)
|
if (operationTest(OP_ARCHIVE_PUSH))
|
||||||
{
|
{
|
||||||
# Make sure the archive push operation happens on the db side
|
# Make sure the archive push operation happens on the db side
|
||||||
if ($strRemote eq DB)
|
if ($strRemote eq DB)
|
||||||
@ -222,7 +223,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
|
|
||||||
if ($bArchiveLocal)
|
if ($bArchiveLocal)
|
||||||
{
|
{
|
||||||
$strStopFile = "${strArchivePath}/lock/" . param_get(PARAM_STANZA) . "-archive.stop";
|
$strStopFile = "${strArchivePath}/lock/" . optionGet(OPTION_STANZA) . "-archive.stop";
|
||||||
}
|
}
|
||||||
|
|
||||||
# If an archive file is defined, then push it
|
# If an archive file is defined, then push it
|
||||||
@ -244,7 +245,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
# Create the file object
|
# Create the file object
|
||||||
my $oFile = new BackRest::File
|
my $oFile = new BackRest::File
|
||||||
(
|
(
|
||||||
param_get(PARAM_STANZA),
|
optionGet(OPTION_STANZA),
|
||||||
config_key_load($strSection, CONFIG_KEY_PATH, true),
|
config_key_load($strSection, CONFIG_KEY_PATH, true),
|
||||||
$bArchiveLocal ? NONE : $strRemote,
|
$bArchiveLocal ? NONE : $strRemote,
|
||||||
remote_get($bArchiveLocal, config_key_load(CONFIG_SECTION_ARCHIVE, CONFIG_KEY_COMPRESS_LEVEL),
|
remote_get($bArchiveLocal, config_key_load(CONFIG_SECTION_ARCHIVE, CONFIG_KEY_COMPRESS_LEVEL),
|
||||||
@ -272,7 +273,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Fork and exit the parent process so the async process can continue
|
# Fork and exit the parent process so the async process can continue
|
||||||
if (!param_get(PARAM_TEST_NO_FORK))
|
if (!optionTest(OPTION_TEST_NO_FORK))
|
||||||
{
|
{
|
||||||
if (fork())
|
if (fork())
|
||||||
{
|
{
|
||||||
@ -295,7 +296,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
&log(INFO, 'starting async archive-push');
|
&log(INFO, 'starting async archive-push');
|
||||||
|
|
||||||
# Create a lock file to make sure async archive-push does not run more than once
|
# Create a lock file to make sure async archive-push does not run more than once
|
||||||
my $strLockPath = "${strArchivePath}/lock/" . param_get(PARAM_STANZA) . "-archive.lock";
|
my $strLockPath = "${strArchivePath}/lock/" . optionGet(OPTION_STANZA) . "-archive.lock";
|
||||||
|
|
||||||
if (!lock_file_create($strLockPath))
|
if (!lock_file_create($strLockPath))
|
||||||
{
|
{
|
||||||
@ -304,7 +305,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Build the basic command string that will be used to modify the command during processing
|
# Build the basic command string that will be used to modify the command during processing
|
||||||
my $strCommand = $^X . ' ' . $0 . " --stanza=" . param_get(PARAM_STANZA);
|
my $strCommand = $^X . ' ' . $0 . " --stanza=" . optionGet(OPTION_STANZA);
|
||||||
|
|
||||||
# Get the new operational flags
|
# Get the new operational flags
|
||||||
my $bCompress = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false;
|
my $bCompress = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false;
|
||||||
@ -315,7 +316,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
# Create the file object
|
# Create the file object
|
||||||
my $oFile = new BackRest::File
|
my $oFile = new BackRest::File
|
||||||
(
|
(
|
||||||
param_get(PARAM_STANZA),
|
optionGet(OPTION_STANZA),
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
||||||
$strRemote,
|
$strRemote,
|
||||||
remote_get(false, config_key_load(CONFIG_SECTION_ARCHIVE, CONFIG_KEY_COMPRESS_LEVEL),
|
remote_get(false, config_key_load(CONFIG_SECTION_ARCHIVE, CONFIG_KEY_COMPRESS_LEVEL),
|
||||||
@ -340,7 +341,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
|
|
||||||
while (!defined($iLogTotal) || $iLogTotal > 0)
|
while (!defined($iLogTotal) || $iLogTotal > 0)
|
||||||
{
|
{
|
||||||
$iLogTotal = archive_xfer($strArchivePath . "/archive/" . param_get(PARAM_STANZA), $strStopFile,
|
$iLogTotal = archive_xfer($strArchivePath . "/archive/" . optionGet(OPTION_STANZA), $strStopFile,
|
||||||
$strCommand, $iArchiveMaxMB);
|
$strCommand, $iArchiveMaxMB);
|
||||||
|
|
||||||
if ($iLogTotal > 0)
|
if ($iLogTotal > 0)
|
||||||
@ -402,7 +403,7 @@ if (operation_get() eq OP_ARCHIVE_PUSH)
|
|||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# ARCHIVE-GET Command
|
# ARCHIVE-GET Command
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
if (operation_get() eq OP_ARCHIVE_GET)
|
if (operationTest(OP_ARCHIVE_GET))
|
||||||
{
|
{
|
||||||
# Make sure the archive file is defined
|
# Make sure the archive file is defined
|
||||||
if (!defined($ARGV[1]))
|
if (!defined($ARGV[1]))
|
||||||
@ -419,7 +420,7 @@ if (operation_get() eq OP_ARCHIVE_GET)
|
|||||||
# Init the file object
|
# Init the file object
|
||||||
my $oFile = new BackRest::File
|
my $oFile = new BackRest::File
|
||||||
(
|
(
|
||||||
param_get(PARAM_STANZA),
|
optionGet(OPTION_STANZA),
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
||||||
$strRemote,
|
$strRemote,
|
||||||
remote_get(false,
|
remote_get(false,
|
||||||
@ -446,7 +447,7 @@ if (operation_get() eq OP_ARCHIVE_GET)
|
|||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
my $oFile = new BackRest::File
|
my $oFile = new BackRest::File
|
||||||
(
|
(
|
||||||
param_get(PARAM_STANZA),
|
optionGet(OPTION_STANZA),
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true),
|
||||||
$strRemote,
|
$strRemote,
|
||||||
remote_get(false,
|
remote_get(false,
|
||||||
@ -457,7 +458,7 @@ my $oFile = new BackRest::File
|
|||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# RESTORE
|
# RESTORE
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
if (operation_get() eq OP_RESTORE)
|
if (operationTest(OP_RESTORE))
|
||||||
{
|
{
|
||||||
if ($strRemote eq DB)
|
if ($strRemote eq DB)
|
||||||
{
|
{
|
||||||
@ -465,31 +466,31 @@ if (operation_get() eq OP_RESTORE)
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Open the log file
|
# Open the log file
|
||||||
log_file_set(config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_PATH, true) . '/log/' . param_get(PARAM_STANZA) . '-restore');
|
log_file_set(config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_PATH, true) . '/log/' . optionGet(OPTION_STANZA) . '-restore');
|
||||||
|
|
||||||
# Set the lock path
|
# Set the lock path
|
||||||
my $strLockPath = config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_PATH, true) . '/lock/' .
|
my $strLockPath = config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_PATH, true) . '/lock/' .
|
||||||
param_get(PARAM_STANZA) . '-' . operation_get() . '.lock';
|
optionGet(OPTION_STANZA) . '-' . operationGet() . '.lock';
|
||||||
|
|
||||||
# Do the restore
|
# Do the restore
|
||||||
new BackRest::Restore
|
new BackRest::Restore
|
||||||
(
|
(
|
||||||
config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH, true),
|
config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH, true),
|
||||||
param_get(PARAM_SET),
|
optionGet(OPTION_SET),
|
||||||
config_section_load(CONFIG_SECTION_TABLESPACE_MAP),
|
config_section_load(CONFIG_SECTION_TABLESPACE_MAP),
|
||||||
$oFile,
|
$oFile,
|
||||||
config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_THREAD_MAX, true),
|
config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_THREAD_MAX, true),
|
||||||
param_get(PARAM_DELTA),
|
optionGet(OPTION_DELTA),
|
||||||
param_get(PARAM_FORCE),
|
optionGet(OPTION_FORCE),
|
||||||
param_get(PARAM_TYPE),
|
optionGet(OPTION_TYPE),
|
||||||
param_get(PARAM_TARGET),
|
optionGet(OPTION_TARGET, false),
|
||||||
param_get(PARAM_TARGET_EXCLUSIVE),
|
optionGet(OPTION_TARGET_EXCLUSIVE, false),
|
||||||
param_get(PARAM_TARGET_RESUME),
|
optionGet(OPTION_TARGET_RESUME, false),
|
||||||
param_get(PARAM_TARGET_TIMELINE),
|
optionGet(OPTION_TARGET_TIMELINE, false),
|
||||||
config_section_load(CONFIG_SECTION_RECOVERY_OPTION),
|
config_section_load(CONFIG_SECTION_RECOVERY_OPTION),
|
||||||
param_get(PARAM_STANZA),
|
optionGet(OPTION_STANZA),
|
||||||
$0,
|
$0,
|
||||||
param_get(PARAM_CONFIG)
|
optionGet(OPTION_CONFIG)
|
||||||
)->restore;
|
)->restore;
|
||||||
|
|
||||||
remote_exit(0);
|
remote_exit(0);
|
||||||
@ -499,7 +500,7 @@ if (operation_get() eq OP_RESTORE)
|
|||||||
# GET MORE CONFIG INFO
|
# GET MORE CONFIG INFO
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# Open the log file
|
# Open the log file
|
||||||
log_file_set(config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true) . '/log/' . param_get(PARAM_STANZA));
|
log_file_set(config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true) . '/log/' . optionGet(OPTION_STANZA));
|
||||||
|
|
||||||
# Make sure backup and expire operations happen on the backup side
|
# Make sure backup and expire operations happen on the backup side
|
||||||
if ($strRemote eq BACKUP)
|
if ($strRemote eq BACKUP)
|
||||||
@ -512,18 +513,18 @@ my $bCompress = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true
|
|||||||
|
|
||||||
# Set the lock path
|
# Set the lock path
|
||||||
my $strLockPath = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true) . '/lock/' .
|
my $strLockPath = config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_PATH, true) . '/lock/' .
|
||||||
param_get(PARAM_STANZA) . '-' . operation_get() . '.lock';
|
optionGet(OPTION_STANZA) . '-' . operationGet() . '.lock';
|
||||||
|
|
||||||
if (!lock_file_create($strLockPath))
|
if (!lock_file_create($strLockPath))
|
||||||
{
|
{
|
||||||
&log(ERROR, 'backup process is already running for stanza ' . param_get(PARAM_STANZA) . ' - exiting');
|
&log(ERROR, 'backup process is already running for stanza ' . optionGet(OPTION_STANZA) . ' - exiting');
|
||||||
remote_exit(0);
|
remote_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Initialize the db object
|
# Initialize the db object
|
||||||
my $oDb;
|
my $oDb;
|
||||||
|
|
||||||
if (!param_get(PARAM_NO_START_STOP))
|
if (!optionGet(OPTION_NO_START_STOP))
|
||||||
{
|
{
|
||||||
$oDb = new BackRest::Db
|
$oDb = new BackRest::Db
|
||||||
(
|
(
|
||||||
@ -538,31 +539,31 @@ backup_init
|
|||||||
(
|
(
|
||||||
$oDb,
|
$oDb,
|
||||||
$oFile,
|
$oFile,
|
||||||
param_get(PARAM_TYPE),
|
optionGet(OPTION_TYPE),
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false,
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_COMPRESS, true, 'y') eq 'y' ? true : false,
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HARDLINK, true, 'y') eq 'y' ? true : false,
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_HARDLINK, true, 'y') eq 'y' ? true : false,
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_MAX),
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_MAX),
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_ARCHIVE_REQUIRED, true, 'y') eq 'y' ? true : false,
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_ARCHIVE_REQUIRED, true, 'y') eq 'y' ? true : false,
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_TIMEOUT),
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_THREAD_TIMEOUT),
|
||||||
param_get(PARAM_NO_START_STOP),
|
optionGet(OPTION_NO_START_STOP),
|
||||||
param_get(PARAM_FORCE)
|
optionTest(OPTION_FORCE)
|
||||||
);
|
);
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# BACKUP
|
# BACKUP
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
if (operation_get() eq OP_BACKUP)
|
if (operationTest(OP_BACKUP))
|
||||||
{
|
{
|
||||||
backup(config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH),
|
backup(config_key_load(CONFIG_SECTION_STANZA, CONFIG_KEY_PATH),
|
||||||
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_START_FAST, true, 'n') eq 'y' ? true : false);
|
config_key_load(CONFIG_SECTION_BACKUP, CONFIG_KEY_START_FAST, true, 'n') eq 'y' ? true : false);
|
||||||
|
|
||||||
operation_set(OP_EXPIRE);
|
operationSet(OP_EXPIRE);
|
||||||
}
|
}
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# EXPIRE
|
# EXPIRE
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
if (operation_get() eq OP_EXPIRE)
|
if (operationTest(OP_EXPIRE))
|
||||||
{
|
{
|
||||||
backup_expire
|
backup_expire
|
||||||
(
|
(
|
||||||
|
@ -16,6 +16,7 @@ use Thread::Queue;
|
|||||||
use lib dirname($0);
|
use lib dirname($0);
|
||||||
use BackRest::Utility;
|
use BackRest::Utility;
|
||||||
use BackRest::Exception;
|
use BackRest::Exception;
|
||||||
|
use BackRest::Param;
|
||||||
use BackRest::Config;
|
use BackRest::Config;
|
||||||
use BackRest::Manifest;
|
use BackRest::Manifest;
|
||||||
use BackRest::File;
|
use BackRest::File;
|
||||||
|
@ -7,33 +7,21 @@ use strict;
|
|||||||
use warnings FATAL => qw(all);
|
use warnings FATAL => qw(all);
|
||||||
use Carp qw(confess);
|
use Carp qw(confess);
|
||||||
|
|
||||||
use Pod::Usage;
|
|
||||||
use File::Basename;
|
use File::Basename;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
|
|
||||||
use lib dirname($0) . '/../lib';
|
use lib dirname($0) . '/../lib';
|
||||||
use BackRest::Exception;
|
use BackRest::Exception;
|
||||||
use BackRest::Utility;
|
use BackRest::Utility;
|
||||||
|
use BackRest::Param;
|
||||||
|
|
||||||
use Exporter qw(import);
|
use Exporter qw(import);
|
||||||
|
|
||||||
our @EXPORT = qw(config_load config_key_load config_section_load operation_get operation_set param_get
|
our @EXPORT = qw(config_load config_key_load config_section_load
|
||||||
|
|
||||||
FILE_MANIFEST FILE_VERSION FILE_POSTMASTER_PID FILE_RECOVERY_CONF
|
FILE_MANIFEST FILE_VERSION FILE_POSTMASTER_PID FILE_RECOVERY_CONF
|
||||||
PATH_LATEST
|
PATH_LATEST
|
||||||
|
|
||||||
OP_ARCHIVE_GET OP_ARCHIVE_PUSH OP_BACKUP OP_RESTORE OP_EXPIRE
|
|
||||||
|
|
||||||
BACKUP_TYPE_FULL BACKUP_TYPE_DIFF BACKUP_TYPE_INCR
|
|
||||||
|
|
||||||
RECOVERY_TYPE_NAME RECOVERY_TYPE_TIME RECOVERY_TYPE_XID RECOVERY_TYPE_PRESERVE RECOVERY_TYPE_NONE
|
|
||||||
RECOVERY_TYPE_DEFAULT
|
|
||||||
|
|
||||||
PARAM_CONFIG PARAM_STANZA PARAM_TYPE PARAM_DELTA PARAM_SET PARAM_NO_START_STOP PARAM_FORCE PARAM_TARGET
|
|
||||||
PARAM_TARGET_EXCLUSIVE PARAM_TARGET_RESUME PARAM_TARGET_TIMELINE CONFIG_SECTION_RECOVERY
|
|
||||||
|
|
||||||
PARAM_VERSION PARAM_HELP PARAM_TEST PARAM_TEST_DELAY PARAM_TEST_NO_FORK
|
|
||||||
|
|
||||||
CONFIG_SECTION_COMMAND CONFIG_SECTION_GENERAL CONFIG_SECTION_COMMAND_OPTION CONFIG_SECTION_LOG CONFIG_SECTION_BACKUP
|
CONFIG_SECTION_COMMAND CONFIG_SECTION_GENERAL CONFIG_SECTION_COMMAND_OPTION CONFIG_SECTION_LOG CONFIG_SECTION_BACKUP
|
||||||
CONFIG_SECTION_RESTORE CONFIG_SECTION_RECOVERY CONFIG_SECTION_RECOVERY_OPTION CONFIG_SECTION_TABLESPACE_MAP
|
CONFIG_SECTION_RESTORE CONFIG_SECTION_RECOVERY CONFIG_SECTION_RECOVERY_OPTION CONFIG_SECTION_TABLESPACE_MAP
|
||||||
CONFIG_SECTION_ARCHIVE CONFIG_SECTION_RETENTION CONFIG_SECTION_STANZA
|
CONFIG_SECTION_ARCHIVE CONFIG_SECTION_RETENTION CONFIG_SECTION_STANZA
|
||||||
@ -65,68 +53,6 @@ use constant
|
|||||||
FILE_VERSION => 'version',
|
FILE_VERSION => 'version',
|
||||||
FILE_POSTMASTER_PID => 'postmaster.pid',
|
FILE_POSTMASTER_PID => 'postmaster.pid',
|
||||||
FILE_RECOVERY_CONF => 'recovery.conf',
|
FILE_RECOVERY_CONF => 'recovery.conf',
|
||||||
|
|
||||||
PATH_LATEST => 'latest'
|
|
||||||
};
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# Operation constants - basic operations that are allowed in backrest
|
|
||||||
####################################################################################################################################
|
|
||||||
use constant
|
|
||||||
{
|
|
||||||
OP_ARCHIVE_GET => 'archive-get',
|
|
||||||
OP_ARCHIVE_PUSH => 'archive-push',
|
|
||||||
OP_BACKUP => 'backup',
|
|
||||||
OP_RESTORE => 'restore',
|
|
||||||
OP_EXPIRE => 'expire'
|
|
||||||
};
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# BACKUP Type Constants
|
|
||||||
####################################################################################################################################
|
|
||||||
use constant
|
|
||||||
{
|
|
||||||
BACKUP_TYPE_FULL => 'full',
|
|
||||||
BACKUP_TYPE_DIFF => 'diff',
|
|
||||||
BACKUP_TYPE_INCR => 'incr'
|
|
||||||
};
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# RECOVERY Type Constants
|
|
||||||
####################################################################################################################################
|
|
||||||
use constant
|
|
||||||
{
|
|
||||||
RECOVERY_TYPE_NAME => 'name',
|
|
||||||
RECOVERY_TYPE_TIME => 'time',
|
|
||||||
RECOVERY_TYPE_XID => 'xid',
|
|
||||||
RECOVERY_TYPE_PRESERVE => 'preserve',
|
|
||||||
RECOVERY_TYPE_NONE => 'none',
|
|
||||||
RECOVERY_TYPE_DEFAULT => 'default'
|
|
||||||
};
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# Parameter constants
|
|
||||||
####################################################################################################################################
|
|
||||||
use constant
|
|
||||||
{
|
|
||||||
PARAM_CONFIG => 'config',
|
|
||||||
PARAM_STANZA => 'stanza',
|
|
||||||
PARAM_TYPE => 'type',
|
|
||||||
PARAM_NO_START_STOP => 'no-start-stop',
|
|
||||||
PARAM_DELTA => 'delta',
|
|
||||||
PARAM_SET => 'set',
|
|
||||||
PARAM_FORCE => 'force',
|
|
||||||
PARAM_VERSION => 'version',
|
|
||||||
PARAM_HELP => 'help',
|
|
||||||
|
|
||||||
PARAM_TARGET => 'target',
|
|
||||||
PARAM_TARGET_EXCLUSIVE => 'target-exclusive',
|
|
||||||
PARAM_TARGET_RESUME => 'target-resume',
|
|
||||||
PARAM_TARGET_TIMELINE => 'target-timeline',
|
|
||||||
|
|
||||||
PARAM_TEST => 'test',
|
|
||||||
PARAM_TEST_DELAY => 'test-delay',
|
|
||||||
PARAM_TEST_NO_FORK => 'no-fork'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
@ -216,8 +142,6 @@ use constant
|
|||||||
# Global variables
|
# Global variables
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
my %oConfig; # Configuration hash
|
my %oConfig; # Configuration hash
|
||||||
my %oParam = (); # Parameter hash
|
|
||||||
my $strOperation; # Operation (backup, archive-get, ...)
|
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# CONFIG_LOAD
|
# CONFIG_LOAD
|
||||||
@ -228,61 +152,9 @@ sub config_load
|
|||||||
{
|
{
|
||||||
my $strFile = shift; # Full path to ini file to load from
|
my $strFile = shift; # Full path to ini file to load from
|
||||||
|
|
||||||
# Default for general parameters
|
# Load parameters
|
||||||
param_set(PARAM_NO_START_STOP, false); # Do not perform start/stop backup (and archive-required gets set to false)
|
configLoad();
|
||||||
param_set(PARAM_FORCE, false); # Force an action that would not normally be allowed (varies by action)
|
ini_load(optionGet(OPTION_CONFIG), \%oConfig);
|
||||||
param_set(PARAM_VERSION, false); # Display version and exit
|
|
||||||
param_set(PARAM_HELP, false); # Display help and exit
|
|
||||||
|
|
||||||
# Defaults for test parameters - not for general use
|
|
||||||
param_set(PARAM_TEST_NO_FORK, false); # Prevents the archive process from forking when local archiving is enabled
|
|
||||||
param_set(PARAM_TEST, false); # Enters test mode - not harmful, but adds special logging and pauses for unit testing
|
|
||||||
param_set(PARAM_TEST_DELAY, 5); # Seconds to delay after a test point (default is not enough for manual tests)
|
|
||||||
|
|
||||||
# Get command line parameters
|
|
||||||
GetOptions (\%oParam, PARAM_CONFIG . '=s', PARAM_STANZA . '=s', PARAM_TYPE . '=s', PARAM_DELTA, PARAM_SET . '=s',
|
|
||||||
PARAM_NO_START_STOP, PARAM_FORCE, PARAM_TARGET . '=s', PARAM_TARGET_EXCLUSIVE, PARAM_TARGET_RESUME,
|
|
||||||
PARAM_TARGET_TIMELINE . '=s', PARAM_VERSION, PARAM_HELP,
|
|
||||||
PARAM_TEST, PARAM_TEST_DELAY . '=s', PARAM_TEST_NO_FORK)
|
|
||||||
or pod2usage(2);
|
|
||||||
|
|
||||||
# Display version and exit if requested
|
|
||||||
if (param_get(PARAM_VERSION) || param_get(PARAM_HELP))
|
|
||||||
{
|
|
||||||
print 'pg_backrest ' . version_get() . "\n";
|
|
||||||
|
|
||||||
if (!param_get(PARAM_HELP))
|
|
||||||
{
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Display help and exit if requested
|
|
||||||
if (param_get(PARAM_HELP))
|
|
||||||
{
|
|
||||||
print "\n";
|
|
||||||
pod2usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get and validate the operation
|
|
||||||
$strOperation = $ARGV[0];
|
|
||||||
|
|
||||||
# Validate params
|
|
||||||
param_valid();
|
|
||||||
|
|
||||||
# # Validate thread parameter
|
|
||||||
# if (defined(param_get(PARAM_THREAD)) && !(param_get(PARAM_THREAD) >= 1))
|
|
||||||
# {
|
|
||||||
# confess &log(ERROR, 'thread parameter should be >= 1');
|
|
||||||
# }
|
|
||||||
|
|
||||||
# Get configuration parameter and load it
|
|
||||||
if (!defined(param_get(PARAM_CONFIG)))
|
|
||||||
{
|
|
||||||
param_set(PARAM_CONFIG, '/etc/pg_backrest.conf');
|
|
||||||
}
|
|
||||||
|
|
||||||
ini_load(param_get(PARAM_CONFIG), \%oConfig);
|
|
||||||
|
|
||||||
# If this is a restore, then try to default config
|
# If this is a restore, then try to default config
|
||||||
if (!defined(config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_PATH)))
|
if (!defined(config_key_load(CONFIG_SECTION_RESTORE, CONFIG_KEY_PATH)))
|
||||||
@ -304,9 +176,6 @@ sub config_load
|
|||||||
|
|
||||||
# Validate config
|
# Validate config
|
||||||
config_valid();
|
config_valid();
|
||||||
|
|
||||||
# Set test parameters
|
|
||||||
test_set(param_get(PARAM_TEST), param_get(PARAM_TEST_DELAY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
@ -316,7 +185,7 @@ sub config_section_load
|
|||||||
{
|
{
|
||||||
my $strSection = shift;
|
my $strSection = shift;
|
||||||
|
|
||||||
$strSection = param_get(PARAM_STANZA) . ':' . $strSection;
|
$strSection = optionGet(OPTION_STANZA) . ':' . $strSection;
|
||||||
|
|
||||||
return $oConfig{$strSection};
|
return $oConfig{$strSection};
|
||||||
}
|
}
|
||||||
@ -342,13 +211,13 @@ sub config_key_load
|
|||||||
# Look in the default stanza section
|
# Look in the default stanza section
|
||||||
if ($strSection eq CONFIG_SECTION_STANZA)
|
if ($strSection eq CONFIG_SECTION_STANZA)
|
||||||
{
|
{
|
||||||
$strValue = $oConfig{param_get(PARAM_STANZA)}{"${strKey}"};
|
$strValue = $oConfig{optionGet(OPTION_STANZA)}{"${strKey}"};
|
||||||
}
|
}
|
||||||
# Else look in the supplied section
|
# Else look in the supplied section
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
# First check the stanza section
|
# First check the stanza section
|
||||||
$strValue = $oConfig{param_get(PARAM_STANZA) . ":${strSection}"}{"${strKey}"};
|
$strValue = $oConfig{optionGet(OPTION_STANZA) . ":${strSection}"}{"${strKey}"};
|
||||||
|
|
||||||
# If the stanza section value is undefined then check global
|
# If the stanza section value is undefined then check global
|
||||||
if (!defined($strValue))
|
if (!defined($strValue))
|
||||||
@ -396,7 +265,7 @@ sub config_key_set
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Set the value
|
# Set the value
|
||||||
$strSection = param_get(PARAM_STANZA) . ':' . $strSection;
|
$strSection = optionGet(OPTION_STANZA) . ':' . $strSection;
|
||||||
|
|
||||||
$oConfig{$strSection}{$strKey} = $strValue;
|
$oConfig{$strSection}{$strKey} = $strValue;
|
||||||
}
|
}
|
||||||
@ -413,7 +282,7 @@ sub config_valid
|
|||||||
my $oSectionHashRef;
|
my $oSectionHashRef;
|
||||||
|
|
||||||
# Check [stanza]:recovery:option section
|
# Check [stanza]:recovery:option section
|
||||||
$strSection = param_get(PARAM_STANZA) . ':' . CONFIG_SECTION_RECOVERY_OPTION;
|
$strSection = optionGet(OPTION_STANZA) . ':' . CONFIG_SECTION_RECOVERY_OPTION;
|
||||||
$oSectionHashRef = $oConfig{$strSection};
|
$oSectionHashRef = $oConfig{$strSection};
|
||||||
|
|
||||||
if (defined($oSectionHashRef) && keys($oSectionHashRef) != 0)
|
if (defined($oSectionHashRef) && keys($oSectionHashRef) != 0)
|
||||||
@ -511,7 +380,7 @@ sub config_key_valid
|
|||||||
$oConfig{$strSection}{$strKey} = $strValue;
|
$oConfig{$strSection}{$strKey} = $strValue;
|
||||||
|
|
||||||
# Also do validation for the stanza section
|
# Also do validation for the stanza section
|
||||||
my $strStanza = param_get(PARAM_STANZA);
|
my $strStanza = optionGet(OPTION_STANZA);
|
||||||
|
|
||||||
if (substr($strSection, 0, length($strStanza) + 1) ne "${strStanza}:")
|
if (substr($strSection, 0, length($strStanza) + 1) ne "${strStanza}:")
|
||||||
{
|
{
|
||||||
@ -519,177 +388,4 @@ sub config_key_valid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# PARAM_VALID
|
|
||||||
#
|
|
||||||
# Make sure the command-line parameters are valid.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub param_valid
|
|
||||||
{
|
|
||||||
# Check the stanza
|
|
||||||
if (!defined(param_get(PARAM_STANZA)))
|
|
||||||
{
|
|
||||||
confess 'a backup stanza must be specified';
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check that the operation is present and valid
|
|
||||||
if (!defined($strOperation))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, "operation must be specified", ERROR_PARAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($strOperation ne OP_ARCHIVE_GET &&
|
|
||||||
$strOperation ne OP_ARCHIVE_PUSH &&
|
|
||||||
$strOperation ne OP_BACKUP &&
|
|
||||||
$strOperation ne OP_RESTORE &&
|
|
||||||
$strOperation ne OP_EXPIRE)
|
|
||||||
{
|
|
||||||
confess &log(ERROR, "invalid operation ${strOperation}");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check type param
|
|
||||||
my $strParam = PARAM_TYPE;
|
|
||||||
my $strType = param_get($strParam);
|
|
||||||
|
|
||||||
# Type is only valid for backup and restore operations
|
|
||||||
if (operation_test(OP_BACKUP) || operation_test(OP_RESTORE))
|
|
||||||
{
|
|
||||||
# Check types for backup
|
|
||||||
if (operation_test(OP_BACKUP))
|
|
||||||
{
|
|
||||||
# If type is not defined set to BACKUP_TYPE_INCR
|
|
||||||
if (!defined($strType))
|
|
||||||
{
|
|
||||||
$strType = BACKUP_TYPE_INCR;
|
|
||||||
param_set($strParam, $strType);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check that type is in valid list
|
|
||||||
if (!($strType eq BACKUP_TYPE_FULL || $strType eq BACKUP_TYPE_DIFF || $strType eq BACKUP_TYPE_INCR))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, "invalid type '${strType}' for ${strOperation}, must be: '" . BACKUP_TYPE_FULL . "', '" .
|
|
||||||
BACKUP_TYPE_DIFF . "', '" . BACKUP_TYPE_INCR . "'", ERROR_PARAM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check types for restore
|
|
||||||
elsif (operation_test(OP_RESTORE))
|
|
||||||
{
|
|
||||||
# If type is not defined set to RECOVERY_TYPE_DEFAULT
|
|
||||||
if (!defined($strType))
|
|
||||||
{
|
|
||||||
$strType = RECOVERY_TYPE_DEFAULT;
|
|
||||||
param_set($strParam, $strType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($strType eq RECOVERY_TYPE_NAME || $strType eq RECOVERY_TYPE_TIME || $strType eq RECOVERY_TYPE_XID ||
|
|
||||||
$strType eq RECOVERY_TYPE_PRESERVE || $strType eq RECOVERY_TYPE_NONE || $strType eq RECOVERY_TYPE_DEFAULT))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, "invalid type '${strType}' for ${strOperation}, must be: '" . RECOVERY_TYPE_NAME .
|
|
||||||
"', '" . RECOVERY_TYPE_TIME . "', '" . RECOVERY_TYPE_XID . "', '" . RECOVERY_TYPE_PRESERVE .
|
|
||||||
"', '" . RECOVERY_TYPE_NONE . "', '" . RECOVERY_TYPE_DEFAULT . "'", ERROR_PARAM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (defined($strType))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, PARAM_TYPE . ' is only valid for '. OP_BACKUP . ' and ' . OP_RESTORE . ' operations', ERROR_PARAM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check target param
|
|
||||||
$strParam = PARAM_TARGET;
|
|
||||||
my $strTarget = param_get($strParam);
|
|
||||||
my $strTargetMessage = 'for ' . OP_RESTORE . " operations where type is '" . RECOVERY_TYPE_NAME .
|
|
||||||
"', '" . RECOVERY_TYPE_TIME . "', or '" . RECOVERY_TYPE_XID . "'";
|
|
||||||
|
|
||||||
if (operation_test(OP_RESTORE) &&
|
|
||||||
($strType eq RECOVERY_TYPE_NAME || $strType eq RECOVERY_TYPE_TIME || $strType eq RECOVERY_TYPE_XID))
|
|
||||||
{
|
|
||||||
if (!defined($strTarget))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, PARAM_TARGET . ' is required ' . $strTargetMessage, ERROR_PARAM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elsif (defined($strTarget))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, PARAM_TARGET . ' is only required ' . $strTargetMessage, ERROR_PARAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check target-resume - can only be used when target is specified
|
|
||||||
if (defined(param_get(PARAM_TARGET_RESUME)) && !defined($strTarget))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, PARAM_TARGET_RESUME . ' and ' . PARAM_TARGET_TIMELINE .
|
|
||||||
' are only valid when target is specified', ERROR_PARAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check target-exclusive - can only be used when target is time or xid
|
|
||||||
if (defined(param_get(PARAM_TARGET_EXCLUSIVE)) && !($strType eq RECOVERY_TYPE_TIME || $strType eq RECOVERY_TYPE_XID))
|
|
||||||
{
|
|
||||||
confess &log(ERROR, PARAM_TARGET_EXCLUSIVE . ' is only valid when target is specified and recovery type is ' .
|
|
||||||
RECOVERY_TYPE_TIME . ' or ' . RECOVERY_TYPE_XID, ERROR_PARAM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# OPERATION_GET
|
|
||||||
#
|
|
||||||
# Get the current operation.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub operation_get
|
|
||||||
{
|
|
||||||
return $strOperation;
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# OPERATION_TEST
|
|
||||||
#
|
|
||||||
# Test the current operation.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub operation_test
|
|
||||||
{
|
|
||||||
my $strOperationTest = shift;
|
|
||||||
|
|
||||||
return $strOperationTest eq $strOperation;
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# OPERATION_SET
|
|
||||||
#
|
|
||||||
# Set current operation (usually for triggering follow-on operations).
|
|
||||||
####################################################################################################################################
|
|
||||||
sub operation_set
|
|
||||||
{
|
|
||||||
my $strValue = shift;
|
|
||||||
|
|
||||||
$strOperation = $strValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# PARAM_GET
|
|
||||||
#
|
|
||||||
# Get param value.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub param_get
|
|
||||||
{
|
|
||||||
my $strParam = shift;
|
|
||||||
|
|
||||||
return $oParam{$strParam};
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# PARAM_SET
|
|
||||||
#
|
|
||||||
# Set param value.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub param_set
|
|
||||||
{
|
|
||||||
my $strParam = shift;
|
|
||||||
my $strValue = shift;
|
|
||||||
|
|
||||||
$oParam{$strParam} = $strValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -11,21 +11,25 @@ use Carp qw(confess);
|
|||||||
# Exports
|
# Exports
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
use Exporter qw(import);
|
use Exporter qw(import);
|
||||||
our @EXPORT = qw(ERROR_CHECKSUM ERROR_CONFIG ERROR_PARAM ERROR_POSTMASTER_RUNNING ERROR_PROTOCOL ERROR_RESTORE_PATH_NOT_EMPTY
|
our @EXPORT = qw(ERROR_ASSERT ERROR_CHECKSUM ERROR_CONFIG ERROR_OPERATION_REQUIRED ERROR_OPTION_REQUIRED ERROR_OPTION_INVALID
|
||||||
ERROR_FORMAT);
|
ERROR_OPTION_INVALID_VALUE ERROR_POSTMASTER_RUNNING ERROR_PROTOCOL ERROR_RESTORE_PATH_NOT_EMPTY ERROR_FORMAT);
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# Exception Codes
|
# Exception Codes
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
use constant
|
use constant
|
||||||
{
|
{
|
||||||
ERROR_CHECKSUM => 100,
|
ERROR_ASSERT => 100,
|
||||||
ERROR_CONFIG => 101,
|
ERROR_CHECKSUM => 101,
|
||||||
ERROR_PARAM => 102,
|
ERROR_CONFIG => 102,
|
||||||
ERROR_RESTORE_PATH_NOT_EMPTY => 103,
|
ERROR_FORMAT => 103,
|
||||||
ERROR_POSTMASTER_RUNNING => 104,
|
ERROR_OPERATION_REQUIRED => 104,
|
||||||
ERROR_PROTOCOL => 105,
|
ERROR_OPTION_REQUIRED => 105,
|
||||||
ERROR_FORMAT => 106
|
ERROR_OPTION_INVALID => 106,
|
||||||
|
ERROR_OPTION_INVALID_VALUE => 107,
|
||||||
|
ERROR_POSTMASTER_RUNNING => 108,
|
||||||
|
ERROR_PROTOCOL => 109,
|
||||||
|
ERROR_RESTORE_PATH_NOT_EMPTY => 110
|
||||||
};
|
};
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
|
785
lib/BackRest/Param.pm
Normal file
785
lib/BackRest/Param.pm
Normal file
@ -0,0 +1,785 @@
|
|||||||
|
####################################################################################################################################
|
||||||
|
# PARAM MODULE
|
||||||
|
####################################################################################################################################
|
||||||
|
package BackRest::Param;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings FATAL => qw(all);
|
||||||
|
use Carp qw(confess);
|
||||||
|
|
||||||
|
use Pod::Usage;
|
||||||
|
use File::Basename;
|
||||||
|
use Getopt::Long qw(GetOptions);
|
||||||
|
use Storable qw(dclone);
|
||||||
|
|
||||||
|
use lib dirname($0) . '/../lib';
|
||||||
|
use BackRest::Exception;
|
||||||
|
use BackRest::Utility;
|
||||||
|
|
||||||
|
use Exporter qw(import);
|
||||||
|
|
||||||
|
our @EXPORT = qw(configLoad optionGet optionTest optionRuleGet operationGet operationTest operationSet
|
||||||
|
|
||||||
|
OP_ARCHIVE_GET OP_ARCHIVE_PUSH OP_BACKUP OP_RESTORE OP_EXPIRE
|
||||||
|
|
||||||
|
BACKUP_TYPE_FULL BACKUP_TYPE_DIFF BACKUP_TYPE_INCR
|
||||||
|
|
||||||
|
RECOVERY_TYPE_NAME RECOVERY_TYPE_TIME RECOVERY_TYPE_XID RECOVERY_TYPE_PRESERVE RECOVERY_TYPE_NONE
|
||||||
|
RECOVERY_TYPE_DEFAULT
|
||||||
|
|
||||||
|
OPTION_CONFIG OPTION_STANZA OPTION_TYPE OPTION_DELTA OPTION_SET OPTION_NO_START_STOP OPTION_FORCE OPTION_TARGET
|
||||||
|
OPTION_TARGET_EXCLUSIVE OPTION_TARGET_RESUME OPTION_TARGET_TIMELINE OPTION_THREAD_MAX
|
||||||
|
|
||||||
|
OPTION_VERSION OPTION_HELP OPTION_TEST OPTION_TEST_DELAY OPTION_TEST_NO_FORK
|
||||||
|
|
||||||
|
OPTION_DEFAULT_RESTORE_SET);
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Operation constants - basic operations that are allowed in backrest
|
||||||
|
####################################################################################################################################
|
||||||
|
use constant
|
||||||
|
{
|
||||||
|
OP_ARCHIVE_GET => 'archive-get',
|
||||||
|
OP_ARCHIVE_PUSH => 'archive-push',
|
||||||
|
OP_BACKUP => 'backup',
|
||||||
|
OP_RESTORE => 'restore',
|
||||||
|
OP_EXPIRE => 'expire'
|
||||||
|
};
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# BACKUP Type Constants
|
||||||
|
####################################################################################################################################
|
||||||
|
use constant
|
||||||
|
{
|
||||||
|
BACKUP_TYPE_FULL => 'full',
|
||||||
|
BACKUP_TYPE_DIFF => 'diff',
|
||||||
|
BACKUP_TYPE_INCR => 'incr'
|
||||||
|
};
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# RECOVERY Type Constants
|
||||||
|
####################################################################################################################################
|
||||||
|
use constant
|
||||||
|
{
|
||||||
|
RECOVERY_TYPE_NAME => 'name',
|
||||||
|
RECOVERY_TYPE_TIME => 'time',
|
||||||
|
RECOVERY_TYPE_XID => 'xid',
|
||||||
|
RECOVERY_TYPE_PRESERVE => 'preserve',
|
||||||
|
RECOVERY_TYPE_NONE => 'none',
|
||||||
|
RECOVERY_TYPE_DEFAULT => 'default'
|
||||||
|
};
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Option constants
|
||||||
|
####################################################################################################################################
|
||||||
|
use constant
|
||||||
|
{
|
||||||
|
# Command-line-only options
|
||||||
|
OPTION_CONFIG => 'config',
|
||||||
|
OPTION_DELTA => 'delta',
|
||||||
|
OPTION_FORCE => 'force',
|
||||||
|
OPTION_NO_START_STOP => 'no-start-stop',
|
||||||
|
OPTION_SET => 'set',
|
||||||
|
OPTION_STANZA => 'stanza',
|
||||||
|
OPTION_TARGET => 'target',
|
||||||
|
OPTION_TARGET_EXCLUSIVE => 'target-exclusive',
|
||||||
|
OPTION_TARGET_RESUME => 'target-resume',
|
||||||
|
OPTION_TARGET_TIMELINE => 'target-timeline',
|
||||||
|
OPTION_TYPE => 'type',
|
||||||
|
|
||||||
|
# Command-line-only/conf file options
|
||||||
|
OPTION_THREAD_MAX => 'thread-max',
|
||||||
|
|
||||||
|
# Command-line-only help/version options
|
||||||
|
OPTION_HELP => 'help',
|
||||||
|
OPTION_VERSION => 'version',
|
||||||
|
|
||||||
|
# Command-line-only test options
|
||||||
|
OPTION_TEST => 'test',
|
||||||
|
OPTION_TEST_DELAY => 'test-delay',
|
||||||
|
OPTION_TEST_NO_FORK => 'no-fork'
|
||||||
|
};
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Option Defaults
|
||||||
|
####################################################################################################################################
|
||||||
|
use constant
|
||||||
|
{
|
||||||
|
OPTION_DEFAULT_CONFIG => '/etc/pg_backrest.conf',
|
||||||
|
OPTION_DEFAULT_THREAD_MAX => 1,
|
||||||
|
|
||||||
|
OPTION_DEFAULT_BACKUP_FORCE => false,
|
||||||
|
OPTION_DEFAULT_BACKUP_NO_START_STOP => false,
|
||||||
|
OPTION_DEFAULT_BACKUP_TYPE => BACKUP_TYPE_INCR,
|
||||||
|
|
||||||
|
OPTION_DEFAULT_RESTORE_DELTA => false,
|
||||||
|
OPTION_DEFAULT_RESTORE_FORCE => false,
|
||||||
|
OPTION_DEFAULT_RESTORE_SET => 'latest',
|
||||||
|
OPTION_DEFAULT_RESTORE_TYPE => RECOVERY_TYPE_DEFAULT,
|
||||||
|
OPTION_DEFAULT_RESTORE_TARGET_EXCLUSIVE => false,
|
||||||
|
OPTION_DEFAULT_RESTORE_TARGET_RESUME => false,
|
||||||
|
|
||||||
|
OPTION_DEFAULT_HELP => false,
|
||||||
|
OPTION_DEFAULT_VERSION => false,
|
||||||
|
|
||||||
|
OPTION_DEFAULT_TEST => false,
|
||||||
|
OPTION_DEFAULT_TEST_DELAY => 5,
|
||||||
|
OPTION_DEFAULT_TEST_NO_FORK => false
|
||||||
|
};
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Option Rules
|
||||||
|
####################################################################################################################################
|
||||||
|
use constant
|
||||||
|
{
|
||||||
|
OPTION_RULE_ALLOW_LIST => 'allow-list',
|
||||||
|
OPTION_RULE_DEFAULT => 'default',
|
||||||
|
OPTION_RULE_DEPEND => 'depend',
|
||||||
|
OPTION_RULE_DEPEND_OPTION => 'depend-option',
|
||||||
|
OPTION_RULE_DEPEND_LIST => 'depend-list',
|
||||||
|
OPTION_RULE_DEPEND_VALUE => 'depend-value',
|
||||||
|
OPTION_RULE_REQUIRED => 'required',
|
||||||
|
OPTION_RULE_OPERATION => 'operation',
|
||||||
|
OPTION_RULE_TYPE => 'type'
|
||||||
|
};
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Option Types
|
||||||
|
####################################################################################################################################
|
||||||
|
use constant
|
||||||
|
{
|
||||||
|
OPTION_TYPE_STRING => 'string',
|
||||||
|
OPTION_TYPE_BOOLEAN => 'boolean',
|
||||||
|
OPTION_TYPE_INTEGER => 'integer',
|
||||||
|
OPTION_TYPE_FLOAT => 'float'
|
||||||
|
};
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Option Rule Hash
|
||||||
|
####################################################################################################################################
|
||||||
|
my %oOptionRule =
|
||||||
|
(
|
||||||
|
&OPTION_CONFIG =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_STRING,
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_CONFIG
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_DELTA =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_DELTA,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_FORCE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_FORCE,
|
||||||
|
},
|
||||||
|
|
||||||
|
&OP_BACKUP =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_BACKUP_FORCE,
|
||||||
|
&OPTION_RULE_DEPEND =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND_OPTION => OPTION_NO_START_STOP,
|
||||||
|
&OPTION_RULE_DEPEND_VALUE => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_NO_START_STOP =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_BACKUP =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_BACKUP_NO_START_STOP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_SET =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_STRING,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_TYPE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_STANZA =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_STRING
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TARGET =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_STRING,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND_OPTION => OPTION_TYPE,
|
||||||
|
&OPTION_RULE_DEPEND_LIST =>
|
||||||
|
{
|
||||||
|
&RECOVERY_TYPE_NAME => true,
|
||||||
|
&RECOVERY_TYPE_TIME => true,
|
||||||
|
&RECOVERY_TYPE_XID => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TARGET_EXCLUSIVE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_TARGET_EXCLUSIVE,
|
||||||
|
&OPTION_RULE_DEPEND =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND_OPTION => OPTION_TYPE,
|
||||||
|
&OPTION_RULE_DEPEND_LIST =>
|
||||||
|
{
|
||||||
|
&RECOVERY_TYPE_TIME => true,
|
||||||
|
&RECOVERY_TYPE_XID => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TARGET_RESUME =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_TARGET_RESUME,
|
||||||
|
&OPTION_RULE_DEPEND =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND_OPTION => OPTION_TYPE,
|
||||||
|
&OPTION_RULE_DEPEND_LIST =>
|
||||||
|
{
|
||||||
|
&RECOVERY_TYPE_NAME => true,
|
||||||
|
&RECOVERY_TYPE_TIME => true,
|
||||||
|
&RECOVERY_TYPE_XID => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TARGET_TIMELINE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_STRING,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_REQUIRED => false,
|
||||||
|
&OPTION_RULE_DEPEND =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND_OPTION => OPTION_TYPE,
|
||||||
|
&OPTION_RULE_DEPEND_LIST =>
|
||||||
|
{
|
||||||
|
&RECOVERY_TYPE_DEFAULT => true,
|
||||||
|
&RECOVERY_TYPE_NAME => true,
|
||||||
|
&RECOVERY_TYPE_TIME => true,
|
||||||
|
&RECOVERY_TYPE_XID => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TYPE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_STRING,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_BACKUP =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_BACKUP_TYPE,
|
||||||
|
&OPTION_RULE_ALLOW_LIST =>
|
||||||
|
{
|
||||||
|
&BACKUP_TYPE_FULL => true,
|
||||||
|
&BACKUP_TYPE_DIFF => true,
|
||||||
|
&BACKUP_TYPE_INCR => true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OP_RESTORE =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_RESTORE_TYPE,
|
||||||
|
&OPTION_RULE_ALLOW_LIST =>
|
||||||
|
{
|
||||||
|
&RECOVERY_TYPE_NAME => true,
|
||||||
|
&RECOVERY_TYPE_TIME => true,
|
||||||
|
&RECOVERY_TYPE_XID => true,
|
||||||
|
&RECOVERY_TYPE_PRESERVE => true,
|
||||||
|
&RECOVERY_TYPE_NONE => true,
|
||||||
|
&RECOVERY_TYPE_DEFAULT => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_THREAD_MAX =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_INTEGER,
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_THREAD_MAX,
|
||||||
|
&OPTION_RULE_OPERATION =>
|
||||||
|
{
|
||||||
|
&OP_BACKUP => true,
|
||||||
|
&OP_RESTORE => true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_HELP =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_HELP
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_VERSION =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_VERSION
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TEST =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_TEST
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TEST_DELAY =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_FLOAT,
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_TEST_DELAY,
|
||||||
|
&OPTION_RULE_DEPEND =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND_OPTION => OPTION_TEST,
|
||||||
|
&OPTION_RULE_DEPEND_VALUE => true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
&OPTION_TEST_NO_FORK =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_TYPE => OPTION_TYPE_BOOLEAN,
|
||||||
|
&OPTION_RULE_DEFAULT => OPTION_DEFAULT_TEST_NO_FORK,
|
||||||
|
&OPTION_RULE_DEPEND =>
|
||||||
|
{
|
||||||
|
&OPTION_RULE_DEPEND_OPTION => OPTION_TEST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Global variables
|
||||||
|
####################################################################################################################################
|
||||||
|
my %oOption; # Option hash
|
||||||
|
my $strOperation; # Operation (backup, archive-get, ...)
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# configLoad
|
||||||
|
#
|
||||||
|
# Load configuration.
|
||||||
|
####################################################################################################################################
|
||||||
|
sub configLoad
|
||||||
|
{
|
||||||
|
# Clear option in case it was loaded before
|
||||||
|
%oOption = ();
|
||||||
|
|
||||||
|
# Build hash with all valid command-line options
|
||||||
|
my %oOption;
|
||||||
|
|
||||||
|
foreach my $strKey (keys(%oOptionRule))
|
||||||
|
{
|
||||||
|
my $strOption = $strKey;
|
||||||
|
|
||||||
|
if (!defined($oOptionRule{$strKey}{&OPTION_RULE_TYPE}))
|
||||||
|
{
|
||||||
|
confess &log(ASSERT, "Option ${strKey} does not have a defined type", ERROR_ASSERT);
|
||||||
|
}
|
||||||
|
elsif ($oOptionRule{$strKey}{&OPTION_RULE_TYPE} ne OPTION_TYPE_BOOLEAN)
|
||||||
|
{
|
||||||
|
$strOption .= '=s';
|
||||||
|
}
|
||||||
|
|
||||||
|
$oOption{$strOption} = $strOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get command-line options
|
||||||
|
my %oOptionTest;
|
||||||
|
|
||||||
|
GetOptions(\%oOptionTest, %oOption)
|
||||||
|
or pod2usage(2);
|
||||||
|
|
||||||
|
# Validate and store options
|
||||||
|
optionValid(\%oOptionTest);
|
||||||
|
|
||||||
|
# Display version and exit if requested
|
||||||
|
if (optionGet(OPTION_VERSION) || optionGet(OPTION_HELP))
|
||||||
|
{
|
||||||
|
print 'pg_backrest ' . version_get() . "\n";
|
||||||
|
|
||||||
|
if (!OPTION_get(OPTION_HELP))
|
||||||
|
{
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Display help and exit if requested
|
||||||
|
if (optionGet(OPTION_HELP))
|
||||||
|
{
|
||||||
|
print "\n";
|
||||||
|
pod2usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set test options
|
||||||
|
!optionGet(OPTION_TEST) or test_set(optionGet(OPTION_TEST), optionGet(OPTION_TEST_DELAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# optionValid
|
||||||
|
#
|
||||||
|
# Make sure the command-line options are valid based on the operation.
|
||||||
|
####################################################################################################################################
|
||||||
|
sub optionValid
|
||||||
|
{
|
||||||
|
my $oOptionTest = shift;
|
||||||
|
|
||||||
|
# Check that the operation is present and valid
|
||||||
|
$strOperation = $ARGV[0];
|
||||||
|
|
||||||
|
if (!defined($strOperation))
|
||||||
|
{
|
||||||
|
confess &log(ERROR, "operation must be specified", ERROR_OPERATION_REQUIRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($strOperation ne OP_ARCHIVE_GET &&
|
||||||
|
$strOperation ne OP_ARCHIVE_PUSH &&
|
||||||
|
$strOperation ne OP_BACKUP &&
|
||||||
|
$strOperation ne OP_RESTORE &&
|
||||||
|
$strOperation ne OP_EXPIRE)
|
||||||
|
{
|
||||||
|
confess &log(ERROR, "invalid operation ${strOperation}");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Keep track of unresolved dependencies
|
||||||
|
my $bDependUnresolved = true;
|
||||||
|
my %oOptionResolved;
|
||||||
|
|
||||||
|
# Loop through all possible options
|
||||||
|
while ($bDependUnresolved)
|
||||||
|
{
|
||||||
|
# Assume that all dependencies will be resolved in this loop
|
||||||
|
$bDependUnresolved = false;
|
||||||
|
|
||||||
|
foreach my $strOption (sort(keys(%oOptionRule)))
|
||||||
|
{
|
||||||
|
# Skip the option if it has been resolved in a prior loop
|
||||||
|
if (defined($oOptionResolved{$strOption}))
|
||||||
|
{
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check dependency for the operation then for the option
|
||||||
|
my $oDepend;
|
||||||
|
my $bDependResolved = true;
|
||||||
|
|
||||||
|
if (defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}) &&
|
||||||
|
defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) &&
|
||||||
|
ref($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) eq 'HASH')
|
||||||
|
{
|
||||||
|
$oDepend = $oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}{&OPTION_RULE_DEPEND};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined($oDepend))
|
||||||
|
{
|
||||||
|
$oDepend = $oOptionRule{$strOption}{&OPTION_RULE_DEPEND};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($oDepend))
|
||||||
|
{
|
||||||
|
# Make sure the depend option has been resolved, otherwise skip this option for now
|
||||||
|
my $strDependOption = $$oDepend{&OPTION_RULE_DEPEND_OPTION};
|
||||||
|
|
||||||
|
if (!defined($oOptionResolved{$strDependOption}))
|
||||||
|
{
|
||||||
|
$bDependUnresolved = true;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if the depend option has a value
|
||||||
|
my $strDependValue = $oOption{$strDependOption};
|
||||||
|
my $strError = "option '${strOption}' not valid without option '${strDependOption}'";
|
||||||
|
|
||||||
|
$bDependResolved = defined($strDependValue) ? true : false;
|
||||||
|
|
||||||
|
if (!$bDependResolved && defined($$oOptionTest{$strOption}))
|
||||||
|
{
|
||||||
|
confess &log(ERROR, $strError, ERROR_OPTION_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
# If a depend value exists, make sure the option value matches
|
||||||
|
if ($bDependResolved && defined($$oDepend{&OPTION_RULE_DEPEND_VALUE}) &&
|
||||||
|
$$oDepend{&OPTION_RULE_DEPEND_VALUE} ne $strDependValue)
|
||||||
|
{
|
||||||
|
$bDependResolved = false;
|
||||||
|
|
||||||
|
if (defined($$oOptionTest{$strOption}))
|
||||||
|
{
|
||||||
|
if ($oOptionRule{$strDependOption}{&OPTION_RULE_TYPE} eq OPTION_TYPE_BOOLEAN)
|
||||||
|
{
|
||||||
|
if (!$$oDepend{&OPTION_RULE_DEPEND_VALUE})
|
||||||
|
{
|
||||||
|
confess &log(ASSERT, "no error has been created for unused case where depend value = false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$strError .= " = '$$oDepend{&OPTION_RULE_DEPEND_VALUE}'";
|
||||||
|
}
|
||||||
|
|
||||||
|
confess &log(ERROR, $strError, ERROR_OPTION_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# If a depend list exists, make sure the value is in the list
|
||||||
|
if ($bDependResolved && defined($$oDepend{&OPTION_RULE_DEPEND_LIST}) &&
|
||||||
|
!defined($$oDepend{&OPTION_RULE_DEPEND_LIST}{$strDependValue}))
|
||||||
|
{
|
||||||
|
$bDependResolved = false;
|
||||||
|
|
||||||
|
if (defined($$oOptionTest{$strOption}))
|
||||||
|
{
|
||||||
|
my @oyValue;
|
||||||
|
|
||||||
|
foreach my $strValue (sort(keys($$oDepend{&OPTION_RULE_DEPEND_LIST})))
|
||||||
|
{
|
||||||
|
push(@oyValue, "'${strValue}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$strError .= @oyValue == 1 ? " = $oyValue[0]" : " in (" . join(", ", @oyValue) . ")";
|
||||||
|
confess &log(ERROR, $strError, ERROR_OPTION_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Is the option defined?
|
||||||
|
if (defined($$oOptionTest{$strOption}))
|
||||||
|
{
|
||||||
|
my $strValue = $$oOptionTest{$strOption};
|
||||||
|
|
||||||
|
# Test option type
|
||||||
|
if ($oOptionRule{$strOption}{&OPTION_RULE_TYPE} eq OPTION_TYPE_INTEGER ||
|
||||||
|
$oOptionRule{$strOption}{&OPTION_RULE_TYPE} eq OPTION_TYPE_FLOAT)
|
||||||
|
{
|
||||||
|
# Test that the string is a valid float or integer by adding 1 to it. It's pretty hokey but it works and it
|
||||||
|
# beats requiring Scalar::Util::Numeric to do it properly.
|
||||||
|
eval
|
||||||
|
{
|
||||||
|
my $strTest = $strValue + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
my $bError = $@ ? true : false;
|
||||||
|
|
||||||
|
# Check that integers are really integers
|
||||||
|
if (!$bError && $oOptionRule{$strOption}{&OPTION_RULE_TYPE} eq OPTION_TYPE_INTEGER &&
|
||||||
|
(int($strValue) . 'S') ne ($strValue . 'S'))
|
||||||
|
{
|
||||||
|
$bError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Error if the value did not pass tests
|
||||||
|
!$bError
|
||||||
|
or confess &log(ERROR, "'${strValue}' is not valid for '${strOption}' option", ERROR_OPTION_INVALID_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process an allow list for the operation then for the option
|
||||||
|
my $oAllow;
|
||||||
|
|
||||||
|
if (defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}) &&
|
||||||
|
defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) &&
|
||||||
|
ref($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) eq 'HASH')
|
||||||
|
{
|
||||||
|
$oAllow = $oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}{&OPTION_RULE_ALLOW_LIST};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined($oAllow))
|
||||||
|
{
|
||||||
|
$oAllow = $oOptionRule{$strOption}{&OPTION_RULE_ALLOW_LIST};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($oAllow) && !defined($$oAllow{$$oOptionTest{$strOption}}))
|
||||||
|
{
|
||||||
|
confess &log(ERROR, "'${strValue}' is not valid for '${strOption}' option", ERROR_OPTION_INVALID_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set option value
|
||||||
|
$oOption{$strOption} = $strValue;
|
||||||
|
}
|
||||||
|
# Else set the default if required
|
||||||
|
elsif (!defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}) ||
|
||||||
|
defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}))
|
||||||
|
{
|
||||||
|
# Check for default in operation then option
|
||||||
|
my $strDefault;
|
||||||
|
|
||||||
|
if (defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}) &&
|
||||||
|
defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) &&
|
||||||
|
ref($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) eq 'HASH')
|
||||||
|
{
|
||||||
|
$strDefault = $oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}{&OPTION_RULE_DEFAULT}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined($strDefault))
|
||||||
|
{
|
||||||
|
$strDefault = $oOptionRule{$strOption}{&OPTION_RULE_DEFAULT};
|
||||||
|
}
|
||||||
|
|
||||||
|
# If default is defined
|
||||||
|
if (defined($strDefault))
|
||||||
|
{
|
||||||
|
# Only set default if dependency is resolved
|
||||||
|
$oOption{$strOption} = $strDefault if $bDependResolved;
|
||||||
|
}
|
||||||
|
# Else error
|
||||||
|
else
|
||||||
|
{
|
||||||
|
# Check for required in operation then option
|
||||||
|
my $bRequired;
|
||||||
|
|
||||||
|
if (defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}) &&
|
||||||
|
defined($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) &&
|
||||||
|
ref($oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}) eq 'HASH')
|
||||||
|
{
|
||||||
|
$bRequired = $oOptionRule{$strOption}{&OPTION_RULE_OPERATION}{$strOperation}{&OPTION_RULE_REQUIRED};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined($bRequired))
|
||||||
|
{
|
||||||
|
$bRequired = $oOptionRule{$strOption}{&OPTION_RULE_REQUIRED};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined($bRequired) || $bRequired)
|
||||||
|
{
|
||||||
|
if ($bDependResolved)
|
||||||
|
{
|
||||||
|
confess &log(ERROR, "${strOperation} operation requires option: ${strOption}", ERROR_OPTION_REQUIRED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$oOptionResolved{$strOption} = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# operationGet
|
||||||
|
#
|
||||||
|
# Get the current operation.
|
||||||
|
####################################################################################################################################
|
||||||
|
sub operationGet
|
||||||
|
{
|
||||||
|
return $strOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# operationTest
|
||||||
|
#
|
||||||
|
# Test the current operation.
|
||||||
|
####################################################################################################################################
|
||||||
|
sub operationTest
|
||||||
|
{
|
||||||
|
my $strOperationTest = shift;
|
||||||
|
|
||||||
|
return $strOperationTest eq $strOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# operationSet
|
||||||
|
#
|
||||||
|
# Set current operation (usually for triggering follow-on operations).
|
||||||
|
####################################################################################################################################
|
||||||
|
sub operationSet
|
||||||
|
{
|
||||||
|
my $strValue = shift;
|
||||||
|
|
||||||
|
$strOperation = $strValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# optionGet
|
||||||
|
#
|
||||||
|
# Get option value.
|
||||||
|
####################################################################################################################################
|
||||||
|
sub optionGet
|
||||||
|
{
|
||||||
|
my $strOption = shift;
|
||||||
|
my $bRequired = shift;
|
||||||
|
|
||||||
|
if (!defined($oOption{$strOption}) && (!defined($bRequired) || $bRequired))
|
||||||
|
{
|
||||||
|
confess &log(ASSERT, "option ${strOption} is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $oOption{$strOption};
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# optionTest
|
||||||
|
#
|
||||||
|
# Test a option value.
|
||||||
|
####################################################################################################################################
|
||||||
|
sub optionTest
|
||||||
|
{
|
||||||
|
my $strOption = shift;
|
||||||
|
my $strValue = shift;
|
||||||
|
|
||||||
|
if (defined($strValue))
|
||||||
|
{
|
||||||
|
return optionGet($strOption) eq $strValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defined($oOption{$strOption});
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# optionRuleGet
|
||||||
|
#
|
||||||
|
# Get the option rules.
|
||||||
|
####################################################################################################################################
|
||||||
|
sub optionRuleGet
|
||||||
|
{
|
||||||
|
return dclone(\%oOptionRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
@ -17,6 +17,7 @@ use lib dirname($0);
|
|||||||
use BackRest::Exception;
|
use BackRest::Exception;
|
||||||
use BackRest::Utility;
|
use BackRest::Utility;
|
||||||
use BackRest::ThreadGroup;
|
use BackRest::ThreadGroup;
|
||||||
|
use BackRest::Param;
|
||||||
use BackRest::Config;
|
use BackRest::Config;
|
||||||
use BackRest::Manifest;
|
use BackRest::Manifest;
|
||||||
use BackRest::File;
|
use BackRest::File;
|
||||||
@ -50,6 +51,7 @@ sub new
|
|||||||
|
|
||||||
# Initialize variables
|
# Initialize variables
|
||||||
$self->{strDbClusterPath} = $strDbClusterPath;
|
$self->{strDbClusterPath} = $strDbClusterPath;
|
||||||
|
$self->{strBackupPath} = $strBackupPath;
|
||||||
$self->{oRemapRef} = $oRemapRef;
|
$self->{oRemapRef} = $oRemapRef;
|
||||||
$self->{oFile} = $oFile;
|
$self->{oFile} = $oFile;
|
||||||
$self->{iThreadTotal} = defined($iThreadTotal) ? $iThreadTotal : 1;
|
$self->{iThreadTotal} = defined($iThreadTotal) ? $iThreadTotal : 1;
|
||||||
@ -65,16 +67,6 @@ sub new
|
|||||||
$self->{strBackRestBin} = $strBackRestBin;
|
$self->{strBackRestBin} = $strBackRestBin;
|
||||||
$self->{strConfigFile} = $strConfigFile;
|
$self->{strConfigFile} = $strConfigFile;
|
||||||
|
|
||||||
# If backup path is not specified then default to latest
|
|
||||||
if (defined($strBackupPath))
|
|
||||||
{
|
|
||||||
$self->{strBackupPath} = $strBackupPath;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$self->{strBackupPath} = PATH_LATEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +188,7 @@ sub manifest_load
|
|||||||
# If backup is latest then set it equal to backup label, else verify that requested backup and label match
|
# If backup is latest then set it equal to backup label, else verify that requested backup and label match
|
||||||
my $strBackupLabel = $oManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL);
|
my $strBackupLabel = $oManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL);
|
||||||
|
|
||||||
if ($self->{strBackupPath} eq PATH_LATEST)
|
if ($self->{strBackupPath} eq OPTION_DEFAULT_RESTORE_SET)
|
||||||
{
|
{
|
||||||
$self->{strBackupPath} = $strBackupLabel;
|
$self->{strBackupPath} = $strBackupLabel;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# BackupTest.pl - Unit Tests for BackRest::File
|
# BackupTest.pl - Unit Tests for BackRest::Backup and BackRest::Restore
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
package BackRestTest::BackupTest;
|
package BackRestTest::BackupTest;
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ use DBI;
|
|||||||
use lib dirname($0) . '/../lib';
|
use lib dirname($0) . '/../lib';
|
||||||
use BackRest::Exception;
|
use BackRest::Exception;
|
||||||
use BackRest::Utility;
|
use BackRest::Utility;
|
||||||
|
use BackRest::Param;
|
||||||
use BackRest::Config;
|
use BackRest::Config;
|
||||||
use BackRest::Manifest;
|
use BackRest::Manifest;
|
||||||
use BackRest::File;
|
use BackRest::File;
|
||||||
@ -1963,7 +1964,7 @@ sub BackRestTestBackup_Test
|
|||||||
|
|
||||||
# Static backup parameters
|
# Static backup parameters
|
||||||
my $bSynthetic = false;
|
my $bSynthetic = false;
|
||||||
my $fTestDelay = .25;
|
my $fTestDelay = 1;
|
||||||
|
|
||||||
# Variable backup parameters
|
# Variable backup parameters
|
||||||
my $bDelta = true;
|
my $bDelta = true;
|
||||||
|
392
test/lib/BackRestTest/ConfigTest.pm
Executable file
392
test/lib/BackRestTest/ConfigTest.pm
Executable file
@ -0,0 +1,392 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
####################################################################################################################################
|
||||||
|
# ConfigTest.pl - Unit Tests for BackRest::Param and BackRest::Config
|
||||||
|
####################################################################################################################################
|
||||||
|
package BackRestTest::ConfigTest;
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# Perl includes
|
||||||
|
####################################################################################################################################
|
||||||
|
use strict;
|
||||||
|
use warnings FATAL => qw(all);
|
||||||
|
use Carp qw(confess);
|
||||||
|
|
||||||
|
use File::Basename qw(dirname);
|
||||||
|
use Scalar::Util 'blessed';
|
||||||
|
#use Data::Dumper qw(Dumper);
|
||||||
|
#use Scalar::Util qw(blessed);
|
||||||
|
# use Test::More qw(no_plan);
|
||||||
|
# use Test::Deep;
|
||||||
|
|
||||||
|
use lib dirname($0) . '/../lib';
|
||||||
|
use BackRest::Exception;
|
||||||
|
use BackRest::Utility;
|
||||||
|
use BackRest::Param;
|
||||||
|
|
||||||
|
use BackRestTest::CommonTest;
|
||||||
|
|
||||||
|
use Exporter qw(import);
|
||||||
|
our @EXPORT = qw(BackRestTestConfig_Test);
|
||||||
|
|
||||||
|
sub optionSetTest
|
||||||
|
{
|
||||||
|
my $oOption = shift;
|
||||||
|
my $strKey = shift;
|
||||||
|
my $strValue = shift;
|
||||||
|
|
||||||
|
$$oOption{option}{$strKey} = $strValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub optionSetBoolTest
|
||||||
|
{
|
||||||
|
my $oOption = shift;
|
||||||
|
my $strKey = shift;
|
||||||
|
|
||||||
|
$$oOption{boolean}{$strKey} = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub operationSetTest
|
||||||
|
{
|
||||||
|
my $oOption = shift;
|
||||||
|
my $strOperation = shift;
|
||||||
|
|
||||||
|
$$oOption{operation} = $strOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub optionRemoveTest
|
||||||
|
{
|
||||||
|
my $oOption = shift;
|
||||||
|
my $strKey = shift;
|
||||||
|
|
||||||
|
delete($$oOption{option}{$strKey});
|
||||||
|
delete($$oOption{boolean}{$strKey});
|
||||||
|
}
|
||||||
|
|
||||||
|
sub argvWriteTest
|
||||||
|
{
|
||||||
|
my $oOption = shift;
|
||||||
|
|
||||||
|
@ARGV = ();
|
||||||
|
|
||||||
|
if (defined($$oOption{boolean}))
|
||||||
|
{
|
||||||
|
foreach my $strKey (keys $$oOption{boolean})
|
||||||
|
{
|
||||||
|
if ($$oOption{boolean}{$strKey})
|
||||||
|
{
|
||||||
|
$ARGV[@ARGV] = "--${strKey}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ARGV[@ARGV] = "--no-${strKey}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($$oOption{option}))
|
||||||
|
{
|
||||||
|
foreach my $strKey (keys $$oOption{option})
|
||||||
|
{
|
||||||
|
$ARGV[@ARGV] = "--${strKey}=";
|
||||||
|
|
||||||
|
if (defined($$oOption{option}{$strKey}))
|
||||||
|
{
|
||||||
|
$ARGV[@ARGV - 1] .= $$oOption{option}{$strKey};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ARGV[@ARGV] = $$oOption{operation};
|
||||||
|
|
||||||
|
&log(INFO, " command line: " . join(" ", @ARGV));
|
||||||
|
|
||||||
|
%$oOption = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub configLoadExpectError
|
||||||
|
{
|
||||||
|
my $oOption = shift;
|
||||||
|
my $strOperation = shift;
|
||||||
|
my $iExpectedError = shift;
|
||||||
|
my $strErrorParam1 = shift;
|
||||||
|
my $strErrorParam2 = shift;
|
||||||
|
my $strErrorParam3 = shift;
|
||||||
|
|
||||||
|
my $oOptionRuleExpected = optionRuleGet();
|
||||||
|
|
||||||
|
operationSetTest($oOption, $strOperation);
|
||||||
|
argvWriteTest($oOption);
|
||||||
|
|
||||||
|
eval
|
||||||
|
{
|
||||||
|
configLoad();
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($@)
|
||||||
|
{
|
||||||
|
if (!defined($iExpectedError))
|
||||||
|
{
|
||||||
|
confess $@;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $oMessage = $@;
|
||||||
|
|
||||||
|
if (blessed($oMessage) && $oMessage->isa('BackRest::Exception'))
|
||||||
|
{
|
||||||
|
if ($oMessage->code() != $iExpectedError)
|
||||||
|
{
|
||||||
|
confess "expected error ${iExpectedError} from configLoad but got " . $oMessage->code();
|
||||||
|
}
|
||||||
|
|
||||||
|
my $strError;
|
||||||
|
|
||||||
|
if ($iExpectedError == ERROR_OPTION_REQUIRED)
|
||||||
|
{
|
||||||
|
$strError = "backup operation requires option: ${strErrorParam1}";
|
||||||
|
}
|
||||||
|
elsif ($iExpectedError == ERROR_OPERATION_REQUIRED)
|
||||||
|
{
|
||||||
|
$strError = "operation must be specified";
|
||||||
|
}
|
||||||
|
elsif ($iExpectedError == ERROR_OPTION_INVALID)
|
||||||
|
{
|
||||||
|
$strError = "option '${strErrorParam1}' not valid without option '${strErrorParam2}'";
|
||||||
|
|
||||||
|
if (defined($strErrorParam3))
|
||||||
|
{
|
||||||
|
$strError .= @{$strErrorParam3} == 1 ? " = '$$strErrorParam3[0]'" :
|
||||||
|
" in ('" . join("', '",@{ $strErrorParam3}) . "')";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($iExpectedError == ERROR_OPTION_INVALID_VALUE)
|
||||||
|
{
|
||||||
|
$strError = "'${strErrorParam1}' is not valid for '${strErrorParam2}' option";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
confess "must construct message for error ${iExpectedError}, use this as an example: '" . $oMessage->message() . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($oMessage->message() ne $strError)
|
||||||
|
{
|
||||||
|
confess "expected error message \"${strError}\" from configLoad but got \"" . $oMessage->message() . "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
confess "configLoad should throw BackRest::Exception:\n$oMessage";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (defined($iExpectedError))
|
||||||
|
{
|
||||||
|
confess "expected error ${iExpectedError} from configLoad but got success";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# cmp_deeply(OPTION_rule_get(), $oOptionRuleExpected, 'compare original and new rule hashes')
|
||||||
|
# or die 'comparison failed';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub optionTestExpect
|
||||||
|
{
|
||||||
|
my $strOption = shift;
|
||||||
|
my $strExpectedValue = shift;
|
||||||
|
|
||||||
|
if (defined($strExpectedValue))
|
||||||
|
{
|
||||||
|
my $strActualValue = optionGet($strOption);
|
||||||
|
|
||||||
|
$strActualValue eq $strExpectedValue
|
||||||
|
or confess "expected option ${strOption} to have value ${strExpectedValue}, but ${strActualValue} found instead";
|
||||||
|
}
|
||||||
|
elsif (optionTest($strOption))
|
||||||
|
{
|
||||||
|
confess "expected option ${strOption} to be [undef], but " . optionGet($strOption) . ' found instead';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################################
|
||||||
|
# BackRestTestConfig_Test
|
||||||
|
####################################################################################################################################
|
||||||
|
sub BackRestTestConfig_Test
|
||||||
|
{
|
||||||
|
my $strTest = shift;
|
||||||
|
|
||||||
|
# Setup test variables
|
||||||
|
my $iRun;
|
||||||
|
my $bCreate;
|
||||||
|
my $strStanza = 'main';
|
||||||
|
my $oOption = {};
|
||||||
|
my @oyArray;
|
||||||
|
use constant BOGUS => 'bogus';
|
||||||
|
|
||||||
|
# Print test banner
|
||||||
|
&log(INFO, 'CONFIG MODULE ******************************************************************');
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
# Test config
|
||||||
|
#-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
if ($strTest eq 'all' || $strTest eq 'option')
|
||||||
|
{
|
||||||
|
&log(INFO, "Option module\n");
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup with no stanza'))
|
||||||
|
{
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP , ERROR_OPTION_REQUIRED, OPTION_STANZA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup with boolean stanza'))
|
||||||
|
{
|
||||||
|
optionSetBoolTest($oOption, OPTION_STANZA);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP, , ERROR_OPERATION_REQUIRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup type defaults to ' . BACKUP_TYPE_INCR))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP);
|
||||||
|
optionTestExpect(OPTION_TYPE, BACKUP_TYPE_INCR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup type set to ' . BACKUP_TYPE_FULL))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_TYPE, BACKUP_TYPE_FULL);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP);
|
||||||
|
optionTestExpect(OPTION_TYPE, BACKUP_TYPE_FULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup type invalid'))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_TYPE, BOGUS);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP , ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup invalid force'))
|
||||||
|
{
|
||||||
|
# $oOption = {};
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetBoolTest($oOption, OPTION_FORCE);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP, ERROR_OPTION_INVALID, OPTION_FORCE, OPTION_NO_START_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup valid force'))
|
||||||
|
{
|
||||||
|
# $oOption = {};
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetBoolTest($oOption, OPTION_NO_START_STOP);
|
||||||
|
optionSetBoolTest($oOption, OPTION_FORCE);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP);
|
||||||
|
optionTestExpect(OPTION_NO_START_STOP, true);
|
||||||
|
optionTestExpect(OPTION_FORCE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup invalid value for ' . OPTION_TEST_DELAY))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetBoolTest($oOption, OPTION_TEST);
|
||||||
|
optionSetTest($oOption, OPTION_TEST_DELAY, BOGUS);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP , ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_TEST_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup invalid ' . OPTION_TEST_DELAY))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_TEST_DELAY, 5);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP , ERROR_OPTION_INVALID, OPTION_TEST_DELAY, OPTION_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'backup check ' . OPTION_TEST_DELAY . ' undef'))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP);
|
||||||
|
optionTestExpect(OPTION_TEST_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'restore invalid ' . OPTION_TARGET))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_TYPE, RECOVERY_TYPE_DEFAULT);
|
||||||
|
optionSetTest($oOption, OPTION_TARGET, BOGUS);
|
||||||
|
|
||||||
|
@oyArray = (RECOVERY_TYPE_NAME, RECOVERY_TYPE_TIME, RECOVERY_TYPE_XID);
|
||||||
|
configLoadExpectError($oOption, OP_RESTORE , ERROR_OPTION_INVALID, OPTION_TARGET, OPTION_TYPE, \@oyArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'restore ' . OPTION_TARGET))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_TYPE, RECOVERY_TYPE_NAME);
|
||||||
|
optionSetTest($oOption, OPTION_TARGET, BOGUS);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_RESTORE);
|
||||||
|
optionTestExpect(OPTION_TYPE, RECOVERY_TYPE_NAME);
|
||||||
|
optionTestExpect(OPTION_TARGET, BOGUS);
|
||||||
|
optionTestExpect(OPTION_TARGET_TIMELINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'invalid string ' . OPTION_THREAD_MAX))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_THREAD_MAX, BOGUS);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP , ERROR_OPTION_INVALID_VALUE, BOGUS, OPTION_THREAD_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'invalid float ' . OPTION_THREAD_MAX))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_THREAD_MAX, '0.0');
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP , ERROR_OPTION_INVALID_VALUE, '0.0', OPTION_THREAD_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'valid ' . OPTION_THREAD_MAX))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_THREAD_MAX, '2');
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'valid float ' . OPTION_TEST_DELAY))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetBoolTest($oOption, OPTION_TEST);
|
||||||
|
optionSetTest($oOption, OPTION_TEST_DELAY, '0.25');
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'valid int ' . OPTION_TEST_DELAY))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetBoolTest($oOption, OPTION_TEST);
|
||||||
|
optionSetTest($oOption, OPTION_TEST_DELAY, 3);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_BACKUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Run(++$iRun, 'restore valid ' . OPTION_TARGET_TIMELINE))
|
||||||
|
{
|
||||||
|
optionSetTest($oOption, OPTION_STANZA, $strStanza);
|
||||||
|
optionSetTest($oOption, OPTION_TARGET_TIMELINE, 2);
|
||||||
|
|
||||||
|
configLoadExpectError($oOption, OP_RESTORE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# BackupTest.pl - Unit Tests for BackRest::File
|
# UtilityTest.pl - Unit Tests for BackRest::Utility
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
package BackRestTest::UtilityTest;
|
package BackRestTest::UtilityTest;
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ use File::Basename;
|
|||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use Cwd 'abs_path';
|
use Cwd 'abs_path';
|
||||||
use Pod::Usage;
|
use Pod::Usage;
|
||||||
|
#use Test::More;
|
||||||
|
|
||||||
use lib dirname($0) . '/../lib';
|
use lib dirname($0) . '/../lib';
|
||||||
use BackRest::Utility;
|
use BackRest::Utility;
|
||||||
@ -21,6 +22,7 @@ use BackRest::Utility;
|
|||||||
use lib dirname($0) . '/lib';
|
use lib dirname($0) . '/lib';
|
||||||
use BackRestTest::CommonTest;
|
use BackRestTest::CommonTest;
|
||||||
use BackRestTest::UtilityTest;
|
use BackRestTest::UtilityTest;
|
||||||
|
use BackRestTest::ConfigTest;
|
||||||
use BackRestTest::FileTest;
|
use BackRestTest::FileTest;
|
||||||
use BackRestTest::BackupTest;
|
use BackRestTest::BackupTest;
|
||||||
|
|
||||||
@ -102,6 +104,8 @@ if ($bVersion || $bHelp)
|
|||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Test::More->builder->output('/dev/null');
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# Setup
|
# Setup
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
@ -229,6 +233,11 @@ do
|
|||||||
BackRestTestUtility_Test($strModuleTest);
|
BackRestTestUtility_Test($strModuleTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($strModule eq 'all' || $strModule eq 'config')
|
||||||
|
{
|
||||||
|
BackRestTestConfig_Test($strModuleTest);
|
||||||
|
}
|
||||||
|
|
||||||
if ($strModule eq 'all' || $strModule eq 'file')
|
if ($strModule eq 'all' || $strModule eq 'file')
|
||||||
{
|
{
|
||||||
BackRestTestFile_Test($strModuleTest);
|
BackRestTestFile_Test($strModuleTest);
|
||||||
|
Loading…
Reference in New Issue
Block a user