|
1 | | -from os import fsync |
| 1 | +import os |
2 | 2 | from pathlib import Path |
3 | 3 | import time |
4 | 4 | from dataclasses import dataclass |
| 5 | +import consts |
5 | 6 | from utils.commands import run |
6 | 7 | from config import config |
7 | 8 | from utils.errors import FsFreezeNotSupportedOnBlockVolumes, SnapshotCreateVolumeInUse |
8 | 9 | from utils.lock import VolLock |
9 | 10 | from utils.rawfile import ( |
10 | 11 | attached_loops, |
11 | 12 | img_file, |
| 13 | + is_cow_supported, |
12 | 14 | metadata, |
13 | | - patch_metadata, |
14 | 15 | snapshots_dir, |
15 | 16 | ) |
16 | 17 | from glob import glob |
@@ -72,15 +73,6 @@ def create_snapshot( |
72 | 73 |
|
73 | 74 | creation_time = time.time() |
74 | 75 | Path(f"{snap_path}.creating").unlink(missing_ok=True) |
75 | | - meta = metadata(volume_id) |
76 | | - reflink_attached = list(set(meta.get("reflink_attached", []))) |
77 | | - if copy_on_write: |
78 | | - reflink_attached.append(name) |
79 | | - patch_metadata( |
80 | | - volume_id, |
81 | | - meta.get("storage_pool", config.csi_driver.default_pool), |
82 | | - {"reflink_attached": reflink_attached}, |
83 | | - ) |
84 | 76 | return Snapshot( |
85 | 77 | name=name, |
86 | 78 | volume_id=volume_id, |
@@ -110,30 +102,26 @@ def delete_snapshot(self, volume_id: str, name: str, temporary: bool = False): |
110 | 102 | Path(f"{snap_path}.creating"), |
111 | 103 | ): |
112 | 104 | path.unlink(missing_ok=True) |
113 | | - meta = metadata(volume_id) |
114 | | - reflink_attached = list(set(meta.get("reflink_attached", []))) |
115 | | - if name in reflink_attached: |
116 | | - reflink_attached.remove(name) |
117 | | - patch_metadata( |
118 | | - volume_id, |
119 | | - meta["storage_pool"], |
120 | | - {"reflink_attached": reflink_attached}, |
121 | | - ) |
122 | 105 |
|
123 | 106 | def restore_snapshot( |
124 | 107 | self, volume_id: str, name: str, destination: Path, temporary: bool = False |
125 | 108 | ): |
126 | 109 | """Restore a snapshot""" |
127 | | - chunk_size = 1024 * 1024 |
| 110 | + volume_meta = metadata(volume_id) |
128 | 111 | snap_path = self._get_snapshot_path(volume_id, name, temporary) |
129 | | - with open(snap_path, "rb") as src, open(destination, "wb") as dst: |
130 | | - while True: |
131 | | - buf = src.read(chunk_size) |
132 | | - if not buf: |
133 | | - break |
134 | | - dst.write(buf) |
135 | | - dst.flush() |
136 | | - fsync(dst.fileno()) |
| 112 | + copy_on_write_param = volume_meta.get("copy_on_write", None) |
| 113 | + copy_on_write = ( |
| 114 | + copy_on_write_param |
| 115 | + if copy_on_write_param is not None |
| 116 | + else consts.COW_SUPPORT_MAP.get( |
| 117 | + volume_meta.get("storage_pool", None), False |
| 118 | + ) |
| 119 | + ) and is_cow_supported(Path(os.path.dirname(snap_path)), destination) |
| 120 | + reflink = "always" if copy_on_write else "never" |
| 121 | + cmd = ( |
| 122 | + f"cp --sparse=auto --reflink={reflink} {snap_path} {destination.as_posix()}" |
| 123 | + ) |
| 124 | + run(cmd, check=True) |
137 | 125 |
|
138 | 126 | def list_snapshots( |
139 | 127 | self, |
|
0 commit comments