Search in sources :

Example 11 with VPlexApiClient

use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.

the class VPlexMigrationJob method getVPlexAPIClient.

/**
 * Get the HTTP client for making requests to the VPlex at the
 * endpoint specified in the passed profile.
 *
 * @param jobContext The job context
 * @param vplexSystem The VPlex storage system
 *
 * @return A reference to the VPlex API HTTP client.
 * @throws URISyntaxException
 */
private VPlexApiClient getVPlexAPIClient(JobContext jobContext, StorageSystem vplexSystem) throws URISyntaxException {
    // Create the URI to access the VPlex Management Station based
    // on the IP and port for the passed VPlex system.
    URI vplexEndpointURI = new URI("https", null, vplexSystem.getIpAddress(), vplexSystem.getPortNumber(), "/", null, null);
    s_logger.debug("VPlex base URI is {}", vplexEndpointURI.toString());
    VPlexApiFactory vplexApiFactory = jobContext.getVPlexApiFactory();
    s_logger.debug("Got VPlex API factory");
    VPlexApiClient client = vplexApiFactory.getClient(vplexEndpointURI, vplexSystem.getUsername(), vplexSystem.getPassword());
    s_logger.debug("Got VPlex API client");
    return client;
}
Also used : VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) URI(java.net.URI) VPlexApiFactory(com.emc.storageos.vplex.api.VPlexApiFactory)

Example 12 with VPlexApiClient

use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.

the class VPlexDeviceController method commitMigration.

/**
 * Invoked by the migration workflow to commit the migration after it has
 * been completed.
 *
 * @param vplexURI
 *            The URI of the VPlex storage system.
 * @param virtualVolumeURI
 *            The URI of the virtual volume.
 * @param migrationURI
 *            The URI of the data migration.
 * @param rename
 *            Indicates if the volume should be renamed after commit to
 *            conform to ViPR standard naming conventions.
 * @param newVpoolURI - the new virtual pool for the virtual volume (or null if not changing)
 * @param newVarrayURI - the new varray for the virtual volume (or null if not changing)
 * @param stepId
 *            The workflow step identifier.
 *
 * @throws WorkflowException
 */
public void commitMigration(URI vplexURI, URI virtualVolumeURI, URI migrationURI, Boolean rename, URI newVpoolURI, URI newVarrayURI, String stepId) throws WorkflowException {
    _log.info("Committing migration {}", migrationURI);
    Migration migration = null;
    VPlexApiClient client = null;
    try {
        // Update step state to executing.
        WorkflowStepCompleter.stepExecuting(stepId);
        // Get the migration.
        migration = getDataObject(Migration.class, migrationURI, _dbClient);
        // workflow, so check the status.
        if (!VPlexMigrationInfo.MigrationStatus.COMMITTED.getStatusValue().equals(migration.getMigrationStatus())) {
            // Get the VPlex API client.
            StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
            client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
            _log.info("Got VPlex API client for system {}", vplexURI);
            // Make a call to the VPlex API client to commit the migration.
            // Note that for ingested VPLEX volumes created outside ViPR, we
            // don't want to update the name.
            List<VPlexMigrationInfo> migrationInfoList = new ArrayList<VPlexMigrationInfo>();
            Volume virtualVolume = getDataObject(Volume.class, virtualVolumeURI, _dbClient);
            try {
                migrationInfoList = client.commitMigrations(virtualVolume.getDeviceLabel(), Arrays.asList(migration.getLabel()), true, true, rename.booleanValue());
                _log.info("Committed migration {}", migration.getLabel());
            } catch (VPlexApiException vae) {
                _log.error("Exception committing VPlex migration: " + vae.getMessage(), vae);
                boolean committed = false;
                // Check the migration status. Maybe it committed even though we had an error.
                VPlexMigrationInfo migrationInfo = client.getMigrationInfo(migration.getLabel());
                if (migrationInfo.getStatus().equalsIgnoreCase(VPlexMigrationInfo.MigrationStatus.COMMITTED.name())) {
                    _log.info("Migration {} has committed despite exception", migration.getLabel());
                    migrationInfoList.clear();
                    migrationInfoList.add(migrationInfo);
                    committed = true;
                } else {
                    _log.info("Migration {} status {}", migration.getLabel(), migrationInfo.getStatus());
                }
                if (!committed) {
                    // This was observed at customer site COP-21257
                    if (vae.getServiceCode() == ServiceCode.VPLEX_API_RESPONSE_TIMEOUT_ERROR) {
                        // We are going to throw an error, but we don't want to rollback completely
                        _workflowService.setWorkflowRollbackContOnError(stepId, false);
                    }
                    WorkflowStepCompleter.stepFailed(stepId, vae);
                    return;
                }
            }
            // Below this point migration is committed, no turning back.
            // Initialize the migration info in the database.
            migration.setMigrationStatus(VPlexMigrationInfo.MigrationStatus.COMMITTED.getStatusValue());
            _dbClient.updateObject(migration);
            _log.info("Update migration status to committed");
            // Update the virtual volume native id and associated
            // volumes. Note that we don't update CoS until all
            // commits are successful.
            VPlexVirtualVolumeInfo updatedVirtualVolumeInfo = migrationInfoList.get(0).getVirtualVolumeInfo();
            // update any properties that were changed after migration including deviceLabel, nativeGuid, and nativeId.
            // also, if the updated volume isn't thin-enabled, it is thin-capable, and the target vpool supports thin
            // provisioning, then a call should be made to the VPLEX to flip the thin-enabled flag on for this volume.
            URI targetVolumeUri = migration.getTarget();
            Volume targetVolume = getDataObject(Volume.class, targetVolumeUri, _dbClient);
            if (updatedVirtualVolumeInfo != null) {
                _log.info(String.format("New virtual volume is %s", updatedVirtualVolumeInfo.toString()));
                // if the new virtual volume is thin-capable, but thin-enabled is not true,
                // that means we need to ask the VPLEX to convert it to a thin-enabled volume.
                // this doesn't happen automatically for thick-to-thin data migrations.
                boolean isThinEnabled = updatedVirtualVolumeInfo.isThinEnabled();
                if (!isThinEnabled && VPlexApiConstants.TRUE.equalsIgnoreCase(updatedVirtualVolumeInfo.getThinCapable())) {
                    if (verifyVplexSupportsThinProvisioning(vplexSystem)) {
                        if (null != targetVolume) {
                            _log.info(String.format("migration target Volume is %s", targetVolume.forDisplay()));
                            VirtualPool targetVirtualPool = getDataObject(VirtualPool.class, targetVolume.getVirtualPool(), _dbClient);
                            if (null != targetVirtualPool) {
                                _log.info(String.format("migration target VirtualPool is %s", targetVirtualPool.forDisplay()));
                                boolean doEnableThin = VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(targetVirtualPool.getSupportedProvisioningType());
                                if (doEnableThin) {
                                    _log.info(String.format("the new VirtualPool is thin, requesting VPLEX to enable thin provisioning on %s", updatedVirtualVolumeInfo.getName()));
                                    isThinEnabled = client.setVirtualVolumeThinEnabled(updatedVirtualVolumeInfo);
                                }
                            }
                        }
                    }
                }
                virtualVolume.setDeviceLabel(updatedVirtualVolumeInfo.getName());
                virtualVolume.setNativeId(updatedVirtualVolumeInfo.getPath());
                virtualVolume.setNativeGuid(updatedVirtualVolumeInfo.getPath());
                virtualVolume.setThinlyProvisioned(isThinEnabled);
            }
            // Note that for ingested volumes, there will be no associated volumes
            // at first.
            StringSet assocVolumes = virtualVolume.getAssociatedVolumes();
            if ((assocVolumes != null) && (!assocVolumes.isEmpty())) {
                // For a distributed volume, there could be multiple
                // migrations. When the first completes, there will
                // be no associated volumes. However, when the second
                // completes, there will be associated volumes. However,
                // the migration source could be null.
                URI sourceVolumeUri = migration.getSource();
                if (sourceVolumeUri != null) {
                    assocVolumes.remove(sourceVolumeUri.toString());
                    // Retain any previous RP fields on the new target volume.
                    Volume sourceVolume = getDataObject(Volume.class, sourceVolumeUri, _dbClient);
                    if (sourceVolume != null) {
                        boolean targetUpdated = false;
                        if (NullColumnValueGetter.isNotNullValue(sourceVolume.getRpCopyName())) {
                            targetVolume.setRpCopyName(sourceVolume.getRpCopyName());
                            targetUpdated = true;
                        }
                        if (NullColumnValueGetter.isNotNullValue(sourceVolume.getInternalSiteName())) {
                            targetVolume.setInternalSiteName(sourceVolume.getInternalSiteName());
                            targetUpdated = true;
                        }
                        if (targetUpdated) {
                            _dbClient.updateObject(targetVolume);
                        }
                    }
                }
                assocVolumes.add(migration.getTarget().toString());
            } else {
                // NOTE: Now an ingested volume will have associated volumes.
                // It will no longer be considered an ingested volume.
                assocVolumes = new StringSet();
                assocVolumes.add(migration.getTarget().toString());
                virtualVolume.setAssociatedVolumes(assocVolumes);
            }
            updateMigratedVirtualVolumeVpoolAndVarray(virtualVolume, newVpoolURI, newVarrayURI);
            _dbClient.updateObject(virtualVolume);
            _log.info("Updated virtual volume.");
        } else {
            _log.info("The migration is already committed.");
            // Note that we don't set the device label and native id. If the
            // migration was committed outside of Bourne, the virtual volume
            // will still have the old name. If it was committed through
            // Bourne, these values would already have been update.
            // Regardless, we have to update the vpool, and we update the
            // associated volumes in case it was committed outside of
            // Bourne.
            associateVplexVolumeWithMigratedTarget(migration, virtualVolumeURI);
            _log.info("Updated virtual volume.");
        }
        // Update the workflow step status.
        StringBuilder successMsgBuilder = new StringBuilder();
        successMsgBuilder.append("VPlex System: ");
        successMsgBuilder.append(vplexURI);
        successMsgBuilder.append(" migration: ");
        successMsgBuilder.append(migrationURI);
        successMsgBuilder.append(" was committed");
        _log.info(successMsgBuilder.toString());
        WorkflowStepCompleter.stepSucceded(stepId);
        _log.info("Updated workflow step state to success");
    } catch (VPlexApiException vae) {
        _log.error("Exception committing VPlex migration: " + vae.getMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception committing VPlex migration: " + ex.getMessage(), ex);
        String opName = ResourceOperationTypeEnum.COMMIT_VOLUME_MIGRATION.getName();
        ServiceError serviceError = VPlexApiException.errors.commitMigrationFailed(opName, ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) Migration(com.emc.storageos.db.client.model.Migration) ArrayList(java.util.ArrayList) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) 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) VPlexMigrationInfo(com.emc.storageos.vplex.api.VPlexMigrationInfo) Volume(com.emc.storageos.db.client.model.Volume) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) StringSet(com.emc.storageos.db.client.model.StringSet) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 13 with VPlexApiClient

use of com.emc.storageos.vplex.api.VPlexApiClient in project coprhd-controller by CoprHD.

the class VPlexDeviceController method pauseMigrationStep.

public void pauseMigrationStep(URI vplexURI, URI migrationURI, String stepId) {
    WorkflowStepCompleter.stepExecuting(stepId);
    try {
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
        client.pauseMigrations(Arrays.asList(migration.getLabel()));
        migration.setMigrationStatus(VPlexMigrationInfo.MigrationStatus.PAUSED.getStatusValue());
        _dbClient.updateObject(migration);
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (Exception ex) {
        _log.error("Exception pausing migration: ", ex);
        String opName = ResourceOperationTypeEnum.PAUSE_MIGRATION.getName();
        ServiceError serviceError = VPlexApiException.errors.operateMigrationFailed(opName, ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) Migration(com.emc.storageos.db.client.model.Migration) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) 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) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 14 with VPlexApiClient

use of com.emc.storageos.vplex.api.VPlexApiClient 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 15 with VPlexApiClient

use of com.emc.storageos.vplex.api.VPlexApiClient 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)

Aggregations

VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)81 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)57 URISyntaxException (java.net.URISyntaxException)57 ControllerException (com.emc.storageos.volumecontroller.ControllerException)55 WorkflowException (com.emc.storageos.workflow.WorkflowException)55 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)54 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)52 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)52 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)52 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)48 IOException (java.io.IOException)47 URI (java.net.URI)41 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)40 Volume (com.emc.storageos.db.client.model.Volume)34 ArrayList (java.util.ArrayList)34 NamedURI (com.emc.storageos.db.client.model.NamedURI)26 HashMap (java.util.HashMap)18 ExportMask (com.emc.storageos.db.client.model.ExportMask)16 VPlexStorageViewInfo (com.emc.storageos.vplex.api.VPlexStorageViewInfo)16 VPlexVirtualVolumeInfo (com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo)16