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


##########
server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java:
##########
@@ -2728,6 +2766,41 @@ private UserVm importKvmVirtualMachineFromDisk(final 
ImportSource importSource,
         }
     }
 
+    private void checkVmResourceLimitsForExternalKvmVmImport(Account owner, 
ServiceOfferingVO serviceOffering, VMTemplateVO template, Map<String, String> 
details, List<Reserver> reservations) throws ResourceAllocationException {
+        // When importing an external VM, the amount of CPUs and memory is 
always obtained from the compute offering,
+        // unlike the unmanaged instance import that obtains it from the 
hypervisor unless the VM is powered off and the offering is fixed
+        Integer cpu = serviceOffering.getCpu();
+        Integer memory = serviceOffering.getRamSize();
+
+        if (serviceOffering.isDynamic()) {
+            cpu = getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details);
+            memory = getDetailAsInteger(VmDetailConstants.MEMORY, details);
+        }
+
+        List<String> resourceLimitHostTags = 
resourceLimitService.getResourceLimitHostTags(serviceOffering, template);
+
+        CheckedReservation vmReservation = new CheckedReservation(owner, 
Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, 
resourceLimitService);
+        reservations.add(vmReservation);
+
+        CheckedReservation cpuReservation = new CheckedReservation(owner, 
Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), 
reservationDao, resourceLimitService);
+        reservations.add(cpuReservation);
+
+        CheckedReservation memReservation = new CheckedReservation(owner, 
Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), 
reservationDao, resourceLimitService);
+        reservations.add(memReservation);
+    }

Review Comment:
   New VM resource-limit selection logic (dynamic vs fixed offering, 
powered-off vs running unmanaged VM, and parsing CPU/memory from `details`) is 
not covered by unit tests in `UnmanagedVMsManagerImplTest`. Add focused tests 
for: (1) unmanaged import with null/unknown powerState, (2) external import 
with dynamic offering reading `cpuNumber`/`memory`, and (3) validation failures 
for missing/invalid values, to prevent regressions back to NPEs.



##########
server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java:
##########
@@ -1634,6 +1670,10 @@ protected UserVm 
importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
             Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = 
getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, 
clusterName, sourceHostName, sourceVMName);
             sourceVMwareInstance = sourceInstanceDetails.first();
             isClonedInstance = sourceInstanceDetails.second();
+
+            // Ensure that the configured resource limits will not be exceeded 
before beggining the conversion process

Review Comment:
   Typo in comment: “beggining” → “beginning”.
   ```suggestion
               // Ensure that the configured resource limits will not be 
exceeded before beginning the conversion process
   ```



##########
server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java:
##########
@@ -2728,6 +2766,41 @@ private UserVm importKvmVirtualMachineFromDisk(final 
ImportSource importSource,
         }
     }
 
+    private void checkVmResourceLimitsForExternalKvmVmImport(Account owner, 
ServiceOfferingVO serviceOffering, VMTemplateVO template, Map<String, String> 
details, List<Reserver> reservations) throws ResourceAllocationException {
+        // When importing an external VM, the amount of CPUs and memory is 
always obtained from the compute offering,
+        // unlike the unmanaged instance import that obtains it from the 
hypervisor unless the VM is powered off and the offering is fixed
+        Integer cpu = serviceOffering.getCpu();
+        Integer memory = serviceOffering.getRamSize();
+
+        if (serviceOffering.isDynamic()) {
+            cpu = getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details);
+            memory = getDetailAsInteger(VmDetailConstants.MEMORY, details);
+        }
+
+        List<String> resourceLimitHostTags = 
resourceLimitService.getResourceLimitHostTags(serviceOffering, template);
+
+        CheckedReservation vmReservation = new CheckedReservation(owner, 
Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, 
resourceLimitService);
+        reservations.add(vmReservation);
+
+        CheckedReservation cpuReservation = new CheckedReservation(owner, 
Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), 
reservationDao, resourceLimitService);
+        reservations.add(cpuReservation);
+
+        CheckedReservation memReservation = new CheckedReservation(owner, 
Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), 
reservationDao, resourceLimitService);
+        reservations.add(memReservation);

Review Comment:
   `checkVmResourceLimitsForExternalKvmVmImport` can still throw an NPE: if 
`serviceOffering.getCpu()` / `getRamSize()` are null (e.g., custom offering 
metadata) and the offering is not treated as dynamic here, `cpu.longValue()` / 
`memory.longValue()` will crash. Add explicit validation (null/<=0) for cpu and 
memory (both for dynamic and non-dynamic) and throw a parameter/internal error 
before constructing reservations.



##########
server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java:
##########
@@ -1555,6 +1559,36 @@ private UserVm 
importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cl
         return userVm;
     }
 
+    private void checkVmResourceLimitsForUnmanagedInstanceImport(Account 
owner, UnmanagedInstanceTO unmanagedInstance, ServiceOfferingVO 
serviceOffering, VMTemplateVO template, List<Reserver> reservations) throws 
ResourceAllocationException {
+        // When importing a unmanaged instance, the amount of CPUs and memory 
is obtained from the hypervisor unless powered off
+        // and not using a dynamic offering, unlike the external VM import 
that always obtains it from the compute offering
+        Integer cpu = serviceOffering.getCpu();
+        Integer memory = serviceOffering.getRamSize();
+
+        if (serviceOffering.isDynamic() || 
!unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOff))
 {

Review Comment:
   `unmanagedInstance.getPowerState()` can be null (see UnmanagedInstanceTO), 
so calling `.equals(PowerOff)` here can throw an NPE during import. Make this 
null-safe (e.g., compare with `PowerOff.equals(...)` or treat null/unknown as 
not-PowerOff) so the resource-limit check can’t crash the import path.
   ```suggestion
           if (serviceOffering.isDynamic() || 
!UnmanagedInstanceTO.PowerState.PowerOff.equals(unmanagedInstance.getPowerState()))
 {
   ```



-- 
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