use of com.emc.storageos.db.client.model.BlockObject in project coprhd-controller by CoprHD.
the class BlockConsistencyGroupService method updateConsistencyGroup.
/**
* Update the specified consistency group
*
* @prereq none
*
* @param id the URN of a ViPR Consistency group
*
* @brief Update consistency group
* @return TaskResourceRep
*/
@PUT
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}")
@CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.OWN, ACL.ALL })
public TaskResourceRep updateConsistencyGroup(@PathParam("id") final URI id, final BlockConsistencyGroupUpdate param) {
// Get the consistency group.
BlockConsistencyGroup consistencyGroup = (BlockConsistencyGroup) queryResource(id);
StorageDriverManager storageDriverManager = (StorageDriverManager) StorageDriverManager.getApplicationContext().getBean(StorageDriverManager.STORAGE_DRIVER_MANAGER);
// Verify a volume was specified to be added or removed.
if (!param.hasEitherAddOrRemoveVolumes()) {
throw APIException.badRequests.noVolumesToBeAddedRemovedFromCG();
}
// TODO require a check if requested list contains all volumes/replicas?
// For replicas, check replica count with volume count in CG
StorageSystem cgStorageSystem = null;
// Throw exception if the operation is attempted on volumes that are in RP CG.
if (consistencyGroup.isRPProtectedCG()) {
throw APIException.badRequests.operationNotAllowedOnRPVolumes();
}
// This method also supports adding volumes or replicas to CG (VMAX - SMIS 8.0.x)
if ((!consistencyGroup.created() || NullColumnValueGetter.isNullURI(consistencyGroup.getStorageController())) && param.hasVolumesToAdd()) {
// we just need to check the case of add volumes in this case
BlockObject bo = BlockObject.fetch(_dbClient, param.getAddVolumesList().getVolumes().get(0));
cgStorageSystem = _permissionsHelper.getObjectById(bo.getStorageController(), StorageSystem.class);
} else {
cgStorageSystem = _permissionsHelper.getObjectById(consistencyGroup.getStorageController(), StorageSystem.class);
}
// IBMXIV, XtremIO, VPlex, VNX, ScaleIO, and VMax volumes only
String systemType = cgStorageSystem.getSystemType();
if (!storageDriverManager.isDriverManaged(cgStorageSystem.getSystemType())) {
if (!systemType.equals(DiscoveredDataObject.Type.vplex.name()) && !systemType.equals(DiscoveredDataObject.Type.vnxblock.name()) && !systemType.equals(DiscoveredDataObject.Type.vmax.name()) && !systemType.equals(DiscoveredDataObject.Type.vnxe.name()) && !systemType.equals(DiscoveredDataObject.Type.unity.name()) && !systemType.equals(DiscoveredDataObject.Type.ibmxiv.name()) && !systemType.equals(DiscoveredDataObject.Type.scaleio.name()) && !systemType.equals(DiscoveredDataObject.Type.xtremio.name())) {
throw APIException.methodNotAllowed.notSupported();
}
}
// Get the specific BlockServiceApiImpl based on the storage system type.
BlockServiceApi blockServiceApiImpl = getBlockServiceImpl(cgStorageSystem);
List<URI> volIds = null;
Set<URI> addSet = new HashSet<URI>();
boolean isReplica = true;
if (param.hasVolumesToAdd()) {
volIds = param.getAddVolumesList().getVolumes();
addSet.addAll(volIds);
URI volId = volIds.get(0);
if (URIUtil.isType(volId, Volume.class)) {
Volume volume = _permissionsHelper.getObjectById(volId, Volume.class);
ArgValidator.checkEntity(volume, volId, false);
if (!BlockFullCopyUtils.isVolumeFullCopy(volume, _dbClient)) {
isReplica = false;
}
}
}
List<Volume> cgVolumes = blockServiceApiImpl.getActiveCGVolumes(consistencyGroup);
// check if add volume list is same as existing volumes in CG
boolean volsAlreadyInCG = false;
if (!isReplica && cgVolumes != null && !cgVolumes.isEmpty()) {
Collection<URI> cgVolIds = transform(cgVolumes, fctnDataObjectToID());
if (addSet.size() == cgVolIds.size()) {
volsAlreadyInCG = addSet.containsAll(cgVolIds);
}
}
// Verify that the add and remove lists do not contain the same volume.
if (param.hasBothAddAndRemoveVolumes()) {
/*
* Make sure the add and remove lists are unique by getting the intersection and
* verifying the size is 0.
*/
Set<URI> removeSet = new HashSet<URI>(param.getRemoveVolumesList().getVolumes());
addSet.retainAll(removeSet);
if (!addSet.isEmpty()) {
throw APIException.badRequests.sameVolumesInAddRemoveList();
}
}
if (cgStorageSystem.getUsingSmis80() && cgStorageSystem.deviceIsType(Type.vmax)) {
// CG can have replicas
if (_log.isDebugEnabled()) {
_log.debug("CG can have replicas for VMAX with SMI-S 8.x");
}
} else if (param.hasVolumesToRemove() || (!isReplica && !volsAlreadyInCG)) {
// CG cannot have replicas when adding/removing volumes to/from CG
// Check snapshots
// Adding/removing volumes to/from a consistency group
// is not supported when the consistency group has active
// snapshots.
URIQueryResultList cgSnapshotsResults = new URIQueryResultList();
_dbClient.queryByConstraint(getBlockSnapshotByConsistencyGroup(id), cgSnapshotsResults);
Iterator<URI> cgSnapshotsIter = cgSnapshotsResults.iterator();
while (cgSnapshotsIter.hasNext()) {
BlockSnapshot cgSnapshot = _dbClient.queryObject(BlockSnapshot.class, cgSnapshotsIter.next());
if ((cgSnapshot != null) && (!cgSnapshot.getInactive())) {
throw APIException.badRequests.notAllowedWhenCGHasSnapshots();
}
}
// VNX group clones and mirrors are just list of replicas, no corresponding group on array side
if (!cgStorageSystem.deviceIsType(Type.vnxblock)) {
// is not supported when existing volumes in CG have mirrors.
if (cgVolumes != null && !cgVolumes.isEmpty()) {
Volume firstVolume = cgVolumes.get(0);
StringSet mirrors = firstVolume.getMirrors();
if (mirrors != null && !mirrors.isEmpty()) {
throw APIException.badRequests.notAllowedWhenCGHasMirrors();
}
}
// Check clones
// Adding/removing volumes to/from a consistency group
// is not supported when the consistency group has
// volumes with full copies to which they are still
// attached or has volumes that are full copies that
// are still attached to their source volumes.
getFullCopyManager().verifyConsistencyGroupCanBeUpdated(consistencyGroup, cgVolumes);
}
}
// Verify the volumes to be removed.
List<URI> removeVolumesList = new ArrayList<URI>();
if (param.hasVolumesToRemove()) {
for (URI volumeURI : param.getRemoveVolumesList().getVolumes()) {
// Validate the volume to be removed exists.
if (URIUtil.isType(volumeURI, Volume.class)) {
Volume volume = _permissionsHelper.getObjectById(volumeURI, Volume.class);
ArgValidator.checkEntity(volume, volumeURI, false);
/**
* Remove SRDF volume from CG is not supported.
*/
if (volume.checkForSRDF()) {
throw APIException.badRequests.notAllowedOnSRDFConsistencyGroups();
}
if (!BlockFullCopyUtils.isVolumeFullCopy(volume, _dbClient)) {
blockServiceApiImpl.verifyRemoveVolumeFromCG(volume, cgVolumes);
}
}
removeVolumesList.add(volumeURI);
}
}
URI xivPoolURI = null;
if (systemType.equals(DiscoveredDataObject.Type.ibmxiv.name()) && !cgVolumes.isEmpty()) {
Volume firstVolume = cgVolumes.get(0);
xivPoolURI = firstVolume.getPool();
}
// Verify the volumes to be added.
List<URI> addVolumesList = new ArrayList<URI>();
List<Volume> volumes = new ArrayList<Volume>();
if (param.hasVolumesToAdd()) {
for (URI volumeURI : param.getAddVolumesList().getVolumes()) {
// Validate the volume to be added exists.
Volume volume = null;
if (!isReplica) {
volume = _permissionsHelper.getObjectById(volumeURI, Volume.class);
ArgValidator.checkEntity(volume, volumeURI, false);
blockServiceApiImpl.verifyAddVolumeToCG(volume, consistencyGroup, cgVolumes, cgStorageSystem);
volumes.add(volume);
} else {
verifyAddReplicaToCG(volumeURI, consistencyGroup, cgStorageSystem);
}
// IBM XIV specific checking
if (systemType.equals(DiscoveredDataObject.Type.ibmxiv.name())) {
// all volumes should be on the same storage pool
if (xivPoolURI == null) {
xivPoolURI = volume.getPool();
} else {
if (!xivPoolURI.equals(volume.getPool())) {
throw APIException.badRequests.invalidParameterIBMXIVConsistencyGroupVolumeNotInPool(volumeURI, xivPoolURI);
}
}
}
// Add the volume to list.
addVolumesList.add(volumeURI);
}
if (!volumes.isEmpty()) {
blockServiceApiImpl.verifyReplicaCount(volumes, cgVolumes, volsAlreadyInCG);
}
}
// Create the task id;
String taskId = UUID.randomUUID().toString();
// Call the block service API to update the consistency group.
return blockServiceApiImpl.updateConsistencyGroup(cgStorageSystem, cgVolumes, consistencyGroup, addVolumesList, removeVolumesList, taskId);
}
use of com.emc.storageos.db.client.model.BlockObject in project coprhd-controller by CoprHD.
the class BlockConsistencyGroupService method verifyAddReplicaToCG.
/**
* Validates the replicas to be added to Consistency group.
* - verifies that the replicas are not internal objects,
* - checks if the given CG is its source volume's CG,
* - validates that the replica is not in any other CG,
* - verifies the project for the replicas to be added is same
* as the project for the consistency group.
*/
private void verifyAddReplicaToCG(URI blockURI, BlockConsistencyGroup cg, StorageSystem cgStorageSystem) {
BlockObject blockObject = BlockObject.fetch(_dbClient, blockURI);
// Don't allow partially ingested object to be added to CG.
BlockServiceUtils.validateNotAnInternalBlockObject(blockObject, false);
URI sourceVolumeURI = null;
URI blockProjectURI = null;
if (blockObject instanceof BlockSnapshot) {
BlockSnapshot snapshot = (BlockSnapshot) blockObject;
blockProjectURI = snapshot.getProject().getURI();
sourceVolumeURI = snapshot.getParent().getURI();
} else if (blockObject instanceof BlockMirror) {
BlockMirror mirror = (BlockMirror) blockObject;
blockProjectURI = mirror.getProject().getURI();
sourceVolumeURI = mirror.getSource().getURI();
} else if (blockObject instanceof Volume) {
Volume volume = (Volume) blockObject;
blockProjectURI = volume.getProject().getURI();
sourceVolumeURI = volume.getAssociatedSourceVolume();
}
// check if the given CG is its source volume's CG
Volume sourceVolume = null;
if (!NullColumnValueGetter.isNullURI(sourceVolumeURI)) {
sourceVolume = _dbClient.queryObject(Volume.class, sourceVolumeURI);
}
if (sourceVolume == null || !cg.getId().equals(sourceVolume.getConsistencyGroup())) {
throw APIException.badRequests.invalidParameterSourceVolumeNotInGivenConsistencyGroup(sourceVolumeURI, cg.getId());
}
// Validate that the replica is not in any other CG.
if (!NullColumnValueGetter.isNullURI(blockObject.getConsistencyGroup()) && !cg.getId().equals(blockObject.getConsistencyGroup())) {
throw APIException.badRequests.invalidParameterVolumeAlreadyInAConsistencyGroup(cg.getId(), blockObject.getConsistencyGroup());
}
// Verify the project for the replicas to be added is same
// as the project for the consistency group.
URI cgProjectURI = cg.getProject().getURI();
if (!blockProjectURI.equals(cgProjectURI)) {
List<Project> projects = _dbClient.queryObjectField(Project.class, "label", Arrays.asList(cgProjectURI, blockProjectURI));
throw APIException.badRequests.consistencyGroupAddVolumeThatIsInDifferentProject(blockObject.getLabel(), projects.get(0).getLabel(), projects.get(1).getLabel());
}
}
use of com.emc.storageos.db.client.model.BlockObject in project coprhd-controller by CoprHD.
the class BlockSnapshotService method queryResource.
@Override
protected BlockObject queryResource(URI id) {
ArgValidator.checkUri(id);
BlockObject blockObj = BlockObject.fetch(_dbClient, id);
ArgValidator.checkEntityNotNull(blockObj, id, isIdEmbeddedInURL(id));
return blockObj;
}
use of com.emc.storageos.db.client.model.BlockObject in project coprhd-controller by CoprHD.
the class ExportGroupService method validateVolumesNotMounted.
/**
* Verify that none of the volumes in the export group are mounted.
* Unexporting a mounted volume is dangerous and should be avoided.
*
* @param exportGroup
* export group
* @param boURIList
* URI list of block objects
*/
private void validateVolumesNotMounted(ExportGroup exportGroup, List<URI> boURIList) {
if (exportGroup == null) {
throw APIException.badRequests.exportGroupContainsMountedVolumesInvalidParam();
}
Map<URI, String> boToLabelMap = new HashMap<>();
// It is valid for there to be no storage volumes in the EG, so only perform the check if there are volumes
if (boURIList != null) {
for (URI boID : boURIList) {
BlockObject bo = BlockObject.fetch(_dbClient, boID);
if (bo != null && bo.getTag() != null) {
ScopedLabelSet tagSet = bo.getTag();
Iterator<ScopedLabel> tagIter = tagSet.iterator();
while (tagIter.hasNext()) {
ScopedLabel sl = tagIter.next();
if (sl.getLabel() != null && (sl.getLabel().startsWith(MOUNTPOINT) || sl.getLabel().startsWith(VMFS_DATASTORE))) {
if (exportGroup.getClusters() != null) {
for (String clusterID : exportGroup.getClusters()) {
if (sl.getLabel().contains(clusterID)) {
boToLabelMap.put(boID, bo.forDisplay());
}
}
}
if (exportGroup.getHosts() != null) {
for (String hostID : exportGroup.getHosts()) {
if (sl.getLabel().contains(hostID)) {
boToLabelMap.put(boID, bo.forDisplay());
}
}
}
}
}
}
}
}
if (!boToLabelMap.isEmpty()) {
_log.error("Export Group {} has volumes {} that are marked as mounted. It is recommended to unmount via controller before unexport. This validation check can be disabled if needed. Contact EMC Support.", exportGroup.getId(), Joiner.on(",").join(boToLabelMap.values()));
ValidatorConfig vc = new ValidatorConfig();
vc.setCoordinator(_coordinator);
if (vc.isValidationEnabled()) {
throw APIException.badRequests.exportGroupContainsMountedVolumes(exportGroup.getId(), Joiner.on(",").join(boToLabelMap.values()));
}
}
}
use of com.emc.storageos.db.client.model.BlockObject in project coprhd-controller by CoprHD.
the class BlockOrchestrationDeviceController method restoreFromFullCopy.
@Override
public void restoreFromFullCopy(URI storage, List<URI> fullCopyURIs, String taskId) throws InternalException {
CloneRestoreCompleter completer = new CloneRestoreCompleter(fullCopyURIs, taskId);
// add the CG to the completer if this is a CG restore
Iterator<Volume> iter = getDbClient().queryIterativeObjects(Volume.class, fullCopyURIs);
while (iter.hasNext()) {
Volume fc = iter.next();
if (!NullColumnValueGetter.isNullURI(fc.getAssociatedSourceVolume())) {
BlockObject firstSource = BlockObject.fetch(getDbClient(), fc.getAssociatedSourceVolume());
if (firstSource != null) {
if (firstSource instanceof Volume && !NullColumnValueGetter.isNullURI(firstSource.getConsistencyGroup())) {
completer.addConsistencyGroupId(firstSource.getConsistencyGroup());
}
break;
}
}
}
s_logger.info("Creating steps for restore from full copy.");
try {
// Validate the volume identities before proceeding
validator.volumeURIs(fullCopyURIs, true, true, ValCk.ID, ValCk.VPLEX);
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, RESTORE_FROM_FULLCOPY_WF_NAME, true, taskId);
// the wait for key returned by previous call
String waitFor = null;
// First, call the RP controller to add RP steps for volume restore
waitFor = _rpDeviceController.addPreRestoreFromFullcopySteps(workflow, waitFor, storage, fullCopyURIs, taskId);
// Call the VplexDeviceController to add its steps for restore volume from full copy
waitFor = _vplexDeviceController.addStepsForRestoreFromFullcopy(workflow, waitFor, storage, fullCopyURIs, taskId, completer);
// Call the BlockDeviceController to add its steps for restore volume from full copy
waitFor = _blockDeviceController.addStepsForRestoreFromFullcopy(workflow, waitFor, storage, fullCopyURIs, taskId, completer);
// Call the RPDeviceController to add its steps for post restore volume from full copy
waitFor = _rpDeviceController.addPostRestoreFromFullcopySteps(workflow, waitFor, storage, fullCopyURIs, taskId);
// Finish up and execute the plan.
// The Workflow will handle the TaskCompleter
String successMessage = "Restore from full copy completed successfully";
Object[] callbackArgs = new Object[] { new ArrayList<URI>(fullCopyURIs) };
workflow.executePlan(completer, successMessage, new WorkflowCallback(), callbackArgs, null, null);
} catch (Exception ex) {
s_logger.error("Could not restore volume: ", ex);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
completer.error(s_dbClient, _locker, serviceError);
}
}
Aggregations