/*
* Copyright (c) 2008-2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service.impl.resource.blockingestorchestration;
import java.net.URI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.IngestionRequestContext;
import com.emc.storageos.api.service.impl.resource.utils.PropertySetterUtil;
import com.emc.storageos.api.service.impl.resource.utils.VolumeIngestionUtil;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.constraint.AlternateIdConstraint;
import com.emc.storageos.db.client.constraint.URIQueryResultList;
import com.emc.storageos.db.client.model.BlockMirror;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.Project;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StringSetMap;
import com.emc.storageos.db.client.model.VirtualArray;
import com.emc.storageos.db.client.model.VirtualPool;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume.SupportedVolumeInformation;
public class BlockMirrorIngestOrchestrator extends BlockIngestOrchestrator {
private static final Logger logger = LoggerFactory.getLogger(BlockMirrorIngestOrchestrator.class);
@Override
public <T extends BlockObject> T ingestBlockObjects(IngestionRequestContext requestContext, Class<T> clazz)
throws IngestionException {
UnManagedVolume unManagedVolume = requestContext.getCurrentUnmanagedVolume();
boolean unManagedVolumeExported = requestContext.getVolumeContext().isVolumeExported();
// Validate the unManagedVolume properties
validateUnManagedVolume(unManagedVolume, requestContext.getVpool(unManagedVolume));
validateParentNotRpProtected(unManagedVolume);
// Check whether mirror already ingested or not.
String mirrorNativeGuid = unManagedVolume.getNativeGuid().replace(VolumeIngestionUtil.UNMANAGEDVOLUME,
VolumeIngestionUtil.VOLUME);
BlockMirror mirrorObj = VolumeIngestionUtil.checkIfBlockMirrorExistsInDB(mirrorNativeGuid, _dbClient);
// Check if ingested volume has exportmasks pending for ingestion.
if (isExportIngestionPending(mirrorObj, unManagedVolume.getId(), unManagedVolumeExported)) {
return clazz.cast(mirrorObj);
}
if (null == mirrorObj) {
mirrorObj = createBlockMirror(mirrorNativeGuid, requestContext.getStorageSystem(), unManagedVolume,
requestContext.getVpool(unManagedVolume), requestContext.getVarray(unManagedVolume), requestContext.getProject());
}
// Run this always when the volume is NO_PUBLIC_ACCESS
if (markUnManagedVolumeInactive(requestContext, mirrorObj)) {
logger.info("Marking UnManaged Volume {} as inactive, all the related replicas and parent has been ingested",
unManagedVolume.getNativeGuid());
// mark inactive if this is not to be exported. Else, mark as inactive after successful export
if (!unManagedVolumeExported) {
unManagedVolume.setInactive(true);
requestContext.getUnManagedVolumesToBeDeleted().add(unManagedVolume);
}
} else {
logger.info("Not all the parent/replicas of unManagedVolume {} have been ingested , hence marking as internal",
unManagedVolume.getNativeGuid());
mirrorObj.addInternalFlags(INTERNAL_VOLUME_FLAGS);
}
return clazz.cast(mirrorObj);
}
/**
* ViPR doesn't support creating mirrors off RP protected volumes. So check if the mirror to be ingested has RP
* protected parent. If yes, throw an ingestion exception
*
* @param unManagedVolume
*/
private void validateParentNotRpProtected(UnManagedVolume unManagedVolume) {
String parentNativeGUID = null;
StringSetMap unManagedVolumeInformation = unManagedVolume.getVolumeInformation();
if (unManagedVolumeInformation.containsKey(SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.toString())) {
parentNativeGUID = PropertySetterUtil.extractValueFromStringSet(
SupportedVolumeInformation.LOCAL_REPLICA_SOURCE_VOLUME.toString(),
unManagedVolumeInformation);
} else if (unManagedVolumeInformation.containsKey(SupportedVolumeInformation.VPLEX_PARENT_VOLUME.toString())) {
parentNativeGUID = PropertySetterUtil.extractValueFromStringSet(
SupportedVolumeInformation.VPLEX_PARENT_VOLUME.toString(),
unManagedVolumeInformation);
}
if (parentNativeGUID != null) {
logger.info("Finding unmanagedvolume {} in vipr db", parentNativeGUID);
URIQueryResultList umvUriList = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory
.getVolumeInfoNativeIdConstraint(parentNativeGUID), umvUriList);
if (umvUriList.iterator().hasNext()) {
logger.info("Found unmanagedvolume {} in vipr db", parentNativeGUID);
URI umvUri = umvUriList.iterator().next();
UnManagedVolume parentUnManagedVolume = _dbClient.queryObject(UnManagedVolume.class, umvUri);
if (parentUnManagedVolume != null && VolumeIngestionUtil.checkUnManagedResourceIsRecoverPointEnabled(parentUnManagedVolume)) {
logger.warn("Unmanaged mirror {} has RP protected parent", unManagedVolume.getLabel());
throw IngestionException.exceptions.cannotIngestMirrorsOfRPVolumes(unManagedVolume.getLabel(),
parentUnManagedVolume.getLabel());
}
} else {
// the parent might already be ingested in the vipr db.
logger.info("Finding managed volume in vipr db corresponding to {}", parentNativeGUID);
BlockObject parentObject = VolumeIngestionUtil.getBlockObject(parentNativeGUID.replace(VolumeIngestionUtil.UNMANAGEDVOLUME,
VolumeIngestionUtil.VOLUME), _dbClient);
if (parentObject != null && BlockObject.checkForRP(_dbClient, parentObject.getId())) {
logger.warn("Unmanaged mirror {} has RP protected parent", unManagedVolume.getLabel());
throw IngestionException.exceptions.cannotIngestMirrorsOfRPVolumes(unManagedVolume.getLabel(),
parentObject.getLabel());
}
}
}
}
/**
* Create block Mirror object from the UnManagedVolume object.
*
* @param unManagedVolume
* @param system
* @param volume
* @return
*/
private BlockMirror createBlockMirror(String nativeGuid, StorageSystem system, UnManagedVolume unManagedVolume,
VirtualPool vPool, VirtualArray vArray, Project project) {
BlockMirror mirror = new BlockMirror();
mirror.setId(URIUtil.createId(BlockMirror.class));
mirror.setInactive(false);
StoragePool pool = _dbClient.queryObject(StoragePool.class, unManagedVolume.getStoragePoolUri());
updateVolume(mirror, system, nativeGuid, pool, vArray, vPool, unManagedVolume, project);
String syncInstance = PropertySetterUtil.extractValueFromStringSet(
SupportedVolumeInformation.SYNCHRONIZED_INSTANCE.toString(),
unManagedVolume.getVolumeInformation());
mirror.setSynchronizedInstance(syncInstance);
String syncState = PropertySetterUtil.extractValueFromStringSet(
SupportedVolumeInformation.SYNC_STATE.toString(), unManagedVolume.getVolumeInformation());
mirror.setSyncState(syncState);
String syncType = PropertySetterUtil.extractValueFromStringSet(
SupportedVolumeInformation.SYNC_TYPE.toString(), unManagedVolume.getVolumeInformation());
mirror.setSyncType(syncType);
String autoTierPolicyId = getAutoTierPolicy(unManagedVolume, system, vPool);
validateAutoTierPolicy(autoTierPolicyId, unManagedVolume, vPool);
if (null != autoTierPolicyId) {
updateTierPolicyProperties(autoTierPolicyId, mirror);
}
return mirror;
}
}