@@ -549,6 +549,252 @@ def test_snapshot_on_running_vm(self) -> None:
549549 finally :
550550 snapshot .destroy (verify = True )
551551
552+ def test_vdi_revert (self ) -> None :
553+ # Successives reverts to ensure the
554+ # snapshot tree stays consistent
555+ # Created snapshot Tree
556+ # snap 1 -> snap 2
557+ # |-----> snap 3
558+ # Revert order: 1 -> 2 -> 3 -> 1 -> 1
559+ vm = self .clone ()
560+ snapshots = []
561+ if not vm .is_running ():
562+ vm .start ()
563+ vm .wait_for_vm_running_and_ssh_up ()
564+ try :
565+ snap_1 = vm .snapshot ()
566+ snapshots .append (snap_1 )
567+
568+ snap_2_file = f"/root/{ uuid .uuid4 ()} "
569+ vm .ssh_touch_file (snap_2_file )
570+ snap_2 = vm .snapshot ()
571+ snapshots .append (snap_2 )
572+
573+ snap_1 .revert ()
574+ vm .start ()
575+ vm .wait_for_vm_running_and_ssh_up ()
576+ vm .ssh (f'test ! -f { snap_2_file } ' )
577+
578+ snap_3_file = f"/root/{ uuid .uuid4 ()} "
579+ vm .ssh_touch_file (snap_3_file )
580+ snap_3 = vm .snapshot ()
581+ snapshots .append (snap_3 )
582+
583+ snap_2 .revert ()
584+ vm .start ()
585+ vm .wait_for_vm_running_and_ssh_up ()
586+ vm .ssh (f'test ! -f { snap_3_file } ' )
587+ vm .ssh (f'test -f { snap_2_file } ' )
588+
589+ snap_3 .revert ()
590+ vm .start ()
591+ vm .wait_for_vm_running_and_ssh_up ()
592+ vm .ssh (f'test ! -f { snap_2_file } ' )
593+ vm .ssh (f'test -f { snap_3_file } ' )
594+
595+ snap_1 .revert ()
596+ vm .start ()
597+ vm .wait_for_vm_running_and_ssh_up ()
598+ vm .ssh (f'test ! -f { snap_2_file } ' )
599+ vm .ssh (f'test ! -f { snap_3_file } ' )
600+
601+ tmp_file = f"/root/{ uuid .uuid4 ()} "
602+ vm .ssh_touch_file (tmp_file )
603+ snap_1 .revert ()
604+ vm .start ()
605+ vm .wait_for_vm_running_and_ssh_up ()
606+ vm .ssh (f'test ! -f { snap_2_file } ' )
607+ vm .ssh (f'test ! -f { snap_3_file } ' )
608+ vm .ssh (f'test ! -f { tmp_file } ' )
609+
610+ finally :
611+ for snap in snapshots :
612+ snap .destroy (verify = True )
613+ vm .destroy ()
614+
615+ def test_vdi_revert_cbt (self ):
616+ snapshots = []
617+ vm = self .clone ()
618+ sr = vm .get_sr ()
619+
620+ if not vm .is_running ():
621+ vm .start ()
622+ vm .wait_for_vm_running_and_ssh_up ()
623+ snap_no_cbt_file = f"/root/{ uuid .uuid4 ()} "
624+ vm .ssh_touch_file (snap_no_cbt_file )
625+ snap_no_cbt = vm .snapshot ()
626+ snapshots .append (snap_no_cbt )
627+
628+ try :
629+ vm .vdis [0 ].enable_cbt ()
630+ assert len (vm .vdis ) == 1
631+ snap_cbt_file = f"/root/{ uuid .uuid4 ()} "
632+ vm .ssh_touch_file (snap_cbt_file )
633+ snap_cbt = vm .snapshot ()
634+ snapshots .append (snap_cbt )
635+
636+ before_revert_file = f"/root/{ uuid .uuid4 ()} "
637+ vm .ssh_touch_file (before_revert_file )
638+
639+ # CBT -> CBT
640+ snap_cbt .revert ()
641+ vm .start ()
642+ vm .wait_for_vm_running_and_ssh_up ()
643+ vm .ssh (f'test ! -f { before_revert_file } ' )
644+ vm .ssh (f'test -f { snap_no_cbt_file } ' )
645+ vm .ssh (f'test -f { snap_cbt_file } ' )
646+ assert vm .vdis [0 ].is_cbt_enabled ()
647+ assert VDI (snap_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
648+ assert not VDI (snap_no_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
649+
650+ # CBT -> no CBT
651+ snap_no_cbt .revert ()
652+ vm .start ()
653+ vm .wait_for_vm_running_and_ssh_up ()
654+ vm .ssh (f'test ! -f { before_revert_file } ' )
655+ vm .ssh (f'test -f { snap_no_cbt_file } ' )
656+ vm .ssh (f'test ! -f { snap_cbt_file } ' )
657+ assert not vm .vdis [0 ].is_cbt_enabled ()
658+ assert VDI (snap_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
659+ assert not VDI (snap_no_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
660+
661+ # no CBT -> CBT
662+ snap_cbt .revert ()
663+ vm .start ()
664+ vm .wait_for_vm_running_and_ssh_up ()
665+ vm .ssh (f'test ! -f { before_revert_file } ' )
666+ vm .ssh (f'test -f { snap_no_cbt_file } ' )
667+ vm .ssh (f'test -f { snap_cbt_file } ' )
668+ assert vm .vdis [0 ].is_cbt_enabled ()
669+ assert VDI (snap_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
670+ assert not VDI (snap_no_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
671+
672+ finally :
673+ for snap in snapshots :
674+ snap .destroy (verify = True )
675+ vm .destroy ()
676+
677+ def test_vdi_revert_journal_cbt (self , request : pytest .FixtureRequest , fistpoint : str , host : Host | None = None ):
678+ from lib .fistpoint import FistPoint # noqa: I001 Avoid circular import
679+ host_uuid = host .uuid if host else None
680+
681+ request .getfixturevalue ("exit_on_fistpoint" )
682+ vm = self .clone ()
683+ sr = vm .get_sr ()
684+
685+ snapshots = []
686+ if not vm .is_running ():
687+ vm .start (host_uuid )
688+ vm .wait_for_vm_running_and_ssh_up ()
689+
690+ snap_no_cbt_file = f"/root/{ uuid .uuid4 ()} "
691+ vm .ssh_touch_file (snap_no_cbt_file )
692+ snap_no_cbt = vm .snapshot ()
693+ snapshots .append (snap_no_cbt )
694+
695+ vm .vdis [0 ].enable_cbt ()
696+ snap_cbt_file = f"/root/{ uuid .uuid4 ()} "
697+ vm .ssh_touch_file (snap_cbt_file )
698+ snap_cbt = vm .snapshot ()
699+ snapshots .append (snap_cbt )
700+
701+ before_revert_file = f"/root/{ uuid .uuid4 ()} "
702+ vm .ssh_touch_file (before_revert_file )
703+ try :
704+ # CBT -> CBT
705+ with FistPoint (vm .host , fistpoint ), pytest .raises (commands .SSHCommandFailed ):
706+ snap_cbt .revert ()
707+ vm .start (host_uuid )
708+ vm .wait_for_vm_running_and_ssh_up ()
709+ vm .ssh (f'test -f { before_revert_file } ' )
710+ vm .ssh (f'test -f { snap_no_cbt_file } ' )
711+ vm .ssh (f'test -f { snap_cbt_file } ' )
712+ assert vm .vdis [0 ].is_cbt_enabled ()
713+ assert VDI (snap_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
714+ assert not VDI (snap_no_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
715+
716+ # CBT -> no CBT
717+ with FistPoint (vm .host , fistpoint ), pytest .raises (commands .SSHCommandFailed ):
718+ snap_no_cbt .revert ()
719+ vm .start (host_uuid )
720+ vm .wait_for_vm_running_and_ssh_up ()
721+ vm .ssh (f'test -f { before_revert_file } ' )
722+ vm .ssh (f'test -f { snap_no_cbt_file } ' )
723+ vm .ssh (f'test -f { snap_cbt_file } ' )
724+ assert vm .vdis [0 ].is_cbt_enabled ()
725+ assert VDI (snap_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
726+ assert not VDI (snap_no_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
727+
728+ # no CBT -> CBT
729+ snap_no_cbt .revert ()
730+ with FistPoint (vm .host , fistpoint ), pytest .raises (commands .SSHCommandFailed ):
731+ snap_cbt .revert ()
732+ vm .start (host_uuid )
733+ vm .wait_for_vm_running_and_ssh_up ()
734+ vm .ssh (f'test ! -f { before_revert_file } ' )
735+ vm .ssh (f'test -f { snap_no_cbt_file } ' )
736+ vm .ssh (f'test ! -f { snap_cbt_file } ' )
737+ assert not vm .vdis [0 ].is_cbt_enabled ()
738+ assert VDI (snap_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
739+ assert not VDI (snap_no_cbt .vdi_uuids ()[0 ], sr = sr ).is_cbt_enabled ()
740+
741+ finally :
742+ for snap in snapshots :
743+ snap .destroy (verify = True )
744+ vm .destroy ()
745+
746+ def test_vdi_revert_journal (self , request : pytest .FixtureRequest , fistpoint : str , host : Host | None = None ):
747+ from lib .fistpoint import FistPoint # noqa: I001 Avoid circular import
748+ request .getfixturevalue ("exit_on_fistpoint" )
749+ vm = self .clone ()
750+ snap = vm .snapshot ()
751+ host_uuid = host .uuid if host else None
752+ if not vm .is_running ():
753+ vm .start (host_uuid )
754+ vm .wait_for_vm_running_and_ssh_up ()
755+ try :
756+ file = f"/root/{ uuid .uuid4 ()} "
757+ vm .ssh_touch_file (file )
758+
759+ with FistPoint (host if host else vm .host , fistpoint ), pytest .raises (commands .SSHCommandFailed ):
760+ snap .revert ()
761+
762+ vm .start (host_uuid )
763+ vm .wait_for_vm_running_and_ssh_up ()
764+ vm .ssh (f'test -f { file } ' )
765+
766+ snap .revert ()
767+ vm .start (host_uuid )
768+ vm .wait_for_vm_running_and_ssh_up ()
769+ vm .ssh (f'test ! -f { file } ' )
770+ finally :
771+ snap .destroy (verify = True )
772+ vm .destroy ()
773+
774+ def test_critical_journal_revert (self , request : pytest .FixtureRequest , host : Host , fistpoint : str ):
775+ from lib .fistpoint import FistPoint # noqa: I001 Avoid circular import
776+ vm = self .clone ()
777+ sr = vm .get_sr ()
778+ request .getfixturevalue ("exit_on_fistpoint" )
779+ snap = vm .snapshot ()
780+ sr .param_set ("other-config" , "false" , "auto-scan" ) # Avoid journals being run during tests unexpectedly
781+ try :
782+ with FistPoint (vm .host , fistpoint ), pytest .raises (commands .SSHCommandFailed ):
783+ snap .revert ()
784+
785+ with pytest .raises (
786+ commands .SSHCommandFailed ,
787+ check = lambda e : (
788+ "The SR is not available [opterr=Critical journals are pending. A scan is required.]" in e .stdout
789+ ),
790+ ):
791+ vm .start (on = host .uuid )
792+ finally :
793+ sr .scan () # Force journals to be processed
794+ sr .param_remove ("other-config" , "auto-scan" )
795+ snap .destroy (verify = True )
796+ vm .destroy ()
797+
552798 def get_messages (self , name : str ) -> List [str ]:
553799 args : dict [str , str | bool | dict [str , str ]] = {
554800 'obj-uuid' : self .uuid ,
0 commit comments