mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
Create DB view for Volume to speed up ListVolumesCmd.
Signed-off-by: Min Chen <min.chen@citrix.com>
This commit is contained in:
parent
78d70d349b
commit
21c1623a03
@ -115,7 +115,6 @@ public interface StorageService{
|
||||
|
||||
Volume migrateVolume(Long volumeId, Long storagePoolId) throws ConcurrentOperationException;
|
||||
|
||||
Pair<List<? extends Volume>, Integer> searchForVolumes(ListVolumesCmd cmd);
|
||||
|
||||
/**
|
||||
* Uploads the volume to secondary storage
|
||||
|
||||
@ -116,17 +116,7 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd {
|
||||
|
||||
@Override
|
||||
public void execute(){
|
||||
Pair<List<? extends Volume>, Integer> volumes = _storageService.searchForVolumes(this);
|
||||
|
||||
ListResponse<VolumeResponse> response = new ListResponse<VolumeResponse>();
|
||||
List<VolumeResponse> volResponses = new ArrayList<VolumeResponse>();
|
||||
for (Volume volume : volumes.first()) {
|
||||
VolumeResponse volResponse = _responseGenerator.createVolumeResponse(volume);
|
||||
volResponse.setObjectName("volume");
|
||||
volResponses.add(volResponse);
|
||||
}
|
||||
|
||||
response.setResponses(volResponses, volumes.second());
|
||||
ListResponse<VolumeResponse> response = _queryService.searchForVolumes(this);
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
}
|
||||
|
||||
@ -17,7 +17,9 @@
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.storage.Volume;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
@ -28,7 +30,7 @@ import org.apache.cloudstack.api.Entity;
|
||||
|
||||
@Entity(value=Volume.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class VolumeResponse extends BaseResponse implements ControlledEntityResponse{
|
||||
public class VolumeResponse extends BaseResponse implements ControlledViewEntityResponse{
|
||||
@SerializedName(ApiConstants.ID)
|
||||
@Param(description = "ID of the disk volume")
|
||||
private String id;
|
||||
@ -156,9 +158,11 @@ public class VolumeResponse extends BaseResponse implements ControlledEntityResp
|
||||
private String status;
|
||||
|
||||
@SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with volume", responseObject = ResourceTagResponse.class)
|
||||
private List<ResourceTagResponse> tags;
|
||||
|
||||
private Set<ResourceTagResponse> tags;
|
||||
|
||||
public VolumeResponse(){
|
||||
tags = new HashSet<ResourceTagResponse>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getObjectId() {
|
||||
@ -304,7 +308,11 @@ public class VolumeResponse extends BaseResponse implements ControlledEntityResp
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
public void setTags(List<ResourceTagResponse> tags) {
|
||||
public void setTags(Set<ResourceTagResponse> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public void addTag(ResourceTagResponse tag){
|
||||
this.tags.add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCm
|
||||
import org.apache.cloudstack.api.command.user.tag.ListTagsCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
|
||||
import org.apache.cloudstack.api.response.DomainRouterResponse;
|
||||
import org.apache.cloudstack.api.response.EventResponse;
|
||||
import org.apache.cloudstack.api.response.HostResponse;
|
||||
@ -39,11 +40,11 @@ import org.apache.cloudstack.api.response.ResourceTagResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.UserResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
|
||||
|
||||
|
||||
import com.cloud.async.AsyncJob;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.storage.Snapshot;
|
||||
|
||||
/**
|
||||
* Service used for list api query.
|
||||
@ -73,4 +74,6 @@ public interface QueryService {
|
||||
public ListResponse<ProjectAccountResponse> listProjectAccounts(ListProjectAccountsCmd cmd);
|
||||
|
||||
public ListResponse<HostResponse> searchForServers(ListHostsCmd cmd);
|
||||
|
||||
public ListResponse<VolumeResponse> searchForVolumes(ListVolumesCmd cmd);
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ import org.apache.cloudstack.api.response.ResourceTagResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.UserResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
|
||||
import com.cloud.api.query.dao.DomainRouterJoinDao;
|
||||
import com.cloud.api.query.dao.HostJoinDao;
|
||||
@ -45,6 +46,7 @@ import com.cloud.api.query.dao.ProjectJoinDao;
|
||||
import com.cloud.api.query.dao.ResourceTagJoinDao;
|
||||
import com.cloud.api.query.dao.SecurityGroupJoinDao;
|
||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||
import com.cloud.api.query.dao.VolumeJoinDao;
|
||||
import com.cloud.api.query.vo.DomainRouterJoinVO;
|
||||
import com.cloud.api.query.vo.EventJoinVO;
|
||||
import com.cloud.api.query.vo.HostJoinVO;
|
||||
@ -56,6 +58,7 @@ import com.cloud.api.query.vo.ResourceTagJoinVO;
|
||||
import com.cloud.api.query.vo.SecurityGroupJoinVO;
|
||||
import com.cloud.api.query.vo.UserAccountJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.api.query.vo.VolumeJoinVO;
|
||||
import com.cloud.async.AsyncJob;
|
||||
import com.cloud.async.AsyncJobManager;
|
||||
import com.cloud.async.AsyncJobVO;
|
||||
@ -180,6 +183,7 @@ import com.cloud.storage.VMTemplateHostVO;
|
||||
import com.cloud.storage.VMTemplateS3VO;
|
||||
import com.cloud.storage.VMTemplateSwiftVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.Volume.Type;
|
||||
import com.cloud.storage.VolumeHostVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
@ -313,6 +317,7 @@ public class ApiDBUtils {
|
||||
private static ProjectAccountJoinDao _projectAccountJoinDao;
|
||||
private static ProjectInvitationJoinDao _projectInvitationJoinDao;
|
||||
private static HostJoinDao _hostJoinDao;
|
||||
private static VolumeJoinDao _volJoinDao;
|
||||
|
||||
private static PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
|
||||
private static PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
|
||||
@ -400,6 +405,7 @@ public class ApiDBUtils {
|
||||
_projectAccountJoinDao = locator.getDao(ProjectAccountJoinDao.class);
|
||||
_projectInvitationJoinDao = locator.getDao(ProjectInvitationJoinDao.class);
|
||||
_hostJoinDao = locator.getDao(HostJoinDao.class);
|
||||
_volJoinDao = locator.getDao(VolumeJoinDao.class);
|
||||
|
||||
_physicalNetworkTrafficTypeDao = locator.getDao(PhysicalNetworkTrafficTypeDao.class);
|
||||
_physicalNetworkServiceProviderDao = locator.getDao(PhysicalNetworkServiceProviderDao.class);
|
||||
@ -1324,4 +1330,18 @@ public class ApiDBUtils {
|
||||
public static List<HostJoinVO> newHostView(Host vr){
|
||||
return _hostJoinDao.newHostView(vr);
|
||||
}
|
||||
|
||||
public static VolumeResponse newVolumeResponse(VolumeJoinVO vr) {
|
||||
return _volJoinDao.newVolumeResponse(vr);
|
||||
}
|
||||
|
||||
|
||||
public static VolumeResponse fillVolumeDetails(VolumeResponse vrData, VolumeJoinVO vr){
|
||||
return _volJoinDao.setVolumeResponse(vrData, vr);
|
||||
}
|
||||
|
||||
public static List<VolumeJoinVO> newVolumeView(Volume vr){
|
||||
return _volJoinDao.newVolumeView(vr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -57,6 +57,7 @@ import com.cloud.api.query.vo.ResourceTagJoinVO;
|
||||
import com.cloud.api.query.vo.SecurityGroupJoinVO;
|
||||
import com.cloud.api.query.vo.UserAccountJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.api.query.vo.VolumeJoinVO;
|
||||
import com.cloud.api.response.ApiResponseSerializer;
|
||||
import org.apache.cloudstack.api.response.AsyncJobResponse;
|
||||
import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
|
||||
@ -1019,138 +1020,10 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
|
||||
@Override
|
||||
public VolumeResponse createVolumeResponse(Volume volume) {
|
||||
VolumeResponse volResponse = new VolumeResponse();
|
||||
volResponse.setId(volume.getUuid());
|
||||
|
||||
if (volume.getName() != null) {
|
||||
volResponse.setName(volume.getName());
|
||||
} else {
|
||||
volResponse.setName("");
|
||||
}
|
||||
|
||||
DataCenter zone = ApiDBUtils.findZoneById(volume.getDataCenterId());
|
||||
if (zone != null) {
|
||||
volResponse.setZoneId(zone.getUuid());
|
||||
volResponse.setZoneName(zone.getName());
|
||||
}
|
||||
|
||||
volResponse.setVolumeType(volume.getVolumeType().toString());
|
||||
volResponse.setDeviceId(volume.getDeviceId());
|
||||
|
||||
Long instanceId = volume.getInstanceId();
|
||||
if (instanceId != null && volume.getState() != Volume.State.Destroy) {
|
||||
VMInstanceVO vm = ApiDBUtils.findVMInstanceById(instanceId);
|
||||
if (vm != null) {
|
||||
volResponse.setVirtualMachineId(vm.getUuid());
|
||||
volResponse.setVirtualMachineName(vm.getHostName());
|
||||
volResponse.setVirtualMachineState(vm.getState().toString());
|
||||
UserVm userVm = ApiDBUtils.findUserVmById(vm.getId());
|
||||
if (userVm != null) {
|
||||
if (userVm.getDisplayName() != null) {
|
||||
volResponse.setVirtualMachineDisplayName(userVm.getDisplayName());
|
||||
}
|
||||
} else {
|
||||
s_logger.error("User Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
|
||||
}
|
||||
} else {
|
||||
s_logger.error("Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
|
||||
}
|
||||
}
|
||||
|
||||
// Show the virtual size of the volume
|
||||
volResponse.setSize(volume.getSize());
|
||||
|
||||
volResponse.setCreated(volume.getCreated());
|
||||
volResponse.setState(volume.getState().toString());
|
||||
if(volume.getState() == Volume.State.UploadOp){
|
||||
com.cloud.storage.VolumeHostVO volumeHostRef = ApiDBUtils.findVolumeHostRef(volume.getId(), volume.getDataCenterId());
|
||||
volResponse.setSize(volumeHostRef.getSize());
|
||||
volResponse.setCreated(volumeHostRef.getCreated());
|
||||
Account caller = UserContext.current().getCaller();
|
||||
if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)
|
||||
volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volumeHostRef.getFormat()).toString());
|
||||
if (volumeHostRef.getDownloadState() != Status.DOWNLOADED) {
|
||||
String volumeStatus = "Processing";
|
||||
if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
|
||||
if (volumeHostRef.getDownloadPercent() == 100) {
|
||||
volumeStatus = "Checking Volume";
|
||||
} else {
|
||||
volumeStatus = volumeHostRef.getDownloadPercent() + "% Uploaded";
|
||||
}
|
||||
volResponse.setState("Uploading");
|
||||
} else {
|
||||
volumeStatus = volumeHostRef.getErrorString();
|
||||
if(volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.NOT_DOWNLOADED){
|
||||
volResponse.setState("UploadNotStarted");
|
||||
}else {
|
||||
volResponse.setState("UploadError");
|
||||
}
|
||||
}
|
||||
volResponse.setStatus(volumeStatus);
|
||||
} else if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
|
||||
volResponse.setStatus("Upload Complete");
|
||||
volResponse.setState("Uploaded");
|
||||
} else {
|
||||
volResponse.setStatus("Successfully Installed");
|
||||
}
|
||||
}
|
||||
|
||||
populateOwner(volResponse, volume);
|
||||
|
||||
DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
|
||||
if (diskOffering != null) {
|
||||
if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
|
||||
volResponse.setServiceOfferingId(diskOffering.getUuid());
|
||||
} else {
|
||||
volResponse.setDiskOfferingId(diskOffering.getUuid());
|
||||
}
|
||||
|
||||
if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
|
||||
volResponse.setServiceOfferingName(diskOffering.getName());
|
||||
volResponse.setServiceOfferingDisplayText(diskOffering.getDisplayText());
|
||||
} else {
|
||||
volResponse.setDiskOfferingName(diskOffering.getName());
|
||||
volResponse.setDiskOfferingDisplayText(diskOffering.getDisplayText());
|
||||
}
|
||||
volResponse.setStorageType(diskOffering.getUseLocalStorage() ? ServiceOffering.StorageType.local.toString()
|
||||
: ServiceOffering.StorageType.shared.toString());
|
||||
}
|
||||
Long poolId = volume.getPoolId();
|
||||
String poolName = (poolId == null) ? "none" : ApiDBUtils.findStoragePoolById(poolId).getName();
|
||||
volResponse.setStoragePoolName(poolName);
|
||||
// volResponse.setSourceId(volume.getSourceId());
|
||||
// if (volume.getSourceType() != null) {
|
||||
// volResponse.setSourceType(volume.getSourceType().toString());
|
||||
// }
|
||||
|
||||
// return hypervisor for ROOT and Resource domain only
|
||||
Account caller = UserContext.current().getCaller();
|
||||
if ((caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) && volume.getState() != Volume.State.UploadOp) {
|
||||
volResponse.setHypervisor(ApiDBUtils.getVolumeHyperType(volume.getId()).toString());
|
||||
}
|
||||
|
||||
volResponse.setAttached(volume.getAttached());
|
||||
volResponse.setDestroyed(volume.getState() == Volume.State.Destroy);
|
||||
boolean isExtractable = true;
|
||||
if (volume.getVolumeType() != Volume.Type.DATADISK) { // Datadisk dont have any template dependence.
|
||||
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
|
||||
if (template != null) { // For ISO based volumes template = null and we allow extraction of all ISO based volumes
|
||||
isExtractable = template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
|
||||
}
|
||||
}
|
||||
|
||||
//set tag information
|
||||
List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Volume, volume.getId());
|
||||
List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
|
||||
for (ResourceTag tag : tags) {
|
||||
ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
|
||||
tagResponses.add(tagResponse);
|
||||
}
|
||||
volResponse.setTags(tagResponses);
|
||||
|
||||
volResponse.setExtractable(isExtractable);
|
||||
volResponse.setObjectName("volume");
|
||||
return volResponse;
|
||||
List<VolumeJoinVO> viewVrs = ApiDBUtils.newVolumeView(volume);
|
||||
List<VolumeResponse> listVrs = ViewResponseHelper.createVolumeResponse(viewVrs.toArray(new VolumeJoinVO[viewVrs.size()]));
|
||||
assert listVrs != null && listVrs.size() == 1 : "There should be one volume returned";
|
||||
return listVrs.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -55,6 +55,7 @@ import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
|
||||
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.ConnectionClosedException;
|
||||
@ -464,7 +465,8 @@ public class ApiServer implements HttpRequestHandler {
|
||||
&& !(cmdObj instanceof ListProjectsCmd)
|
||||
&& !(cmdObj instanceof ListProjectAccountsCmd)
|
||||
&& !(cmdObj instanceof ListProjectInvitationsCmd)
|
||||
&& !(cmdObj instanceof ListHostsCmd)) {
|
||||
&& !(cmdObj instanceof ListHostsCmd)
|
||||
&& !(cmdObj instanceof ListVolumesCmd)) {
|
||||
buildAsyncListResponse((BaseListCmd) cmdObj, caller);
|
||||
}
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCm
|
||||
import org.apache.cloudstack.api.command.user.tag.ListTagsCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
|
||||
import org.apache.cloudstack.api.response.DomainRouterResponse;
|
||||
import org.apache.cloudstack.api.response.EventResponse;
|
||||
import org.apache.cloudstack.api.response.HostResponse;
|
||||
@ -51,6 +52,7 @@ import org.apache.cloudstack.api.response.ResourceTagResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.UserResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
import org.apache.cloudstack.query.QueryService;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
@ -65,6 +67,7 @@ import com.cloud.api.query.dao.ProjectJoinDao;
|
||||
import com.cloud.api.query.dao.ResourceTagJoinDao;
|
||||
import com.cloud.api.query.dao.SecurityGroupJoinDao;
|
||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||
import com.cloud.api.query.dao.VolumeJoinDao;
|
||||
import com.cloud.api.query.vo.DomainRouterJoinVO;
|
||||
import com.cloud.api.query.vo.EventJoinVO;
|
||||
import com.cloud.api.query.vo.HostJoinVO;
|
||||
@ -76,6 +79,7 @@ import com.cloud.api.query.vo.ResourceTagJoinVO;
|
||||
import com.cloud.api.query.vo.SecurityGroupJoinVO;
|
||||
import com.cloud.api.query.vo.UserAccountJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.api.query.vo.VolumeJoinVO;
|
||||
import com.cloud.async.AsyncJob;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.domain.DomainVO;
|
||||
@ -98,7 +102,12 @@ import com.cloud.projects.ProjectService;
|
||||
import com.cloud.projects.dao.ProjectAccountDao;
|
||||
import com.cloud.projects.dao.ProjectDao;
|
||||
import com.cloud.server.Criteria;
|
||||
import com.cloud.server.ResourceTag.TaggedResourceType;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.tags.ResourceTagVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountManagerImpl;
|
||||
@ -119,6 +128,8 @@ import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.SearchCriteria.Func;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
|
||||
/**
|
||||
@ -188,6 +199,9 @@ public class QueryManagerImpl implements QueryService, Manager {
|
||||
@Inject
|
||||
private HostJoinDao _hostJoinDao;
|
||||
|
||||
@Inject
|
||||
private VolumeJoinDao _volumeJoinDao;
|
||||
|
||||
@Inject
|
||||
private HighAvailabilityManager _haMgr;
|
||||
|
||||
@ -1371,9 +1385,9 @@ public class QueryManagerImpl implements QueryService, Manager {
|
||||
if ((Boolean) haHosts) {
|
||||
sb.and("tag", sb.entity().getTag(), SearchCriteria.Op.EQ);
|
||||
} else {
|
||||
sb.and("tag", sb.entity().getTag(), SearchCriteria.Op.NEQ);
|
||||
//FIXME: should we have another condition say tag = null?
|
||||
//hostTagSearch.or("tagNull", hostTagSearch.entity().getTag(), SearchCriteria.Op.NULL);
|
||||
sb.and().op("tag", sb.entity().getTag(), SearchCriteria.Op.NEQ);
|
||||
sb.or("tagNull", sb.entity().getTag(), SearchCriteria.Op.NULL);
|
||||
sb.cp();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1439,4 +1453,142 @@ public class QueryManagerImpl implements QueryService, Manager {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListResponse<VolumeResponse> searchForVolumes(ListVolumesCmd cmd) {
|
||||
Pair<List<VolumeJoinVO>, Integer> result = searchForVolumesInternal(cmd);
|
||||
ListResponse<VolumeResponse> response = new ListResponse<VolumeResponse>();
|
||||
|
||||
List<VolumeResponse> routerResponses = ViewResponseHelper.createVolumeResponse(result.first().toArray(new VolumeJoinVO[result.first().size()]));
|
||||
response.setResponses(routerResponses, result.second());
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
private Pair<List<VolumeJoinVO>, Integer> searchForVolumesInternal(ListVolumesCmd cmd) {
|
||||
|
||||
Account caller = UserContext.current().getCaller();
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
|
||||
Long id = cmd.getId();
|
||||
Long vmInstanceId = cmd.getVirtualMachineId();
|
||||
String name = cmd.getVolumeName();
|
||||
String keyword = cmd.getKeyword();
|
||||
String type = cmd.getType();
|
||||
Map<String, String> tags = cmd.getTags();
|
||||
|
||||
Long zoneId = cmd.getZoneId();
|
||||
Long podId = null;
|
||||
if (_accountMgr.isAdmin(caller.getType())) {
|
||||
podId = cmd.getPodId();
|
||||
}
|
||||
|
||||
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();
|
||||
Boolean isRecursive = domainIdRecursiveListProject.second();
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
|
||||
Filter searchFilter = new Filter(VolumeJoinVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
|
||||
// hack for now, this should be done better but due to needing a join I opted to
|
||||
// do this quickly and worry about making it pretty later
|
||||
SearchBuilder<VolumeJoinVO> sb = _volumeJoinDao.createSearchBuilder();
|
||||
sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct
|
||||
// ids to get
|
||||
// number of
|
||||
// records with
|
||||
// pagination
|
||||
_accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
|
||||
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
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);
|
||||
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
|
||||
// Only return volumes that are not destroyed
|
||||
sb.and("state", sb.entity().getState(), SearchCriteria.Op.NEQ);
|
||||
sb.and("systemUse", sb.entity().isSystemUse(), SearchCriteria.Op.NEQ);
|
||||
// display UserVM volumes only
|
||||
sb.and().op("type", sb.entity().getVmType(), SearchCriteria.Op.NIN);
|
||||
sb.or("nulltype", sb.entity().getVmType(), SearchCriteria.Op.NULL);
|
||||
sb.cp();
|
||||
|
||||
if (tags != null && !tags.isEmpty()) {
|
||||
for (int count=0; count < tags.size(); count++) {
|
||||
sb.or().op("key" + String.valueOf(count), sb.entity().getTagKey(), SearchCriteria.Op.EQ);
|
||||
sb.and("value" + String.valueOf(count), sb.entity().getTagValue(), SearchCriteria.Op.EQ);
|
||||
sb.cp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// now set the SC criteria...
|
||||
SearchCriteria<VolumeJoinVO> sc = sb.create();
|
||||
_accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
|
||||
|
||||
if (keyword != null) {
|
||||
SearchCriteria<VolumeJoinVO> ssc = _volumeJoinDao.createSearchCriteria();
|
||||
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
|
||||
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
sc.setParameters("name", "%" + name + "%");
|
||||
}
|
||||
|
||||
sc.setParameters("systemUse", 1);
|
||||
|
||||
if (tags != null && !tags.isEmpty()) {
|
||||
int count = 0;
|
||||
for (String key : tags.keySet()) {
|
||||
sc.setParameters("key" + String.valueOf(count), key);
|
||||
sc.setParameters("value" + String.valueOf(count), tags.get(key));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
sc.setParameters("id", id);
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
sc.setParameters("volumeType", "%" + type + "%");
|
||||
}
|
||||
if (vmInstanceId != null) {
|
||||
sc.setParameters("instanceId", vmInstanceId);
|
||||
}
|
||||
if (zoneId != null) {
|
||||
sc.setParameters("dataCenterId", zoneId);
|
||||
}
|
||||
if (podId != null) {
|
||||
sc.setParameters("podId", podId);
|
||||
}
|
||||
|
||||
// Don't return DomR and ConsoleProxy volumes
|
||||
sc.setParameters("type", VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.DomainRouter);
|
||||
|
||||
// Only return volumes that are not destroyed
|
||||
sc.setParameters("state", Volume.State.Destroy);
|
||||
|
||||
// search Volume details by ids
|
||||
Pair<List<VolumeJoinVO>, Integer> uniqueVolPair = _volumeJoinDao.searchAndCount(sc, searchFilter);
|
||||
Integer count = uniqueVolPair.second();
|
||||
if (count.intValue() == 0) {
|
||||
// empty result
|
||||
return uniqueVolPair;
|
||||
}
|
||||
List<VolumeJoinVO> uniqueVols = uniqueVolPair.first();
|
||||
Long[] vrIds = new Long[uniqueVols.size()];
|
||||
int i = 0;
|
||||
for (VolumeJoinVO v : uniqueVols) {
|
||||
vrIds[i++] = v.getId();
|
||||
}
|
||||
List<VolumeJoinVO> vrs = _volumeJoinDao.searchByIds(vrIds);
|
||||
return new Pair<List<VolumeJoinVO>, Integer>(vrs, count);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ import org.apache.cloudstack.api.response.ResourceTagResponse;
|
||||
import org.apache.cloudstack.api.response.SecurityGroupResponse;
|
||||
import org.apache.cloudstack.api.response.UserResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
@ -48,6 +49,7 @@ import com.cloud.api.query.vo.ResourceTagJoinVO;
|
||||
import com.cloud.api.query.vo.SecurityGroupJoinVO;
|
||||
import com.cloud.api.query.vo.UserAccountJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.api.query.vo.VolumeJoinVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.UserContext;
|
||||
|
||||
@ -214,4 +216,21 @@ public class ViewResponseHelper {
|
||||
}
|
||||
return new ArrayList<HostResponse>(vrDataList.values());
|
||||
}
|
||||
|
||||
public static List<VolumeResponse> createVolumeResponse(VolumeJoinVO... volumes) {
|
||||
Hashtable<Long, VolumeResponse> vrDataList = new Hashtable<Long, VolumeResponse>();
|
||||
for (VolumeJoinVO vr : volumes) {
|
||||
VolumeResponse vrData = vrDataList.get(vr.getId());
|
||||
if ( vrData == null ){
|
||||
// first time encountering this volume
|
||||
vrData = ApiDBUtils.newVolumeResponse(vr);
|
||||
}
|
||||
else{
|
||||
// update tags
|
||||
vrData = ApiDBUtils.fillVolumeDetails(vrData, vr);
|
||||
}
|
||||
vrDataList.put(vr.getId(), vrData);
|
||||
}
|
||||
return new ArrayList<VolumeResponse>(vrDataList.values());
|
||||
}
|
||||
}
|
||||
|
||||
37
server/src/com/cloud/api/query/dao/VolumeJoinDao.java
Normal file
37
server/src/com/cloud/api/query/dao/VolumeJoinDao.java
Normal file
@ -0,0 +1,37 @@
|
||||
// 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
|
||||
|
||||
import com.cloud.api.query.vo.VolumeJoinVO;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface VolumeJoinDao extends GenericDao<VolumeJoinVO, Long> {
|
||||
|
||||
VolumeResponse newVolumeResponse(VolumeJoinVO vol);
|
||||
|
||||
VolumeResponse setVolumeResponse(VolumeResponse volData, VolumeJoinVO vol);
|
||||
|
||||
List<VolumeJoinVO> newVolumeView(Volume vol);
|
||||
|
||||
List<VolumeJoinVO> searchByIds(Long... ids);
|
||||
}
|
||||
230
server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
Normal file
230
server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
Normal file
@ -0,0 +1,230 @@
|
||||
// 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import com.cloud.api.ApiResponseHelper;
|
||||
import com.cloud.api.query.vo.ResourceTagJoinVO;
|
||||
import com.cloud.api.query.vo.VolumeJoinVO;
|
||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.VMTemplateHostVO;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
|
||||
@Local(value={VolumeJoinDao.class})
|
||||
public class VolumeJoinDaoImpl extends GenericDaoBase<VolumeJoinVO, Long> implements VolumeJoinDao {
|
||||
public static final Logger s_logger = Logger.getLogger(VolumeJoinDaoImpl.class);
|
||||
|
||||
private SearchBuilder<VolumeJoinVO> volSearch;
|
||||
|
||||
private SearchBuilder<VolumeJoinVO> volIdSearch;
|
||||
|
||||
protected VolumeJoinDaoImpl() {
|
||||
|
||||
volSearch = createSearchBuilder();
|
||||
volSearch.and("idIN", volSearch.entity().getId(), SearchCriteria.Op.IN);
|
||||
volSearch.done();
|
||||
|
||||
volIdSearch = createSearchBuilder();
|
||||
volIdSearch.and("id", volIdSearch.entity().getId(), SearchCriteria.Op.EQ);
|
||||
volIdSearch.done();
|
||||
|
||||
this._count = "select count(distinct id) from volume_view WHERE ";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public VolumeResponse newVolumeResponse(VolumeJoinVO volume) {
|
||||
Account caller = UserContext.current().getCaller();
|
||||
|
||||
VolumeResponse volResponse = new VolumeResponse();
|
||||
volResponse.setId(volume.getUuid());
|
||||
|
||||
if (volume.getName() != null) {
|
||||
volResponse.setName(volume.getName());
|
||||
} else {
|
||||
volResponse.setName("");
|
||||
}
|
||||
|
||||
volResponse.setZoneId(volume.getDataCenterUuid());
|
||||
volResponse.setZoneName(volume.getDataCenterName());
|
||||
|
||||
volResponse.setVolumeType(volume.getVolumeType().toString());
|
||||
volResponse.setDeviceId(volume.getDeviceId());
|
||||
|
||||
long instanceId = volume.getVmId();
|
||||
if (instanceId > 0 && volume.getState() != Volume.State.Destroy) {
|
||||
volResponse.setVirtualMachineId(volume.getVmUuid());
|
||||
volResponse.setVirtualMachineName(volume.getVmName());
|
||||
volResponse.setVirtualMachineState(volume.getVmState().toString());
|
||||
volResponse.setVirtualMachineDisplayName(volume.getVmDisplayName());
|
||||
}
|
||||
|
||||
// Show the virtual size of the volume
|
||||
volResponse.setSize(volume.getSize());
|
||||
|
||||
volResponse.setCreated(volume.getCreated());
|
||||
volResponse.setState(volume.getState().toString());
|
||||
if (volume.getState() == Volume.State.UploadOp) {
|
||||
// com.cloud.storage.VolumeHostVO volumeHostRef =
|
||||
// ApiDBUtils.findVolumeHostRef(volume.getId(),
|
||||
// volume.getDataCenterId());
|
||||
volResponse.setSize(volume.getVolumeHostSize());
|
||||
volResponse.setCreated(volume.getVolumeHostCreated());
|
||||
|
||||
if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)
|
||||
volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volume.getFormat()).toString());
|
||||
if (volume.getDownloadState() != Status.DOWNLOADED) {
|
||||
String volumeStatus = "Processing";
|
||||
if (volume.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
|
||||
if (volume.getDownloadPercent() == 100) {
|
||||
volumeStatus = "Checking Volume";
|
||||
} else {
|
||||
volumeStatus = volume.getDownloadPercent() + "% Uploaded";
|
||||
}
|
||||
volResponse.setState("Uploading");
|
||||
} else {
|
||||
volumeStatus = volume.getErrorString();
|
||||
if (volume.getDownloadState() == VMTemplateHostVO.Status.NOT_DOWNLOADED) {
|
||||
volResponse.setState("UploadNotStarted");
|
||||
} else {
|
||||
volResponse.setState("UploadError");
|
||||
}
|
||||
}
|
||||
volResponse.setStatus(volumeStatus);
|
||||
} else if (volume.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
|
||||
volResponse.setStatus("Upload Complete");
|
||||
volResponse.setState("Uploaded");
|
||||
} else {
|
||||
volResponse.setStatus("Successfully Installed");
|
||||
}
|
||||
}
|
||||
|
||||
// populate owner.
|
||||
ApiResponseHelper.populateOwner(volResponse, volume);
|
||||
|
||||
// DiskOfferingVO diskOffering =
|
||||
// ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
|
||||
if (volume.getDiskOfferingId() > 0) {
|
||||
if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
|
||||
volResponse.setServiceOfferingId(volume.getDiskOfferingUuid());
|
||||
} else {
|
||||
volResponse.setDiskOfferingId(volume.getDiskOfferingUuid());
|
||||
}
|
||||
|
||||
if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
|
||||
volResponse.setServiceOfferingName(volume.getDiskOfferingName());
|
||||
volResponse.setServiceOfferingDisplayText(volume.getDiskOfferingDisplayText());
|
||||
} else {
|
||||
volResponse.setDiskOfferingName(volume.getDiskOfferingName());
|
||||
volResponse.setDiskOfferingDisplayText(volume.getDiskOfferingDisplayText());
|
||||
}
|
||||
volResponse.setStorageType(volume.isUseLocalStorage() ? ServiceOffering.StorageType.local.toString() : ServiceOffering.StorageType.shared
|
||||
.toString());
|
||||
}
|
||||
Long poolId = volume.getPoolId();
|
||||
String poolName = (poolId == null) ? "none" : volume.getPoolName();
|
||||
volResponse.setStoragePoolName(poolName);
|
||||
|
||||
// return hypervisor for ROOT and Resource domain only
|
||||
if ((caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)
|
||||
&& volume.getState() != Volume.State.UploadOp && volume.getHypervisorType() != null) {
|
||||
volResponse.setHypervisor(volume.getHypervisorType().toString());
|
||||
}
|
||||
|
||||
volResponse.setAttached(volume.getAttached());
|
||||
volResponse.setDestroyed(volume.getState() == Volume.State.Destroy);
|
||||
boolean isExtractable = true;
|
||||
if (volume.getVolumeType() != Volume.Type.DATADISK) { // Datadisk dont
|
||||
// have any
|
||||
// template
|
||||
// dependence.
|
||||
if (volume.getTemplateId() > 0) { // For ISO based volumes template
|
||||
// = null and we allow extraction
|
||||
// of all ISO based volumes
|
||||
isExtractable = volume.isExtractable() && volume.getTemplateType() != Storage.TemplateType.SYSTEM;
|
||||
}
|
||||
}
|
||||
|
||||
// update tag information
|
||||
long tag_id = volume.getTagId();
|
||||
if (tag_id > 0) {
|
||||
ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
|
||||
if (vtag != null) {
|
||||
volResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
|
||||
}
|
||||
}
|
||||
|
||||
volResponse.setExtractable(isExtractable);
|
||||
volResponse.setObjectName("volume");
|
||||
return volResponse;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public VolumeResponse setVolumeResponse(VolumeResponse volData, VolumeJoinVO vol) {
|
||||
long tag_id = vol.getTagId();
|
||||
if (tag_id > 0) {
|
||||
ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
|
||||
if ( vtag != null ){
|
||||
volData.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
|
||||
}
|
||||
}
|
||||
return volData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<VolumeJoinVO> newVolumeView(Volume vol) {
|
||||
SearchCriteria<VolumeJoinVO> sc = volIdSearch.create();
|
||||
sc.setParameters("id", vol.getId());
|
||||
return searchIncludingRemoved(sc, null, null, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<VolumeJoinVO> searchByIds(Long... ids) {
|
||||
SearchCriteria<VolumeJoinVO> sc = volSearch.create();
|
||||
sc.setParameters("idIN", ids);
|
||||
return searchIncludingRemoved(sc, null, null, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
1032
server/src/com/cloud/api/query/vo/VolumeJoinVO.java
Normal file
1032
server/src/com/cloud/api/query/vo/VolumeJoinVO.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,7 @@ import com.cloud.api.query.dao.ResourceTagJoinDaoImpl;
|
||||
import com.cloud.api.query.dao.SecurityGroupJoinDaoImpl;
|
||||
import com.cloud.api.query.dao.UserVmJoinDaoImpl;
|
||||
import com.cloud.api.query.dao.HostJoinDaoImpl;
|
||||
import com.cloud.api.query.dao.VolumeJoinDaoImpl;
|
||||
import com.cloud.async.AsyncJobExecutorContextImpl;
|
||||
import com.cloud.async.AsyncJobManagerImpl;
|
||||
import com.cloud.async.SyncQueueManagerImpl;
|
||||
@ -222,6 +223,7 @@ import com.cloud.vm.dao.VMInstanceDaoImpl;
|
||||
import com.cloud.event.dao.EventJoinDaoImpl;
|
||||
|
||||
|
||||
|
||||
public class DefaultComponentLibrary extends ComponentLibraryBase implements ComponentLibrary {
|
||||
protected void populateDaos() {
|
||||
addDao("StackMaidDao", StackMaidDaoImpl.class);
|
||||
@ -241,6 +243,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
||||
addDao("ProjectAccountJoinDao", ProjectAccountJoinDaoImpl.class);
|
||||
addDao("ProjectInvitationJoinDao", ProjectInvitationJoinDaoImpl.class);
|
||||
addDao("HostJoinDao", HostJoinDaoImpl.class);
|
||||
addDao("VolumeJoinDao", VolumeJoinDaoImpl.class);
|
||||
ComponentInfo<? extends GenericDao<?, ? extends Serializable>> info = addDao("ServiceOfferingDao", ServiceOfferingDaoImpl.class);
|
||||
info.addParameter("cache.size", "50");
|
||||
info.addParameter("cache.time.to.live", "600");
|
||||
|
||||
@ -3859,124 +3859,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
||||
return secHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<? extends Volume>, Integer> searchForVolumes(ListVolumesCmd cmd) {
|
||||
Account caller = UserContext.current().getCaller();
|
||||
List<Long> permittedAccounts = new ArrayList<Long>();
|
||||
|
||||
Long id = cmd.getId();
|
||||
Long vmInstanceId = cmd.getVirtualMachineId();
|
||||
String name = cmd.getVolumeName();
|
||||
String keyword = cmd.getKeyword();
|
||||
String type = cmd.getType();
|
||||
Map<String, String> tags = cmd.getTags();
|
||||
|
||||
Long zoneId = cmd.getZoneId();
|
||||
Long podId = null;
|
||||
// Object host = null; TODO
|
||||
if (_accountMgr.isAdmin(caller.getType())) {
|
||||
podId = cmd.getPodId();
|
||||
// host = cmd.getHostId(); TODO
|
||||
}
|
||||
|
||||
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();
|
||||
Boolean isRecursive = domainIdRecursiveListProject.second();
|
||||
ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
|
||||
Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
|
||||
// hack for now, this should be done better but due to needing a join I opted to
|
||||
// do this quickly and worry about making it pretty later
|
||||
SearchBuilder<VolumeVO> sb = _volumeDao.createSearchBuilder();
|
||||
_accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
|
||||
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
|
||||
sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
|
||||
// Only return volumes that are not destroyed
|
||||
sb.and("state", sb.entity().getState(), SearchCriteria.Op.NEQ);
|
||||
|
||||
SearchBuilder<DiskOfferingVO> diskOfferingSearch = _diskOfferingDao.createSearchBuilder();
|
||||
diskOfferingSearch.and("systemUse", diskOfferingSearch.entity().getSystemUse(), SearchCriteria.Op.NEQ);
|
||||
sb.join("diskOfferingSearch", diskOfferingSearch, sb.entity().getDiskOfferingId(), diskOfferingSearch.entity().getId(), JoinBuilder.JoinType.LEFTOUTER);
|
||||
|
||||
// display UserVM volumes only
|
||||
SearchBuilder<VMInstanceVO> vmSearch = _vmInstanceDao.createSearchBuilder();
|
||||
vmSearch.and("type", vmSearch.entity().getType(), SearchCriteria.Op.NIN);
|
||||
vmSearch.or("nulltype", vmSearch.entity().getType(), SearchCriteria.Op.NULL);
|
||||
sb.join("vmSearch", vmSearch, sb.entity().getInstanceId(), vmSearch.entity().getId(), JoinBuilder.JoinType.LEFTOUTER);
|
||||
|
||||
if (tags != null && !tags.isEmpty()) {
|
||||
SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
|
||||
for (int count=0; count < tags.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);
|
||||
}
|
||||
|
||||
// now set the SC criteria...
|
||||
SearchCriteria<VolumeVO> sc = sb.create();
|
||||
_accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
|
||||
|
||||
if (keyword != null) {
|
||||
SearchCriteria<VolumeVO> ssc = _volumeDao.createSearchCriteria();
|
||||
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
|
||||
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
sc.setParameters("name", "%" + name + "%");
|
||||
}
|
||||
|
||||
sc.setJoinParameters("diskOfferingSearch", "systemUse", 1);
|
||||
|
||||
if (tags != null && !tags.isEmpty()) {
|
||||
int count = 0;
|
||||
sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Volume.toString());
|
||||
for (String key : tags.keySet()) {
|
||||
sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
|
||||
sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
sc.setParameters("id", id);
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
sc.setParameters("volumeType", "%" + type + "%");
|
||||
}
|
||||
if (vmInstanceId != null) {
|
||||
sc.setParameters("instanceId", vmInstanceId);
|
||||
}
|
||||
if (zoneId != null) {
|
||||
sc.setParameters("dataCenterId", zoneId);
|
||||
}
|
||||
if (podId != null) {
|
||||
sc.setParameters("podId", podId);
|
||||
}
|
||||
|
||||
// Don't return DomR and ConsoleProxy volumes
|
||||
sc.setJoinParameters("vmSearch", "type", VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.DomainRouter);
|
||||
|
||||
// Only return volumes that are not destroyed
|
||||
sc.setParameters("state", Volume.State.Destroy);
|
||||
|
||||
Pair<List<VolumeVO>, Integer> volumes = _volumeDao.searchAndCount(sc, searchFilter);
|
||||
|
||||
return new Pair<List<? extends Volume>, Integer>(volumes.first(), volumes.second());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSupportedImageFormatForCluster(Long clusterId) {
|
||||
|
||||
@ -106,4 +106,18 @@ public class ListPerfTest extends APITest {
|
||||
System.out.println("Time taken to list Hosts: " + (after - before) + " ms");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListVolumes(){
|
||||
// issue list Hosts calls
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
params.put("response", "json");
|
||||
params.put("listAll", "true");
|
||||
params.put("sessionkey", sessionKey);
|
||||
long before = System.currentTimeMillis();
|
||||
String result = this.sendRequest("listVolumes", params);
|
||||
long after = System.currentTimeMillis();
|
||||
System.out.println("Time taken to list Volumes: " + (after - before) + " ms");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -3062,4 +3062,86 @@ left join op_host_capacity mem_caps on host.id = mem_caps.host_id and mem_caps.c
|
||||
left join op_host_capacity cpu_caps on host.id = cpu_caps.host_id and cpu_caps.capacity_type = 1
|
||||
left join async_job on async_job.instance_id = host.id and async_job.instance_type = "Host" and async_job.job_status = 0;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`volume_view`;
|
||||
CREATE VIEW volume_view AS
|
||||
select
|
||||
volumes.id,
|
||||
volumes.uuid,
|
||||
volumes.name,
|
||||
volumes.device_id,
|
||||
volumes.volume_type,
|
||||
volumes.size,
|
||||
volumes.created,
|
||||
volumes.state,
|
||||
volumes.attached,
|
||||
volumes.removed,
|
||||
volumes.pod_id,
|
||||
account.id account_id,
|
||||
account.uuid account_uuid,
|
||||
account.account_name account_name,
|
||||
account.type account_type,
|
||||
domain.id domain_id,
|
||||
domain.uuid domain_uuid,
|
||||
domain.name domain_name,
|
||||
domain.path domain_path,
|
||||
projects.id project_id,
|
||||
projects.uuid project_uuid,
|
||||
projects.name project_name,
|
||||
data_center.id data_center_id,
|
||||
data_center.uuid data_center_uuid,
|
||||
data_center.name data_center_name,
|
||||
vm_instance.id vm_id,
|
||||
vm_instance.uuid vm_uuid,
|
||||
vm_instance.name vm_name,
|
||||
vm_instance.state vm_state,
|
||||
vm_instance.vm_type,
|
||||
user_vm.display_name vm_display_name,
|
||||
volume_host_ref.size volume_host_size,
|
||||
volume_host_ref.created volume_host_created,
|
||||
volume_host_ref.format,
|
||||
volume_host_ref.download_pct,
|
||||
volume_host_ref.download_state,
|
||||
volume_host_ref.error_str,
|
||||
disk_offering.id disk_offering_id,
|
||||
disk_offering.uuid disk_offering_uuid,
|
||||
disk_offering.name disk_offering_name,
|
||||
disk_offering.display_text disk_offering_display_text,
|
||||
disk_offering.use_local_storage,
|
||||
disk_offering.system_use,
|
||||
storage_pool.id pool_id,
|
||||
storage_pool.uuid pool_uuid,
|
||||
storage_pool.name pool_name,
|
||||
cluster.hypervisor_type,
|
||||
vm_template.id template_id,
|
||||
vm_template.uuid template_uuid,
|
||||
vm_template.extractable,
|
||||
vm_template.type template_type,
|
||||
resource_tags.id tag_id,
|
||||
resource_tags.uuid tag_uuid,
|
||||
resource_tags.key tag_key,
|
||||
resource_tags.value tag_value,
|
||||
resource_tags.domain_id tag_domain_id,
|
||||
resource_tags.account_id tag_account_id,
|
||||
resource_tags.resource_id tag_resource_id,
|
||||
resource_tags.resource_uuid tag_resource_uuid,
|
||||
resource_tags.resource_type tag_resource_type,
|
||||
resource_tags.customer tag_customer,
|
||||
async_job.id job_id,
|
||||
async_job.uuid job_uuid,
|
||||
async_job.job_status job_status,
|
||||
async_job.account_id job_account_id
|
||||
from volumes
|
||||
inner join account on volumes.account_id=account.id
|
||||
inner join domain on volumes.domain_id=domain.id
|
||||
left join projects on projects.project_account_id = account.id
|
||||
left join data_center on volumes.data_center_id = data_center.id
|
||||
left join vm_instance on volumes.instance_id = vm_instance.id
|
||||
left join user_vm on user_vm.id = vm_instance.id
|
||||
left join volume_host_ref on volumes.id = volume_host_ref.volume_id and volumes.data_center_id = volume_host_ref.zone_id
|
||||
left join disk_offering on volumes.disk_offering_id = disk_offering.id
|
||||
left join storage_pool on volumes.pool_id = storage_pool.id
|
||||
left join cluster on storage_pool.cluster_id = cluster.id
|
||||
left join vm_template on volumes.template_id = vm_template.id
|
||||
left join resource_tags on resource_tags.resource_id = volumes.id and resource_tags.resource_type = "Volume"
|
||||
left join async_job on async_job.instance_id = volumes.id and async_job.instance_type = "Volume" and async_job.job_status = 0;
|
||||
|
||||
|
||||
@ -637,3 +637,88 @@ left join host_tags on host_tags.host_id = host.id
|
||||
left join op_host_capacity mem_caps on host.id = mem_caps.host_id and mem_caps.capacity_type = 0
|
||||
left join op_host_capacity cpu_caps on host.id = cpu_caps.host_id and cpu_caps.capacity_type = 1
|
||||
left join async_job on async_job.instance_id = host.id and async_job.instance_type = "Host" and async_job.job_status = 0;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`volume_view`;
|
||||
CREATE VIEW volume_view AS
|
||||
select
|
||||
volumes.id,
|
||||
volumes.uuid,
|
||||
volumes.name,
|
||||
volumes.device_id,
|
||||
volumes.volume_type,
|
||||
volumes.size,
|
||||
volumes.created,
|
||||
volumes.state,
|
||||
volumes.attached,
|
||||
volumes.removed,
|
||||
volumes.pod_id,
|
||||
account.id account_id,
|
||||
account.uuid account_uuid,
|
||||
account.account_name account_name,
|
||||
account.type account_type,
|
||||
domain.id domain_id,
|
||||
domain.uuid domain_uuid,
|
||||
domain.name domain_name,
|
||||
domain.path domain_path,
|
||||
projects.id project_id,
|
||||
projects.uuid project_uuid,
|
||||
projects.name project_name,
|
||||
data_center.id data_center_id,
|
||||
data_center.uuid data_center_uuid,
|
||||
data_center.name data_center_name,
|
||||
vm_instance.id vm_id,
|
||||
vm_instance.uuid vm_uuid,
|
||||
vm_instance.name vm_name,
|
||||
vm_instance.state vm_state,
|
||||
vm_instance.vm_type,
|
||||
user_vm.display_name vm_display_name,
|
||||
volume_host_ref.size volume_host_size,
|
||||
volume_host_ref.created volume_host_created,
|
||||
volume_host_ref.format,
|
||||
volume_host_ref.download_pct,
|
||||
volume_host_ref.download_state,
|
||||
volume_host_ref.error_str,
|
||||
disk_offering.id disk_offering_id,
|
||||
disk_offering.uuid disk_offering_uuid,
|
||||
disk_offering.name disk_offering_name,
|
||||
disk_offering.display_text disk_offering_display_text,
|
||||
disk_offering.use_local_storage,
|
||||
disk_offering.system_use,
|
||||
storage_pool.id pool_id,
|
||||
storage_pool.uuid pool_uuid,
|
||||
storage_pool.name pool_name,
|
||||
cluster.hypervisor_type,
|
||||
vm_template.id template_id,
|
||||
vm_template.uuid template_uuid,
|
||||
vm_template.extractable,
|
||||
vm_template.type template_type,
|
||||
resource_tags.id tag_id,
|
||||
resource_tags.uuid tag_uuid,
|
||||
resource_tags.key tag_key,
|
||||
resource_tags.value tag_value,
|
||||
resource_tags.domain_id tag_domain_id,
|
||||
resource_tags.account_id tag_account_id,
|
||||
resource_tags.resource_id tag_resource_id,
|
||||
resource_tags.resource_uuid tag_resource_uuid,
|
||||
resource_tags.resource_type tag_resource_type,
|
||||
resource_tags.customer tag_customer,
|
||||
async_job.id job_id,
|
||||
async_job.uuid job_uuid,
|
||||
async_job.job_status job_status,
|
||||
async_job.account_id job_account_id
|
||||
from volumes
|
||||
inner join account on volumes.account_id=account.id
|
||||
inner join domain on volumes.domain_id=domain.id
|
||||
left join projects on projects.project_account_id = account.id
|
||||
left join data_center on volumes.data_center_id = data_center.id
|
||||
left join vm_instance on volumes.instance_id = vm_instance.id
|
||||
left join user_vm on user_vm.id = vm_instance.id
|
||||
left join volume_host_ref on volumes.id = volume_host_ref.volume_id and volumes.data_center_id = volume_host_ref.zone_id
|
||||
left join disk_offering on volumes.disk_offering_id = disk_offering.id
|
||||
left join storage_pool on volumes.pool_id = storage_pool.id
|
||||
left join cluster on storage_pool.cluster_id = cluster.id
|
||||
left join vm_template on volumes.template_id = vm_template.id
|
||||
left join resource_tags on resource_tags.resource_id = volumes.id and resource_tags.resource_type = "Volume"
|
||||
left join async_job on async_job.instance_id = volumes.id and async_job.instance_type = "Volume" and async_job.job_status = 0;
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user