summaryrefslogtreecommitdiff
path: root/lbup
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2023-10-12 19:07:02 +0200
committerAnton Khirnov <anton@khirnov.net>2023-10-12 19:10:07 +0200
commitb877c3546f5e523df641e3d237cde34c31265c51 (patch)
treeb917a5eb899359d0e5a3542dee7a9a16584140e1 /lbup
parentdc52f123745748ee61e894fe36eeca1788fc4ed8 (diff)
targets: remove TargetSSHLXCLVM
It is complex and fragile and has been replaced by idmapping/TargetSSHLVM/strip_mountpoint=True. Also drop nsmount.c, which was to be used with this target.
Diffstat (limited to 'lbup')
-rw-r--r--lbup/targets.py105
1 files changed, 5 insertions, 100 deletions
diff --git a/lbup/targets.py b/lbup/targets.py
index 37a58f0..d6d44ff 100644
--- a/lbup/targets.py
+++ b/lbup/targets.py
@@ -241,11 +241,6 @@ class TargetSSHLVM(TargetSSH):
"""
_snapshot_size = None
- """
- PID of the process whose mount namespace we use.
- """
- _mntns_pid = None
-
_strip_mountpoint = None
def __init__(self, name, dirs, excludes = None, logger = None,
@@ -259,22 +254,6 @@ class TargetSSHLVM(TargetSSH):
def __str__(self):
return "%s{LVM:%s}" % (super().__str__(), self._snapshot_size)
- def _root_remote(self):
- """
- The the remote for root operations, such as manipulating LVM.
-
- Overridden in subclasses.
- """
- return SSHRemote(self._remote.host, self._remote.port,
- 'root', self._remote.proxy_remote)
-
- def _resolve_mntns(self, ssh):
- """
- Get the PID of the process whose mount namespace we use.
- Always 1 here, overridden in subclasses.
- """
- return 1
-
def _resolve_lv(self, ssh, devnum):
"""
Find the logical volume for the given device number.
@@ -347,8 +326,11 @@ class TargetSSHLVM(TargetSSH):
def save(self, dry_run = False):
with contextlib.ExitStack() as stack:
+ root_remote = SSHRemote(self._remote.host, self._remote.port,
+ 'root', self._remote.proxy_remote)
+
conn_tgt = stack.enter_context(_ssh_client.SSHConnection(self._remote))
- conn_root = stack.enter_context(_ssh_client.SSHConnection(self._root_remote()))
+ conn_root = stack.enter_context(_ssh_client.SSHConnection(root_remote))
# resolve the remote paths
bupdir = self._resolve_remote_path(conn_tgt, self._remote_bupdir)
@@ -362,12 +344,9 @@ class TargetSSHLVM(TargetSSH):
snapshot_mount = '%s/%s' % (bupdir, 'lbup_mount')
self._paramiko_exec_cmd(conn_tgt, 'mkdir -p -m 700 ' + snapshot_mount)
- self._mntns_pid = self._resolve_mntns(conn_root)
-
# read and parse the mountinfo table
mntinfo = MountInfo(
- self._paramiko_exec_cmd(conn_root, 'cat /proc/%d/mountinfo' % self._mntns_pid,
- decode = False))
+ self._paramiko_exec_cmd(conn_root, 'cat /proc/1/mountinfo', decode = False))
devnum, mountpoint, fstype = _resolve_mntdev(mntinfo, dirs)
@@ -392,77 +371,3 @@ class TargetSSHLVM(TargetSSH):
return self._do_save(bup_exec, dry_run,
dirs = dirs, excludes = excludes,
save_opts = save_opts, index_opts = index_opts)
-
-class TargetSSHLXCLVM(TargetSSHLVM):
- """
- This target backs up an LXC container that lives on its own LVM logical
- volume. Requires root-capable login on the container's host.
-
- :param SSHRemote parent_remote:
- """
- # The container is treated as untrusted, so all code here needs to be
- # careful to avoid giving it access to anything it would not have otherwise.
- # Specifically, any information obtained by running binaries in the
- # container should be assumed to have been potentially maliciously
- # manipulated. No binaries from the container should be run as the (host) root.
- _parent_remote = None
- _lxc_username = None
- _lxc_containername = None
-
- def __init__(self, name, dirs, excludes = None, logger = None,
- target_remote = None, target_remote_bupdir = None,
- parent_remote = None,
- lxc_username = None, lxc_containername = None,
- snapshot_size = '20G'):
- if parent_remote is None:
- raise ValueError('parent_remote not specified')
- if lxc_username is None:
- lxc_username = parent_remote.usename
-
- self._parent_remote = parent_remote
- self._lxc_username = lxc_username
- self._lxc_containername = lxc_containername
-
- super().__init__(name, dirs, excludes, logger,
- target_remote, target_remote_bupdir,
- snapshot_size)
-
- def __str__(self):
- return "%s{LXC:%s/%s@[%s]}{LVM:%s}" % (super().__str__(), self._lxc_containername,
- self._lxc_username, str(self._parent_remote), self._snapshot_size)
-
- def _resolve_mntns(self, ssh):
- # get the PID of the container's init
- cmd = 'su -s /bin/sh -c "lxc-info -H -p -n {container}" {user}'.format(
- container = self._lxc_containername, user = self._lxc_username)
- container_pid = self._paramiko_exec_cmd(ssh, cmd).rstrip('\n')
- return int(container_pid)
-
- def _root_remote(self):
- return self._parent_remote
-
- @contextlib.contextmanager
- def _mount_snapshot(self, ssh, devnum, mount_path, 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 = self._mntns_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 = self._mntns_pid, mount_path = mount_path))