This is an automated email from the ASF dual-hosted git repository. weizhou pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit e78b5cc3cc9bcfc50d23c7cce1d706483c748a08 Merge: 4884f52c908 98b9af29040 Author: Wei Zhou <[email protected]> AuthorDate: Wed Sep 24 09:27:08 2025 +0200 Merge remote-tracking branch 'apache/4.20' api/src/main/java/com/cloud/vm/UserVmService.java | 26 ++++++- .../com/cloud/vm/snapshot/VMSnapshotService.java | 3 + .../subsystem/api/storage/SnapshotDataFactory.java | 3 + .../subsystem/api/storage/VMSnapshotStrategy.java | 3 + .../java/com/cloud/storage/StorageManager.java | 2 +- .../com/cloud/vm/snapshot/VMSnapshotManager.java | 1 - .../com/cloud/vm/snapshot/dao/VMSnapshotDao.java | 2 + .../storage/snapshot/SnapshotDataFactoryImpl.java | 22 +++++- .../vmsnapshot/DefaultVMSnapshotStrategy.java | 10 +++ .../vmsnapshot/ScaleIOVMSnapshotStrategy.java | 10 +++ .../framework/jobs/impl/AsyncJobManagerImpl.java | 55 ++++++++++++++- .../com/cloud/hypervisor/HypervisorGuruBase.java | 16 +++-- .../main/java/com/cloud/vm/UserVmManagerImpl.java | 53 +++++++++------ .../cloud/vm/snapshot/VMSnapshotManagerImpl.java | 7 ++ .../cloudstack/vm/UnmanagedVMsManagerImpl.java | 79 +++++++--------------- .../cloudstack/vm/UnmanagedVMsManagerImplTest.java | 7 -- 16 files changed, 205 insertions(+), 94 deletions(-) diff --cc engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java index 2d9b1e67e09,1801c877893..a19fcb9eda8 --- a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java +++ b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java @@@ -500,18 -482,13 +500,28 @@@ public class DefaultVMSnapshotStrategy return StrategyPriority.DEFAULT; } + private boolean vmHasKvmDiskOnlySnapshot(UserVm vm) { + if (!Hypervisor.HypervisorType.KVM.equals(vm.getHypervisorType())) { + return false; + } + + for (VMSnapshotVO vmSnapshotVO : vmSnapshotDao.findByVmAndByType(vm.getId(), VMSnapshot.Type.Disk)) { + List<VMSnapshotDetailsVO> vmSnapshotDetails = vmSnapshotDetailsDao.listDetails(vmSnapshotVO.getId()); + if (vmSnapshotDetails.stream().anyMatch(vmSnapshotDetailsVO -> vmSnapshotDetailsVO.getName().equals(KVM_FILE_BASED_STORAGE_SNAPSHOT))) { + return true; + } + } + + return false; + } ++ + @Override + public void updateOperationFailed(VMSnapshot vmSnapshot) throws NoTransitionException { + try { + vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed); + } catch (NoTransitionException e) { + logger.debug("Failed to change vm snapshot state with event OperationFailed"); + throw e; + } + } } diff --cc framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java index ea7de4f79c6,80140b0d950..7672b9dc6f9 --- a/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java +++ b/framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java @@@ -35,9 -35,13 +35,14 @@@ import java.util.concurrent.TimeUnit import javax.inject.Inject; import javax.naming.ConfigurationException; + import com.cloud.storage.SnapshotVO; + import com.cloud.vm.snapshot.VMSnapshot; + import com.cloud.vm.snapshot.VMSnapshotService; + import com.cloud.vm.snapshot.VMSnapshotVO; + import com.cloud.vm.snapshot.dao.VMSnapshotDao; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.command.ReconcileCommandService; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; diff --cc server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java index 1aa9a1af3fa,4f14fe20dac..d40b5b22698 --- a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java @@@ -23,7 -23,7 +23,8 @@@ import java.util.UUID import javax.inject.Inject; +import com.cloud.agent.api.to.GPUDeviceTO; + import com.cloud.cpu.CPU; import com.cloud.dc.DataCenter; import com.cloud.dc.dao.DataCenterDao; import com.cloud.domain.Domain; @@@ -312,15 -308,18 +313,20 @@@ public abstract class HypervisorGuruBas to.setNics(nics); to.setDisks(vmProfile.getDisks().toArray(new DiskTO[vmProfile.getDisks().size()])); - if (vmProfile.getTemplate().getBits() == 32) { - to.setArch("i686"); - } else if("s390x".equals(System.getProperty("os.arch"))) { - to.setArch("s390x"); + CPU.CPUArch templateArch = vmProfile.getTemplate().getArch(); + if (templateArch != null) { + to.setArch(templateArch.getType()); } else { - to.setArch("x86_64"); + if (vmProfile.getTemplate().getBits() == 32) { + to.setArch(CPU.CPUArch.x86.getType()); ++ } else if("s390x".equals(System.getProperty("os.arch"))) { ++ to.setArch("s390x"); + } else { + to.setArch(CPU.CPUArch.amd64.getType()); + } } - Map<String, String> detailsInVm = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); + Map<String, String> detailsInVm = _vmInstanceDetailsDao.listDetailsKeyPairs(vm.getId()); if (detailsInVm != null) { to.setDetails(detailsInVm); addExtraConfig(detailsInVm, to, vm.getAccountId(), vm.getHypervisorType()); diff --cc server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index cff0b15f9dd,5b3284c2c1e..187d4093447 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@@ -9378,28 -9003,33 +9386,33 @@@ public class UserVmManagerImpl extends final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKeys, final String hostName, final HypervisorType hypervisorType, final Map<String, String> customParameters, final VirtualMachine.PowerState powerState, final LinkedHashMap<String, List<NicProfile>> networkNicMap) throws InsufficientCapacityException { - if (zone == null) { - throw new InvalidParameterValueException("Unable to import virtual machine with invalid zone"); - } - if (host == null && hypervisorType == HypervisorType.VMware) { - throw new InvalidParameterValueException("Unable to import virtual machine with invalid host"); - } + return Transaction.execute((TransactionCallbackWithException<UserVm, InsufficientCapacityException>) status -> { + if (zone == null) { + throw new InvalidParameterValueException("Unable to import virtual machine with invalid zone"); + } + if (host == null && hypervisorType == HypervisorType.VMware) { + throw new InvalidParameterValueException("Unable to import virtual machine with invalid host"); + } - final long id = _vmDao.getNextInSequence(Long.class, "id"); + final long id = _vmDao.getNextInSequence(Long.class, "id"); + String instanceName = StringUtils.isBlank(instanceNameInternal) ? + getInternalName(owner.getAccountId(), id) : + instanceNameInternal; - if (hostName != null) { - // Check is hostName is RFC compliant - checkNameForRFCCompliance(hostName); - } + if (hostName != null) { + // Check is hostName is RFC compliant + checkNameForRFCCompliance(hostName); + } - final String uuidName = _uuidMgr.generateUuid(UserVm.class, null); - final Host lastHost = powerState != VirtualMachine.PowerState.PowerOn ? host : null; - final Boolean dynamicScalingEnabled = checkIfDynamicScalingCanBeEnabled(null, serviceOffering, template, zone.getId()); - return commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, - null, null, userData, null, null, isDisplayVm, keyboard, - accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), sshPublicKeys, networkNicMap, - id, instanceName, uuidName, hypervisorType, customParameters, - null, null, null, powerState, dynamicScalingEnabled, null, serviceOffering.getDiskOfferingId(), null, null, null, null); + final String uuidName = _uuidMgr.generateUuid(UserVm.class, null); + final Host lastHost = powerState != VirtualMachine.PowerState.PowerOn ? host : null; + final Boolean dynamicScalingEnabled = checkIfDynamicScalingCanBeEnabled(null, serviceOffering, template, zone.getId()); + return commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, + null, null, userData, null, null, isDisplayVm, keyboard, + accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), sshPublicKeys, networkNicMap, + id, instanceName, uuidName, hypervisorType, customParameters, - null, null, null, powerState, dynamicScalingEnabled, null, serviceOffering.getDiskOfferingId(), null); ++ null, null, null, powerState, dynamicScalingEnabled, null, serviceOffering.getDiskOfferingId(), null, null, null, null); + }); } @Override diff --cc server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java index 80dbb451530,26f7603240f..0dae0c265fc --- a/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java @@@ -110,7 -111,7 +110,8 @@@ import com.cloud.utils.db.TransactionCa import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.UserVmDetailVO; ++import com.cloud.utils.fsm.NoTransitionException; +import com.cloud.vm.VMInstanceDetailVO; import com.cloud.vm.UserVmManager; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO;
