use of com.emc.storageos.recoverpoint.impl.RecoverPointClient in project coprhd-controller by CoprHD.
the class RPDeviceController method deleteRSetStep.
/**
* Delete the replication set
*
* @param rpSystem
* RP system
* @param params
* parameters needed to create the CG
* @param token
* the task
* @return
* @throws InternalException
*/
public boolean deleteRSetStep(URI rpSystemId, List<URI> volumeIds, String token) throws InternalException {
List<String> replicationSetNames = new ArrayList<String>();
try {
List<RecoverPointVolumeProtectionInfo> volumeProtectionInfoList = new ArrayList<RecoverPointVolumeProtectionInfo>();
ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, rpSystemId);
RecoverPointClient rp = RPHelper.getRecoverPointClient(rpSystem);
for (URI volumeId : volumeIds) {
Volume volume = _dbClient.queryObject(Volume.class, volumeId);
RecoverPointVolumeProtectionInfo volumeProtectionInfo = rp.getProtectionInfoForVolume(RPHelper.getRPWWn(volume.getId(), _dbClient));
// Get the volume's source volume in order to determine if we are dealing with a MetroPoint
// configuration.
Volume sourceVolume = RPHelper.getRPSourceVolume(_dbClient, volume);
VirtualPool virtualPool = _dbClient.queryObject(VirtualPool.class, sourceVolume.getVirtualPool());
// Set the MetroPoint flag
volumeProtectionInfo.setMetroPoint(VirtualPool.vPoolSpecifiesMetroPoint(virtualPool));
volumeProtectionInfoList.add(volumeProtectionInfo);
replicationSetNames.add(volume.getRSetName());
}
if (!volumeProtectionInfoList.isEmpty()) {
rp.deleteReplicationSets(volumeProtectionInfoList);
}
// Update the workflow state.
WorkflowStepCompleter.stepSucceded(token);
} catch (Exception e) {
_log.error(String.format("deleteRSetStep Failed - Replication Sets: %s", replicationSetNames.toString()));
return stepFailed(token, e, "deleteRSetStep");
}
return true;
}
use of com.emc.storageos.recoverpoint.impl.RecoverPointClient in project coprhd-controller by CoprHD.
the class RPDeviceController method createBookmarkStep.
/**
* This method creates a RP bookmark
*
* @param snapshotList
* List of snapshot
* @param system
* Protection Sytem
* @param snapshotName
* snapshot name
* @param volumeWWNs
* WWNs of the volumes whose snap is requested
* @param rpBookmarkOnly
* if true, an RP bookmark is taken or a local array snap is performed.
* @param token
* step Id corresponding to this step.
* @return true if successful, false otherwise.
*/
public boolean createBookmarkStep(List<URI> snapshotList, ProtectionSystem system, String snapshotName, Set<String> volumeWWNs, boolean rpBookmarkOnly, String token) {
RecoverPointClient rp = RPHelper.getRecoverPointClient(system);
CreateBookmarkRequestParams request = new CreateBookmarkRequestParams();
request.setVolumeWWNSet(volumeWWNs);
request.setBookmark(snapshotName);
try {
// Create the bookmark on the RP System
CreateBookmarkResponse response = rp.createBookmarks(request);
if (response == null) {
throw DeviceControllerExceptions.recoverpoint.failedToCreateBookmark();
}
if (snapshotList != null && !snapshotList.isEmpty()) {
// RP Bookmark-only flow.
if (rpBookmarkOnly) {
// This will update the blocksnapshot object based on the return of the EM call
// The construct method will set the task completer on each snapshot
constructSnapshotObjectFromBookmark(response, system, snapshotList, snapshotName, token);
} else {
// image access later on.
for (URI snapshotURI : snapshotList) {
BlockSnapshot snapshot = _dbClient.queryObject(BlockSnapshot.class, snapshotURI);
snapshot.setEmName(snapshotName);
_dbClient.updateObject(snapshot);
}
}
}
WorkflowStepCompleter.stepSucceded(token);
} catch (RecoverPointException e) {
_log.error("create bookmark step failed with a RecoverPoint exception: ", e);
WorkflowStepCompleter.stepFailed(token, e);
return false;
} catch (Exception e) {
_log.error("create bookmark step failed with an unchecked exception: ", e);
WorkflowStepCompleter.stepFailed(token, DeviceControllerException.errors.jobFailed(e));
return false;
}
return true;
}
use of com.emc.storageos.recoverpoint.impl.RecoverPointClient in project coprhd-controller by CoprHD.
the class RPDeviceController method connect.
@Override
public void connect(URI systemId) throws InternalException {
_log.debug("BEGIN RPDeviceController.connect()");
ProtectionSystem rpSystem = null;
rpSystem = _dbClient.queryObject(ProtectionSystem.class, systemId);
// Verify non-null storage device returned from the database client.
if (rpSystem == null) {
throw DeviceControllerExceptions.recoverpoint.failedConnectingForMonitoring(systemId);
}
RecoverPointClient rp = RPHelper.getRecoverPointClient(rpSystem);
rp.ping();
_log.debug("END RPDeviceController.connect()");
}
use of com.emc.storageos.recoverpoint.impl.RecoverPointClient in project coprhd-controller by CoprHD.
the class RPDeviceController method recreateRSetStep.
/**
* Recreate the replication set
*
* @param rpSystem
* RP system
* @param params
* parameters needed to create the CG
* @param token
* the task
* @return
* @throws InternalException
*/
public boolean recreateRSetStep(URI rpSystemId, List<URI> volumeIds, Map<String, RecreateReplicationSetRequestParams> rsetParams, String token) throws InternalException {
List<String> replicationSetNames = new ArrayList<String>();
try {
ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, rpSystemId);
for (URI volumeId : volumeIds) {
Volume volume = _dbClient.queryObject(Volume.class, volumeId);
replicationSetNames.add(volume.getRSetName());
}
RecoverPointClient rp = RPHelper.getRecoverPointClient(rpSystem);
_log.info("Sleeping for 15 seconds before rescanning bus to account for latencies.");
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
_log.warn("Thread sleep interrupted. Allowing to continue without sleep");
}
rp.recreateReplicationSets(rsetParams);
// Update the workflow state.
WorkflowStepCompleter.stepSucceded(token);
} catch (Exception e) {
_log.error(String.format("recreateRSetStep Failed - Replication Set(s): %s", replicationSetNames.toString()));
return stepFailed(token, e, "recreateRSetStep");
}
return true;
}
use of com.emc.storageos.recoverpoint.impl.RecoverPointClient 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;
}
Aggregations