CLOUDSTACK-5017: Throw CloudRuntimeException in case of template/volume

download when ssvm is not ready so that caller can remove some leftover
entries in template_store_ref and volume_store_ref.
This commit is contained in:
Min Chen 2013-11-04 12:31:31 -08:00
parent 84b5bfff74
commit 9a62239a92
3 changed files with 76 additions and 24 deletions

View File

@ -172,12 +172,26 @@ public class TemplateServiceImpl implements TemplateService {
return;
}
TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(callback,
templateOnStore, null);
try {
TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(callback,
templateOnStore, null);
AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context);
store.getDriver().createAsync(store, templateOnStore, caller);
AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context);
store.getDriver().createAsync(store, templateOnStore, caller);
} catch (CloudRuntimeException ex) {
// clean up already persisted template_store_ref entry in case of createTemplateCallback is never called
TemplateDataStoreVO templateStoreVO = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId());
if (templateStoreVO != null) {
TemplateInfo tmplObj = _templateFactory.getTemplate(template, store);
tmplObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
}
TemplateApiResult result = new TemplateApiResult(template);
result.setResult(ex.getMessage());
if (callback != null) {
callback.complete(result);
}
}
}
@Override
@ -732,11 +746,23 @@ public class TemplateServiceImpl implements TemplateService {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Invoke datastore driver createAsync to create template on destination store");
}
TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null,
(TemplateObject) templateOnStore, future);
AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().copyTemplateCrossZoneCallBack(null, null)).setContext(context);
destStore.getDriver().createAsync(destStore, templateOnStore, caller);
try {
TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null,
(TemplateObject)templateOnStore, future);
AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().copyTemplateCrossZoneCallBack(null, null)).setContext(context);
destStore.getDriver().createAsync(destStore, templateOnStore, caller);
} catch (CloudRuntimeException ex) {
// clean up already persisted template_store_ref entry in case of createTemplateCallback is never called
TemplateDataStoreVO templateStoreVO = _vmTemplateStoreDao.findByStoreTemplate(destStore.getId(), srcTemplate.getId());
if (templateStoreVO != null) {
TemplateInfo tmplObj = _templateFactory.getTemplate(srcTemplate, destStore);
tmplObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
}
TemplateApiResult res = new TemplateApiResult((TemplateObject)templateOnStore);
res.setResult(ex.getMessage());
future.complete(res);
}
return future;
}

View File

@ -40,6 +40,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
@ -55,7 +56,6 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
@ -165,12 +165,24 @@ public class VolumeServiceImpl implements VolumeService {
DataObject volumeOnStore = dataStore.create(volume);
volumeOnStore.processEvent(Event.CreateOnlyRequested);
CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, volumeOnStore,
future);
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createVolumeCallback(null, null)).setContext(context);
try {
CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, volumeOnStore,
future);
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createVolumeCallback(null, null)).setContext(context);
dataStore.getDriver().createAsync(dataStore, volumeOnStore, caller);
dataStore.getDriver().createAsync(dataStore, volumeOnStore, caller);
} catch (CloudRuntimeException ex) {
// clean up already persisted volume_store_ref entry in case of createVolumeCallback is never called
VolumeDataStoreVO volStoreVO = _volumeStoreDao.findByStoreVolume(dataStore.getId(), volume.getId());
if (volStoreVO != null) {
VolumeInfo volObj = volFactory.getVolume(volume, dataStore);
volObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
}
VolumeApiResult volResult = new VolumeApiResult((VolumeObject)volumeOnStore);
volResult.setResult(ex.getMessage());
future.complete(volResult);
}
return future;
}
@ -1022,13 +1034,25 @@ public class VolumeServiceImpl implements VolumeService {
volumeOnStore.processEvent(Event.CreateOnlyRequested);
CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, volumeOnStore,
future);
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().registerVolumeCallback(null, null));
caller.setContext(context);
try {
CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, volumeOnStore,
future);
AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().registerVolumeCallback(null, null));
caller.setContext(context);
store.getDriver().createAsync(store, volumeOnStore, caller);
store.getDriver().createAsync(store, volumeOnStore, caller);
} catch (CloudRuntimeException ex) {
// clean up already persisted volume_store_ref entry in case of createVolumeCallback is never called
VolumeDataStoreVO volStoreVO = _volumeStoreDao.findByStoreVolume(store.getId(), volume.getId());
if (volStoreVO != null) {
VolumeInfo volObj = volFactory.getVolume(volume, store);
volObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
}
VolumeApiResult res = new VolumeApiResult((VolumeObject)volumeOnStore);
res.setResult(ex.getMessage());
future.complete(res);
}
return future;
}

View File

@ -67,6 +67,7 @@ import com.cloud.storage.upload.UploadListener;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;
@Component
@Local(value = { DownloadMonitor.class })
@ -169,8 +170,9 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor
}
EndPoint ep = _epSelector.select(template);
if (ep == null) {
s_logger.warn("There is no secondary storage VM for downloading template to image store " + store.getName());
return;
String errMsg = "There is no secondary storage VM for downloading template to image store " + store.getName();
s_logger.warn(errMsg);
throw new CloudRuntimeException(errMsg);
}
DownloadListener dl = new DownloadListener(ep, store, template, _timer, this, dcmd,
callback);