use of com.emc.storageos.db.client.model.StoragePool in project coprhd-controller by CoprHD.
the class BlockVolumeIngestOrchestrator method ingestBlockObjects.
@Override
protected <T extends BlockObject> T ingestBlockObjects(IngestionRequestContext requestContext, Class<T> clazz) throws IngestionException {
UnManagedVolume unManagedVolume = requestContext.getCurrentUnmanagedVolume();
boolean unManagedVolumeExported = requestContext.getVolumeContext().isVolumeExported();
Volume volume = null;
List<BlockSnapshotSession> snapSessions = new ArrayList<BlockSnapshotSession>();
URI unManagedVolumeUri = unManagedVolume.getId();
String volumeNativeGuid = unManagedVolume.getNativeGuid().replace(VolumeIngestionUtil.UNMANAGEDVOLUME, VolumeIngestionUtil.VOLUME);
volume = VolumeIngestionUtil.checkIfVolumeExistsInDB(volumeNativeGuid, _dbClient);
// Check if ingested volume has export masks pending for ingestion.
if (isExportIngestionPending(volume, unManagedVolumeUri, unManagedVolumeExported)) {
return clazz.cast(volume);
}
if (null == volume) {
validateUnManagedVolume(unManagedVolume, requestContext.getVpool(unManagedVolume));
// @TODO Need to revisit this. In 8.x Provider, ReplicationGroup is automatically created when a volume is associated to a
// StorageGroup.
// checkUnManagedVolumeAddedToCG(unManagedVolume, virtualArray, tenant, project, vPool);
checkVolumeExportState(unManagedVolume, unManagedVolumeExported);
checkVPoolValidForExportInitiatorProtocols(requestContext.getVpool(unManagedVolume), unManagedVolume);
checkHostIOLimits(requestContext.getVpool(unManagedVolume), unManagedVolume, unManagedVolumeExported);
StoragePool pool = validateAndReturnStoragePoolInVAarray(unManagedVolume, requestContext.getVarray(unManagedVolume));
// validate quota is exceeded for storage systems and pools
checkSystemResourceLimitsExceeded(requestContext.getStorageSystem(), unManagedVolume, requestContext.getExhaustedStorageSystems());
checkPoolResourceLimitsExceeded(requestContext.getStorageSystem(), pool, unManagedVolume, requestContext.getExhaustedPools());
String autoTierPolicyId = getAutoTierPolicy(unManagedVolume, requestContext.getStorageSystem(), requestContext.getVpool(unManagedVolume));
validateAutoTierPolicy(autoTierPolicyId, unManagedVolume, requestContext.getVpool(unManagedVolume));
volume = createVolume(requestContext, volumeNativeGuid, pool, unManagedVolume, autoTierPolicyId);
}
if (volume != null) {
String syncActive = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.IS_SYNC_ACTIVE.toString(), unManagedVolume.getVolumeInformation());
boolean isSyncActive = (null != syncActive) ? Boolean.parseBoolean(syncActive) : false;
volume.setSyncActive(isSyncActive);
if (VolumeIngestionUtil.isFullCopy(unManagedVolume)) {
_logger.info("Setting clone related properties {}", unManagedVolume.getId());
String replicaState = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.REPLICA_STATE.toString(), unManagedVolume.getVolumeInformation());
volume.setReplicaState(replicaState);
String replicationGroupName = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.FULL_COPY_CONSISTENCY_GROUP_NAME.toString(), unManagedVolume.getVolumeInformation());
if (replicationGroupName != null && !replicationGroupName.isEmpty()) {
volume.setReplicationGroupInstance(replicationGroupName);
}
}
// Create snapshot sessions for each synchronization aspect for the volume.
StringSet syncAspectInfoForVolume = PropertySetterUtil.extractValuesFromStringSet(SupportedVolumeInformation.SNAPSHOT_SESSIONS.toString(), unManagedVolume.getVolumeInformation());
if ((syncAspectInfoForVolume != null) && (!syncAspectInfoForVolume.isEmpty())) {
Project project = requestContext.getProject();
// If this is a vplex backend volume, then the front end project should be set as snapshot session's project
if (requestContext instanceof VplexVolumeIngestionContext && VolumeIngestionUtil.isVplexBackendVolume(unManagedVolume)) {
project = ((VplexVolumeIngestionContext) requestContext).getFrontendProject();
}
for (String syncAspectInfo : syncAspectInfoForVolume) {
String[] syncAspectInfoComponents = syncAspectInfo.split(":");
String syncAspectName = syncAspectInfoComponents[0];
String syncAspectObjPath = syncAspectInfoComponents[1];
// Make sure it is not already created.
URIQueryResultList queryResults = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getBlockSnapshotSessionBySessionInstance(syncAspectObjPath), queryResults);
Iterator<URI> queryResultsIter = queryResults.iterator();
if (!queryResultsIter.hasNext()) {
BlockSnapshotSession session = new BlockSnapshotSession();
session.setId(URIUtil.createId(BlockSnapshotSession.class));
session.setLabel(syncAspectName);
session.setSessionLabel(syncAspectName);
session.setParent(new NamedURI(volume.getId(), volume.getLabel()));
session.setProject(new NamedURI(project.getId(), project.getLabel()));
session.setStorageController(volume.getStorageController());
session.setSessionInstance(syncAspectObjPath);
StringSet linkedTargetURIs = new StringSet();
URIQueryResultList snapshotQueryResults = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getBlockSnapshotBySettingsInstance(syncAspectObjPath), snapshotQueryResults);
Iterator<URI> snapshotQueryResultsIter = snapshotQueryResults.iterator();
while (snapshotQueryResultsIter.hasNext()) {
linkedTargetURIs.add(snapshotQueryResultsIter.next().toString());
}
session.setLinkedTargets(linkedTargetURIs);
session.setOpStatus(new OpStatusMap());
snapSessions.add(session);
}
}
if (!snapSessions.isEmpty()) {
_dbClient.createObject(snapSessions);
}
}
}
// Note that a VPLEX backend volume can also be a snapshot target volume.
// When the VPLEX ingest orchestrator is executed, it gets the ingestion
// strategy for the backend volume and executes it. If the backend volume
// is both a snapshot and a VPLEX backend volume, this local volume ingest
// strategy is invoked and a Volume instance will result. That is fine because
// we need to represent that VPLEX backend volume. However, we also need a
// BlockSnapshot instance to represent the snapshot target volume. Therefore,
// if the unmanaged volume is also a snapshot target volume, we get and
// execute the local snapshot ingest strategy to create this BlockSnapshot
// instance and we add it to the created object list. Note that since the
// BlockSnapshot is added to the created objects list and the Volume and
// BlockSnapshot instance will have the same native GUID, we must be careful
// about adding the Volume to the created object list in the VPLEX ingestion
// strategy.
BlockObject snapshot = null;
if (VolumeIngestionUtil.isSnapshot(unManagedVolume)) {
String strategyKey = ReplicationStrategy.LOCAL.name() + "_" + VolumeType.SNAPSHOT.name();
IngestStrategy ingestStrategy = ingestStrategyFactory.getIngestStrategy(IngestStrategyEnum.getIngestStrategy(strategyKey));
snapshot = ingestStrategy.ingestBlockObjects(requestContext, BlockSnapshot.class);
requestContext.getBlockObjectsToBeCreatedMap().put(snapshot.getNativeGuid(), snapshot);
}
// Run this always when volume NO_PUBLIC_ACCESS
if (markUnManagedVolumeInactive(requestContext, volume)) {
_logger.info("All the related replicas and parent has been ingested ", unManagedVolume.getNativeGuid());
// RP masks.
if (!unManagedVolumeExported && !VolumeIngestionUtil.checkUnManagedResourceIsRecoverPointEnabled(unManagedVolume)) {
unManagedVolume.setInactive(true);
requestContext.getUnManagedVolumesToBeDeleted().add(unManagedVolume);
}
} else if (volume != null) {
_logger.info("Not all the parent/replicas of unManagedVolume {} have been ingested , hence marking as internal", unManagedVolume.getNativeGuid());
volume.addInternalFlags(INTERNAL_VOLUME_FLAGS);
for (BlockSnapshotSession snapSession : snapSessions) {
snapSession.addInternalFlags(INTERNAL_VOLUME_FLAGS);
}
_dbClient.updateObject(snapSessions);
}
return clazz.cast(volume);
}
use of com.emc.storageos.db.client.model.StoragePool in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method prepareVolumeForRequest.
/**
* Prepare a new Bourne volume.
*
* TODO: Use existing function (prepareVolume) when VirtualPool capabilities change
* completed by Stalin. Just pass size instead of getting from VolumeCreate
* parameter.
*
* @param size The volume size.
* @param project A reference to the volume's Project.
* @param neighborhood A reference to the volume's varray.
* @param vpool A reference to the volume's VirtualPool.
* @param storageSystemURI The URI of the volume's storage system.
* @param storagePoolURI The URI of the volume's storage pool.
* @param label The volume label.
* @param token The task id for volume creation.
* @param dbClient A reference to a database client.
*
* @return A reference to the new volume.
*/
public static Volume prepareVolumeForRequest(Long size, Project project, VirtualArray neighborhood, VirtualPool vpool, URI storageSystemURI, URI storagePoolURI, String label, ResourceOperationTypeEnum opType, String token, DbClient dbClient) {
Volume volume = new Volume();
volume.setId(URIUtil.createId(Volume.class));
volume.setLabel(label);
volume.setCapacity(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(neighborhood.getId());
StoragePool storagePool = null;
if (!NullColumnValueGetter.getNullURI().toString().equals(storagePoolURI.toString())) {
storagePool = dbClient.queryObject(StoragePool.class, storagePoolURI);
if (null != storagePool) {
volume.setProtocol(new StringSet());
volume.getProtocol().addAll(VirtualPoolUtil.getMatchingProtocols(vpool.getProtocols(), storagePool.getProtocols()));
}
} else {
// Must be preparing a VPLEX volume which does not
// have a storage pool so a null URI is passed. Set
// the volume protocols to FC.
StringSet protocols = new StringSet();
protocols.add(StorageProtocol.Block.FC.name());
volume.setProtocol(protocols);
}
volume.setStorageController(storageSystemURI);
StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, storageSystemURI);
String systemType = storageSystem.checkIfVmax3() ? DiscoveredDataObject.Type.vmax3.name() : storageSystem.getSystemType();
volume.setSystemType(systemType);
volume.setPool(storagePoolURI);
volume.setOpStatus(new OpStatusMap());
// Set the auto tiering policy.
if (null != vpool.getAutoTierPolicyName()) {
URI autoTierPolicyUri = StorageScheduler.getAutoTierPolicy(storagePoolURI, vpool.getAutoTierPolicyName(), dbClient);
if (null != autoTierPolicyUri) {
volume.setAutoTieringPolicyUri(autoTierPolicyUri);
}
}
if (opType != null) {
Operation op = new Operation();
op.setResourceType(opType);
volume.getOpStatus().createTaskStatus(token, op);
}
dbClient.createObject(volume);
return volume;
}
use of com.emc.storageos.db.client.model.StoragePool in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method verifyTargetSystemsForCGDataMigration.
/**
* Verifies if the valid storage pools for the target vpool specify a single
* target storage system.
*
* @param currentVPool The source vpool for a vpool change
* @param newVPool The target vpool for a vpool change.
* @param srcVarrayURI The virtual array for the volumes being migrated.
*/
private void verifyTargetSystemsForCGDataMigration(List<Volume> volumes, VirtualPool newVPool, URI srcVarrayURI) {
// Determine if the vpool change requires a migration. If the
// new vpool is null, then this is a varray migration and the
// varray is changing. In either case, the valid storage pools
// specified in the target vpool that are tagged to the passed
// varray must specify the same system so that all volumes are
// placed on the same array.
URI tgtSystemURI = null;
URI tgtHASystemURI = null;
for (Volume volume : volumes) {
VirtualPool currentVPool = _dbClient.queryObject(VirtualPool.class, volume.getVirtualPool());
if ((newVPool == null) || (VirtualPoolChangeAnalyzer.vpoolChangeRequiresMigration(currentVPool, newVPool))) {
VirtualPool vPoolToCheck = (newVPool == null ? currentVPool : newVPool);
List<StoragePool> pools = VirtualPool.getValidStoragePools(vPoolToCheck, _dbClient, true);
for (StoragePool pool : pools) {
// are tagged to the virtual array for the volumes being migrated.
if (!pool.getTaggedVirtualArrays().contains(srcVarrayURI.toString())) {
continue;
}
if (tgtSystemURI == null) {
tgtSystemURI = pool.getStorageDevice();
} else if (!tgtSystemURI.equals(pool.getStorageDevice())) {
throw APIException.badRequests.targetVPoolDoesNotSpecifyUniqueSystem();
}
}
}
// The same restriction applies to the target HA virtual pool
// when the HA side is being migrated.
URI haVArrayURI = VirtualPoolChangeAnalyzer.getHaVarrayURI(currentVPool);
if (!NullColumnValueGetter.isNullURI(haVArrayURI)) {
// The HA varray is not null so must be distributed.
VirtualPool currentHAVpool = VirtualPoolChangeAnalyzer.getHaVpool(currentVPool, _dbClient);
VirtualPool newHAVpool = VirtualPoolChangeAnalyzer.getNewHaVpool(currentVPool, newVPool, _dbClient);
if (VirtualPoolChangeAnalyzer.vpoolChangeRequiresMigration(currentHAVpool, newHAVpool)) {
List<StoragePool> haPools = VirtualPool.getValidStoragePools(newHAVpool, _dbClient, true);
for (StoragePool haPool : haPools) {
// tagged to the HA virtual array for the volumes being migrated.
if (!haPool.getTaggedVirtualArrays().contains(haVArrayURI.toString())) {
continue;
}
if (tgtHASystemURI == null) {
tgtHASystemURI = haPool.getStorageDevice();
} else if (!tgtHASystemURI.equals(haPool.getStorageDevice())) {
throw APIException.badRequests.targetHAVPoolDoesNotSpecifyUniqueSystem();
}
}
}
}
}
}
use of com.emc.storageos.db.client.model.StoragePool in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method printMigrationInfo.
/**
* Method for logging for migrations.
*
* @param migration The migration that has been created
* @param sourceVolume The source/original volume to be migrated from (potential to be null for ingested volumes)
* @param targetVolume The target volume to be migrated to
*/
private void printMigrationInfo(Migration migration, Volume sourceVolume, Volume targetVolume) {
StringBuffer migrationInfo = new StringBuffer();
migrationInfo.append("\n+++++++++++++++++++++++++++++++++++++++++++");
migrationInfo.append(String.format("\nPrepared Migration: (%s)", migration.getId()));
if (sourceVolume != null) {
VirtualArray migrationSourceVarray = _dbClient.queryObject(VirtualArray.class, sourceVolume.getVirtualArray());
VirtualPool migrationSourceVpool = _dbClient.queryObject(VirtualPool.class, sourceVolume.getVirtualPool());
StoragePool migrationSourcePool = _dbClient.queryObject(StoragePool.class, sourceVolume.getPool());
StorageSystem migrationSourceStorageSystem = _dbClient.queryObject(StorageSystem.class, sourceVolume.getStorageController());
migrationInfo.append("\nMigration from... ");
migrationInfo.append(String.format("\n\tMigration Source Volume: [%s](%s)", sourceVolume.getLabel(), sourceVolume.getId()));
migrationInfo.append(String.format("\n\tMigration Source Varray: [%s](%s)", migrationSourceVarray.getLabel(), migrationSourceVarray.getId()));
migrationInfo.append(String.format("\n\tMigration Source Vpool: [%s](%s)", migrationSourceVpool.getLabel(), migrationSourceVpool.getId()));
migrationInfo.append(String.format("\n\tMigration Source Pool: [%s](%s)", migrationSourcePool.getLabel(), migrationSourcePool.getId()));
migrationInfo.append(String.format("\n\tMigration Source Storage: [%s](%s)", migrationSourceStorageSystem.getLabel(), migrationSourceStorageSystem.getId()));
}
VirtualArray migrationTargetVarray = _dbClient.queryObject(VirtualArray.class, targetVolume.getVirtualArray());
VirtualPool migrationTargetVpool = _dbClient.queryObject(VirtualPool.class, targetVolume.getVirtualPool());
StoragePool migrationTargetPool = _dbClient.queryObject(StoragePool.class, targetVolume.getPool());
StorageSystem migrationTargetStorageSystem = _dbClient.queryObject(StorageSystem.class, targetVolume.getStorageController());
migrationInfo.append("\nMigration to... ");
migrationInfo.append(String.format("\n\tMigration Target Volume: [%s](%s)", targetVolume.getLabel(), targetVolume.getId()));
migrationInfo.append(String.format("\n\tMigration Target Varray: [%s](%s)", migrationTargetVarray.getLabel(), migrationTargetVarray.getId()));
migrationInfo.append(String.format("\n\tMigration Target Vpool: [%s](%s)", migrationTargetVpool.getLabel(), migrationTargetVpool.getId()));
migrationInfo.append(String.format("\n\tMigration Target Pool: [%s](%s)", migrationTargetPool.getLabel(), migrationTargetPool.getId()));
migrationInfo.append(String.format("\n\tnMigration Target Storage: [%s](%s)", migrationTargetStorageSystem.getLabel(), migrationTargetStorageSystem.getId()));
migrationInfo.append("\n+++++++++++++++++++++++++++++++++++++++++++");
s_logger.info(migrationInfo.toString());
}
use of com.emc.storageos.db.client.model.StoragePool in project coprhd-controller by CoprHD.
the class CapacityUtils method getPoolCapacityMetrics.
/**
* Returns aggregate capacity data for storage pools. Capacity is returned
* in the same unit as it was discovered and stored in storage pools (KB).
* Calculation is using BigInteger type to prevent overflow.
*
* @param storagePools storage pools
* @param DbClient dbClient
* @param VirtualPool vPool
* @return map of capacity metrics
* @throws ServiceCodeException
*/
private static Map<String, BigInteger> getPoolCapacityMetrics(List<StoragePool> storagePools, VirtualPool vPool, DbClient dbClient, CoordinatorClient coordinator) {
BigInteger totalCapacity = BigInteger.ZERO;
BigInteger freeCapacity = BigInteger.ZERO;
BigInteger subscribedCapacity = BigInteger.ZERO;
BigInteger netFreeCapacity = BigInteger.ZERO;
Map<String, BigInteger> capacityMetrics = new HashMap<String, BigInteger>();
if (storagePools == null || storagePools.isEmpty()) {
_log.warn("There are no pools passed to this method. Returning zero capacity metrics.");
capacityMetrics.put(StorageMetrics.USABLE.toString(), totalCapacity);
capacityMetrics.put(StorageMetrics.FREE.toString(), freeCapacity);
capacityMetrics.put(StorageMetrics.SUBSCRIBED.toString(), subscribedCapacity);
capacityMetrics.put(StorageMetrics.NET_FREE.toString(), netFreeCapacity);
return capacityMetrics;
}
// Cache of sharedStorageCapacity flags of storage systems
// The flag means if all storage pools share the same capacity
Map<String, Boolean> storageSharedFlags = new HashMap<String, Boolean>();
for (StoragePool storagePool : storagePools) {
if (storagePool.getTotalCapacity() == 0) {
_log.error("Storage pool: {} has zero total capacity, skipping the pool.", storagePool.getId().toString());
continue;
}
String storageDeviceId = storagePool.getStorageDevice().toString();
if (!storageSharedFlags.containsKey(storageDeviceId)) {
StorageSystem system = dbClient.queryObject(StorageSystem.class, storagePool.getStorageDevice());
storageSharedFlags.put(storageDeviceId, system.getSharedStorageCapacity());
} else if (storageSharedFlags.get(storageDeviceId).booleanValue()) {
// Skip current pool
continue;
}
totalCapacity = totalCapacity.add(BigInteger.valueOf(storagePool.getTotalCapacity()));
freeCapacity = freeCapacity.add(BigInteger.valueOf(storagePool.getFreeCapacity()));
long usedPoolCapacity = storagePool.getTotalCapacity() - storagePool.getFreeCapacity();
long subscribedPoolCapacity = 0;
long netFreeSubscription = 0;
boolean isBlock = VirtualPool.Type.block.name().equalsIgnoreCase(vPool.getType());
// calculate subscribed capacity only for block CoS
if (isBlock) {
subscribedPoolCapacity = storagePool.getSubscribedCapacity();
if (storagePool.getSubscribedCapacity() < 0) {
// device pool
subscribedPoolCapacity = usedPoolCapacity;
}
subscribedCapacity = subscribedCapacity.add(BigInteger.valueOf(subscribedPoolCapacity));
// 3) for thin pools check thin Pool Subscription percentage
double maxSubscribedPercentage = CapacityMatcher.getMaxPoolSubscriptionPercentage(storagePool, coordinator);
long poolMaximumSubscribedCapacity = (long) (storagePool.getTotalCapacity() * maxSubscribedPercentage / 100);
netFreeSubscription = poolMaximumSubscribedCapacity - subscribedPoolCapacity;
} else {
// if isFile
// For the file system we do not have information on its subscribe limit.
// Instead we used all available capacity as its netSubscription for thin provisioning.
netFreeSubscription = storagePool.getTotalCapacity() - usedPoolCapacity;
}
// 1) Check that the maximum resource limit is not reached for the pool or the storage system
if (MaxResourcesMatcher.checkPoolMaximumResourcesApproached(storagePool, dbClient, 0)) {
// ignore this pool, it does not contain any net free capacity
continue;
}
// 2) Check against Maximum Utilizaiton Percentage
double maxPoolUtilizationPercentage = CapacityMatcher.getMaxPoolUtilizationPercentage(storagePool, coordinator);
long poolMaximumCapacity = (long) (storagePool.getTotalCapacity() * maxPoolUtilizationPercentage / 100);
long netFreeUtilization = poolMaximumCapacity - usedPoolCapacity;
if (netFreeUtilization < 0) {
// ignore this pool
continue;
}
// THICK virtual pool
if (VirtualPool.ProvisioningType.Thick.name().equals(vPool.getSupportedProvisioningType())) {
netFreeCapacity = netFreeCapacity.add(BigInteger.valueOf(netFreeUtilization));
} else {
// 3) Check against Maximum Subscription. Ignore if it pool is oversubscribed.
if (netFreeSubscription > 0) {
netFreeCapacity = netFreeCapacity.add(BigInteger.valueOf(netFreeSubscription));
}
// else ignore.
}
}
capacityMetrics.put(StorageMetrics.USABLE.toString(), totalCapacity);
capacityMetrics.put(StorageMetrics.FREE.toString(), freeCapacity);
capacityMetrics.put(StorageMetrics.SUBSCRIBED.toString(), subscribedCapacity);
capacityMetrics.put(StorageMetrics.NET_FREE.toString(), netFreeCapacity);
return capacityMetrics;
}
Aggregations