summaryrefslogtreecommitdiff
path: root/lbup
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2020-10-20 11:18:45 +0200
committerAnton Khirnov <anton@khirnov.net>2020-10-20 11:18:45 +0200
commit1a6e05e609b1ef45bdde97fcaf3944fc2824fd40 (patch)
tree506c1f7e61a1c165a9f023e3b67f292fd643a723 /lbup
parent5ea14e4a132788472205f66be68ad1540ad56243 (diff)
TargetSSHLXCLVM: factor creating+mounting the snapshot
Make it into its own context manager, similar to TargetSSHLVM. This is easier to follow and will allow to share more code in the future.
Diffstat (limited to 'lbup')
-rw-r--r--lbup/targets.py55
1 files changed, 31 insertions, 24 deletions
diff --git a/lbup/targets.py b/lbup/targets.py
index 8b90188..7f85526 100644
--- a/lbup/targets.py
+++ b/lbup/targets.py
@@ -396,6 +396,32 @@ class TargetSSHLXCLVM(TargetSSHLVM):
return "%s{LXC:%s/%s@[%s]}{LVM:%s}" % (super().__str__(), self._lxc_containername,
self._lxc_username, str(self._parent_remote), self._snapshot_size)
+ @contextlib.contextmanager
+ def _nsmount_snapshot(self, ssh, devnum, mount_path, container_pid, fstype):
+ """
+ Return a context manager that creates a read-only LVM snapshot
+ for the specified LV device number and mounts it at mount_path
+ inside the container, then unmounts and destroys it at exit.
+ """
+ with self._snapshot_lv(ssh, devnum) as lv_path:
+ # we cannot trust any binaries located inside the container, since a
+ # compromised container could use them to execute arbitrary code
+ # with real root privileges, thus nullifying the point of
+ # unprivileged containers)
+ # so we ship a special tool, 'nsmount', which has to be
+ # installed on the parent, to mount the snapshot into the
+ # container mount namespace
+ self._paramiko_exec_cmd(ssh,
+ 'nsmount m {pid} {mount_path} {lv_path} {fstype}'.format(
+ pid = container_pid, mount_path = mount_path,
+ lv_path = lv_path, fstype = fstype))
+ try:
+ yield None
+ finally:
+ self._paramiko_exec_cmd(ssh,
+ 'nsmount u {pid} {mount_path}'.format(
+ pid = container_pid, mount_path = mount_path))
+
def save(self, dry_run = False):
with contextlib.ExitStack() as stack:
parent = stack.enter_context(_ssh_client.SSHConnection(self._parent_remote))
@@ -433,33 +459,14 @@ class TargetSSHLXCLVM(TargetSSHLVM):
self._logger.debug('Backup targets are at device %s(%s), mounted at %s',
"%d:%d" % (lv_devnum >> 8, lv_devnum & 255), lv_fstype, lv_mountpoint)
- snapshot_path = stack.enter_context(self._snapshot_lv(parent, lv_devnum))
+ stack.enter_context(self._nsmount_snapshot(parent, lv_devnum, container_mountpoint,
+ container_pid, lv_fstype))
# execute the backup
-
- # we cannot trust any binaries located inside the container, since a
- # compromised container could use them to execute arbitrary code
- # with real root privileges, thus nullifying the point of
- # unprivileged containers)
- # so we ship a special tool, 'nsmount', which has to be
- # installed on the parent, to mount the snapshot into the
- # container mount namespace
- self._paramiko_exec_cmd(parent,
- 'nsmount m {pid} {mountpoint} {devpath} {fstype}'.format(
- pid = container_pid, mountpoint = container_mountpoint,
- devpath = snapshot_path, fstype = lv_fstype))
-
bup_exec = ['bup', 'on', '%s@%s' % (self._remote.username, self._remote.host),
'-d', container_bupdir]
save_opts = ['--graft=%s=%s' % (container_mountpoint, lv_mountpoint)]
reparent = (lv_mountpoint, AbsPath(container_mountpoint))
- try:
- ret = self._do_save(bup_exec, dry_run,
- reparent = reparent,
- save_opts = save_opts, index_opts = ['--no-check-device'])
- finally:
- self._paramiko_exec_cmd(parent,
- 'nsmount u {pid} {mountpoint}'.format(
- pid = container_pid, mountpoint = container_mountpoint))
-
- return ret
+ return self._do_save(bup_exec, dry_run,
+ reparent = reparent,
+ save_opts = save_opts, index_opts = ['--no-check-device'])