Search in sources :

Example 96 with Project

use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.

the class VPlexDeviceController method importVolume.

/**
 * Updated importVolume code to create underlying volumes using other controllers.
 *
 * @param volumeDescriptors
 *            -- Contains the VPLEX_VIRTUAL volume, and optionally,
 *            a protection BLOCK_DATA volume to be created.
 * @param vplexSystemProject
 * @param vplexSystemTenant
 * @param importedVolumeURI
 *            -- For the import use case, will give the URI of the existing
 *            storage array volume to be imported.
 * @param newCosURI
 * @param opId
 * @throws ControllerException
 */
@Override
public void importVolume(URI vplexURI, List<VolumeDescriptor> volumeDescriptors, URI vplexSystemProject, URI vplexSystemTenant, URI newCosURI, String newLabel, String setTransferSpeed, Boolean markInactive, String opId) throws ControllerException {
    // Figure out the various arguments.
    List<VolumeDescriptor> vplexDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
    // must be one VPLEX volume
    Assert.isTrue(vplexDescriptors.size() == 1);
    VolumeDescriptor vplexDescriptor = vplexDescriptors.get(0);
    URI vplexVolumeURI = vplexDescriptor.getVolumeURI();
    List<URI> volumeURIs = new ArrayList<URI>();
    volumeURIs.add(vplexVolumeURI);
    // See if there are any volumes to be created.
    List<VolumeDescriptor> blockDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.BLOCK_DATA }, new VolumeDescriptor.Type[] {});
    URI createdVolumeURI = null;
    if (blockDescriptors.size() == 1) {
        createdVolumeURI = blockDescriptors.get(0).getVolumeURI();
    }
    Map<URI, StorageSystem> arrayMap = buildArrayMap(null, blockDescriptors, null);
    Map<URI, Volume> volumeMap = buildVolumeMap(null, blockDescriptors, null);
    if (!blockDescriptors.isEmpty()) {
        volumeURIs.addAll(VolumeDescriptor.getVolumeURIs(blockDescriptors));
    }
    // See if there is a Volume to be imported.
    List<VolumeDescriptor> importDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.VPLEX_IMPORT_VOLUME }, new VolumeDescriptor.Type[] {});
    URI importedVolumeURI = null;
    if (!importDescriptors.isEmpty()) {
        importedVolumeURI = importDescriptors.get(0).getVolumeURI();
        volumeURIs.add(importedVolumeURI);
    }
    // Get the VPlex storage system and the volumes.
    StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
    Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
    // If there is a volume to be imported, we're creating a new Virtual Volume from
    // the imported volume. Otherwise, we're upgrading an existing Virtual Volume to be
    // distributed.
    StorageSystem importedArray = null;
    Volume importedVolume = null;
    if (importedVolumeURI != null) {
        importedVolume = getDataObject(Volume.class, importedVolumeURI, _dbClient);
        importedArray = getDataObject(StorageSystem.class, importedVolume.getStorageController(), _dbClient);
        arrayMap.put(importedArray.getId(), importedArray);
        volumeMap.put(importedVolumeURI, importedVolume);
    }
    try {
        // Generate the Workflow.
        Workflow workflow = _workflowService.getNewWorkflow(this, IMPORT_VOLUMES_WF_NAME, false, opId);
        String waitFor = null;
        // Add a rollback step to remove the Virtual Volume if we are
        // importing and therefore creating a new virtual volume.
        List<URI> vplexVolumeURIs = new ArrayList<URI>();
        vplexVolumeURIs.add(vplexVolumeURI);
        if (importedVolumeURI != null) {
            Workflow.Method nullMethod = rollbackMethodNullMethod();
            Workflow.Method virtVolInactiveMethod = markVolumesInactiveMethod(vplexVolumeURIs);
            waitFor = workflow.createStep(null, "Mark virtual volume inactive on rollback", waitFor, vplexURI, vplexSystem.getSystemType(), this.getClass(), nullMethod, virtVolInactiveMethod, null);
        }
        // to which the data for the virtual volume will saved (if used).
        if (createdVolumeURI != null) {
            waitFor = _blockDeviceController.addStepsForCreateVolumes(workflow, waitFor, volumeDescriptors, opId);
        }
        // Set the project and tenant to those of an underlying volume.
        Volume firstVolume = volumeMap.values().iterator().next();
        URI projectURI = firstVolume.getProject().getURI();
        URI tenantURI = firstVolume.getTenant().getURI();
        Project project = _dbClient.queryObject(Project.class, projectURI);
        // the VPlex can see these new backend volumes.
        if (!project.checkInternalFlags(Flag.INTERNAL_OBJECT) && vplexSystemProject != null && vplexSystemTenant != null) {
            // If project is not set as an INTERAL_OBJECT then this is the case
            // where native volume is moved into VPLEX.
            // vplexSystemProject and vplexSystemTenant are passed in this case
            // and we need to use that else backend export group gets visible
            // in UI as the native volume project at this point is not a VPLEX
            // project.
            createWorkflowStepsForBlockVolumeExport(workflow, vplexSystem, arrayMap, volumeMap, vplexSystemProject, vplexSystemTenant, waitFor);
        } else {
            createWorkflowStepsForBlockVolumeExport(workflow, vplexSystem, arrayMap, volumeMap, projectURI, tenantURI, waitFor);
        }
        String transferSize = null;
        // "rebuild set-transfer-speed" command.
        if (setTransferSpeed != null) {
            transferSize = migrationSpeedToTransferSizeMap.get(setTransferSpeed);
            if (transferSize == null) {
                _log.info("Transfer speed parameter {} is invalid", setTransferSpeed);
            }
        }
        if (transferSize == null) {
            String speed = customConfigHandler.getComputedCustomConfigValue(CustomConfigConstants.MIGRATION_SPEED, vplexSystem.getSystemType(), null);
            _log.info("Migration speed is {}", speed);
            transferSize = migrationSpeedToTransferSizeMap.get(speed);
        }
        // Now make a Step to create the VPlex Virtual volumes.
        // This will be done from this controller.
        String stepId = workflow.createStepId();
        Workflow.Method vplexExecuteMethod = createVirtualVolumeFromImportMethod(vplexVolume.getStorageController(), vplexVolumeURI, importedVolumeURI, createdVolumeURI, vplexSystemProject, vplexSystemTenant, newCosURI, newLabel, transferSize);
        Workflow.Method vplexRollbackMethod = null;
        if (importedVolumeURI != null) {
            // If importing to a local/distributed virtual volume, then
            // rollback the VPlex create virtual volumes operation.
            // We will restore the original volume.
            vplexRollbackMethod = deleteVirtualVolumesMethod(vplexURI, vplexVolumeURIs, null);
        } else {
            // COP-16861: If rolling back an upgrade from local to distributed, then
            // try to detach remote mirror and delete new artifacts created on VPLEX
            // and clean up backend array volume.
            // Without this rollback method with original code, if we failed to clean-up
            // on VPLEX it used to still clean-up backed volume which would leave VPLEX
            // volume in bad state. With this rollback we will clean-up backend array only
            // if we were successful in clean-up on VPLEX.
            // We will restore the VPlex local volume.
            vplexRollbackMethod = rollbackUpgradeVirtualVolumeLocalToDistributedMethod(vplexURI, vplexVolume.getDeviceLabel(), vplexVolume.getNativeId(), stepId);
        }
        workflow.createStep(VPLEX_STEP, String.format("VPlex %s creating virtual volume", vplexSystem.getId().toString()), EXPORT_STEP, vplexURI, vplexSystem.getSystemType(), this.getClass(), vplexExecuteMethod, vplexRollbackMethod, stepId);
        // simply trying to wait until the rebuild completes.
        if (createdVolumeURI != null) {
            createWorkflowStepForWaitOnRebuild(workflow, vplexSystem, vplexVolumeURI, VPLEX_STEP);
        }
        if (importedVolume != null && importedVolume.getConsistencyGroup() != null) {
            // Add virtual volume to a Vplex consistency group.
            ConsistencyGroupManager consistencyGroupManager = getConsistencyGroupManager(vplexVolume);
            List<URI> volsForCG = Arrays.asList(vplexVolumeURI);
            consistencyGroupManager.addStepsForCreateConsistencyGroup(workflow, VPLEX_STEP, vplexSystem, volsForCG, false);
        }
        // Finish up and execute the plan.
        // The Workflow will handle the TaskCompleter
        String successMessage;
        if (importedVolumeURI != null) {
            successMessage = "Import volume to VPLEX virtual volume successful for: " + vplexVolumeURIs.toString();
        } else {
            successMessage = "Upgrade local VPLEX volume to distributed successful for: " + vplexVolumeURIs.toString();
        }
        TaskCompleter completer = new VPlexTaskCompleter(Volume.class, volumeURIs, opId, null);
        ImportRollbackHandler importRollbackHandler = new ImportRollbackHandler();
        Object[] importRollbackHandlerArgs = new Object[] { importedVolumeURI, createdVolumeURI, vplexVolumeURI };
        // TODO DUPP CWF COP-22431: This is a child workflow, needs idempotent check (1 of three flows seems like a
        // subflow)
        workflow.executePlan(completer, successMessage, null, null, importRollbackHandler, importRollbackHandlerArgs);
    } catch (Exception ex) {
        ServiceError serviceError;
        if (importedVolumeURI != null) {
            _log.error("Could not import volume for vplex: " + vplexURI, ex);
            String opName = ResourceOperationTypeEnum.IMPORT_BLOCK_VOLUME.getName();
            serviceError = VPlexApiException.errors.importVolumeFailedException(opName, ex);
        } else {
            _log.error("Could not upgrade volume for vplex: " + vplexURI, ex);
            String opName = ResourceOperationTypeEnum.UPGRADE_VPLEX_LOCAL_TO_DISTRIBUTED.getName();
            serviceError = VPlexApiException.errors.upgradeLocalToDistributedFailedException(opName, ex);
        }
        TaskCompleter completer = new VPlexTaskCompleter(Volume.class, volumeURIs, opId, null);
        failStep(completer, opId, serviceError);
        // here.
        if (markInactive) {
            // operation, rather than an upgrade of a local volume to distributed.
            if ((importedVolumeURI != null) && (vplexVolume != null)) {
                _dbClient.removeObject(vplexVolume);
            }
            // the VPLEX volume for deletion.
            if (createdVolumeURI != null) {
                Volume createdVolume = _dbClient.queryObject(Volume.class, createdVolumeURI);
                if (createdVolume != null) {
                    _dbClient.removeObject(createdVolume);
                }
            }
            // a non-VPLEX volume to VPLEX, this will be a public volume.
            if ((importedVolume != null) && (importedVolume.checkInternalFlags(DataObject.Flag.INTERNAL_OBJECT))) {
                _dbClient.removeObject(importedVolume);
            }
        }
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) 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) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) 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) Volume(com.emc.storageos.db.client.model.Volume) DiscoveredDataObject(com.emc.storageos.db.client.model.DiscoveredDataObject) DataObject(com.emc.storageos.db.client.model.DataObject) VPlexControllerUtils.getDataObject(com.emc.storageos.vplexcontroller.VPlexControllerUtils.getDataObject) BlockObject(com.emc.storageos.db.client.model.BlockObject) MigrationTaskCompleter(com.emc.storageos.vplexcontroller.completers.MigrationTaskCompleter) VolumeGroupUpdateTaskCompleter(com.emc.storageos.vplexcontroller.completers.VolumeGroupUpdateTaskCompleter) ExportTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter) 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) TaskCompleter(com.emc.storageos.volumecontroller.TaskCompleter) WorkflowTaskCompleter(com.emc.storageos.workflow.WorkflowTaskCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 97 with Project

use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.

the class VPlexDeviceController method prepareVolumeDescriptor.

/**
 * Create a volume instance and VolumeDescriptor using the characteristics of the passed in source volume.
 *
 * @param source
 *            - The volume will be used to create the volume instance
 * @param name
 *            - The new volume label
 * @param type
 *            - VolumeDescriptor type
 * @param size
 *            - The volume size
 * @param isInternal
 *            -If the volume is internal
 * @return - The newly created VolumeDescriptor
 */
private VolumeDescriptor prepareVolumeDescriptor(Volume source, String name, VolumeDescriptor.Type type, long size, boolean isInternal) {
    Volume volume = new Volume();
    volume.setId(URIUtil.createId(Volume.class));
    volume.setLabel(name);
    volume.setCapacity(size);
    URI vpoolUri = source.getVirtualPool();
    VirtualPool vpool = getDataObject(VirtualPool.class, vpoolUri, _dbClient);
    volume.setThinlyProvisioned(VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(vpool.getSupportedProvisioningType()));
    volume.setVirtualPool(vpool.getId());
    URI projectId = source.getProject().getURI();
    Project project = getDataObject(Project.class, projectId, _dbClient);
    volume.setProject(new NamedURI(projectId, volume.getLabel()));
    volume.setTenant(new NamedURI(project.getTenantOrg().getURI(), volume.getLabel()));
    volume.setVirtualArray(source.getVirtualArray());
    volume.setPool(source.getPool());
    volume.setProtocol(source.getProtocol());
    volume.setStorageController(source.getStorageController());
    volume.setSystemType(source.getSystemType());
    if (isInternal) {
        volume.addInternalFlags(Flag.INTERNAL_OBJECT);
    }
    _dbClient.createObject(volume);
    VirtualPoolCapabilityValuesWrapper capabilities = getCapabilities(source, size);
    return new VolumeDescriptor(type, volume.getStorageController(), volume.getId(), volume.getPool(), capabilities);
}
Also used : VirtualPoolCapabilityValuesWrapper(com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper) Project(com.emc.storageos.db.client.model.Project) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume) NamedURI(com.emc.storageos.db.client.model.NamedURI) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI)

Example 98 with Project

use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.

the class VPlexDeviceController method promoteMirror.

/**
 * This method creates the virtual volume from the detached mirror device.
 *
 * @param vplexURI
 *            The vplex storage system URI
 * @param vplexMirrorURI
 *            The URI of the vplex mirror that needs to be promoted to the virtual volume
 * @param promoteVolumeURI
 *            The URI of the volume will be used as a promoted vplex volume
 * @param stepId
 *            The worflow stepId
 *
 * @throws WorkflowException
 *             When an error occurs updating the workflow step
 *             state.
 */
public void promoteMirror(URI vplexURI, URI vplexMirrorURI, URI promoteVolumeURI, String stepId) throws WorkflowException {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexURI, _dbClient);
        VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
        Volume sourceVplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
        Volume promoteVolume = _dbClient.queryObject(Volume.class, promoteVolumeURI);
        // Find virtual volume that should have been created when we did detach mirror.
        // Virtual volume is created with the same name as the device name.
        VPlexVirtualVolumeInfo vvInfo = client.findVirtualVolume(vplexMirror.getDeviceLabel(), null);
        // Get the backend volume for this promoted VPLEX volume.
        StringSet assocVolumes = vplexMirror.getAssociatedVolumes();
        // Get the ViPR label for the promoted VPLEX volume.
        String promotedLabel = String.format("%s-%s", sourceVplexVolume.getLabel(), vplexMirror.getLabel());
        // Rename the vplex volume created using device detach mirror. If custom naming is enabled
        // generate the custom name, else the name follows the default naming convention and must
        // be renamed to append the "_vol" suffix.
        String newVolumeName = null;
        try {
            if (CustomVolumeNamingUtils.isCustomVolumeNamingEnabled(customConfigHandler, DiscoveredDataObject.Type.vplex.name())) {
                String customConfigName = CustomConfigConstants.CUSTOM_VOLUME_NAME;
                Project project = _dbClient.queryObject(Project.class, promoteVolume.getProject().getURI());
                TenantOrg tenant = _dbClient.queryObject(TenantOrg.class, promoteVolume.getTenant().getURI());
                DataSource customNameDataSource = CustomVolumeNamingUtils.getCustomConfigDataSource(project, tenant, promotedLabel, vvInfo.getWwn(), null, dataSourceFactory, customConfigName, _dbClient);
                if (customNameDataSource != null) {
                    newVolumeName = CustomVolumeNamingUtils.getCustomName(customConfigHandler, customConfigName, customNameDataSource, DiscoveredDataObject.Type.vplex.name());
                }
                // Rename the vplex volume created using device detach mirror,
                vvInfo = CustomVolumeNamingUtils.renameVolumeOnVPlex(vvInfo, newVolumeName, client);
                promotedLabel = newVolumeName;
            } else {
                // Build the name for volume so as to rename the vplex volume that is created
                // with the same name as the device name to follow the name pattern _vol
                // as the suffix for the vplex volumes
                StringBuilder volumeNameBuilder = new StringBuilder();
                volumeNameBuilder.append(vplexMirror.getDeviceLabel());
                volumeNameBuilder.append(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX);
                newVolumeName = volumeNameBuilder.toString();
                // Rename the vplex volume created using device detach mirror,
                vvInfo = CustomVolumeNamingUtils.renameVolumeOnVPlex(vvInfo, newVolumeName, client);
            }
        } catch (Exception e) {
            _log.warn(String.format("Error renaming promoted VPLEX volume %s", promoteVolumeURI), e);
        }
        _log.info(String.format("Renamed promoted virtual volume: %s path: %s", vvInfo.getName(), vvInfo.getPath()));
        // Fill in the details for the promoted vplex volume
        promoteVolume.setLabel(promotedLabel);
        promoteVolume.setNativeId(vvInfo.getPath());
        promoteVolume.setNativeGuid(vvInfo.getPath());
        promoteVolume.setDeviceLabel(vvInfo.getName());
        promoteVolume.setThinlyProvisioned(vvInfo.isThinEnabled());
        promoteVolume.setWWN(vvInfo.getWwn());
        // For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
        promoteVolume.setAllocatedCapacity(0L);
        promoteVolume.setCapacity(vplexMirror.getCapacity());
        promoteVolume.setProvisionedCapacity(vplexMirror.getProvisionedCapacity());
        promoteVolume.setVirtualPool(vplexMirror.getVirtualPool());
        promoteVolume.setVirtualArray(vplexMirror.getVirtualArray());
        promoteVolume.setStorageController(vplexMirror.getStorageController());
        promoteVolume.setSystemType(DiscoveredDataObject.Type.vplex.name());
        promoteVolume.setPool(NullColumnValueGetter.getNullURI());
        promoteVolume.setAssociatedVolumes(new StringSet(assocVolumes));
        promoteVolume.setThinlyProvisioned(vplexMirror.getThinlyProvisioned());
        promoteVolume.setThinVolumePreAllocationSize(vplexMirror.getThinPreAllocationSize());
        // VPLEX volumes created by VIPR have syncActive set to true hence setting same value for promoted vplex
        // volumes
        promoteVolume.setSyncActive(true);
        // Also, we update the name portion of the project and tenant URIs
        // to reflect the new name. This is necessary because the API
        // to search for volumes by project, extracts the name portion of the
        // project URI to get the volume name.
        NamedURI namedURI = promoteVolume.getProject();
        namedURI.setName(promotedLabel);
        promoteVolume.setProject(namedURI);
        namedURI = promoteVolume.getTenant();
        namedURI.setName(promotedLabel);
        promoteVolume.setTenant(namedURI);
        // Remove mirror from the source VPLEX volume
        sourceVplexVolume.getMirrors().remove(vplexMirror.getId().toString());
        _dbClient.updateObject(sourceVplexVolume);
        // Delete the mirror object
        _dbClient.removeObject(vplexMirror);
        // Persist changes for the newly promoted volume
        _dbClient.updateObject(promoteVolume);
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        _log.error("Exception promoting mirror volume: " + vae.getMessage(), vae);
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception ex) {
        _log.error("Exception promoting mirror volume: " + ex.getMessage(), ex);
        ServiceError serviceError = VPlexApiException.errors.promoteMirrorFailed(ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) NamedURI(com.emc.storageos.db.client.model.NamedURI) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) DataSource(com.emc.storageos.customconfigcontroller.DataSource) Project(com.emc.storageos.db.client.model.Project) 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) TenantOrg(com.emc.storageos.db.client.model.TenantOrg) VplexMirror(com.emc.storageos.db.client.model.VplexMirror)

Example 99 with Project

use of com.emc.storageos.db.client.model.Project 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) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) 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) MigrationTaskCompleter(com.emc.storageos.vplexcontroller.completers.MigrationTaskCompleter) VolumeGroupUpdateTaskCompleter(com.emc.storageos.vplexcontroller.completers.VolumeGroupUpdateTaskCompleter) ExportTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter) 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) TaskCompleter(com.emc.storageos.volumecontroller.TaskCompleter) WorkflowTaskCompleter(com.emc.storageos.workflow.WorkflowTaskCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 100 with Project

use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.

the class ProtectionSetToBlockConsistencyGroupMigration method createRpBlockConsistencyGroups.

/**
 * Create RP BlockConsistencyGroup objects for each ProtectionSet.
 */
private void createRpBlockConsistencyGroups() {
    DbClient dbClient = this.getDbClient();
    List<URI> protectionSetURIs = dbClient.queryByType(ProtectionSet.class, false);
    Iterator<ProtectionSet> protectionSets = dbClient.queryIterativeObjects(ProtectionSet.class, protectionSetURIs);
    while (protectionSets.hasNext()) {
        ProtectionSet ps = protectionSets.next();
        Project project = dbClient.queryObject(Project.class, ps.getProject());
        BlockConsistencyGroup cg = new BlockConsistencyGroup();
        cg.setId(URIUtil.createId(BlockConsistencyGroup.class));
        cg.setLabel(ps.getLabel());
        cg.setDeviceName(ps.getLabel());
        cg.setType(BlockConsistencyGroup.Types.RP.toString());
        cg.setProject(new NamedURI(project.getId(), project.getLabel()));
        cg.setTenant(project.getTenantOrg());
        dbClient.createObject(cg);
        log.debug("Created ConsistencyGroup (id={}) based on ProtectionSet (id={})", cg.getId().toString(), ps.getId().toString());
        // Organize the volumes by replication set
        for (String protectionVolumeID : ps.getVolumes()) {
            URI uri = URI.create(protectionVolumeID);
            Volume protectionVolume = dbClient.queryObject(Volume.class, uri);
            protectionVolume.addConsistencyGroup(cg.getId().toString());
            dbClient.persistObject(protectionVolume);
            log.debug("Volume (id={}) added to ConsistencyGroup (id={})", protectionVolume.getId().toString(), cg.getId().toString());
        }
    }
}
Also used : Project(com.emc.storageos.db.client.model.Project) DbClient(com.emc.storageos.db.client.DbClient) NamedURI(com.emc.storageos.db.client.model.NamedURI) Volume(com.emc.storageos.db.client.model.Volume) ProtectionSet(com.emc.storageos.db.client.model.ProtectionSet) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup)

Aggregations

Project (com.emc.storageos.db.client.model.Project)191 URI (java.net.URI)98 NamedURI (com.emc.storageos.db.client.model.NamedURI)93 ArrayList (java.util.ArrayList)67 VirtualPool (com.emc.storageos.db.client.model.VirtualPool)66 Volume (com.emc.storageos.db.client.model.Volume)58 TenantOrg (com.emc.storageos.db.client.model.TenantOrg)55 VirtualArray (com.emc.storageos.db.client.model.VirtualArray)50 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)47 StringSet (com.emc.storageos.db.client.model.StringSet)43 VirtualPoolCapabilityValuesWrapper (com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper)40 List (java.util.List)37 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)36 Produces (javax.ws.rs.Produces)35 BlockConsistencyGroup (com.emc.storageos.db.client.model.BlockConsistencyGroup)33 Test (org.junit.Test)31 CheckPermission (com.emc.storageos.security.authorization.CheckPermission)28 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)27 Operation (com.emc.storageos.db.client.model.Operation)27 Consumes (javax.ws.rs.Consumes)27