use of com.emc.storageos.vplex.api.VPlexStorageViewInfo 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.VPlexStorageViewInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method storageViewAddInitiators.
/**
* Workflow Step to add initiator to Storage View.
* Note arguments (except stepId) must match storageViewAddInitiatorsMethod above.
*
* @param vplexURI
* -- URI of VPlex StorageSystem
* @param exportURI
* -- ExportGroup URI
* @param maskURI
* -- ExportMask URI. Optional.
* If non-null, only the indicated ExportMask will be processed.
* Otherwise, all ExportMasks will be processed.
* @param initiatorURIs
* -- List of initiator URIs to be added.
* @param targetURIs
* -- optional list of additional targets URIs (VPLEX FE ports) to be added.
* If non null, the targets (VPlex front end ports) indicated by the targetURIs will be added
* to the Storage View.
* @param completer the ExportMaskAddInitiatorCompleter
* @param stepId
* -- Workflow step id.
* @throws WorkflowException
*/
public void storageViewAddInitiators(URI vplexURI, URI exportURI, URI maskURI, List<URI> initiatorURIs, List<URI> targetURIs, boolean sharedExportMask, ExportMaskAddInitiatorCompleter completer, String stepId) throws DeviceControllerException {
try {
WorkflowStepCompleter.stepExecuting(stepId);
ExportOperationContext context = new VplexExportOperationContext();
// Prime the context object
completer.updateWorkflowStepContext(context);
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
ExportGroup exportGroup = getDataObject(ExportGroup.class, exportURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
List<ExportMask> exportMasks = ExportMaskUtils.getExportMasks(_dbClient, exportGroup, vplexURI);
for (ExportMask exportMask : exportMasks) {
// If a specific ExportMask is to be processed, ignore any others.
if (maskURI != null && !exportMask.getId().equals(maskURI)) {
continue;
}
_log.info("Refreshing ExportMask {}", exportMask.getMaskName());
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName), _networkDeviceController);
// Determine host of ExportMask
Set<URI> exportMaskHosts = VPlexUtil.getExportMaskHosts(_dbClient, exportMask, sharedExportMask);
List<Initiator> inits = _dbClient.queryObject(Initiator.class, initiatorURIs);
if (sharedExportMask) {
for (Initiator initUri : inits) {
URI hostUri = VPlexUtil.getInitiatorHost(initUri);
if (null != hostUri) {
exportMaskHosts.add(hostUri);
}
}
}
// Invoke artificial failure to simulate invalid storageview name on vplex
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_060);
// Add new targets if specified
if (targetURIs != null && targetURIs.isEmpty() == false) {
List<PortInfo> targetPortInfos = new ArrayList<PortInfo>();
List<URI> targetsAddedToStorageView = new ArrayList<URI>();
for (URI target : targetURIs) {
// Do not try to add a port twice.
if (exportMask.getStoragePorts().contains(target.toString())) {
continue;
}
// Log any ports not listed as a target in the Export Masks zoningMap
Set<String> zoningMapTargets = BlockStorageScheduler.getTargetIdsFromAssignments(exportMask.getZoningMap());
if (!zoningMapTargets.contains(target.toString())) {
_log.info(String.format("Target %s not in zoning map", target));
}
// Build the PortInfo structure for the port to be added
StoragePort port = getDataObject(StoragePort.class, target, _dbClient);
PortInfo pi = new PortInfo(port.getPortNetworkId().toUpperCase().replaceAll(":", ""), null, port.getPortName(), null);
targetPortInfos.add(pi);
targetsAddedToStorageView.add(target);
}
if (!targetPortInfos.isEmpty()) {
// Add the targets on the VPLEX
client.addTargetsToStorageView(exportMask.getMaskName(), targetPortInfos);
// Add the targets to the database.
for (URI target : targetsAddedToStorageView) {
exportMask.addTarget(target);
}
}
}
List<PortInfo> initiatorPortInfos = new ArrayList<PortInfo>();
List<String> initiatorPortWwns = new ArrayList<String>();
Map<PortInfo, Initiator> portInfosToInitiatorMap = new HashMap<PortInfo, Initiator>();
for (Initiator initiator : inits) {
// Only add this initiator if it's for the same host as other initiators in mask
if (!exportMaskHosts.contains(VPlexUtil.getInitiatorHost(initiator))) {
continue;
}
// Only add this initiator if it's not in the mask already after refresh
if (exportMask.hasInitiator(initiator.getId().toString())) {
continue;
}
PortInfo portInfo = new PortInfo(initiator.getInitiatorPort().toUpperCase().replaceAll(":", ""), initiator.getInitiatorNode().toUpperCase().replaceAll(":", ""), initiator.getLabel(), getVPlexInitiatorType(initiator));
initiatorPortInfos.add(portInfo);
initiatorPortWwns.add(initiator.getInitiatorPort());
portInfosToInitiatorMap.put(portInfo, initiator);
}
if (!initiatorPortInfos.isEmpty()) {
String lockName = null;
boolean lockAcquired = false;
try {
StringSet portIds = exportMask.getStoragePorts();
StoragePort exportMaskPort = getDataObject(StoragePort.class, URI.create(portIds.iterator().next()), _dbClient);
String clusterId = ConnectivityUtil.getVplexClusterOfPort(exportMaskPort);
lockName = _vplexApiLockManager.getLockName(vplexURI, clusterId);
lockAcquired = _vplexApiLockManager.acquireLock(lockName, LockTimeoutValue.get(LockType.VPLEX_API_LIB));
if (!lockAcquired) {
throw VPlexApiException.exceptions.couldNotObtainConcurrencyLock(vplex.getLabel());
}
// Add the initiators to the VPLEX
client.addInitiatorsToStorageView(exportMask.getMaskName(), vplexClusterName, initiatorPortInfos);
ExportOperationContext.insertContextOperation(completer, VplexExportOperationContext.OPERATION_ADD_INITIATORS_TO_STORAGE_VIEW, initiatorURIs);
} finally {
if (lockAcquired) {
_vplexApiLockManager.releaseLock(lockName);
}
}
}
}
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_003);
completer.ready(_dbClient);
} catch (VPlexApiException vae) {
_log.error("VPlexApiException adding initiator to Storage View: " + vae.getMessage(), vae);
failStep(completer, stepId, vae);
} catch (Exception ex) {
_log.error("Exception adding initiator to Storage View: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.ADD_STORAGE_VIEW_INITIATOR.getName();
ServiceError serviceError = VPlexApiException.errors.storageViewAddInitiatorFailed(opName, ex);
failStep(completer, stepId, serviceError);
}
}
use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method storageViewAddVolumes.
/**
* Method for adding volumes to a single ExportMask.
*
* @param vplexURI
* @param exportGroupURI
* @param exportMaskURI
* @param volumeMap
* @param opId
* @throws ControllerException
*/
public void storageViewAddVolumes(URI vplexURI, URI exportGroupURI, URI exportMaskURI, Map<URI, Integer> volumeMap, String opId) throws ControllerException {
String volListStr = "";
ExportMaskAddVolumeCompleter completer = null;
try {
WorkflowStepCompleter.stepExecuting(opId);
completer = new ExportMaskAddVolumeCompleter(exportGroupURI, exportMaskURI, volumeMap, opId);
ExportOperationContext context = new VplexExportOperationContext();
// Prime the context object
completer.updateWorkflowStepContext(context);
volListStr = Joiner.on(',').join(volumeMap.keySet());
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
ExportMask exportMask = getDataObject(ExportMask.class, exportMaskURI, _dbClient);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_001);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
// Need to massage the map to fit the API
List<BlockObject> volumes = new ArrayList<BlockObject>();
Map<String, Integer> deviceLabelToHLU = new HashMap<String, Integer>();
boolean duplicateHLU = false;
List<URI> volumesToAdd = new ArrayList<URI>();
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName), _networkDeviceController);
exportMask = getDataObject(ExportMask.class, exportMaskURI, _dbClient);
for (Map.Entry<URI, Integer> entry : volumeMap.entrySet()) {
if (exportMask.hasVolume(entry.getKey())) {
_log.info(String.format("Volume %s is already in Exportmask %s %s hence skipping adding volume again. This must be shared exportmask. ", entry.getKey(), exportMask.getMaskName(), exportMask.getId()));
continue;
}
Integer requestedHLU = entry.getValue();
// If user have provided specific HLU for volume, then check if its already in use
if (requestedHLU.intValue() != VPlexApiConstants.LUN_UNASSIGNED && exportMask.anyVolumeHasHLU(requestedHLU.toString())) {
String message = String.format("Failed to add Volumes %s to ExportMask %s", volListStr, exportMaskURI);
_log.error(message);
String opName = ResourceOperationTypeEnum.ADD_EXPORT_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.exportHasExistingVolumeWithRequestedHLU(entry.getKey().toString(), requestedHLU.toString(), opName);
failStep(completer, opId, serviceError);
duplicateHLU = true;
break;
}
BlockObject vol = Volume.fetchExportMaskBlockObject(_dbClient, entry.getKey());
volumes.add(vol);
deviceLabelToHLU.put(vol.getDeviceLabel(), requestedHLU);
volumesToAdd.add(entry.getKey());
}
// If duplicate HLU are found then return, completer is set to error above
if (duplicateHLU) {
return;
}
// If deviceLabelToHLU map is empty then volumes already exists in the storage view hence return.
if (deviceLabelToHLU.isEmpty()) {
completer.ready(_dbClient);
return;
}
VPlexStorageViewInfo svInfo = client.addVirtualVolumesToStorageView(exportMask.getMaskName(), vplexClusterName, deviceLabelToHLU);
ExportOperationContext.insertContextOperation(completer, VplexExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_VIEW, volumesToAdd);
// When VPLEX volumes are exported to a storage view, they get a WWN,
// so set the WWN from the returned storage view information.
Map<URI, Integer> updatedVolumeMap = new HashMap<URI, Integer>();
for (BlockObject volume : volumes) {
String deviceLabel = volume.getDeviceLabel();
String wwn = svInfo.getWWNForStorageViewVolume(volume.getDeviceLabel());
volume.setWWN(wwn);
_dbClient.updateObject(volume);
updatedVolumeMap.put(volume.getId(), svInfo.getHLUForStorageViewVolume(deviceLabel));
// user.
if (exportMask.hasExistingVolume(wwn)) {
_log.info("wwn {} has been added to the storage view {} by the user, but it " + "was already in existing volumes, removing from existing volumes.", wwn, exportMask.forDisplay());
exportMask.removeFromExistingVolumes(wwn);
}
exportMask.addToUserCreatedVolumes(volume);
}
// We also need to update the volume/lun id map in the export mask
// to those assigned by the VPLEX.
_log.info("Updating volume/lun map in export mask {}", exportMask.getId());
exportMask.addVolumes(updatedVolumeMap);
_dbClient.updateObject(exportMask);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_002);
completer.ready(_dbClient);
} catch (VPlexApiException vae) {
String message = String.format("Failed to add Volumes %s to ExportMask %s", volListStr, exportMaskURI);
_log.error(message, vae);
failStep(completer, opId, vae);
} catch (Exception ex) {
String message = String.format("Failed to add Volumes %s to ExportMask %s", volListStr, exportMaskURI);
_log.error(message, ex);
String opName = ResourceOperationTypeEnum.ADD_EXPORT_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.exportGroupAddVolumesFailed(volListStr, exportGroupURI.toString(), opName, ex);
failStep(completer, opId, serviceError);
}
}
use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method deleteStorageView.
/**
* A Workflow Step to delete a VPlex Storage View.
*
* @param vplexURI vplex
* @param exportMaskURI export mask
* @param isRollbackStep is this being run as a rollback step?
* @param stepId step ID
* @throws WorkflowException
*/
public void deleteStorageView(URI vplexURI, URI exportGroupURI, URI exportMaskURI, boolean isRollbackStep, String stepId) throws WorkflowException {
ExportMaskDeleteCompleter completer = null;
try {
WorkflowStepCompleter.stepExecuting(stepId);
completer = new ExportMaskDeleteCompleter(exportGroupURI, exportMaskURI, stepId);
completer.setRollingBack(isRollbackStep);
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
Boolean[] viewFound = new Boolean[] { new Boolean(false) };
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
if (exportMask != null) {
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
if (storageView != null) {
// we can ignore this in the case of a missing storage view on the VPLEX, it has already been
// deleted
_log.info("Refreshing ExportMask {}", exportMask.getMaskName());
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName), _networkDeviceController);
}
if (exportMask.hasAnyExistingVolumes() || exportMask.hasAnyExistingInitiators()) {
_log.warn("ExportMask {} still has non-ViPR-created existing volumes or initiators, " + "so ViPR will not remove it from the VPLEX device", exportMask.getMaskName());
}
if (exportMask.getInactive()) {
_log.warn("ExportMask {} is already inactive, so there's " + "no need to delete it off the VPLEX", exportMask.getMaskName());
} else {
List<URI> volumeURIs = new ArrayList<URI>();
if (exportMask.getUserAddedVolumes() != null && !exportMask.getUserAddedVolumes().isEmpty()) {
volumeURIs = StringSetUtil.stringSetToUriList(exportMask.getUserAddedVolumes().values());
}
List<Initiator> initiators = new ArrayList<>();
if (exportMask.getUserAddedInitiators() != null && !exportMask.getUserAddedInitiators().isEmpty()) {
List<URI> initiatorURIs = StringSetUtil.stringSetToUriList(exportMask.getUserAddedInitiators().values());
initiators.addAll(_dbClient.queryObject(Initiator.class, initiatorURIs));
}
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(vplex);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(volumeURIs, _dbClient);
ctx.setInitiators(initiators);
ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(stepId));
validator.exportMaskDelete(ctx).validate();
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_084);
// note: there's a chance if the existing storage view originally had only
// storage ports configured in it, then it would be deleted by this
_log.info("removing this export mask from VPLEX: " + exportMask.getMaskName());
client.deleteStorageView(exportMask.getMaskName(), vplexClusterName, viewFound);
if (viewFound[0]) {
_log.info("as expected, storage view was found for deletion on the VPLEX.");
} else {
_log.info("storage view was not found on the VPLEX during deletion, " + "but no errors were encountered.");
}
}
_log.info("Marking export mask for deletion from Vipr: " + exportMask.getMaskName());
_dbClient.markForDeletion(exportMask);
_log.info("updating ExportGroups containing this ExportMask");
List<ExportGroup> exportGroups = ExportMaskUtils.getExportGroups(_dbClient, exportMask);
for (ExportGroup exportGroup : exportGroups) {
_log.info("Removing mask from ExportGroup " + exportGroup.getGeneratedName());
exportGroup.removeExportMask(exportMaskURI);
_dbClient.updateObject(exportGroup);
}
} else {
_log.info("ExportMask to delete could not be found in database: " + exportMaskURI);
}
completer.ready(_dbClient);
} catch (VPlexApiException vae) {
_log.error("Exception deleting ExportMask: " + exportMaskURI, vae);
failStep(completer, stepId, vae);
} catch (DeviceControllerException ex) {
_log.error("Exception deleting ExportMask: " + exportMaskURI, ex);
failStep(completer, stepId, ex);
} catch (Exception ex) {
_log.error("Exception deleting ExportMask: " + exportMaskURI, ex);
ServiceError svcError = VPlexApiException.errors.deleteStorageViewFailed(ex);
failStep(completer, stepId, svcError);
}
}
use of com.emc.storageos.vplex.api.VPlexStorageViewInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method createStorageView.
/**
* A Workflow Step to create a Storage View on the VPlex.
*
* @param vplexURI
* @param exportURI
* @param blockObjectMap
* - A list of Volume/Snapshot URIs to LUN ids.
* @param initiators
* @param stepId
* @throws ControllerException
*/
public void createStorageView(URI vplexURI, URI exportURI, URI exportMaskURI, Map<URI, Integer> blockObjectMap, List<URI> initiators, List<URI> targets, ExportMaskCreateCompleter completer, String stepId) throws ControllerException {
String lockName = null;
boolean lockAcquired = false;
try {
WorkflowStepCompleter.stepExecuting(stepId);
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
ExportMask exportMask = getDataObject(ExportMask.class, exportMaskURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
// Setup the call to the VPlex API.
List<PortInfo> targetPortInfos = new ArrayList<PortInfo>();
for (URI target : targets) {
StoragePort port = getDataObject(StoragePort.class, target, _dbClient);
PortInfo pi = new PortInfo(port.getPortNetworkId().toUpperCase().replaceAll(":", ""), null, port.getPortName(), null);
targetPortInfos.add(pi);
if (lockName == null) {
String clusterId = ConnectivityUtil.getVplexClusterOfPort(port);
lockName = _vplexApiLockManager.getLockName(vplexURI, clusterId);
}
}
List<PortInfo> initiatorPortInfos = new ArrayList<PortInfo>();
for (URI init : initiators) {
Initiator initiator = getDataObject(Initiator.class, init, _dbClient);
PortInfo pi = new PortInfo(initiator.getInitiatorPort().toUpperCase().replaceAll(":", ""), initiator.getInitiatorNode().toUpperCase().replaceAll(":", ""), initiator.getLabel(), getVPlexInitiatorType(initiator));
initiatorPortInfos.add(pi);
}
List<BlockObject> blockObjects = new ArrayList<BlockObject>();
Map<String, Integer> boMap = new HashMap<String, Integer>();
for (URI vol : blockObjectMap.keySet()) {
Integer lun = blockObjectMap.get(vol);
if (lun == null) {
lun = ExportGroup.LUN_UNASSIGNED;
}
BlockObject bo = Volume.fetchExportMaskBlockObject(_dbClient, vol);
blockObjects.add(bo);
boMap.put(bo.getDeviceLabel(), lun);
}
lockAcquired = _vplexApiLockManager.acquireLock(lockName, LockTimeoutValue.get(LockType.VPLEX_API_LIB));
if (!lockAcquired) {
throw VPlexApiException.exceptions.couldNotObtainConcurrencyLock(vplex.getLabel());
}
VPlexStorageViewInfo svInfo = client.createStorageView(exportMask.getMaskName(), targetPortInfos, initiatorPortInfos, boMap);
// When VPLEX volumes or snapshots are exported to a storage view, they get a WWN,
// so set the WWN from the returned storage view information.
Map<URI, Integer> updatedBlockObjectMap = new HashMap<URI, Integer>();
for (BlockObject bo : blockObjects) {
String deviceLabel = bo.getDeviceLabel();
bo.setWWN(svInfo.getWWNForStorageViewVolume(deviceLabel));
_dbClient.updateObject(bo);
updatedBlockObjectMap.put(bo.getId(), svInfo.getHLUForStorageViewVolume(deviceLabel));
}
// We also need to update the volume/lun id map in the export mask
// to those assigned by the VPLEX.
_log.info("Updating volume/lun map in export mask {}", exportMask.getId());
_log.info("updatedBlockObjectMap: " + updatedBlockObjectMap.toString());
exportMask.addVolumes(updatedBlockObjectMap);
// Update user created volumes
exportMask.addToUserCreatedVolumes(blockObjects);
// update native id (this is the context path to the storage view on the vplex)
// e.g.: /clusters/cluster-1/exports/storage-views/V1_myserver_288
// this column being set to non-null can be used to indicate a storage view that
// has been successfully created on the VPLEX device
exportMask.setNativeId(svInfo.getPath());
_dbClient.updateObject(exportMask);
completer.ready(_dbClient);
} catch (VPlexApiException vae) {
_log.error("Exception creating VPlex Storage View: " + vae.getMessage(), vae);
if ((null != vae.getMessage()) && vae.getMessage().toUpperCase().contains(VPlexApiConstants.DUPLICATE_STORAGE_VIEW_ERROR_FRAGMENT.toUpperCase())) {
_log.error("storage view creation failure is due to duplicate storage view name");
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
if (null != exportMask) {
_log.error("marking ExportMask inactive so that rollback will " + "not delete the existing storage view on the VPLEX");
_dbClient.removeObject(exportMask);
}
}
failStep(completer, stepId, vae);
} catch (Exception ex) {
_log.error("Exception creating VPlex Storage View: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.CREATE_STORAGE_VIEW.getName();
ServiceError serviceError = VPlexApiException.errors.createStorageViewFailed(opName, ex);
failStep(completer, stepId, serviceError);
} finally {
if (lockAcquired) {
_vplexApiLockManager.releaseLock(lockName);
}
}
}
Aggregations