summaryrefslogtreecommitdiff
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
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.
-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'])