Hooks to mount/umount remote (e.g. NFS) folder containing the Borg repository? #657
Labels
No Label
bug
data loss
design finalized
good first issue
new feature area
question / support
security
waiting for response
No Milestone
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: borgmatic-collective/borgmatic#657
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What I'm trying to do and why
I am looking for a way to NFS-mount a remote folder containing the Borg repository prior to any Borg command being run by borgmatic.
The
before_actions
andafter_actions
hooks are great. I can test+mount in before and unmount in after:It works, except for the
borgmatic mount
command where theafter_actions
tries to unmount the remote folder borgmatic just accessed to open the Borg repository for borgfs.Issue #463 had interesting ideas with per-repository
mountcmd
/unmountcmd
options that could have been the solution to my issue.The solutions I can think of:
after_actions
: check any borgfs mount before umounting.Other notes / implementation ideas
If I opt for performing more checks during
after_actions
, having access via an environment variable to the complete executed borgmatic CLI command (e.g.BORGMATIC_COMMAND
containingborgmatic mount --mount-point /mnt/test
) or at least to the borgmatic action (eg.BORGMATIC_ACTION
containingmount
) in the hooks' commands would be great.Environment
borgmatic version: 1.7.4
borgmatic installation method: Debian package
Borg version: 1.1.16
Python version: 3.9.2
operating system and version: Debian 11 (Bullseye)
Thanks for taking the time to file this! It's helpful to see exactly the shell commands you're running from hooks.
Got it. Out of curiosity, is the
after_actions
unmount blowing up because the repository is still in use by theborg mount
? Or does it successfully unmount the repository and therefore the Borg-mounted directory stops working?I'm not sure that actually solves your issue, because if
mountcmd
andunmountcmd
for instance are run before/after all the actions for a given repository, that's identical to the existingbefore_actions
andafter_actions
. So presumably you'd have the exact same probably withmount
.. Although I suppose borgmatic could be smart enough not to run theunmountcmd
after anymount
action.Yeah, that seems like it'd be up to the user as to whether they'd want to set that up. I can see why you'd instead want everything contained in borgmatic's config file.
The main trick here is that there can be multiple actions at once. There is a single borgmatic command-line, of course, but it can contain multiple actions and their flags, and I'm not sure I'd expect a shell command to parse that.
BORGMATIC_ACTION
is interesting, and it'd be easier to parse for a shell command, although it'd of course have to beBORGMATIC_ACTIONS
to accommodate multiple. And instead of an environment variable, the convention is to use variable interpolation for passing borgmatic information to hook commands.Okay, so next steps. My inclination is to solve this requirement within borgmatic (or at least in borgmatic with some user configuration) rather than requiring ever more complex shell scripting. So at the risk of blowing up scope ... Imagine if all the
before_*
/after_*
hooks were replaced with something like this (inspired by #463 comments among others):This sort of structure could also replace any of the other command hooks. For instance, this might be a replacement for
before_check
:Or even combining hooks:
(One thing to work out for this last example is if it runs twice, once before
prune
and once beforecompact
—or if it just runs once before all actions if any of them arecompact
orprune
.)My attempt to check for a borgfs mount before trying to unmount my remote folder:
It should have worked but did not: When I run
borgmatic umount
, when theafter_actions
hook executes there is still a borgfs mount (according tofindmnt --type fuse --source borgfs
) :-/It looks like borgmatic calls
borg umount
(which effectively unmounts the Borg repository) after executing theafter_actions
hooks.In the end, I've found an ugly way of "scheduling" an unmount after borgmatic ends with:
Spoiler: it works ;)
(Saw your reply after I finished my tries and error)
Originally It was failing for
borgmatic mount
because the repository was intentionally still in use. I said it to highlight the limit of my first idea (where I thought I could wrap borgmatic actions with simplemount
andumount
).I was indeed counting on that: if I tell borgmatic how to mount/unmount the path of a repository, I trust him to do the mounting and unmounting when needed.
I must admit I overlooked the documentation and failed to notice the variable interpolation which could do just fine. I guess we could add a
action_name
(or similar) variable?Theses a great solutions! But I guess they require a lot of work.
I have no idea on how many people are having similar issues.
One reason I'm a little resistant to the mount/unmount command options is they'd only solve a subset of use cases and therefore could be confusing. For instance, there are use cases like yours around mounting repository directories. But there are also legitimate use cases around mounting source directories! (Or even, I suppose, mounting directories containing PostgreSQL client certificates.) I guess introducing options for each would be a possibility.
Or.. just adding an
action_names
interpolated variable (say, a comma-separated list of actions) could be a place to start. And I think it would be a fairly surgical change, unlike the giant hook refactor I was proposing above. (Although ultimately that may be a good idea.)Thoughts?
For a start the interpolated variable is fine start, it gives the user all the card to shape it's hooks commands for it's own use case without adding complexity to borgmatic.
Something like this?:
That totally works, but I think it could be simplified even further! Here's an example:
True 👍
I wanted to keep the
action_names
as a list as long as possible ;) (and my Python skills failed me for thekey for key in arguments.keys()
part too :P)Gotcha, that makes sense! Let me know if you want to take a stab at a PR (ideally with tests) or if you'd prefer me to take care of this. I'm totally fine either way.
Thanks, I'll try to submit a PR with tests.
Well, here goes my PR: #695 (hope it will pass the quality check ;))
Closing this for now due to inactivity, but I'd be happy to revisit this if you're game!