Fix ExtractVolume bug for S3 as secondary storage.

This commit is contained in:
Min Chen 2013-05-30 14:19:59 -07:00
parent d6c6634d97
commit 614e08e19f
3 changed files with 82 additions and 7 deletions

View File

@ -18,6 +18,7 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
import com.cloud.agent.api.Answer;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Volume;
@ -33,4 +34,10 @@ public interface VolumeInfo extends DataObject, Volume {
public Long getLastPoolId();
public String getAttachedVmName();
public void processEventOnly(ObjectInDataStoreStateMachine.Event event);
public void processEventOnly(ObjectInDataStoreStateMachine.Event event, Answer answer);
public boolean stateTransit(Volume.Event event);
}

View File

@ -126,6 +126,7 @@ public class VolumeObject implements VolumeInfo {
return volumeVO.getId();
}
@Override
public boolean stateTransit(Volume.Event event) {
boolean result = false;
try {
@ -236,6 +237,22 @@ public class VolumeObject implements VolumeInfo {
}
@Override
public void processEventOnly(ObjectInDataStoreStateMachine.Event event) {
try {
objectInStoreMgr.update(this, event);
} catch (Exception e) {
s_logger.debug("Failed to update state", e);
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);
}
}
}
@Override
public String getName() {
return this.volumeVO.getName();
@ -434,6 +451,56 @@ public class VolumeObject implements VolumeInfo {
}
@Override
public void processEventOnly(ObjectInDataStoreStateMachine.Event event, Answer answer) {
try {
if (this.dataStore.getRole() == DataStoreRole.Primary) {
if (answer instanceof CopyCmdAnswer) {
CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer;
VolumeVO vol = this.volumeDao.findById(this.getId());
VolumeObjectTO newVol = (VolumeObjectTO) cpyAnswer.getNewData();
vol.setPath(newVol.getPath());
vol.setSize(newVol.getSize());
vol.setPoolId(this.getDataStore().getId());
volumeDao.update(vol.getId(), vol);
} else if (answer instanceof CreateObjectAnswer) {
CreateObjectAnswer createAnswer = (CreateObjectAnswer) answer;
VolumeObjectTO newVol = (VolumeObjectTO) createAnswer.getData();
VolumeVO vol = this.volumeDao.findById(this.getId());
vol.setPath(newVol.getPath());
vol.setSize(newVol.getSize());
vol.setPoolId(this.getDataStore().getId());
volumeDao.update(vol.getId(), vol);
}
} else {
// image store or imageCache store
if (answer instanceof DownloadAnswer) {
DownloadAnswer dwdAnswer = (DownloadAnswer) answer;
VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(),
this.getId());
volStore.setInstallPath(dwdAnswer.getInstallPath());
volStore.setChecksum(dwdAnswer.getCheckSum());
this.volumeStoreDao.update(volStore.getId(), volStore);
} else if (answer instanceof CopyCmdAnswer) {
CopyCmdAnswer cpyAnswer = (CopyCmdAnswer) answer;
VolumeDataStoreVO volStore = this.volumeStoreDao.findByStoreVolume(this.dataStore.getId(),
this.getId());
VolumeObjectTO newVol = (VolumeObjectTO) cpyAnswer.getNewData();
volStore.setInstallPath(newVol.getPath());
volStore.setSize(newVol.getSize());
this.volumeStoreDao.update(volStore.getId(), volStore);
}
}
} catch (RuntimeException ex) {
if (event == ObjectInDataStoreStateMachine.Event.OperationFailed) {
objectInStoreMgr.delete(this);
}
throw ex;
}
this.processEventOnly(event);
}
@Override
public ImageFormat getFormat() {
return this.volumeVO.getFormat();

View File

@ -623,6 +623,7 @@ public class VolumeServiceImpl implements VolumeService {
srcVolume.processEvent(Event.OperationFailed);
res.setResult(result.getResult());
future.complete(res);
return null;
}
srcVolume.processEvent(Event.OperationSuccessed);
@ -643,8 +644,8 @@ public class VolumeServiceImpl implements VolumeService {
VolumeInfo destVolume = null;
try {
destVolume = (VolumeInfo)destStore.create(srcVolume);
destVolume.processEvent(Event.CreateOnlyRequested);
srcVolume.processEvent(Event.CopyingRequested); // this is just used for locking that src volume record in DB to avoid using lock
srcVolume.processEvent(Event.MigrationRequested); // this is just used for locking that src volume record in DB to avoid using lock
destVolume.processEventOnly(Event.CreateOnlyRequested);
CopyVolumeContext<VolumeApiResult> context = new CopyVolumeContext<VolumeApiResult>(null, future, srcVolume,
destVolume,
@ -658,7 +659,7 @@ public class VolumeServiceImpl implements VolumeService {
} catch (Exception e) {
s_logger.error("failed to copy volume to image store", e);
if (destVolume != null) {
destVolume.processEvent(Event.OperationFailed);
destVolume.getDataStore().delete(destVolume);
}
srcVolume.processEvent(Event.OperationFailed); // unlock source volume record
res.setResult(e.toString());
@ -675,13 +676,13 @@ public class VolumeServiceImpl implements VolumeService {
VolumeApiResult res = new VolumeApiResult(destVolume);
try {
if (res.isFailed()) {
destVolume.processEvent(Event.OperationFailed);
srcVolume.processEvent(Event.OperationFailed);
srcVolume.processEvent(Event.OperationFailed); // back to Ready state in Volume table
destVolume.processEventOnly(Event.OperationFailed);
res.setResult(result.getResult());
future.complete(res);
}else{
srcVolume.processEvent(Event.OperationSuccessed);
destVolume.processEvent(Event.OperationSuccessed, result.getAnswer());
srcVolume.processEvent(Event.OperationSuccessed); // back to Ready state in Volume table
destVolume.processEventOnly(Event.OperationSuccessed, result.getAnswer());
future.complete(res);
}
} catch (Exception e) {