Reallocate new PowerFlex/ScaleIO ROOT volume for the VM when template to managed volume copy fails (#105)

This commit is contained in:
sureshanaparti 2020-11-03 14:24:43 +05:30 committed by GitHub
parent 7d5a4cde7c
commit ee4384e8a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 12 deletions

View File

@ -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));

View File

@ -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.

View File

@ -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