diff options
Diffstat (limited to 'hosts/vidhar/borg')
| -rwxr-xr-x | hosts/vidhar/borg/copy.py | 61 |
1 files changed, 30 insertions, 31 deletions
diff --git a/hosts/vidhar/borg/copy.py b/hosts/vidhar/borg/copy.py index 168fa967..df77e4bb 100755 --- a/hosts/vidhar/borg/copy.py +++ b/hosts/vidhar/borg/copy.py | |||
| @@ -45,14 +45,14 @@ halo_args = { | |||
| 45 | 45 | ||
| 46 | borg_pwd = getpwnam('borg') | 46 | borg_pwd = getpwnam('borg') |
| 47 | 47 | ||
| 48 | def as_borg(caps=set(), newns=True): | 48 | def as_borg(caps=set(), withns=lambda: pass): |
| 49 | if caps: | 49 | if caps: |
| 50 | for capset in [cap_permitted, cap_inheritable, cap_effective, cap_ambient]: | 50 | for capset in [cap_permitted, cap_inheritable, cap_effective, cap_ambient]: |
| 51 | capset.add(*caps) | 51 | capset.add(*caps) |
| 52 | 52 | ||
| 53 | if newns: | 53 | unshare.unshare(unshare.CLONE_NEWNS) |
| 54 | unshare.unshare(unshare.CLONE_NEWNS) | 54 | subprocess.run(['mount', '--make-rprivate', '/'], check=True) |
| 55 | subprocess.run(['mount', '--make-rprivate', '/'], check=True) | 55 | withns() |
| 56 | if os.environ.get('CREDENTIALS_DIRECTORY'): | 56 | if os.environ.get('CREDENTIALS_DIRECTORY'): |
| 57 | creds_path = pathlib.Path(os.environ['CREDENTIALS_DIRECTORY']).relative_to('/') | 57 | creds_path = pathlib.Path(os.environ['CREDENTIALS_DIRECTORY']).relative_to('/') |
| 58 | subprocess.run(['bindfs', '-r', f'--force-user={borg_pwd.pw_uid}', f'--force-group={borg_pwd.pw_gid}', pathlib.Path('/') / creds_path, chroot / creds_path], check=True) | 58 | subprocess.run(['bindfs', '-r', f'--force-user={borg_pwd.pw_uid}', f'--force-group={borg_pwd.pw_gid}', pathlib.Path('/') / creds_path, chroot / creds_path], check=True) |
| @@ -114,34 +114,33 @@ def copy_archive(src_repo_path, dst_repo_path, entry): | |||
| 114 | dir = pathlib.Path('/borg') | 114 | dir = pathlib.Path('/borg') |
| 115 | 115 | ||
| 116 | def preexec_fn(): | 116 | def preexec_fn(): |
| 117 | # print('unshare/chroot', file=stderr) | 117 | def withns(): |
| 118 | unshare.unshare(unshare.CLONE_NEWNS) | 118 | chroot = pathlib.Path(tmpdir) / 'chroot' |
| 119 | subprocess.run(['mount', '--make-rprivate', '/'], check=True) | 119 | upper = pathlib.Path(tmpdir) / 'upper' |
| 120 | chroot = pathlib.Path(tmpdir) / 'chroot' | 120 | work = pathlib.Path(tmpdir) / 'work' |
| 121 | upper = pathlib.Path(tmpdir) / 'upper' | 121 | for path in [chroot,upper,work]: |
| 122 | work = pathlib.Path(tmpdir) / 'work' | 122 | path.mkdir() |
| 123 | for path in [chroot,upper,work]: | 123 | subprocess.run(['mount', '-t', 'overlay', 'overlay', '-o', f'lowerdir=/,upperdir={upper},workdir={work}', chroot], check=True) |
| 124 | path.mkdir() | 124 | bindMounts = ['nix', 'run', 'proc', 'dev', 'sys', pathlib.Path(os.path.expanduser('~')).relative_to('/')] |
| 125 | subprocess.run(['mount', '-t', 'overlay', 'overlay', '-o', f'lowerdir=/,upperdir={upper},workdir={work}', chroot], check=True) | 125 | if os.environ.get('BORG_BASE_DIR'): |
| 126 | bindMounts = ['nix', 'run', 'proc', 'dev', 'sys', pathlib.Path(os.path.expanduser('~')).relative_to('/')] | 126 | bindMounts.append(pathlib.Path(os.environ['BORG_BASE_DIR']).relative_to('/')) |
| 127 | if os.environ.get('BORG_BASE_DIR'): | 127 | if not ":" in src_repo_path: |
| 128 | bindMounts.append(pathlib.Path(os.environ['BORG_BASE_DIR']).relative_to('/')) | 128 | bindMounts.append(pathlib.Path(src_repo_path).relative_to('/')) |
| 129 | if not ":" in src_repo_path: | 129 | if 'SSH_AUTH_SOCK' in os.environ: |
| 130 | bindMounts.append(pathlib.Path(src_repo_path).relative_to('/')) | 130 | bindMounts.append(pathlib.Path(os.environ['SSH_AUTH_SOCK']).parent.relative_to('/')) |
| 131 | if 'SSH_AUTH_SOCK' in os.environ: | 131 | for bindMount in bindMounts: |
| 132 | bindMounts.append(pathlib.Path(os.environ['SSH_AUTH_SOCK']).parent.relative_to('/')) | 132 | (chroot / bindMount).mkdir(parents=True,exist_ok=True) |
| 133 | for bindMount in bindMounts: | 133 | # print(*['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], file=stderr) |
| 134 | (chroot / bindMount).mkdir(parents=True,exist_ok=True) | 134 | subprocess.run(['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], check=True) |
| 135 | # print(*['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], file=stderr) | 135 | os.chroot(chroot) |
| 136 | subprocess.run(['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], check=True) | 136 | os.chdir('/') |
| 137 | os.chroot(chroot) | 137 | dir.mkdir(parents=True,exist_ok=True,mode=750) |
| 138 | os.chdir('/') | 138 | os.chown(dir, borg_pwd.pw_uid, borg_pwd.pw_gid) |
| 139 | dir.mkdir(parents=True,exist_ok=True,mode=750) | 139 | as_borg(withns=withns, caps={Cap.DAC_READ_SEARCH}) |
| 140 | os.chown(dir, borg_pwd.pw_uid, borg_pwd.pw_gid) | 140 | |
| 141 | as_borg(newns=False, caps={Cap.DAC_READ_SEARCH}) | 141 | total_size = None |
| 142 | total_files = None | ||
| 142 | with Halo(text=f'Determine size', **halo_args) as sp: | 143 | with Halo(text=f'Determine size', **halo_args) as sp: |
| 143 | total_size = None | ||
| 144 | total_files = None | ||
| 145 | with subprocess.Popen(['borg', 'info', '--info', '--json', '--lock-wait=600', f'{src_repo_path}::{entry["name"]}'], stdout=subprocess.PIPE, text=True, preexec_fn=lambda: as_borg()) as proc: | 144 | with subprocess.Popen(['borg', 'info', '--info', '--json', '--lock-wait=600', f'{src_repo_path}::{entry["name"]}'], stdout=subprocess.PIPE, text=True, preexec_fn=lambda: as_borg()) as proc: |
| 146 | stats = json.load(proc.stdout)['archives'][0]['stats'] | 145 | stats = json.load(proc.stdout)['archives'][0]['stats'] |
| 147 | total_size = stats['original_size'] | 146 | total_size = stats['original_size'] |
