You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/11/01 01:21:59 UTC

[48/50] [abbrv] Merge branch 'master' into rbac.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/com/cloud/api/query/QueryManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/api/query/QueryManagerImpl.java
index 80a2227,51ee249..7ab2298
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@@ -44,7 -33,7 +43,8 @@@ import org.apache.cloudstack.affinity.A
  import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
  import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
  import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
+ import org.apache.cloudstack.api.ResourceDetail;
 +import org.apache.cloudstack.api.ResponseObject.ResponseView;
  import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
  import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd;
  import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
@@@ -165,9 -151,10 +167,9 @@@ import com.cloud.projects.ProjectManage
  import com.cloud.projects.dao.ProjectAccountDao;
  import com.cloud.projects.dao.ProjectDao;
  import com.cloud.resource.ResourceManager;
 -import com.cloud.server.Criteria;
  import com.cloud.server.ResourceMetaDataService;
  import com.cloud.server.ResourceTag;
- import com.cloud.server.ResourceTag.TaggedResourceType;
+ import com.cloud.server.ResourceTag.ResourceObjectType;
  import com.cloud.server.TaggedResourceService;
  import com.cloud.service.ServiceOfferingVO;
  import com.cloud.service.dao.ServiceOfferingDao;
@@@ -341,19 -336,10 +351,24 @@@ public class QueryManagerImpl extends M
      AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
  
      @Inject
 -    NetworkDetailsDao _networkDetailsDao;
 +    AclRoleJoinDao _aclRoleJoinDao;
 +
 +    @Inject
 +    AclRoleDao _aclRoleDao;
 +
 +    @Inject
 +    AclGroupJoinDao _aclGroupJoinDao;
 +
 +    @Inject
 +    AclGroupDao _aclGroupDao;
 +
 +    @Inject
 +    AclService _aclService;
++    
++    @Inject NetworkDetailsDao _networkDetailsDao;
+     
+     @Inject
+     ResourceTagDao _resourceTagDao;
  
      /*
       * (non-Javadoc)
@@@ -751,47 -730,82 +766,53 @@@
          Boolean isRecursive = domainIdRecursiveListProject.second();
          ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
  
 -        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
 -        // Criteria c = new Criteria(null, Boolean.FALSE, cmd.getStartIndex(),
 -        // cmd.getPageSizeVal()); //version without default sorting
 -        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
 -        c.addCriteria(Criteria.ID, cmd.getId());
 -        c.addCriteria(Criteria.NAME, cmd.getName());
 -        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());
 -        c.addCriteria(Criteria.TEMPLATE_ID, cmd.getTemplateId());
 -        c.addCriteria(Criteria.ISO_ID, cmd.getIsoId());
 -        c.addCriteria(Criteria.VPC_ID, cmd.getVpcId());
 -        c.addCriteria(Criteria.AFFINITY_GROUP_ID, cmd.getAffinityGroupId());
 +        Filter searchFilter = new Filter(UserVmJoinVO.class, "id", true, cmd.getStartIndex(),
 +                cmd.getPageSizeVal());
  
 -        if (domainId != null) {
 -            c.addCriteria(Criteria.DOMAINID, domainId);
 -        }
 +        // first search distinct vm id by using query criteria and pagination
 +        SearchBuilder<UserVmJoinVO> sb = _userVmJoinDao.createSearchBuilder();
 +        sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids
  
 -        if (HypervisorType.getType(hypervisor) != HypervisorType.None) {
 -            c.addCriteria(Criteria.HYPERVISOR, hypervisor);
 -        } else if (hypervisor != null) {
 -            throw new InvalidParameterValueException("Invalid HypervisorType " + hypervisor);
 -        }
 +        // build acl search builder condition
 +        _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts,
 +                listProjectResourcesCriteria, grantedIds, revokedIds);
  
 -        // ignore these search requests if it's not an admin
 +        Map<String, String> tags = cmd.getTags();
 +        String hypervisor = cmd.getHypervisor();
 +        Object name = cmd.getName();
 +        Object state = cmd.getState();
 +        Object zoneId = cmd.getZoneId();
 +        Object keyword = cmd.getKeyword();
 +        boolean isAdmin = false;
++        boolean isRootAdmin = false;
          if (_accountMgr.isAdmin(caller.getType())) {
 -            c.addCriteria(Criteria.PODID, cmd.getPodId());
 -            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
 -            c.addCriteria(Criteria.STORAGE_ID, cmd.getStorageId());
 +            isAdmin = true;
          }
 -
 -        if (!permittedAccounts.isEmpty()) {
 -            c.addCriteria(Criteria.ACCOUNTID, permittedAccounts.toArray());
++        if (_accountMgr.isRootAdmin(caller.getId())) {
++            isRootAdmin = true;
+         }
 -        c.addCriteria(Criteria.ISADMIN, _accountMgr.isAdmin(caller.getType()));
 -
 -        return searchForUserVMsByCriteria(c, caller, domainId, isRecursive, permittedAccounts, listAll,
 -                listProjectResourcesCriteria, tags);
 -    }
 -
 -    private Pair<List<UserVmJoinVO>, Integer> searchForUserVMsByCriteria(Criteria c, Account caller, Long domainId,
 -            boolean isRecursive, List<Long> permittedAccounts, boolean listAll,
 -            ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags) {
 -        Filter searchFilter = new Filter(UserVmJoinVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(),
 -                c.getLimit());
 -        boolean isRootAdmin = _accountMgr.isRootAdmin(caller.getType());
+ 
 -        // first search distinct vm id by using query criteria and pagination
 -        SearchBuilder<UserVmJoinVO> sb = _userVmJoinDao.createSearchBuilder();
 -        sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct
 -        // ids
 -        _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts,
 -                listProjectResourcesCriteria);
 +        Object groupId = cmd.getGroupId();
 +        Object networkId = cmd.getNetworkId();
 +        if (HypervisorType.getType(hypervisor) == HypervisorType.None && hypervisor != null) {
 +            // invalid hypervisor type input
 +            throw new InvalidParameterValueException("Invalid HypervisorType " + hypervisor);
 +        }
 +        Object templateId = cmd.getTemplateId();
 +        Object isoId = cmd.getIsoId();
 +        Object vpcId = cmd.getVpcId();
 +        Object affinityGroupId = cmd.getAffinityGroupId();
 +        Object pod = null;
 +        Object hostId = null;
 +        Object storageId = null;
 +        if (cmd instanceof ListVMsCmdByAdmin) {
 +            ListVMsCmdByAdmin adCmd = (ListVMsCmdByAdmin)cmd;
 +            pod = adCmd.getPodId();
 +            hostId = adCmd.getHostId();
 +            storageId = adCmd.getStorageId();
 +        }
  
 -        Object id = c.getCriteria(Criteria.ID);
 -        Object name = c.getCriteria(Criteria.NAME);
 -        Object state = c.getCriteria(Criteria.STATE);
 -        Object notState = c.getCriteria(Criteria.NOTSTATE);
 -        Object zoneId = c.getCriteria(Criteria.DATACENTERID);
 -        Object pod = c.getCriteria(Criteria.PODID);
 -        Object hostId = c.getCriteria(Criteria.HOSTID);
 -        Object hostName = c.getCriteria(Criteria.HOSTNAME);
 -        Object keyword = c.getCriteria(Criteria.KEYWORD);
 -        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
 -        assert c.getCriteria(Criteria.IPADDRESS) == null : "We don't support search by ip address on VM any more.  If you see this assert, it means we have to find a different way to search by the nic table.";
 -        Object groupId = c.getCriteria(Criteria.GROUPID);
 -        Object networkId = c.getCriteria(Criteria.NETWORKID);
 -        Object hypervisor = c.getCriteria(Criteria.HYPERVISOR);
 -        Object storageId = c.getCriteria(Criteria.STORAGE_ID);
 -        Object templateId = c.getCriteria(Criteria.TEMPLATE_ID);
 -        Object isoId = c.getCriteria(Criteria.ISO_ID);
 -        Object vpcId = c.getCriteria(Criteria.VPC_ID);
 -        Object affinityGroupId = c.getCriteria(Criteria.AFFINITY_GROUP_ID);
+ 
          sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
          sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
          sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
@@@ -826,7 -841,9 +847,10 @@@
              sb.and("affinityGroupId", sb.entity().getAffinityGroupId(), SearchCriteria.Op.EQ);
          }
  
 -        if(!isRootAdmin){
 +
++        if (!isRootAdmin) {
+             sb.and("displayVm", sb.entity().isDisplayVm(), SearchCriteria.Op.EQ);
+         }
  
          // populate the search criteria with the values passed in
          SearchCriteria<UserVmJoinVO> sc = sb.create();
@@@ -925,8 -945,14 +949,11 @@@
          if (storageId != null) {
              sc.setParameters("poolId", storageId);
          }
 -
 -        if (affinityGroupId != null) {
 -            sc.setParameters("affinityGroupId", affinityGroupId);
          }
  
+         if(!isRootAdmin){
+             sc.setParameters("displayVm", 1);
+         }
          // search vm details by ids
          Pair<List<UserVmJoinVO>, Integer> uniqueVmPair = _userVmJoinDao.searchAndCount(sc, searchFilter);
          Integer count = uniqueVmPair.second();
@@@ -2340,8 -2380,7 +2381,7 @@@
          isAscending = (isAscending == null ? true : isAscending);
          Filter searchFilter = new Filter(ServiceOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(),
                  cmd.getPageSizeVal());
-         SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
 -        
 +
          Account caller = CallContext.current().getCallingAccount();
          Object name = cmd.getServiceOfferingName();
          Object id = cmd.getId();
@@@ -2350,8 -2389,10 +2390,9 @@@
          Long domainId = cmd.getDomainId();
          Boolean isSystem = cmd.getIsSystem();
          String vmTypeStr = cmd.getSystemVmType();
 -        
 -        SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
  
 -        if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && isSystem) {
++        SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
 +        if (!_accountMgr.isRootAdmin(caller.getId()) && isSystem) {
              throw new InvalidParameterValueException("Only ROOT admins can access system's offering");
          }
  
@@@ -2376,11 -2438,20 +2438,20 @@@
              }
              // find all domain Id up to root domain for this account
              List<Long> domainIds = new ArrayList<Long>();
-             DomainVO domainRecord = _domainDao.findById(caller.getDomainId());
-             if (domainRecord == null) {
+             DomainVO domainRecord;
+             if (vmId != null) {
+                  UserVmVO vmInstance = _userVmDao.findById(vmId);
+                  domainRecord = _domainDao.findById(vmInstance.getDomainId());
+                  if ( domainRecord == null ){
+                      s_logger.error("Could not find the domainId for vmId:" + vmId);
+                      throw new CloudAuthenticationException("Could not find the domainId for vmId:" + vmId);
+                  }
+             } else {
+                  domainRecord = _domainDao.findById(caller.getDomainId());
+                  if ( domainRecord == null ){
 -                     s_logger.error("Could not find the domainId for account:" + caller.getAccountName());
 +                s_logger.error("Could not find the domainId for account:" + caller.getAccountName());
-                 throw new CloudAuthenticationException("Could not find the domainId for account:"
-                         + caller.getAccountName());
+                      throw new CloudAuthenticationException("Could not find the domainId for account:" + caller.getAccountName());
+                  }
              }
              domainIds.add(domainRecord.getId());
              while (domainRecord.getParent() != null) {
@@@ -2470,9 -2521,23 +2521,23 @@@
          String keyword = cmd.getKeyword();
          String name = cmd.getName();
          String networkType = cmd.getNetworkType();
+         Map<String, String> resourceTags = cmd.getTags();
+         
+         SearchBuilder<DataCenterJoinVO> sb = _dcJoinDao.createSearchBuilder();
+         if (resourceTags != null && !resourceTags.isEmpty()) {
+             SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
+             for (int count=0; count < resourceTags.size(); count++) {
+                 tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+                 tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+                 tagSearch.cp();
+             }
+             tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+             sb.groupBy(sb.entity().getId());
+             sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
+         }
 -        
 +
          Filter searchFilter = new Filter(DataCenterJoinVO.class, null, false, cmd.getStartIndex(), cmd.getPageSizeVal());
-         SearchCriteria<DataCenterJoinVO> sc = _dcJoinDao.createSearchCriteria();
+         SearchCriteria<DataCenterJoinVO> sc = sb.create();
  
          if (networkType != null) {
              sc.addAnd("networkType", SearchCriteria.Op.EQ, networkType);
@@@ -2621,7 -2686,17 +2686,17 @@@
                  }
              }
          }
 -        
 +
+         if (resourceTags != null && !resourceTags.isEmpty()) {
+             int count = 0;
+             sc.setJoinParameters("tagSearch", "resourceType", ResourceObjectType.Zone.toString());
+             for (String key : resourceTags.keySet()) {
+                 sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
+                 sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), resourceTags.get(key));
+                 count++;
+             }
+         }
+ 
          return _dcJoinDao.searchAndCount(sc, searchFilter);
      }
  
@@@ -2808,7 -2883,8 +2883,8 @@@
                      }
  
                      // get all child domain ID's
-                     if (_accountMgr.isAdmin(account.getType())) {
 -                    if (_accountMgr.isAdmin(account.getType()) 
++                    if (_accountMgr.isAdmin(account.getType())
+                             || (templateFilter == TemplateFilter.featured || templateFilter == TemplateFilter.community)) {
                          List<DomainVO> allChildDomains = _domainDao.findAllChildren(accountDomain.getPath(),
                                  accountDomain.getId());
                          for (DomainVO childDomain : allChildDomains) {
@@@ -3185,272 -3261,48 +3261,257 @@@
      }
  
      @Override
-     public List<ResourceDetailResponse> listResource(ListResourceDetailsCmd cmd) {
- 
+     public List<ResourceDetailResponse> listResourceDetails(ListResourceDetailsCmd cmd) {
          String key = cmd.getKey();
-         ResourceTag.TaggedResourceType resourceType = cmd.getResourceType();
-         String resourceId = cmd.getResourceId();
-         Long id = _taggedResourceMgr.getResourceId(resourceId, resourceType);
- 
-         if (resourceType == ResourceTag.TaggedResourceType.Volume) {
+         Boolean forDisplay = cmd.forDisplay();
+         ResourceTag.ResourceObjectType resourceType = cmd.getResourceType();
+         String resourceIdStr = cmd.getResourceId();
+         long resourceId = _taggedResourceMgr.getResourceId(resourceIdStr, resourceType);
 -        List<? extends ResourceDetail> detailList = new ArrayList<ResourceDetail>();        
++        List<? extends ResourceDetail> detailList = new ArrayList<ResourceDetail>();
+         ResourceDetail requestedDetail = null;
  
-             List<VolumeDetailVO> volumeDetailList;
 -        if (key == null) {
 +            if (key == null) {
-                 volumeDetailList = _volumeDetailDao.findDetails(id);
+             detailList = _resourceMetaDataMgr.getDetailsList(resourceId, resourceType, forDisplay);
 -        } else {
 +            } else {
-                 VolumeDetailVO volumeDetail = _volumeDetailDao.findDetail(id, key);
-                 volumeDetailList = new LinkedList<VolumeDetailVO>();
-                 volumeDetailList.add(volumeDetail);
+             requestedDetail = _resourceMetaDataMgr.getDetail(resourceId, resourceType, key);
+             if (forDisplay != null && requestedDetail.isDisplay() != forDisplay) {
+                 requestedDetail = null;
              }
- 
-             List<ResourceDetailResponse> volumeDetailResponseList = new ArrayList<ResourceDetailResponse>();
-             for (VolumeDetailVO volumeDetail : volumeDetailList) {
-                 ResourceDetailResponse volumeDetailResponse = new ResourceDetailResponse();
-                 volumeDetailResponse.setResourceId(id.toString());
-                 volumeDetailResponse.setName(volumeDetail.getName());
-                 volumeDetailResponse.setValue(volumeDetail.getValue());
-                 volumeDetailResponse.setResourceType(ResourceTag.TaggedResourceType.Volume.toString());
-                 volumeDetailResponse.setObjectName("volumedetail");
-                 volumeDetailResponseList.add(volumeDetailResponse);
 -        }
 -        
 +            }
 +
-             return volumeDetailResponseList;
- 
+         List<ResourceDetailResponse> responseList = new ArrayList<ResourceDetailResponse>();
+         if (requestedDetail != null) {
+             ResourceDetailResponse detailResponse = createResourceDetailsResponse(requestedDetail, resourceType);
+             responseList.add(detailResponse);
          } else {
- 
-             List<NicDetailVO> nicDetailList;
-             if (key == null) {
-                 nicDetailList = _nicDetailDao.findDetails(id);
-             } else {
-                 NicDetailVO nicDetail = _nicDetailDao.findDetail(id, key);
-                 nicDetailList = new LinkedList<NicDetailVO>();
-                 nicDetailList.add(nicDetail);
+             for (ResourceDetail detail : detailList) {
+                 ResourceDetailResponse detailResponse = createResourceDetailsResponse(detail, resourceType);
+                 responseList.add(detailResponse);
              }
- 
-             List<ResourceDetailResponse> nicDetailResponseList = new ArrayList<ResourceDetailResponse>();
-             for (NicDetailVO nicDetail : nicDetailList) {
-                 ResourceDetailResponse nicDetailResponse = new ResourceDetailResponse();
-                 // String uuid = ApiDBUtils.findN
-                 nicDetailResponse.setName(nicDetail.getName());
-                 nicDetailResponse.setValue(nicDetail.getValue());
-                 nicDetailResponse.setResourceType(ResourceTag.TaggedResourceType.Nic.toString());
-                 nicDetailResponse.setObjectName("nicdetail");
-                 nicDetailResponseList.add(nicDetailResponse);
 -        }
 -        
 +            }
 +
-             return nicDetailResponseList;
- 
+         return responseList;
 -    }
 +        }
  
+     
+     protected ResourceDetailResponse createResourceDetailsResponse(ResourceDetail requestedDetail, ResourceTag.ResourceObjectType resourceType) {
+         ResourceDetailResponse resourceDetailResponse = new ResourceDetailResponse();
+         resourceDetailResponse.setResourceId(String.valueOf(requestedDetail.getResourceId()));
+         resourceDetailResponse.setName(requestedDetail.getName());
+         resourceDetailResponse.setValue(requestedDetail.getValue());
+         resourceDetailResponse.setForDisplay(requestedDetail.isDisplay());
+         resourceDetailResponse.setResourceType(resourceType.toString().toString());
+         resourceDetailResponse.setObjectName("resourcedetail");
+         return resourceDetailResponse;
      }
  
 +    @Override
 +    public ListResponse<AclRoleResponse> listAclRoles(Long aclRoleId, String aclRoleName, Long domainId, Long startIndex, Long pageSize) {
 +        Pair<List<AclRoleJoinVO>, Integer> result = listAclRolesInternal(aclRoleId, aclRoleName, domainId, true, true, startIndex, pageSize);
 +        ListResponse<AclRoleResponse> response = new ListResponse<AclRoleResponse>();
 +
 +        List<AclRoleResponse> roleResponses = ViewResponseHelper.createAclRoleResponses(result.first());
 +        response.setResponses(roleResponses, result.second());
 +        return response;
 +    }
 +
 +    private Pair<List<AclRoleJoinVO>, Integer> listAclRolesInternal(Long aclRoleId, String aclRoleName, Long domainId, boolean isRecursive, boolean listAll, Long startIndex,
 +            Long pageSize) {
 +
 +        Account caller = CallContext.current().getCallingAccount();
 +        Boolean listForDomain = false;
 +
 +        if (aclRoleId != null) {
 +            AclRole role = _aclRoleDao.findById(aclRoleId);
 +            if (role == null) {
 +                throw new InvalidParameterValueException("Unable to find acl role by id " + aclRoleId);
 +            }
 +
 +            _accountMgr.checkAccess(caller, null, true, role);
 +        }
 +
 +        if (domainId != null) {
 +            Domain domain = _domainDao.findById(domainId);
 +            if (domain == null) {
 +                throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
 +            }
 +
 +            _accountMgr.checkAccess(caller, domain);
 +
 +            if (aclRoleName != null) {
 +                AclRole role = _aclRoleDao.findByName(domainId, aclRoleName);
 +                if (role == null) {
 +                    throw new InvalidParameterValueException("Unable to find acl role by name " + aclRoleName
 +                            + " in domain " + domainId);
 +                }
 +                _accountMgr.checkAccess(caller, null, true, role);
 +            }
 +        }
 +
 +        if (aclRoleId == null) {
 +            if (_accountMgr.isAdmin(caller.getType()) && listAll && domainId == null) {
 +                listForDomain = true;
 +                isRecursive = true;
 +                if (domainId == null) {
 +                    domainId = caller.getDomainId();
 +                }
 +            } else if (_accountMgr.isAdmin(caller.getType()) && domainId != null) {
 +                listForDomain = true;
 +            }
 +        }
 +
 +        Filter searchFilter = new Filter(AclRoleJoinVO.class, "id", true, startIndex, pageSize);
 +
 +
 +        SearchBuilder<AclRoleJoinVO> sb = _aclRoleJoinDao.createSearchBuilder();
 +        sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids
 +
 +        sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
 +        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
 +        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
 +
 +        if (listForDomain && isRecursive) {
 +            sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
 +        }
 +
 +        SearchCriteria<AclRoleJoinVO> sc = sb.create();
 +
 +        if (aclRoleName != null) {
 +            sc.setParameters("name", aclRoleName);
 +        }
 +
 +        if (aclRoleId != null) {
 +            sc.setParameters("id", aclRoleId);
 +        }
 +
 +        if (listForDomain) {
 +            if (isRecursive) {
 +                Domain domain = _domainDao.findById(domainId);
 +                sc.setParameters("path", domain.getPath() + "%");
 +            } else {
 +                sc.setParameters("domainId", domainId);
 +            }
 +        }
 +
 +
 +        // search role details by ids
 +        Pair<List<AclRoleJoinVO>, Integer> uniqueRolePair = _aclRoleJoinDao.searchAndCount(sc, searchFilter);
 +        Integer count = uniqueRolePair.second();
 +        if (count.intValue() == 0) {
 +            // empty result
 +            return uniqueRolePair;
 +        }
 +        List<AclRoleJoinVO> uniqueRoles = uniqueRolePair.first();
 +        Long[] vrIds = new Long[uniqueRoles.size()];
 +        int i = 0;
 +        for (AclRoleJoinVO v : uniqueRoles) {
 +            vrIds[i++] = v.getId();
 +        }
 +        List<AclRoleJoinVO> vrs = _aclRoleJoinDao.searchByIds(vrIds);
 +        return new Pair<List<AclRoleJoinVO>, Integer>(vrs, count);
 +    }
 +
 +    @Override
 +    public ListResponse<AclGroupResponse> listAclGroups(Long aclGroupId, String aclGroupName, Long domainId, Long startIndex, Long pageSize) {
 +        Pair<List<AclGroupJoinVO>, Integer> result = listAclGroupsInternal(aclGroupId, aclGroupName, domainId, true, true, startIndex, pageSize);
 +        ListResponse<AclGroupResponse> response = new ListResponse<AclGroupResponse>();
 +
 +        List<AclGroupResponse> groupResponses = ViewResponseHelper.createAclGroupResponses(result.first());
 +        response.setResponses(groupResponses, result.second());
 +        return response;
 +    }
 +
 +    private Pair<List<AclGroupJoinVO>, Integer> listAclGroupsInternal(Long aclGroupId, String aclGroupName, Long domainId, boolean isRecursive, boolean listAll, Long startIndex,
 +            Long pageSize) {
 +
 +        Account caller = CallContext.current().getCallingAccount();
 +        Boolean listForDomain = false;
 +
 +        if (aclGroupId != null) {
 +            AclGroup group = _aclGroupDao.findById(aclGroupId);
 +            if (group == null) {
 +                throw new InvalidParameterValueException("Unable to find acl group by id " + aclGroupId);
 +            }
 +
 +            _accountMgr.checkAccess(caller, null, true, group);
 +        }
 +
 +        if (domainId != null) {
 +            Domain domain = _domainDao.findById(domainId);
 +            if (domain == null) {
 +                throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
 +            }
 +
 +            _accountMgr.checkAccess(caller, domain);
 +
 +            if (aclGroupName != null) {
 +                AclGroup group = _aclGroupDao.findByName(domainId, aclGroupName);
 +                if (group == null) {
 +                    throw new InvalidParameterValueException("Unable to find acl group by name " + aclGroupName
 +                            + " in domain " + domainId);
 +                }
 +                _accountMgr.checkAccess(caller, null, true, group);
 +            }
 +        }
 +
 +        if (aclGroupId == null) {
 +            if (_accountMgr.isAdmin(caller.getType()) && listAll && domainId == null) {
 +                listForDomain = true;
 +                isRecursive = true;
 +                if (domainId == null) {
 +                    domainId = caller.getDomainId();
 +                }
 +            } else if (_accountMgr.isAdmin(caller.getType()) && domainId != null) {
 +                listForDomain = true;
 +            }
 +        }
 +
 +        Filter searchFilter = new Filter(AclGroupJoinVO.class, "id", true, startIndex, pageSize);
 +
 +        SearchBuilder<AclGroupJoinVO> sb = _aclGroupJoinDao.createSearchBuilder();
 +        sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids
 +
 +        sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
 +        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
 +        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
 +
 +        if (listForDomain && isRecursive) {
 +            sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
 +        }
 +
 +        SearchCriteria<AclGroupJoinVO> sc = sb.create();
 +
 +        if (aclGroupName != null) {
 +            sc.setParameters("name", aclGroupName);
 +        }
 +
 +        if (aclGroupId != null) {
 +            sc.setParameters("id", aclGroupId);
 +        }
 +
 +        if (listForDomain) {
 +            if (isRecursive) {
 +                Domain domain = _domainDao.findById(domainId);
 +                sc.setParameters("path", domain.getPath() + "%");
 +            } else {
 +                sc.setParameters("domainId", domainId);
 +            }
 +        }
 +
 +        // search group details by ids
 +        Pair<List<AclGroupJoinVO>, Integer> uniqueGroupPair = _aclGroupJoinDao.searchAndCount(sc, searchFilter);
 +        Integer count = uniqueGroupPair.second();
 +        if (count.intValue() == 0) {
 +            // empty result
 +            return uniqueGroupPair;
 +        }
 +        List<AclGroupJoinVO> uniqueGroups = uniqueGroupPair.first();
 +        Long[] vrIds = new Long[uniqueGroups.size()];
 +        int i = 0;
 +        for (AclGroupJoinVO v : uniqueGroups) {
 +            vrIds[i++] = v.getId();
 +        }
 +        List<AclGroupJoinVO> vrs = _aclGroupJoinDao.searchByIds(vrIds);
 +        return new Pair<List<AclGroupJoinVO>, Integer>(vrs, count);
 +    }
  }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
index 63bf563,c06e294..b28ace0
--- a/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
@@@ -19,20 -19,20 +19,22 @@@ package com.cloud.api.query.dao
  import java.util.List;
  
  import javax.ejb.Local;
 +import javax.inject.Inject;
  
+ import org.apache.cloudstack.api.response.ResourceTagResponse;
+ import org.apache.cloudstack.api.response.ZoneResponse;
+ import org.apache.cloudstack.context.CallContext;
  import org.apache.log4j.Logger;
+ import org.springframework.stereotype.Component;
  
  import com.cloud.api.ApiDBUtils;
  import com.cloud.api.ApiResponseHelper;
  import com.cloud.api.query.vo.DataCenterJoinVO;
+ import com.cloud.api.query.vo.ResourceTagJoinVO;
  import com.cloud.dc.DataCenter;
- 
- import org.apache.cloudstack.api.response.ZoneResponse;
- import org.apache.cloudstack.context.CallContext;
- 
+ import com.cloud.server.ResourceTag.ResourceObjectType;
  import com.cloud.user.Account;
 +import com.cloud.user.AccountManager;
  import com.cloud.utils.db.GenericDaoBase;
  import com.cloud.utils.db.SearchBuilder;
  import com.cloud.utils.db.SearchCriteria;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
index 01ceb10,799690e..0094638
--- a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
@@@ -263,7 -263,15 +266,15 @@@ public class UserVmJoinDaoImpl extends 
                  userVmResponse.addAffinityGroup(resp);
              }
          }
 -        
 +
+         // set resource details map
+         // only hypervisortoolsversion can be returned to the end user       }
+         if (userVm.getDetailName() != null && userVm.getDetailName().equalsIgnoreCase(VmDetailConstants.HYPERVISOR_TOOLS_VERSION)){
+             Map<String, String> resourceDetails = new HashMap<String, String>();
+             resourceDetails.put(userVm.getDetailName(), userVm.getDetailValue());
+             userVmResponse.setDetails(resourceDetails);
+         }
+ 
          userVmResponse.setObjectName(objectName);
          if (userVm.isDynamicallyScalable() == null) {
              userVmResponse.setDynamicallyScalable(false);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/com/cloud/api/query/vo/AclGroupJoinVO.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/api/query/vo/AclGroupJoinVO.java
index 0a32f4d,0000000..5d67e34
mode 100644,000000..100644
--- a/server/src/com/cloud/api/query/vo/AclGroupJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/AclGroupJoinVO.java
@@@ -1,190 -1,0 +1,186 @@@
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with the License.  You may obtain a copy of the License at
 +//
 +//   http://www.apache.org/licenses/LICENSE-2.0
 +//
 +// Unless required by applicable law or agreed to in writing,
 +// software distributed under the License is distributed on an
 +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 +// KIND, either express or implied.  See the License for the
 +// specific language governing permissions and limitations
 +// under the License.
 +package com.cloud.api.query.vo;
 +
 +import java.util.Date;
 +
 +import javax.persistence.Column;
 +import javax.persistence.Entity;
 +import javax.persistence.EnumType;
 +import javax.persistence.Enumerated;
 +import javax.persistence.GeneratedValue;
 +import javax.persistence.GenerationType;
 +import javax.persistence.Id;
 +import javax.persistence.Table;
 +
 +import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 +
 +import com.cloud.utils.db.GenericDao;
 +
 +@Entity
 +@Table(name = ("acl_group_view"))
 +public class AclGroupJoinVO extends BaseViewVO {
 +    @Id
 +    @GeneratedValue(strategy = GenerationType.IDENTITY)
 +    @Column(name = "id")
 +    private long id;
 +
 +    @Column(name = "name")
 +    private String name;
 +
 +    @Column(name = "description")
 +    private String description;
 +
 +    @Column(name = "uuid")
 +    private String uuid;
 +
 +    @Column(name = "domain_id")
 +    private long domainId;
 +
 +    @Column(name = "domain_uuid")
 +    private String domainUuid;
 +
 +    @Column(name = "domain_name")
 +    private String domainName;
 +
 +    @Column(name = "domain_path")
 +    private String domainPath;
 +
 +    @Column(name = GenericDao.REMOVED_COLUMN)
 +    private Date removed;
 +
 +    @Column(name = GenericDao.CREATED_COLUMN)
 +    private Date created;
 +
 +    @Column(name = "role_id")
 +    private long roleId;
 +
 +    @Column(name = "role_uuid")
 +    private String roleUuid;
 +
 +    @Column(name = "role_name")
 +    private String roleName;
 +
 +    @Column(name = "account_id")
 +    private long accountId;
 +
 +    @Column(name = "account_uuid")
 +    private String accountUuid;
 +
 +    @Column(name = "account_name")
 +    private String accountName;
 +
 +    @Column(name = "entity_type")
 +    private String entityType;
 +
 +    @Column(name = "entity_id")
 +    private long entityId;
 +
 +    @Column(name = "entity_uuid")
 +    private String entityUuid;
 +
 +    @Column(name = "access_type")
 +    @Enumerated(value = EnumType.STRING)
 +    AccessType accessType;
 +
 +    public AclGroupJoinVO() {
 +    }
 +
 +    @Override
 +    public long getId() {
 +        return id;
 +    }
 +
-     @Override
-     public void setId(long id) {
-         this.id = id;
-     }
 +
 +    public String getName() {
 +        return name;
 +    }
 +
 +    public String getDescription() {
 +        return description;
 +    }
 +
 +    public String getUuid() {
 +        return uuid;
 +    }
 +
 +    public long getDomainId() {
 +        return domainId;
 +    }
 +
 +    public String getDomainUuid() {
 +        return domainUuid;
 +    }
 +
 +    public String getDomainName() {
 +        return domainName;
 +    }
 +
 +    public String getDomainPath() {
 +        return domainPath;
 +    }
 +
 +
 +    public Date getRemoved() {
 +        return removed;
 +    }
 +
 +    public Date getCreated() {
 +        return created;
 +    }
 +
 +    public long getRoleId() {
 +        return roleId;
 +    }
 +
 +    public String getRoleUuid() {
 +        return roleUuid;
 +    }
 +
 +    public String getRoleName() {
 +        return roleName;
 +    }
 +
 +    public long getAccountId() {
 +        return accountId;
 +    }
 +
 +    public String getAccountUuid() {
 +        return accountUuid;
 +    }
 +
 +    public String getAccountName() {
 +        return accountName;
 +    }
 +
 +    public String getEntityType() {
 +        return entityType;
 +    }
 +
 +    public long getEntityId() {
 +        return entityId;
 +    }
 +
 +    public String getEntityUuid() {
 +        return entityUuid;
 +    }
 +
 +    public AccessType getAccessType() {
 +        return accessType;
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/com/cloud/api/query/vo/AclRoleJoinVO.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/api/query/vo/AclRoleJoinVO.java
index 97809ef,0000000..a18f034
mode 100644,000000..100644
--- a/server/src/com/cloud/api/query/vo/AclRoleJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/AclRoleJoinVO.java
@@@ -1,121 -1,0 +1,117 @@@
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with the License.  You may obtain a copy of the License at
 +//
 +//   http://www.apache.org/licenses/LICENSE-2.0
 +//
 +// Unless required by applicable law or agreed to in writing,
 +// software distributed under the License is distributed on an
 +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 +// KIND, either express or implied.  See the License for the
 +// specific language governing permissions and limitations
 +// under the License.
 +package com.cloud.api.query.vo;
 +
 +import java.util.Date;
 +
 +import javax.persistence.Column;
 +import javax.persistence.Entity;
 +import javax.persistence.GeneratedValue;
 +import javax.persistence.GenerationType;
 +import javax.persistence.Id;
 +import javax.persistence.Table;
 +
 +import com.cloud.utils.db.GenericDao;
 +
 +@Entity
 +@Table(name = ("acl_role_view"))
 +public class AclRoleJoinVO extends BaseViewVO {
 +    @Id
 +    @GeneratedValue(strategy = GenerationType.IDENTITY)
 +    @Column(name = "id")
 +    private long id;
 +
 +    @Column(name = "name")
 +    private String name;
 +
 +    @Column(name = "description")
 +    private String description;
 +
 +    @Column(name = "uuid")
 +    private String uuid;
 +
 +    @Column(name = "domain_id")
 +    private long domainId;
 +
 +    @Column(name = "domain_uuid")
 +    private String domainUuid;
 +
 +    @Column(name = "domain_name")
 +    private String domainName;
 +
 +    @Column(name = "domain_path")
 +    private String domainPath;
 +
 +    @Column(name = "api_name")
 +    private String apiName;
 +
 +    @Column(name = GenericDao.REMOVED_COLUMN)
 +    private Date removed;
 +
 +    @Column(name = GenericDao.CREATED_COLUMN)
 +    private Date created;
 +
 +    public AclRoleJoinVO() {
 +    }
 +
 +    @Override
 +    public long getId() {
 +        return id;
 +    }
 +
-     @Override
-     public void setId(long id) {
-         this.id = id;
-     }
 +
 +    public String getName() {
 +        return name;
 +    }
 +
 +    public String getDescription() {
 +        return description;
 +    }
 +
 +    public String getUuid() {
 +        return uuid;
 +    }
 +
 +    public long getDomainId() {
 +        return domainId;
 +    }
 +
 +    public String getDomainUuid() {
 +        return domainUuid;
 +    }
 +
 +    public String getDomainName() {
 +        return domainName;
 +    }
 +
 +    public String getDomainPath() {
 +        return domainPath;
 +    }
 +
 +    public String getApiName() {
 +        return apiName;
 +    }
 +
 +    public Date getRemoved() {
 +        return removed;
 +    }
 +
 +    public Date getCreated() {
 +        return created;
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/com/cloud/api/response/ApiResponseSerializer.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/api/response/ApiResponseSerializer.java
index 37f350f,fb32e7d..9631850
--- a/server/src/com/cloud/api/response/ApiResponseSerializer.java
+++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java
@@@ -16,19 -16,12 +16,18 @@@
  // under the License.
  package com.cloud.api.response;
  
 -import com.cloud.api.ApiDBUtils;
 -import com.cloud.api.ApiResponseGsonHelper;
 -import com.cloud.api.ApiServer;
 -import com.cloud.utils.encoding.URLEncoder;
 -import com.cloud.utils.exception.CloudRuntimeException;
 -import com.cloud.utils.exception.ExceptionProxyObject;
 +import java.lang.reflect.Field;
- import java.lang.reflect.Method;
 +import java.lang.reflect.Modifier;
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.Collection;
 +import java.util.Date;
 +import java.util.List;
 +import java.util.regex.Matcher;
 +import java.util.regex.Pattern;
 +
 +import org.apache.log4j.Logger;
 +
  import com.google.gson.Gson;
  import com.google.gson.annotations.SerializedName;