diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java index 8aacfc87008..17c3185e350 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java @@ -1078,8 +1078,13 @@ protected boolean validateImpl() { return false; } - if (getVm().getCustomCompatibilityVersion() != null && - vm.getCustomCompatibilityVersion().less(getStoragePool().getCompatibilityVersion())) { + // 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 (vm.getCustomCompatibilityVersion() != null && + vm.getCustomCompatibilityVersion().less(getStoragePool().getCompatibilityVersion()) && + vm.getStatus() != VMStatus.Paused && + vm.getStatus() != VMStatus.Suspended) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_COMPATIBILITY_VERSION_NOT_SUPPORTED, String.format("$VmName %1$s", getVm().getName()), String.format("$VmVersion %1$s", getVm().getCustomCompatibilityVersion().toString()), diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java index 5d17e6ffb89..ea28c0a7eb8 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/RunVmCommandTest.java @@ -44,6 +44,7 @@ import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import org.ovirt.engine.core.bll.context.CommandContext; +import org.ovirt.engine.core.bll.interfaces.BackendInternal; import org.ovirt.engine.core.bll.network.host.NetworkDeviceHelper; import org.ovirt.engine.core.bll.network.host.VfScheduler; import org.ovirt.engine.core.bll.scheduling.SchedulingManager; @@ -70,6 +71,8 @@ import org.ovirt.engine.core.common.businessentities.storage.StorageType; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.errors.EngineException; +import org.ovirt.engine.core.common.errors.EngineMessage; +import org.ovirt.engine.core.common.interfaces.ErrorTranslator; import org.ovirt.engine.core.common.interfaces.VDSBrokerFrontend; import org.ovirt.engine.core.common.osinfo.OsRepository; import org.ovirt.engine.core.common.utils.VmDeviceType; @@ -78,6 +81,7 @@ import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.Version; +import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dao.DiskImageDao; import org.ovirt.engine.core.dao.SnapshotDao; import org.ovirt.engine.core.dao.StorageServerConnectionDao; @@ -159,6 +163,12 @@ public class RunVmCommandTest extends BaseCommandTest { @Mock private ResourceManager resourceManager; + @Mock + private BackendInternal backend; + + @Mock + private AuditLogDirector auditLogDirector; + private static final String ACTIVE_ISO_PREFIX = "/rhev/data-center/mnt/some_computer/f6bccab4-e2f5-4e02-bba0-5748a7bc07b6/images/11111111-1111-1111-1111-111111111111"; private static final String INACTIVE_ISO_PREFIX = ""; @@ -376,6 +386,7 @@ public void setUp() { doNothing().when(command).initParametersForExternalNetworks(null, false); doReturn(Collections.emptyMap()).when(command).flushPassthroughVnicToVfMap(); doReturn(vmManager).when(command).getVmManager(); + when(backend.getErrorsTranslator()).thenReturn(mock(ErrorTranslator.class)); mockBackend(); } @@ -402,6 +413,73 @@ public void testValidate() { ValidateTestUtils.runAndAssertValidateSuccess(command); } + @Test + @MockedConfig("mockConfiguration") + public void testValidateFailsOnOlderCustomCompatibilityVersionWhenVmDown() { + final VM vm = new VM(); + vm.setStatus(VMStatus.Down); + 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.runAndAssertValidateFailure(command, + EngineMessage.ACTION_TYPE_FAILED_VM_COMPATIBILITY_VERSION_NOT_SUPPORTED); + } + + @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); + } + public static Stream validateUnsupportedRng() { Set sourcesEmpty = new HashSet<>(); Set sourcesRandom = new HashSet<>();