You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by we...@apache.org on 2024/04/12 15:03:14 UTC

(cloudstack) branch main updated (19f79b1d94f -> 45daa1ce591)

This is an automated email from the ASF dual-hosted git repository.

weizhou pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


    from 19f79b1d94f Merge branch '4.19'
     add b998e7dbb63 Allow overriding root disk offering & size, and expunge old root disk while restoring a VM (#8800)
     add 44aa08c02a3 Fixup 4.19 build issue (#8905)
     new 45daa1ce591 Merge remote-tracking branch 'apache/4.19'

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/com/cloud/storage/VolumeApiService.java   |   2 +
 api/src/main/java/com/cloud/vm/UserVmService.java  |   2 +-
 .../api/command/user/vm/RestoreVMCmd.java          |  45 ++-
 .../java/com/cloud/vm/VirtualMachineManager.java   |   2 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java    |  18 +-
 .../src/main/java/com/cloud/vm/VmWorkRestore.java  |  27 +-
 .../engine/orchestration/CloudOrchestrator.java    |   7 +-
 .../engine/orchestration/VolumeOrchestrator.java   |  65 ++---
 .../com/cloud/storage/VolumeApiServiceImpl.java    |  14 +-
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  | 124 +++++++--
 .../cloudstack/vm/UnmanagedVMsManagerImpl.java     |  11 +-
 .../java/com/cloud/vm/UserVmManagerImplTest.java   |  26 +-
 ui/src/config/section/compute.js                   |  27 +-
 ui/src/views/compute/ReinstallVm.vue               | 307 +++++++++++++++++++++
 14 files changed, 542 insertions(+), 135 deletions(-)
 create mode 100644 ui/src/views/compute/ReinstallVm.vue


(cloudstack) 01/01: Merge remote-tracking branch 'apache/4.19'

Posted by we...@apache.org.
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 45daa1ce591a43442c30cc6ec9a70124440063eb
Merge: 19f79b1d94f 44aa08c02a3
Author: Wei Zhou <we...@apache.org>
AuthorDate: Fri Apr 12 16:40:07 2024 +0200

    Merge remote-tracking branch 'apache/4.19'

 .../java/com/cloud/storage/VolumeApiService.java   |   2 +
 api/src/main/java/com/cloud/vm/UserVmService.java  |   2 +-
 .../api/command/user/vm/RestoreVMCmd.java          |  45 ++-
 .../java/com/cloud/vm/VirtualMachineManager.java   |   2 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java    |  18 +-
 .../src/main/java/com/cloud/vm/VmWorkRestore.java  |  27 +-
 .../engine/orchestration/CloudOrchestrator.java    |   7 +-
 .../engine/orchestration/VolumeOrchestrator.java   |  65 ++---
 .../com/cloud/storage/VolumeApiServiceImpl.java    |  14 +-
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  | 124 +++++++--
 .../cloudstack/vm/UnmanagedVMsManagerImpl.java     |  11 +-
 .../java/com/cloud/vm/UserVmManagerImplTest.java   |  26 +-
 ui/src/config/section/compute.js                   |  27 +-
 ui/src/views/compute/ReinstallVm.vue               | 307 +++++++++++++++++++++
 14 files changed, 542 insertions(+), 135 deletions(-)

diff --cc api/src/main/java/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java
index e1c4dd5f678,17c4e97eb3b..3839049eee5
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java
@@@ -16,9 -16,12 +16,9 @@@
  // under the License.
  package org.apache.cloudstack.api.command.user.vm;
  
- import org.apache.cloudstack.api.ApiCommandResourceType;
- 
+ import com.cloud.vm.VmDetailConstants;
 -import org.apache.cloudstack.api.ApiCommandResourceType;
 -import org.apache.cloudstack.api.response.DiskOfferingResponse;
 -import org.apache.log4j.Logger;
 -
  import org.apache.cloudstack.acl.SecurityChecker.AccessType;
++import org.apache.cloudstack.api.ApiCommandResourceType;
  import org.apache.cloudstack.api.ACL;
  import org.apache.cloudstack.api.APICommand;
  import org.apache.cloudstack.api.ApiConstants;
@@@ -28,6 -31,6 +28,7 @@@ import org.apache.cloudstack.api.Parame
  import org.apache.cloudstack.api.ResponseObject.ResponseView;
  import org.apache.cloudstack.api.ServerApiException;
  import org.apache.cloudstack.api.command.user.UserCmd;
++import org.apache.cloudstack.api.response.DiskOfferingResponse;
  import org.apache.cloudstack.api.response.TemplateResponse;
  import org.apache.cloudstack.api.response.UserVmResponse;
  import org.apache.cloudstack.context.CallContext;
diff --cc engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index 4372741de66,243613907ff..9f743668cd5
--- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@@ -5691,8 -5610,20 +5691,8 @@@ public class VirtualMachineManagerImpl 
          return workJob;
      }
  
 -    protected void resourceCountIncrement (long accountId, Long cpu, Long memory) {
 -        _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm);
 -        _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.cpu, cpu);
 -        _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.memory, memory);
 -    }
 -
 -    protected void resourceCountDecrement (long accountId, Long cpu, Long memory) {
 -        _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.user_vm);
 -        _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.cpu, cpu);
 -        _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, memory);
 -    }
 -
      @Override
-     public UserVm restoreVirtualMachine(final long vmId, final Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException {
+     public UserVm restoreVirtualMachine(final long vmId, final Long newTemplateId, final Long rootDiskOfferingId, final boolean expunge, final Map<String, String> details) throws ResourceUnavailableException, InsufficientCapacityException {
          final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
          if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
              VmWorkJobVO placeHolder = null;
@@@ -5722,14 -5653,14 +5722,14 @@@
          }
      }
  
-     private UserVm orchestrateRestoreVirtualMachine(final long vmId, final Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException {
-         logger.debug("Restoring vm " + vmId + " with new templateId " + newTemplateId);
+     private UserVm orchestrateRestoreVirtualMachine(final long vmId, final Long newTemplateId, final Long rootDiskOfferingId, final boolean expunge, final Map<String, String> details) throws ResourceUnavailableException, InsufficientCapacityException {
 -        s_logger.debug("Restoring vm " + vmId + " with templateId : " + newTemplateId + " diskOfferingId : " + rootDiskOfferingId + " details : " + details);
++        logger.debug("Restoring vm " + vmId + " with templateId : " + newTemplateId + " diskOfferingId : " + rootDiskOfferingId + " details : " + details);
          final CallContext context = CallContext.current();
          final Account account = context.getCallingAccount();
-         return _userVmService.restoreVirtualMachine(account, vmId, newTemplateId);
+         return _userVmService.restoreVirtualMachine(account, vmId, newTemplateId, rootDiskOfferingId, expunge, details);
      }
  
-     public Outcome<VirtualMachine> restoreVirtualMachineThroughJobQueue(final long vmId, final Long newTemplateId) {
+     public Outcome<VirtualMachine> restoreVirtualMachineThroughJobQueue(final long vmId, final Long newTemplateId, final Long rootDiskOfferingId, final boolean expunge, Map<String, String> details) {
          String commandName = VmWorkRestore.class.getName();
          Pair<VmWorkJobVO, Long> pendingWorkJob = retrievePendingWorkJob(vmId, commandName);
  
diff --cc server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 97bfef9a95d,566fcb38fc9..d76713b73cb
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@@ -7825,20 -7697,38 +7848,38 @@@ public class UserVmManagerImpl extends 
              ex.addProxyObject(String.valueOf(vmId), "vmId");
              throw ex;
          }
- 
          _accountMgr.checkAccess(caller, null, true, vm);
  
+         DiskOffering diskOffering = rootDiskOfferingId != null ? validateAndGetDiskOffering(rootDiskOfferingId, vm, caller) : null;
+         VMTemplateVO template = _templateDao.findById(newTemplateId);
+         if (template.getSize() != null) {
+             String rootDiskSize = details.get(VmDetailConstants.ROOT_DISK_SIZE);
+             Long templateSize = template.getSize();
+             if (StringUtils.isNumeric(rootDiskSize)) {
+                 if (Long.parseLong(rootDiskSize) * GiB_TO_BYTES < templateSize) {
+                     throw new InvalidParameterValueException(String.format("Root disk size [%s] is smaller than the template size [%s]", rootDiskSize, templateSize));
+                 }
+             } else if (diskOffering != null && diskOffering.getDiskSize() < templateSize) {
+                 throw new InvalidParameterValueException(String.format("Disk size for selected offering [%s] is less than the template's size [%s]", diskOffering.getDiskSize(), templateSize));
+             }
+         }
+ 
          //check if there are any active snapshots on volumes associated with the VM
 -        s_logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
 +        logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
          if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) {
              throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, Re-install VM is not permitted, please try again later.");
          }
 -        s_logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
 +        logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
-         return restoreVMInternal(caller, vm, newTemplateId);
+         return restoreVMInternal(caller, vm, newTemplateId, rootDiskOfferingId, expunge, details);
      }
  
-     public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) throws InsufficientCapacityException, ResourceUnavailableException {
-         return _itMgr.restoreVirtualMachine(vm.getId(), newTemplateId);
+     public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId, Long rootDiskOfferingId, boolean expunge, Map<String, String> details) throws InsufficientCapacityException, ResourceUnavailableException {
+         return _itMgr.restoreVirtualMachine(vm.getId(), newTemplateId, rootDiskOfferingId, expunge, details);
+     }
+ 
+ 
+     public UserVm restoreVMInternal(Account caller, UserVmVO vm) throws InsufficientCapacityException, ResourceUnavailableException {
+         return restoreVMInternal(caller, vm, null, null, false, null);
      }
  
      private VMTemplateVO getRestoreVirtualMachineTemplate(Account caller, Long newTemplateId, List<VolumeVO> rootVols, UserVmVO vm) {
diff --cc server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
index 07d2e9bd59f,303a9b08b1c..1292b9e230c
--- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
+++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
@@@ -1450,131 -1379,6 +1436,131 @@@ public class UserVmManagerImplTest 
          vmSnapshots.add(vmSnapshot);
          when(vmSnapshotDaoMock.findByVm(vmId)).thenReturn(vmSnapshots);
  
-         userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId);
+         userVmManagerImpl.restoreVirtualMachine(accountMock, vmId, newTemplateId, null, false, null);
      }
 +
 +    @Test
 +    public void addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecifiedTestDetailsConstantIsNotNullDoNothing() {
 +        int currentValue = 123;
 +
 +        for (String detailsConstant : detailsConstants) {
 +            userVmManagerImpl.addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecified(null, customParameters, detailsConstant, currentValue);
 +        }
 +
 +        Assert.assertEquals(customParameters.get(VmDetailConstants.MEMORY), "2048");
 +        Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_NUMBER), "4");
 +        Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_SPEED), "1000");
 +    }
 +
 +    @Test
 +    public void addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecifiedTestNewValueIsNotNullDoNothing() {
 +        Map<String, String> details = new HashMap<>();
 +        int currentValue = 123;
 +
 +        for (String detailsConstant : detailsConstants) {
 +            userVmManagerImpl.addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecified(321, details, detailsConstant, currentValue);
 +        }
 +
 +        Assert.assertNull(details.get(VmDetailConstants.MEMORY));
 +        Assert.assertNull(details.get(VmDetailConstants.CPU_NUMBER));
 +        Assert.assertNull(details.get(VmDetailConstants.CPU_SPEED));
 +    }
 +
 +    @Test
 +    public void addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecifiedTestBothValuesAreNullKeepCurrentValue() {
 +        Map<String, String> details = new HashMap<>();
 +        int currentValue = 123;
 +
 +        for (String detailsConstant : detailsConstants) {
 +            userVmManagerImpl.addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecified(null, details, detailsConstant, currentValue);
 +        }
 +
 +        Assert.assertEquals(details.get(VmDetailConstants.MEMORY), String.valueOf(currentValue));
 +        Assert.assertEquals(details.get(VmDetailConstants.CPU_NUMBER), String.valueOf(currentValue));
 +        Assert.assertEquals(details.get(VmDetailConstants.CPU_SPEED),String.valueOf(currentValue));
 +    }
 +
 +    @Test
 +    public void addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecifiedTestNeitherValueIsNullDoNothing() {
 +        int currentValue = 123;
 +
 +        for (String detailsConstant : detailsConstants) {
 +            userVmManagerImpl.addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecified(321, customParameters, detailsConstant, currentValue);
 +        }
 +
 +        Assert.assertEquals(customParameters.get(VmDetailConstants.MEMORY), "2048");
 +        Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_NUMBER), "4");
 +        Assert.assertEquals(customParameters.get(VmDetailConstants.CPU_SPEED),"1000");
 +    }
 +
 +    @Test
 +    public void updateInstanceDetailsMapWithCurrentValuesForAbsentDetailsTestAllConstantsAreUpdated() {
 +        Mockito.doReturn(serviceOffering).when(_serviceOfferingDao).findById(Mockito.anyLong());
 +        Mockito.doReturn(1L).when(vmInstanceMock).getId();
 +        Mockito.doReturn(1L).when(vmInstanceMock).getServiceOfferingId();
 +        Mockito.doReturn(serviceOffering).when(_serviceOfferingDao).findByIdIncludingRemoved(Mockito.anyLong(), Mockito.anyLong());
 +        userVmManagerImpl.updateInstanceDetailsMapWithCurrentValuesForAbsentDetails(null, vmInstanceMock, 0l);
 +
 +        Mockito.verify(userVmManagerImpl).addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecified(Mockito.any(), Mockito.any(), Mockito.eq(VmDetailConstants.CPU_SPEED), Mockito.any());
 +        Mockito.verify(userVmManagerImpl).addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecified(Mockito.any(), Mockito.any(), Mockito.eq(VmDetailConstants.MEMORY), Mockito.any());
 +        Mockito.verify(userVmManagerImpl).addCurrentDetailValueToInstanceDetailsMapIfNewValueWasNotSpecified(Mockito.any(), Mockito.any(), Mockito.eq(VmDetailConstants.CPU_NUMBER), Mockito.any());
 +    }
 +
 +    @Test
 +    public void testCheckVolumesLimits() {
 +        userVmManagerImpl.resourceLimitService = resourceLimitMgr;
 +        long diskOffId1 = 1L;
 +        DiskOfferingVO diskOfferingVO1 = Mockito.mock(DiskOfferingVO.class);
 +        Mockito.when(diskOfferingDao.findById(diskOffId1)).thenReturn(diskOfferingVO1);
 +        Mockito.when(resourceLimitMgr.getResourceLimitStorageTags(diskOfferingVO1)).thenReturn(List.of("tag1", "tag2"));
 +        long diskOffId2 = 2L;
 +        DiskOfferingVO diskOfferingVO2 = Mockito.mock(DiskOfferingVO.class);
 +        Mockito.when(diskOfferingDao.findById(diskOffId2)).thenReturn(diskOfferingVO2);
 +        Mockito.when(resourceLimitMgr.getResourceLimitStorageTags(diskOfferingVO2)).thenReturn(List.of("tag2"));
 +        long diskOffId3 = 3L;
 +        DiskOfferingVO diskOfferingVO3 = Mockito.mock(DiskOfferingVO.class);
 +        Mockito.when(diskOfferingDao.findById(diskOffId3)).thenReturn(diskOfferingVO3);
 +        Mockito.when(resourceLimitMgr.getResourceLimitStorageTags(diskOfferingVO3)).thenReturn(new ArrayList<>());
 +
 +        VolumeVO vol1 = Mockito.mock(VolumeVO.class);
 +        Mockito.when(vol1.getDiskOfferingId()).thenReturn(diskOffId1);
 +        Mockito.when(vol1.getSize()).thenReturn(10L);
 +        Mockito.when(vol1.isDisplay()).thenReturn(true);
 +        VolumeVO undisplayedVolume = Mockito.mock(VolumeVO.class); // shouldn't be considered for limits
 +        Mockito.when(undisplayedVolume.isDisplay()).thenReturn(false);
 +        VolumeVO vol3 = Mockito.mock(VolumeVO.class);
 +        Mockito.when(vol3.getDiskOfferingId()).thenReturn(diskOffId2);
 +        Mockito.when(vol3.getSize()).thenReturn(30L);
 +        Mockito.when(vol3.isDisplay()).thenReturn(true);
 +        VolumeVO vol4 = Mockito.mock(VolumeVO.class);
 +        Mockito.when(vol4.getDiskOfferingId()).thenReturn(diskOffId3);
 +        Mockito.when(vol4.getSize()).thenReturn(40L);
 +        Mockito.when(vol4.isDisplay()).thenReturn(true);
 +        VolumeVO vol5 = Mockito.mock(VolumeVO.class);
 +        Mockito.when(vol5.getDiskOfferingId()).thenReturn(diskOffId1);
 +        Mockito.when(vol5.getSize()).thenReturn(50L);
 +        Mockito.when(vol5.isDisplay()).thenReturn(true);
 +
 +        List<VolumeVO> volumes = List.of(vol1, undisplayedVolume, vol3, vol4, vol5);
 +        Long size = volumes.stream().filter(VolumeVO::isDisplay).mapToLong(VolumeVO::getSize).sum();
 +        try {
 +            userVmManagerImpl.checkVolumesLimits(account, volumes);
 +            Mockito.verify(resourceLimitMgr, Mockito.times(1))
 +                    .checkResourceLimit(account, Resource.ResourceType.volume, 4);
 +            Mockito.verify(resourceLimitMgr, Mockito.times(1))
 +                    .checkResourceLimit(account, Resource.ResourceType.primary_storage, size);
 +            Mockito.verify(resourceLimitMgr, Mockito.times(1))
 +                    .checkResourceLimitWithTag(account, Resource.ResourceType.volume, "tag1", 2);
 +            Mockito.verify(resourceLimitMgr, Mockito.times(1))
 +                    .checkResourceLimitWithTag(account, Resource.ResourceType.volume, "tag2", 3);
 +            Mockito.verify(resourceLimitMgr, Mockito.times(1))
 +                    .checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, "tag1",
 +                            vol1.getSize() + vol5.getSize());
 +            Mockito.verify(resourceLimitMgr, Mockito.times(1))
 +                    .checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, "tag2",
 +                            vol1.getSize() + vol3.getSize() + vol5.getSize());
 +        } catch (ResourceAllocationException e) {
 +            Assert.fail(e.getMessage());
 +        }
 +    }
  }