Clean up entries in template_store_ref, volume_store_ref and

snapshot_store_ref in case of operation failure.
This commit is contained in:
Min Chen 2013-05-21 12:00:04 -07:00
parent 2f6d94462e
commit 8f549db518
6 changed files with 200 additions and 164 deletions

View File

@ -28,5 +28,5 @@ public interface StorageCacheManager {
* @return * @return
*/ */
DataObject getCacheObject(DataObject data, Scope scope); DataObject getCacheObject(DataObject data, Scope scope);
DataObject deleteCacheObject(DataObject data); boolean deleteCacheObject(DataObject data);
} }

View File

@ -81,8 +81,6 @@ public class SnapshotDataStoreVO implements StateObject<ObjectInDataStoreStateMa
@Column (name="install_path") @Column (name="install_path")
private String installPath; private String installPath;
@Column(name = GenericDao.REMOVED_COLUMN)
Date removed;
@Column(name="update_count", updatable = true, nullable=false) @Column(name="update_count", updatable = true, nullable=false)
protected long updatedCount; protected long updatedCount;

View File

@ -233,7 +233,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
CopyCommand cmd = new CopyCommand(srcData.getTO(), volObj.getTO(), _createVolumeFromSnapshotWait); CopyCommand cmd = new CopyCommand(srcData.getTO(), volObj.getTO(), _createVolumeFromSnapshotWait);
EndPoint ep = selector.select(snapObj, volObj); EndPoint ep = selector.select(snapObj, volObj);
Answer answer = ep.sendMessage(cmd); Answer answer = ep.sendMessage(cmd);
return answer; return answer;
} catch (Exception e) { } catch (Exception e) {
s_logger.error(basicErrMsg, e); s_logger.error(basicErrMsg, e);
@ -299,7 +299,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
} else if (srcData.getType() == DataObjectType.SNAPSHOT && } else if (srcData.getType() == DataObjectType.SNAPSHOT &&
destData.getType() == DataObjectType.SNAPSHOT) { destData.getType() == DataObjectType.SNAPSHOT) {
answer = copySnapshot(srcData, destData); answer = copySnapshot(srcData, destData);
} }
if (answer != null && !answer.getResult()) { if (answer != null && !answer.getResult()) {
errMsg = answer.getDetails(); errMsg = answer.getDetails();
@ -368,21 +368,27 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
int _backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue())); int _backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue()));
DataObject cacheData = null; DataObject cacheData = null;
Answer answer = null;
try { try {
if (needCacheStorage(srcData, destData)) { if (needCacheStorage(srcData, destData)) {
cacheData = cacheMgr.getCacheObject(srcData, destData.getDataStore().getScope()); cacheData = cacheMgr.getCacheObject(srcData, destData.getDataStore().getScope());
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait); CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait);
cmd.setCacheTO(cacheData.getTO()); cmd.setCacheTO(cacheData.getTO());
EndPoint ep = selector.select(srcData, destData); EndPoint ep = selector.select(srcData, destData);
Answer answer = ep.sendMessage(cmd); answer = ep.sendMessage(cmd);
} else {
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait);
EndPoint ep = selector.select(srcData, destData);
answer = ep.sendMessage(cmd);
}
// clean up cache entry in case of failure
if (answer == null || !answer.getResult()) {
if (cacheData != null) {
cacheMgr.deleteCacheObject(cacheData);
}
}
return answer; return answer;
} else {
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait);
EndPoint ep = selector.select(srcData, destData);
Answer answer = ep.sendMessage(cmd);
return answer;
}
} catch (Exception e) { } catch (Exception e) {
s_logger.debug("copy snasphot failed: " + e.toString()); s_logger.debug("copy snasphot failed: " + e.toString());
if (cacheData != null) { if (cacheData != null) {

View File

@ -63,7 +63,7 @@ public class TemplateObject implements TemplateInfo {
@Inject @Inject
VMTemplateDao imageDao; VMTemplateDao imageDao;
@Inject @Inject
ObjectInDataStoreManager ojbectInStoreMgr; ObjectInDataStoreManager objectInStoreMgr;
@Inject VMTemplatePoolDao templatePoolDao; @Inject VMTemplatePoolDao templatePoolDao;
@Inject TemplateDataStoreDao templateStoreDao; @Inject TemplateDataStoreDao templateStoreDao;
@ -191,10 +191,15 @@ public class TemplateObject implements TemplateInfo {
} }
} }
ojbectInStoreMgr.update(this, event); objectInStoreMgr.update(this, event);
} catch (NoTransitionException e) { } catch (NoTransitionException e) {
s_logger.debug("failed to update state", e); s_logger.debug("failed to update state", e);
throw new CloudRuntimeException("Failed to update state" + e.toString()); throw new CloudRuntimeException("Failed to update state" + e.toString());
} finally{
// in case of OperationFailed, expunge the entry
if ( event == ObjectInDataStoreStateMachine.Event.OperationFailed){
objectInStoreMgr.delete(this);
}
} }
} }
@ -247,10 +252,15 @@ public class TemplateObject implements TemplateInfo {
this.stateTransit(templEvent); this.stateTransit(templEvent);
} }
} }
ojbectInStoreMgr.update(this, event); objectInStoreMgr.update(this, event);
} catch (NoTransitionException e) { } catch (NoTransitionException e) {
s_logger.debug("failed to update state", e); s_logger.debug("failed to update state", e);
throw new CloudRuntimeException("Failed to update state" + e.toString()); throw new CloudRuntimeException("Failed to update state" + e.toString());
} finally{
// in case of OperationFailed, expunge the entry
if ( event == ObjectInDataStoreStateMachine.Event.OperationFailed){
objectInStoreMgr.delete(this);
}
} }
} }
@ -266,7 +276,7 @@ public class TemplateObject implements TemplateInfo {
@Override @Override
public String getInstallPath() { public String getInstallPath() {
DataObjectInStore obj = ojbectInStoreMgr.findObject(this, this.dataStore); DataObjectInStore obj = objectInStoreMgr.findObject(this, this.dataStore);
return obj.getInstallPath(); return obj.getInstallPath();
} }

View File

@ -52,34 +52,37 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.NoTransitionException;
public class SnapshotObject implements SnapshotInfo { public class SnapshotObject implements SnapshotInfo {
private static final Logger s_logger = Logger.getLogger(SnapshotObject.class); private static final Logger s_logger = Logger.getLogger(SnapshotObject.class);
private SnapshotVO snapshot; private SnapshotVO snapshot;
private DataStore store; private DataStore store;
@Inject @Inject
protected SnapshotDao snapshotDao; protected SnapshotDao snapshotDao;
@Inject @Inject
protected VolumeDao volumeDao; protected VolumeDao volumeDao;
@Inject protected VolumeDataFactory volFactory; @Inject
@Inject protected SnapshotStateMachineManager stateMachineMgr; protected VolumeDataFactory volFactory;
@Inject
protected SnapshotStateMachineManager stateMachineMgr;
@Inject @Inject
SnapshotDataFactory snapshotFactory; SnapshotDataFactory snapshotFactory;
@Inject @Inject
ObjectInDataStoreManager ojbectInStoreMgr; ObjectInDataStoreManager objectInStoreMgr;
@Inject @Inject
SnapshotDataStoreDao snapshotStoreDao; SnapshotDataStoreDao snapshotStoreDao;
public SnapshotObject() { public SnapshotObject() {
} }
protected void configure(SnapshotVO snapshot, DataStore store) { protected void configure(SnapshotVO snapshot, DataStore store) {
this.snapshot = snapshot; this.snapshot = snapshot;
this.store = store; this.store = store;
} }
public static SnapshotObject getSnapshotObject(SnapshotVO snapshot, DataStore store) { public static SnapshotObject getSnapshotObject(SnapshotVO snapshot, DataStore store) {
SnapshotObject snapObj = ComponentContext.inject(SnapshotObject.class); SnapshotObject snapObj = ComponentContext.inject(SnapshotObject.class);
snapObj.configure(snapshot, store); snapObj.configure(snapshot, store);
return snapObj; return snapObj;
} }
public DataStore getStore() { public DataStore getStore() {
@ -88,17 +91,17 @@ public class SnapshotObject implements SnapshotInfo {
@Override @Override
public SnapshotInfo getParent() { public SnapshotInfo getParent() {
SnapshotDataStoreVO snapStoreVO = this.snapshotStoreDao.findByStoreSnapshot(this.store.getRole(), this.store.getId(), this.snapshot.getId()); SnapshotDataStoreVO snapStoreVO = this.snapshotStoreDao.findByStoreSnapshot(this.store.getRole(), this.store.getId(), this.snapshot.getId());
if (snapStoreVO == null) { if (snapStoreVO == null) {
return null; return null;
} }
long parentId = snapStoreVO.getParentSnapshotId(); long parentId = snapStoreVO.getParentSnapshotId();
if (parentId == 0) { if (parentId == 0) {
return null; return null;
} }
return this.snapshotFactory.getSnapshot(parentId, store); return this.snapshotFactory.getSnapshot(parentId, store);
} }
@Override @Override
@ -121,7 +124,7 @@ public class SnapshotObject implements SnapshotInfo {
@Override @Override
public long getId() { public long getId() {
return this.snapshot.getId(); return this.snapshot.getId();
} }
@Override @Override
@ -136,100 +139,100 @@ public class SnapshotObject implements SnapshotInfo {
@Override @Override
public Long getSize() { public Long getSize() {
return this.snapshot.getSize(); return this.snapshot.getSize();
} }
@Override @Override
public DataObjectType getType() { public DataObjectType getType() {
return DataObjectType.SNAPSHOT; return DataObjectType.SNAPSHOT;
} }
@Override @Override
public String getUuid() { public String getUuid() {
return this.snapshot.getUuid(); return this.snapshot.getUuid();
} }
@Override @Override
public void processEvent( public void processEvent(ObjectInDataStoreStateMachine.Event event) {
ObjectInDataStoreStateMachine.Event event) { try {
try { objectInStoreMgr.update(this, event);
ojbectInStoreMgr.update(this, event); } catch (Exception e) {
} catch (Exception e) { s_logger.debug("Failed to update state:" + e.toString());
s_logger.debug("Failed to update state:" + e.toString()); throw new CloudRuntimeException("Failed to update state: " + e.toString());
throw new CloudRuntimeException("Failed to update state: " + e.toString()); } finally {
} if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) {
} objectInStoreMgr.delete(this);
}
}
}
@Override @Override
public long getAccountId() { public long getAccountId() {
return this.snapshot.getAccountId(); return this.snapshot.getAccountId();
} }
@Override @Override
public long getVolumeId() { public long getVolumeId() {
return this.snapshot.getVolumeId(); return this.snapshot.getVolumeId();
} }
@Override @Override
public String getPath() { public String getPath() {
return this.ojbectInStoreMgr.findObject(this, getDataStore()).getInstallPath(); return this.objectInStoreMgr.findObject(this, getDataStore()).getInstallPath();
} }
@Override @Override
public String getName() { public String getName() {
return this.snapshot.getName(); return this.snapshot.getName();
} }
@Override @Override
public Date getCreated() { public Date getCreated() {
return this.snapshot.getCreated(); return this.snapshot.getCreated();
} }
@Override @Override
public Type getRecurringType() { public Type getRecurringType() {
return this.snapshot.getRecurringType(); return this.snapshot.getRecurringType();
} }
@Override @Override
public State getState() { public State getState() {
return this.snapshot.getState(); return this.snapshot.getState();
} }
@Override @Override
public HypervisorType getHypervisorType() { public HypervisorType getHypervisorType() {
return this.snapshot.getHypervisorType(); return this.snapshot.getHypervisorType();
} }
@Override @Override
public boolean isRecursive() { public boolean isRecursive() {
return this.snapshot.isRecursive(); return this.snapshot.isRecursive();
} }
@Override @Override
public short getsnapshotType() { public short getsnapshotType() {
return this.snapshot.getsnapshotType(); return this.snapshot.getsnapshotType();
} }
@Override @Override
public long getDomainId() { public long getDomainId() {
return this.snapshot.getDomainId(); return this.snapshot.getDomainId();
} }
@Override
public Long getDataCenterId() {
return this.snapshot.getDataCenterId();
}
@Override public void processEvent(Snapshot.Event event) throws NoTransitionException {
public Long getDataCenterId() { stateMachineMgr.processEvent(this.snapshot, event);
return this.snapshot.getDataCenterId(); }
}
public void processEvent(Snapshot.Event event) public SnapshotVO getSnapshotVO() {
throws NoTransitionException { return this.snapshot;
stateMachineMgr.processEvent(this.snapshot, event); }
}
public SnapshotVO getSnapshotVO(){
return this.snapshot;
}
@Override @Override
public DataTO getTO() { public DataTO getTO() {
@ -242,34 +245,41 @@ public class SnapshotObject implements SnapshotInfo {
@Override @Override
public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) { public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) {
SnapshotDataStoreVO snapshotStore = this.snapshotStoreDao.findByStoreSnapshot(this.getDataStore().getRole(), try {
this.getDataStore().getId(), this.getId()); SnapshotDataStoreVO snapshotStore = this.snapshotStoreDao.findByStoreSnapshot(this.getDataStore().getRole(), this.getDataStore().getId(),
if (answer instanceof CreateObjectAnswer) { this.getId());
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)((CreateObjectAnswer) answer).getData(); if (answer instanceof CreateObjectAnswer) {
snapshotStore.setInstallPath(snapshotTO.getPath()); SnapshotObjectTO snapshotTO = (SnapshotObjectTO) ((CreateObjectAnswer) answer).getData();
this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore); snapshotStore.setInstallPath(snapshotTO.getPath());
} else if (answer instanceof CopyCmdAnswer) { this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore);
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)((CopyCmdAnswer) answer).getNewData(); } else if (answer instanceof CopyCmdAnswer) {
snapshotStore.setInstallPath(snapshotTO.getPath()); SnapshotObjectTO snapshotTO = (SnapshotObjectTO) ((CopyCmdAnswer) answer).getNewData();
if (snapshotTO.getParentSnapshotPath() == null) { snapshotStore.setInstallPath(snapshotTO.getPath());
snapshotStore.setParentSnapshotId(0L); if (snapshotTO.getParentSnapshotPath() == null) {
} snapshotStore.setParentSnapshotId(0L);
this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore); }
} else { this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore);
throw new CloudRuntimeException("Unknown answer: " + answer.getClass()); } else {
} throw new CloudRuntimeException("Unknown answer: " + answer.getClass());
this.processEvent(event); }
} catch (RuntimeException ex) {
if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) {
objectInStoreMgr.delete(this);
}
throw ex;
}
this.processEvent(event);
} }
@Override @Override
public ObjectInDataStoreStateMachine.State getStatus() { public ObjectInDataStoreStateMachine.State getStatus() {
return this.ojbectInStoreMgr.findObject(this, store).getObjectInStoreState(); return this.objectInStoreMgr.findObject(this, store).getObjectInStoreState();
} }
@Override @Override
public void addPayload(Object data) { public void addPayload(Object data) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
} }

View File

@ -59,7 +59,7 @@ public class VolumeObject implements VolumeInfo {
@Inject @Inject
VolumeDataStoreDao volumeStoreDao; VolumeDataStoreDao volumeStoreDao;
@Inject @Inject
ObjectInDataStoreManager ojbectInStoreMgr; ObjectInDataStoreManager objectInStoreMgr;
@Inject @Inject
VMInstanceDao vmInstanceDao; VMInstanceDao vmInstanceDao;
private Object payload; private Object payload;
@ -159,7 +159,7 @@ public class VolumeObject implements VolumeInfo {
if (this.dataStore == null) { if (this.dataStore == null) {
throw new CloudRuntimeException("datastore must be set before using this object"); throw new CloudRuntimeException("datastore must be set before using this object");
} }
DataObjectInStore obj = ojbectInStoreMgr.findObject(this.volumeVO.getId(), DataObjectType.VOLUME, this.dataStore.getId(), this.dataStore.getRole()); DataObjectInStore obj = objectInStoreMgr.findObject(this.volumeVO.getId(), DataObjectType.VOLUME, this.dataStore.getId(), this.dataStore.getRole());
if (obj.getState() != ObjectInDataStoreStateMachine.State.Ready) { if (obj.getState() != ObjectInDataStoreStateMachine.State.Ready) {
return this.dataStore.getUri() + return this.dataStore.getUri() +
"&" + EncodingType.OBJTYPE + "=" + DataObjectType.VOLUME + "&" + EncodingType.OBJTYPE + "=" + DataObjectType.VOLUME +
@ -187,11 +187,11 @@ public class VolumeObject implements VolumeInfo {
try { try {
Volume.Event volEvent = null; Volume.Event volEvent = null;
if ( this.dataStore.getRole() == DataStoreRole.ImageCache){ if ( this.dataStore.getRole() == DataStoreRole.ImageCache){
ojbectInStoreMgr.update(this, event); objectInStoreMgr.update(this, event);
return; return;
} }
if (this.dataStore.getRole() == DataStoreRole.Image) { if (this.dataStore.getRole() == DataStoreRole.Image) {
ojbectInStoreMgr.update(this, event); objectInStoreMgr.update(this, event);
if (event == ObjectInDataStoreStateMachine.Event.CreateRequested) { if (event == ObjectInDataStoreStateMachine.Event.CreateRequested) {
volEvent = Volume.Event.UploadRequested; volEvent = Volume.Event.UploadRequested;
} else if (event == ObjectInDataStoreStateMachine.Event.OperationSuccessed) { } else if (event == ObjectInDataStoreStateMachine.Event.OperationSuccessed) {
@ -225,6 +225,11 @@ public class VolumeObject implements VolumeInfo {
} catch (Exception e) { } catch (Exception e) {
s_logger.debug("Failed to update state", e); s_logger.debug("Failed to update state", e);
throw new CloudRuntimeException("Failed to update state:" + e.toString()); throw new CloudRuntimeException("Failed to update state:" + e.toString());
} finally{
// in case of OperationFailed, expunge the entry
if ( event == ObjectInDataStoreStateMachine.Event.OperationFailed){
objectInStoreMgr.delete(this);
}
} }
} }
@ -249,7 +254,7 @@ public class VolumeObject implements VolumeInfo {
if (this.dataStore.getRole() == DataStoreRole.Primary) { if (this.dataStore.getRole() == DataStoreRole.Primary) {
return this.volumeVO.getPath(); return this.volumeVO.getPath();
} else { } else {
DataObjectInStore objInStore = this.ojbectInStoreMgr.findObject(this, dataStore); DataObjectInStore objInStore = this.objectInStoreMgr.findObject(this, dataStore);
return objInStore.getInstallPath(); return objInStore.getInstallPath();
} }
} }
@ -379,34 +384,41 @@ public class VolumeObject implements VolumeInfo {
@Override @Override
public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) { public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) {
if (this.dataStore.getRole() == DataStoreRole.Primary) { try {
if (answer instanceof CopyCmdAnswer) { if (this.dataStore.getRole() == DataStoreRole.Primary) {
CopyCmdAnswer cpyAnswer = (CopyCmdAnswer)answer; if (answer instanceof CopyCmdAnswer) {
VolumeVO vol = this.volumeDao.findById(this.getId()); CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer;
VolumeObjectTO newVol = (VolumeObjectTO)cpyAnswer.getNewData(); VolumeVO vol = this.volumeDao.findById(this.getId());
vol.setPath(newVol.getPath()); VolumeObjectTO newVol = (VolumeObjectTO) cpyAnswer.getNewData();
vol.setSize(newVol.getSize()); vol.setPath(newVol.getPath());
vol.setPoolId(this.getDataStore().getId()); vol.setSize(newVol.getSize());
volumeDao.update(vol.getId(), vol); vol.setPoolId(this.getDataStore().getId());
} else if (answer instanceof CreateObjectAnswer) { volumeDao.update(vol.getId(), vol);
CreateObjectAnswer createAnswer =(CreateObjectAnswer)answer; } else if (answer instanceof CreateObjectAnswer) {
VolumeObjectTO newVol = (VolumeObjectTO)createAnswer.getData(); CreateObjectAnswer createAnswer = (CreateObjectAnswer) answer;
VolumeVO vol = this.volumeDao.findById(this.getId()); VolumeObjectTO newVol = (VolumeObjectTO) createAnswer.getData();
vol.setPath(newVol.getPath()); VolumeVO vol = this.volumeDao.findById(this.getId());
vol.setSize(newVol.getSize()); vol.setPath(newVol.getPath());
vol.setPoolId(this.getDataStore().getId()); vol.setSize(newVol.getSize());
volumeDao.update(vol.getId(), vol); vol.setPoolId(this.getDataStore().getId());
} volumeDao.update(vol.getId(), vol);
} else if (this.dataStore.getRole() == DataStoreRole.Image) { }
if (answer instanceof DownloadAnswer) { } else if (this.dataStore.getRole() == DataStoreRole.Image) {
DownloadAnswer dwdAnswer = (DownloadAnswer)answer; if (answer instanceof DownloadAnswer) {
VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(), this.getId()); DownloadAnswer dwdAnswer = (DownloadAnswer) answer;
volStore.setInstallPath(dwdAnswer.getInstallPath()); VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(), this.getId());
volStore.setChecksum(dwdAnswer.getCheckSum()); volStore.setInstallPath(dwdAnswer.getInstallPath());
this.volumeStoreDao.update(volStore.getId(), volStore); volStore.setChecksum(dwdAnswer.getCheckSum());
} this.volumeStoreDao.update(volStore.getId(), volStore);
} }
}
} catch (RuntimeException ex) {
if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) {
objectInStoreMgr.delete(this);
}
throw ex;
}
this.processEvent(event);
this.processEvent(event);
} }
} }