Skip to content

Commit 136774f

Browse files
committed
WIP: Half working cbt and partial rollback
Signed-off-by: Antoine Bartuccio <antoine.bartuccio@vates.tech>
1 parent 4f63b5d commit 136774f

File tree

2 files changed

+115
-46
lines changed

2 files changed

+115
-46
lines changed

drivers/FileSR.py

Lines changed: 114 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717
#
1818
# FileSR: local-file storage repository
19+
import contextlib
1920
from contextlib import contextmanager
2021

2122
from sm_typing import Dict, Optional, List, override, Tuple
2223

24+
import cbtutil
2325
import SR
2426
import VDI
2527
import SRCommand
@@ -768,7 +770,10 @@ def _tap_pause(self, secondary=None):
768770
blktap2.VDI.tap_unpause(self.session, self.sr.uuid, self.uuid, secondary)
769771

770772
@override
771-
def _do_revert(self, dest: "FileVDI", cbtlog: Optional[str] = None):
773+
def _do_revert(self,
774+
dest: "FileVDI", # type: ignore # self and dest are the same type
775+
cbtlog: Optional[str] = None
776+
):
772777
# Sanity checks
773778
if not self._checkpath(self.path):
774779
raise xs_errors.XenError(f"Could not find {self.path}")
@@ -778,20 +783,29 @@ def _do_revert(self, dest: "FileVDI", cbtlog: Optional[str] = None):
778783

779784
self._ensure_not_max_depth()
780785

781-
# Get first common parent
786+
cbt_consistency_state = False
787+
if cbtlog:
788+
cbt_consistency_state = blktap2.VDI.tap_status(self.session, self.uuid)
789+
util.SMlog("Saving log consistency state of %s for vdi: %s" %
790+
(cbt_consistency_state, self.uuid))
791+
792+
util.SMlog(f"---------------------------------------------> {self.parent}")
793+
# Get downward child
782794
if self.parent == dest.parent:
783795
downward_child = None
784796
else:
785797
children = [child for child in self.sr.get_children_of(self.parent) if child != self.uuid]
786798
if not children:
787799
downward_child = None
800+
elif len(children) > 1:
801+
raise xs_errors.SRException(f"Too many children for {self.parent}. Expected 1, found {len(children) + 1}")
788802
else:
789803
downward_child = VDI.VDI.from_uuid(self.sr.session, children[0])
790804

791805
with self._tap_pause(), dest._tap_pause():
792-
self._revert(dest, downward_child, cbtlog)
806+
self._revert(dest, downward_child, cbtlog, cbt_consistency_state)
793807

794-
def _revert(self, dest: "FileVDI", downward_child: Optional["FileVDI"], cbtlog: Optional[str]):
808+
def _revert(self, dest: "FileVDI", downward_child: Optional["FileVDI"], cbtlog: Optional[str], cbt_consistency_state: bool):
795809
"""This assumes that self and dest VDIs has been paused"""
796810
dest_tmp_uuid = util.gen_uuid() # Will be replaced by dest.uuid at the end
797811
dest_tmp_path = os.path.join(dest.sr.path, "%s%s" % (dest_tmp_uuid, VDI_TYPE_TO_EXTENSION[dest.vdi_type]))
@@ -807,13 +821,6 @@ def update_vdi_from_file(vdi, path):
807821
if vdi.parent:
808822
vdi.sm_config['vhd-parent'] = vdi.parent
809823

810-
# try:
811-
util.fistpoint.activate_custom_fn(
812-
"FileSR_fail_snap1",
813-
self.__fist_enospace)
814-
util.ioretry(lambda: self._snap(dest_tmp_path, src_parent.path, False))
815-
self.cowutil.setHidden(dest_tmp_path, False)
816-
817824
if downward_child:
818825
# Create a new parent VDI based on src parent and attach the rest of the snapshoot tree to it
819826
src_parent_clone_uuid = util.gen_uuid()
@@ -824,56 +831,118 @@ def update_vdi_from_file(vdi, path):
824831

825832
downward_child.sm_config = downward_child.session.xenapi.VDI.get_sm_config(downward_child.sr.srcmd.params['vdi_ref'])
826833

827-
util.fistpoint.activate_custom_fn(
828-
"FileSR_fail_snap2",
829-
self.__fist_enospace)
830-
util.ioretry(lambda: self._snap(src_parent_clone_path, src_parent.path, False))
831-
self.cowutil.setHidden(src_parent_clone_path, False)
832-
834+
# Used both for snapshot and cleanup
833835
is_raw = self.VDI_TYPE == VdiType.RAW
834-
self.cowutil.setParent(src_parent_clone_path, src_parent.path, is_raw)
835-
self.cowutil.setParent(downward_child.path, src_parent_clone_path, is_raw)
836-
self.cowutil.setParent(self.path, src_parent_clone_path, is_raw)
836+
downward_child_old_parent, _ = downward_child._get_path_and_type(downward_child.parent)
837+
src_old_parent = src_parent.path
838+
if not downward_child_old_parent:
839+
raise xs_errors.SRException(f"Error getting parent path of {downward_child.uuid}")
837840

838-
# Introduce new readonly vdi to db
839-
src_parent_clone = VDI.VDI(self.sr, src_parent_clone_uuid)
841+
try:
842+
util.fistpoint.activate_custom_fn(
843+
"FileSR_fail_snap2",
844+
self.__fist_enospace)
845+
util.ioretry(lambda: self._snap(src_parent_clone_path, src_parent.path, False))
846+
self.cowutil.setHidden(src_parent_clone_path, False)
840847

841-
# FileVDI emulation for update_vdi_from_file
842-
src_parent_clone.path = src_parent_clone_path
843-
src_parent_clone.parent = src_parent.uuid
844-
src_parent_clone.cowutil = self.cowutil
848+
self.cowutil.setParent(src_parent_clone_path, src_parent.path, is_raw)
849+
self.cowutil.setParent(downward_child.path, src_parent_clone_path, is_raw)
850+
self.cowutil.setParent(self.path, src_parent_clone_path, is_raw)
845851

846-
src_parent_clone.label = "base copy"
847-
src_parent_clone.read_only = True
848-
src_parent_clone.location = src_parent_clone_uuid
849-
src_parent_clone.sm_config = {}
850-
# TODO: fix the raw snapshot case
851-
src_parent_clone.sm_config["image-format"] = getImageStringFromVdiType(self.vdi_type)
852-
if "key_hash" in downward_child.sm_config:
853-
src_parent_clone.sm_config['key_hash'] = downward_child.sm_config['key_hash']
854-
update_vdi_from_file(src_parent_clone, src_parent_clone_uuid)
852+
# Introduce new readonly vdi to db
853+
src_parent_clone = FileVDI(self.sr, src_parent_clone_uuid)
855854

856-
self.sm_config = self.session.xenapi.VDI.get_sm_config(self.sr.srcmd.params['vdi_ref'])
857-
update_vdi_from_file(self, self.path)
855+
src_parent_clone.label = "base copy"
856+
src_parent_clone.read_only = True
857+
src_parent_clone.location = src_parent_clone_uuid
858+
src_parent_clone.sm_config = {}
859+
# TODO: fix the raw snapshot case
860+
src_parent_clone.sm_config["image-format"] = getImageStringFromVdiType(self.vdi_type)
861+
if "key_hash" in downward_child.sm_config:
862+
src_parent_clone.sm_config['key_hash'] = downward_child.sm_config['key_hash']
863+
src_parent_clone.cbt_enabled = bool(cbtlog)
858864

859-
update_vdi_from_file(downward_child, downward_child.path)
865+
update_vdi_from_file(src_parent_clone, src_parent_clone_uuid)
860866

861-
src_parent_clone._db_introduce()
867+
self.sm_config = self.session.xenapi.VDI.get_sm_config(self.sr.srcmd.params['vdi_ref'])
868+
update_vdi_from_file(self, self.path)
862869

863-
downward_child._db_update()
870+
update_vdi_from_file(downward_child, downward_child.path)
864871

865-
self._db_update()
872+
src_parent_clone._db_introduce()
866873

867-
self.cowutil.setHidden(src_parent_clone_path, True)
874+
if cbtlog:
875+
# Set downward_child's parent as src_parent_clone
876+
downward_child_cbt_path = downward_child._get_cbt_logpath(downward_child.uuid)
877+
if util.pathexists(downward_child_cbt_path):
878+
downward_child._cbt_op(
879+
downward_child.uuid,
880+
cbtutil.set_cbt_parent,
881+
downward_child_cbt_path,
882+
src_parent_clone.uuid,
883+
)
884+
# Set self's parent as src_parent_clone
885+
self._cbt_op(
886+
self.uuid,
887+
cbtutil.set_cbt_parent,
888+
self._get_cbt_logpath(self.uuid),
889+
src_parent_clone.uuid,
890+
)
891+
892+
downward_child._db_update()
893+
894+
self._db_update()
895+
896+
self.cowutil.setHidden(src_parent_clone.path, True)
897+
except Exception as e:
898+
# Restore parents
899+
util.SMlog(f"Error during revert of {self.uuid}, rolling back and cleaning up")
900+
self.cowutil.setParent(downward_child.path, downward_child_old_parent, is_raw)
901+
self.cowutil.setParent(self.path, src_old_parent, is_raw)
868902

869-
util.ioretry(lambda: self._rename(dest_tmp_path, dest.path),
870-
errlist=[errno.EIO, errno.EACCES])
903+
update_vdi_from_file(downward_child, downward_child.path)
904+
update_vdi_from_file(self, self.path)
905+
906+
util.SMlog(f"Deleting {src_parent_clone_uuid}")
907+
with contextlib.suppress(Exception):
908+
src_parent_clone = FileVDI(self.sr, src_parent_clone_uuid)
909+
src_parent_clone.delete(src_parent_clone.sr, src_parent_clone.uuid)
910+
if util.ioretry(lambda: util.pathexists(src_parent_clone_path)):
911+
self._unlink(src_parent_clone_path)
912+
913+
downward_child._db_update()
914+
self._db_update()
915+
raise e
916+
917+
try:
918+
util.fistpoint.activate_custom_fn(
919+
"FileSR_fail_snap1",
920+
self.__fist_enospace)
921+
util.ioretry(lambda: self._snap(dest_tmp_path, src_parent.path, False))
922+
self.cowutil.setHidden(dest_tmp_path, False)
923+
except Exception as e:
924+
if util.ioretry(lambda: util.pathexists(dest_tmp_path)):
925+
self._unlink(dest_tmp_path)
926+
raise e
871927

872928
dest.sm_config = dest.session.xenapi.VDI.get_sm_config(dest.sr.srcmd.params['vdi_ref'])
929+
if cbtlog:
930+
dest.cbt_enabled = True
931+
try:
932+
# copy self -> dest
933+
# set consistency
934+
# set dest as child
935+
dest._cbt_snapshot(self.uuid, cbt_consistency_state) # Broken part
936+
except:
937+
# CBT operation failed.
938+
util.end_log_entry(dest.sr.path, dest.path, ["error"])
939+
raise
940+
941+
util.ioretry(lambda: self._rename(dest_tmp_path, dest.path),
942+
errlist=[errno.EIO, errno.EACCES])
873943
update_vdi_from_file(dest, dest.path)
874944

875945
dest._db_update()
876-
# except:
877946
#cleanup
878947

879948
@override

drivers/VDI.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def _do_snapshot(self, sr_uuid, vdi_uuid, snapType,
217217
cloneOp=False, secondary=None, cbtlog=None, is_mirror_destination=False) -> str:
218218
raise xs_errors.XenError('Unimplemented')
219219

220-
def _do_revert(self, dest, cbtlog: Optional[str] = None) -> None:
220+
def _do_revert(self, dest: "VDI", cbtlog: Optional[str] = None) -> None:
221221
raise xs_errors.XenError('Unimplemented')
222222

223223
def _delete_cbt_log(self) -> None:

0 commit comments

Comments
 (0)