Attempt to repair any inconsistencies found during a consistency check via "borgmatic check --repair" flag (#266).
This commit is contained in:
parent
0c6c61a272
commit
2ab9daaa0f
5 changed files with 38 additions and 7 deletions
2
NEWS
2
NEWS
|
@ -2,6 +2,8 @@
|
|||
* #235: Pass extra options directly to particular Borg commands, handy for Borg options that
|
||||
borgmatic does not yet support natively. Use "extra_borg_options" in the storage configuration
|
||||
section.
|
||||
* #266: Attempt to repair any inconsistencies found during a consistency check via
|
||||
"borgmatic check --repair" flag.
|
||||
|
||||
1.4.16
|
||||
* #256: Fix for "before_backup" hook not triggering an error when the command contains "borg" and
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
|
||||
from borgmatic.borg import extract
|
||||
from borgmatic.execute import execute_command
|
||||
from borgmatic.execute import execute_command, execute_command_without_capture
|
||||
|
||||
DEFAULT_CHECKS = ('repository', 'archives')
|
||||
DEFAULT_PREFIX = '{hostname}-'
|
||||
|
@ -91,12 +91,13 @@ def check_archives(
|
|||
consistency_config,
|
||||
local_path='borg',
|
||||
remote_path=None,
|
||||
repair=None,
|
||||
only_checks=None,
|
||||
):
|
||||
'''
|
||||
Given a local or remote repository path, a storage config dict, a consistency config dict,
|
||||
local/remote commands to run, and an optional list of checks to use instead of configured
|
||||
checks, check the contained Borg archives for consistency.
|
||||
local/remote commands to run, whether to attempt a repair, and an optional list of checks
|
||||
to use instead of configured checks, check the contained Borg archives for consistency.
|
||||
|
||||
If there are no consistency checks to run, skip running them.
|
||||
'''
|
||||
|
@ -106,9 +107,7 @@ def check_archives(
|
|||
extra_borg_options = storage_config.get('extra_borg_options', {}).get('check', '')
|
||||
|
||||
if set(checks).intersection(set(DEFAULT_CHECKS + ('data',))):
|
||||
remote_path_flags = ('--remote-path', remote_path) if remote_path else ()
|
||||
lock_wait = storage_config.get('lock_wait', None)
|
||||
lock_wait_flags = ('--lock-wait', str(lock_wait)) if lock_wait else ()
|
||||
|
||||
verbosity_flags = ()
|
||||
if logger.isEnabledFor(logging.INFO):
|
||||
|
@ -120,14 +119,21 @@ def check_archives(
|
|||
|
||||
full_command = (
|
||||
(local_path, 'check')
|
||||
+ (('--repair',) if repair else ())
|
||||
+ _make_check_flags(checks, check_last, prefix)
|
||||
+ remote_path_flags
|
||||
+ lock_wait_flags
|
||||
+ (('--remote-path', remote_path) if remote_path else ())
|
||||
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
|
||||
+ verbosity_flags
|
||||
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
|
||||
+ (repository,)
|
||||
)
|
||||
|
||||
# The Borg repair option trigger an interactive prompt, which won't work when output is
|
||||
# captured.
|
||||
if repair:
|
||||
execute_command_without_capture(full_command, error_on_warnings=True)
|
||||
return
|
||||
|
||||
execute_command(full_command, error_on_warnings=True)
|
||||
|
||||
if 'extract' in checks:
|
||||
|
|
|
@ -266,6 +266,13 @@ def parse_arguments(*unparsed_arguments):
|
|||
add_help=False,
|
||||
)
|
||||
check_group = check_parser.add_argument_group('check arguments')
|
||||
check_group.add_argument(
|
||||
'--repair',
|
||||
dest='repair',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help='Attempt to repair any inconsistencies found (experimental and only for interactive use)',
|
||||
)
|
||||
check_group.add_argument(
|
||||
'--only',
|
||||
metavar='CHECK',
|
||||
|
|
|
@ -230,6 +230,7 @@ def run_actions(
|
|||
consistency,
|
||||
local_path=local_path,
|
||||
remote_path=remote_path,
|
||||
repair=arguments['check'].repair,
|
||||
only_checks=arguments['check'].only,
|
||||
)
|
||||
if 'extract' in arguments:
|
||||
|
|
|
@ -158,6 +158,21 @@ def test_make_check_flags_with_default_checks_and_prefix_includes_prefix_flag():
|
|||
assert flags == ('--prefix', 'foo-')
|
||||
|
||||
|
||||
def test_check_archives_with_repair_calls_borg_with_repair_parameter():
|
||||
checks = ('repository',)
|
||||
consistency_config = {'check_last': None}
|
||||
flexmock(module).should_receive('_parse_checks').and_return(checks)
|
||||
flexmock(module).should_receive('_make_check_flags').and_return(())
|
||||
flexmock(module).should_receive('execute_command').never()
|
||||
flexmock(module).should_receive('execute_command_without_capture').with_args(
|
||||
('borg', 'check', '--repair', 'repo'), error_on_warnings=True
|
||||
).once()
|
||||
|
||||
module.check_archives(
|
||||
repository='repo', storage_config={}, consistency_config=consistency_config, repair=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'checks',
|
||||
(
|
||||
|
|
Loading…
Reference in a new issue