Skip to content

Commit 5d262d7

Browse files
committed
CLOUDSTACK-5648:CopyTemplate and CopyISO across zones fails after NFS
migration to S3.
1 parent 30d55cf commit 5d262d7

5 files changed

Lines changed: 51 additions & 22 deletions

File tree

api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ public class CopyTemplateCmd extends BaseAsyncCmd {
5959
@Parameter(name = ApiConstants.SOURCE_ZONE_ID,
6060
type = CommandType.UUID,
6161
entityType = ZoneResponse.class,
62-
required = true,
63-
description = "ID of the zone the template is currently hosted on.")
62+
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.")
6463
private Long sourceZoneId;
6564

6665
/////////////////////////////////////////////////////
@@ -137,7 +136,7 @@ public void execute() throws ResourceAllocationException {
137136
}
138137

139138
response.setResponseName(getCommandName());
140-
this.setResponseObject(response);
139+
setResponseObject(response);
141140
} else {
142141
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to copy template");
143142
}

engine/components-api/src/com/cloud/template/TemplateManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ public interface TemplateManager {
101101

102102
DataStore getImageStore(long zoneId, long tmpltId);
103103

104+
DataStore getImageStore(long tmpltId);
105+
104106
Long getTemplateSize(long templateId, long zoneId);
105107

106108
DataStore getImageStore(String storeUuid, Long zoneId);

engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ public interface TemplateDataStoreDao extends GenericDao<TemplateDataStoreVO, Lo
5959

6060
TemplateDataStoreVO findByTemplate(long templateId, DataStoreRole role);
6161

62+
TemplateDataStoreVO findReadyByTemplate(long templateId, DataStoreRole role);
63+
6264
TemplateDataStoreVO findByTemplateZone(long templateId, Long zoneId, DataStoreRole role);
6365

6466
List<TemplateDataStoreVO> listByTemplate(long templateId);

engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,20 @@ public TemplateDataStoreVO findByTemplate(long templateId, DataStoreRole role) {
350350
}
351351

352352
@Override
353-
public TemplateDataStoreVO findReadyOnCache(long templateId) {
353+
public TemplateDataStoreVO findReadyByTemplate(long templateId, DataStoreRole role) {
354354
SearchCriteria<TemplateDataStoreVO> sc = templateRoleSearch.create();
355355
sc.setParameters("template_id", templateId);
356-
sc.setParameters("store_role", DataStoreRole.ImageCache);
356+
sc.setParameters("store_role", role);
357357
sc.setParameters("destroyed", false);
358358
sc.setParameters("state", ObjectInDataStoreStateMachine.State.Ready);
359359
return findOneIncludingRemovedBy(sc);
360360
}
361361

362+
@Override
363+
public TemplateDataStoreVO findReadyOnCache(long templateId) {
364+
return findReadyByTemplate(templateId, DataStoreRole.ImageCache);
365+
}
366+
362367
@Override
363368
public List<TemplateDataStoreVO> listOnCache(long templateId) {
364369
SearchCriteria<TemplateDataStoreVO> sc = templateRoleSearch.create();

server/src/com/cloud/template/TemplateManagerImpl.java

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -689,38 +689,47 @@ public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUn
689689
Account caller = CallContext.current().getCallingAccount();
690690

691691
// Verify parameters
692-
if (sourceZoneId.equals(destZoneId)) {
693-
throw new InvalidParameterValueException("Please specify different source and destination zones.");
694-
}
695-
696-
DataCenterVO sourceZone = _dcDao.findById(sourceZoneId);
697-
if (sourceZone == null) {
698-
throw new InvalidParameterValueException("Please specify a valid source zone.");
699-
}
700-
701-
DataCenterVO dstZone = _dcDao.findById(destZoneId);
702-
if (dstZone == null) {
703-
throw new InvalidParameterValueException("Please specify a valid destination zone.");
704-
}
705-
706692
VMTemplateVO template = _tmpltDao.findById(templateId);
707693
if (template == null || template.getRemoved() != null) {
708694
throw new InvalidParameterValueException("Unable to find template with id");
709695
}
710696

711-
DataStore srcSecStore = getImageStore(sourceZoneId, templateId);
697+
DataStore srcSecStore = null;
698+
if (sourceZoneId != null) {
699+
// template is on zone-wide secondary storage
700+
srcSecStore = getImageStore(sourceZoneId, templateId);
701+
} else {
702+
// template is on region store
703+
srcSecStore = getImageStore(templateId);
704+
}
705+
712706
if (srcSecStore == null) {
713-
throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId);
707+
throw new InvalidParameterValueException("There is no template " + templateId + " ready on image store.");
714708
}
715709

716710
if (template.isCrossZones()) {
717-
//TODO: we may need UI still enable CopyTemplate in case of cross zone template to trigger sync to region store.
718711
// 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.
719712
_tmpltSvr.syncTemplateToRegionStore(templateId, srcSecStore);
720713
s_logger.debug("Template " + templateId + " is cross-zone, don't need to copy");
721714
return template;
722715
}
723716

717+
if (sourceZoneId != null) {
718+
if (sourceZoneId.equals(destZoneId)) {
719+
throw new InvalidParameterValueException("Please specify different source and destination zones.");
720+
}
721+
722+
DataCenterVO sourceZone = _dcDao.findById(sourceZoneId);
723+
if (sourceZone == null) {
724+
throw new InvalidParameterValueException("Please specify a valid source zone.");
725+
}
726+
}
727+
728+
DataCenterVO dstZone = _dcDao.findById(destZoneId);
729+
if (dstZone == null) {
730+
throw new InvalidParameterValueException("Please specify a valid destination zone.");
731+
}
732+
724733
DataStore dstSecStore = getImageStore(destZoneId, templateId);
725734
if (dstSecStore != null) {
726735
s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecStore.getName() + " in zone " + destZoneId + " , don't need to copy");
@@ -1692,6 +1701,18 @@ public DataStore getImageStore(long zoneId, long tmpltId) {
16921701
return null;
16931702
}
16941703

1704+
// get the region wide image store where a template is READY on,
1705+
// just pick one is enough.
1706+
@Override
1707+
public DataStore getImageStore(long tmpltId) {
1708+
TemplateDataStoreVO tmpltStore = _tmplStoreDao.findReadyByTemplate(tmpltId, DataStoreRole.Image);
1709+
if (tmpltStore != null) {
1710+
return _dataStoreMgr.getDataStore(tmpltStore.getDataStoreId(), DataStoreRole.Image);
1711+
}
1712+
1713+
return null;
1714+
}
1715+
16951716
@Override
16961717
public Long getTemplateSize(long templateId, long zoneId) {
16971718
TemplateDataStoreVO templateStoreRef = _tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, zoneId, VMTemplateStorageResourceAssoc.Status.DOWNLOADED);

0 commit comments

Comments
 (0)