mirror of https://github.com/apache/cloudstack.git
Reallocate new PowerFlex/ScaleIO ROOT volume for the VM when template to managed volume copy fails (#105)
This commit is contained in:
parent
7d5a4cde7c
commit
ee4384e8a3
|
|
@ -84,6 +84,7 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba
|
|||
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.OperationSucceeded, Ready, null));
|
||||
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.DestroyRequested, Destroy, null));
|
||||
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Creating, Event.CreateRequested, Creating, null));
|
||||
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.CreateRequested, Creating, null));
|
||||
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Ready, Event.ResizeRequested, Resizing, null));
|
||||
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Resizing, Event.OperationSucceeded, Ready, Arrays.asList(new StateMachine2.Transition.Impact[]{StateMachine2.Transition.Impact.USAGE})));
|
||||
s_fsm.addTransition(new StateMachine2.Transition<State, Event>(Resizing, Event.OperationFailed, Ready, null));
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import java.util.Random;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
|
|
@ -173,6 +174,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
private VolumeDetailsDao _volumeDetailsDao;
|
||||
@Inject
|
||||
private TemplateDataFactory tmplFactory;
|
||||
@Inject
|
||||
private VolumeOrchestrationService _volumeMgr;
|
||||
|
||||
private final static String SNAPSHOT_ID = "SNAPSHOT_ID";
|
||||
|
||||
|
|
@ -812,9 +815,15 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
volDao.update(volume.getId(), volume);
|
||||
vo.processEvent(Event.OperationSuccessed);
|
||||
} else {
|
||||
vo.processEvent(Event.DestroyRequested);
|
||||
volResult.setResult(result.getResult());
|
||||
|
||||
try {
|
||||
destroyAndReallocateManagedVolume((VolumeInfo) vo);
|
||||
} catch (CloudRuntimeException ex) {
|
||||
s_logger.warn("Couldn't destroy managed volume: " + vo.getId());
|
||||
}
|
||||
}
|
||||
|
||||
AsyncCallFuture<VolumeApiResult> future = context.getFuture();
|
||||
|
|
@ -1093,15 +1102,13 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
// Refresh the volume info from the DB.
|
||||
volumeInfo = volFactory.getVolume(volumeInfo.getId(), destPrimaryDataStore);
|
||||
|
||||
volumeInfo.processEvent(Event.CreateRequested);
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<>(null, volumeInfo, destPrimaryDataStore, srcTemplateOnPrimary, future, null);
|
||||
|
||||
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
|
||||
|
||||
caller.setCallback(caller.getTarget().createVolumeFromBaseManagedImageCallBack(null, null));
|
||||
caller.setContext(context);
|
||||
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
|
||||
details.put(PrimaryDataStore.MANAGED, Boolean.TRUE.toString());
|
||||
details.put(PrimaryDataStore.STORAGE_HOST, destPrimaryDataStore.getHostAddress());
|
||||
details.put(PrimaryDataStore.STORAGE_PORT, String.valueOf(destPrimaryDataStore.getPort()));
|
||||
|
|
@ -1122,16 +1129,12 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
throw e;
|
||||
} catch (Throwable e) {
|
||||
s_logger.debug("Failed to copy managed template on primary storage", e);
|
||||
String errMsg = e.toString();
|
||||
volumeInfo.processEvent(Event.DestroyRequested);
|
||||
String errMsg = "Failed due to " + e.toString();
|
||||
|
||||
try {
|
||||
AsyncCallFuture<VolumeApiResult> expungeVolumeFuture = expungeVolumeAsync(volumeInfo);
|
||||
VolumeApiResult expungeVolumeResult = expungeVolumeFuture.get();
|
||||
if (expungeVolumeResult.isFailed()) {
|
||||
errMsg += " : Failed to expunge a volume that was created";
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
destroyAndReallocateManagedVolume(volumeInfo);
|
||||
} catch (CloudRuntimeException ex) {
|
||||
s_logger.warn("Failed to destroy managed volume: " + volumeInfo.getId());
|
||||
errMsg += " : " + ex.getMessage();
|
||||
}
|
||||
|
||||
|
|
@ -1148,6 +1151,44 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
}
|
||||
|
||||
private void destroyAndReallocateManagedVolume(VolumeInfo volumeInfo) {
|
||||
if (volumeInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
VolumeVO volume = volDao.findById(volumeInfo.getId());
|
||||
if (volume == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (volume.getState() == State.Allocated) { // Possible states here: Allocated, Ready & Creating
|
||||
return;
|
||||
}
|
||||
|
||||
volumeInfo.processEvent(Event.DestroyRequested);
|
||||
|
||||
Volume newVol = _volumeMgr.allocateDuplicateVolume(volume, null);
|
||||
VolumeVO newVolume = (VolumeVO) newVol;
|
||||
newVolume.set_iScsiName(null);
|
||||
volDao.update(newVolume.getId(), newVolume);
|
||||
s_logger.debug("Allocated new volume: " + newVolume.getId() + " for the VM: " + volume.getInstanceId());
|
||||
|
||||
try {
|
||||
AsyncCallFuture<VolumeApiResult> expungeVolumeFuture = expungeVolumeAsync(volumeInfo);
|
||||
VolumeApiResult expungeVolumeResult = expungeVolumeFuture.get();
|
||||
if (expungeVolumeResult.isFailed()) {
|
||||
s_logger.warn("Failed to expunge volume: " + volumeInfo.getId() + " that was created");
|
||||
throw new CloudRuntimeException("Failed to expunge volume: " + volumeInfo.getId() + " that was created");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (canVolumeBeRemoved(volumeInfo.getId())) {
|
||||
volDao.remove(volumeInfo.getId());
|
||||
}
|
||||
s_logger.warn("Unable to expunge volume: " + volumeInfo.getId() + " due to: " + ex.getMessage());
|
||||
throw new CloudRuntimeException("Unable to expunge volume: " + volumeInfo.getId() + " due to: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void createManagedVolumeCopyTemplateAsync(VolumeInfo volumeInfo, PrimaryDataStore primaryDataStore, TemplateInfo srcTemplateInfo, Host destHost, AsyncCallFuture<VolumeApiResult> future) {
|
||||
try {
|
||||
// Create a volume on managed storage.
|
||||
|
|
|
|||
|
|
@ -3093,6 +3093,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
volumeToAttach.setPath(volumeToAttach.get_iScsiName());
|
||||
_volsDao.update(volumeToAttach.getId(), volumeToAttach);
|
||||
}
|
||||
|
||||
if (host != null && volumeToAttachStoragePool.getPoolType() == Storage.StoragePoolType.PowerFlex) {
|
||||
// Unmap the volume on PowerFlex/ScaleIO pool for stopped VM
|
||||
volService.revokeAccess(volFactory.getVolume(volumeToAttach.getId()), host, dataStore);
|
||||
}
|
||||
}
|
||||
|
||||
// insert record for disk I/O statistics
|
||||
|
|
|
|||
Loading…
Reference in New Issue