Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lib/vdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,17 @@ def wait_for_coalesce(self, fn: Callable[[], R] | None = None) -> R | None:
wait_for(lambda: self.get_parent() != previous_parent, msg="Waiting for coalesce", timeout_secs=10 * 60)
logging.info("Coalesce done")
return ret

def enable_cbt(self) -> None:
logging.info(f"Enabling CBT on VDI {self.uuid}")
self.sr.pool.master.xe('vdi-enable-cbt', {'uuid': self.uuid})

def disable_cbt(self) -> None:
logging.info(f"Disabling CBT on VDI {self.uuid}")
self.sr.pool.master.xe('vdi-disable-cbt', {'uuid': self.uuid})

def get_cbt_enabled(self) -> str:
return self.param_get('cbt-enabled')

def is_cbt_enabled(self) -> bool:
return self.get_cbt_enabled() == 'true'
32 changes: 31 additions & 1 deletion tests/storage/cephfs/test_cephfs_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
import time

from lib.commands import SSHCommandFailed
from lib.common import vm_image, wait_for
from lib.common import Defer, vm_image, wait_for
from lib.host import Host
from lib.pool import Pool
from lib.sr import SR
from lib.vdi import VDI
from lib.vm import VM
from tests.storage import vdi_is_open
from tests.storage.storage import (
check_critical_journal_revert,
check_vdi_revert,
check_vdi_revert_journal,
)

# Requirements:
# - one XCP-ng host >= 8.2
Expand Down Expand Up @@ -45,6 +50,31 @@ def test_snapshot(self, vm_on_cephfs_sr: VM) -> None:
finally:
vm.shutdown(verify=True)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert(self, vm_on_cephfs_sr: VM, defer: Defer) -> None:
check_vdi_revert(defer, vm_on_cephfs_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
@pytest.mark.parametrize(
"fistpoint",
[
"FileSR_revert_create_insert",
"FileSR_revert_create_src",
"FileSR_revert_create_dest",
]
)
def test_revert_journal(self, vm_on_cephfs_sr: VM, defer: Defer, exit_on_fistpoint: None, fistpoint: str):
check_vdi_revert_journal(defer, vm_on_cephfs_sr, fistpoint, vm_on_cephfs_sr.host.pool.master)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_critical_journal_revert(
self, vm_on_cephfs_sr: VM, defer: Defer, exit_on_fistpoint: None, hostA2: Host
) -> None:
check_critical_journal_revert(defer, vm_on_cephfs_sr, hostA2, "FileSR_revert_create_src")

# *** tests with reboots (longer tests).

@pytest.mark.reboot
Expand Down
34 changes: 34 additions & 0 deletions tests/storage/ext/test_ext_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
vdi_is_open,
xva_export_import,
)
from tests.storage.storage import (
check_vdi_revert,
check_vdi_revert_cbt,
check_vdi_revert_journal,
check_vdi_revert_journal_cbt,
)

# Requirements:
# - one XCP-ng host with an additional unused disk for the SR
Expand Down Expand Up @@ -62,6 +68,34 @@ def test_snapshot(self, vm_on_ext_sr: VM) -> None:
finally:
vm.shutdown(verify=True)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert(self, vm_on_ext_sr: VM, defer: Defer) -> None:
check_vdi_revert(defer, vm_on_ext_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert_cbt(self, vm_on_ext_sr: VM, defer: Defer) -> None:
check_vdi_revert_cbt(defer, vm_on_ext_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert_journal_cbt(self, vm_on_ext_sr: VM, defer: Defer, exit_on_fistpoint: None):
check_vdi_revert_journal_cbt(defer, vm_on_ext_sr, "FileSR_revert_create_src")

@pytest.mark.small_vm
@pytest.mark.big_vm
@pytest.mark.parametrize(
"fistpoint",
[
"FileSR_revert_create_insert",
"FileSR_revert_create_src",
"FileSR_revert_create_dest",
]
)
def test_revert_journal(self, vm_on_ext_sr: VM, defer: Defer, exit_on_fistpoint: None, fistpoint: str):
check_vdi_revert_journal(defer, vm_on_ext_sr, fistpoint)

@pytest.mark.small_vm
@pytest.mark.parametrize("vdi_op", ["snapshot", "clone"])
def test_coalesce(self, storage_test_vm: VM, vdi_on_ext_sr: VDI, vdi_op: CoalesceOperation, defer: Defer) -> None:
Expand Down
28 changes: 27 additions & 1 deletion tests/storage/glusterfs/test_glusterfs_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import logging

from lib.commands import SSHCommandFailed
from lib.common import vm_image, wait_for
from lib.common import Defer, vm_image, wait_for
from lib.host import Host
from lib.pool import Pool
from lib.sr import SR
from lib.vdi import VDI
from lib.vm import VM
from tests.storage import vdi_is_open
from tests.storage.storage import check_critical_journal_revert, check_vdi_revert, check_vdi_revert_journal

# Requirements:
# - one XCP-ng host >= 8.2 with an additional unused disk for the SR
Expand Down Expand Up @@ -61,6 +62,31 @@ def test_volume_stopped(self, host: Host, glusterfs_sr: SR) -> None:
if not volume_running:
host.ssh('gluster --mode=script volume start vol0')

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert(self, vm_on_glusterfs_sr: VM, defer: Defer) -> None:
check_vdi_revert(defer, vm_on_glusterfs_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
@pytest.mark.parametrize(
"fistpoint",

@gthvn1 gthvn1 Jul 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity, what does 'fistpoint' mean here? I have a few ideas, but they don't really seem to fit? Is it kind of a joke?
I saw it in the code as well that is why I'm curious here :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fistpoints are special files that are used to alter the behaviour of the smapi.
Basically, when present, they activates some sorts of breakpoints at specific points of the program.
We can trigger different kinds of callbacks, the default one is to pause for 10s. When combined with the exit_on_fistpoint fistpoint, it enforces a crash when reaching those breakpoints.

This is what makes the revert fail in controlled conditions, they are designed for end to end testing.

And yes, the name is funny, they exists since the first git commit of the sm project.

[
"FileSR_revert_create_insert",
"FileSR_revert_create_src",
"FileSR_revert_create_dest",
]
)
def test_revert_journal(self, vm_on_glusterfs_sr: VM, defer: Defer, exit_on_fistpoint: None, fistpoint: str):
check_vdi_revert_journal(defer, vm_on_glusterfs_sr, fistpoint, vm_on_glusterfs_sr.host.pool.master)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_critical_journal_revert(
self, vm_on_glusterfs_sr: VM, defer: Defer, exit_on_fistpoint: None, hostA2: Host
) -> None:
check_critical_journal_revert(defer, vm_on_glusterfs_sr, hostA2, "FileSR_revert_create_src")

# *** tests with reboots (longer tests).

@pytest.mark.reboot
Expand Down
36 changes: 35 additions & 1 deletion tests/storage/largeblock/test_largeblock_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

import pytest

from lib.common import vm_image, wait_for
from lib.common import Defer, vm_image, wait_for
from lib.vdi import ImageFormat
from tests.storage import try_to_create_sr_with_missing_device, vdi_is_open
from tests.storage.storage import (
check_vdi_revert,
check_vdi_revert_cbt,
check_vdi_revert_journal,
check_vdi_revert_journal_cbt,
)

from typing import TYPE_CHECKING

Expand Down Expand Up @@ -50,6 +56,34 @@ def test_snapshot(self, vm_on_largeblock_sr: VM) -> None:
vm.test_snapshot_on_running_vm()
vm.shutdown(verify=True)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert(self, vm_on_largeblock_sr: VM, defer: Defer) -> None:
check_vdi_revert(defer, vm_on_largeblock_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert_cbt(self, vm_on_largeblock_sr: VM, defer: Defer) -> None:
check_vdi_revert_cbt(defer, vm_on_largeblock_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert_journal_cbt(self, vm_on_largeblock_sr: VM, defer: Defer, exit_on_fistpoint: None):
check_vdi_revert_journal_cbt(defer, vm_on_largeblock_sr, "FileSR_revert_create_src")

@pytest.mark.small_vm
@pytest.mark.big_vm
@pytest.mark.parametrize(
"fistpoint",
[
"FileSR_revert_create_insert",
"FileSR_revert_create_src",
"FileSR_revert_create_dest",
]
)
def test_revert_journal(self, vm_on_largeblock_sr: VM, defer: Defer, exit_on_fistpoint: None, fistpoint: str):
check_vdi_revert_journal(defer, vm_on_largeblock_sr, fistpoint)

# *** tests with reboots (longer tests).

@pytest.mark.reboot
Expand Down
28 changes: 27 additions & 1 deletion tests/storage/moosefs/test_moosefs_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import time

from lib.commands import SSHCommandFailed
from lib.common import vm_image, wait_for
from lib.common import Defer, vm_image, wait_for
from lib.host import Host
from lib.pool import Pool
from lib.sr import SR
from lib.vdi import VDI
from lib.vm import VM
from tests.storage import vdi_is_open
from tests.storage.storage import check_critical_journal_revert, check_vdi_revert, check_vdi_revert_journal

# Requirements:
# - one XCP-ng host >= 8.2
Expand Down Expand Up @@ -82,6 +83,31 @@ def test_moosefs_missing_client_pbd_plug_fails(self, host: Host, moosefs_sr: SR)
if not moosefs_installed:
host.yum_install(['moosefs-client'])

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert(self, vm_on_moosefs_sr: VM, defer: Defer) -> None:
check_vdi_revert(defer, vm_on_moosefs_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
@pytest.mark.parametrize(
"fistpoint",
[
"FileSR_revert_create_insert",
"FileSR_revert_create_src",
"FileSR_revert_create_dest",
]
)
def test_revert_journal(self, vm_on_moosefs_sr: VM, defer: Defer, exit_on_fistpoint: None, fistpoint: str):
check_vdi_revert_journal(defer, vm_on_moosefs_sr, fistpoint, vm_on_moosefs_sr.host.pool.master)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_critical_journal_revert(
self, vm_on_moosefs_sr: VM, defer: Defer, exit_on_fistpoint: None, hostA2: Host
) -> None:
check_critical_journal_revert(defer, vm_on_moosefs_sr, hostA2, "FileSR_revert_create_src")

# *** tests with reboots (longer tests).

@pytest.mark.reboot
Expand Down
42 changes: 42 additions & 0 deletions tests/storage/nfs/test_nfs_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
vdi_is_open,
xva_export_import,
)
from tests.storage.storage import (
check_critical_journal_revert,
check_vdi_revert,
check_vdi_revert_cbt,
check_vdi_revert_journal,
check_vdi_revert_journal_cbt,
)

# Requirements:
# - one XCP-ng host >= 8.0 with an additional unused disk for the SR
Expand Down Expand Up @@ -104,6 +111,41 @@ def test_snapshot(self, dispatch_nfs: VM) -> None:
finally:
vm.shutdown(verify=True)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert(self, vm_on_nfs_sr: VM, defer: Defer) -> None:
check_vdi_revert(defer, vm_on_nfs_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert_cbt(self, vm_on_nfs_sr: VM, defer: Defer) -> None:
check_vdi_revert_cbt(defer, vm_on_nfs_sr)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_revert_journal_cbt(self, vm_on_nfs_sr: VM, defer: Defer, exit_on_fistpoint: None):
check_vdi_revert_journal_cbt(defer, vm_on_nfs_sr, "FileSR_revert_create_src", vm_on_nfs_sr.host.pool.master)

@pytest.mark.small_vm
@pytest.mark.big_vm
@pytest.mark.parametrize(
"fistpoint",
[
"FileSR_revert_create_insert",
"FileSR_revert_create_src",
"FileSR_revert_create_dest",
]
)
def test_revert_journal(self, vm_on_nfs_sr: VM, defer: Defer, exit_on_fistpoint: None, fistpoint: str):
check_vdi_revert_journal(defer, vm_on_nfs_sr, fistpoint, vm_on_nfs_sr.host.pool.master)

@pytest.mark.small_vm
@pytest.mark.big_vm
def test_critical_journal_revert(
self, vm_on_nfs_sr: VM, defer: Defer, exit_on_fistpoint: None, hostA2: Host
) -> None:
check_critical_journal_revert(defer, vm_on_nfs_sr, hostA2, "FileSR_revert_create_src")

@pytest.mark.small_vm
@pytest.mark.parametrize('dispatch_nfs', ['vdi_on_nfs_sr', 'vdi_on_nfs4_sr'], indirect=True)
@pytest.mark.parametrize('vdi_op', ['snapshot', 'clone'])
Expand Down
Loading
Loading