use of com.emc.storageos.recoverpoint.responses.RecoverPointVolumeProtectionInfo in project coprhd-controller by CoprHD.
the class RPDeviceController method cgDeleteStep.
/**
* The step that deletes the CG from the RecoverPoint appliance if all of the volumeIDs are in the request,
* otherwise delete replication sets and associated journals.
*
* @param rpSystem
* protection system
* @param volumeIDs
* volume IDs
* @param journalVolumeIDs
* Volume IDs of journals
* @param token
* task ID
* @return true if successful
* @throws ControllerException
*/
public boolean cgDeleteStep(URI rpSystem, List<URI> volumeIDs, List<URI> journalVolumeIDs, String token) throws ControllerException {
WorkflowStepCompleter.stepExecuting(token);
_log.info("cgDeleteStep is running");
boolean lockException = false;
try {
// Validate input arguments
if (rpSystem == null) {
_log.error("Protection system not sent into cgDeleteStep");
throw DeviceControllerExceptions.recoverpoint.cgDeleteStepInvalidParam("protection system URI");
}
ProtectionSystem system = _dbClient.queryObject(ProtectionSystem.class, rpSystem);
if (system == null) {
_log.error("Protection system not in database");
throw DeviceControllerExceptions.recoverpoint.cgDeleteStepInvalidParam("protection system null");
}
if (system.getInactive()) {
_log.error("Protection system set to be deleted");
throw DeviceControllerExceptions.recoverpoint.cgDeleteStepInvalidParam("protection system deleted");
}
if (volumeIDs == null) {
_log.error("Volume IDs list is null");
throw DeviceControllerExceptions.recoverpoint.cgDeleteStepInvalidParam("volume IDs null");
}
if (volumeIDs.isEmpty()) {
_log.error("Volume IDs list is empty");
throw DeviceControllerExceptions.recoverpoint.cgDeleteStepInvalidParam("volume IDs empty");
}
List<Volume> volumes = _dbClient.queryObject(Volume.class, volumeIDs);
if (volumes.isEmpty()) {
_log.info("All volumes already deleted. Not performing RP CG operation");
WorkflowStepCompleter.stepSucceded(token);
return true;
}
BlockConsistencyGroup cg = _dbClient.queryObject(BlockConsistencyGroup.class, volumes.get(0).getConsistencyGroup());
// lock around create and delete operations on the same CG
List<String> lockKeys = new ArrayList<String>();
lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(_dbClient, cg.getId(), system.getId()));
boolean lockAcquired = _workflowService.acquireWorkflowLocks(_workflowService.getWorkflowFromStepId(token), lockKeys, LockTimeoutValue.get(LockType.RP_CG));
if (!lockAcquired) {
lockException = true;
throw DeviceControllerException.exceptions.failedToAcquireLock(lockKeys.toString(), String.format("Delete or remove volumes from RP consistency group %s", cg.getCgNameOnStorageSystem(rpSystem)));
}
// Validate that all volumes belong to the same BlockConsistencyGroup
for (Volume volume : volumes) {
if (!volume.getConsistencyGroup().equals(cg.getId())) {
_log.error("Not all volumes belong to the same consistency group.");
throw DeviceControllerExceptions.recoverpoint.cgDeleteStepInvalidParam("volumes from different consistency groups");
}
}
// Find a valid protection set reference so we can cleanup the protection set later.
ProtectionSet protectionSet = null;
for (Volume volume : volumes) {
if (!NullColumnValueGetter.isNullNamedURI(volume.getProtectionSet())) {
protectionSet = _dbClient.queryObject(ProtectionSet.class, volume.getProtectionSet());
break;
}
}
RecoverPointClient rp = RPHelper.getRecoverPointClient(system);
// Validate that we found the protection info for each volume.
RecoverPointVolumeProtectionInfo volumeProtectionInfo = null;
for (Volume volume : volumes) {
try {
if (volumeProtectionInfo == null) {
volumeProtectionInfo = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(volume.getId(), _dbClient));
VirtualPool virtualPool = _dbClient.queryObject(VirtualPool.class, volume.getVirtualPool());
volumeProtectionInfo.setMetroPoint(VirtualPool.vPoolSpecifiesMetroPoint(virtualPool));
}
} catch (Exception e) {
// Do nothing. If we cannot find volume protection info for a volume, we do not want that
// exception preventing us from trying to find it for other volumes being deleted.
_log.warn("Looks like the volume(s) we're trying to remove from the RP appliance are no longer associated with a RP CG, continuing delete process.");
}
}
// is nothing in RP we need to cleanup.
if (volumeProtectionInfo == null) {
_log.warn("Looks like the volume(s) we're trying to remove from the RP appliance are no longer associated with a RP CG, continuing delete process.");
WorkflowStepCompleter.stepSucceded(token);
return true;
}
if (RPHelper.cgSourceVolumesContainsAll(_dbClient, cg.getId(), volumeIDs)) {
// We are deleting all source volumes in the consistency group so we can delete the
// RecoverPoint CG as well.
rp.deleteCG(volumeProtectionInfo);
// We want to reflect the CG being deleted in the BlockConsistencyGroup
if (volumeIDs != null && !volumeIDs.isEmpty()) {
// Get the CG URI from the first volume
Volume vol = _dbClient.queryObject(Volume.class, volumeIDs.get(0));
if (vol.getConsistencyGroup() != null) {
cleanUpRPCG(system.getId(), vol.getConsistencyGroup());
}
if (protectionSet == null || protectionSet.getInactive() || protectionSet.getVolumes() == null || protectionSet.getVolumes().isEmpty()) {
_log.info("Cleanup unnecessary as protection set in ViPR is empty or has already been marked for deletion.");
} else {
_log.info("Removing all volume from protection set: " + protectionSet.getLabel());
// Remove all volumes in the ProtectionSet and mark for deletion
List<String> removeVolumeIDs = new ArrayList<String>(protectionSet.getVolumes());
cleanupProtectionSetVolumes(protectionSet, removeVolumeIDs, true);
}
}
setProtectionSetStatus(volumeProtectionInfo, ProtectionStatus.DISABLED.toString(), system);
} else {
List<RecoverPointVolumeProtectionInfo> replicationSetsToRemove = new ArrayList<RecoverPointVolumeProtectionInfo>();
List<String> removeVolumeIDs = new ArrayList<String>();
for (Volume volume : volumes) {
_log.info(String.format("Volume [%s] (%s) needs to have its replication set removed from RP", volume.getLabel(), volume.getId()));
// Delete the replication set if there are more volumes (other replication sets).
// If there are no other replications sets we will simply delete the CG instead.
volumeProtectionInfo = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(volume.getId(), _dbClient));
// Volume Info to give RP to clean up the RSets
replicationSetsToRemove.add(volumeProtectionInfo);
// Source volume to be removed from Protection Set
if (!NullColumnValueGetter.isNullURI(volume.getId())) {
removeVolumeIDs.add(volume.getId().toString());
}
// All Target volumes to be removed from Protection Set
List<Volume> targetVolumes = RPHelper.getTargetVolumes(volume, _dbClient);
for (Volume targetVol : targetVolumes) {
removeVolumeIDs.add(targetVol.getId().toString());
}
}
// Remove the Replication Sets from RP.
// Wait for a min before attempting to delete the rsets.
// RP has not yet synced up with the fact that new rsets were added and we attempted to delete them
// because the rollback
// started.
// This delay helps in RP catching up before we issue another command.
_log.info("waiting for 1 min before deleting replication sets");
Thread.sleep(1000 * 60);
rp.deleteReplicationSets(replicationSetsToRemove);
// Remove any journal volumes that were added in this operation. Otherwise CG ends up in a weird state.
if (journalVolumeIDs.isEmpty()) {
_log.info("There are no journal volumes to be deleted");
} else {
List<Volume> journalVolumes = _dbClient.queryObject(Volume.class, journalVolumeIDs);
for (Volume journalVolume : journalVolumes) {
String journalWWN = RPHelper.getRPWWn(journalVolume.getId(), _dbClient);
_log.info(String.format("Removing Journal volume - %s : WWN - %s", journalVolume.getLabel(), journalWWN));
volumeProtectionInfo = rp.getProtectionInfoForVolume(journalWWN);
rp.deleteJournalFromCopy(volumeProtectionInfo, journalWWN);
removeVolumeIDs.add(journalVolume.getId().toString());
}
}
// Cleanup the ViPR Protection Set
cleanupProtectionSetVolumes(protectionSet, removeVolumeIDs, false);
}
WorkflowStepCompleter.stepSucceded(token);
_log.info("cgDeleteStep is complete");
// collect and update the protection system statistics to account for
// the CG that has been removed
_log.info("Collection RP statistics post CG delete.");
// Collect stats, even if we didn't delete the CG, because the volume count in the CG will go down.
collectRPStatistics(system);
} catch (Exception e) {
if (lockException) {
ServiceError serviceError = DeviceControllerException.errors.deleteVolumesAborted(volumeIDs.toString(), e);
return stepFailed(token, serviceError, "cgDeleteStep");
} else {
return stepFailed(token, e, "cgDeleteStep");
}
}
return true;
}
use of com.emc.storageos.recoverpoint.responses.RecoverPointVolumeProtectionInfo in project coprhd-controller by CoprHD.
the class RPDeviceController method getReplicationSettings.
/**
* Gets the replication settings from RP for a given volume.
*
* @param rpSystem
* the RecoverPoint system.
* @param volumeId
* the volume ID.
* @return the replication set params to perform a recreate operation
* @throws RecoverPointException
*/
public RecreateReplicationSetRequestParams getReplicationSettings(ProtectionSystem rpSystem, URI volumeId) throws RecoverPointException {
RecoverPointClient rp = RPHelper.getRecoverPointClient(rpSystem);
Volume volume = _dbClient.queryObject(Volume.class, volumeId);
RecoverPointVolumeProtectionInfo volumeProtectionInfo = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(volume.getId(), _dbClient));
return rp.getReplicationSet(volumeProtectionInfo);
}
Aggregations