Skip to content

bll: Allow resuming Paused/Suspended VMs with older custom compatibil… - #1178

Open
dupondje wants to merge 1 commit into
masterfrom
fix_resume_compat
Open

bll: Allow resuming Paused/Suspended VMs with older custom compatibil…#1178
dupondje wants to merge 1 commit into
masterfrom
fix_resume_compat

Conversation

@dupondje

Copy link
Copy Markdown
Member

…ity version

When a data center is upgraded to a newer compatibility version, VMs that were hibernated (Suspended) or Paused with an older custom compatibility version could no longer be resumed. The validation in RunVmCommand rejected them with ACTION_TYPE_FAILED_VM_COMPATIBILITY_VERSION_NOT_SUPPORTED, even though these VMs were already running with that version before the upgrade and are only being resumed, not started fresh.

Skip the custom compatibility version check when the VM status is Paused or Suspended, so that the RESUME_PAUSE and RESUME_HIBERNATE flows can proceed. The check is still enforced for VMs being started from Down status, preserving the existing protection against running a VM with an unsupported compatibility version.

Added tests covering:

  • Down VM with older custom compatibility version still fails validation
  • Suspended VM with older custom compatibility version now passes
  • Paused VM with older custom compatibility version now passes

Are you the owner of the code you are sending in, or do you have permission of the owner?

[y]

@peter-boden peter-boden left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM apart from a small nit 😅

// Skip the compatibility version check when resuming a Paused or Suspended VM,
// since the VM was already running with its custom compatibility version before
// the data center was upgraded and is only being resumed, not started fresh.
if (getVm().getCustomCompatibilityVersion() != null &&

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The old code also did it, but the mixed use of getVm() and vm is confusing.

@dupondje
dupondje force-pushed the fix_resume_compat branch 2 times, most recently from a3a6a6d to 4a731cf Compare August 17, 2026 12:49
…ity version

When a data center is upgraded to a newer compatibility version, VMs that
were hibernated (Suspended) or Paused with an older custom compatibility
version could no longer be resumed. The validation in RunVmCommand
rejected them with ACTION_TYPE_FAILED_VM_COMPATIBILITY_VERSION_NOT_SUPPORTED,
even though these VMs were already running with that version before the
upgrade and are only being resumed, not started fresh.

Skip the custom compatibility version check when the VM status is Paused
or Suspended, so that the RESUME_PAUSE and RESUME_HIBERNATE flows can
proceed. The check is still enforced for VMs being started from Down
status, preserving the existing protection against running a VM with an
unsupported compatibility version.

Added tests covering:
- Down VM with older custom compatibility version still fails validation
- Suspended VM with older custom compatibility version now passes
- Paused VM with older custom compatibility version now passes

Signed-off-by: Jean-Louis Dupond <jean-louis@dupond.be>
@dupondje
dupondje requested a review from peter-boden August 17, 2026 13:39
@dupondje dupondje self-assigned this Aug 17, 2026
@JasperB-TeamBlue

Copy link
Copy Markdown
Collaborator

/ost

@github-actions

Copy link
Copy Markdown

⏳ Running ost suite 'basic-suite-master' on distro 'centos9'.

Follow the progress here.

@github-actions

Copy link
Copy Markdown

😎💪 ost suite 'basic-suite-master' on distro 'centos9' finished successfully. (details)

@JasperB-TeamBlue JasperB-TeamBlue left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Functionality wise looking good, just a slight improvement that could be made on the test side of things.

Comment on lines +439 to +481
@Test
@MockedConfig("mockConfiguration")
public void testValidateSucceedsOnOlderCustomCompatibilityVersionWhenVmSuspended() {
final VM vm = new VM();
vm.setStatus(VMStatus.Suspended);
vm.setCustomCompatibilityVersion(new Version(4, 7));
command.setVm(vm);
StoragePool storagePool = new StoragePool();
storagePool.setCompatibilityVersion(new Version(4, 8));
command.setStoragePool(storagePool);
doReturn(true).when(command).checkRngDeviceClusterCompatibility();
doReturn(true).when(command).checkPayload(any());
doReturn(ValidationResult.VALID).when(command).checkDisksInBackupStorage();
doReturn(false).when(command).isVmDuringBackup();
doNothing().when(command).checkVmLeaseStorageDomain();
Cluster cluster = new Cluster();
cluster.setArchitecture(ArchitectureType.x86_64);
cluster.setCompatibilityVersion(new Version(4, 8));
command.setCluster(cluster);
ValidateTestUtils.runAndAssertValidateSuccess(command);
}

@Test
@MockedConfig("mockConfiguration")
public void testValidateSucceedsOnOlderCustomCompatibilityVersionWhenVmPaused() {
final VM vm = new VM();
vm.setStatus(VMStatus.Paused);
vm.setCustomCompatibilityVersion(new Version(4, 7));
command.setVm(vm);
StoragePool storagePool = new StoragePool();
storagePool.setCompatibilityVersion(new Version(4, 8));
command.setStoragePool(storagePool);
doReturn(true).when(command).checkRngDeviceClusterCompatibility();
doReturn(true).when(command).checkPayload(any());
doReturn(ValidationResult.VALID).when(command).checkDisksInBackupStorage();
doReturn(false).when(command).isVmDuringBackup();
doNothing().when(command).checkVmLeaseStorageDomain();
Cluster cluster = new Cluster();
cluster.setArchitecture(ArchitectureType.x86_64);
cluster.setCompatibilityVersion(new Version(4, 8));
command.setCluster(cluster);
ValidateTestUtils.runAndAssertValidateSuccess(command);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Instead of writing two tests that share the same result and a lot of repetitive code this could be rewritten as a parameterized test

    @ParameterizedTest
    @EnumSource(value = VMStatus.class, names = {"Suspended", "Paused"})
    @MockedConfig("mockConfiguration")
    public void testValidateSucceedsOnOlderCustomCompatibilityVersionWhenVmSuspendedOrPaused(VMStatus vmStatus) {
        final VM vm = new VM();
        vm.setStatus(vmStatus);
        vm.setCustomCompatibilityVersion(new Version(4, 7));
        command.setVm(vm);
        StoragePool storagePool = new StoragePool();
        storagePool.setCompatibilityVersion(new Version(4, 8));
        command.setStoragePool(storagePool);
        doReturn(true).when(command).checkRngDeviceClusterCompatibility();
        doReturn(true).when(command).checkPayload(any());
        doReturn(ValidationResult.VALID).when(command).checkDisksInBackupStorage();
        doReturn(false).when(command).isVmDuringBackup();
        doNothing().when(command).checkVmLeaseStorageDomain();
        Cluster cluster = new Cluster();
        cluster.setArchitecture(ArchitectureType.x86_64);
        cluster.setCompatibilityVersion(new Version(4, 8));
        command.setCluster(cluster);
        ValidateTestUtils.runAndAssertValidateSuccess(command);
    }

This results in the same vm states being tested, but less repetitive code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants