CLOUDSTACK-5648:CopyTemplate and CopyISO across zones fails after NFS

migration to S3.
This commit is contained in:
Min Chen 2013-12-26 11:12:00 -08:00
parent 7e54ca8831
commit 35ba14d88d
5 changed files with 57 additions and 26 deletions

View File

@ -18,6 +18,8 @@ package org.apache.cloudstack.api.command.user.template;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
@ -26,12 +28,9 @@ import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
@ -56,7 +55,7 @@ public class CopyTemplateCmd extends BaseAsyncCmd {
private Long id;
@Parameter(name=ApiConstants.SOURCE_ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
required=true, description="ID of the zone the template is currently hosted on.")
description = "ID of the zone the template is currently hosted on. If not specified and template is cross-zone, then we will sync this template to region wide image store")
private Long sourceZoneId;
@ -110,10 +109,12 @@ public class CopyTemplateCmd extends BaseAsyncCmd {
return "copying template: " + getId() + " from zone: " + getSourceZoneId() + " to zone: " + getDestinationZoneId();
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.Template;
}
@Override
public Long getInstanceId() {
return getId();
}
@ -132,7 +133,7 @@ public class CopyTemplateCmd extends BaseAsyncCmd {
}
response.setResponseName(getCommandName());
this.setResponseObject(response);
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to copy template");
}

View File

@ -103,6 +103,8 @@ public interface TemplateManager {
DataStore getImageStore(long zoneId, long tmpltId);
DataStore getImageStore(long tmpltId);
Long getTemplateSize(long templateId, long zoneId);
DataStore getImageStore(String storeUuid, Long zoneId);

View File

@ -62,6 +62,8 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
TemplateDataStoreVO findByTemplate(long templateId, DataStoreRole role);
TemplateDataStoreVO findReadyByTemplate(long templateId, DataStoreRole role);
TemplateDataStoreVO findByTemplateZone(long templateId, Long zoneId, DataStoreRole role);
List<TemplateDataStoreVO> listByTemplate(long templateId);

View File

@ -343,15 +343,20 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
}
@Override
public TemplateDataStoreVO findReadyOnCache(long templateId) {
public TemplateDataStoreVO findReadyByTemplate(long templateId, DataStoreRole role) {
SearchCriteria<TemplateDataStoreVO> sc = templateRoleSearch.create();
sc.setParameters("template_id", templateId);
sc.setParameters("store_role", DataStoreRole.ImageCache);
sc.setParameters("store_role", role);
sc.setParameters("destroyed", false);
sc.setParameters("state", ObjectInDataStoreStateMachine.State.Ready);
return findOneIncludingRemovedBy(sc);
}
@Override
public TemplateDataStoreVO findReadyOnCache(long templateId) {
return findReadyByTemplate(templateId, DataStoreRole.ImageCache);
}
@Override
public List<TemplateDataStoreVO> listOnCache(long templateId) {
SearchCriteria<TemplateDataStoreVO> sc = templateRoleSearch.create();

View File

@ -694,38 +694,47 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
Account caller = CallContext.current().getCallingAccount();
// Verify parameters
if (sourceZoneId.equals(destZoneId)) {
throw new InvalidParameterValueException("Please specify different source and destination zones.");
}
DataCenterVO sourceZone = _dcDao.findById(sourceZoneId);
if (sourceZone == null) {
throw new InvalidParameterValueException("Please specify a valid source zone.");
}
DataCenterVO dstZone = _dcDao.findById(destZoneId);
if (dstZone == null) {
throw new InvalidParameterValueException("Please specify a valid destination zone.");
}
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null || template.getRemoved() != null) {
throw new InvalidParameterValueException("Unable to find template with id");
}
DataStore srcSecStore = getImageStore(sourceZoneId, templateId);
if (srcSecStore == null) {
throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId);
DataStore srcSecStore = null;
if (sourceZoneId != null) {
// template is on zone-wide secondary storage
srcSecStore = getImageStore(sourceZoneId, templateId);
} else {
// template is on region store
srcSecStore = getImageStore(templateId);
}
if (template.isCrossZones()){
//TODO: we may need UI still enable CopyTemplate in case of cross zone template to trigger sync to region store.
if (srcSecStore == null) {
throw new InvalidParameterValueException("There is no template " + templateId + " ready on image store.");
}
if (template.isCrossZones()) {
// sync template from cache store to region store if it is not there, for cases where we are going to migrate existing NFS to S3.
_tmpltSvr.syncTemplateToRegionStore(templateId, srcSecStore);
s_logger.debug("Template " + templateId + " is cross-zone, don't need to copy");
return template;
}
if (sourceZoneId != null) {
if (sourceZoneId.equals(destZoneId)) {
throw new InvalidParameterValueException("Please specify different source and destination zones.");
}
DataCenterVO sourceZone = _dcDao.findById(sourceZoneId);
if (sourceZone == null) {
throw new InvalidParameterValueException("Please specify a valid source zone.");
}
}
DataCenterVO dstZone = _dcDao.findById(destZoneId);
if (dstZone == null) {
throw new InvalidParameterValueException("Please specify a valid destination zone.");
}
DataStore dstSecStore = getImageStore(destZoneId, templateId);
if (dstSecStore != null) {
s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecStore.getName() + " in zone " + destZoneId
@ -1706,6 +1715,18 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
return null;
}
// get the region wide image store where a template is READY on,
// just pick one is enough.
@Override
public DataStore getImageStore(long tmpltId) {
TemplateDataStoreVO tmpltStore = _tmplStoreDao.findReadyByTemplate(tmpltId, DataStoreRole.Image);
if (tmpltStore != null) {
return _dataStoreMgr.getDataStore(tmpltStore.getDataStoreId(), DataStoreRole.Image);
}
return null;
}
@Override
public Long getTemplateSize(long templateId, long zoneId) {
TemplateDataStoreVO templateStoreRef = _tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, zoneId,