|
3 | 3 | import json |
4 | 4 | import datetime |
5 | 5 | import subprocess |
| 6 | +from glob import iglob |
6 | 7 |
|
7 | 8 |
|
8 | 9 | CEPH_BACKUPS_HEARTBEAT_URL = os.getenv('CEPH_BACKUPS_HEARTBEAT_URL') |
@@ -43,39 +44,32 @@ def main_shared(namespace, pvc_name, pv): |
43 | 44 | pool = pv['spec']['csi']['volumeAttributes']['pool'] |
44 | 45 | fs_name = pv['spec']['csi']['volumeAttributes']['fsName'] |
45 | 46 | sub_volume_name = pv['spec']['csi']['volumeAttributes']['subvolumeName'] |
| 47 | + sub_volume_path = pv['spec']['csi']['volumeAttributes']['subvolumePath'] |
| 48 | + group_name = 'csi' |
| 49 | + print(f'Pool: {pool}, Filesystem name: {fs_name}, Subvolume name: {sub_volume_name}, Group name: {group_name}') |
| 50 | + print(f'Subvolume path: {sub_volume_path}') |
46 | 51 | backup_datestr = datetime.datetime.now().strftime('%Y%m%d%H%M%S') |
47 | 52 | backup_name = f'hasadna-k8s-pvc-backup-{backup_datestr}' |
48 | | - clone_name = f'hasadna-k8s-pvc-backup-{sub_volume_name}-{backup_datestr}' |
49 | | - print(f'Pool: {pool}, Filesystem name: {fs_name}, Subvolume name: {sub_volume_name}') |
50 | 53 | print(f'Backup name: {backup_name}') |
51 | | - print(f'Clone name: {clone_name}') |
52 | 54 | subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'create', fs_name, sub_volume_name, backup_name, 'csi']) |
53 | | - subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'clone', fs_name, sub_volume_name, backup_name, clone_name, pool, 'csi']) |
54 | | - i = 0 |
55 | | - while True: |
56 | | - time.sleep(60) |
57 | | - i += 1 |
58 | | - status, output = subprocess.getstatusoutput(f'ceph fs clone status {fs_name} {clone_name}') |
59 | | - if status == 0: |
60 | | - if json.loads(output).get('status', {}).get('state', '') == 'complete': |
61 | | - print(output) |
62 | | - break |
63 | | - else: |
64 | | - print(f'Error checking clone status (exit code {status}): {output}') |
65 | | - assert i < 120, f'Clone {clone_name} did not complete within 2 hours.' |
66 | | - backup_path = subprocess.check_output(['ceph', 'fs', 'subvolume', 'getpath', fs_name, clone_name]).decode().strip() |
67 | | - print(f'Backup path: {backup_path}') |
68 | | - subprocess.check_call(['mkdir', '-p', f'/tmp{backup_path}']) |
69 | | - subprocess.check_call(['ceph-fuse', f'/tmp{backup_path}', '--client-mountpoint', backup_path]) |
70 | | - kopia_snapshot_source = f'ceph@{namespace}:{pvc_name}' |
71 | | - print(f'Creating Kopia snapshot with source {kopia_snapshot_source}...') |
72 | | - subprocess.check_call(['kopia', 'snapshot', 'create', f'/tmp{backup_path}', '--override-source', kopia_snapshot_source]) |
73 | | - print("Kopia snapshot created successfully.") |
74 | | - print('Unmounting and cleaning up...') |
75 | | - subprocess.check_call(['umount', f'/tmp{backup_path}']) |
76 | | - subprocess.check_call(['ceph', 'fs', 'subvolume', 'rm', fs_name, clone_name]) |
77 | | - subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'rm', fs_name, sub_volume_name, backup_name, 'csi']) |
78 | | - print('Backup completed successfully.') |
| 55 | + try: |
| 56 | + os.mkdir('/mnt/ceph') |
| 57 | + subprocess.check_call(['ceph-fuse', '/mnt/ceph']) |
| 58 | + try: |
| 59 | + paths = [path for path in iglob(os.path.join('/mnt/ceph', sub_volume_path, '.snap/*')) if backup_name in os.path.basename(path)] |
| 60 | + assert len(paths) == 1, f"Expected exactly one snapshot path for {backup_name}, found {len(paths)}" |
| 61 | + path = paths[0] |
| 62 | + print(f'snapshot path: {path}') |
| 63 | + kopia_snapshot_source = f'ceph@{namespace}:{pvc_name}' |
| 64 | + print(f'Creating Kopia snapshot with source {kopia_snapshot_source}...') |
| 65 | + subprocess.check_call(['kopia', 'snapshot', 'create', path, '--override-source', kopia_snapshot_source]) |
| 66 | + print("Kopia snapshot created successfully.") |
| 67 | + finally: |
| 68 | + if subprocess.call(['umount', '/mnt/ceph']) != 0: |
| 69 | + print(f"ERROR! Failed to unmount /mnt/ceph after creating snapshot {backup_name} for namespace '{namespace}', pvc '{pvc_name}'") |
| 70 | + finally: |
| 71 | + if subprocess.call(['ceph', 'fs', 'subvolume', 'snapshot', 'rm', fs_name, sub_volume_name, backup_name, 'csi']) != 0: |
| 72 | + print(f"ERROR! Failed to remove snapshot {backup_name} for namespace '{namespace}', pvc '{pvc_name}'") |
79 | 73 |
|
80 | 74 |
|
81 | 75 | def main_pvc(namespace, pvc_name, pvc): |
|
0 commit comments