use of com.emc.storageos.vplex.api.VPlexDeviceInfo in project coprhd-controller by CoprHD.
the class VplexVolumeValidator method validateVolume.
/**
* Validates an individual volume.
*
* @param virtualVolume the Volume to validate
* @param delete boolean indicating if this validation is part of a delete operation
* @param remediate boolean indicating whether or not remediation should be attempted
* @param checks variable list of ValCks
*/
public void validateVolume(Volume virtualVolume, boolean delete, boolean remediate, ValCk... checks) {
List<ValCk> checkList = Arrays.asList(checks);
String volumeId = String.format("%s (%s)(%s)", virtualVolume.getLabel(), virtualVolume.getNativeGuid(), virtualVolume.getId());
log.info("Initiating Vplex Volume validation: " + volumeId);
VPlexVirtualVolumeInfo vvinfo = null;
try {
vvinfo = client.findVirtualVolume(virtualVolume.getDeviceLabel(), virtualVolume.getNativeId());
} catch (VPlexApiException ex) {
log.info(ex.getMessage());
}
if (vvinfo == null) {
try {
// Didn't find the virtual volume. Look at the storage volume, and from that determine
// the deviceName. Then lookup the Device or DistributedDevice and check to see if
// the device has been reassigned to a different virtual volume.
Volume storageVolume = VPlexUtil.getVPLEXBackendVolume(virtualVolume, true, getDbClient(), false);
if (storageVolume != null) {
StorageSystem system = getDbClient().queryObject(StorageSystem.class, storageVolume.getStorageController());
// Look up the corresponding device name to our Storage Volume
VolumeInfo volumeInfo = new VolumeInfo(system.getNativeGuid(), system.getSystemType(), storageVolume.getWWN().toUpperCase().replaceAll(":", ""), storageVolume.getNativeId(), storageVolume.getThinlyProvisioned().booleanValue(), VPlexControllerUtils.getVolumeITLs(storageVolume));
String deviceName = client.getDeviceForStorageVolume(volumeInfo);
log.info("device name is " + deviceName);
if (deviceName == null) {
if (!delete) {
// We didn't find a device name for the storage volume. Error if not deleting.
getValidatorLogger().logDiff(volumeId, "Vplex device-name", system.getSerialNumber() + "-" + storageVolume.getNativeId(), ValidatorLogger.NO_MATCHING_ENTRY);
return;
}
}
if (null != deviceName && !deviceName.trim().matches(VPlexApiConstants.STORAGE_VOLUME_NOT_IN_USE)) {
String volumeType = VPlexApiConstants.LOCAL_VIRTUAL_VOLUME;
if (virtualVolume.getAssociatedVolumes() != null && virtualVolume.getAssociatedVolumes().size() > 1) {
volumeType = VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME;
}
VPlexResourceInfo resourceInfo = client.getDeviceStructure(deviceName, volumeType);
if (resourceInfo instanceof VPlexDeviceInfo) {
// local device
VPlexDeviceInfo localDeviceInfo = (VPlexDeviceInfo) resourceInfo;
String virtualVolumeName = localDeviceInfo.getVirtualVolume();
if (virtualVolumeName != null && !virtualVolumeName.equals(virtualVolume.getDeviceLabel())) {
getValidatorLogger().logDiff(volumeId, "virtual-volume name changed", virtualVolume.getDeviceLabel(), virtualVolumeName);
}
} else if (resourceInfo instanceof VPlexDistributedDeviceInfo) {
VPlexDistributedDeviceInfo distDeviceInfo = (VPlexDistributedDeviceInfo) resourceInfo;
String virtualVolumeName = distDeviceInfo.getVirtualVolume();
if (virtualVolumeName != null && !virtualVolumeName.equals(virtualVolume.getDeviceLabel())) {
getValidatorLogger().logDiff(volumeId, "virtual-volume name changed", virtualVolume.getDeviceLabel(), virtualVolumeName);
}
}
}
}
} catch (VPlexApiException ex) {
log.error("Unable to determine if VPLEX device reused: " + volumeId, ex);
if (getValidatorConfig().isValidationEnabled()) {
throw ex;
}
}
if (!delete) {
// If we didn't log an error above indicating that the volume was reused,
// and we are not deleting, it is still an error.
// If we are deleting we won't error if it's just not there.
getValidatorLogger().logDiff(volumeId, "virtual-volume", virtualVolume.getDeviceLabel(), ValidatorLogger.NO_MATCHING_ENTRY);
}
log.info("Vplex Validation complete (no vvinfo found); " + volumeId);
return;
}
if (checkList.contains(ValCk.ID)) {
if (!virtualVolume.getDeviceLabel().equals(vvinfo.getName())) {
getValidatorLogger().logDiff(volumeId, "native-id", virtualVolume.getNativeId(), vvinfo.getName());
}
if (!NullColumnValueGetter.isNullValue(virtualVolume.getWWN()) && vvinfo.getWwn() != null && !virtualVolume.getWWN().equalsIgnoreCase(vvinfo.getWwn())) {
getValidatorLogger().logDiff(volumeId, "wwn", virtualVolume.getWWN(), vvinfo.getWwn());
}
if (virtualVolume.getAssociatedVolumes() != null && !virtualVolume.getAssociatedVolumes().isEmpty()) {
String locality = virtualVolume.getAssociatedVolumes().size() > 1 ? VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME : VPlexApiConstants.LOCAL_VIRTUAL_VOLUME;
if (!locality.equalsIgnoreCase(vvinfo.getLocality())) {
getValidatorLogger().logDiff(volumeId, "locality", locality, vvinfo.getLocality());
}
}
}
if (checkList.contains(ValCk.VPLEX) && !virtualVolume.isIngestedVolumeWithoutBackend(getDbClient())) {
try {
String drillDownInfo = client.getDrillDownInfoForDevice(vvinfo.getSupportingDevice());
VPlexDrillDownParser parser = new VPlexDrillDownParser(drillDownInfo);
VPlexDrillDownParser.Node root = parser.parse();
boolean distributed = (root.getType() == VPlexDrillDownParser.NodeType.DIST) ? true : false;
if (distributed) {
List<VPlexDrillDownParser.Node> svols = root.getNodesOfType(NodeType.SVOL);
boolean hasMirror = svols.size() > 2;
String clusterName = VPlexControllerUtils.getVPlexClusterName(getDbClient(), virtualVolume);
for (VPlexDrillDownParser.Node child : root.getChildren()) {
if (child.getArg2().equals(clusterName)) {
validateStorageVolumes(virtualVolume, volumeId, root.getArg1(), true, child.getArg2(), hasMirror);
}
}
} else {
List<VPlexDrillDownParser.Node> svols = root.getNodesOfType(NodeType.SVOL);
boolean hasMirror = svols.size() > 1;
validateStorageVolumes(virtualVolume, volumeId, root.getArg1(), false, root.getArg2(), hasMirror);
}
} catch (Exception ex) {
getValidatorLogger().logDiff(volumeId, "exception trying to validate storage volumes", virtualVolume.getDeviceLabel(), "N/A");
}
}
log.info("Vplex Validation complete; " + volumeId);
}
use of com.emc.storageos.vplex.api.VPlexDeviceInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method migrationSupportedForVolume.
/**
* Determines if the controller can support migration for the passed VPLEX volume.
*
* @param volume
* A reference to a VPLEX volume.
* @param varrayURI
* A reference to a varray or null.
*
* @return true if migration is supported, false otherwise.
*/
public static boolean migrationSupportedForVolume(Volume volume, URI varrayURI, DbClient dbClient) {
boolean supported = true;
// Migration is supported for all volumes that were not ingested.
if (volume.isIngestedVolumeWithoutBackend(dbClient)) {
VirtualPool vpool = dbClient.queryObject(VirtualPool.class, volume.getVirtualPool());
// Migration is supported for all local volumes.
if (VirtualPool.HighAvailabilityType.vplex_distributed.name().equals(vpool.getHighAvailability())) {
StorageSystem vplexSystem = dbClient.queryObject(StorageSystem.class, volume.getStorageController());
try {
VPlexApiFactory apiFactory = VPlexApiFactory.getInstance();
VPlexApiClient client = getVPlexAPIClient(apiFactory, vplexSystem, dbClient);
VPlexVirtualVolumeInfo vvInfo = client.getVirtualVolumeStructure(volume.getDeviceLabel());
VPlexDistributedDeviceInfo ddInfo = (VPlexDistributedDeviceInfo) vvInfo.getSupportingDeviceInfo();
List<VPlexDeviceInfo> localDeviceInfoList = ddInfo.getLocalDeviceInfo();
for (VPlexDeviceInfo localDeviceInfo : localDeviceInfoList) {
_log.info("localDeviceInfo: {}, {}", localDeviceInfo.getName(), localDeviceInfo.getCluster());
// the passed varray.
if (varrayURI != null) {
_log.info("varrayURI:{}", varrayURI);
String varrayCluster = ConnectivityUtil.getVplexClusterForVarray(varrayURI, vplexSystem.getId(), dbClient);
_log.info("varrayCluster:{}", varrayCluster);
if (!localDeviceInfo.getCluster().contains(varrayCluster)) {
continue;
}
}
// For distributed volumes, the local device must be built
// on a single extent.
_log.info("Local device: {}", localDeviceInfo.getName());
_log.info("Extent count: {}", localDeviceInfo.getExtentInfo().size());
if (localDeviceInfo.getExtentInfo().size() != 1) {
supported = false;
break;
}
}
} catch (VPlexApiException vae) {
_log.error("Exception checking if migration supported for volume:", vae);
throw vae;
} catch (Exception ex) {
_log.error("Exception checking if migration supported for volume", ex);
throw VPlexApiException.exceptions.failedGettingMigrationSupportedForVolume(vplexSystem.getId().toString(), volume.getLabel());
}
}
}
return supported;
}
use of com.emc.storageos.vplex.api.VPlexDeviceInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method createMirrors.
/**
* Do the creation of a VPlex Mirror device and attach it as a mirror to the Virtual Volume.
* This is called as a Workflow Step.
* NOTE: The parameters here must match createMirrorsMethod above (except stepId).
*
* @param vplexURI
* URI of the VPlex StorageSystem
* @param vplexMirrorURIs
* URI of the mirrors to be created.
* @param workflowTaskId
* The workflow taskId.
* @param stepId
* The stepId used for completion.
*
* @throws WorkflowException
* When an error occurs updating the workflow step
* state.
*/
public void createMirrors(URI vplexURI, List<URI> vplexMirrorURIs, String workflowTaskId, String stepId) throws WorkflowException {
List<VolumeInfo> rollbackData = new ArrayList<VolumeInfo>();
List<URI> createdVplexMirrorURIs = new ArrayList<URI>();
VplexMirrorTaskCompleter completer = new VplexMirrorTaskCompleter(VplexMirror.class, vplexMirrorURIs, workflowTaskId);
try {
WorkflowStepCompleter.stepExecuting(stepId);
// Get the API client.
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
// Make a map of StorageSystem ids to Storage System
Map<URI, StorageSystem> storageMap = new HashMap<URI, StorageSystem>();
// Make a map of Mirrors to Storage Volumes.
Map<VplexMirror, Volume> mirrorMap = new HashMap<VplexMirror, Volume>();
for (URI vplexMirrorURI : vplexMirrorURIs) {
VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
// Find the underlying Storage Volume, there will be only one associated storage volume
for (String associatedVolume : vplexMirror.getAssociatedVolumes()) {
Volume storageVolume = getDataObject(Volume.class, new URI(associatedVolume), _dbClient);
URI storageSystemId = storageVolume.getStorageController();
if (storageMap.containsKey(storageSystemId) == false) {
StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageSystemId);
storageMap.put(storageSystemId, storage);
}
mirrorMap.put(vplexMirror, storageVolume);
}
}
// Now make a call to the VPlexAPIClient.createDeviceAndAttachAsMirror for each vplex mirror.
StringBuilder buf = new StringBuilder();
buf.append("Vplex: " + vplexURI + " created mirror(s): ");
for (VplexMirror vplexMirror : mirrorMap.keySet()) {
URI vplexMirrorId = vplexMirror.getId();
Volume sourceVplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
VPlexVirtualVolumeInfo vplexVolumeInfo = new VPlexVirtualVolumeInfo();
vplexVolumeInfo.setName(sourceVplexVolume.getDeviceLabel());
vplexVolumeInfo.setPath(sourceVplexVolume.getNativeId());
if (null == sourceVplexVolume.getAssociatedVolumes() || sourceVplexVolume.getAssociatedVolumes().isEmpty()) {
_log.error("VPLEX volume {} has no backend volumes.", sourceVplexVolume.forDisplay());
throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(sourceVplexVolume.forDisplay());
}
if (sourceVplexVolume.getAssociatedVolumes().size() > 1) {
vplexVolumeInfo.setLocality(VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME);
} else {
vplexVolumeInfo.setLocality(VPlexApiConstants.LOCAL_VIRTUAL_VOLUME);
}
_log.info(String.format("Creating mirror: %s (%s)", vplexMirror.getLabel(), vplexMirrorId));
Volume storageVolume = mirrorMap.get(vplexMirror);
long totalProvisioned = storageVolume.getProvisionedCapacity();
StorageSystem storage = storageMap.get(storageVolume.getStorageController());
List<String> itls = VPlexControllerUtils.getVolumeITLs(storageVolume);
VolumeInfo vinfo = new VolumeInfo(storage.getNativeGuid(), storage.getSystemType(), storageVolume.getWWN().toUpperCase().replaceAll(":", ""), storageVolume.getNativeId(), storageVolume.getThinlyProvisioned().booleanValue(), itls);
// Update rollback information.
rollbackData.add(vinfo);
List<VolumeInfo> vinfos = new ArrayList<VolumeInfo>();
vinfos.add(vinfo);
_workflowService.storeStepData(stepId, rollbackData);
// Make the call to create device and attach it as mirror to the source virtual volume device.
VPlexDeviceInfo vInfo = client.createDeviceAndAttachAsMirror(vplexVolumeInfo, vinfos, true, false);
buf.append(vInfo.getName() + " ");
_log.info(String.format("Created mirror : %s path: %s : for virtual volume %s device label %s", vInfo.getName(), vInfo.getPath(), sourceVplexVolume.getLabel(), sourceVplexVolume.getDeviceLabel()));
vplexMirror.setNativeId(vInfo.getPath());
vplexMirror.setDeviceLabel(vInfo.getName());
// For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
vplexMirror.setAllocatedCapacity(0L);
vplexMirror.setProvisionedCapacity(totalProvisioned);
if (vplexVolumeInfo.isThinEnabled() != sourceVplexVolume.getThinlyProvisioned()) {
_log.info("Thin provisioned setting changed after mirror operation to " + vplexVolumeInfo.isThinEnabled());
sourceVplexVolume.setThinlyProvisioned(vplexVolumeInfo.isThinEnabled());
_dbClient.updateObject(sourceVplexVolume);
}
vplexMirror.setThinlyProvisioned(vplexVolumeInfo.isThinEnabled());
_dbClient.updateObject(vplexMirror);
// Record VPLEX volume created event.
createdVplexMirrorURIs.add(vplexMirrorId);
recordBourneVplexMirrorEvent(vplexMirrorId, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(true), Operation.Status.ready, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
}
completer.ready(_dbClient);
WorkflowStepCompleter.stepSucceded(stepId);
} catch (VPlexApiException vae) {
_log.error("Exception creating Mirror for the Virtual Volume: " + vae.getMessage(), vae);
// not created.
for (URI vplexMirrorURI : vplexMirrorURIs) {
if (!createdVplexMirrorURIs.contains(vplexMirrorURI)) {
recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(false), Operation.Status.error, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
}
}
failStep(completer, stepId, vae);
} catch (Exception ex) {
_log.error("Exception creating Mirror for the Virtual Volume: " + ex.getMessage(), ex);
// not created.
for (URI vplexMirrorURI : vplexMirrorURIs) {
if (!createdVplexMirrorURIs.contains(vplexMirrorURI)) {
recordBourneVplexMirrorEvent(vplexMirrorURI, OperationTypeEnum.CREATE_VOLUME_MIRROR.getEvType(false), Operation.Status.error, OperationTypeEnum.CREATE_VOLUME_MIRROR.getDescription());
}
}
ServiceError serviceError = VPlexApiException.errors.createMirrorsFailed(ex);
failStep(completer, stepId, serviceError);
}
}
use of com.emc.storageos.vplex.api.VPlexDeviceInfo in project coprhd-controller by CoprHD.
the class VplexBackendIngestionContext method getMirrorMap.
/**
* Creates a Map of cluster name to sorted Map of slot numbers to VPlexDeviceInfos
* for use in describing the layout of VPLEX native mirrors.
*
* @return a Map of cluster id to sorted Map of slot numbers to VPlexDeviceInfos
*/
private Map<String, Map<String, VPlexDeviceInfo>> getMirrorMap() {
if (null != mirrorMap) {
return mirrorMap;
}
// the mirror map is a mapping of:
//
// cluster id (e.g., cluster-1 and cluster-2) to:
// a sorted map of device slot-number to:
// the VPlexDeviceInfo in that slot
// sort of like: Map<ClusterName, Map<SlotNumber, VPlexDeviceInfo>>
//
// if distributed, it assumes only one mirror set
// can be present on each side of the vplex
_logger.info("assembling mirror map");
mirrorMap = new HashMap<String, Map<String, VPlexDeviceInfo>>();
VPlexResourceInfo device = getTopLevelDevice();
if (isLocal() && (device instanceof VPlexDeviceInfo)) {
VPlexDeviceInfo localDevice = ((VPlexDeviceInfo) device);
if (VPlexApiConstants.ARG_GEOMETRY_RAID1.equals(((VPlexDeviceInfo) device).getGeometry())) {
mirrorMap.put(localDevice.getCluster(), mapDevices(localDevice));
}
} else {
for (VPlexDeviceInfo localDevice : ((VPlexDistributedDeviceInfo) device).getLocalDeviceInfo()) {
if (VPlexApiConstants.ARG_GEOMETRY_RAID1.equals(((VPlexDistributedDeviceInfo) device).getGeometry())) {
mirrorMap.put(localDevice.getCluster(), mapDevices(localDevice));
}
}
}
_logger.info("mirror map is: " + mirrorMap);
return mirrorMap;
}
use of com.emc.storageos.vplex.api.VPlexDeviceInfo in project coprhd-controller by CoprHD.
the class VplexBackendIngestionContext method getUnmanagedVplexMirrors.
/**
* Returns a Map of UnManagedVolume objects that are parts
* of a VplexMirror to their device context path from the
* VPLEX API.
*
* @return a map of UnManagedVolume to device context paths
*/
public Map<UnManagedVolume, String> getUnmanagedVplexMirrors() {
if (null != unmanagedMirrors) {
return unmanagedMirrors;
}
if (!isDiscoveryInProgress()) {
// first check the database for this unmanaged volume's backend mirrors
StringSet mirrorMapFromTheDatabase = extractValuesFromStringSet(SupportedVolumeInformation.VPLEX_MIRROR_MAP.toString(), _unmanagedVirtualVolume.getVolumeInformation());
if (null != mirrorMapFromTheDatabase && !mirrorMapFromTheDatabase.isEmpty()) {
_logger.info("fetching mirror map from database");
for (String mirrorEntry : mirrorMapFromTheDatabase) {
// extract 'n' parse the mirror info from the database
// pair[0] is the native id of the mirror
// pair[1] is the device context path from the VPLEX API
String[] pair = mirrorEntry.split("=");
UnManagedVolume mirrorVolume = null;
String contextPath = pair[1];
// find the mirror UnManagedVolume object
URIQueryResultList unManagedVolumeList = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getVolumeInfoNativeIdConstraint(pair[0]), unManagedVolumeList);
if (unManagedVolumeList.iterator().hasNext()) {
mirrorVolume = _dbClient.queryObject(UnManagedVolume.class, unManagedVolumeList.iterator().next());
}
// add to the map that will be returned from this method
if (null != mirrorVolume && null != contextPath) {
if (null == unmanagedMirrors) {
unmanagedMirrors = new HashMap<UnManagedVolume, String>();
}
unmanagedMirrors.put(mirrorVolume, contextPath);
// now remove the mirror from the list of regular backend volumes
// so that it won't be ingested that way
Iterator<UnManagedVolume> itr = getUnmanagedBackendVolumes().iterator();
while (itr.hasNext()) {
if (mirrorVolume.getId().toString().equals(itr.next().getId().toString())) {
itr.remove();
}
}
}
}
if (null != unmanagedMirrors && !unmanagedMirrors.isEmpty()) {
_logger.info("found mirror map: " + unmanagedMirrors);
return unmanagedMirrors;
}
}
}
unmanagedMirrors = new HashMap<UnManagedVolume, String>();
// to check for native mirrors
if (!_shouldCheckForMirrors) {
return unmanagedMirrors;
}
// if we're in discovery only mode, don't check again during ingestion
if (isIngestionInProgress() && isInDiscoveryOnlyMode()) {
return unmanagedMirrors;
}
// if the mirror map couldn't be found in the database,
// we will query the VPLEX API for this information
long start = System.currentTimeMillis();
_logger.info("getting unmanaged mirrors");
if (!getMirrorMap().isEmpty()) {
for (Entry<String, Map<String, VPlexDeviceInfo>> mirrorMapEntry : getMirrorMap().entrySet()) {
_logger.info("looking at mirrors for device leg on cluster " + mirrorMapEntry.getKey());
Map<String, VPlexDeviceInfo> slotToDeviceMap = mirrorMapEntry.getValue();
if (null != slotToDeviceMap && !slotToDeviceMap.isEmpty()) {
// figure out the source and target (mirror) UnManagedVolumes for this leg
UnManagedVolume associatedVolumeSource = null;
UnManagedVolume associatedVolumeMirror = null;
// source will be in slot-0, target/mirror will be in slot-1
for (Entry<String, VPlexDeviceInfo> entry : slotToDeviceMap.entrySet()) {
if (SLOT_0.equals(entry.getKey())) {
_logger.info("looking at slot-0");
associatedVolumeSource = getAssociatedVolumeForComponentDevice(entry.getValue());
}
if (SLOT_1.equals(entry.getKey())) {
_logger.info("looking at slot-1");
associatedVolumeMirror = getAssociatedVolumeForComponentDevice(entry.getValue());
}
}
// once found, wire them together:
if (null != associatedVolumeMirror && null != associatedVolumeSource) {
// 1. remove the mirror volume from the general backend volumes
_logger.info("removing mirror volume {} from associated " + "vols and adding to mirrors", associatedVolumeMirror.getLabel());
getUnmanagedBackendVolumes().remove(associatedVolumeMirror);
// 2. add the mirror the unmanagedMirrors map that will be returned by this method
unmanagedMirrors.put(associatedVolumeMirror, slotToDeviceMap.get("1").getPath());
// 3. update the source volume with the target mirror information
StringSet set = new StringSet();
set.add(associatedVolumeMirror.getNativeGuid());
_logger.info("adding mirror set {} to source unmanaged volume {}", set, associatedVolumeSource);
associatedVolumeSource.putVolumeInfo(SupportedVolumeInformation.VPLEX_NATIVE_MIRROR_TARGET_VOLUME.toString(), set);
_logger.info("setting VPLEX_BACKEND_CLUSTER_ID on mirrored volumes: " + mirrorMapEntry.getKey());
StringSet clusterIds = new StringSet();
clusterIds.add(mirrorMapEntry.getKey());
associatedVolumeSource.putVolumeInfo(SupportedVolumeInformation.VPLEX_BACKEND_CLUSTER_ID.name(), clusterIds);
// 4. update the target volume with the source volume information
set = new StringSet();
set.add(associatedVolumeSource.getNativeGuid());
associatedVolumeMirror.putVolumeInfo(SupportedVolumeInformation.VPLEX_NATIVE_MIRROR_SOURCE_VOLUME.toString(), set);
associatedVolumeMirror.putVolumeInfo(SupportedVolumeInformation.VPLEX_BACKEND_CLUSTER_ID.name(), clusterIds);
// 5. need to go ahead and persist any changes to backend volume info
_dbClient.updateObject(associatedVolumeSource);
_dbClient.updateObject(associatedVolumeMirror);
} else {
String reason = "couldn't find all associated device components in mirror device: ";
reason += " associatedVolumeSource is " + associatedVolumeSource;
reason += " and associatedVolumeMirror is " + associatedVolumeMirror;
_logger.error(reason);
throw VPlexApiException.exceptions.backendIngestionContextLoadFailure(reason);
}
}
}
}
_logger.info("unmanaged mirrors found: " + unmanagedMirrors);
_tracker.fetchMirrors = System.currentTimeMillis() - start;
if (!unmanagedMirrors.isEmpty()) {
StringSet mirrorEntries = new StringSet();
for (Entry<UnManagedVolume, String> mirrorEntry : unmanagedMirrors.entrySet()) {
mirrorEntries.add(mirrorEntry.getKey().getNativeGuid() + "=" + mirrorEntry.getValue());
}
if (mirrorEntries != null && !mirrorEntries.isEmpty()) {
_logger.info("setting VPLEX_MIRROR_MAP: " + mirrorEntries);
_unmanagedVirtualVolume.putVolumeInfo(SupportedVolumeInformation.VPLEX_MIRROR_MAP.name(), mirrorEntries);
}
// need to update the backend volumes because a mirror target shouldn't be considered a direct backend volume
updateUnmanagedBackendVolumesInParent();
}
return unmanagedMirrors;
}
Aggregations