Copilot commented on code in PR #13178:
URL: https://github.com/apache/cloudstack/pull/13178#discussion_r3257574063


##########
server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java:
##########
@@ -3927,6 +3924,137 @@ public void createVirtualMachineWithExistingSnapshot() 
throws ResourceUnavailabl
         userVmManagerImpl.createVirtualMachine(deployVMCmd);
     }
 
+    /**
+     * Bug fix: when deploying a VM from a snapshot whose source volume 
resided on
+     * local (HOST-scoped) storage, the zone-wide pool check must be skipped.
+     * The source volume's pool type is irrelevant – only the snapshot matters.
+     */
+    @Test
+    public void 
createVirtualMachineWithSnapshotFromExpungedLocalStorageVolumeSucceeds()
+            throws ResourceUnavailableException, 
InsufficientCapacityException, ResourceAllocationException {

Review Comment:
   The test name/Javadoc says it covers a snapshot whose *source volume is on 
HOST-scoped (local) storage*, but the setup never stubs 
volumeInfo.getDataStore()/scope to return HOST. As written, this test 
effectively exercises the same “null data store” path (Mockito default) as the 
next test, so it doesn’t validate the intended regression. Please explicitly 
mock the data store scope to HOST here (or rename/remove the test to avoid 
misleading/duplicated coverage).



##########
server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java:
##########
@@ -3927,6 +3924,137 @@ public void createVirtualMachineWithExistingSnapshot() 
throws ResourceUnavailabl
         userVmManagerImpl.createVirtualMachine(deployVMCmd);
     }
 
+    /**
+     * Bug fix: when deploying a VM from a snapshot whose source volume 
resided on
+     * local (HOST-scoped) storage, the zone-wide pool check must be skipped.
+     * The source volume's pool type is irrelevant – only the snapshot matters.
+     */
+    @Test
+    public void 
createVirtualMachineWithSnapshotFromExpungedLocalStorageVolumeSucceeds()
+            throws ResourceUnavailableException, 
InsufficientCapacityException, ResourceAllocationException {
+        DeployVMCmd deployVMCmd = new DeployVMCmd();
+        ReflectionTestUtils.setField(deployVMCmd, "zoneId", zoneId);
+        ReflectionTestUtils.setField(deployVMCmd, "serviceOfferingId", 
serviceOfferingId);
+        ReflectionTestUtils.setField(deployVMCmd, "snapshotId", snashotId);
+        deployVMCmd._accountService = accountService;
+
+        when(accountService.finalyzeAccountId(nullable(String.class), 
nullable(Long.class), nullable(Long.class), eq(true))).thenReturn(accountId);
+        
when(accountService.getActiveAccountById(accountId)).thenReturn(account);
+        when(entityManager.findById(DataCenter.class, 
zoneId)).thenReturn(_dcMock);
+        when(entityManager.findById(ServiceOffering.class, 
serviceOfferingId)).thenReturn(serviceOffering);
+        when(snapshotDaoMock.findById(snashotId)).thenReturn(snapshotMock);
+        when(snapshotMock.getVolumeId()).thenReturn(volumeId);
+        when(volumeDataFactory.getVolume(volumeId)).thenReturn(volumeInfo);
+        when(volumeInfo.getTemplateId()).thenReturn(templateId);
+        when(volumeInfo.getInstanceId()).thenReturn(null);
+        
when(entityManager.findByIdIncludingRemoved(VirtualMachineTemplate.class, 
templateId)).thenReturn(templateMock);
+        
when(templateMock.getTemplateType()).thenReturn(Storage.TemplateType.VNF);
+        
when(templateMock.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
+        when(templateMock.isDeployAsIs()).thenReturn(false);
+        when(templateMock.getFormat()).thenReturn(Storage.ImageFormat.QCOW2);
+        when(templateMock.getUserDataId()).thenReturn(null);
+        
Mockito.doNothing().when(vnfTemplateManager).validateVnfApplianceNics(any(), 
nullable(List.class), any());
+        when(_dcMock.isLocalStorageEnabled()).thenReturn(true);
+        
when(_dcMock.getNetworkType()).thenReturn(DataCenter.NetworkType.Basic);
+        
Mockito.doReturn(userVmVoMock).when(userVmManagerImpl).createBasicSecurityGroupVirtualMachine(any(),
 any(), any(), any(), any(), any(), any(),
+                any(), any(), any(), any(), any(), any(), any(), any(), any(), 
any(), any(), any(), nullable(Boolean.class), any(), any(), any(),
+                any(), any(), any(), any(), eq(true), any(), any(), any());
+
+        // Must NOT throw "Deployment of virtual machine is supported only for 
Zone-wide storage pools"
+        userVmManagerImpl.createVirtualMachine(deployVMCmd);
+    }
+
+    /**
+     * Bug fix: when deploying a VM from a snapshot whose source volume's 
storage pool
+     * was expunged (data store is null), the zone-wide pool check must be 
skipped.
+     */
+    @Test
+    public void 
createVirtualMachineWithSnapshotFromVolumeWithNullDataStoreSucceeds()
+            throws ResourceUnavailableException, 
InsufficientCapacityException, ResourceAllocationException {
+        DeployVMCmd deployVMCmd = new DeployVMCmd();

Review Comment:
   These two snapshot-success tests are nearly identical; with the current 
stubbing they both pass with a null data store and don’t differentiate 
local(HOST)-scoped vs expunged/null-datastore scenarios. Consider consolidating 
them or making one explicitly HOST-scoped and the other explicitly null 
datastore to keep the intent and coverage clear.



##########
server/src/main/java/com/cloud/vm/UserVmManagerImpl.java:
##########
@@ -6413,7 +6413,13 @@ public UserVm createVirtualMachine(DeployVMCmd cmd) 
throws InsufficientCapacityE
             }
             _accountMgr.checkAccess(caller, null, true, snapshot);
             VolumeInfo volumeOfSnapshot = getVolume(snapshot.getVolumeId(), 
templateId, true);
-            templateId = volumeOfSnapshot.getTemplateId();
+            if (volumeOfSnapshot != null) {
+                templateId = volumeOfSnapshot.getTemplateId();
+            } else if (templateId == null) {
+                throw new InvalidParameterValueException(
+                        "Could not determine template from snapshot id=" + 
cmd.getSnapshotId() +
+                                "; the source volume no longer exists. Please 
specify a templateId.");

Review Comment:
   The error message asks users to specify "templateId", but the public API 
parameter is named "templateid" (ApiConstants.TEMPLATE_ID). To reduce confusion 
for API users/UI, consider referencing the actual parameter name (e.g., 
"templateid") or wording it as "template id".
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to