summaryrefslogtreecommitdiff
path: root/hosts/vidhar/borg/copy.py
diff options
context:
space:
mode:
Diffstat (limited to 'hosts/vidhar/borg/copy.py')
-rwxr-xr-xhosts/vidhar/borg/copy.py61
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
46borg_pwd = getpwnam('borg') 46borg_pwd = getpwnam('borg')
47 47
48def as_borg(caps=set(), newns=True): 48def 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']