CLOUDSTACK-9351: Add ids parameter to resource listing API calls

This commit is contained in:
nvazquez 2016-04-12 10:57:55 -07:00 committed by nvazquez
parent 6d0c92be72
commit baa8610061
10 changed files with 225 additions and 9 deletions

View File

@ -551,6 +551,7 @@ public class ApiConstants {
public static final String VM_SNAPSHOT_DESCRIPTION = "description";
public static final String VM_SNAPSHOT_DISPLAYNAME = "name";
public static final String VM_SNAPSHOT_ID = "vmsnapshotid";
public static final String VM_SNAPSHOT_IDS = "vmsnapshotids";
public static final String VM_SNAPSHOT_DISK_IDS = "vmsnapshotdiskids";
public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory";
public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm";

View File

@ -48,6 +48,9 @@ public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = SnapshotResponse.class, description = "lists snapshot by snapshot ID")
private Long id;
@Parameter(name=ApiConstants.IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType=SnapshotResponse.class, description="the IDs of the snapshots, mutually exclusive with id", since = "4.9")
private List<Long> ids;
@Parameter(name = ApiConstants.INTERVAL_TYPE, type = CommandType.STRING, description = "valid values are HOURLY, DAILY, WEEKLY, and MONTHLY.")
private String intervalType;
@ -120,4 +123,8 @@ public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd {
setResponseObject(response);
}
public List<Long> getIds() {
return ids;
}
}

View File

@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.template;
import org.apache.log4j.Logger;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
@ -50,6 +51,9 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "the template ID")
private Long id;
@Parameter(name=ApiConstants.IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType=TemplateResponse.class, description="the IDs of the templates, mutually exclusive with id", since = "4.9")
private List<Long> ids;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the template name")
private String templateName;
@ -132,4 +136,8 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd {
response.setResponseName(getCommandName());
setResponseObject(response);
}
public List<Long> getIds() {
return ids;
}
}

View File

@ -39,6 +39,9 @@ public class ListVMSnapshotCmd extends BaseListTaggedResourcesCmd {
@Parameter(name = ApiConstants.VM_SNAPSHOT_ID, type = CommandType.UUID, entityType = VMSnapshotResponse.class, description = "The ID of the VM snapshot")
private Long id;
@Parameter(name=ApiConstants.VM_SNAPSHOT_IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType=VMSnapshotResponse.class, description="the IDs of the vm snapshots, mutually exclusive with vmsnapshotid", since = "4.9")
private List<Long> ids;
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "state of the virtual machine snapshot")
private String state;
@ -84,4 +87,8 @@ public class ListVMSnapshotCmd extends BaseListTaggedResourcesCmd {
return s_name;
}
public List<Long> getIds() {
return ids;
}
}

View File

@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.volume;
import org.apache.log4j.Logger;
import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
@ -53,6 +54,9 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, description = "the ID of the disk volume")
private Long id;
@Parameter(name=ApiConstants.IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType=VolumeResponse.class, description="the IDs of the volumes, mutually exclusive with id", since = "4.9")
private List<Long> ids;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the disk volume")
private String volumeName;
@ -153,4 +157,8 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd {
response.setResponseName(getCommandName());
setResponseObject(response);
}
public List<Long> getIds() {
return ids;
}
}

View File

@ -0,0 +1,62 @@
//
// 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;
import java.util.ArrayList;
import java.util.List;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.SearchCriteria;
public class MutualExclusiveIdsManagerBase extends ManagerBase {
/***
* Include ids list in query criteria if ids is not null
* @param sc search criteria, class type SearchCriteria<Z>
* @param ids ids list, class type List<T>
*/
protected <Z,T> void setIdsListToSearchCriteria(SearchCriteria<Z> sc, List<T> ids){
if (ids != null && !ids.isEmpty()) {
sc.setParameters("idIN", ids.toArray());
}
}
/***
* Mutually exclusive parameters id and ids for API calls.<br/>
* Retrieve a list of ids or a list containing id depending on which of them is not null, or null if both are null
* @param id entity id, class type T
* @param ids entities ids, class type List<T>
* @return if id is not null return a list containing id else return ids, if both parameters are null -> return null
* @throws InvalidParameterValueException - if id and ids are both not null
*/
protected <T> List<T> getIdsListFromCmd(T id, List<T> ids){
List<T> idsList = null;
if (id != null) {
if (ids != null && !ids.isEmpty()) {
throw new InvalidParameterValueException("Specify either id or ids but not both parameters");
}
idsList = new ArrayList<T>();
idsList.add(id);
} else {
idsList = ids;
}
return idsList;
}
}

View File

@ -205,7 +205,6 @@ import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
@ -222,7 +221,7 @@ import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
@Component
public class QueryManagerImpl extends ManagerBase implements QueryService, Configurable {
public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements QueryService, Configurable {
public static final Logger s_logger = Logger.getLogger(QueryManagerImpl.class);
@ -1731,6 +1730,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
Long zoneId = cmd.getZoneId();
Long podId = cmd.getPodId();
List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds());
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
cmd.getDomainId(), cmd.isRecursive(), null);
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts,
@ -1754,6 +1755,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN);
sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
sb.and("instanceId", sb.entity().getVmId(), SearchCriteria.Op.EQ);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
@ -1790,6 +1792,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
sc.setParameters("display", display);
}
setIdsListToSearchCriteria(sc, ids);
sc.setParameters("systemUse", 1);
if (tags != null && !tags.isEmpty()) {
@ -3077,14 +3081,15 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
return searchForTemplatesInternal(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null,
cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr,
cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl);
cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl,
cmd.getIds());
}
private Pair<List<TemplateJoinVO>, Integer> searchForTemplatesInternal(Long templateId, String name,
String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize,
Long startIndex, Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady,
List<Account> permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria,
Map<String, String> tags, boolean showRemovedTmpl) {
Map<String, String> tags, boolean showRemovedTmpl, List<Long> ids) {
// check if zone is configured, if not, just return empty list
List<HypervisorType> hypers = null;
@ -3104,6 +3109,9 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
SearchBuilder<TemplateJoinVO> sb = _templateJoinDao.createSearchBuilder();
sb.select(null, Func.DISTINCT, sb.entity().getTempZonePair()); // select distinct (templateId, zoneId) pair
if (ids != null && !ids.isEmpty()){
sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN);
}
SearchCriteria<TemplateJoinVO> sc = sb.create();
// verify templateId parameter and specially handle it
@ -3149,6 +3157,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
// hypers = _resourceMgr.listAvailHypervisorInZone(null, null);
// }
setIdsListToSearchCriteria(sc, ids);
// add criteria for project or not
if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) {
sc.addAnd("accountType", SearchCriteria.Op.NEQ, Account.ACCOUNT_TYPE_PROJECT);
@ -3386,7 +3396,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
return searchForTemplatesInternal(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true,
cmd.isBootable(), cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, true,
cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO);
cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO,
null);
}
@Override

View File

@ -58,6 +58,7 @@ import com.cloud.agent.api.Command;
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
import com.cloud.alert.AlertManager;
import com.cloud.api.commands.ListRecurringSnapshotScheduleCmd;
import com.cloud.api.query.MutualExclusiveIdsManagerBase;
import com.cloud.configuration.Config;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.ClusterVO;
@ -112,7 +113,6 @@ import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
@ -129,7 +129,7 @@ import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@Component
public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, SnapshotApiService {
public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements SnapshotManager, SnapshotApiService {
private static final Logger s_logger = Logger.getLogger(SnapshotManagerImpl.class);
@Inject
VMTemplateDao _templateDao;
@ -512,6 +512,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
}
}
List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds());
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null);
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
Long domainId = domainIdRecursiveListProject.first();
@ -526,6 +528,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
sb.and("volumeId", sb.entity().getVolumeId(), SearchCriteria.Op.EQ);
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN);
sb.and("snapshotTypeEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.IN);
sb.and("snapshotTypeNEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.NEQ);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
@ -565,6 +568,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
sc.setParameters("dataCenterId", zoneId);
}
setIdsListToSearchCriteria(sc, ids);
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}

View File

@ -46,6 +46,7 @@ import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO;
import org.apache.cloudstack.jobs.JobInfo;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import com.cloud.api.query.MutualExclusiveIdsManagerBase;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
@ -77,7 +78,6 @@ import com.cloud.utils.Pair;
import com.cloud.utils.Predicate;
import com.cloud.utils.ReflectionUse;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchBuilder;
@ -99,7 +99,7 @@ import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@Component
public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotManager, VMSnapshotService, VmWorkJobHandler {
public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements VMSnapshotManager, VMSnapshotService, VmWorkJobHandler {
private static final Logger s_logger = Logger.getLogger(VMSnapshotManagerImpl.class);
public static final String VM_WORK_JOB_HANDLER = VMSnapshotManagerImpl.class.getSimpleName();
@ -176,6 +176,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
String name = cmd.getVmSnapshotName();
String accountName = cmd.getAccountName();
List<Long> ids = getIdsListFromCmd(cmd.getId(), cmd.getIds());
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
cmd.getDomainId(), cmd.isRecursive(), null);
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, listAll,
@ -193,6 +195,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
sb.and("status", sb.entity().getState(), SearchCriteria.Op.IN);
sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN);
sb.and("display_name", sb.entity().getDisplayName(), SearchCriteria.Op.EQ);
sb.and("account_id", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.done();
@ -209,6 +212,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
sc.setParameters("vm_id", vmId);
}
setIdsListToSearchCriteria(sc, ids);
if (domainId != null) {
sc.setParameters("domain_id", domainId);
}

View File

@ -0,0 +1,102 @@
//
// 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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.never;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.db.SearchCriteria;
@RunWith(MockitoJUnitRunner.class)
public class MutualExclusiveIdsManagerBaseTest {
@Mock
SearchCriteria<String> sc;
private static Long id1 = 1L;
private static Long id2 = 2L;
private List<Long> idsList;
private List<Long> idsEmptyList;
private List<Long> expectedListId;
private List<Long> expectedListIds;
private MutualExclusiveIdsManagerBase mgr = new MutualExclusiveIdsManagerBase();
@Before
public void setup() {
idsList = Arrays.asList(id1, id2);
idsEmptyList = Arrays.asList();
expectedListId = Arrays.asList(id1);
expectedListIds = Arrays.asList(id1, id2);
}
@Test
public void testSetIdsListToSearchCriteria(){
mgr.setIdsListToSearchCriteria(sc, idsList);
Mockito.verify(sc).setParameters(Mockito.same("idIN"), Mockito.same(id1), Mockito.same(id2));
}
@Test
public void testSetIdsListToSearchCriteriaEmptyList(){
mgr.setIdsListToSearchCriteria(sc, idsEmptyList);
Mockito.verify(sc, never()).setParameters(Mockito.anyString(), Mockito.any());
}
@Test
public void testGetIdsListId(){
List<Long> result = mgr.getIdsListFromCmd(id1, idsEmptyList);
assertEquals(expectedListId, result);
}
@Test
public void testGetIdsListProvideList(){
List<Long> result = mgr.getIdsListFromCmd(null, idsList);
assertEquals(expectedListIds, result);
}
@Test(expected=InvalidParameterValueException.class)
public void testGetIdsListBothNotNull(){
mgr.getIdsListFromCmd(id1, idsList);
}
@Test
public void testGetIdsListBothNull(){
List<Long> result = mgr.getIdsListFromCmd(null, null);
assertNull(result);
}
@Test
public void testGetIdsEmptyListIdNull(){
List<Long> result = mgr.getIdsListFromCmd(null, idsEmptyList);
assertEquals(idsEmptyList, result);
}
}