|
18 | 18 | # FileSR: local-file storage repository |
19 | 19 | from contextlib import contextmanager |
20 | 20 |
|
21 | | -from sm_typing import Dict, Optional, List, override, Tuple, Union |
| 21 | +from sm_typing import Dict, Optional, List, override, Tuple |
22 | 22 |
|
23 | 23 | import SR |
24 | 24 | import VDI |
@@ -777,44 +777,111 @@ def revert(self, sr_uuid, src_uuid, dest_uuid): |
777 | 777 | if not dest._checkpath(dest.path): |
778 | 778 | raise xs_errors.XenError(f"Could not find {dest.path}") |
779 | 779 |
|
780 | | - if self.parent != dest.parent: |
781 | | - raise xs_errors.XenError("Not implemented yet") |
| 780 | + def get_child_of(start: FileVDI, parent_uuid: str) -> Optional[str]: |
| 781 | + util.SMlog(f"Looking for common parent: {parent_uuid}") |
| 782 | + current = start.uuid |
| 783 | + while current is not None: |
| 784 | + path, _ = start._get_path_and_type(current) |
| 785 | + util.SMlog(f"Testing path {path}") |
| 786 | + if not path: |
| 787 | + return None |
| 788 | + |
| 789 | + parent = start.cowutil.getParent(path, FileVDI.extractUuid) |
| 790 | + util.SMlog(f"Testing {parent} == {parent_uuid}") |
| 791 | + if parent == parent_uuid: |
| 792 | + util.SMlog(f"Found {current} with next parent {parent}") |
| 793 | + return current |
| 794 | + current = parent |
| 795 | + |
| 796 | + return None |
| 797 | + |
| 798 | + common_parent_uuid = get_child_of(dest, self.parent) |
| 799 | + if not common_parent_uuid: |
| 800 | + raise xs_errors.XenError(f"{self.uuid} and {dest.uuid} aren't on the same snapshot tree") |
782 | 801 |
|
783 | 802 | self._ensure_not_max_depth() |
784 | 803 |
|
785 | 804 | dest_tmp_uuid = util.gen_uuid() # Will be replaced by dest.uuid at the end |
786 | 805 | dest_tmp_path = os.path.join(dest.sr.path, "%s%s" % (dest_tmp_uuid, VDI_TYPE_TO_EXTENSION[dest.vdi_type])) |
787 | 806 |
|
788 | | - # snapshot = self._do_snapshot(sr_uuid, src_uuid, VDI.SNAPSHOT_SINGLE) |
789 | | - # util.SMlog(snapshot) |
790 | | - src_parent_path, _ = self._get_path_and_type(self.parent) |
791 | | - if not src_parent_path: |
792 | | - raise xs_errors.XenError(f"Could not find parent of {self.uuid}") |
| 807 | + src_parent = VDI.VDI.from_uuid(self.sr.session, self.parent) |
793 | 808 |
|
| 809 | + def update_vdi_from_file(vdi: FileVDI, path: str): |
| 810 | + image_info = vdi.cowutil.getInfo(vdi.path, FileVDI.extractUuid) |
| 811 | + vdi.utilisation = image_info.sizePhys |
| 812 | + vdi.size = image_info.sizeVirt |
| 813 | + vdi.parent = image_info.parentUuid |
| 814 | + vdi.hidden = image_info.hidden |
| 815 | + if vdi.parent: |
| 816 | + vdi.sm_config['vhd-parent'] = vdi.parent |
794 | 817 |
|
795 | 818 | with self._tap_pause(), dest._tap_pause(): |
796 | 819 | # try: |
797 | 820 | util.fistpoint.activate_custom_fn( |
798 | 821 | "FileSR_fail_snap1", |
799 | 822 | self.__fist_enospace) |
800 | | - util.ioretry(lambda: self._snap(dest_tmp_path, src_parent_path, False)) |
801 | | - self.cowutil.setHidden(dest_tmp_path, True) |
| 823 | + util.ioretry(lambda: self._snap(dest_tmp_path, src_parent.path, False)) |
| 824 | + self.cowutil.setHidden(dest_tmp_path, False) |
| 825 | + |
| 826 | + if common_parent_uuid != dest.parent: |
| 827 | + # Create a new parent VDI based on src parent |
| 828 | + src_parent_clone_uuid = util.gen_uuid() |
| 829 | + src_parent_clone_path = os.path.join( |
| 830 | + dest.sr.path, |
| 831 | + "%s%s" % (src_parent_clone_uuid, VDI_TYPE_TO_EXTENSION[dest.vdi_type]) |
| 832 | + ) |
802 | 833 |
|
803 | | - if self.parent != dest.parent: |
804 | | - pass # Do more operation |
| 834 | + common_parent = VDI.VDI.from_uuid(self.sr.session, common_parent_uuid) |
| 835 | + common_parent.sm_config = common_parent.session.xenapi.VDI.get_sm_config(common_parent.sr.srcmd.params['vdi_ref']) |
805 | 836 |
|
806 | | - image_info = VdiType.isCowImage(self.vdi_type) |
807 | | - util.SMlog(f"J'ai écrittttttttttttt iciciiiiiii {dest_tmp_path}") |
808 | | - self._rename(dest_tmp_path, dest.path) |
809 | | - util.SMlog(f"J'ai renoméééééé iciciiiiiii {dest.path}") |
| 837 | + util.fistpoint.activate_custom_fn( |
| 838 | + "FileSR_fail_snap2", |
| 839 | + self.__fist_enospace) |
| 840 | + util.ioretry(lambda: self._snap(src_parent_clone_path, src_parent.path, False)) |
| 841 | + self.cowutil.setHidden(src_parent_clone_path, False) |
| 842 | + |
| 843 | + is_raw = self.VDI_TYPE == VdiType.RAW |
| 844 | + self.cowutil.setParent(src_parent_clone_path, src_parent.path, is_raw) |
| 845 | + self.cowutil.setParent(common_parent.path, src_parent_clone_path, is_raw) |
| 846 | + self.cowutil.setParent(self.path, src_parent_clone_path, is_raw) |
| 847 | + |
| 848 | + # Introduce new readonly vdi to db |
| 849 | + src_parent_clone = VDI.VDI(self.sr, src_parent_clone_uuid) |
| 850 | + |
| 851 | + # FileVDI emulation for update_vdi_from_file |
| 852 | + src_parent_clone.path = src_parent_clone_path |
| 853 | + src_parent_clone.parent = src_parent.uuid |
| 854 | + src_parent_clone.cowutil = self.cowutil |
| 855 | + |
| 856 | + src_parent_clone.label = "base copy" |
| 857 | + src_parent_clone.read_only = True |
| 858 | + src_parent_clone.location = src_parent_clone_uuid |
| 859 | + src_parent_clone.sm_config = {} |
| 860 | + # TODO: fix the raw snapshot case |
| 861 | + src_parent_clone.sm_config["image-format"] = getImageStringFromVdiType(self.vdi_type) |
| 862 | + if "key_hash" in common_parent.sm_config: |
| 863 | + src_parent_clone.sm_config['key_hash'] = common_parent.sm_config['key_hash'] |
| 864 | + update_vdi_from_file(src_parent_clone, src_parent_clone_uuid) |
| 865 | + |
| 866 | + self.sm_config = self.session.xenapi.VDI.get_sm_config(self.sr.srcmd.params['vdi_ref']) |
| 867 | + update_vdi_from_file(self, self.path) |
| 868 | + |
| 869 | + update_vdi_from_file(common_parent, common_parent.path) |
| 870 | + |
| 871 | + src_parent_clone._db_introduce() |
| 872 | + |
| 873 | + common_parent._db_update() |
| 874 | + |
| 875 | + self._db_update() |
| 876 | + |
| 877 | + self.cowutil.setHidden(src_parent_clone_path, True) |
| 878 | + |
| 879 | + util.ioretry(lambda: self._rename(dest_tmp_path, dest.path), |
| 880 | + errlist=[errno.EIO, errno.EACCES]) |
810 | 881 |
|
811 | | - image_info = dest.cowutil.getInfo(dest.path, FileVDI.extractUuid) |
812 | | - dest.utilisation = image_info.sizePhys |
813 | | - dest.size = image_info.sizeVirt |
814 | | - dest.hidden = False |
815 | | - dest.parent = image_info.parentUuid |
| 882 | + dest.sm_config = dest.session.xenapi.VDI.get_sm_config(dest.sr.srcmd.params['vdi_ref']) |
| 883 | + update_vdi_from_file(dest, dest.path) |
816 | 884 |
|
817 | | - dest.cowutil.setHidden(dest.path, False) |
818 | 885 | dest._db_update() |
819 | 886 |
|
820 | 887 | return dest.get_params() |
|
0 commit comments