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 ;
10099import com .cloud .capacity .dao .CapacityDao ;
101100import com .cloud .capacity .dao .CapacityDaoImpl ;
102101import com .cloud .cluster .dao .ManagementServerHostDao ;
102+ import com .cloud .dc .ClusterVO ;
103103import com .cloud .dc .DataCenter ;
104104import com .cloud .dc .dao .ClusterDao ;
105105import com .cloud .dc .dao .DataCenterDao ;
112112import com .cloud .host .dao .HostDao ;
113113import com .cloud .network .router .VirtualRouter ;
114114import com .cloud .org .Cluster ;
115+ import com .cloud .projects .Project ;
115116import com .cloud .server .DbStatsCollection ;
116117import com .cloud .server .ManagementServerHostStats ;
117118import com .cloud .server .StatsCollector ;
124125import com .cloud .user .Account ;
125126import com .cloud .user .AccountManager ;
126127import com .cloud .utils .Pair ;
128+ import com .cloud .utils .Ternary ;
127129import com .cloud .utils .db .DbProperties ;
128130import com .cloud .utils .db .DbUtil ;
129131import com .cloud .utils .db .Filter ;
@@ -184,6 +186,10 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
184186
185187 private static Gson gson = new Gson ();
186188
189+ private final List <Account .Type > AccountTypesWithRecursiveUsageAccess = Arrays .asList (
190+ Account .Type .ADMIN , Account .Type .DOMAIN_ADMIN , Account .Type .READ_ONLY_ADMIN
191+ );
192+
187193 protected MetricsServiceImpl () {
188194 super ();
189195 }
@@ -245,17 +251,30 @@ public ListResponse<VolumeMetricsStatsResponse> searchForVolumeMetricsStats(List
245251 * @return the list of VMs.
246252 */
247253 protected Pair <List <UserVmVO >, Integer > searchForUserVmsInternal (ListVMsUsageHistoryCmd cmd ) {
254+ final Long id = cmd .getId ();
255+ Account caller = CallContext .current ().getCallingAccount ();
256+ List <Long > permittedAccounts = new ArrayList <>();
257+ boolean recursive = AccountTypesWithRecursiveUsageAccess .contains (caller .getType ());
258+ Ternary <Long , Boolean , Project .ListProjectResourcesCriteria > domainIdRecursiveListProject = new Ternary <>(null , recursive , null );
259+ accountMgr .buildACLSearchParameters (caller , id , null , null , permittedAccounts , domainIdRecursiveListProject , true , false );
260+ Long domainId = domainIdRecursiveListProject .first ();
261+ Boolean isRecursive = domainIdRecursiveListProject .second ();
262+ Project .ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject .third ();
263+
248264 Filter searchFilter = new Filter (UserVmVO .class , "id" , true , cmd .getStartIndex (), cmd .getPageSizeVal ());
249265 List <Long > ids = getIdsListFromCmd (cmd .getId (), cmd .getIds ());
250266 String name = cmd .getName ();
251267 String keyword = cmd .getKeyword ();
252268
253269 SearchBuilder <UserVmVO > sb = userVmDao .createSearchBuilder ();
270+ sb .select (null , SearchCriteria .Func .DISTINCT , sb .entity ().getId ()); // select distinct
271+ accountMgr .buildACLSearchBuilder (sb , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
254272 sb .and ("idIN" , sb .entity ().getId (), SearchCriteria .Op .IN );
255273 sb .and ("displayName" , sb .entity ().getDisplayName (), SearchCriteria .Op .LIKE );
256274 sb .and ("state" , sb .entity ().getState (), SearchCriteria .Op .EQ );
257275
258276 SearchCriteria <UserVmVO > sc = sb .create ();
277+ accountMgr .buildACLSearchCriteria (sc , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
259278 if (CollectionUtils .isNotEmpty (ids )) {
260279 sc .setParameters ("idIN" , ids .toArray ());
261280 }
@@ -269,7 +288,14 @@ protected Pair<List<UserVmVO>, Integer> searchForUserVmsInternal(ListVMsUsageHis
269288 sc .addAnd ("displayName" , SearchCriteria .Op .SC , ssc );
270289 }
271290
272- return userVmDao .searchAndCount (sc , searchFilter );
291+ Pair <List <UserVmVO >, Integer > uniqueVmPair = userVmDao .searchAndCount (sc , searchFilter );
292+ Integer count = uniqueVmPair .second ();
293+ if (count == 0 ) {
294+ return new Pair <>(new ArrayList <>(), count );
295+ }
296+ List <Long > vmIds = uniqueVmPair .first ().stream ().map (UserVmVO ::getId ).collect (Collectors .toList ());
297+ List <UserVmVO > vms = userVmDao .listByIds (vmIds );
298+ return new Pair <>(vms , count );
273299 }
274300
275301 /**
@@ -331,17 +357,49 @@ protected Map<Long,List<VmStatsVO>> searchForVmMetricsStatsInternal(Date startDa
331357 * @return the list of VMs.
332358 */
333359 protected Pair <List <VolumeVO >, Integer > searchForVolumesInternal (ListVolumesUsageHistoryCmd cmd ) {
360+ final Long id = cmd .getId ();
361+ Account caller = CallContext .current ().getCallingAccount ();
362+ List <Long > permittedAccounts = new ArrayList <>();
363+ boolean recursive = AccountTypesWithRecursiveUsageAccess .contains (caller .getType ());
364+ Ternary <Long , Boolean , Project .ListProjectResourcesCriteria > domainIdRecursiveListProject = new Ternary <>(null , recursive , null );
365+ accountMgr .buildACLSearchParameters (caller , id , null , null , permittedAccounts , domainIdRecursiveListProject , true , false );
366+ Long domainId = domainIdRecursiveListProject .first ();
367+ Boolean isRecursive = domainIdRecursiveListProject .second ();
368+ Project .ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject .third ();
369+
334370 Filter searchFilter = new Filter (VolumeVO .class , "id" , true , cmd .getStartIndex (), cmd .getPageSizeVal ());
335371 List <Long > ids = getIdsListFromCmd (cmd .getId (), cmd .getIds ());
336372 String name = cmd .getName ();
337373 String keyword = cmd .getKeyword ();
338374
339375 SearchBuilder <VolumeVO > sb = volumeDao .createSearchBuilder ();
376+ sb .select (null , SearchCriteria .Func .DISTINCT , sb .entity ().getId ()); // select distinct
377+ accountMgr .buildACLSearchBuilder (sb , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
340378 sb .and ("idIN" , sb .entity ().getId (), SearchCriteria .Op .IN );
341379 sb .and ("name" , sb .entity ().getName (), SearchCriteria .Op .EQ );
342380 sb .and ("state" , sb .entity ().getState (), SearchCriteria .Op .EQ );
343381
382+ boolean shouldListSystemVmVolumes = accountMgr .isRootAdmin (CallContext .current ().getCallingAccountId ());
383+ List <Long > vmIds = new ArrayList <>();
384+ if (!shouldListSystemVmVolumes ) {
385+ SearchBuilder <UserVmVO > vmSearch = userVmDao .createSearchBuilder ();
386+ vmSearch .select (null , SearchCriteria .Func .DISTINCT , vmSearch .entity ().getId ());
387+ accountMgr .buildACLSearchBuilder (vmSearch , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
388+ SearchCriteria <UserVmVO > vmSc = vmSearch .create ();
389+ accountMgr .buildACLSearchCriteria (vmSc , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
390+ List <UserVmVO > vms = userVmDao .search (vmSc , null );
391+ vmIds = vms .stream ().map (UserVmVO ::getId ).collect (Collectors .toList ());
392+ if (vmIds .isEmpty ()) {
393+ sb .and ("instanceIdNull" , sb .entity ().getInstanceId (), SearchCriteria .Op .NULL );
394+ } else {
395+ sb .and ().op ("instanceIdNull" , sb .entity ().getInstanceId (), SearchCriteria .Op .NULL );
396+ sb .or ("instanceIds" , sb .entity ().getInstanceId (), SearchCriteria .Op .IN );
397+ sb .cp ();
398+ }
399+ }
400+
344401 SearchCriteria <VolumeVO > sc = sb .create ();
402+ accountMgr .buildACLSearchCriteria (sc , domainId , isRecursive , permittedAccounts , listProjectResourcesCriteria );
345403 if (CollectionUtils .isNotEmpty (ids )) {
346404 sc .setParameters ("idIN" , ids .toArray ());
347405 }
@@ -354,8 +412,18 @@ protected Pair<List<VolumeVO>, Integer> searchForVolumesInternal(ListVolumesUsag
354412 ssc .addOr ("state" , SearchCriteria .Op .EQ , keyword );
355413 sc .addAnd ("name" , SearchCriteria .Op .SC , ssc );
356414 }
415+ if (!shouldListSystemVmVolumes && CollectionUtils .isNotEmpty (vmIds )) {
416+ sc .setParameters ("instanceIds" , vmIds .toArray ());
417+ }
357418
358- return volumeDao .searchAndCount (sc , searchFilter );
419+ Pair <List <VolumeVO >, Integer > uniqueVolumePair = volumeDao .searchAndCount (sc , searchFilter );
420+ Integer count = uniqueVolumePair .second ();
421+ if (count == 0 ) {
422+ return new Pair <>(new ArrayList <>(), count );
423+ }
424+ List <Long > volumeIds = uniqueVolumePair .first ().stream ().map (VolumeVO ::getId ).collect (Collectors .toList ());
425+ List <VolumeVO > volumes = volumeDao .listByIds (volumeIds );
426+ return new Pair <>(volumes , count );
359427 }
360428
361429 /**
0 commit comments