WIP: Add locking of borgmatic config file #254
|
@ -48,6 +48,14 @@ def run_configuration(config_filename, config, arguments):
|
||||||
)
|
)
|
||||||
global_arguments = arguments['global']
|
global_arguments = arguments['global']
|
||||||
|
|
||||||
|
if location.get("lock_client",False):
|
||||||
|
lock_f = open(config_filename)
|
||||||
|
try:
|
||||||
|
fcntl.flock(lock_f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
|
except IOError:
|
||||||
|
logger.critical("Failed to acquire lock for {}".format(config_filename))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
local_path = location.get('local_path', 'borg')
|
local_path = location.get('local_path', 'borg')
|
||||||
remote_path = location.get('remote_path')
|
remote_path = location.get('remote_path')
|
||||||
borg_environment.initialize(storage)
|
borg_environment.initialize(storage)
|
||||||
|
@ -567,25 +575,9 @@ def main(): # pragma: no cover
|
||||||
logger.debug('Ensuring legacy configuration is upgraded')
|
logger.debug('Ensuring legacy configuration is upgraded')
|
||||||
convert.guard_configuration_upgraded(LEGACY_CONFIG_PATH, config_filenames)
|
convert.guard_configuration_upgraded(LEGACY_CONFIG_PATH, config_filenames)
|
||||||
|
|
||||||
locks = []
|
|
||||||
for config_filename,config in configs.items():
|
|
||||||
lock_config = config.get("location",dict()).get("lock_config",False)
|
|
||||||
if lock_config:
|
|
||||||
f = open(config_filename)
|
|
||||||
try:
|
|
||||||
fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
||||||
except IOError:
|
|
||||||
logger.critical("Failed to acquire lock for {}".format(config_filename))
|
|
||||||
sys.exit(0)
|
|
||||||
locks.append(f)
|
|
||||||
|
|
||||||
summary_logs = parse_logs + list(collect_configuration_run_summary_logs(configs, arguments))
|
summary_logs = parse_logs + list(collect_configuration_run_summary_logs(configs, arguments))
|
||||||
summary_logs_max_level = max(log.levelno for log in summary_logs)
|
summary_logs_max_level = max(log.levelno for log in summary_logs)
|
||||||
|
|
||||||
# this removes the reference to the open files which python will garbage collect the file objects
|
|
||||||
# and close them
|
|
||||||
locks = None
|
|
||||||
|
|
||||||
for message in ('', 'summary:'):
|
for message in ('', 'summary:'):
|
||||||
log_record(
|
log_record(
|
||||||
levelno=summary_logs_max_level,
|
levelno=summary_logs_max_level,
|
||||||
|
|
|
@ -32,7 +32,7 @@ map:
|
||||||
type: bool
|
type: bool
|
||||||
desc: Stay in same file system (do not cross mount points). Defaults to false.
|
desc: Stay in same file system (do not cross mount points). Defaults to false.
|
||||||
example: true
|
example: true
|
||||||
lock_config:
|
lock_client:
|
||||||
type: bool
|
type: bool
|
||||||
desc: Lock config when running borgmatic to prevent multiple instances from running simultaneously
|
desc: Lock config when running borgmatic to prevent multiple instances from running simultaneously
|
||||||
example: true
|
example: true
|
||||||
|
|||||||
|
|
Loading…
Reference in New Issue
Block a user
The fact that it's locking the configuration file might just be an implementation detail as far as the user is concerned. What about calling this something like
lock_client
,lock_borgmatic
, etc? I don't feel strongly about this in any case.Those sound better. I’ll fix it when I get the chance
I renamed it to
lock_client
and left it as a bool for now. I didn't see immediately the best way to do it with the config (and validation), but if you want to keep options open switching this to something likelock: "config"
so that then you could add alock: "everything
option later would be an option.I also wasn't sure if the example line is supposed to be the default value or not.
A bool is fine for now, as far as I'm concerned.
example:
is not usually the default value. In fact it's often the opposite of the default value in that it's demonstrating how you would override the default if you are so inclined. Soexample: true
sounds right to me here, given that I'm assuming the default isfalse
(don't lock).