Search in sources :

Example 6 with VPlexStorageViewInfo

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);
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) BlockMirror(com.emc.storageos.db.client.model.BlockMirror) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) URI(java.net.URI) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) ContainmentConstraint(com.emc.storageos.db.client.constraint.ContainmentConstraint) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) Volume(com.emc.storageos.db.client.model.Volume) VPlexStorageVolumeInfo(com.emc.storageos.vplex.api.VPlexStorageVolumeInfo) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) StringSet(com.emc.storageos.db.client.model.StringSet)

Example 7 with VPlexStorageViewInfo

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);
    }
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) PortInfo(com.emc.storageos.vplex.api.clientdata.PortInfo) Initiator(com.emc.storageos.db.client.model.Initiator) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) StringSet(com.emc.storageos.db.client.model.StringSet) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ExportMask(com.emc.storageos.db.client.model.ExportMask) StoragePort(com.emc.storageos.db.client.model.StoragePort) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient)

Example 8 with VPlexStorageViewInfo

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);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) HashMap(java.util.HashMap) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) ExportMaskAddVolumeCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskAddVolumeCompleter) Map(java.util.Map) OpStatusMap(com.emc.storageos.db.client.model.OpStatusMap) HashMap(java.util.HashMap) StringMap(com.emc.storageos.db.client.model.StringMap) BlockObject(com.emc.storageos.db.client.model.BlockObject) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 9 with VPlexStorageViewInfo

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);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ExportMaskDeleteCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskDeleteCompleter) ExportMaskValidationContext(com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) Initiator(com.emc.storageos.db.client.model.Initiator) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 10 with VPlexStorageViewInfo

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);
        }
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) HashMap(java.util.HashMap) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) StoragePort(com.emc.storageos.db.client.model.StoragePort) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) PortInfo(com.emc.storageos.vplex.api.clientdata.PortInfo) Initiator(com.emc.storageos.db.client.model.Initiator) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) BlockObject(com.emc.storageos.db.client.model.BlockObject) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Aggregations

VPlexStorageViewInfo (com.emc.storageos.vplex.api.VPlexStorageViewInfo)21 URI (java.net.URI)18 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)16 ExportMask (com.emc.storageos.db.client.model.ExportMask)15 ArrayList (java.util.ArrayList)15 NamedURI (com.emc.storageos.db.client.model.NamedURI)14 URISyntaxException (java.net.URISyntaxException)14 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)12 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)12 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)12 IOException (java.io.IOException)12 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)11 Initiator (com.emc.storageos.db.client.model.Initiator)10 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)10 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)10 ControllerException (com.emc.storageos.volumecontroller.ControllerException)10 WorkflowException (com.emc.storageos.workflow.WorkflowException)10 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)9 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)9 HashMap (java.util.HashMap)9