use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class RPDeviceController method cgModifyStep.
/**
* Workflow step method for modifying a consistency group.
*
* @param rpSystemId
* RP system Id
* @param recommendation
* parameters needed to create the CG
* @param token
* the task
* @return true if the operation is a success, false otherwise
* @throws InternalException
*/
public boolean cgModifyStep(URI rpSystemId, List<VolumeDescriptor> volumeDescriptors, CGRequestParams cgParams, String token) throws InternalException {
try {
// Get only the RP_EXISTING_PROTECTED_SOURCE descriptors
List<VolumeDescriptor> existingProtectedSourceVolumeDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_EXISTING_PROTECTED_SOURCE }, new VolumeDescriptor.Type[] {});
WorkflowStepCompleter.stepExecuting(token);
_log.info("Modify CG step executing");
ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, rpSystemId);
if (!existingProtectedSourceVolumeDescriptors.isEmpty()) {
// Get the first descriptor, that's all we need. This operation will
// affect all the RSets in the CG by adding a new standby copy.
VolumeDescriptor descriptor = existingProtectedSourceVolumeDescriptors.get(0);
Volume sourceVolume = _dbClient.queryObject(Volume.class, descriptor.getVolumeURI());
URI newVpoolURI = (URI) descriptor.getParameters().get(VolumeDescriptor.PARAM_VPOOL_CHANGE_NEW_VPOOL_ID);
URI oldVPoolURI = (URI) descriptor.getParameters().get(VolumeDescriptor.PARAM_VPOOL_CHANGE_OLD_VPOOL_ID);
VirtualPool newVpool = _dbClient.queryObject(VirtualPool.class, newVpoolURI);
VirtualPool oldVpool = _dbClient.queryObject(VirtualPool.class, oldVPoolURI);
// as it is non-disruptive. Further CG Updates will be considered in the future.
if (VirtualPool.vPoolSpecifiesRPVPlex(oldVpool) && !VirtualPool.vPoolSpecifiesMetroPoint(oldVpool) && VirtualPool.vPoolSpecifiesMetroPoint(newVpool)) {
upgradeRPVPlexToMetroPoint(sourceVolume, newVpool, oldVpool, rpSystem);
}
// Update the ProtectionSet with any newly added protection set objects
// TODO support remove as well?
ProtectionSet protectionSet = _dbClient.queryObject(ProtectionSet.class, sourceVolume.getProtectionSet());
updateProtectionSet(protectionSet, cgParams);
}
// Collect and update the protection system statistics to account for
// the newly updated CG
_log.info("Collecting RP statistics post CG update.");
collectRPStatistics(rpSystem);
// Update the workflow state.
_log.info("Modify CG step completed");
WorkflowStepCompleter.stepSucceded(token);
} catch (Exception e) {
_log.error("Failed modifying cg: " + e.getStackTrace());
doFailCgModifyStep(volumeDescriptors, cgParams, rpSystemId, token, e);
return false;
}
return true;
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class RPDeviceController method searchForBookmarks.
/**
* Searches for all specified bookmarks (RP snapshots). If even just one
* bookmark does not exist, an exception will be thrown.
*
* @param protectionDevice
* the protection system URI
* @param snapshots
* the RP snapshots to search for
*/
private void searchForBookmarks(URI protectionDevice, Set<URI> snapshots) {
ProtectionSystem rpSystem = getRPSystem(protectionDevice);
RecoverPointClient rpClient = RPHelper.getRecoverPointClient(rpSystem);
// Check that the bookmarks actually exist
Set<Integer> cgIDs = null;
boolean bookmarkExists;
// Map used to keep track of which BlockSnapshots map to which CGs
Map<Integer, List<BlockSnapshot>> cgSnaps = new HashMap<Integer, List<BlockSnapshot>>();
for (URI snapshotID : snapshots) {
cgIDs = new HashSet<Integer>();
BlockSnapshot snapshot = _dbClient.queryObject(BlockSnapshot.class, snapshotID);
// Get the volume associated with this snapshot
Volume volume = _dbClient.queryObject(Volume.class, snapshot.getParent().getURI());
// Now get the protection set (CG) associated with the volume so we can use
// it to search for the bookmark
ProtectionSet protectionSet = _dbClient.queryObject(ProtectionSet.class, volume.getProtectionSet());
Integer cgID = null;
try {
cgID = Integer.valueOf(protectionSet.getProtectionId());
} catch (NumberFormatException nfe) {
throw DeviceControllerExceptions.recoverpoint.exceptionLookingForBookmarks(nfe);
}
cgIDs.add(cgID);
if (cgSnaps.get(cgID) == null) {
cgSnaps.put(cgID, new ArrayList<BlockSnapshot>());
}
cgSnaps.get(cgID).add(snapshot);
}
GetBookmarksResponse bookmarkResponse = rpClient.getRPBookmarks(cgIDs);
// one exists in RP. Fail if any of the snapshots does not exist.
for (Integer cgID : cgSnaps.keySet()) {
for (BlockSnapshot snapshot : cgSnaps.get(cgID)) {
bookmarkExists = false;
if (bookmarkResponse.getCgBookmarkMap() != null && !bookmarkResponse.getCgBookmarkMap().isEmpty()) {
List<RPBookmark> rpBookmarks = bookmarkResponse.getCgBookmarkMap().get(cgID);
if (rpBookmarks != null && !rpBookmarks.isEmpty()) {
// Find the bookmark
for (RPBookmark rpBookmark : rpBookmarks) {
if (rpBookmark.getBookmarkName().equals(snapshot.getEmName())) {
bookmarkExists = true;
}
}
}
}
if (!bookmarkExists) {
throw DeviceControllerExceptions.recoverpoint.failedToFindExpectedBookmarks();
}
}
}
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class RPDeviceController method restoreVolume.
/**
* Restore an RP bookmark. This will enable the specified bookmark on the CG if the CG is not already enabled. This
* step is
* required for RP bookmark restores.
*
* @param protectionDevice
* RP protection system URI
* @param storageDevice
* storage device of the volume
* @param snapshotId
* snapshot URI
* @param task
* task ID
* @return true if the step completed successfully, false otherwise.
* @throws InternalException
*/
public boolean restoreVolume(URI protectionDevice, URI storageDevice, URI snapshotID, BlockSnapshotRestoreCompleter completer, String stepId) throws InternalException {
try {
_log.info("Restoring bookmark on the RP CG");
WorkflowStepCompleter.stepExecuting(stepId);
ProtectionSystem system = null;
system = _dbClient.queryObject(ProtectionSystem.class, protectionDevice);
if (system == null) {
// Verify non-null storage device returned from the database client.
throw DeviceControllerExceptions.recoverpoint.failedConnectingForMonitoring(protectionDevice);
}
Set<String> volumeWWNs = new HashSet<String>();
String emName = null;
// Get the volume associated with this snapshot
BlockSnapshot snapshot = _dbClient.queryObject(BlockSnapshot.class, snapshotID);
if (snapshot.getEmName() != null) {
emName = snapshot.getEmName();
}
Volume volume = _dbClient.queryObject(Volume.class, snapshot.getParent().getURI());
// Take out a workflow step lock on the CG
_workflowService.getWorkflowFromStepId(stepId);
List<String> lockKeys = new ArrayList<String>();
lockKeys.add(ControllerLockingUtil.getConsistencyGroupStorageKey(_dbClient, volume.getConsistencyGroup(), system.getId()));
boolean lockAcquired = _workflowService.acquireWorkflowStepLocks(stepId, lockKeys, LockTimeoutValue.get(LockType.RP_CG));
if (!lockAcquired) {
throw DeviceControllerException.exceptions.failedToAcquireLock(lockKeys.toString(), String.format("failed to get lock while restoring volumes in RP consistency group: %s", volume.getConsistencyGroup().toString()));
}
// Now determine the target volume that corresponds to the site of the snapshot
ProtectionSet protectionSet = _dbClient.queryObject(ProtectionSet.class, volume.getProtectionSet());
Volume targetVolume = ProtectionSet.getTargetVolumeFromSourceAndInternalSiteName(_dbClient, protectionSet, volume, snapshot.getEmInternalSiteName());
volumeWWNs.add(RPHelper.getRPWWn(targetVolume.getId(), _dbClient));
// Now restore image access
RecoverPointClient rp = RPHelper.getRecoverPointClient(system);
MultiCopyRestoreImageRequestParams request = new MultiCopyRestoreImageRequestParams();
request.setBookmark(emName);
request.setVolumeWWNSet(volumeWWNs);
MultiCopyRestoreImageResponse response = rp.restoreImageCopies(request);
if (response == null) {
throw DeviceControllerExceptions.recoverpoint.failedToImageAccessBookmark();
}
WorkflowStepCompleter.stepSucceded(stepId);
_log.info("restoreVolume step is complete");
} catch (InternalException e) {
_log.error("Operation failed with Exception: ", e);
return stepFailed(stepId, (ServiceCoded) e, "restoreVolumeStep");
} catch (URISyntaxException e) {
_log.error("Operation failed with Exception: ", e);
return stepFailed(stepId, e, "restoreVolumeStep");
} catch (Exception e) {
_log.error("Operation failed with Exception: ", e);
return stepFailed(stepId, e, "restoreVolumeStep");
}
return true;
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class RPHelper method updateAccessState.
/**
* Updates the access state for a snapshot's target volume. If image access is being enabled, the
* access state will be set to READWRITE. If image access is being disabled, the access state will
* be set to READ_ONLY.
*
* @param snapshot the snapshot
* @param volume the snapshot's parent volume
* @param accessState the volume access state
* @param dbClient the database client reference
* @throws URISyntaxException
*/
private static void updateAccessState(BlockSnapshot snapshot, Volume volume, VolumeAccessState accessState, DbClient dbClient) throws URISyntaxException {
// For RP+VPLEX volumes, we need to fetch the VPLEX volume. The snapshot object references the
// block/back-end volume as its parent. Fetch the VPLEX volume that is created with this volume
// as the back-end volume.
Volume vol = volume;
if (Volume.checkForVplexBackEndVolume(dbClient, volume)) {
vol = Volume.fetchVplexVolume(dbClient, volume);
}
Volume targetVolume = null;
// If the personality is SOURCE, then the enable image access request is part of export operation.
if (vol.checkPersonality(Volume.PersonalityTypes.SOURCE.toString())) {
// Now determine the target volume that corresponds to the site of the snapshot
ProtectionSet protectionSet = dbClient.queryObject(ProtectionSet.class, vol.getProtectionSet());
targetVolume = ProtectionSet.getTargetVolumeFromSourceAndInternalSiteName(dbClient, protectionSet, vol, snapshot.getEmInternalSiteName());
} else if (vol.checkPersonality(Volume.PersonalityTypes.TARGET.toString())) {
targetVolume = vol;
}
if (targetVolume != null) {
if (accessState != null) {
_log.info(String.format("Updating the access state to %s for target volume %s.", accessState.name(), targetVolume.getId()));
targetVolume.setAccessState(accessState.name());
dbClient.updateObject(targetVolume);
} else {
_log.warn(String.format("Invalid access state. Could not update access state for target volume %s.", targetVolume.getId()));
}
}
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class RPHelper method validateCGForDelete.
/**
* Validate the CG before performing destructive operations.
* If additional volumes appear in the RP CG on the hardware, this method returns false
* Clerical errors (such as missing DB entries) result in an Exception
*
* @param dbClient
* dbclient
* @param system
* protection system
* @param cgId
* BlockConsistencyGroup ID
* @param volumes
* list of volumes
* @return true if CG is what we expect on the hardware, false otherwise
*/
public static boolean validateCGForDelete(DbClient dbClient, ProtectionSystem system, URI cgId, Set<URI> volumes) {
_log.info("validateCGForDelete {} - start", system.getId());
// Retrieve all of the RP CGs, their RSets, and their volumes
RecoverPointClient rp = RPHelper.getRecoverPointClient(system);
Set<GetCGsResponse> cgList = rp.getAllCGs();
if (cgList == null || cgList.isEmpty()) {
String errMsg = "Could not retrieve CGs from the RPA to perform validation.";
throw DeviceControllerExceptions.recoverpoint.unableToPerformValidation(errMsg);
}
// Grab all of the source volumes from the CG according to ViPR
List<Volume> srcVolumes = RPHelper.getCgVolumes(dbClient, cgId, PersonalityTypes.SOURCE.toString());
if (srcVolumes == null || srcVolumes.isEmpty()) {
String errMsg = "Could not retrieve volumes from the database for CG to perform validation";
throw DeviceControllerExceptions.recoverpoint.unableToPerformValidation(errMsg);
}
// Get the protection set ID from the first source volume. All volumes will have the same pset ID.
URI psetId = srcVolumes.get(0).getProtectionSet().getURI();
if (NullColumnValueGetter.isNullURI(psetId)) {
String errMsg = "Could not retrieve protection set ID from the database for CG to perform validation";
throw DeviceControllerExceptions.recoverpoint.unableToPerformValidation(errMsg);
}
// Get the protection set, which is required to get the CG ID on the RPA
ProtectionSet pset = dbClient.queryObject(ProtectionSet.class, psetId);
if (pset == null) {
String errMsg = "Could not retrieve protection set from the database for CG to perform validation";
throw DeviceControllerExceptions.recoverpoint.unableToPerformValidation(errMsg);
}
// Pre-populate the wwn fields for comparisons later.
List<String> srcVolumeWwns = new ArrayList<>();
for (Volume srcVolume : srcVolumes) {
srcVolumeWwns.add(srcVolume.getWWN());
}
// This loop finds the CG on the hardware from the list of all CGs. Ignores all CGs that don't match our ID.
for (GetCGsResponse cgResponse : cgList) {
// Compare the stored CG ID (unique per RP System, doesn't change even if CG name changes)
if (Long.parseLong(pset.getProtectionId()) != cgResponse.getCgId()) {
continue;
}
// Make sure we have rsets before we continue. If the CG has no RSets on the hardware, throw
if (cgResponse.getRsets() == null || cgResponse.getRsets().isEmpty()) {
String errMsg = "Could not retrieve replication sets from the hardware to perform validation";
throw DeviceControllerExceptions.recoverpoint.unableToPerformValidation(errMsg);
}
// Find one of our volumes
for (GetRSetResponse rsetResponse : cgResponse.getRsets()) {
// Make sure we have volumes in the RSet before we continue
if (rsetResponse == null || rsetResponse.getVolumes() == null || rsetResponse.getVolumes().isEmpty()) {
String errMsg = "Could not retrieve the volumes in the replication set from the hardware to perform validation";
throw DeviceControllerExceptions.recoverpoint.unableToPerformValidation(errMsg);
}
// list of WWNs is the list of source volumes we know about.
for (GetVolumeResponse volumeResponse : rsetResponse.getVolumes()) {
// This hardware volume should be represented in the list of srcVolumes
if (!srcVolumeWwns.contains(volumeResponse.getWwn())) {
_log.warn("Found at least one volume that isn't in our list of source volumes {}, therefore we can not delete the entire CG.", volumeResponse.getWwn());
return false;
}
}
}
}
_log.info("validateCGForDelete {} - end", system.getId());
return true;
}
Aggregations