Use data motion service to implement copy template.

This commit is contained in:
Min Chen 2013-04-19 23:01:59 -07:00
parent 6f70fe28e8
commit 86913ab4d3
5 changed files with 224 additions and 116 deletions

View File

@ -18,6 +18,7 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
@ -25,10 +26,25 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
public interface TemplateService {
AsyncCallFuture<CommandResult> createTemplateAsync(TemplateInfo template, DataStore store);
AsyncCallFuture<CommandResult> createTemplateFromSnapshotAsync(SnapshotInfo snapshot, TemplateInfo template, DataStore store);
AsyncCallFuture<CommandResult> createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, DataStore store);
AsyncCallFuture<CommandResult> deleteTemplateAsync(TemplateInfo template);
public class TemplateApiResult extends CommandResult {
private final TemplateInfo template;
public TemplateApiResult(TemplateInfo template) {
this.template = template;
}
public TemplateInfo getTemplate() {
return this.template;
}
}
AsyncCallFuture<TemplateApiResult> createTemplateAsync(TemplateInfo template, DataStore store);
AsyncCallFuture<TemplateApiResult> createTemplateFromSnapshotAsync(SnapshotInfo snapshot, TemplateInfo template, DataStore store);
AsyncCallFuture<TemplateApiResult> createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, DataStore store);
AsyncCallFuture<TemplateApiResult> deleteTemplateAsync(TemplateInfo template);
AsyncCallFuture<TemplateApiResult> copyTemplate(TemplateInfo srcTemplate,
DataStore destStore);
void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId);
void handleTemplateSync(DataStore store);

View File

@ -28,15 +28,20 @@ import java.util.Set;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
import com.cloud.storage.template.TemplateProp;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
@ -68,8 +73,11 @@ import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
@ -93,6 +101,8 @@ public class TemplateServiceImpl implements TemplateService {
@Inject
DataStoreManager _storeMgr;
@Inject
DataMotionService _motionSrv;
@Inject
ResourceLimitService _resourceLimitMgr;
@Inject
AccountManager _accountMgr;
@ -120,33 +130,18 @@ public class TemplateServiceImpl implements TemplateService {
UserVmDao _userVmDao;
@Inject
VolumeDao _volumeDao;
@Inject
TemplateDataFactory _templateFactory;
class CreateTemplateContext<T> extends AsyncRpcConext<T> {
final TemplateInfo srcTemplate;
final DataStore store;
final AsyncCallFuture<CommandResult> future;
final DataObject templateOnStore;
public CreateTemplateContext(AsyncCompletionCallback<T> callback, TemplateInfo srcTemplate,
AsyncCallFuture<CommandResult> future,
DataStore store,
DataObject templateOnStore
) {
super(callback);
this.srcTemplate = srcTemplate;
this.future = future;
this.store = store;
this.templateOnStore = templateOnStore;
}
}
class DeleteTemplateContext<T> extends AsyncRpcConext<T> {
class TemplateOpContext<T> extends AsyncRpcConext<T> {
final TemplateObject template;
final AsyncCallFuture<CommandResult> future;
final AsyncCallFuture<TemplateApiResult> future;
public DeleteTemplateContext(AsyncCompletionCallback<T> callback, TemplateObject template,
AsyncCallFuture<CommandResult> future) {
public TemplateOpContext(AsyncCompletionCallback<T> callback, TemplateObject template,
AsyncCallFuture<TemplateApiResult> future) {
super(callback);
this.template = template;
this.future = future;
@ -156,7 +151,7 @@ public class TemplateServiceImpl implements TemplateService {
return template;
}
public AsyncCallFuture<CommandResult> getFuture() {
public AsyncCallFuture<TemplateApiResult> getFuture() {
return future;
}
@ -164,21 +159,17 @@ public class TemplateServiceImpl implements TemplateService {
}
@Override
public AsyncCallFuture<CommandResult> createTemplateAsync(
public AsyncCallFuture<TemplateApiResult> createTemplateAsync(
TemplateInfo template, DataStore store) {
TemplateObject to = (TemplateObject) template;
AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>();
// persist template_store_ref entry
DataObject templateOnStore = store.create(template);
// update template_store_ref state
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested);
CreateTemplateContext<CommandResult> context = new CreateTemplateContext<CommandResult>(null,
template,
future,
store,
templateOnStore
);
TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null,
(TemplateObject)templateOnStore, future);
AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context);
store.getDriver().createAsync(templateOnStore, caller);
@ -470,15 +461,14 @@ public class TemplateServiceImpl implements TemplateService {
protected Void createTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> callback,
CreateTemplateContext<CreateCmdResult> context) {
TemplateObject template = (TemplateObject)context.srcTemplate;
AsyncCallFuture<CommandResult> future = context.future;
CommandResult result = new CommandResult();
DataObject templateOnStore = context.templateOnStore;
TemplateOpContext<CreateCmdResult> context) {
TemplateObject template = (TemplateObject)context.getTemplate();
AsyncCallFuture<TemplateApiResult> future = context.getFuture();
TemplateApiResult result = new TemplateApiResult(template);
CreateCmdResult callbackResult = callback.getResult();
if (callbackResult.isFailed()) {
try {
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
template.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
template.stateTransit(TemplateEvent.OperationFailed);
} catch (NoTransitionException e) {
s_logger.debug("Failed to update template state", e);
@ -489,7 +479,7 @@ public class TemplateServiceImpl implements TemplateService {
}
try {
templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
template.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
template.stateTransit(TemplateEvent.OperationSucceeded);
} catch (NoTransitionException e) {
s_logger.debug("Failed to transit state", e);
@ -503,22 +493,22 @@ public class TemplateServiceImpl implements TemplateService {
}
@Override
public AsyncCallFuture<CommandResult> deleteTemplateAsync(
public AsyncCallFuture<TemplateApiResult> deleteTemplateAsync(
TemplateInfo template) {
TemplateObject to = (TemplateObject) template;
// update template_store_ref status
to.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested);
AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>();
DeleteTemplateContext<CommandResult> context = new DeleteTemplateContext<CommandResult>(null, to, future);
TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null, to, future);
AsyncCallbackDispatcher<TemplateServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().deleteTemplateCallback(null, null)).setContext(context);
to.getDataStore().getDriver().deleteAsync(to, caller);
return future;
}
public Void deleteTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImpl, CommandResult> callback, DeleteTemplateContext<CommandResult> context) {
CommandResult result = callback.getResult();
public Void deleteTemplateCallback(AsyncCallbackDispatcher<TemplateServiceImpl, TemplateApiResult> callback, TemplateOpContext<TemplateApiResult> context) {
TemplateApiResult result = callback.getResult();
TemplateObject vo = context.getTemplate();
// we can only update state in template_store_ref table
if (result.isSuccess()) {
@ -531,19 +521,114 @@ public class TemplateServiceImpl implements TemplateService {
}
@Override
public AsyncCallFuture<CommandResult> createTemplateFromSnapshotAsync(
public AsyncCallFuture<TemplateApiResult> createTemplateFromSnapshotAsync(
SnapshotInfo snapshot, TemplateInfo template, DataStore store) {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncCallFuture<CommandResult> createTemplateFromVolumeAsync(
public AsyncCallFuture<TemplateApiResult> createTemplateFromVolumeAsync(
VolumeInfo volume, TemplateInfo template, DataStore store) {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncCallFuture<TemplateApiResult> copyTemplate(TemplateInfo srcTemplate,
DataStore destStore) {
AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>();
TemplateApiResult res = new TemplateApiResult(srcTemplate);
try{
// create one entry in template_store_ref
TemplateDataStoreVO destTmpltStore = _vmTemplateStoreDao.findByStoreTemplate(destStore.getId(), srcTemplate.getId());
if (destTmpltStore == null) {
destTmpltStore = new TemplateDataStoreVO(destStore.getId(), srcTemplate.getId());
destTmpltStore.setCopy(true);
_vmTemplateStoreDao.persist(destTmpltStore);
}
TemplateInfo destTemplate = this._templateFactory.getTemplate(destTmpltStore.getTemplateId(), destStore);
destTemplate.processEvent(Event.CreateOnlyRequested);
srcTemplate.processEvent(Event.CopyingRequested);
CopyTemplateContext<TemplateApiResult> context = new CopyTemplateContext<TemplateApiResult>(null, future, srcTemplate,
destTemplate,
destStore);
AsyncCallbackDispatcher<TemplateServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().copyTemplateCallBack(null, null))
.setContext(context);
this._motionSrv.copyAsync(srcTemplate, destTemplate, caller);
} catch (Exception e) {
s_logger.debug("Failed to copy volume", e);
res.setResult(e.toString());
future.complete(res);
}
return future;
}
protected Void copyTemplateCallBack(AsyncCallbackDispatcher<TemplateServiceImpl, CopyCommandResult> callback,
CopyTemplateContext<TemplateApiResult> context) {
TemplateInfo srcTemplate = context.getSrcTemplate();
TemplateInfo destTemplate = context.getDestTemplate();
CopyCommandResult result = callback.getResult();
AsyncCallFuture<TemplateApiResult> future = context.getFuture();
TemplateApiResult res = new TemplateApiResult(destTemplate);
try {
if (result.isFailed()) {
res.setResult(result.getResult());
destTemplate.processEvent(Event.OperationFailed);
srcTemplate.processEvent(Event.OperationFailed);
// remove entry from template_store_ref
TemplateDataStoreVO destTmpltStore = _vmTemplateStoreDao.findByStoreTemplate(context.getDestStore().getId(), destTemplate.getId());
_vmTemplateStoreDao.remove(destTmpltStore.getId());
future.complete(res);
return null;
}
srcTemplate.processEvent(Event.OperationSuccessed);
destTemplate.processEvent(Event.OperationSuccessed);
future.complete(res);
return null;
} catch (Exception e) {
s_logger.debug("Failed to process copy template callback", e);
res.setResult(e.toString());
future.complete(res);
}
return null;
}
class CopyTemplateContext<T> extends AsyncRpcConext<T> {
final TemplateInfo srcTemplate;
final TemplateInfo destTemplate;
final DataStore destStore;
final AsyncCallFuture<TemplateApiResult> future;
/**
* @param callback
*/
public CopyTemplateContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<TemplateApiResult> future, TemplateInfo srcTemplate,
TemplateInfo destTemplate, DataStore destStore) {
super(callback);
this.srcTemplate = srcTemplate;
this.destTemplate = destTemplate;
this.destStore = destStore;
this.future = future;
}
public TemplateInfo getSrcTemplate() {
return srcTemplate;
}
public TemplateInfo getDestTemplate() {
return destTemplate;
}
public DataStore getDestStore() {
return destStore;
}
public AsyncCallFuture<TemplateApiResult> getFuture() {
return future;
}
}
}

View File

@ -41,6 +41,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
@ -93,7 +94,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
VMTemplateDao imageDataDao;
@Inject
VolumeDao2 volumeDao;
@Inject
@Inject
HostDao hostDao;
@Inject
HostPodDao podDao;
@ -119,7 +120,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
HostVO host;
String primaryName = "my primary data store";
DataStore primaryStore;
@Test(priority = -1)
public void setUp() {
ComponentContext.initComponentsLifeCycle();
@ -137,7 +138,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
return;
}
//create data center
DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24",
DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24",
null, null, NetworkType.Basic, null, null, true, true, null, null);
dc = dcDao.persist(dc);
dcId = dc.getId();
@ -172,7 +173,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
host = hostDao.persist(host);
//primaryStore = createPrimaryDataStore();
//CreateVolumeAnswer createVolumeFromImageAnswer = new CreateVolumeAnswer(UUID.randomUUID().toString());
/*try {
@ -188,7 +189,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
//Mockito.when(primaryStoreDao.findById(Mockito.anyLong())).thenReturn(primaryStore);
}
@Override
protected void injectMockito() {
if (host == null) {
@ -225,10 +226,10 @@ public class volumeServiceTest extends CloudStackTestNGBase {
image.setPrepopulate(true);
image.setCrossZones(true);
image.setExtractable(true);
//image.setImageDataStoreId(storeId);
image = imageDataDao.persist(image);
return image;
}
@ -237,7 +238,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
DataStore store = createImageStore();
VMTemplateVO image = createImageData();
TemplateInfo template = imageDataFactory.getTemplate(image.getId(), store);
AsyncCallFuture<CommandResult> future = imageService.createTemplateAsync(template, store);
AsyncCallFuture<TemplateApiResult> future = imageService.createTemplateAsync(template, store);
future.get();
template = imageDataFactory.getTemplate(image.getId(), store);
/*imageProviderMgr.configure("image Provider", new HashMap<String, Object>());
@ -259,7 +260,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
public void createTemplateTest() {
createTemplate();
}
@Test
public void testCreatePrimaryStorage() {
DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("sample primary data store provider");
@ -282,13 +283,13 @@ public class volumeServiceTest extends CloudStackTestNGBase {
params.put("roles", DataStoreRole.Primary.toString());
params.put("uuid", UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString());
params.put("providerName", String.valueOf(provider.getName()));
DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
this.primaryStore = lifeCycle.initialize(params);
ClusterScope scope = new ClusterScope(clusterId, podId, dcId);
lifeCycle.attachCluster(this.primaryStore, scope);
}
private DataStore createImageStore() {
DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider("sample image data store provider");
Map<String, Object> params = new HashMap<String, Object>();
@ -306,7 +307,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
public void testcreateImageStore() {
createImageStore();
}
public DataStore createPrimaryDataStore() {
try {
@ -324,16 +325,16 @@ public class volumeServiceTest extends CloudStackTestNGBase {
params.put("roles", DataStoreRole.Primary.toString());
params.put("uuid", UUID.nameUUIDFromBytes(this.getPrimaryStorageUrl().getBytes()).toString());
params.put("providerName", String.valueOf(provider.getName()));
DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
DataStore store = lifeCycle.initialize(params);
ClusterScope scope = new ClusterScope(clusterId, podId, dcId);
lifeCycle.attachCluster(store, scope);
/*
PrimaryDataStoreProvider provider = primaryDataStoreProviderMgr.getDataStoreProvider("sample primary data store provider");
primaryDataStoreProviderMgr.configure("primary data store mgr", new HashMap<String, Object>());
List<PrimaryDataStoreVO> ds = primaryStoreDao.findPoolByName(this.primaryName);
if (ds.size() >= 1) {
PrimaryDataStoreVO store = ds.get(0);
@ -341,8 +342,8 @@ public class volumeServiceTest extends CloudStackTestNGBase {
return provider.getDataStore(store.getId());
}
}
Map<String, String> params = new HashMap<String, String>();
params.put("url", this.getPrimaryStorageUrl());
params.put("dcId", dcId.toString());
@ -385,8 +386,8 @@ public class volumeServiceTest extends CloudStackTestNGBase {
e.printStackTrace();
}
}
//@Test(priority=3)
//@Test(priority=3)
public void createDataDisk() {
DataStore primaryStore = this.primaryStore;
VolumeVO volume = createVolume(null, primaryStore.getId());
@ -402,8 +403,8 @@ public class volumeServiceTest extends CloudStackTestNGBase {
e.printStackTrace();
}
}
//@Test(priority=3)
//@Test(priority=3)
public void createAndDeleteDataDisk() {
DataStore primaryStore = this.primaryStore;
VolumeVO volume = createVolume(null, primaryStore.getId());
@ -418,7 +419,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
// TODO Auto-generated catch block
e.printStackTrace();
}
//delete the volume
vol = volumeFactory.getVolume(volume.getId(), primaryStore);
future = volumeService.expungeVolumeAsync(vol);

View File

@ -36,6 +36,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
@ -180,7 +181,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te
throw new CloudRuntimeException("Unable to find image store to download template "+ profile.getTemplate());
}
for (DataStore imageStore : imageStores) {
AsyncCallFuture<CommandResult> future = this.imageService
AsyncCallFuture<TemplateApiResult> future = this.imageService
.createTemplateAsync(this.imageFactory.getTemplate(template.getId(), imageStore), imageStore);
try {
future.get();
@ -226,10 +227,10 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te
for (DataStore imageStore : imageStores) {
s_logger.info("Delete template from image store: " + imageStore.getName());
AsyncCallFuture<CommandResult> future = this.imageService
AsyncCallFuture<TemplateApiResult> future = this.imageService
.deleteTemplateAsync(this.imageFactory.getTemplate(template.getId(), imageStore));
try {
CommandResult result = future.get();
TemplateApiResult result = future.get();
success = result.isSuccess();
if ( !success )
break;

View File

@ -64,6 +64,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
@ -945,49 +947,63 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
Transaction txn = Transaction.currentTxn();
txn.start();
//Copy will just find one eligible image store for the destination zone and copy template there, not propagate to all image stores
TemplateInfo srcTemplate = this.tmplFactory.getTemplate(template.getId(), srcSecStore);
// Copy will just find one eligible image store for the destination zone
// and copy template there, not propagate to all image stores
// for that zone
for ( DataStore dstSecStore : dstSecStores ) {
for (DataStore dstSecStore : dstSecStores) {
TemplateDataStoreVO dstTmpltStore = null;
try {
dstTmpltStore = this._tmplStoreDao.findByStoreTemplate(dstSecStore.getId(), tmpltId, true);
if (dstTmpltStore != null) {
dstTmpltStore = _tmplStoreDao.lockRow(dstTmpltStore.getId(), true);
if (dstTmpltStore != null && dstTmpltStore.getDownloadState() == Status.DOWNLOADED) {
if (dstTmpltStore.getDestroyed() == false) {
return true; // already downloaded on this image store
} else {
dstTmpltStore.setDestroyed(false);
_tmplStoreDao.update(dstTmpltStore.getId(), dstTmpltStore);
return true;
}
} else if (dstTmpltStore != null && dstTmpltStore.getDownloadState() == Status.DOWNLOAD_ERROR){
if (dstTmpltStore.getDestroyed() == true) {
dstTmpltStore.setDestroyed(false);
dstTmpltStore.setDownloadState(Status.NOT_DOWNLOADED);
dstTmpltStore.setDownloadPercent(0);
dstTmpltStore.setCopy(true);
dstTmpltStore.setErrorString("");
dstTmpltStore.setJobId(null);
_tmplStoreDao.update(dstTmpltStore.getId(), dstTmpltStore);
}
}
}
dstTmpltStore = this._tmplStoreDao.findByStoreTemplate(dstSecStore.getId(), tmpltId, true);
if (dstTmpltStore != null) {
dstTmpltStore = _tmplStoreDao.lockRow(dstTmpltStore.getId(), true);
if (dstTmpltStore != null && dstTmpltStore.getDownloadState() == Status.DOWNLOADED) {
if (dstTmpltStore.getDestroyed() == false) {
return true; // already downloaded on this image
// store
} else {
dstTmpltStore.setDestroyed(false);
_tmplStoreDao.update(dstTmpltStore.getId(), dstTmpltStore);
return true;
}
} else if (dstTmpltStore != null && dstTmpltStore.getDownloadState() == Status.DOWNLOAD_ERROR) {
if (dstTmpltStore.getDestroyed() == true) {
dstTmpltStore.setDestroyed(false);
dstTmpltStore.setDownloadState(Status.NOT_DOWNLOADED);
dstTmpltStore.setDownloadPercent(0);
dstTmpltStore.setCopy(true);
dstTmpltStore.setErrorString("");
dstTmpltStore.setJobId(null);
_tmplStoreDao.update(dstTmpltStore.getId(), dstTmpltStore);
}
}
}
} finally {
txn.commit();
txn.commit();
}
if(_downloadMonitor.copyTemplate(template, srcSecStore, dstSecStore) ) {
AsyncCallFuture<TemplateApiResult> future = this.tmpltSvr.copyTemplate(srcTemplate, dstSecStore);
try {
TemplateApiResult result = future.get();
if (result.isFailed()) {
s_logger.debug("copy template failed:" + result.getResult());
return false;
}
// if(_downloadMonitor.copyTemplate(template, srcSecStore,
// dstSecStore) ) {
_tmpltDao.addTemplateToZone(template, dstZoneId);
if(account.getId() != Account.ACCOUNT_ID_SYSTEM){
if (account.getId() != Account.ACCOUNT_ID_SYSTEM) {
UsageEventUtils.publishUsageEvent(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltStore.getSize(),
template.getClass().getName(), template.getUuid());
}
return true;
}
return true;
} catch (Exception ex) {
s_logger.debug("failed to copy template to image store:" + dstSecStore.getName() + " ,will try next one");
}
}
return false;
}
@ -1002,17 +1018,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
Long destZoneId = cmd.getDestinationZoneId();
Account caller = UserContext.current().getCaller();
/*
if (_swiftMgr.isSwiftEnabled()) {
throw new CloudRuntimeException("copytemplate API is disabled in Swift setup, templates in Swift can be accessed by all Zones");
}
if (_s3Mgr.isS3Enabled()) {
throw new CloudRuntimeException(
"copytemplate API is disabled in S3 setup -- S3 templates are accessible in all zones.");
}
*/
//Verify parameters
if (sourceZoneId == destZoneId) {
throw new InvalidParameterValueException("Please specify different source and destination zones.");
@ -1769,7 +1774,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (store.size() > 1) {
throw new CloudRuntimeException("muliple image data store, don't know which one to use");
}
AsyncCallFuture<CommandResult> future = null;
AsyncCallFuture<TemplateApiResult> future = null;
if (snapshotId != null) {
SnapshotInfo snapInfo = this.snapshotFactory.getSnapshot(snapshotId);
future = this.tmpltSvr.createTemplateFromSnapshotAsync(snapInfo, tmplInfo, store.get(0));