Search in sources :

Example 56 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VPlexDeviceController method getDescriptorsForAssociatedVolumes.

/**
 * From the passed list of descriptors, finds the descriptors for the
 * associated volumes of the VPLEX volume with the passed URI.
 *
 * @param vplexVolumeURI
 *            The URI of the VPLEX volume.
 * @param descriptors
 *            The list of volume descriptors.
 *
 * @return A list containing the volume descriptors representing the
 *         associated volumes for the VPLEX volume.
 */
private List<VolumeDescriptor> getDescriptorsForAssociatedVolumes(URI vplexVolumeURI, List<VolumeDescriptor> descriptors) {
    _log.info("Getting associated volume descriptors for VPLEX copy {}", vplexVolumeURI);
    List<VolumeDescriptor> assocVolumeDescriptors = new ArrayList<VolumeDescriptor>();
    Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
    _log.info("Got VPLEX volume");
    StringSet assocVolumeURIs = vplexVolume.getAssociatedVolumes();
    if (null == assocVolumeURIs || assocVolumeURIs.isEmpty()) {
        _log.error("VPLEX volume {} has no backend volumes.", vplexVolume.forDisplay());
        throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(vplexVolume.forDisplay());
    }
    Iterator<String> assocVolumeURIsIter = assocVolumeURIs.iterator();
    while (assocVolumeURIsIter.hasNext()) {
        URI assocVolumeURI = URI.create(assocVolumeURIsIter.next());
        _log.info("Associated volume is {}", assocVolumeURI);
        Iterator<VolumeDescriptor> descriptorIter = descriptors.iterator();
        while (descriptorIter.hasNext()) {
            VolumeDescriptor descriptor = descriptorIter.next();
            URI volumeURI = descriptor.getVolumeURI();
            _log.info("Descriptor volume is {}", volumeURI);
            if (volumeURI.equals(assocVolumeURI)) {
                _log.info("Found descriptor for associated volume");
                assocVolumeDescriptors.add(descriptor);
                break;
            }
        }
    }
    return assocVolumeDescriptors;
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume) ArrayList(java.util.ArrayList) StringSet(com.emc.storageos.db.client.model.StringSet) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI)

Example 57 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VPlexDeviceController method importCopy.

/**
 * Creates and starts the import workflow to import the volume to a VPLEX
 * virtual volume.
 *
 * @param vplexSystemURI
 *            The URI of the VPLEX system.
 * @param volumeDescriptors
 *            The list of volume descriptors.
 * @param projectURI
 *            The URI of the VPLEX project.
 * @param tenantURI
 *            The URI of the VPLEX tenant.
 * @param stepId
 *            The workflow step id.
 *
 * @throws ControllerException
 *             When an error occurs configuring the import
 *             workflow.
 */
public void importCopy(URI vplexSystemURI, List<VolumeDescriptor> volumeDescriptors, URI projectURI, URI tenantURI, String stepId) throws ControllerException {
    _log.info("Executing import step for full copy.");
    List<VolumeDescriptor> importVolumeDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.VPLEX_IMPORT_VOLUME }, new VolumeDescriptor.Type[] {});
    VolumeDescriptor importVolumeDescriptor = importVolumeDescriptors.get(0);
    Volume importVolume = getDataObject(Volume.class, importVolumeDescriptor.getVolumeURI(), _dbClient);
    // Update step state to executing.
    WorkflowStepCompleter.stepExecuting(stepId);
    // Reuse the import volume API to create a sub workflow to execute
    // the import.
    importVolume(vplexSystemURI, volumeDescriptors, projectURI, tenantURI, importVolume.getVirtualPool(), importVolume.getLabel(), null, Boolean.FALSE, stepId);
    _log.info("Created and started sub workflow to import the copy");
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume)

Example 58 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VPlexDeviceController method rollbackImportCopy.

/**
 * If a failure occurs during an import of a full copy, make sure
 * the volume is torn back down.
 *
 * @param vplexVolumeDescriptor
 *            The descriptor for the VPLEX copy volume
 * @param assocVolumeDescrs
 *            The descriptors for its backend volumes.
 * @param stepId
 *            The rollback step id.
 */
public void rollbackImportCopy(VolumeDescriptor vplexVolumeDescriptor, List<VolumeDescriptor> assocVolumeDescrs, String stepId) {
    // Update step state to executing.
    WorkflowStepCompleter.stepExecuting(stepId);
    // Make sure the volume is torn down.
    List<VolumeDescriptor> volumeDescriptors = new ArrayList<VolumeDescriptor>();
    // only delete active ones
    Volume vplexVol = _dbClient.queryObject(Volume.class, vplexVolumeDescriptor.getVolumeURI());
    if (vplexVol != null && !vplexVol.getInactive()) {
        volumeDescriptors.add(vplexVolumeDescriptor);
    }
    for (VolumeDescriptor volDes : assocVolumeDescrs) {
        Volume vol = _dbClient.queryObject(Volume.class, volDes.getVolumeURI());
        if (vol != null && !vol.getInactive()) {
            volumeDescriptors.add(volDes);
        }
    }
    _blockOrchestrationController.deleteVolumes(volumeDescriptors, stepId);
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume) ArrayList(java.util.ArrayList)

Example 59 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VPlexDeviceController method migrateVolumes.

/**
 * Deprecating this for now, should be using the migrateVolumes call with the WF passed in from
 * the BlockOrchestrator.
 *
 * {@inheritDoc}
 */
@Override
public void migrateVolumes(URI vplexURI, URI virtualVolumeURI, List<URI> targetVolumeURIs, Map<URI, URI> migrationsMap, Map<URI, URI> poolVolumeMap, URI newCoSURI, URI newNhURI, String successMsg, String failMsg, OperationTypeEnum opType, String opId, String wfStepId) throws ControllerException {
    List<URI> migrationURIs = new ArrayList<URI>(migrationsMap.values());
    try {
        _log.info("VPlex controller migrate volume {} on VPlex {}", virtualVolumeURI, vplexURI);
        // Get the VPlex storage system
        StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        _log.info("Got VPlex system");
        // If a workflow step id is passed, then this is being called
        // from a step in a "parent" workflow. In that case, this
        // sub-workflow takes the name of the step.
        String wfId = (wfStepId != null ? wfStepId : opId);
        // Get a new workflow to execute the migrations.
        Workflow workflow = _workflowService.getNewWorkflow(this, MIGRATE_VOLUMES_WF_NAME, false, wfId);
        _log.info("Created new workflow with operation id {}", wfId);
        // Create a step to validate the volume and prevent migration if the
        // the ViPR DB does not properly reflect the actual backend volumes.
        // A successful migration will delete the backend source volumes. If
        // the ViPR DB does not correctly reflect the actual backend volume,
        // we could delete a backend volume used by some other VPLEX volume.
        String waitFor = createWorkflowStepToValidateVPlexVolume(workflow, vplexSystem, virtualVolumeURI, null);
        // We first need to create steps in the workflow to create the new
        // backend volume(s) to which the data for the virtual volume will
        // be migrated.
        List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
        Map<URI, StorageSystem> storageSystemMap = new HashMap<URI, StorageSystem>();
        Map<URI, Volume> volumeMap = new HashMap<URI, Volume>();
        Iterator<URI> storagePoolIter = poolVolumeMap.keySet().iterator();
        while (storagePoolIter.hasNext()) {
            URI storagePoolURI = storagePoolIter.next();
            URI volumeURI = poolVolumeMap.get(storagePoolURI);
            _log.info("Creating descriptor for volume{} in pool {}", volumeURI, storagePoolURI);
            descriptors.add(createDescriptorForBlockVolumeCreation(storagePoolURI, volumeURI, storageSystemMap, volumeMap));
            _log.info("Created descriptor for volume");
        }
        // Add steps in the block device controller to create the target
        // volumes.
        waitFor = _blockDeviceController.addStepsForCreateVolumes(workflow, waitFor, descriptors, wfId);
        // Set the project and tenant. We prefer a project created for the Vplex system,
        // but will fallback to the volume's project if there isn't a project for the VPlex.
        Volume firstVolume = volumeMap.values().iterator().next();
        Project vplexProject = VPlexUtil.lookupVplexProject(firstVolume, vplexSystem, _dbClient);
        URI tenantURI = vplexProject.getTenantOrg().getURI();
        _log.info("Project is {}, Tenant is {}", vplexProject.getId(), tenantURI);
        // Now we need to do the necessary zoning and export steps to ensure
        // the VPlex can see these new backend volumes.
        createWorkflowStepsForBlockVolumeExport(workflow, vplexSystem, storageSystemMap, volumeMap, vplexProject.getId(), tenantURI, waitFor);
        _log.info("Created workflow steps for volume export.");
        // Now make a migration Step for each passed target to which data
        // for the passed virtual volume will be migrated. The migrations
        // will be done from this controller.
        Iterator<URI> targetVolumeIter = targetVolumeURIs.iterator();
        while (targetVolumeIter.hasNext()) {
            URI targetVolumeURI = targetVolumeIter.next();
            _log.info("Target volume is {}", targetVolumeURI);
            URI migrationURI = migrationsMap.get(targetVolumeURI);
            _log.info("Migration is {}", migrationURI);
            String stepId = workflow.createStepId();
            _log.info("Migration opId is {}", stepId);
            Workflow.Method vplexExecuteMethod = new Workflow.Method(MIGRATE_VIRTUAL_VOLUME_METHOD_NAME, vplexURI, virtualVolumeURI, targetVolumeURI, migrationURI, newNhURI);
            Workflow.Method vplexRollbackMethod = new Workflow.Method(RB_MIGRATE_VIRTUAL_VOLUME_METHOD_NAME, vplexURI, migrationURI, stepId);
            _log.info("Creating workflow migration step");
            workflow.createStep(MIGRATION_CREATE_STEP, String.format("VPlex %s migrating to target volume %s.", vplexSystem.getId().toString(), targetVolumeURI.toString()), EXPORT_STEP, vplexSystem.getId(), vplexSystem.getSystemType(), getClass(), vplexExecuteMethod, vplexRollbackMethod, stepId);
            _log.info("Created workflow migration step");
        }
        // Once the migrations complete, we will commit the migrations.
        // So, now we create the steps to commit the migrations.
        String waitForStep = MIGRATION_CREATE_STEP;
        List<URI> migrationSources = new ArrayList<URI>();
        Iterator<URI> migrationsIter = migrationsMap.values().iterator();
        while (migrationsIter.hasNext()) {
            URI migrationURI = migrationsIter.next();
            _log.info("Migration is {}", migrationURI);
            Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
            // The migration source volume may be null for ingested volumes
            // for which we do not know anything about the backend volumes.
            // If we don't know the source, we know we are migrating an
            // ingested volume and we will not want to do any renaming
            // after the commit as we do when migration ViPR create volumes,
            // which adhere to a standard naming convention.
            Boolean rename = Boolean.TRUE;
            if (migration.getSource() != null) {
                migrationSources.add(migration.getSource());
            } else {
                rename = Boolean.FALSE;
            }
            _log.info("Added migration source {}", migration.getSource());
            String stepId = workflow.createStepId();
            _log.info("Commit operation id is {}", stepId);
            Workflow.Method vplexExecuteMethod = new Workflow.Method(COMMIT_MIGRATION_METHOD_NAME, vplexURI, virtualVolumeURI, migrationURI, rename, newCoSURI, newNhURI);
            Workflow.Method vplexRollbackMethod = new Workflow.Method(RB_COMMIT_MIGRATION_METHOD_NAME, migrationURIs, newCoSURI, newNhURI, stepId);
            _log.info("Creating workflow step to commit migration");
            waitForStep = workflow.createStep(MIGRATION_COMMIT_STEP, String.format("VPlex %s committing volume migration", vplexSystem.getId().toString()), waitForStep, vplexSystem.getId(), vplexSystem.getSystemType(), getClass(), vplexExecuteMethod, vplexRollbackMethod, stepId);
            _log.info("Created workflow step to commit migration");
        }
        // Create a step that creates a sub workflow to delete the old
        // migration source volumes, which are no longer used by the
        // virtual volume. We also update the virtual volume CoS. If
        // we make it to this step, then all migrations were committed.
        // We do this in a sub workflow because we don't won't to
        // initiate rollback regardless of success or failure.
        String stepId = workflow.createStepId();
        Workflow.Method vplexExecuteMethod = new Workflow.Method(DELETE_MIGRATION_SOURCES_METHOD, vplexURI, virtualVolumeURI, newCoSURI, newNhURI, migrationSources);
        workflow.createStep(DELETE_MIGRATION_SOURCES_STEP, String.format("Creating workflow to delete migration sources"), MIGRATION_COMMIT_STEP, vplexSystem.getId(), vplexSystem.getSystemType(), getClass(), vplexExecuteMethod, null, stepId);
        _log.info("Created workflow step to create sub workflow for source deletion");
        // Finish up and execute the plan. The Workflow will handle the
        // TaskCompleter
        List<URI> volumes = new ArrayList<URI>();
        volumes.add(virtualVolumeURI);
        volumes.addAll(targetVolumeURIs);
        TaskCompleter completer = new MigrationWorkflowCompleter(volumes, migrationURIs, opId, wfStepId);
        _log.info("Executing workflow plan");
        workflow.executePlan(completer, successMsg);
        _log.info("Workflow plan executed");
    } catch (Exception e) {
        _log.error(failMsg, e);
        List<URI> volumes = new ArrayList<URI>();
        volumes.add(virtualVolumeURI);
        volumes.addAll(targetVolumeURIs);
        TaskCompleter completer = new MigrationWorkflowCompleter(volumes, migrationURIs, opId, wfStepId);
        ServiceError serviceError = VPlexApiException.errors.jobFailed(e);
        serviceError.setMessage(failMsg);
        failStep(completer, opId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) HashMap(java.util.HashMap) Migration(com.emc.storageos.db.client.model.Migration) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) 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) Project(com.emc.storageos.db.client.model.Project) MigrationWorkflowCompleter(com.emc.storageos.vplexcontroller.completers.MigrationWorkflowCompleter) Volume(com.emc.storageos.db.client.model.Volume) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) ExportTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter) MigrationTaskCompleter(com.emc.storageos.vplexcontroller.completers.MigrationTaskCompleter) CloneTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.CloneTaskCompleter) MigrationOperationTaskCompleter(com.emc.storageos.vplexcontroller.completers.MigrationOperationTaskCompleter) CacheStatusTaskCompleter(com.emc.storageos.vplexcontroller.completers.CacheStatusTaskCompleter) VplexMirrorTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VplexMirrorTaskCompleter) VolumeTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeTaskCompleter) VolumeGroupUpdateTaskCompleter(com.emc.storageos.vplexcontroller.completers.VolumeGroupUpdateTaskCompleter) TaskCompleter(com.emc.storageos.volumecontroller.TaskCompleter) WorkflowTaskCompleter(com.emc.storageos.workflow.WorkflowTaskCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 60 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VPlexDeviceController method buildArrayMap.

/**
 * Build a map of URI to cached StorageSystem for the underlying arrays.
 *
 * @param vplexSystem
 *            Only return Storage Systems connected this VPlex
 * @param descriptors
 * @param VolmeDescriptor.Type
 *            used to filter descriptors
 * @return Map<arrayURI, StorageSystem>
 */
private Map<URI, StorageSystem> buildArrayMap(StorageSystem vplexSystem, List<VolumeDescriptor> descriptors, VolumeDescriptor.Type[] types) {
    Map<URI, StorageSystem> arrayMap = new HashMap<URI, StorageSystem>();
    // Get only the descriptors for the type if specified..
    if (types != null) {
        descriptors = VolumeDescriptor.filterByType(descriptors, types, new VolumeDescriptor.Type[] {});
    }
    for (VolumeDescriptor desc : descriptors) {
        if (arrayMap.containsKey(desc.getDeviceURI()) == false) {
            if (vplexSystem == null) {
                StorageSystem array = getDataObject(StorageSystem.class, desc.getDeviceURI(), _dbClient);
                arrayMap.put(desc.getDeviceURI(), array);
            } else {
                Set<URI> connectedSystems = ConnectivityUtil.getStorageSystemAssociationsByNetwork(_dbClient, vplexSystem.getId(), StoragePort.PortType.backend);
                if (connectedSystems.contains(desc.getDeviceURI())) {
                    StorageSystem array = getDataObject(StorageSystem.class, desc.getDeviceURI(), _dbClient);
                    arrayMap.put(desc.getDeviceURI(), array);
                }
            }
        }
    }
    return arrayMap;
}
Also used : LockType(com.emc.storageos.locking.LockType) Type(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor.Type) TechnologyType(com.emc.storageos.db.client.model.BlockSnapshot.TechnologyType) Initiator_Type(com.emc.storageos.vplex.api.VPlexInitiatorInfo.Initiator_Type) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) HashMap(java.util.HashMap) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Aggregations

VolumeDescriptor (com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor)117 Volume (com.emc.storageos.db.client.model.Volume)98 URI (java.net.URI)86 NamedURI (com.emc.storageos.db.client.model.NamedURI)77 ArrayList (java.util.ArrayList)77 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)38 HashMap (java.util.HashMap)38 StringSet (com.emc.storageos.db.client.model.StringSet)29 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)27 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)19 FCTN_STRING_TO_URI (com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_STRING_TO_URI)18 Workflow (com.emc.storageos.workflow.Workflow)18 ApplicationAddVolumeList (com.emc.storageos.volumecontroller.ApplicationAddVolumeList)17 ControllerException (com.emc.storageos.volumecontroller.ControllerException)17 List (java.util.List)17 BlockOrchestrationController (com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController)16 VirtualPool (com.emc.storageos.db.client.model.VirtualPool)16 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)16 URISyntaxException (java.net.URISyntaxException)16 BlockConsistencyGroup (com.emc.storageos.db.client.model.BlockConsistencyGroup)15