Skip to content

Commit 10655d1

Browse files
committed
fix(FileSR): snapshot from src instead of src's parent in vdi_revert
Signed-off-by: Antoine Bartuccio <antoine.bartuccio@vates.tech>
1 parent 78560d5 commit 10655d1

2 files changed

Lines changed: 83 additions & 79 deletions

File tree

drivers/FileSR.py

Lines changed: 82 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,23 @@ def from_dict(cls, data: Dict[str, str]) -> "RevertLogDestinationVDI":
107107

108108

109109
class RevertLogSourceVDI:
110-
def __init__(self, uuid: str, parent_path: str):
110+
def __init__(self, uuid: str, path: str, parent_path: str):
111111
self.uuid = uuid
112+
self.path = path
112113
self.parent_path = parent_path
113114

114115
def to_dict(self) -> Dict[str, Collection[str]]:
115116
return {
116117
"uuid": self.uuid,
118+
"path": self.path,
117119
"parent_path": self.parent_path,
118120
}
119121

120122
@classmethod
121123
def from_dict(cls, data: Dict[str, str]) -> "RevertLogSourceVDI":
122124
return cls(
123125
uuid=data["uuid"],
126+
path=data["path"],
124127
parent_path=data["parent_path"],
125128
)
126129

@@ -152,7 +155,7 @@ def __init__(
152155
self,
153156
dest: RevertLogDestinationVDI,
154157
src: RevertLogSourceVDI,
155-
inserted: Optional[RevertLogInsertedVDI],
158+
inserted: RevertLogInsertedVDI,
156159
):
157160
self.dest = dest
158161
self.src = src
@@ -163,7 +166,7 @@ def to_dict(self) -> Dict[str, Collection[str]]:
163166
return {
164167
"dest": self.dest.to_dict(),
165168
"src": self.src.to_dict(),
166-
"inserted": self.inserted.to_dict() if self.inserted else ""
169+
"inserted": self.inserted.to_dict(),
167170
}
168171

169172
@override
@@ -173,8 +176,6 @@ def from_dict(cls, data: Dict[str, Union[Dict[str, str], str]]) -> "RevertLogEnt
173176
dest=RevertLogDestinationVDI.from_dict(data["dest"]), # type: ignore # Version checked
174177
src=RevertLogSourceVDI.from_dict(data["src"]), # type: ignore # Version checked
175178
inserted=RevertLogInsertedVDI.from_dict(data["inserted"]) #type: ignore # Version checked
176-
if data["inserted"]
177-
else None,
178179
)
179180

180181

@@ -520,23 +521,25 @@ def _rollback_revert_vdi(self, entry: RevertLogEntry):
520521
dest._db_update()
521522
self.added_vdi(dest)
522523

524+
util.SMlog(f"Restoring src vdi {entry.src.uuid}")
525+
if not util.ioretry(lambda: util.pathexists(entry.src.path)):
526+
util.SMlog(f"Restoring src vdi {entry.src.uuid} from {entry.inserted.uuid}")
527+
dest._rename(entry.inserted.path, entry.src.path)
528+
529+
util.SMlog(f"Restoring parent {entry.src.parent_path} to {entry.src.uuid}")
530+
dest.cowutil.setParent(entry.src.path, entry.src.parent_path, False)
531+
dest.cowutil.setHidden(entry.src.path, False)
532+
523533
src: "FileVDI" = self.vdi(entry.src.uuid) # type: ignore[assignment]
524534
src.sm_config = src.session.xenapi.VDI.get_sm_config(src.session.xenapi.VDI.get_by_uuid(src.uuid))
525-
src.cowutil.setParent(str(src.path), entry.src.parent_path, False)
526535
src.load_from_file(str(src.path))
527536
src._db_update()
528537

529-
if not entry.inserted:
530-
util.SMlog(f"No inserted vdi for {entry.dest.uuid}")
531-
return
538+
self.added_vdi(src)
532539

533-
try:
534-
inserted: "FileVDI" = self.vdi(entry.inserted.uuid) # type: ignore[assignment]
535-
except Exception:
536-
self._unlink_paths(entry.inserted.path)
537-
return
538-
539-
inserted.delete(inserted.sr.uuid, inserted.uuid)
540+
util.SMlog(f"Removing inserted VDI {entry.inserted.uuid}")
541+
self._unlink_paths(entry.inserted.path)
542+
self.deleted_vdi(entry.inserted.uuid)
540543

541544

542545
def _unlink_paths(self, *files: Union[Path, str]):
@@ -974,111 +977,111 @@ def _do_revert(
974977
raise xs_errors.XenError("Not implemented yet")
975978

976979
with self.tap_pause(), dest.tap_pause():
977-
self._revert(dest, self.parent == dest.parent, cbtlog, cbt_consistency_state)
980+
self._revert(dest, cbtlog, cbt_consistency_state)
978981

979982
def _revert(
980983
self,
981984
dest: "FileVDI",
982-
has_same_parents: bool,
983985
cbtlog: Optional[str],
984986
cbt_consistency_state: bool,
985987
):
986988
"""This assumes that self and dest VDIs has been paused"""
987-
dest_tmp_uuid = util.gen_uuid() # Will be replaced by dest.uuid at the end
988-
dest_tmp_path = os.path.join(dest.sr.path, f"{dest_tmp_uuid}{VDI_TYPE_TO_EXTENSION[dest.vdi_type]}.tmp")
989989

990-
dest_backup_path = os.path.join(dest.sr.path, f"{util.gen_uuid()}{VDI_TYPE_TO_EXTENSION[dest.vdi_type]}.back")
990+
self._ensure_not_max_depth()
991991

992-
src_parent = self.sr.vdi(self.parent)
993-
src_parent.sm_config = src_parent.session.xenapi.VDI.get_sm_config(
994-
src_parent.session.xenapi.VDI.get_by_uuid(src_parent.uuid)
992+
src_parent_path = os.path.join(
993+
self.sr.path, f"{self.parent}{VDI_TYPE_TO_EXTENSION[self.vdi_type]}"
995994
)
996995

997-
base_copy_uuid = None
998-
base_copy_path = None
999-
if not has_same_parents:
1000-
self._ensure_not_max_depth()
996+
dest_tmp_uuid = util.gen_uuid() # Will be replaced by dest.uuid at the end
997+
dest_tmp_path = os.path.join(
998+
dest.sr.path, f"{dest_tmp_uuid}{VDI_TYPE_TO_EXTENSION[dest.vdi_type]}.tmp"
999+
)
10011000

1002-
base_copy_uuid = util.gen_uuid()
1003-
base_copy_path = os.path.join(
1004-
src_parent.sr.path,
1005-
"%s%s" % (base_copy_uuid, VDI_TYPE_TO_EXTENSION[src_parent.vdi_type])
1006-
)
1001+
dest_backup_path = os.path.join(
1002+
dest.sr.path,
1003+
f"{util.gen_uuid()}{VDI_TYPE_TO_EXTENSION[dest.vdi_type]}.back",
1004+
)
1005+
1006+
inserted_uuid = util.gen_uuid()
1007+
inserted_path = os.path.join(
1008+
dest.sr.path, f"{inserted_uuid}{VDI_TYPE_TO_EXTENSION[dest.vdi_type]}"
1009+
)
10071010

10081011
log_entry = RevertLogEntry(
10091012
dest=RevertLogDestinationVDI(
10101013
dest.uuid, dest.path, dest_backup_path, dest_tmp_path
10111014
),
1012-
src=RevertLogSourceVDI(self.uuid, src_parent.path),
1013-
inserted=RevertLogInsertedVDI(base_copy_uuid, base_copy_path)
1014-
if base_copy_uuid and base_copy_path
1015-
else None,
1015+
src=RevertLogSourceVDI(self.uuid, self.path, src_parent_path),
1016+
inserted=RevertLogInsertedVDI(inserted_uuid, inserted_path),
10161017
)
10171018
journal_id, journal_content = log_entry.to_journal()
10181019
self.sr.journaler.create(log_entry.JRN_KEY, journal_id, journal_content)
10191020

1020-
# Change destination content
10211021
## First move the old vdi to a backup location to allow rolling back
10221022
## This has to be done first because it's used as a signal to the rollback
10231023
## algorithm to know if there is cleanup work to do
1024-
util.ioretry(lambda: self._rename(dest.path, dest_backup_path),
1025-
errlist=[errno.EIO, errno.EACCES])
1024+
util.ioretry(
1025+
lambda: self._rename(dest.path, dest_backup_path),
1026+
errlist=[errno.EIO, errno.EACCES],
1027+
)
10261028

1027-
if not has_same_parents:
1028-
# Create a base copy to attach both the src snapshot and the new destination
1029-
# This is mandatory to prevent the GC from coalescing everything
1030-
util.fistpoint.activate_custom_fn(
1031-
"FileSR_revert_insert",
1032-
self.__fist_enospace)
1033-
util.ioretry(lambda: self._snap(base_copy_path, src_parent.path, False))
1029+
# Transform src into inserted
1030+
self._rename(self.path, inserted_path)
1031+
1032+
# Create inserted base copy
1033+
util.ioretry(
1034+
lambda: self._snap(
1035+
self.path,
1036+
inserted_path,
1037+
False,
1038+
)
1039+
)
1040+
util.fistpoint.activate_custom_fn("FileSR_revert_insert", self.__fist_enospace)
1041+
1042+
inserted = FileVDI(self.sr, inserted_uuid)
1043+
1044+
inserted.label = "base copy"
1045+
inserted.read_only = True
1046+
inserted.location = inserted_uuid
1047+
inserted.sm_config = {}
1048+
inserted.sm_config["image-format"] = getImageStringFromVdiType(self.vdi_type)
1049+
if "key_hash" in self.sm_config:
1050+
inserted.sm_config["key_hash"] = self.sm_config["key_hash"]
1051+
inserted.cbt_enabled = bool(cbtlog)
10341052

1035-
## Protect the new parent from being coalesced by the GC
1036-
self.cowutil.setHidden(str(base_copy_path), False)
1053+
inserted._db_introduce()
10371054

1038-
## Attach src snapshot to it's new parent
1039-
self.cowutil.setParent(str(self.path), str(base_copy_path), False)
1055+
# Update src
1056+
self.load_from_file(self.path)
1057+
self._db_update()
10401058

1041-
## Create snapshot
1042-
actual_parent_path = base_copy_path if base_copy_path else src_parent.path
1059+
# Create tmp snapshot for dest
10431060
util.ioretry(
10441061
lambda: self._snap(
10451062
dest_tmp_path,
1046-
actual_parent_path,
1063+
inserted.path,
10471064
False,
10481065
)
10491066
)
10501067
util.fistpoint.activate_custom_fn(
1051-
"FileSR_revert_create_snap",
1052-
self.__fist_enospace)
1068+
"FileSR_revert_create_snap", self.__fist_enospace
1069+
)
10531070
self.cowutil.setHidden(dest_tmp_path, False)
10541071
## Force parent (it can be simplified by vhd tools)
1055-
self.cowutil.setParent(dest_tmp_path, actual_parent_path, False)
1056-
1057-
if not has_same_parents:
1058-
# Introduce new parent to the db
1059-
base_copy = FileVDI(self.sr, base_copy_uuid)
1060-
1061-
base_copy.label = "base copy"
1062-
base_copy.read_only = True
1063-
base_copy.location = base_copy_uuid
1064-
base_copy.sm_config = {}
1065-
base_copy.sm_config["image-format"] = getImageStringFromVdiType(self.vdi_type)
1066-
if "key_hash" in src_parent.sm_config:
1067-
base_copy.sm_config['key_hash'] = src_parent.sm_config['key_hash']
1068-
base_copy.cbt_enabled = bool(cbtlog)
1069-
1070-
base_copy._db_introduce()
1072+
self.cowutil.setParent(dest_tmp_path, inserted.path, False)
10711073

1072-
## The new parent can now be set hidden and don't need to be protected by the GC
1073-
base_copy.cowutil.setHidden(base_copy.path, True)
1074-
self._db_update()
1074+
## The new parent can now be set hidden and don't need to be protected by the GC
1075+
inserted.cowutil.setHidden(inserted.path, True)
10751076

10761077
# Apply snapshot
1077-
util.ioretry(lambda: self._rename(dest_tmp_path, dest.path),
1078-
errlist=[errno.EIO, errno.EACCES])
1078+
util.ioretry(
1079+
lambda: self._rename(dest_tmp_path, dest.path),
1080+
errlist=[errno.EIO, errno.EACCES],
1081+
)
10791082
util.fistpoint.activate_custom_fn(
1080-
"FileSR_revert_apply_snap",
1081-
self.__fist_enospace)
1083+
"FileSR_revert_apply_snap", self.__fist_enospace
1084+
)
10821085
dest.load_from_file(dest.path)
10831086
dest._db_update()
10841087

drivers/VDI.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ def revert(self, sr_uuid: str, vdi_uuid: str, target_uuid: str) -> None:
279279
cbtlog = None
280280

281281
dest.sm_config = dest.session.xenapi.VDI.get_sm_config(dest.session.xenapi.VDI.get_by_uuid(dest.uuid))
282+
self.sm_config = dest.session.xenapi.VDI.get_sm_config(dest.session.xenapi.VDI.get_by_uuid(dest.uuid))
282283

283284
self._do_revert(dest, cbtlog=cbtlog)
284285

0 commit comments

Comments
 (0)