diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVolumesUsageHistoryCmd.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVolumesUsageHistoryCmd.java index 4e9191a16f8d..e5d6a2429d26 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVolumesUsageHistoryCmd.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVolumesUsageHistoryCmd.java @@ -21,7 +21,6 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.SystemVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.response.VolumeMetricsStatsResponse; @@ -37,7 +36,7 @@ public class ListVolumesUsageHistoryCmd extends BaseResourceUsageHistoryCmd { @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, description = "the ID of the volume.") private Long id; - @Parameter(name=ApiConstants.IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType= SystemVmResponse.class, description="the IDs of the volumes, mutually exclusive with id.") + @Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = VolumeResponse.class, description = "the IDs of the volumes, mutually exclusive with id.") private List ids; @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "name of the volume (a substring match is made against the parameter value returning the data for all matching Volumes).") diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index c305d9312baa..77785133428e 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -244,6 +244,30 @@ public ListResponse searchForVolumeMetricsStats(List return createVolumeMetricsStatsResponse(volumeList, volumeStatsList); } + /** + * Outputs the parameters that should be used for access control in the query of a resource to + * {@code permittedAccounts} and {@code domainIdRecursiveListProject}. + * @param isIdProvided indicates whether any ID was provided to the command + */ + private void buildBaseACLSearchParametersForMetrics(boolean isIdProvided, List permittedAccounts, Ternary domainIdRecursiveListProject) { + Account caller = CallContext.current().getCallingAccount(); + Account.Type callerType = caller.getType(); + + boolean recursive = AccountTypesWithRecursiveUsageAccess.contains(callerType); + domainIdRecursiveListProject.second(recursive); + + // If no ID was provided, then the listing will skip project resources (null); otherwise, project resources should + // be listed as well (any long allows this) + Long id = isIdProvided ? 1L : null; + + // Allow users to also list metrics of resources owned by projects they belong to (-1L), and admins to list all + // metrics belonging to their domains recursively (null) + Long projectId = isIdProvided && callerType == Account.Type.NORMAL ? -1L : null; + + accountMgr.buildACLSearchParameters(caller, id, null, projectId, permittedAccounts, domainIdRecursiveListProject, true, false); + } + /** * Searches VMs based on {@code ListVMsUsageHistoryCmd} parameters. * @@ -251,18 +275,18 @@ public ListResponse searchForVolumeMetricsStats(List * @return the list of VMs. */ protected Pair, Integer> searchForUserVmsInternal(ListVMsUsageHistoryCmd cmd) { - final Long id = cmd.getId(); - Account caller = CallContext.current().getCallingAccount(); + List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); + + boolean isIdProvided = CollectionUtils.isNotEmpty(ids); List permittedAccounts = new ArrayList<>(); - boolean recursive = AccountTypesWithRecursiveUsageAccess.contains(caller.getType()); - Ternary domainIdRecursiveListProject = new Ternary<>(null, recursive, null); - accountMgr.buildACLSearchParameters(caller, id, null, null, permittedAccounts, domainIdRecursiveListProject, true, false); + Ternary domainIdRecursiveListProject = new Ternary<>(null, null, null); + buildBaseACLSearchParametersForMetrics(isIdProvided, permittedAccounts, domainIdRecursiveListProject); + Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); Project.ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); Filter searchFilter = new Filter(UserVmVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); - List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); String name = cmd.getName(); String keyword = cmd.getKeyword(); @@ -357,18 +381,18 @@ protected Map> searchForVmMetricsStatsInternal(Date startDa * @return the list of VMs. */ protected Pair, Integer> searchForVolumesInternal(ListVolumesUsageHistoryCmd cmd) { - final Long id = cmd.getId(); - Account caller = CallContext.current().getCallingAccount(); + List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); + + boolean isIdProvided = CollectionUtils.isNotEmpty(ids); List permittedAccounts = new ArrayList<>(); - boolean recursive = AccountTypesWithRecursiveUsageAccess.contains(caller.getType()); - Ternary domainIdRecursiveListProject = new Ternary<>(null, recursive, null); - accountMgr.buildACLSearchParameters(caller, id, null, null, permittedAccounts, domainIdRecursiveListProject, true, false); + Ternary domainIdRecursiveListProject = new Ternary<>(null, null, null); + buildBaseACLSearchParametersForMetrics(isIdProvided, permittedAccounts, domainIdRecursiveListProject); + Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); Project.ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); Filter searchFilter = new Filter(VolumeVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); - List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); String name = cmd.getName(); String keyword = cmd.getKeyword();