2222import java .lang .reflect .InvocationTargetException ;
2323import java .text .DecimalFormat ;
2424import java .util .ArrayList ;
25+ import java .util .Arrays ;
2526import java .util .Date ;
2627import java .util .HashMap ;
2728import java .util .List ;
3233import javax .inject .Inject ;
3334import javax .naming .ConfigurationException ;
3435
35- import com .cloud .dc .ClusterVO ;
36- import com .cloud .utils .Ternary ;
3736import org .apache .cloudstack .api .ApiErrorCode ;
3837import org .apache .cloudstack .api .ListClustersMetricsCmd ;
3938import org .apache .cloudstack .api .ListDbMetricsCmd ;
102101import com .cloud .capacity .dao .CapacityDao ;
103102import com .cloud .capacity .dao .CapacityDaoImpl ;
104103import com .cloud .cluster .dao .ManagementServerHostDao ;
104+ import com .cloud .dc .ClusterVO ;
105105import com .cloud .dc .DataCenter ;
106106import com .cloud .dc .dao .ClusterDao ;
107107import com .cloud .dc .dao .DataCenterDao ;
114114import com .cloud .host .dao .HostDao ;
115115import com .cloud .network .router .VirtualRouter ;
116116import com .cloud .org .Cluster ;
117+ import com .cloud .projects .Project ;
117118import com .cloud .server .DbStatsCollection ;
118119import com .cloud .server .ManagementServerHostStats ;
119120import com .cloud .server .StatsCollector ;
126127import com .cloud .user .Account ;
127128import com .cloud .user .AccountManager ;
128129import com .cloud .utils .Pair ;
130+ import com .cloud .utils .Ternary ;
129131import com .cloud .utils .db .DbProperties ;
130132import com .cloud .utils .db .DbUtil ;
131133import com .cloud .utils .db .Filter ;
@@ -188,6 +190,10 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
188190
189191 private static Gson gson = new Gson ();
190192
193+ private final List <Account .Type > AccountTypesWithRecursiveUsageAccess = Arrays .asList (
194+ Account .Type .ADMIN , Account .Type .DOMAIN_ADMIN , Account .Type .READ_ONLY_ADMIN
195+ );
196+
191197 protected MetricsServiceImpl () {
192198 super ();
193199 }
@@ -249,17 +255,30 @@ public ListResponse<VolumeMetricsStatsResponse> searchForVolumeMetricsStats(List
249255 * @return the list of VMs.
250256 */
251257 protected Pair <List <UserVmVO >, Integer > searchForUserVmsInternal (ListVMsUsageHistoryCmd cmd ) {
258+ final Long id = cmd .getId ();
259+ Account caller = CallContext .current ().getCallingAccount ();
260+ List <Long > permittedAccounts = new ArrayList <>();
261+ boolean recursive = AccountTypesWithRecursiveUsageAccess .contains (caller .getType ());
262+ Ternary <Long , Boolean , Project .ListProjectResourcesCriteria > domainIdRecursiveListProject = new Ternary <>(null , recursive , null );
263+ accountMgr .buildACLSearchParameters (caller , id , null , null , permittedAccounts , domainIdRecursiveListProject , true , false );
264+ Long domainId = domainIdRecursiveListProject .first ();
265+ Boolean isRecursive = domainIdRecursiveListProject .second ();
266+ Project .ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject .third ();
267+
252268 Filter searchFilter = new Filter (UserVmVO .class , "id" , true , cmd .getStartIndex (), cmd .getPageSizeVal ());
253269 List <Long > ids = getIdsListFromCmd (cmd .getId (), cmd .getIds ());
254270 String name = cmd .getName ();
255271 String keyword = cmd .getKeyword ();
256272
257273 SearchBuilder <UserVmVO > sb = userVmDao .createSearchBuilder ();
274+ sb .select (null , SearchCriteria .Func .DISTINCT , sb .entity ().getId ()); // select distinct
275+ accountMgr .buildACLSearchBuilder (sb , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
258276 sb .and ("idIN" , sb .entity ().getId (), SearchCriteria .Op .IN );
259277 sb .and ("displayName" , sb .entity ().getDisplayName (), SearchCriteria .Op .LIKE );
260278 sb .and ("state" , sb .entity ().getState (), SearchCriteria .Op .EQ );
261279
262280 SearchCriteria <UserVmVO > sc = sb .create ();
281+ accountMgr .buildACLSearchCriteria (sc , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
263282 if (CollectionUtils .isNotEmpty (ids )) {
264283 sc .setParameters ("idIN" , ids .toArray ());
265284 }
@@ -274,7 +293,14 @@ protected Pair<List<UserVmVO>, Integer> searchForUserVmsInternal(ListVMsUsageHis
274293 sc .addAnd ("displayName" , SearchCriteria .Op .SC , ssc );
275294 }
276295
277- return userVmDao .searchAndCount (sc , searchFilter );
296+ Pair <List <UserVmVO >, Integer > uniqueVmPair = userVmDao .searchAndCount (sc , searchFilter );
297+ Integer count = uniqueVmPair .second ();
298+ if (count == 0 ) {
299+ return new Pair <>(new ArrayList <>(), count );
300+ }
301+ List <Long > vmIds = uniqueVmPair .first ().stream ().map (UserVmVO ::getId ).collect (Collectors .toList ());
302+ List <UserVmVO > vms = userVmDao .listByIds (vmIds );
303+ return new Pair <>(vms , count );
278304 }
279305
280306 /**
@@ -336,17 +362,49 @@ protected Map<Long,List<VmStatsVO>> searchForVmMetricsStatsInternal(Date startDa
336362 * @return the list of VMs.
337363 */
338364 protected Pair <List <VolumeVO >, Integer > searchForVolumesInternal (ListVolumesUsageHistoryCmd cmd ) {
365+ final Long id = cmd .getId ();
366+ Account caller = CallContext .current ().getCallingAccount ();
367+ List <Long > permittedAccounts = new ArrayList <>();
368+ boolean recursive = AccountTypesWithRecursiveUsageAccess .contains (caller .getType ());
369+ Ternary <Long , Boolean , Project .ListProjectResourcesCriteria > domainIdRecursiveListProject = new Ternary <>(null , recursive , null );
370+ accountMgr .buildACLSearchParameters (caller , id , null , null , permittedAccounts , domainIdRecursiveListProject , true , false );
371+ Long domainId = domainIdRecursiveListProject .first ();
372+ Boolean isRecursive = domainIdRecursiveListProject .second ();
373+ Project .ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject .third ();
374+
339375 Filter searchFilter = new Filter (VolumeVO .class , "id" , true , cmd .getStartIndex (), cmd .getPageSizeVal ());
340376 List <Long > ids = getIdsListFromCmd (cmd .getId (), cmd .getIds ());
341377 String name = cmd .getName ();
342378 String keyword = cmd .getKeyword ();
343379
344380 SearchBuilder <VolumeVO > sb = volumeDao .createSearchBuilder ();
381+ sb .select (null , SearchCriteria .Func .DISTINCT , sb .entity ().getId ()); // select distinct
382+ accountMgr .buildACLSearchBuilder (sb , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
345383 sb .and ("idIN" , sb .entity ().getId (), SearchCriteria .Op .IN );
346384 sb .and ("name" , sb .entity ().getName (), SearchCriteria .Op .EQ );
347385 sb .and ("state" , sb .entity ().getState (), SearchCriteria .Op .EQ );
348386
387+ boolean shouldListSystemVmVolumes = accountMgr .isRootAdmin (CallContext .current ().getCallingAccountId ());
388+ List <Long > vmIds = new ArrayList <>();
389+ if (!shouldListSystemVmVolumes ) {
390+ SearchBuilder <UserVmVO > vmSearch = userVmDao .createSearchBuilder ();
391+ vmSearch .select (null , SearchCriteria .Func .DISTINCT , vmSearch .entity ().getId ());
392+ accountMgr .buildACLSearchBuilder (vmSearch , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
393+ SearchCriteria <UserVmVO > vmSc = vmSearch .create ();
394+ accountMgr .buildACLSearchCriteria (vmSc , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
395+ List <UserVmVO > vms = userVmDao .search (vmSc , null );
396+ vmIds = vms .stream ().map (UserVmVO ::getId ).collect (Collectors .toList ());
397+ if (vmIds .isEmpty ()) {
398+ sb .and ("instanceIdNull" , sb .entity ().getInstanceId (), SearchCriteria .Op .NULL );
399+ } else {
400+ sb .and ().op ("instanceIdNull" , sb .entity ().getInstanceId (), SearchCriteria .Op .NULL );
401+ sb .or ("instanceIds" , sb .entity ().getInstanceId (), SearchCriteria .Op .IN );
402+ sb .cp ();
403+ }
404+ }
405+
349406 SearchCriteria <VolumeVO > sc = sb .create ();
407+ accountMgr .buildACLSearchCriteria (sc , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
350408 if (CollectionUtils .isNotEmpty (ids )) {
351409 sc .setParameters ("idIN" , ids .toArray ());
352410 }
@@ -359,8 +417,18 @@ protected Pair<List<VolumeVO>, Integer> searchForVolumesInternal(ListVolumesUsag
359417 ssc .addOr ("state" , SearchCriteria .Op .EQ , keyword );
360418 sc .addAnd ("name" , SearchCriteria .Op .SC , ssc );
361419 }
420+ if (!shouldListSystemVmVolumes && CollectionUtils .isNotEmpty (vmIds )) {
421+ sc .setParameters ("instanceIds" , vmIds .toArray ());
422+ }
362423
363- return volumeDao .searchAndCount (sc , searchFilter );
424+ Pair <List <VolumeVO >, Integer > uniqueVolumePair = volumeDao .searchAndCount (sc , searchFilter );
425+ Integer count = uniqueVolumePair .second ();
426+ if (count == 0 ) {
427+ return new Pair <>(new ArrayList <>(), count );
428+ }
429+ List <Long > volumeIds = uniqueVolumePair .first ().stream ().map (VolumeVO ::getId ).collect (Collectors .toList ());
430+ List <VolumeVO > volumes = volumeDao .listByIds (volumeIds );
431+ return new Pair <>(volumes , count );
364432 }
365433
366434 /**
0 commit comments