From 61ce43bdffe4e8cf0c3167ca06afcbc2f427f63b Mon Sep 17 00:00:00 2001 From: abhishek Date: Fri, 21 Jan 2011 15:24:36 -0800 Subject: [PATCH] bug 7892: introducing recursive listings for various artifacts based on the domain id and the isRecursive flag --- .../cloud/api/commands/ListAccountsCmd.java | 9 ++- .../cloud/api/commands/ListSnapshotsCmd.java | 7 +++ .../com/cloud/api/commands/ListVMsCmd.java | 6 ++ .../cloud/api/commands/ListVolumesCmd.java | 8 +++ .../cloud/server/ManagementServerImpl.java | 48 +++++++++++++--- .../storage/snapshot/SnapshotManagerImpl.java | 18 ++++-- .../src/com/cloud/vm/UserVmManagerImpl.java | 55 +++++++++++++++++++ 7 files changed, 137 insertions(+), 14 deletions(-) diff --git a/api/src/com/cloud/api/commands/ListAccountsCmd.java b/api/src/com/cloud/api/commands/ListAccountsCmd.java index 004f62a4952..e8a7ac0b3ec 100644 --- a/api/src/com/cloud/api/commands/ListAccountsCmd.java +++ b/api/src/com/cloud/api/commands/ListAccountsCmd.java @@ -26,6 +26,7 @@ import com.cloud.api.ApiConstants; import com.cloud.api.BaseListCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.AccountResponse; import com.cloud.api.response.ListResponse; import com.cloud.user.Account; @@ -57,7 +58,9 @@ public class ListAccountsCmd extends BaseListCmd { @Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="list accounts by state. Valid states are enabled, disabled, and locked.") private String state; - + @Parameter(name=ApiConstants.IS_RECURSIVE, type=CommandType.BOOLEAN, description="defaults to false, but if true, lists all accounts from the parent specified by the domain id till leaves.") + private Boolean recursive; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -85,6 +88,10 @@ public class ListAccountsCmd extends BaseListCmd { public String getState() { return state; } + + public Boolean isRecursive() { + return recursive; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/com/cloud/api/commands/ListSnapshotsCmd.java b/api/src/com/cloud/api/commands/ListSnapshotsCmd.java index e01f0e7a71b..0e8b4cd048a 100644 --- a/api/src/com/cloud/api/commands/ListSnapshotsCmd.java +++ b/api/src/com/cloud/api/commands/ListSnapshotsCmd.java @@ -26,6 +26,7 @@ import com.cloud.api.ApiConstants; import com.cloud.api.BaseListCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ListResponse; import com.cloud.api.response.SnapshotResponse; import com.cloud.async.AsyncJob; @@ -62,6 +63,8 @@ public class ListSnapshotsCmd extends BaseListCmd { @Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.LONG, description="the ID of the disk volume") private Long volumeId; + @Parameter(name=ApiConstants.IS_RECURSIVE, type=CommandType.BOOLEAN, description="defaults to false, but if true, lists all snapshots from the parent specified by the domain id till leaves.") + private Boolean recursive; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -94,6 +97,10 @@ public class ListSnapshotsCmd extends BaseListCmd { return volumeId; } + public Boolean isRecursive() { + return recursive; + + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/ListVMsCmd.java b/api/src/com/cloud/api/commands/ListVMsCmd.java index db5f7238e78..d90cf80128c 100644 --- a/api/src/com/cloud/api/commands/ListVMsCmd.java +++ b/api/src/com/cloud/api/commands/ListVMsCmd.java @@ -47,6 +47,9 @@ public class ListVMsCmd extends BaseListCmd { @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the domain ID. If used with the account parameter, lists virtual machines for the specified account in this domain.") private Long domainId; + @Parameter(name=ApiConstants.IS_RECURSIVE, type=CommandType.BOOLEAN, description="defaults to false, but if true, lists all vms from the parent specified by the domain id till leaves.") + private Boolean recursive; + @Parameter(name=ApiConstants.GROUP_ID, type=CommandType.LONG, description="the group ID") private Long groupId; @@ -126,6 +129,9 @@ public class ListVMsCmd extends BaseListCmd { return networkId; } + public Boolean isRecursive() { + return recursive; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/ListVolumesCmd.java b/api/src/com/cloud/api/commands/ListVolumesCmd.java index 368aeade8fe..ee4282e2d2f 100755 --- a/api/src/com/cloud/api/commands/ListVolumesCmd.java +++ b/api/src/com/cloud/api/commands/ListVolumesCmd.java @@ -26,6 +26,7 @@ import com.cloud.api.ApiConstants; import com.cloud.api.BaseListCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ListResponse; import com.cloud.api.response.VolumeResponse; import com.cloud.async.AsyncJob; @@ -68,6 +69,9 @@ public class ListVolumesCmd extends BaseListCmd { @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, description="the ID of the availability zone") private Long zoneId; + @Parameter(name=ApiConstants.IS_RECURSIVE, type=CommandType.BOOLEAN, description="defaults to false, but if true, lists all volumes from the parent specified by the domain id till leaves.") + private Boolean recursive; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -108,6 +112,10 @@ public class ListVolumesCmd extends BaseListCmd { return zoneId; } + public Boolean isRecursive() { + return recursive; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 6172d799d71..e3c34febed3 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1738,7 +1738,11 @@ public class ManagementServerImpl implements ManagementServer { Long domainId = cmd.getDomainId(); Long accountId = cmd.getId(); String accountName = null; - + Boolean isRecursive = cmd.isRecursive(); + + if(isRecursive == null) + isRecursive = false; + if(accountId != null && accountId == 1){ //system account should NOT be searchable List emptyList = new ArrayList(); @@ -1750,6 +1754,7 @@ public class ManagementServerImpl implements ManagementServer { if (domainId == null) { // default domainId to the admin's domain domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId()); + isRecursive = true; } else if (account != null) { if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) { throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts"); @@ -1775,13 +1780,21 @@ public class ManagementServerImpl implements ManagementServer { sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ); - if ((accountId == null) && (domainId != null)) { - // if accountId isn't specified, we can do a domain match for the admin case + if ((accountId == null) && (domainId != null) && isRecursive) { + // if accountId isn't specified, we can do a domain LIKE match for the admin case if isRecursive is true SearchBuilder domainSearch = _domainDao.createSearchBuilder(); domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); - } + } else if ((accountId == null) && (domainId != null) && !isRecursive) { + // if accountId isn't specified, we can do a domain EXACT match for the admin case if isRecursive is true + SearchBuilder domainSearch = _domainDao.createSearchBuilder(); + domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.EQ); + sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); + } + + + SearchCriteria sc = sb.create(); if (keyword != null) { SearchCriteria ssc = _accountDao.createSearchCriteria(); @@ -1801,7 +1814,11 @@ public class ManagementServerImpl implements ManagementServer { DomainVO domain = _domainDao.findById(domainId); // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%' - sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + if(isRecursive) + sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + else + sc.setJoinParameters("domainSearch", "path", domain.getPath()); + sc.setParameters("nid", 1L); } else { sc.setParameters("nid", 1L); @@ -2276,6 +2293,11 @@ public class ManagementServerImpl implements ManagementServer { String accountName = cmd.getAccountName(); Long accountId = null; boolean isAdmin = false; + Boolean isRecursive = cmd.isRecursive(); + + if(isRecursive == null) + isRecursive = false; + if ((account == null) || isAdmin(account.getType())) { isAdmin = true; if (domainId != null) { @@ -2292,6 +2314,7 @@ public class ManagementServerImpl implements ManagementServer { } } else { domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId()); + isRecursive = true; } } else { accountId = account.getId(); @@ -2339,12 +2362,16 @@ public class ManagementServerImpl implements ManagementServer { // Only return volumes that are not destroyed sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ); - if ((accountId == null) && (domainId != null)) { - // if accountId isn't specified, we can do a domain match for the admin case + if (((accountId == null) && (domainId != null) && isRecursive)) { + // if accountId isn't specified, we can do a domain match for the admin case if isRecursive is true SearchBuilder domainSearch = _domainDao.createSearchBuilder(); domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); - } + } else if((accountId == null) && (domainId != null) && !isRecursive) { + SearchBuilder domainSearch = _domainDao.createSearchBuilder(); + domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.EQ); + sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); + } // now set the SC criteria... SearchCriteria sc = sb.create(); @@ -2368,7 +2395,10 @@ public class ManagementServerImpl implements ManagementServer { sc.setParameters("accountIdEQ", accountId); } else if (domainId != null) { DomainVO domain = _domainDao.findById(domainId); - sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + if(isRecursive) + sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + else + sc.setJoinParameters("domainSearch", "path", domain.getPath()); } if (type != null) { sc.setParameters("volumeType", "%" + type + "%"); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index fbe01b3b9df..6bd2e140ae5 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -777,7 +777,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma @Override public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException { Long volumeId = cmd.getVolumeId(); - + Boolean isRecursive = cmd.isRecursive(); + // Verify parameters if(volumeId != null){ VolumeVO volume = _volsDao.findById(volumeId); @@ -798,7 +799,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma } } else if ((account != null) && (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)) { domainId = account.getDomainId(); - } + } if (domainId != null && accountName != null) { Account userAccount = _accountDao.findActiveAccount(accountName, domainId); @@ -810,6 +811,9 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma accountId = account.getId(); } + if(isRecursive == null) + isRecursive = false; + Object name = cmd.getSnapshotName(); Object id = cmd.getId(); Object keyword = cmd.getKeyword(); @@ -831,7 +835,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER); SearchBuilder domainSearch = _domainDao.createSearchBuilder(); - domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); + if(isRecursive) + domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); + else + domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.EQ); accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER); } @@ -863,7 +870,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma } else if (domainId != null) { DomainVO domain = _domainDao.findById(domainId); SearchCriteria joinSearch = sc.getJoin("accountSearch"); - joinSearch.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + if(isRecursive) + joinSearch.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + else + joinSearch.setJoinParameters("domainSearch", "path", domain.getPath()); } if (snapshotTypeStr != null) { diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 03283a189a7..759c089ed72 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2347,6 +2347,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager Long domainId = cmd.getDomainId(); String accountName = cmd.getAccountName(); Long accountId = null; + Boolean isRecursive = cmd.isRecursive(); + List domainsToSearchForVms = new ArrayList(); boolean isAdmin = false; String path = null; if ((account == null) || isAdmin(account.getType())) { @@ -2374,6 +2376,23 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager accountId = account.getId(); } + if(isRecursive == null) + isRecursive = false; + + if(isRecursive && domainId != null) { + DomainVO parentDomain = _domainDao.findById(domainId); + if(parentDomain.getName().equals("ROOT")) { + domainsToSearchForVms.addAll(_domainDao.listAll()); + return recursivelySearchForVms(cmd, path, isAdmin, domainsToSearchForVms, accountId); + }else { + domainsToSearchForVms.add(parentDomain); + domainsToSearchForVms.addAll(_domainDao.findAllChildren(parentDomain.getPath(), parentDomain.getId())); + return recursivelySearchForVms(cmd, path, isAdmin, domainsToSearchForVms, accountId); + } + } else if(isRecursive && domainId == null){ + throw new ServerApiException(BaseCmd.MALFORMED_PARAMETER_ERROR, "Please enter a parent domain id for listing vms recursively"); + } + Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal()); c.addCriteria(Criteria.KEYWORD, cmd.getKeyword()); c.addCriteria(Criteria.ID, cmd.getId()); @@ -2403,6 +2422,42 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager return searchForUserVMs(c); } + private List recursivelySearchForVms(ListVMsCmd cmd, String path, boolean isAdmin, List domainToSearchWithin, Long accountId) { + + List result = new ArrayList(); + for(DomainVO domain : domainToSearchWithin) { + + Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal()); + c.addCriteria(Criteria.KEYWORD, cmd.getKeyword()); + c.addCriteria(Criteria.ID, cmd.getId()); + c.addCriteria(Criteria.NAME, cmd.getInstanceName()); + c.addCriteria(Criteria.STATE, cmd.getState()); + c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId()); + c.addCriteria(Criteria.GROUPID, cmd.getGroupId()); + c.addCriteria(Criteria.FOR_VIRTUAL_NETWORK, cmd.getForVirtualNetwork()); + c.addCriteria(Criteria.NETWORKID, cmd.getNetworkId()); + + if (path != null) { + c.addCriteria(Criteria.PATH, path); + } + + // ignore these search requests if it's not an admin + if (isAdmin == true) { + c.addCriteria(Criteria.DOMAINID, domain.getId()); + c.addCriteria(Criteria.PODID, cmd.getPodId()); + c.addCriteria(Criteria.HOSTID, cmd.getHostId()); + } + + if (accountId != null) { + c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId}); + } + c.addCriteria(Criteria.ISADMIN, isAdmin); + + result.addAll(searchForUserVMs(c)); + } + return result; + } + @Override public List searchForUserVMs(Criteria c) { Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());