use of com.emc.storageos.vplex.api.VPlexDistributedDeviceInfo 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.VPlexDistributedDeviceInfo 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.VPlexDistributedDeviceInfo 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;
}
Aggregations