use of com.emc.storageos.db.client.model.VolumeGroup in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method prepareVolume.
/**
* Prepare Volume for a RecoverPoint protected volume
*
* @param volume Volume to prepare, could be null if brand new vol
* @param project Project for volume
* @param varray Varray for volume
* @param vpool Vpool for volume
* @param size Size of volume
* @param recommendation Main rec for this volume
* @param label Volume label
* @param consistencyGroup CG for volume
* @param protectionSystemURI URI for the Protection System
* @param personality Personality of the volume
* @param rsetName Replication Set Name
* @param internalSiteName RP Internal site of the volume
* @param rpCopyName RP Copy Name
* @param sourceVolume The source volume
* @param vplex Boolean that is true if this is a vplex volume
* @param changeVpoolVolume Existing volume if this is a change vpool
* @param isPreCreatedVolume
* @return Fully prepared Volume for RP
*/
public Volume prepareVolume(Volume volume, Project project, VirtualArray varray, VirtualPool vpool, String size, RPRecommendation recommendation, String label, BlockConsistencyGroup consistencyGroup, URI protectionSystemURI, Volume.PersonalityTypes personality, String rsetName, String internalSiteName, String rpCopyName, Volume sourceVolume, boolean vplex, Volume changeVpoolVolume, boolean isPreCreatedVolume) {
// Check to see if this is a change vpool volume, if so, use it as the already existing volume.
volume = (changeVpoolVolume != null) ? changeVpoolVolume : volume;
// If volume is still null, then it's a brand new volume
boolean isNewVolume = (volume == null);
if (isNewVolume || isPreCreatedVolume) {
if (!isPreCreatedVolume) {
volume = new Volume();
volume.setId(URIUtil.createId(Volume.class));
volume.setOpStatus(new OpStatusMap());
} else {
// Reload volume object from DB
volume = _dbClient.queryObject(Volume.class, volume.getId());
}
volume.setSyncActive(true);
volume.setLabel(label);
volume.setCapacity(SizeUtil.translateSize(size));
volume.setThinlyProvisioned(VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(vpool.getSupportedProvisioningType()));
volume.setVirtualPool(vpool.getId());
volume.setProject(new NamedURI(project.getId(), volume.getLabel()));
volume.setTenant(new NamedURI(project.getTenantOrg().getURI(), volume.getLabel()));
volume.setVirtualArray(varray.getId());
if (null != recommendation.getSourceStoragePool()) {
StoragePool pool = _dbClient.queryObject(StoragePool.class, recommendation.getSourceStoragePool());
if (null != pool) {
volume.setProtocol(new StringSet());
volume.getProtocol().addAll(VirtualPoolUtil.getMatchingProtocols(vpool.getProtocols(), pool.getProtocols()));
if (!vplex) {
volume.setPool(pool.getId());
volume.setStorageController(pool.getStorageDevice());
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, pool.getStorageDevice());
String systemType = storageSystem.checkIfVmax3() ? DiscoveredDataObject.Type.vmax3.name() : storageSystem.getSystemType();
volume.setSystemType(systemType);
}
}
}
volume.setVirtualArray(varray.getId());
}
// Set all Journal Volumes to have the INTERNAL_OBJECT flag.
if (personality.equals(Volume.PersonalityTypes.METADATA)) {
volume.addInternalFlags(Flag.INTERNAL_OBJECT);
volume.addInternalFlags(Flag.SUPPORTS_FORCE);
volume.setAccessState(Volume.VolumeAccessState.NOT_READY.name());
} else if (personality.equals(Volume.PersonalityTypes.SOURCE)) {
volume.setAccessState(Volume.VolumeAccessState.READWRITE.name());
volume.setLinkStatus(Volume.LinkStatus.OTHER.name());
} else if (personality.equals(Volume.PersonalityTypes.TARGET)) {
volume.setAccessState(Volume.VolumeAccessState.NOT_READY.name());
volume.setLinkStatus(Volume.LinkStatus.OTHER.name());
}
if (consistencyGroup != null) {
volume.setConsistencyGroup(consistencyGroup.getId());
// backend volumes added to backend CGs.
if (changeVpoolVolume != null && !changeVpoolVolume.checkForRp() && RPHelper.isVPlexVolume(changeVpoolVolume, _dbClient)) {
// if the CG has array consistency enabled and the CG supports LOCAL type.
if (consistencyGroup.getArrayConsistency()) {
if (null == changeVpoolVolume.getAssociatedVolumes() || changeVpoolVolume.getAssociatedVolumes().isEmpty()) {
_log.error("VPLEX volume {} has no backend volumes.", changeVpoolVolume.forDisplay());
throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(changeVpoolVolume.forDisplay());
}
for (String backendVolumeId : changeVpoolVolume.getAssociatedVolumes()) {
Volume backingVolume = _dbClient.queryObject(Volume.class, URI.create(backendVolumeId));
String rgName = consistencyGroup.getCgNameOnStorageSystem(backingVolume.getStorageController());
if (rgName == null) {
// for new CG
rgName = consistencyGroup.getLabel();
} else {
// if other volumes in the same CG are in an application, add this volume to the same application
VolumeGroup volumeGroup = ControllerUtils.getApplicationForCG(_dbClient, consistencyGroup, rgName);
if (volumeGroup != null) {
backingVolume.getVolumeGroupIds().add(volumeGroup.getId().toString());
}
}
_log.info(String.format("Preparing VPLEX volume [%s](%s) for RP Protection, " + "backend end volume [%s](%s) updated with replication group name: %s", volume.getLabel(), volume.getId(), backingVolume.getLabel(), backingVolume.getId(), rgName));
backingVolume.setReplicationGroupInstance(rgName);
changeVpoolVolume.setBackingReplicationGroupInstance(rgName);
_dbClient.updateObject(backingVolume);
}
}
}
}
volume.setPersonality(personality.toString());
volume.setProtectionController(protectionSystemURI);
volume.setRSetName(rsetName);
volume.setInternalSiteName(internalSiteName);
volume.setRpCopyName(rpCopyName);
if (NullColumnValueGetter.isNotNullValue(vpool.getAutoTierPolicyName())) {
URI autoTierPolicyUri = StorageScheduler.getAutoTierPolicy(volume.getPool(), vpool.getAutoTierPolicyName(), _dbClient);
if (null != autoTierPolicyUri) {
volume.setAutoTieringPolicyUri(autoTierPolicyUri);
}
}
if (isNewVolume && !isPreCreatedVolume) {
// Create the volume in the db
_dbClient.createObject(volume);
} else {
_dbClient.updateObject(volume);
}
// Keep track of target volumes associated with the source volume
if (sourceVolume != null) {
if (sourceVolume.getRpTargets() == null) {
sourceVolume.setRpTargets(new StringSet());
}
sourceVolume.getRpTargets().add(volume.getId().toString());
_dbClient.updateObject(sourceVolume);
}
return volume;
}
use of com.emc.storageos.db.client.model.VolumeGroup in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method prepareSnapshots.
/**
* Prepares the snapshots for a snapshot request.
*
* @param volumes The volumes for which snapshots are to be created.
* @param snapShotType The snapshot technology type.
* @param snapshotName The snapshot name.
* @param snapshotURIs [OUT] The URIs for the prepared snapshots.
* @param taskId The unique task identifier
*
* @return The list of snapshots
*/
@Override
public List<BlockSnapshot> prepareSnapshots(List<Volume> volumes, String snapshotType, String snapshotName, List<URI> snapshotURIs, String taskId) {
List<BlockSnapshot> snapshots = new ArrayList<BlockSnapshot>();
int index = 1;
for (Volume volume : volumes) {
VolumeGroup volumeGroup = volume.getApplication(_dbClient);
boolean isInApplication = volumeGroup != null && !volumeGroup.getInactive();
if (RPHelper.isProtectionBasedSnapshot(volume, snapshotType, _dbClient) && snapshotType.equalsIgnoreCase(BlockSnapshot.TechnologyType.RP.toString())) {
// need to create snapshots on
if (!volume.getRpTargets().isEmpty()) {
List<URI> targetVolumeURIs = new ArrayList<URI>();
// Build a URI list of target volumes for the call to obtain copy access states
for (String targetVolumeStr : volume.getRpTargets()) {
targetVolumeURIs.add(URI.create(targetVolumeStr));
}
// Get a handle on the RPController so we can query the access states associated with the
// target volumes.
RPController rpController = getController(RPController.class, ProtectionSystem._RP);
Map<URI, String> copyAccessStates = rpController.getCopyAccessStates(volume.getProtectionController(), targetVolumeURIs);
for (URI targetVolumeURI : targetVolumeURIs) {
Volume targetVolume = _dbClient.queryObject(Volume.class, targetVolumeURI);
// can be created for that copy.
if (copyAccessStates != null && !copyAccessStates.isEmpty() && RPHelper.isValidBookmarkState(copyAccessStates.get(targetVolume.getId()))) {
BlockSnapshot snapshot = prepareSnapshotFromVolume(volume, snapshotName, targetVolume, 0, snapshotType, isInApplication);
snapshot.setOpStatus(new OpStatusMap());
snapshot.setEmName(snapshotName);
snapshot.setEmInternalSiteName(targetVolume.getInternalSiteName());
snapshot.setVirtualArray(targetVolume.getVirtualArray());
snapshots.add(snapshot);
_log.info(String.format("Prepared snapshot : [%s]", snapshot.getLabel()));
} else {
_log.warn(String.format("A BlockSnapshot is not being prepared for target volume %s because copy %s is currently in a state [%s] that does not allow bookmarks to be created.", targetVolume.getId(), targetVolume.getRpCopyName(), copyAccessStates.get(targetVolume.getId())));
}
}
}
} else {
boolean vplex = RPHelper.isVPlexVolume(volume, _dbClient);
Volume volumeToSnap = volume;
if (vplex) {
volumeToSnap = vplexBlockServiceApiImpl.getVPLEXSnapshotSourceVolume(volume);
}
boolean isRPTarget = false;
if (NullColumnValueGetter.isNotNullValue(volume.getPersonality()) && volume.getPersonality().equals(PersonalityTypes.TARGET.name())) {
isRPTarget = true;
}
BlockSnapshot snapshot = prepareSnapshotFromVolume(volumeToSnap, snapshotName, (isRPTarget ? volume : null), index++, snapshotType, isInApplication);
snapshot.setTechnologyType(snapshotType);
// Check to see if the RP Copy Name of this volume contains any of the RP Source
// suffix's appended by ViPR
boolean rpCopyNameContainsSrcSuffix = NullColumnValueGetter.isNotNullValue(volume.getRpCopyName()) && (volume.getRpCopyName().contains(SRC_COPY_SUFFIX) || volume.getRpCopyName().contains(MP_ACTIVE_COPY_SUFFIX) || volume.getRpCopyName().contains(MP_STANDBY_COPY_SUFFIX));
// Hotfix for COP-18957
// Check to see if the requested volume is a former Source.
// We do this by checking to see if this is a Target volume and that the RP Copy Name
// contains any of the RP Source suffix's appended by ViPR.
//
// TODO: This is a short term solution since there will be a better way of determining
// this in future releases.
//
// FIXME: One concern here is RP ingestion where ViPR isn't the one who sets the copy names.
// Valid concern and this needs to be changed when RP ingest supports RP+VPLEX: Yoda/Yoda+.
boolean isFormerSource = isRPTarget && rpCopyNameContainsSrcSuffix;
// Check to see if the requested volume is a former target that is now the
// source as a result of a swap. This is done by checking the source volume's
// virtual pool for RP protection. If RP protection does not exist, we know this
// is a former target.
// TODO: In the future the swap functionality should update the vpools accordingly to
// add/remove protection. This check should be removed at that point and another
// method to check for a swapped state should be used.
boolean isFormerTarget = false;
if (NullColumnValueGetter.isNotNullValue(volume.getPersonality()) && volume.getPersonality().equals(PersonalityTypes.SOURCE.name()) && !rpCopyNameContainsSrcSuffix) {
isFormerTarget = true;
}
if (!isInApplication && (((isRPTarget || isFormerTarget) && vplex && !isFormerSource) || !vplex)) {
// For RP+Vplex targets (who are not former source volumes) and former target volumes,
// we do not want to create a backing array CG snap. To avoid doing this, we do not
// set the consistency group.
// OR
// This is a native snapshot so do not set the consistency group, otherwise
// the SMIS code/array will get confused trying to look for a consistency
// group that only exists in RecoverPoint.
snapshot.setConsistencyGroup(null);
}
snapshots.add(snapshot);
_log.info(String.format("Prepared snapshot : [%s]", snapshot.getLabel()));
}
}
if (!snapshots.isEmpty()) {
for (BlockSnapshot snapshot : snapshots) {
Operation op = new Operation();
op.setResourceType(ResourceOperationTypeEnum.CREATE_VOLUME_SNAPSHOT);
op.setStartTime(Calendar.getInstance());
snapshot.getOpStatus().createTaskStatus(taskId, op);
snapshotURIs.add(snapshot.getId());
}
// Create all the snapshot objects
_dbClient.createObject(snapshots);
} else {
// are in direct access mode (invalid bookmark state).
throw APIException.badRequests.cannotCreateSnapshots();
}
// But only return the unique ones
return snapshots;
}
use of com.emc.storageos.db.client.model.VolumeGroup in project coprhd-controller by CoprHD.
the class DefaultBlockServiceApiImpl method updateVolumesInVolumeGroup.
/**
* {@inheritDoc}
*/
@Override
public void updateVolumesInVolumeGroup(VolumeGroupVolumeList addVolumes, List<Volume> removeVolumes, URI volumeGroupId, String taskId) {
VolumeGroup volumeGroup = _dbClient.queryObject(VolumeGroup.class, volumeGroupId);
ApplicationAddVolumeList addVolumeList = null;
if (addVolumes != null && addVolumes.getVolumes() != null && !addVolumes.getVolumes().isEmpty()) {
addVolumeList = addVolumesToApplication(addVolumes, volumeGroup, taskId);
}
if (removeVolumes != null && !removeVolumes.isEmpty()) {
removeVolumesFromApplication(removeVolumes, volumeGroup, taskId);
}
// call controller to handle non application ready CG volumes
if ((addVolumeList != null && !addVolumeList.getVolumes().isEmpty())) {
List<URI> vols = addVolumeList.getVolumes();
Volume firstVolume = _dbClient.queryObject(Volume.class, vols.get(0));
URI systemURI = firstVolume.getStorageController();
StorageSystem system = _dbClient.queryObject(StorageSystem.class, systemURI);
BlockController controller = getController(BlockController.class, system.getSystemType());
controller.updateApplication(systemURI, addVolumeList, volumeGroup.getId(), taskId);
} else {
// No need to call to controller. update the application task
Operation op = volumeGroup.getOpStatus().get(taskId);
op.ready();
volumeGroup.getOpStatus().updateTaskStatus(taskId, op);
_dbClient.updateObject(volumeGroup);
}
}
use of com.emc.storageos.db.client.model.VolumeGroup in project coprhd-controller by CoprHD.
the class VolumeGroupService method createVolumeGroupSnapshotSession.
/**
* Creates a volume group snapshot session
* - Creates snapshot session for all the array replication groups within this Application.
* - If partial flag is specified, it creates snapshot session only for set of array replication groups.
* A Volume from each array replication group can be provided to indicate which array replication
* groups are required to take snapshot session.
*
* @prereq none
*
* @param volumeGroupId the URI of the Volume Group
* - Volume group URI
* @param param VolumeGroupSnapshotSessionCreateParam
*
* @brief Create volume group snapshot session
* @return TaskList
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/protection/snapshot-sessions")
@CheckPermission(roles = { Role.SYSTEM_ADMIN }, acls = { ACL.ANY })
public TaskList createVolumeGroupSnapshotSession(@PathParam("id") final URI volumeGroupId, VolumeGroupSnapshotSessionCreateParam param) {
ArgValidator.checkFieldUriType(volumeGroupId, VolumeGroup.class, ID_FIELD);
// Query volume group
final VolumeGroup volumeGroup = (VolumeGroup) queryResource(volumeGroupId);
// validate replica operation for volume group
validateCopyOperationForVolumeGroup(volumeGroup, ReplicaTypeEnum.SNAPSHOT_SESSION);
// validate name
String name = TimeUtils.formatDateForCurrent(param.getName());
ArgValidator.checkFieldNotEmpty(name, NAME_FIELD);
name = ResourceOnlyNameGenerator.removeSpecialCharsForName(name, SmisConstants.MAX_SNAPSHOT_NAME_LENGTH);
if (StringUtils.isEmpty(name)) {
// original name has special chars only
throw APIException.badRequests.invalidCopySetName(param.getName(), ReplicaTypeEnum.SNAPSHOT_SESSION.toString());
}
// check name provided is not duplicate
VolumeGroupCopySetList sessionSet = getVolumeGroupSnapsetSessionSets(volumeGroup);
if (sessionSet.getCopySets().contains(name)) {
// duplicate name
throw APIException.badRequests.duplicateCopySetName(param.getName(), ReplicaTypeEnum.SNAPSHOT_SESSION.toString());
}
// volumes to be processed
List<Volume> volumes = new ArrayList<Volume>();
List<URI> partialVolumeList = new ArrayList<URI>();
boolean partial = isPartialRequest(param, volumeGroup, partialVolumeList);
if (partial) {
log.info("Snapshot Session requested for subset of array groups in Application.");
// validate that at least one volume URI is provided
ArgValidator.checkFieldNotEmpty(partialVolumeList, VOLUMES_FIELD);
// validate the provided volumes
for (URI volumeURI : partialVolumeList) {
ArgValidator.checkFieldUriType(volumeURI, Volume.class, VOLUME_FIELD);
// Get the volume
Volume volume = _dbClient.queryObject(Volume.class, volumeURI);
ArgValidator.checkEntity(volume, volumeURI, isIdEmbeddedInURL(volumeURI));
// validate that provided volume is part of Volume Group
if (!volume.getVolumeGroupIds().contains(volumeGroupId.toString())) {
throw APIException.badRequests.replicaOperationNotAllowedVolumeNotInVolumeGroup(ReplicaTypeEnum.SNAPSHOT_SESSION.toString(), volume.getLabel());
}
volumes.add(volume);
}
} else {
log.info("Snapshot Session creation for entire Application");
// get all volumes
volumes.addAll(ControllerUtils.getVolumeGroupVolumes(_dbClient, volumeGroup));
// validate that there should be some volumes in VolumeGroup
if (volumes.isEmpty()) {
throw APIException.badRequests.replicaOperationNotAllowedOnEmptyVolumeGroup(volumeGroup.getLabel(), ReplicaTypeEnum.SNAPSHOT_SESSION.toString());
}
}
// Check for pending tasks
checkForApplicationPendingTasks(volumeGroup, _dbClient, false);
auditOp(OperationTypeEnum.CREATE_VOLUME_GROUP_SNAPSHOT_SESSION, true, AuditLogManager.AUDITOP_BEGIN, volumeGroupId.toString(), name);
TaskList taskList = new TaskList();
Map<URI, List<URI>> cgToVolUris = ControllerUtils.groupVolumeURIsByCG(volumes);
Set<Entry<URI, List<URI>>> entrySet = cgToVolUris.entrySet();
for (Entry<URI, List<URI>> entry : entrySet) {
URI cgUri = entry.getKey();
log.info("Create snapshot session for consistency group {}, volumes {}", cgUri, Joiner.on(',').join(entry.getValue()));
try {
SnapshotSessionCreateParam cgSnapshotSessionParam = new SnapshotSessionCreateParam(name, param.getNewLinkedTargets(), entry.getValue());
taskList.getTaskList().addAll(_blockConsistencyGroupService.createConsistencyGroupSnapshotSession(cgUri, cgSnapshotSessionParam).getTaskList());
} catch (Exception ex) {
log.error("Unexpected Exception occurred when creating snapshot session for consistency group {}", cgUri, ex);
}
}
auditOp(OperationTypeEnum.CREATE_VOLUME_GROUP_SNAPSHOT_SESSION, true, AuditLogManager.AUDITOP_END, volumeGroupId.toString(), name);
return taskList;
}
use of com.emc.storageos.db.client.model.VolumeGroup in project coprhd-controller by CoprHD.
the class VolumeGroupService method getVolumes.
/**
* Get application volumes
*
* @param id Application Id
* @brief List volumes for an application
* @return NamedVolumesList
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/volumes")
public NamedVolumesList getVolumes(@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, VolumeGroup.class, "id");
VolumeGroup volumeGroup = (VolumeGroup) queryResource(id);
NamedVolumesList result = new NamedVolumesList();
List<Volume> volumes = ControllerUtils.getVolumeGroupVolumes(_dbClient, volumeGroup);
for (Volume volume : volumes) {
result.getVolumes().add(toNamedRelatedResource(volume));
}
return result;
}
Aggregations