|
| 1 | +import json |
| 2 | +import datetime |
| 3 | +import subprocess |
| 4 | + |
| 5 | + |
| 6 | +def main_block(namespace, pvc_name, pv): |
| 7 | + pool = pv['spec']['csi']['volumeAttributes']['pool'] |
| 8 | + image_name = pv['spec']['csi']['volumeAttributes']['imageName'] |
| 9 | + print(f'Pool: {pool}, Image name: {image_name}') |
| 10 | + backup_datestr = datetime.datetime.now().strftime('%Y%m%d%H%M%S') |
| 11 | + backup_name = f'hasadna-k8s-pvc-backup-{backup_datestr}' |
| 12 | + print(f'Backup name: {backup_name}') |
| 13 | + subprocess.check_call(['rbd', 'snap', 'create', f'{pool}/{image_name}@{backup_name}']) |
| 14 | + subprocess.check_call(['rbd', 'snap', 'protect', f'{pool}/{image_name}@{backup_name}']) |
| 15 | + device = subprocess.check_output(['rbd-nbd', 'map', f'{pool}/{image_name}@{backup_name}']).decode().strip() |
| 16 | + print(f'Device: {device}') |
| 17 | + subprocess.check_call(['mkdir', '-p', f'/tmp{device}']) |
| 18 | + subprocess.check_call(['mount', '-t', 'ext4', '-o', 'ro,noload', device, f'/tmp{device}']) |
| 19 | + kopia_snapshot_source = f'ceph@{namespace}:{pvc_name}' |
| 20 | + print(f'Creating Kopia snapshot with source {kopia_snapshot_source}...') |
| 21 | + subprocess.check_call(['kopia', 'snapshot', 'create', f'/tmp{device}', '--override-source', kopia_snapshot_source]) |
| 22 | + print("Kopia snapshot created successfully.") |
| 23 | + print('Unmounting and cleaning up...') |
| 24 | + subprocess.check_call(['umount', f'/tmp{device}']) |
| 25 | + subprocess.check_call(['rbd-nbd', 'unmap', device]) |
| 26 | + subprocess.check_call(['rbd', 'snap', 'unprotect', f'{pool}/{image_name}@{backup_name}']) |
| 27 | + subprocess.check_call(['rbd', 'snap', 'rm', f'{pool}/{image_name}@{backup_name}']) |
| 28 | + print('Backup completed successfully.') |
| 29 | + |
| 30 | + |
| 31 | +def main_shared(namespace, pvc_name, pv): |
| 32 | + pool = pv['spec']['csi']['volumeAttributes']['pool'] |
| 33 | + fs_name = pv['spec']['csi']['volumeAttributes']['fsName'] |
| 34 | + sub_volume_name = pv['spec']['csi']['volumeAttributes']['subVolumeName'] |
| 35 | + backup_datestr = datetime.datetime.now().strftime('%Y%m%d%H%M%S') |
| 36 | + backup_name = f'hasadna-k8s-pvc-backup-{backup_datestr}' |
| 37 | + print(f'Pool: {pool}, Filesystem name: {fs_name}, Subvolume name: {sub_volume_name}') |
| 38 | + print(f'Backup name: {backup_name}') |
| 39 | + subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'create', fs_name, sub_volume_name, backup_name, 'csi']) |
| 40 | + subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'clone', fs_name, sub_volume_name, backup_name, backup_name, pool, 'csi']) |
| 41 | + backup_path = subprocess.check_output(['ceph', 'fs', 'subvolume', 'getpath', fs_name, backup_name]).decode().strip() |
| 42 | + print(f'Backup path: {backup_path}') |
| 43 | + subprocess.check_call(['mkdir', '-p', f'/tmp{backup_path}']) |
| 44 | + subprocess.check_call(['ceph-fuse', f'/tmp{backup_path}', '--client-mountpoint', backup_path]) |
| 45 | + kopia_snapshot_source = f'ceph@{namespace}:{pvc_name}' |
| 46 | + print(f'Creating Kopia snapshot with source {kopia_snapshot_source}...') |
| 47 | + subprocess.check_call(['kopia', 'snapshot', 'create', f'/tmp{backup_path}', '--override-source', kopia_snapshot_source]) |
| 48 | + print("Kopia snapshot created successfully.") |
| 49 | + print('Unmounting and cleaning up...') |
| 50 | + subprocess.check_call(['umount', f'/tmp{backup_path}']) |
| 51 | + subprocess.check_call(['ceph', 'fs', 'subvolume', 'rm', fs_name, backup_name]) |
| 52 | + subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'rm', fs_name, sub_volume_name, backup_name, 'csi']) |
| 53 | + print('Backup completed successfully.') |
| 54 | + |
| 55 | + |
| 56 | +def main(namespace, pvc_name): |
| 57 | + print(f'Creating backup for PVC {pvc_name} in namespace {namespace}...') |
| 58 | + pvc = json.loads(subprocess.check_output([ |
| 59 | + 'kubectl', '-n', namespace, 'get', 'pvc', pvc_name, '-o', 'json' |
| 60 | + ])) |
| 61 | + storage_class_name = pvc['spec']['storageClassName'] |
| 62 | + volume_name = pvc['spec']['volumeName'] |
| 63 | + print(f'Volume name: {volume_name}') |
| 64 | + pv = json.loads(subprocess.check_output(['kubectl', 'get', 'pv', volume_name, '-o', 'json'])) |
| 65 | + if storage_class_name == 'rook-cephfs-shared': |
| 66 | + main_shared(namespace, pvc_name, pv) |
| 67 | + elif storage_class_name == 'rook-ceph-block': |
| 68 | + main_block(namespace, pvc_name, pv) |
0 commit comments