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


##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -614,7 +621,6 @@ public DomainResponse createDomainResponse(Domain domain) {
         if (domain.getChildCount() > 0) {
             domainResponse.setHasChild(true);
         }
-        populateDomainTags(domain.getUuid(), domainResponse);
         domainResponse.setObjectName("domain");

Review Comment:
   Direct domain responses no longer include resource tags. 
Create/update/move/list-domain-children all call this method, while the 
query-based list path still calls `populateDomainTags`, so these APIs now 
return inconsistent domain data. Restore the tag population before returning 
the response.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -5145,6 +5270,56 @@ public SSHKeyPairResponse 
createSSHKeyPairResponse(SSHKeyPair sshkeyPair, boolea
         return response;
     }
 
+    @Override
+    public ApiKeyPairResponse createKeyPairResponse(ApiKeyPair keyPair) {
+        ApiKeyPairResponse response = new ApiKeyPairResponse();
+        if (keyPair == null) {
+            return response;
+        }
+        response.setId(keyPair.getUuid());
+        response.setName(keyPair.getName());
+        response.setApiKey(keyPair.getApiKey());
+        response.setSecretKey(keyPair.getSecretKey());
+        response.setDescription(keyPair.getDescription());
+        response.setStartDate(keyPair.getStartDate());
+        response.setEndDate(keyPair.getEndDate());
+        response.setCreated(keyPair.getCreated());
+
+        // populate account
+        try {
+            Account account = 
ApiDBUtils.findAccountById(keyPair.getAccountId());
+            if (account != null && account.getType() != Account.Type.PROJECT) {
+                response.setAccountName(account.getAccountName());

Review Comment:
   This replacement of the existing key-pair mapper drops contract fields 
including `state`, `accountid`, `accounttype`, and all role metadata; it also 
omits the account name for project accounts. List/register key APIs will 
therefore return materially incomplete responses. Preserve the previous 
state/account/role population while moving the method.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -2901,10 +2922,7 @@ public NetworkResponse 
createNetworkResponse(ResponseView view, Network network)
             }
         }
 
-        if (CallContext.current().getCallingAccount().getType() == 
Account.Type.ADMIN &&
-                network.getVpcId() == null && network.getGuestType() == 
Network.GuestType.Isolated) {
-            
response.setKeepMacAddressOnPublicNic(network.getKeepMacAddressOnPublicNic());
-        }
+

Review Comment:
   Admin responses for isolated, non-VPC networks now omit 
`keepmacaddressonpublicnic`, although this remains a documented response field 
and is displayed by the UI. Restore the conditional population.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -1684,7 +1706,6 @@ public FirewallRuleResponse 
createPortForwardingRuleResponse(PortForwardingRule
 
         Network guestNtwk = ApiDBUtils.findNetworkById(fwRule.getNetworkId());
         response.setNetworkId(guestNtwk.getUuid());
-        response.setNetworkName(guestNtwk.getName());
 

Review Comment:
   This removal leaves the documented `networkname` field null for every 
port-forwarding-rule response even though `guestNtwk` has already been loaded. 
Restore the field assignment to avoid an unrelated API response regression.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -3588,7 +3595,7 @@ public VpcResponse createVpcResponse(ResponseView view, 
Vpc vpc) {
         if (voff != null) {
             response.setVpcOfferingId(voff.getUuid());
             response.setVpcOfferingName(voff.getName());
-            response.setVpcOfferingConserveMode(voff.isConserveMode());
+

Review Comment:
   The VPC response no longer reports whether its offering uses conserve mode, 
leaving the documented `vpcofferingconservemode` field null for all VPCs. 
Restore the assignment from the offering.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -1912,8 +1933,6 @@ public SystemVmResponse 
createSystemVmResponse(VirtualMachine vm) {
                             
vmResponse.setPublicNetmask(singleNicProfile.getIPv4Netmask());
                             
vmResponse.setGateway(singleNicProfile.getIPv4Gateway());
                         }
-                    } else if (network.getTrafficType() == 
TrafficType.Storage) {
-                        
vmResponse.setStorageIp(singleNicProfile.getIPv4Address());
                     }

Review Comment:
   Storage-network NICs are no longer handled, so `listSystemVms` loses the 
`storageip` value that the response contract and UI expose. Restore the storage 
traffic branch.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -3684,9 +3691,7 @@ public VpcResponse createVpcResponse(ResponseView view, 
Vpc vpc) {
             }
         }
 
-        if (CallContext.current().getCallingAccount().getType() == 
Account.Type.ADMIN) {
-            
response.setKeepMacAddressOnPublicNic(vpc.getKeepMacAddressOnPublicNic());
-        }
+

Review Comment:
   Admin VPC responses now omit `keepmacaddressonpublicnic`, despite the field 
remaining in the response contract and admin UI. Restore the value from the VPC.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -4785,7 +4911,7 @@ public NicSecondaryIpResponse 
createSecondaryIPToNicResponse(NicSecondaryIp resu
         setResponseIpAddress(result, response);
         response.setNicId(nic.getUuid());
         response.setNwId(network.getUuid());
-        response.setDescription(result.getDescription());
+

Review Comment:
   The standalone secondary-IP response now drops its documented description 
even when the entity contains one. Restore the mapping so callers of this 
response path retain the value.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -4872,7 +4998,7 @@ public NicResponse createNicResponse(Nic result) {
                 for (NicSecondaryIpVO ip : secondaryIps) {
                     NicSecondaryIpResponse ipRes = new 
NicSecondaryIpResponse();
                     ipRes.setId(ip.getUuid());
-                    ipRes.setDescription(ip.getDescription());
+

Review Comment:
   Secondary IPs embedded in NIC responses now lose their descriptions because 
the mapping was removed. Restore it for parity with the secondary-IP entity and 
response contract.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -3981,14 +3986,7 @@ public Site2SiteCustomerGatewayResponse 
createSite2SiteCustomerGatewayResponse(S
         response.setIkeVersion(result.getIkeVersion());
         response.setSplitConnections(result.getSplitConnections());
 
-        Set<String> obsoleteParameters = 
site2SiteVpnManager.getObsoleteVpnGatewayParameters(result);
-        if (CollectionUtils.isNotEmpty(obsoleteParameters)) {
-            
response.setContainsObsoleteParameters(obsoleteParameters.toString());
-        }
-        Set<String> excludedParameters = 
site2SiteVpnManager.getExcludedVpnGatewayParameters(result);
-        if (CollectionUtils.isNotEmpty(excludedParameters)) {
-            
response.setContainsExcludedParameters(excludedParameters.toString());
-        }
+
 

Review Comment:
   Customer-gateway responses no longer populate the documented 
obsolete/excluded VPN parameter indicators. This hides compatibility warnings 
for every gateway; restore the manager dependency and both response assignments.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -4210,474 +4208,602 @@ public UsageRecordResponse createUsageResponse(Usage 
usageRecord, Map<String, Se
             }
         }
 
-        ResourceTag.ResourceObjectType resourceType = null;
-        Long resourceId = null;
+        UsageResourceDetails resourceDetails = 
populateUsageTypeSpecificDetails(usageRecord, usageRecResponse, oldFormat, 
vmInstance, template);
+        if (resourceTagResponseMap != null && resourceDetails.resourceId != 
null && resourceDetails.resourceType != null) {
+            final String tagKey = resourceDetails.resourceId + ":" + 
resourceDetails.resourceType;
+            if (resourceTagResponseMap.get(tagKey) != null) {
+                usageRecResponse.setTags(resourceTagResponseMap.get(tagKey));
+            }
+        }
+
+        if (usageRecord.getRawUsage() != null) {
+            DecimalFormat decimalFormat = new 
DecimalFormat("###########.######");
+            
usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage()));
+        }
+
+        if (usageRecord.getStartDate() != null) {
+            usageRecResponse.setStartDate(usageRecord.getStartDate());
+        }
+        if (usageRecord.getEndDate() != null) {
+            usageRecResponse.setEndDate(usageRecord.getEndDate());
+        }
+
+        return usageRecResponse;
+    }
+
+    private UsageResourceDetails populateUsageTypeSpecificDetails(Usage 
usageRecord, UsageRecordResponse usageRecResponse, boolean oldFormat,
+            VMInstanceVO vmInstance, VMTemplateVO template) {
         if (usageRecord.getUsageType() == UsageTypes.RUNNING_VM || 
usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM) {
-            ServiceOfferingVO svcOffering = 
_entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, 
usageRecord.getOfferingId().toString());
-            //Service Offering Id
-            if(svcOffering != null) {
-                usageRecResponse.setOfferingId(svcOffering.getUuid());
-            }
-            //VM Instance ID
-            VMInstanceVO vm = null;
-            if (usageRecord.getUsageId() != null && 
usageRecord.getUsageId().equals(usageRecord.getVmInstanceId())) {
-                vm = vmInstance;
-            } else {
-                vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getUsageId().toString());
+            return populateRunningOrAllocatedVmUsageResponse(usageRecord, 
usageRecResponse, oldFormat, vmInstance, template);
+        } else if (usageRecord.getUsageType() == UsageTypes.IP_ADDRESS) {
+            return populateIpAddressUsageResponse(usageRecord, 
usageRecResponse);
+        } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT 
|| usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) {
+            return populateNetworkBytesUsageResponse(usageRecord, 
usageRecResponse, oldFormat);
+        } else if (usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_READ || 
usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_WRITE
+                || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_READ 
|| usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_WRITE) {
+            return populateVmDiskUsageResponse(usageRecord, usageRecResponse, 
oldFormat, vmInstance);
+        } else if (usageRecord.getUsageType() == UsageTypes.VOLUME) {
+            return populateVolumeUsageResponse(usageRecord, usageRecResponse, 
oldFormat, vmInstance, template);
+        } else if (usageRecord.getUsageType() == UsageTypes.TEMPLATE || 
usageRecord.getUsageType() == UsageTypes.ISO) {
+            return populateTemplateOrIsoUsageResponse(usageRecord, 
usageRecResponse, oldFormat);
+        } else if (usageRecord.getUsageType() == UsageTypes.SNAPSHOT) {
+            return populateSnapshotUsageResponse(usageRecord, 
usageRecResponse, oldFormat);
+        } else if (usageRecord.getUsageType() == 
UsageTypes.LOAD_BALANCER_POLICY) {
+            return populateLoadBalancerPolicyUsageResponse(usageRecord, 
usageRecResponse, oldFormat);
+        } else if (usageRecord.getUsageType() == 
UsageTypes.PORT_FORWARDING_RULE) {
+            return populatePortForwardingRuleUsageResponse(usageRecord, 
usageRecResponse, oldFormat);
+        } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING) {
+            return populateNetworkOfferingUsageResponse(usageRecord, 
usageRecResponse, oldFormat, vmInstance);
+        } else if (usageRecord.getUsageType() == UsageTypes.VPN_USERS) {
+            return populateVpnUsersUsageResponse(usageRecord, 
usageRecResponse, oldFormat);
+        } else if (usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP) {
+            return populateSecurityGroupUsageResponse(usageRecord, 
usageRecResponse, oldFormat, vmInstance);
+        } else if (usageRecord.getUsageType() == UsageTypes.BACKUP) {
+            return populateBackupUsageResponse(usageRecord, usageRecResponse, 
vmInstance);
+        } else if (usageRecord.getUsageType() == UsageTypes.VM_SNAPSHOT) {
+            return populateVmSnapshotUsageResponse(usageRecord, 
usageRecResponse, oldFormat, vmInstance);
+        } else if (usageRecord.getUsageType() == UsageTypes.VOLUME_SECONDARY) {
+            return populateVolumeSecondaryUsageResponse(usageRecord, 
usageRecResponse, oldFormat);
+        } else if (usageRecord.getUsageType() == 
UsageTypes.VM_SNAPSHOT_ON_PRIMARY) {
+            return populateVmSnapshotOnPrimaryUsageResponse(usageRecord, 
usageRecResponse, oldFormat, vmInstance);
+        } else if (usageRecord.getUsageType() == UsageTypes.BUCKET) {
+            return populateBucketUsageResponse(usageRecord, usageRecResponse);
+        }
+
+        return new UsageResourceDetails();
+    }
+
+    private UsageResourceDetails 
populateRunningOrAllocatedVmUsageResponse(Usage usageRecord, 
UsageRecordResponse usageRecResponse, boolean oldFormat,
+            VMInstanceVO vmInstance, VMTemplateVO template) {
+        UsageResourceDetails resourceDetails = new UsageResourceDetails();
+        ServiceOfferingVO svcOffering = 
_entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, 
usageRecord.getOfferingId());
+        //Service Offering Id
+        if(svcOffering != null) {
+            usageRecResponse.setOfferingId(svcOffering.getUuid());
+        }
+        //VM Instance ID
+        VMInstanceVO vm = null;
+        if (usageRecord.getUsageId() != null && 
usageRecord.getUsageId().equals(usageRecord.getVmInstanceId())) {
+            vm = vmInstance;
+        } else {
+            vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getUsageId());
+        }
+        if (vm != null) {
+            resourceDetails.resourceType = 
ResourceTag.ResourceObjectType.UserVm;
+            usageRecResponse.setUsageId(vm.getUuid());
+            resourceDetails.resourceId = vm.getId();
+            final GuestOS guestOS = _guestOsDao.findById(vm.getGuestOSId());
+            if (guestOS != null) {
+                usageRecResponse.setOsTypeId(guestOS.getUuid());
+                usageRecResponse.setOsDisplayName(guestOS.getDisplayName());
+                final GuestOsCategory guestOsCategory = 
_guestOsCategoryDao.findById(guestOS.getCategoryId());
+                if (guestOsCategory != null) {
+                    
usageRecResponse.setOsCategoryId(guestOsCategory.getUuid());
+                    
usageRecResponse.setOsCategoryName(guestOsCategory.getName());
+                }
+            }
+        }
+        //Hypervisor Type
+        usageRecResponse.setType(usageRecord.getType());
+        //Dynamic compute offerings details
+        if (usageRecord.getCpuCores() != null) {
+            usageRecResponse.setCpuNumber(usageRecord.getCpuCores());
+        } else if (svcOffering != null && svcOffering.getCpu() != null) {
+            usageRecResponse.setCpuNumber(svcOffering.getCpu().longValue());
+        }
+        if (usageRecord.getCpuSpeed() != null) {
+            usageRecResponse.setCpuSpeed(usageRecord.getCpuSpeed());
+        } else if (svcOffering != null && svcOffering.getSpeed() != null) {
+            usageRecResponse.setCpuSpeed(svcOffering.getSpeed().longValue());
+        }
+        if (usageRecord.getMemory() != null) {
+            usageRecResponse.setMemory(usageRecord.getMemory());
+        } else if (svcOffering != null && svcOffering.getRamSize() != null) {
+            usageRecResponse.setMemory(svcOffering.getRamSize().longValue());
+        }
+        if (!oldFormat) {
+            final StringBuilder builder = new StringBuilder();
+            if (usageRecord.getUsageType() == UsageTypes.RUNNING_VM) {
+                builder.append("Running VM usage ");
+            } else if(usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM) {
+                builder.append("Allocated VM usage ");
             }
             if (vm != null) {
-                resourceType = ResourceTag.ResourceObjectType.UserVm;
-                usageRecResponse.setUsageId(vm.getUuid());
-                resourceId = vm.getId();
-                final GuestOS guestOS = 
_guestOsDao.findById(vm.getGuestOSId());
-                if (guestOS != null) {
-                    usageRecResponse.setOsTypeId(guestOS.getUuid());
-                    
usageRecResponse.setOsDisplayName(guestOS.getDisplayName());
-                    final GuestOsCategory guestOsCategory = 
_guestOsCategoryDao.findById(guestOS.getCategoryId());
-                    if (guestOsCategory != null) {
-                        
usageRecResponse.setOsCategoryId(guestOsCategory.getUuid());
-                        
usageRecResponse.setOsCategoryName(guestOsCategory.getName());
-                    }
-                }
+                builder.append("for ").append(vm.getHostName()).append(" 
(").append(vm.getInstanceName()).append(") (").append(vm.getUuid()).append(") 
");
             }
-            //Hypervisor Type
-            usageRecResponse.setType(usageRecord.getType());
-            //Dynamic compute offerings details
-            if(usageRecord.getCpuCores() != null) {
-                usageRecResponse.setCpuNumber(usageRecord.getCpuCores());
-            } else if (svcOffering.getCpu() != null){
-                
usageRecResponse.setCpuNumber(svcOffering.getCpu().longValue());
-            }
-            if(usageRecord.getCpuSpeed() != null) {
-                usageRecResponse.setCpuSpeed(usageRecord.getCpuSpeed());
-            } else if(svcOffering.getSpeed() != null){
-                
usageRecResponse.setCpuSpeed(svcOffering.getSpeed().longValue());
-            }
-            if(usageRecord.getMemory() != null) {
-                usageRecResponse.setMemory(usageRecord.getMemory());
-            } else if(svcOffering.getRamSize() != null) {
-                
usageRecResponse.setMemory(svcOffering.getRamSize().longValue());
-            }
-            if (!oldFormat) {
-                final StringBuilder builder = new StringBuilder();
-                if (usageRecord.getUsageType() == UsageTypes.RUNNING_VM) {
-                    builder.append("Running VM usage ");
-                } else if(usageRecord.getUsageType() == 
UsageTypes.ALLOCATED_VM) {
-                    builder.append("Allocated VM usage ");
-                }
-                if (vm != null) {
-                    builder.append("for ").append(vm.getHostName()).append(" 
(").append(vm.getInstanceName()).append(") (").append(vm.getUuid()).append(") 
");
-                }
-                if (svcOffering != null) {
-                    builder.append("using service offering 
").append(svcOffering.getName()).append(" 
(").append(svcOffering.getUuid()).append(") ");
-                }
-                if (template != null) {
-                    builder.append("and template 
").append(template.getName()).append(" 
(").append(template.getUuid()).append(")");
-                }
-                usageRecResponse.setDescription(builder.toString());
+            if (svcOffering != null) {
+                builder.append("using service offering 
").append(svcOffering.getName()).append(" 
(").append(svcOffering.getUuid()).append(") ");
             }
-        } else if (usageRecord.getUsageType() == UsageTypes.IP_ADDRESS) {
-            //IP Address ID
-            IPAddressVO ip = 
_entityMgr.findByIdIncludingRemoved(IPAddressVO.class, 
usageRecord.getUsageId().toString());
-            if (ip != null) {
-                Long networkId = ip.getAssociatedWithNetworkId();
-                if (networkId == null) {
-                    networkId = ip.getSourceNetworkId();
-                }
-                resourceType = ResourceObjectType.PublicIpAddress;
-                resourceId = ip.getId();
-                usageRecResponse.setUsageId(ip.getUuid());
-            }
-            //isSourceNAT
-            
usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat")) ? 
true : false);
-            //isSystem
-            usageRecResponse.setSystem((usageRecord.getSize() == 1) ? true : 
false);
-        } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT 
|| usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) {
-            //Device Type
-            resourceType = ResourceObjectType.UserVm;
-            usageRecResponse.setType(usageRecord.getType());
-            VMInstanceVO vm = null;
-            HostVO host = null;
-            if (usageRecord.getType().equals("DomainRouter") || 
usageRecord.getType().equals("UserVm")) {
-                //Domain Router Id
-                vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getUsageId().toString());
-                if (vm != null) {
-                    resourceId = vm.getId();
-                    usageRecResponse.setUsageId(vm.getUuid());
-                }
-            } else {
-                //External Device Host Id
-                host = _entityMgr.findByIdIncludingRemoved(HostVO.class, 
usageRecord.getUsageId().toString());
-                if (host != null) {
-                    usageRecResponse.setUsageId(host.getUuid());
-                }
+            if (template != null) {
+                builder.append("and template 
").append(template.getName()).append(" 
(").append(template.getUuid()).append(")");
             }
-            //Network ID
-            NetworkVO network = null;
-            if((usageRecord.getNetworkId() != null) && 
(usageRecord.getNetworkId() != 0)) {
-                network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, 
usageRecord.getNetworkId().toString());
-                if (network != null) {
-                    resourceType = ResourceObjectType.Network;
-                    if (network.getTrafficType() == TrafficType.Public) {
-                        VirtualRouter router = 
ApiDBUtils.findDomainRouterById(usageRecord.getUsageId());
-                        Vpc vpc = 
ApiDBUtils.findVpcByIdIncludingRemoved(router.getVpcId());
+            usageRecResponse.setDescription(builder.toString());
+        }
+        return resourceDetails;
+    }
+
+    private UsageResourceDetails populateIpAddressUsageResponse(Usage 
usageRecord, UsageRecordResponse usageRecResponse) {
+        UsageResourceDetails resourceDetails = new UsageResourceDetails();
+        //IP Address ID
+        IPAddressVO ip = 
_entityMgr.findByIdIncludingRemoved(IPAddressVO.class, 
usageRecord.getUsageId());
+        if (ip != null) {
+            resourceDetails.resourceType = ResourceObjectType.PublicIpAddress;
+            resourceDetails.resourceId = ip.getId();
+            usageRecResponse.setUsageId(ip.getUuid());
+        }
+        //isSourceNAT
+        
usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat")) ? 
true : false);
+        //isSystem
+        usageRecResponse.setSystem((usageRecord.getSize() == 1) ? true : 
false);
+        return resourceDetails;
+    }
+
+    private UsageResourceDetails populateNetworkBytesUsageResponse(Usage 
usageRecord, UsageRecordResponse usageRecResponse, boolean oldFormat) {
+        UsageResourceDetails resourceDetails = new UsageResourceDetails();
+        //Device Type
+        resourceDetails.resourceType = ResourceObjectType.UserVm;
+        usageRecResponse.setType(usageRecord.getType());
+        VMInstanceVO vm = null;
+        HostVO host = null;
+        if (usageRecord.getType().equals("DomainRouter") || 
usageRecord.getType().equals("UserVm")) {
+            //Domain Router Id
+            vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getUsageId());
+            if (vm != null) {
+                resourceDetails.resourceId = vm.getId();
+                usageRecResponse.setUsageId(vm.getUuid());
+            }
+        } else {
+            //External Device Host Id
+            host = _entityMgr.findByIdIncludingRemoved(HostVO.class, 
usageRecord.getUsageId());
+            if (host != null) {
+                usageRecResponse.setUsageId(host.getUuid());
+            }
+        }
+        //Network ID
+        NetworkVO network = null;
+        if((usageRecord.getNetworkId() != null) && (usageRecord.getNetworkId() 
!= 0)) {
+            network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, 
usageRecord.getNetworkId());
+            if (network != null) {
+                resourceDetails.resourceType = ResourceObjectType.Network;
+                if (network.getTrafficType() == TrafficType.Public) {
+                    VirtualRouter router = 
ApiDBUtils.findDomainRouterById(usageRecord.getUsageId());
+                    Vpc vpc = router != null && router.getVpcId() != null ? 
ApiDBUtils.findVpcByIdIncludingRemoved(router.getVpcId()) : null;
+                    if (vpc != null) {
                         usageRecResponse.setVpcId(vpc.getUuid());
-                        resourceId = vpc.getId();
+                        resourceDetails.resourceId = vpc.getId();
                     } else {
                         usageRecResponse.setNetworkId(network.getUuid());
-                        resourceId = network.getId();
+                        resourceDetails.resourceId = network.getId();
                     }
-                    usageRecResponse.setResourceName(network.getName());
+                } else {
+                    usageRecResponse.setNetworkId(network.getUuid());
+                    resourceDetails.resourceId = network.getId();
                 }
+                usageRecResponse.setResourceName(network.getName());

Review Comment:
   This new branch changes API behavior for non-public network traffic: it now 
sets `networkId`/`resourceName` and changes the tag lookup ID from the 
VM/host-derived value to the network ID. That is an observable business-logic 
change despite the PR's claim of a strictly structural refactor; either 
preserve the original branch semantics or document and isolate this behavior 
change.



##########
server/src/main/java/com/cloud/api/ApiResponseHelper.java:
##########
@@ -4903,7 +5029,6 @@ public NicResponse createNicResponse(Nic result) {
             response.setVpcName(vpc.getName());
         }
 

Review Comment:
   Every NIC response now omits the documented `enabled` state because the 
assignment was removed. Restore this mapping to avoid returning incomplete NIC 
data.



##########
server/src/test/java/com/cloud/api/ApiResponseHelperTest.java:
##########
@@ -781,23 +809,661 @@ public void 
createConsoleSessionResponseTestShouldReturnFullResponse() {
 
             ConsoleSessionResponse response = 
apiResponseHelper.createConsoleSessionResponse(consoleSessionMock, 
ResponseObject.ResponseView.Full);
 
-            Assert.assertEquals(expected.getId(), response.getId());
-            Assert.assertEquals(expected.getCreated(), response.getCreated());
-            Assert.assertEquals(expected.getAcquired(), 
response.getAcquired());
-            Assert.assertEquals(expected.getRemoved(), response.getRemoved());
-            Assert.assertEquals(expected.getConsoleEndpointCreatorAddress(), 
response.getConsoleEndpointCreatorAddress());
-            Assert.assertEquals(expected.getClientAddress(), 
response.getClientAddress());
-            Assert.assertEquals(expected.getDomain(), response.getDomain());
-            Assert.assertEquals(expected.getDomainPath(), 
response.getDomainPath());
-            Assert.assertEquals(expected.getDomainId(), 
response.getDomainId());
-            Assert.assertEquals(expected.getUser(), response.getUser());
-            Assert.assertEquals(expected.getUserId(), response.getUserId());
-            Assert.assertEquals(expected.getAccount(), response.getAccount());
-            Assert.assertEquals(expected.getAccountId(), 
response.getAccountId());
-            Assert.assertEquals(expected.getHostId(), response.getHostId());
-            Assert.assertEquals(expected.getHostName(), 
response.getHostName());
-            Assert.assertEquals(expected.getVmId(), response.getVmId());
-            Assert.assertEquals(expected.getVmName(), response.getVmName());
+            Assertions.assertEquals(expected.getId(), response.getId());
+            Assertions.assertEquals(expected.getCreated(), 
response.getCreated());
+            Assertions.assertEquals(expected.getAcquired(), 
response.getAcquired());
+            Assertions.assertEquals(expected.getRemoved(), 
response.getRemoved());
+            
Assertions.assertEquals(expected.getConsoleEndpointCreatorAddress(), 
response.getConsoleEndpointCreatorAddress());
+            Assertions.assertEquals(expected.getClientAddress(), 
response.getClientAddress());
+            Assertions.assertEquals(expected.getDomain(), 
response.getDomain());
+            Assertions.assertEquals(expected.getDomainPath(), 
response.getDomainPath());
+            Assertions.assertEquals(expected.getDomainId(), 
response.getDomainId());
+            Assertions.assertEquals(expected.getUser(), response.getUser());
+            Assertions.assertEquals(expected.getUserId(), 
response.getUserId());
+            Assertions.assertEquals(expected.getAccount(), 
response.getAccount());
+            Assertions.assertEquals(expected.getAccountId(), 
response.getAccountId());
+            Assertions.assertEquals(expected.getHostId(), 
response.getHostId());
+            Assertions.assertEquals(expected.getHostName(), 
response.getHostName());
+            Assertions.assertEquals(expected.getVmId(), response.getVmId());
+            Assertions.assertEquals(expected.getVmName(), 
response.getVmName());
         }
     }
+
+    @Test
+    @DisplayName("RUNNING_VM usage populates service offering, VM and OS 
details")
+    public void populateRunningVmUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
+        VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+        VMTemplateVO template = mock(VMTemplateVO.class);
+        GuestOSVO guestOS = mock(GuestOSVO.class);
+        GuestOSCategoryVO guestOSCategory = mock(GuestOSCategoryVO.class);
+        Long usageId = 11L;
+        Long offeringId = 21L;
+        Long guestOSId = 31L;
+        Long guestOSCategoryId = 41L;
+
+        when(usageRecord.getUsageType()).thenReturn(UsageTypes.RUNNING_VM);
+        when(usageRecord.getOfferingId()).thenReturn(offeringId);
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getVmInstanceId()).thenReturn(usageId);
+        when(usageRecord.getType()).thenReturn("KVM");
+        when(usageRecord.getCpuCores()).thenReturn(null);
+        when(usageRecord.getCpuSpeed()).thenReturn(2400L);
+        when(usageRecord.getMemory()).thenReturn(8192L);
+        
when(entityManagerMock.findByIdIncludingRemoved(ServiceOfferingVO.class, 
offeringId)).thenReturn(serviceOffering);
+        when(serviceOffering.getUuid()).thenReturn("service-offering-uuid");
+        when(serviceOffering.getName()).thenReturn("Small Instance");
+        when(serviceOffering.getCpu()).thenReturn(4);
+        when(vmInstance.getUuid()).thenReturn("vm-uuid");
+        when(vmInstance.getId()).thenReturn(usageId);
+        when(vmInstance.getHostName()).thenReturn("vm-host");
+        when(vmInstance.getInstanceName()).thenReturn("i-2-11-VM");
+        when(vmInstance.getGuestOSId()).thenReturn(guestOSId);
+        when(guestOSDaoMock.findById(guestOSId)).thenReturn(guestOS);
+        when(guestOS.getUuid()).thenReturn("guest-os-uuid");
+        when(guestOS.getDisplayName()).thenReturn("Ubuntu 22.04");
+        when(guestOS.getCategoryId()).thenReturn(guestOSCategoryId);
+        
when(guestOSCategoryDaoMock.findById(guestOSCategoryId)).thenReturn(guestOSCategory);
+        when(guestOSCategory.getUuid()).thenReturn("guest-os-category-uuid");
+        when(guestOSCategory.getName()).thenReturn("Linux");
+        when(template.getUuid()).thenReturn("template-uuid");
+        when(template.getName()).thenReturn("Ubuntu Template");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateRunningOrAllocatedVmUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class, VMTemplateVO.class},
+                usageRecord, response, false, vmInstance, template);
+
+        // Assert
+        assertResponseField(response, "offeringId", "service-offering-uuid");
+        assertResponseField(response, "usageId", "vm-uuid");
+        assertResponseField(response, "type", "KVM");
+        assertResponseField(response, "cpuNumber", 4L);
+        assertResponseField(response, "cpuSpeed", 2400L);
+        assertResponseField(response, "memory", 8192L);
+        assertResponseField(response, "osTypeId", "guest-os-uuid");
+        assertResponseField(response, "osDisplayName", "Ubuntu 22.04");
+        assertResponseField(response, "osCategoryId", 
"guest-os-category-uuid");
+        assertResponseField(response, "osCategoryName", "Linux");
+        assertDescriptionContains(response, "Running VM usage for vm-host 
(i-2-11-VM) (vm-uuid)");
+        assertDescriptionContains(response, "using service offering Small 
Instance (service-offering-uuid)");
+        assertDescriptionContains(response, "and template Ubuntu Template 
(template-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.UserVm, usageId);
+        
verify(entityManagerMock).findByIdIncludingRemoved(ServiceOfferingVO.class, 
offeringId);
+        verify(guestOSDaoMock).findById(guestOSId);
+    }
+
+    @Test
+    @DisplayName("ALLOCATED_VM usage falls back to service offering compute 
details")
+    public void populateAllocatedVmUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
+        VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+        Long usageId = 12L;
+        Long vmInstanceId = 22L;
+        Long offeringId = 32L;
+
+        when(usageRecord.getUsageType()).thenReturn(UsageTypes.ALLOCATED_VM);
+        when(usageRecord.getOfferingId()).thenReturn(offeringId);
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getVmInstanceId()).thenReturn(vmInstanceId);
+        when(usageRecord.getType()).thenReturn("KVM");
+        when(usageRecord.getCpuCores()).thenReturn(null);
+        when(usageRecord.getCpuSpeed()).thenReturn(null);
+        when(usageRecord.getMemory()).thenReturn(null);
+        
when(entityManagerMock.findByIdIncludingRemoved(ServiceOfferingVO.class, 
offeringId)).thenReturn(serviceOffering);
+        when(entityManagerMock.findByIdIncludingRemoved(VMInstanceVO.class, 
usageId)).thenReturn(vmInstance);
+        
when(serviceOffering.getUuid()).thenReturn("allocated-service-offering-uuid");
+        when(serviceOffering.getName()).thenReturn("Medium Instance");
+        when(serviceOffering.getCpu()).thenReturn(2);
+        when(serviceOffering.getSpeed()).thenReturn(1800);
+        when(serviceOffering.getRamSize()).thenReturn(4096);
+        when(vmInstance.getUuid()).thenReturn("allocated-vm-uuid");
+        when(vmInstance.getId()).thenReturn(usageId);
+        when(vmInstance.getHostName()).thenReturn("allocated-vm-host");
+        when(vmInstance.getInstanceName()).thenReturn("i-2-12-VM");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateRunningOrAllocatedVmUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class, VMTemplateVO.class},
+                usageRecord, response, false, null, null);
+
+        // Assert
+        assertResponseField(response, "offeringId", 
"allocated-service-offering-uuid");
+        assertResponseField(response, "usageId", "allocated-vm-uuid");
+        assertResponseField(response, "type", "KVM");
+        assertResponseField(response, "cpuNumber", 2L);
+        assertResponseField(response, "cpuSpeed", 1800L);
+        assertResponseField(response, "memory", 4096L);
+        assertDescriptionContains(response, "Allocated VM usage for 
allocated-vm-host (i-2-12-VM) (allocated-vm-uuid)");
+        assertDescriptionContains(response, "using service offering Medium 
Instance (allocated-service-offering-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.UserVm, usageId);
+        
verify(entityManagerMock).findByIdIncludingRemoved(ServiceOfferingVO.class, 
offeringId);
+        verify(entityManagerMock).findByIdIncludingRemoved(VMInstanceVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("IP_ADDRESS usage populates public IP flags")
+    public void populateIpAddressUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        IPAddressVO ipAddress = mock(IPAddressVO.class);
+        Long usageId = 13L;
+
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getType()).thenReturn("SourceNat");
+        when(usageRecord.getSize()).thenReturn(1L);
+        when(entityManagerMock.findByIdIncludingRemoved(IPAddressVO.class, 
usageId)).thenReturn(ipAddress);
+        when(ipAddress.getUuid()).thenReturn("ip-address-uuid");
+        when(ipAddress.getId()).thenReturn(usageId);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateIpAddressUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class}, 
usageRecord, response);
+
+       // Assert
+        assertResponseField(response, "usageId", "ip-address-uuid");
+        assertResponseField(response, "isSourceNat", Boolean.TRUE);
+        assertResponseField(response, "isSystem", Boolean.TRUE);
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.PublicIpAddress, usageId);
+        verify(entityManagerMock).findByIdIncludingRemoved(IPAddressVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("NETWORK_BYTES_SENT usage populates VM and network details")
+    public void populateNetworkBytesSentUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+        NetworkVO network = mock(NetworkVO.class);
+        Long usageId = 14L;
+        Long networkId = 24L;
+
+        
when(usageRecord.getUsageType()).thenReturn(UsageTypes.NETWORK_BYTES_SENT);
+        when(usageRecord.getType()).thenReturn("UserVm");
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getNetworkId()).thenReturn(networkId);
+        when(usageRecord.getRawUsage()).thenReturn(1024D);
+        when(entityManagerMock.findByIdIncludingRemoved(VMInstanceVO.class, 
usageId)).thenReturn(vmInstance);
+        when(entityManagerMock.findByIdIncludingRemoved(NetworkVO.class, 
networkId)).thenReturn(network);
+        when(vmInstance.getUuid()).thenReturn("network-vm-uuid");
+        when(vmInstance.getId()).thenReturn(usageId);
+        when(vmInstance.getInstanceName()).thenReturn("r-14-VM");
+        when(network.getUuid()).thenReturn("network-uuid");
+        when(network.getId()).thenReturn(networkId);
+        when(network.getName()).thenReturn("guest-network");
+        when(network.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateNetworkBytesUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "type", "UserVm");
+        assertResponseField(response, "usageId", "network-vm-uuid");
+        assertResponseField(response, "networkId", "network-uuid");
+        assertResponseField(response, "resourceName", "guest-network");
+        assertDescriptionContains(response, "Bytes sent by network 
guest-network (network-uuid)");
+        assertDescriptionContains(response, "using router r-14-VM 
(network-vm-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.Network, networkId);
+        verify(entityManagerMock).findByIdIncludingRemoved(VMInstanceVO.class, 
usageId);
+        verify(entityManagerMock).findByIdIncludingRemoved(NetworkVO.class, 
networkId);
+    }
+
+    @Test
+    @DisplayName("NETWORK_BYTES_RECEIVED usage populates VM and network 
details")
+    public void populateNetworkBytesReceivedUsageResponseTest() throws 
Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+        NetworkVO network = mock(NetworkVO.class);
+        Long usageId = 15L;
+        Long networkId = 25L;
+
+        
when(usageRecord.getUsageType()).thenReturn(UsageTypes.NETWORK_BYTES_RECEIVED);
+        when(usageRecord.getType()).thenReturn("DomainRouter");
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getNetworkId()).thenReturn(networkId);
+        when(usageRecord.getRawUsage()).thenReturn(2048D);
+        when(entityManagerMock.findByIdIncludingRemoved(VMInstanceVO.class, 
usageId)).thenReturn(vmInstance);
+        when(entityManagerMock.findByIdIncludingRemoved(NetworkVO.class, 
networkId)).thenReturn(network);
+        when(vmInstance.getUuid()).thenReturn("network-router-uuid");
+        when(vmInstance.getId()).thenReturn(usageId);
+        when(vmInstance.getInstanceName()).thenReturn("r-15-VM");
+        when(network.getUuid()).thenReturn("received-network-uuid");
+        when(network.getId()).thenReturn(networkId);
+        when(network.getName()).thenReturn("received-network");
+        when(network.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateNetworkBytesUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "type", "DomainRouter");
+        assertResponseField(response, "usageId", "network-router-uuid");
+        assertResponseField(response, "networkId", "received-network-uuid");
+        assertResponseField(response, "resourceName", "received-network");
+        assertDescriptionContains(response, "Bytes received by network 
received-network (received-network-uuid)");
+        assertDescriptionContains(response, "using router r-15-VM 
(network-router-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.Network, networkId);
+        verify(entityManagerMock).findByIdIncludingRemoved(VMInstanceVO.class, 
usageId);
+        verify(entityManagerMock).findByIdIncludingRemoved(NetworkVO.class, 
networkId);
+    }
+
+    @Test
+    @DisplayName("VOLUME usage populates volume size and offering details")
+    public void populateVolumeUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+        VMTemplateVO template = mock(VMTemplateVO.class);
+        VolumeVO volume = mock(VolumeVO.class);
+        DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
+        Long usageId = 16L;
+        Long offeringId = 26L;
+
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getOfferingId()).thenReturn(offeringId);
+        when(usageRecord.getSize()).thenReturn(4096L);
+        when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, 
usageId)).thenReturn(volume);
+        when(entityManagerMock.findByIdIncludingRemoved(DiskOfferingVO.class, 
offeringId)).thenReturn(diskOffering);
+        when(volume.getUuid()).thenReturn("volume-uuid");
+        when(volume.getId()).thenReturn(usageId);
+        when(volume.getName()).thenReturn("data-volume");
+        when(diskOffering.getUuid()).thenReturn("disk-offering-uuid");
+        when(diskOffering.getName()).thenReturn("Small Disk");
+        when(vmInstance.getUuid()).thenReturn("volume-vm-uuid");
+        when(vmInstance.getHostName()).thenReturn("volume-vm");
+        when(template.getUuid()).thenReturn("volume-template-uuid");
+        when(template.getName()).thenReturn("Volume Template");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateVolumeUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class, VMTemplateVO.class},
+                usageRecord, response, false, vmInstance, template);
+
+        // Assert
+        assertResponseField(response, "usageId", "volume-uuid");
+        assertResponseField(response, "size", 4096L);
+        assertResponseField(response, "offeringId", "disk-offering-uuid");
+        assertDescriptionContains(response, "Volume usage for data-volume 
(volume-uuid)");
+        assertDescriptionContains(response, "attached to VM volume-vm 
(volume-vm-uuid)");
+        assertDescriptionContains(response, "with disk offering Small Disk 
(disk-offering-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.Volume, usageId);
+        verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, 
usageId);
+        
verify(entityManagerMock).findByIdIncludingRemoved(DiskOfferingVO.class, 
offeringId);
+    }
+
+    @Test
+    @DisplayName("TEMPLATE usage populates template size details")
+    public void populateTemplateUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMTemplateVO template = mock(VMTemplateVO.class);
+        Long usageId = 17L;
+
+        when(usageRecord.getUsageType()).thenReturn(UsageTypes.TEMPLATE);
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getSize()).thenReturn(8192L);
+        when(usageRecord.getVirtualSize()).thenReturn(16384L);
+        when(entityManagerMock.findByIdIncludingRemoved(VMTemplateVO.class, 
usageId)).thenReturn(template);
+        when(template.getUuid()).thenReturn("template-usage-uuid");
+        when(template.getId()).thenReturn(usageId);
+        when(template.getName()).thenReturn("CentOS Template");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateTemplateOrIsoUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "usageId", "template-usage-uuid");
+        assertResponseField(response, "size", 8192L);
+        assertResponseField(response, "virtualSize", 16384L);
+        assertDescriptionContains(response, "Template usage for CentOS 
Template (template-usage-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.Template, usageId);
+        verify(entityManagerMock).findByIdIncludingRemoved(VMTemplateVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("ISO usage populates ISO size details")
+    public void populateIsoUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMTemplateVO iso = mock(VMTemplateVO.class);
+        Long usageId = 18L;
+
+        when(usageRecord.getUsageType()).thenReturn(UsageTypes.ISO);
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getSize()).thenReturn(2048L);
+        when(usageRecord.getVirtualSize()).thenReturn(4096L);
+        when(entityManagerMock.findByIdIncludingRemoved(VMTemplateVO.class, 
usageId)).thenReturn(iso);
+        when(iso.getUuid()).thenReturn("iso-usage-uuid");
+        when(iso.getId()).thenReturn(usageId);
+        when(iso.getName()).thenReturn("Installer ISO");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateTemplateOrIsoUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "usageId", "iso-usage-uuid");
+        assertResponseField(response, "size", 2048L);
+        assertResponseField(response, "virtualSize", 2048L);
+        assertDescriptionContains(response, "ISO usage for Installer ISO 
(iso-usage-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.ISO, usageId);
+        verify(entityManagerMock).findByIdIncludingRemoved(VMTemplateVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("SNAPSHOT usage populates snapshot size details")
+    public void populateSnapshotUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        SnapshotVO snapshot = mock(SnapshotVO.class);
+        Long usageId = 19L;
+
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(usageRecord.getSize()).thenReturn(1024L);
+        when(entityManagerMock.findByIdIncludingRemoved(SnapshotVO.class, 
usageId)).thenReturn(snapshot);
+        when(snapshot.getUuid()).thenReturn("snapshot-uuid");
+        when(snapshot.getId()).thenReturn(usageId);
+        when(snapshot.getName()).thenReturn("daily-snapshot");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateSnapshotUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "usageId", "snapshot-uuid");
+        assertResponseField(response, "size", 1024L);
+        assertDescriptionContains(response, "Snapshot usage for daily-snapshot 
(snapshot-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.Snapshot, usageId);
+        verify(entityManagerMock).findByIdIncludingRemoved(SnapshotVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("SECURITY_GROUP usage populates security group details")
+    public void populateSecurityGroupUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        SecurityGroupVO securityGroup = mock(SecurityGroupVO.class);
+        VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+        Long usageId = 20L;
+
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(entityManagerMock.findByIdIncludingRemoved(SecurityGroupVO.class, 
usageId)).thenReturn(securityGroup);
+        when(securityGroup.getUuid()).thenReturn("security-group-uuid");
+        when(securityGroup.getId()).thenReturn(usageId);
+        when(securityGroup.getName()).thenReturn("web-tier");
+        when(vmInstance.getUuid()).thenReturn("security-group-vm-uuid");
+        when(vmInstance.getHostName()).thenReturn("security-group-vm");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateSecurityGroupUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class},
+                usageRecord, response, false, vmInstance);
+
+        // Assert
+        assertResponseField(response, "usageId", "security-group-uuid");
+        assertDescriptionContains(response, "Security group web-tier 
(security-group-uuid) usage");
+        assertDescriptionContains(response, "for VM security-group-vm 
(security-group-vm-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.SecurityGroup, usageId);
+        
verify(entityManagerMock).findByIdIncludingRemoved(SecurityGroupVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("LOAD_BALANCER_POLICY usage populates load balancer details")
+    public void populateLoadBalancerPolicyUsageResponseTest() throws Exception 
{
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        LoadBalancerVO loadBalancer = mock(LoadBalancerVO.class);
+        Long usageId = 21L;
+
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(entityManagerMock.findByIdIncludingRemoved(LoadBalancerVO.class, 
usageId)).thenReturn(loadBalancer);
+        when(loadBalancer.getUuid()).thenReturn("load-balancer-uuid");
+        when(loadBalancer.getId()).thenReturn(usageId);
+        when(loadBalancer.getName()).thenReturn("public-lb");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateLoadBalancerPolicyUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "usageId", "load-balancer-uuid");
+        assertDescriptionContains(response, "Loadbalancer policy usage 
public-lb (load-balancer-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.LoadBalancer, usageId);
+        
verify(entityManagerMock).findByIdIncludingRemoved(LoadBalancerVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("PORT_FORWARDING_RULE usage populates port forwarding rule 
details")
+    public void populatePortForwardingRuleUsageResponseTest() throws Exception 
{
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        PortForwardingRuleVO portForwardingRule = 
mock(PortForwardingRuleVO.class);
+        Long usageId = 22L;
+
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        
when(entityManagerMock.findByIdIncludingRemoved(PortForwardingRuleVO.class, 
usageId)).thenReturn(portForwardingRule);
+        
when(portForwardingRule.getUuid()).thenReturn("port-forwarding-rule-uuid");
+        when(portForwardingRule.getId()).thenReturn(usageId);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populatePortForwardingRuleUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "usageId", "port-forwarding-rule-uuid");
+        assertDescriptionContains(response, "Port forwarding rule usage 
(port-forwarding-rule-uuid)");
+        assertUsageResourceDetails(resourceDetails, 
ResourceTag.ResourceObjectType.PortForwardingRule, usageId);
+        
verify(entityManagerMock).findByIdIncludingRemoved(PortForwardingRuleVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("NETWORK_OFFERING usage populates offering and default flag")
+    public void populateNetworkOfferingUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        NetworkOfferingVO networkOffering = mock(NetworkOfferingVO.class);
+        VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+        Long offeringId = 23L;
+
+        when(usageRecord.getOfferingId()).thenReturn(offeringId);
+        when(usageRecord.getUsageId()).thenReturn(1L);
+        
when(entityManagerMock.findByIdIncludingRemoved(NetworkOfferingVO.class, 
offeringId)).thenReturn(networkOffering);
+        when(networkOffering.getUuid()).thenReturn("network-offering-uuid");
+        when(networkOffering.getName()).thenReturn("Default Isolated Network");
+        when(vmInstance.getUuid()).thenReturn("network-offering-vm-uuid");
+        when(vmInstance.getHostName()).thenReturn("network-offering-vm");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateNetworkOfferingUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class},
+                usageRecord, response, false, vmInstance);
+
+        // Assert
+        assertResponseField(response, "offeringId", "network-offering-uuid");
+        assertResponseField(response, "isDefault", Boolean.TRUE);
+        assertDescriptionContains(response, "Network offering Default Isolated 
Network (network-offering-uuid) usage");
+        assertDescriptionContains(response, "for VM network-offering-vm 
(network-offering-vm-uuid)");
+        assertUsageResourceDetails(resourceDetails, null, null);
+        
verify(entityManagerMock).findByIdIncludingRemoved(NetworkOfferingVO.class, 
offeringId);
+    }
+
+    @Test
+    @DisplayName("VPN_USERS usage populates VPN user details")
+    public void populateVpnUsersUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = mock(UsageVO.class);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VpnUserVO vpnUser = mock(VpnUserVO.class);
+        Long usageId = 24L;
+
+        when(usageRecord.getUsageId()).thenReturn(usageId);
+        when(entityManagerMock.findByIdIncludingRemoved(VpnUserVO.class, 
usageId)).thenReturn(vpnUser);
+        when(vpnUser.getUuid()).thenReturn("vpn-user-uuid");
+        when(vpnUser.getUsername()).thenReturn("vpn-user");
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateVpnUsersUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class}, usageRecord, response, false);
+
+        // Assert
+        assertResponseField(response, "usageId", "vpn-user-uuid");
+        assertDescriptionContains(response, "VPN usage for user vpn-user 
(vpn-user-uuid)");
+        assertUsageResourceDetails(resourceDetails, null, null);
+        verify(entityManagerMock).findByIdIncludingRemoved(VpnUserVO.class, 
usageId);
+    }
+
+    @Test
+    @DisplayName("VM_DISK_IO_READ usage populates disk read request details")
+    public void populateVmDiskIoReadUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = 
mockVmDiskUsageRecord(UsageTypes.VM_DISK_IO_READ, 25L, 512D);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMInstanceVO vmInstance = mockVmInstance("vm-disk-read-vm", 
"vm-disk-read-vm-uuid");
+        VolumeVO volume = mockVolume(25L, "vm-disk-read-volume-uuid", 
"vm-disk-read-volume");
+        when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, 
25L)).thenReturn(volume);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class},
+                usageRecord, response, false, vmInstance);
+
+        // Assert
+        assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O read 
requests", "vm-disk-read-volume-uuid", "vm-disk-read-volume", 25L);
+        verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, 
25L);
+    }
+
+    @Test
+    @DisplayName("VM_DISK_IO_WRITE usage populates disk write request details")
+    public void populateVmDiskIoWriteUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = 
mockVmDiskUsageRecord(UsageTypes.VM_DISK_IO_WRITE, 26L, 1024D);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMInstanceVO vmInstance = mockVmInstance("vm-disk-write-vm", 
"vm-disk-write-vm-uuid");
+        VolumeVO volume = mockVolume(26L, "vm-disk-write-volume-uuid", 
"vm-disk-write-volume");
+        when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, 
26L)).thenReturn(volume);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class},
+                usageRecord, response, false, vmInstance);
+
+        // Assert
+        assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O write 
requests", "vm-disk-write-volume-uuid", "vm-disk-write-volume", 26L);
+        verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, 
26L);
+    }
+
+    @Test
+    @DisplayName("VM_DISK_BYTES_READ usage populates disk read byte details")
+    public void populateVmDiskBytesReadUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = 
mockVmDiskUsageRecord(UsageTypes.VM_DISK_BYTES_READ, 27L, 2048D);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMInstanceVO vmInstance = mockVmInstance("vm-disk-bytes-read-vm", 
"vm-disk-bytes-read-vm-uuid");
+        VolumeVO volume = mockVolume(27L, "vm-disk-bytes-read-volume-uuid", 
"vm-disk-bytes-read-volume");
+        when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, 
27L)).thenReturn(volume);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class},
+                usageRecord, response, false, vmInstance);
+
+        // Assert
+        assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O read 
bytes", "vm-disk-bytes-read-volume-uuid", "vm-disk-bytes-read-volume", 27L);
+        verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, 
27L);
+    }
+
+    @Test
+    @DisplayName("VM_DISK_BYTES_WRITE usage populates disk write byte details")
+    public void populateVmDiskBytesWriteUsageResponseTest() throws Exception {
+        // Arrange
+        UsageVO usageRecord = 
mockVmDiskUsageRecord(UsageTypes.VM_DISK_BYTES_WRITE, 28L, 4096D);
+        UsageRecordResponse response = new UsageRecordResponse();
+        VMInstanceVO vmInstance = mockVmInstance("vm-disk-bytes-write-vm", 
"vm-disk-bytes-write-vm-uuid");
+        VolumeVO volume = mockVolume(28L, "vm-disk-bytes-write-volume-uuid", 
"vm-disk-bytes-write-volume");
+        when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, 
28L)).thenReturn(volume);
+
+        // Act
+        Object resourceDetails = 
invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+                new Class<?>[] {Usage.class, UsageRecordResponse.class, 
boolean.class, VMInstanceVO.class},
+                usageRecord, response, false, vmInstance);
+
+        // Assert
+        assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O write 
bytes", "vm-disk-bytes-write-volume-uuid", "vm-disk-bytes-write-volume", 28L);
+        verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, 
28L);
+    }
+
+    private Object invokeUsageDetailsHelper(String methodName, Class<?>[] 
parameterTypes, Object... args) throws Exception {
+        Method method = ApiResponseHelper.class.getDeclaredMethod(methodName, 
parameterTypes);
+        method.setAccessible(true);
+        return method.invoke(helper, args);

Review Comment:
   The new tests invoke private helpers directly, so they never verify 
dispatcher routing or tag propagation through `createUsageResponse`; they also 
provide no coverage for backup, VM snapshot, secondary-volume, primary 
VM-snapshot, or bucket helpers. Add public-method cases for every extracted 
branch so structural wiring regressions are detectable.



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