Search in sources :

Example 1 with MigrationWorkflowCompleter

use of com.emc.storageos.vplexcontroller.completers.MigrationWorkflowCompleter 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)

Aggregations

VolumeDescriptor (com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor)1 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)1 Migration (com.emc.storageos.db.client.model.Migration)1 NamedURI (com.emc.storageos.db.client.model.NamedURI)1 Project (com.emc.storageos.db.client.model.Project)1 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)1 Volume (com.emc.storageos.db.client.model.Volume)1 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)1 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)1 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)1 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)1 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)1 ApplicationAddVolumeList (com.emc.storageos.volumecontroller.ApplicationAddVolumeList)1 ControllerException (com.emc.storageos.volumecontroller.ControllerException)1 TaskCompleter (com.emc.storageos.volumecontroller.TaskCompleter)1 CloneTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.CloneTaskCompleter)1 ExportTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter)1 VolumeTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeTaskCompleter)1 VplexMirrorTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.VplexMirrorTaskCompleter)1 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)1