use of com.emc.storageos.vplex.api.VPlexStorageVolumeInfo in project coprhd-controller by CoprHD.
the class VplexVolumeValidator method validateStorageVolumes.
/**
* Validates either storage volumes for either distributed or local vplex volumes.
*
* @param virtualVolume
* -- Vplex virtual volume
* @param volumeId
* -- identification for log
* @param topLevelDeviceName
* -- top level VPLEX device name
* @param distributed
* -- if true VPLEX distributed, false if VPLEX local
* @param cluster
* cluster-1 or cluster-2
* @param hasMirror
* -- if true this cluster has a mirror
* @return failed -- If true a discrepancy was detected
*/
private boolean validateStorageVolumes(Volume virtualVolume, String volumeId, String topLevelDeviceName, boolean distributed, String cluster, boolean hasMirror) {
boolean failed = false;
Map<String, VPlexStorageVolumeInfo> wwnToStorageVolumeInfos = client.getStorageVolumeInfoForDevice(topLevelDeviceName, distributed ? VPlexApiConstants.DISTRIBUTED_VIRTUAL_VOLUME : VPlexApiConstants.LOCAL_VIRTUAL_VOLUME, cluster, hasMirror);
// Check local volume is present
Volume assocVolume = VPlexUtil.getVPLEXBackendVolume(virtualVolume, true, getDbClient());
if (!storageSystemSupportsValidation(assocVolume)) {
return failed;
}
if (!wwnToStorageVolumeInfos.keySet().contains(assocVolume.getWWN())) {
getValidatorLogger().logDiff(volumeId, "SOURCE storage volume WWN", assocVolume.getWWN(), wwnToStorageVolumeInfos.keySet().toString());
failed = true;
} else {
wwnToStorageVolumeInfos.remove(assocVolume.getWWN());
}
// Check HA volume is present
if (distributed) {
assocVolume = VPlexUtil.getVPLEXBackendVolume(virtualVolume, false, getDbClient());
if (!storageSystemSupportsValidation(assocVolume)) {
return failed;
}
if (!wwnToStorageVolumeInfos.keySet().contains(assocVolume.getWWN())) {
getValidatorLogger().logDiff(volumeId, "HA storage volume WWN", assocVolume.getWWN(), wwnToStorageVolumeInfos.keySet().toString());
failed = true;
} else {
wwnToStorageVolumeInfos.remove(assocVolume.getWWN());
}
}
// Process any mirrors that were found
if (virtualVolume.getMirrors() != null) {
for (String mirrorId : virtualVolume.getMirrors()) {
VplexMirror mirror = getDbClient().queryObject(VplexMirror.class, URI.create(mirrorId));
if (mirror == null || mirror.getInactive() || mirror.getAssociatedVolumes() == null) {
// Not fully formed for some reason, skip it
continue;
}
// Now get the underlying Storage Volume
for (String mirrorAssociatedId : mirror.getAssociatedVolumes()) {
Volume mirrorVolume = getDbClient().queryObject(Volume.class, URI.create(mirrorAssociatedId));
if (!storageSystemSupportsValidation(mirrorVolume)) {
return failed;
}
if (mirrorVolume != null && !NullColumnValueGetter.isNullValue(mirrorVolume.getWWN())) {
if (!wwnToStorageVolumeInfos.keySet().contains(mirrorVolume.getWWN())) {
getValidatorLogger().logDiff(volumeId, "Mirror WWN", mirrorVolume.getWWN(), wwnToStorageVolumeInfos.keySet().toString());
failed = true;
} else {
wwnToStorageVolumeInfos.remove(mirrorVolume.getWWN());
}
}
}
}
}
if (!wwnToStorageVolumeInfos.isEmpty()) {
getValidatorLogger().logDiff(volumeId, "Extra storage volumes found", ValidatorLogger.NO_MATCHING_ENTRY, wwnToStorageVolumeInfos.keySet().toString());
failed = true;
}
return failed;
}
use of com.emc.storageos.vplex.api.VPlexStorageVolumeInfo in project coprhd-controller by CoprHD.
the class VPlexControllerUtils method getStorageVolumeInfoForDevice.
/**
* Returns a Map of lowest-level storage-volume resource's WWN to its VPlexStorageVolumeInfo
* object for a given device name, virtual volume type, and cluster name. If
* hasMirror is true, this indicates the top-level device is composed of a
* RAID-1 mirror, so there's an extra layers of components to traverse in finding
* the lowest-level storage-volume resources.
*
* @param deviceName the name of the top-level device to look at
* @param virtualVolumeType the type of virtual volume (local or distributed)
* @param clusterName the cluster name
* @param hasMirror indicates if the top-level device is a RAID-1 mirror
* @param vplexUri the URI of the VPLEX system
* @param dbClient a reference to the database client
*
* @return a map of WWNs to VPlexStorageVolumeInfo objects
* @throws VPlexApiException
*/
public static Map<String, VPlexStorageVolumeInfo> getStorageVolumeInfoForDevice(String deviceName, String virtualVolumeType, String clusterName, boolean hasMirror, URI vplexUri, DbClient dbClient) throws VPlexApiException {
Map<String, VPlexStorageVolumeInfo> storageVolumeInfo = null;
VPlexApiClient client = null;
try {
VPlexApiFactory vplexApiFactory = VPlexApiFactory.getInstance();
client = VPlexControllerUtils.getVPlexAPIClient(vplexApiFactory, vplexUri, dbClient);
} catch (URISyntaxException e) {
log.error("cannot load vplex api client", e);
}
if (null != client) {
storageVolumeInfo = client.getStorageVolumeInfoForDevice(deviceName, virtualVolumeType, clusterName, hasMirror);
}
log.info("Backend storage volume wwns for {} are {}", deviceName, storageVolumeInfo);
return storageVolumeInfo;
}
use of com.emc.storageos.vplex.api.VPlexStorageVolumeInfo in project coprhd-controller by CoprHD.
the class VplexDBCkr method checkVolumesOnVplex.
public void checkVolumesOnVplex(URI vplexSystemURI, boolean deleteInvalidVolumes) {
URIQueryResultList result = new URIQueryResultList();
List<URI> deletevirtualvolumeURIs = new ArrayList<URI>();
int nerrors = 0;
int invalidVolumeCount = 0;
dbClient.queryByConstraint(ContainmentConstraint.Factory.getStorageDeviceVolumeConstraint(vplexSystemURI), result);
Iterator<URI> iter = result.iterator();
VPlexApiClient client = getVPlexApiClient(vplexSystemURI);
// Get all the virtual volumes. We elect for shallow here as it's quicker-
// we will spend time below getting details.
writeLog("Retrieving all virtual volumes... this will take some time...");
Map<String, VPlexVirtualVolumeInfo> vvInfoMap = client.getVirtualVolumes(true);
List<VPlexStorageViewInfo> storageViews = client.getStorageViewsLite();
writeLog("... done");
try {
while (iter.hasNext()) {
Volume volume = dbClient.queryObject(Volume.class, iter.next());
if (volume == null || volume.getInactive()) {
continue;
}
writeLog(String.format("Checking volume %s (%s)", volume.getLabel(), volume.getDeviceLabel()));
if (volume.getAssociatedVolumes() == null || volume.getAssociatedVolumes().isEmpty()) {
writeLog(String.format("Volume %s (%s) has no associated volumes... skipping", volume.getLabel(), volume.getDeviceLabel()));
continue;
}
VPlexVirtualVolumeInfo vvInfo = vvInfoMap.get(volume.getDeviceLabel());
if (vvInfo == null) {
writeLog(String.format("ERROR: Volume %s (%s) had no VirtualVolumeInfo in VPlex", volume.getLabel(), volume.getDeviceLabel()));
deletevirtualvolumeURIs.add(volume.getId());
nerrors++;
invalidVolumeCount++;
continue;
}
if ((null != vvInfo.getWwn()) && (null != volume.getWWN())) {
if (vvInfo.getName().equals(volume.getDeviceLabel())) {
if (vvInfo.getWwn().toUpperCase().equals(volume.getWWN().toUpperCase())) {
writeLog(String.format("Virtual Volume %s wwn %s matches VPLEX", vvInfo.getName(), vvInfo.getWwn()));
} else {
writeLog(String.format("ERROR: Virtual Volume %s wwn %s in VPLEX mismatch with viprdb %s", vvInfo.getName(), vvInfo.getWwn(), volume.getWWN()));
deletevirtualvolumeURIs.add(volume.getId());
invalidVolumeCount++;
nerrors++;
}
}
}
StringSet wwns = new StringSet();
for (String cluster : vvInfo.getClusters()) {
Map<String, VPlexStorageVolumeInfo> svInfoMap = client.getStorageVolumeInfoForDevice(vvInfo.getSupportingDevice(), vvInfo.getLocality(), cluster, false);
for (String wwn : svInfoMap.keySet()) {
// writeLog("adding wwn " + wwn.toUpperCase());
wwns.add(wwn.toUpperCase());
VPlexStorageVolumeInfo svInfo = svInfoMap.get(wwn);
writeLog(String.format("StorageVolume wwn %s name %s cluster %s", wwn, svInfo.getName(), cluster));
}
}
// Now check associated volumes against the wwns.
for (String associatedVolume : volume.getAssociatedVolumes()) {
Volume assocVolume = dbClient.queryObject(Volume.class, URI.create(associatedVolume));
if (assocVolume == null) {
writeLog("Associated volunme not found in database... skipping: " + associatedVolume);
continue;
}
if (wwns.contains(assocVolume.getWWN().toUpperCase())) {
writeLog(String.format("Volume %s wwn %s matches VPLEX", assocVolume.getLabel(), assocVolume.getWWN()));
} else {
writeLog(String.format("ERROR: Volume %s wwn %s is not present in VPLEX", assocVolume.getLabel(), assocVolume.getWWN()));
nerrors++;
}
}
List<ExportMask> exportMaskListInDB = isVolumeExported(volume.getId());
if (null != exportMaskListInDB) {
for (ExportMask exportMaskInDB : exportMaskListInDB) {
boolean found = false;
boolean storageviewfound = false;
for (VPlexStorageViewInfo storageView : storageViews) {
if (storageView.getName().equals(exportMaskInDB.getMaskName())) {
storageviewfound = true;
for (String volumeNameStr : storageView.getVirtualVolumes()) {
String[] tokens = volumeNameStr.split(",");
String volumeName = tokens[1];
if (volumeName.equals(volume.getDeviceLabel())) {
found = true;
break;
}
}
if (!found) {
writeLog(String.format("ERROR: volume %s is in exportmask %s in viprdb but not in vplex storageview %s", volume.getDeviceLabel(), exportMaskInDB.getMaskName(), storageView.getName()));
nerrors++;
}
break;
}
}
if (!storageviewfound) {
writeLog(String.format("ERROR: volume %s is in exportmask %s in viprdb but storageview not found in vplex", volume.getDeviceLabel(), exportMaskInDB.getMaskName()));
nerrors++;
}
}
}
for (VPlexStorageViewInfo storageView : storageViews) {
writeLog(String.format("Checking Storageview %s", storageView.getName()));
for (String volumeNameStr : storageView.getVirtualVolumes()) {
String[] tokens = volumeNameStr.split(",");
String volumeName = tokens[1];
if (volumeName.equals(volume.getDeviceLabel())) {
boolean storageviewfound = false;
if (null != exportMaskListInDB) {
for (ExportMask exportMaskInDB : exportMaskListInDB) {
if (storageView.getName().equals(exportMaskInDB.getMaskName())) {
storageviewfound = true;
break;
}
}
}
if (!storageviewfound) {
writeLog(String.format("ERROR: volume %s is in vplex storageview %s but not in viprdb exportmask", volumeName, storageView.getName()));
nerrors++;
}
}
}
}
}
if (deleteInvalidVolumes) {
writeLog("deleting invalid volumes");
// deleting virtual volumes that no longer exist in vplex
List<VolumeDescriptor> volumeDescriptors = getDescriptorsForVolumesToBeDeleted(vplexSystemURI, deletevirtualvolumeURIs, VolumeDeleteTypeEnum.VIPR_ONLY.name());
cleanupForViPROnlyDelete(volumeDescriptors);
// Mark them inactive. Note that some of the volumes may be mirrors,
// which have a different database type.
List<VolumeDescriptor> descriptorsForMirrors = VolumeDescriptor.getDescriptors(volumeDescriptors, VolumeDescriptor.Type.BLOCK_MIRROR);
dbClient.markForDeletion(dbClient.queryObject(BlockMirror.class, VolumeDescriptor.getVolumeURIs(descriptorsForMirrors)));
List<VolumeDescriptor> descriptorsForVolumes = VolumeDescriptor.filterByType(volumeDescriptors, null, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.BLOCK_MIRROR });
dbClient.markForDeletion(dbClient.queryObject(Volume.class, VolumeDescriptor.getVolumeURIs(descriptorsForVolumes)));
// Update the task status for each volume
for (URI volumeURI : deletevirtualvolumeURIs) {
Volume volume = dbClient.queryObject(Volume.class, volumeURI);
dbClient.updateObject(volume);
}
}
} catch (Exception e) {
writeLog(String.format("Exception: while verifying virtual volumes", e));
}
// List<URI> maskUrislist = new ArrayList<URI>();;
// maskUrislist.add(URI.create("urn:storageos:ExportMask:3742e612-cc93-422b-a1a5-43490e0fe8ea:vdc1"));
// for (URI mskUri : maskUrislist) {
// boolean found = false;
// ExportMask exportMaskUri = dbClient.queryObject(ExportMask.class, mskUri);
// if (exportMaskUri == null || exportMaskUri.getInactive()) {
// continue;
// }
// writeLog(String.format("exportMaskUri in ViPR DB is %s", exportMaskUri.getMaskName()));
// for (VPlexStorageViewInfo storageView : storageViews) {
// if (storageView.getName().equals(exportMaskUri.getMaskName())) {
// found = true;
// }
// }
// if(!found) {
// writeLog(String.format("ERROR: exportMask not found in vplex %s",exportMaskUri.getMaskName()));
// nerrors++;
// }
// }
writeLog("Total errors for this VPLEX: " + nerrors);
}
use of com.emc.storageos.vplex.api.VPlexStorageVolumeInfo in project coprhd-controller by CoprHD.
the class VplexBackendIngestionContext method updateUnmanagedBackendVolumesInParent.
/**
* Sets the VPLEX_BACKEND_VOLUMES information on the virtual UnManagedVolume
* as well as the VPLEX_PARENT_VOLUME and VPLEX_BACKEND_CLUSTER_ID
* on each associated UnManagedVolume.
*/
private void updateUnmanagedBackendVolumesInParent() {
if (!getUnmanagedBackendVolumes().isEmpty()) {
StringSet bvols = new StringSet();
for (UnManagedVolume backendVol : unmanagedBackendVolumes) {
bvols.add(backendVol.getNativeGuid());
// set the parent volume native guid on the backend volume
StringSet parentVol = new StringSet();
parentVol.add(_unmanagedVirtualVolume.getNativeGuid());
backendVol.putVolumeInfo(SupportedVolumeInformation.VPLEX_PARENT_VOLUME.name(), parentVol);
if (isDistributed()) {
// determine cluster location of distributed component storage volume leg
VPlexStorageVolumeInfo storageVolume = getBackendVolumeWwnToInfoMap().get(backendVol.getWwn());
if (null != storageVolume) {
String clusterId = getClusterLocationForStorageVolume(storageVolume);
if (null != clusterId && !clusterId.isEmpty()) {
_logger.info("setting VPLEX_BACKEND_CLUSTER_ID: " + clusterId);
StringSet clusterIds = new StringSet();
clusterIds.add(clusterId);
backendVol.putVolumeInfo(SupportedVolumeInformation.VPLEX_BACKEND_CLUSTER_ID.name(), clusterIds);
}
}
}
_dbClient.updateObject(backendVol);
}
if (bvols != null && !bvols.isEmpty()) {
_logger.info("setting VPLEX_BACKEND_VOLUMES: " + unmanagedBackendVolumes);
_unmanagedVirtualVolume.putVolumeInfo(SupportedVolumeInformation.VPLEX_BACKEND_VOLUMES.name(), bvols);
_unmanagedVirtualVolume.setLabel(getFriendlyLabel());
}
}
}
use of com.emc.storageos.vplex.api.VPlexStorageVolumeInfo in project coprhd-controller by CoprHD.
the class VplexBackendIngestionContext method getAssociatedVolumeForComponentDevice.
/**
* Finds the backend associated UnManagedVolume for the given VPlexDeviceInfo
* object. It does this by finding the overlap between the context paths
* of the VPlexDeviceInfo and VPlexStorageVolumeInfo objects and then using
* the WWN to locate the related UnManagedVolume.
*
* @param device the VPlexDeviceInfo object to search for
* @return an UnManagedVolume matching the VPlexDeviceInfo.
*/
private UnManagedVolume getAssociatedVolumeForComponentDevice(VPlexDeviceInfo device) {
String devicePath = device.getPath();
_logger.info("associated volume device context path: " + devicePath);
for (Entry<String, VPlexStorageVolumeInfo> entry : getBackendVolumeWwnToInfoMap().entrySet()) {
String storageVolumePath = entry.getValue().getPath();
_logger.info("\tstorage volume context path: " + storageVolumePath);
// context paths should overlap if the device contains the storage volume...
if (null != storageVolumePath && storageVolumePath.startsWith(devicePath)) {
_logger.info("\t\tthis storage volume is a match, trying to find unmanaged backend volume");
for (UnManagedVolume vol : getUnmanagedBackendVolumes()) {
_logger.info("\t\t\tlooking at " + vol.getNativeGuid());
if (vol.getWwn().equalsIgnoreCase(entry.getKey())) {
_logger.info("\t\t\t\tit's a match for " + vol.getWwn());
return vol;
}
}
}
}
return null;
}
Aggregations