Search in sources :

Example 21 with VolumeURIHLU

use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.

the class VmaxExportOperations method addVolumes.

@Override
public void addVolumes(StorageSystem storage, URI exportMaskURI, VolumeURIHLU[] volumeURIHLUs, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
    _log.info("{} addVolumes START...", storage.getSerialNumber());
    try {
        _log.info("addVolumes: Export mask id: {}", exportMaskURI);
        _log.info("addVolumes: volume-HLU pairs: {}", Joiner.on(',').join(volumeURIHLUs));
        if (initiatorList != null) {
            _log.info("addVolumes: initiators impacted: {}", Joiner.on(',').join(initiatorList));
        }
        boolean isVmax3 = storage.checkIfVmax3();
        ExportMask mask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
        ExportOperationContext context = new VmaxExportOperationContext();
        // Prime the context object
        taskCompleter.updateWorkflowStepContext(context);
        String maskingViewName = _helper.getExportMaskName(exportMaskURI);
        // Always get the Storage Group from masking View, rather than depending on the name to find out SG.
        String parentGroupName = _helper.getStorageGroupForGivenMaskingView(maskingViewName, storage);
        // Storage Group does not exist, remove the volumes from the mask.
        if (null == parentGroupName) {
            List<URI> volumeURIList = new ArrayList<URI>();
            for (VolumeURIHLU vuh : volumeURIHLUs) {
                volumeURIList.add(vuh.getVolumeURI());
            }
            mask.removeVolumes(volumeURIList);
            _dbClient.updateObject(mask);
            taskCompleter.error(_dbClient, DeviceControllerException.errors.vmaxStorageGroupNameNotFound(maskingViewName));
            return;
        }
        // For existing masking views on the array (co-existence),
        // if it has stand alone storage group, convert it into cascaded storage group.
        CIMObjectPath storageGroupPath = _cimPath.getMaskingGroupPath(storage, parentGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
        if (_helper.isStandAloneSG(storage, storageGroupPath)) {
            _log.info("Found Stand alone storage group, verifying the storage array version before converting it to Cascaded..");
            if (storage.checkIfVmax3()) {
                _log.info("Converting Stand alone storage group to Cascaded..");
                _helper.convertStandAloneStorageGroupToCascaded(storage, storageGroupPath, parentGroupName);
            } else {
                _log.info("Converting Stand alone storage group to Cascaded is not supported for VMAX2. Proceeding provisioning without conversion.");
            }
        }
        // Get the export mask initiator list. This is required to compute the storage group name
        Set<Initiator> initiators = ExportMaskUtils.getInitiatorsForExportMask(_dbClient, mask, null);
        // Flag to indicate whether or not we need to use the EMCForce flag on this operation.
        // We currently use this flag when dealing with RP Volumes as they are tagged for RP and the
        // operation on these volumes would fail otherwise.
        boolean forceFlag = false;
        // Determine if the volume is already in the masking view.
        // If so, log and remove from volumes we need to process.
        parentGroupName = _helper.getStorageGroupForGivenMaskingView(maskingViewName, storage);
        Set<String> deviceIds = _helper.getVolumeDeviceIdsFromStorageGroup(storage, parentGroupName);
        List<VolumeURIHLU> removeURIs = new ArrayList<>();
        for (VolumeURIHLU volumeUriHLU : volumeURIHLUs) {
            BlockObject bo = BlockObject.fetch(_dbClient, volumeUriHLU.getVolumeURI());
            if (deviceIds.contains(bo.getNativeId())) {
                _log.info("Found volume {} is already associated with masking view.  Assuming this is from a previous operation.", bo.getLabel());
                removeURIs.add(volumeUriHLU);
            }
        }
        // Create the new array of volumes that don't exist yet in the masking view.
        VolumeURIHLU[] addVolumeURIHLUs = new VolumeURIHLU[volumeURIHLUs.length - removeURIs.size()];
        int index = 0;
        for (VolumeURIHLU volumeUriHLU : volumeURIHLUs) {
            if (!removeURIs.contains(volumeUriHLU)) {
                addVolumeURIHLUs[index++] = volumeUriHLU;
            }
        }
        /**
         * Group Volumes by Fast Policy and Host IO limit attributes
         *
         * policyToVolumeGroupEntry - this will essentially have multiple Groups
         * E.g Group 1--> Fast Policy (FP1)+ FEBandwidth (100)
         * Group 2--> Fast Policy (FP2)+ IOPS (100)
         * Group 3--> FEBandwidth (100) + IOPS (100) ..
         */
        ListMultimap<StorageGroupPolicyLimitsParam, VolumeURIHLU> policyToVolumeGroup = ArrayListMultimap.create();
        for (VolumeURIHLU volumeUriHLU : addVolumeURIHLUs) {
            StorageGroupPolicyLimitsParam sgPolicyLimitsParam = null;
            URI boUri = volumeUriHLU.getVolumeURI();
            BlockObject bo = BlockObject.fetch(_dbClient, boUri);
            boolean fastAssociatedAlready = false;
            // Always treat fast volumes as non-fast if fast is associated on these volumes already
            // Export fast volumes to 2 different nodes.
            // Also note that Volumes with Compression set to true are also fast managed for VMAX3 Arrays.
            String policyName = volumeUriHLU.getAutoTierPolicyName();
            if (_helper.isFastPolicy(policyName) || ((isVmax3) && volumeUriHLU.getCompression())) {
                if (isVmax3) {
                    policyName = _helper.getVMAX3FastSettingForVolume(boUri, policyName);
                }
                fastAssociatedAlready = _helper.checkVolumeAssociatedWithAnySGWithPolicy(bo.getNativeId(), storage, policyName);
            }
            // should not be created with a FAST policy assigned.
            if (fastAssociatedAlready || isRPJournalVolume(bo)) {
                _log.info("Forcing policy name to NONE to prevent volume from using FAST policy.");
                volumeUriHLU.setAutoTierPolicyName(Constants.NONE);
                // Compression was applied on existing SG associated with policy!!
                volumeUriHLU.setCompression(false);
                sgPolicyLimitsParam = new StorageGroupPolicyLimitsParam(Constants.NONE, volumeUriHLU.getHostIOLimitBandwidth(), volumeUriHLU.getHostIOLimitIOPs(), storage);
            } else {
                if (isVmax3) {
                    sgPolicyLimitsParam = new StorageGroupPolicyLimitsParam(volumeUriHLU, storage, _helper);
                } else {
                    sgPolicyLimitsParam = new StorageGroupPolicyLimitsParam(volumeUriHLU, storage);
                }
            }
            policyToVolumeGroup.put(sgPolicyLimitsParam, volumeUriHLU);
            // The force flag only needs to be set once
            if (!forceFlag) {
                forceFlag = ExportUtils.useEMCForceFlag(_dbClient, volumeUriHLU.getVolumeURI());
            }
        }
        _log.info(" {} Groups generated based on grouping volumes by fast policy", policyToVolumeGroup.size());
        String storageGroupCustomTemplateName = CustomConfigConstants.VMAX_HOST_STORAGE_GROUP_MASK_NAME;
        String exportType = ExportMaskUtils.getExportType(_dbClient, mask);
        if (ExportGroupType.Cluster.name().equals(exportType)) {
            storageGroupCustomTemplateName = CustomConfigConstants.VMAX_CLUSTER_STORAGE_GROUP_MASK_NAME;
        }
        DataSource sgDataSource = ExportMaskUtils.getExportDatasource(storage, new ArrayList<Initiator>(initiators), dataSourceFactory, storageGroupCustomTemplateName);
        // Group volumes by Storage Group
        Map<String, Collection<VolumeURIHLU>> volumesByStorageGroup = _helper.groupVolumesByStorageGroup(storage, parentGroupName, sgDataSource, storageGroupCustomTemplateName, policyToVolumeGroup, customConfigHandler);
        // associate it with fast if needed, then add the new Child Group to the existing Parent Cascaded Group
        for (Entry<String, Collection<VolumeURIHLU>> volumesByStorageGroupEntry : volumesByStorageGroup.entrySet()) {
            VolumeURIHLU[] volumeURIHLUArray = null;
            // Even though policy and limits info are already in volumURIHLU, let's still extract to a holder for
            // easy access
            // Is it safe to not touch the below variable as it seems to be used by non VMAX3 cases only?
            StorageGroupPolicyLimitsParam volumePolicyLimitsParam = new StorageGroupPolicyLimitsParam(Constants.NONE);
            if (null != volumesByStorageGroupEntry.getValue()) {
                volumeURIHLUArray = volumesByStorageGroupEntry.getValue().toArray(new VolumeURIHLU[0]);
                volumePolicyLimitsParam = _helper.createStorageGroupPolicyLimitsParam(volumesByStorageGroupEntry.getValue(), storage, _dbClient);
            }
            String childGroupName = volumesByStorageGroupEntry.getKey().toString();
            if (isVmax3) {
                childGroupName = childGroupName.replaceAll(Constants.SMIS_PLUS_REGEX, Constants.UNDERSCORE_DELIMITER);
            }
            _log.info("Group Name : {} --- volume storage group name : {}", childGroupName, (volumeURIHLUArray != null ? Joiner.on("\t").join(volumeURIHLUArray) : ""));
            CIMObjectPath childGroupPath = _cimPath.getMaskingGroupPath(storage, childGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
            CIMInstance childGroupInstance = _helper.checkExists(storage, childGroupPath, false, false);
            if (null == childGroupInstance) {
                // For the newly created group, set policy, and other required properties bandwidth, iops as needed.
                // Once child group created, add this child Group to existing Parent Cascaded Group.
                // Empty child group is created to be able to add volumes with HLUs
                // once this child group is added in the cascaded storage group.
                _log.info("Group {} doesn't exist, creating a new group", childGroupName);
                CIMObjectPath childGroupCreated = createVolumeGroup(storage, childGroupName, volumeURIHLUArray, taskCompleter, false);
                _log.debug("Created Child Group {}", childGroupCreated);
                // Get childGroupName from the child group path childGroupCreated as it
                // could have been truncated in createVolumeGroup method
                childGroupName = _cimPath.getMaskingGroupName(storage, childGroupCreated);
                if (!isVmax3 && _helper.isFastPolicy(volumePolicyLimitsParam.getAutoTierPolicyName()) && !_helper.checkVolumeGroupAssociatedWithPolicy(storage, childGroupCreated, volumePolicyLimitsParam.getAutoTierPolicyName())) {
                    _log.debug("Adding Storage Group {} to Fast Policy {}", childGroupName, volumePolicyLimitsParam.getAutoTierPolicyName());
                    addVolumeGroupToAutoTieringPolicy(storage, volumePolicyLimitsParam.getAutoTierPolicyName(), childGroupCreated, taskCompleter);
                }
                // Add new Child Storage Group to Parent Cascaded Group
                // NOTE: host IO limit is set during the first child SG created with cascaded group.
                // Logically (or easy to follow) is to set limits after SG is created. However, because add job
                // logic
                // is executed in a queue. Hence, move update logic to SmisMaskingViewAddVolumeJob
                addGroupsToCascadedVolumeGroup(storage, parentGroupName, childGroupCreated, null, taskCompleter, forceFlag);
                _log.debug("Added newly created Storage Group {} to Parent Cascaded Group {}", childGroupName, parentGroupName);
                // Add volumes to the newly created child group
                _log.info("Adding Volumes to non cascaded Storage Group {} START", childGroupName);
                // Create a relatively empty completer associated with the export mask. We don't have the export
                // group
                // at this level, so there's nothing decent to attach the completer to anyway.
                String task = UUID.randomUUID().toString();
                ExportMaskVolumeToStorageGroupCompleter completer = new ExportMaskVolumeToStorageGroupCompleter(null, exportMaskURI, task);
                SmisMaskingViewAddVolumeJob job = new SmisMaskingViewAddVolumeJob(null, storage.getId(), exportMaskURI, volumeURIHLUArray, childGroupCreated, completer);
                job.setCIMObjectPathfactory(_cimPath);
                _helper.addVolumesToStorageGroup(volumeURIHLUArray, storage, childGroupName, job, forceFlag);
                ExportOperationContext.insertContextOperation(taskCompleter, VmaxExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_GROUP, childGroupName, volumeURIHLUArray, forceFlag);
                _log.info("Adding Volumes to non cascaded Storage Group {} END", childGroupName);
            } else // Only reusable groups will have null volumeURIHLUArray
            if (null != volumeURIHLUArray) {
                // Only add volumes that don't already exist in the StorageGroup
                VolumeURIHLU[] newVolumesToAdd = getVolumesThatAreNotAlreadyInSG(storage, childGroupPath, childGroupName, volumesByStorageGroupEntry.getValue().toArray(new VolumeURIHLU[0]));
                if (newVolumesToAdd != null) {
                    // We should not disturb any existing masking views on the Array. In this case, if the found
                    // storage group is not
                    // associated with expected fast policy, then we cannot proceed with neither of the below
                    // 1. Adding fast volumes to existing non fast storage group part of masking view
                    // 2. Creating a new Cascaded Group, and adding the existing storage group to it, as existing
                    // SG-->MV needs to be
                    // broken
                    StorageGroupPolicyLimitsParam childGroupKey = _helper.createStorageGroupPolicyLimitsParam(storage, childGroupInstance);
                    if (!isVmax3 && _helper.isFastPolicy(volumePolicyLimitsParam.getAutoTierPolicyName()) && !_helper.isFastPolicy(childGroupKey.getAutoTierPolicyName())) {
                        // Go through each volume associated with this storage group and pluck out by policy
                        for (StorageGroupPolicyLimitsParam phantomStorageGroupPolicyLimitsParam : policyToVolumeGroup.keySet()) {
                            String phantomPolicyName = phantomStorageGroupPolicyLimitsParam.getAutoTierPolicyName();
                            // If this is a non-FAST policy in the grouping, skip it.
                            if (!_helper.isFastPolicy(phantomPolicyName)) {
                                continue;
                            }
                            // Find the volumes in the volumeURIHLU associated with this policy
                            VolumeURIHLU[] phantomVolumesToAdd = getVolumesThatBelongToPolicy(newVolumesToAdd, phantomStorageGroupPolicyLimitsParam, storage);
                            _log.info(String.format("In order to add this volume to the masking view, we need to create/find a storage group " + "for the FAST policy %s and add the volume to the storage group and the existing storage group associated with the masking view", phantomStorageGroupPolicyLimitsParam));
                            // Check to see if there already is a phantom storage group with this policy on the
                            // array
                            List<String> phantomStorageGroupNames = _helper.findPhantomStorageGroupAssociatedWithFastPolicy(storage, phantomStorageGroupPolicyLimitsParam);
                            // If there's no existing phantom storage group, create one.
                            if (phantomStorageGroupNames == null || phantomStorageGroupNames.isEmpty()) {
                                // TODO: Probably need to use some name generator for this.
                                String phantomStorageGroupName = childGroupName + "_" + phantomStorageGroupPolicyLimitsParam;
                                // We need to create a new phantom storage group with our policy associated with it.
                                _log.info("phantom storage group {} doesn't exist, creating a new group", phantomStorageGroupName);
                                CIMObjectPath phantomStorageGroupCreated = createVolumeGroup(storage, phantomStorageGroupName, phantomVolumesToAdd, taskCompleter, true);
                                _log.info("Adding Storage Group {} to Fast Policy {}", phantomStorageGroupName, phantomPolicyName);
                                addVolumeGroupToAutoTieringPolicy(storage, phantomPolicyName, phantomStorageGroupCreated, taskCompleter);
                            } else {
                                // take the first matching phantom SG from the list
                                String phantomStorageGroupName = phantomStorageGroupNames.get(0);
                                // We found the phantom storage group, but we need to make sure the volumes aren't
                                // already in the
                                // storage
                                // group from a previous operation or manual intervention.
                                List<URI> phantomVolumeIds = new ArrayList<URI>();
                                for (VolumeURIHLU phantomVolume : phantomVolumesToAdd) {
                                    phantomVolumeIds.add(phantomVolume.getVolumeURI());
                                }
                                phantomVolumeIds.removeAll(_helper.findVolumesInStorageGroup(storage, phantomStorageGroupName, phantomVolumeIds));
                                if (phantomVolumeIds.isEmpty()) {
                                    _log.info("Found that the volume(s) we wanted to add to the phantom storage group are already added.");
                                } else {
                                    // If we found a phantom storage group with our policy, use it.
                                    _log.info("Found that we need to add volumes to the phantom storage group: " + phantomStorageGroupName);
                                    // Create a relatively empty completer associated with the export mask. We don't
                                    // have the export
                                    // group
                                    // at this level, so there's nothing decent to attach the completer to anyway.
                                    String task = UUID.randomUUID().toString();
                                    ExportMaskVolumeToStorageGroupCompleter completer = new ExportMaskVolumeToStorageGroupCompleter(null, exportMaskURI, task);
                                    SmisMaskingViewAddVolumeJob job = new SmisMaskingViewAddVolumeJob(null, storage.getId(), exportMaskURI, phantomVolumesToAdd, null, completer);
                                    job.setCIMObjectPathfactory(_cimPath);
                                    _helper.addVolumesToStorageGroup(phantomVolumesToAdd, storage, phantomStorageGroupName, job, forceFlag);
                                    ExportOperationContext.insertContextOperation(taskCompleter, VmaxExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_GROUP, phantomStorageGroupName, phantomVolumesToAdd, forceFlag);
                                    _log.info("Adding Volumes to non cascaded Storage Group {} END", phantomStorageGroupName);
                                }
                            }
                        }
                    }
                    if (isVmax3) {
                        // Remove volumes from the parking storage group
                        Set<String> nativeIds = new HashSet<String>();
                        for (VolumeURIHLU volURIHLU : newVolumesToAdd) {
                            nativeIds.add(_helper.getBlockObjectNativeId(volURIHLU.getVolumeURI()));
                        }
                        _helper.removeVolumeFromParkingSLOStorageGroup(storage, nativeIds.toArray(new String[] {}), forceFlag);
                    }
                    _log.info("Adding Volumes to non cascaded Storage Group {} START", childGroupName);
                    // Create a relatively empty completer associated with the export mask. We don't have the export
                    // group
                    // at this level, so there's nothing decent to attach the completer to anyway.
                    String task = UUID.randomUUID().toString();
                    ExportMaskVolumeToStorageGroupCompleter completer = new ExportMaskVolumeToStorageGroupCompleter(null, exportMaskURI, task);
                    SmisMaskingViewAddVolumeJob job = new SmisMaskingViewAddVolumeJob(null, storage.getId(), exportMaskURI, newVolumesToAdd, null, completer);
                    job.setCIMObjectPathfactory(_cimPath);
                    _helper.addVolumesToStorageGroup(newVolumesToAdd, storage, childGroupName, job, forceFlag);
                    ExportOperationContext.insertContextOperation(taskCompleter, VmaxExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_GROUP, childGroupName, newVolumesToAdd, forceFlag);
                    _log.info("Adding Volumes to non cascaded Storage Group {} END", childGroupName);
                } else {
                    // newVolumesToAdd == null, implying that all the requested
                    // volumes are already in the StorageGroup. This is a no-op.
                    _log.info("All volumes are already in the storage group");
                }
            } else // Else, we have existing groups which hold these volumes, hence add those groups to
            // cascaded group.
            {
                _log.info("Adding Existing Storage Group {} to Cascaded Group {} START :", childGroupName, parentGroupName);
                if (!isVmax3 && _helper.isFastPolicy(volumePolicyLimitsParam.getAutoTierPolicyName()) && !_helper.checkVolumeGroupAssociatedWithPolicy(storage, childGroupPath, volumePolicyLimitsParam.getAutoTierPolicyName())) {
                    _log.info("Adding Storage Group {} to Fast Policy {}", childGroupName, volumePolicyLimitsParam.getAutoTierPolicyName());
                    addVolumeGroupToAutoTieringPolicy(storage, volumePolicyLimitsParam.getAutoTierPolicyName(), childGroupPath, taskCompleter);
                }
                String task = UUID.randomUUID().toString();
                ExportMaskVolumeToStorageGroupCompleter completer = new ExportMaskVolumeToStorageGroupCompleter(null, exportMaskURI, task);
                SmisMaskingViewAddVolumeJob job = new SmisMaskingViewAddVolumeJob(null, storage.getId(), exportMaskURI, volumeURIHLUArray, null, completer);
                job.setCIMObjectPathfactory(_cimPath);
                addGroupsToCascadedVolumeGroup(storage, parentGroupName, childGroupPath, job, taskCompleter, forceFlag);
                _log.debug("Adding Existing Storage Group {} to Cascaded Group {} END :", childGroupName, parentGroupName);
            }
        }
        // Test mechanism to invoke a failure. No-op on production systems.
        InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_002);
        taskCompleter.ready(_dbClient);
    } catch (Exception e) {
        _log.error(String.format("addVolumes failed - maskName: %s", exportMaskURI.toString()), e);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
        taskCompleter.error(_dbClient, serviceError);
    }
    _log.info("{} addVolumes END...", storage.getSerialNumber());
}
Also used : Set(java.util.Set) Sets.newHashSet(com.google.common.collect.Sets.newHashSet) HashSet(java.util.HashSet) StringSet(com.emc.storageos.db.client.model.StringSet) ArrayList(java.util.ArrayList) URI(java.net.URI) CIMInstance(javax.cim.CIMInstance) ExportMaskVolumeToStorageGroupCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskVolumeToStorageGroupCompleter) Initiator(com.emc.storageos.db.client.model.Initiator) ExportOperationContext(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) BlockObject(com.emc.storageos.db.client.model.BlockObject) ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ExportMask(com.emc.storageos.db.client.model.ExportMask) CIMObjectPath(javax.cim.CIMObjectPath) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) ContainmentConstraint(com.emc.storageos.db.client.constraint.ContainmentConstraint) SmisException(com.emc.storageos.volumecontroller.impl.smis.SmisException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) WBEMException(javax.wbem.WBEMException) DataSource(com.emc.storageos.customconfigcontroller.DataSource) SmisMaskingViewAddVolumeJob(com.emc.storageos.volumecontroller.impl.smis.job.SmisMaskingViewAddVolumeJob) Collection(java.util.Collection) StorageGroupPolicyLimitsParam(com.emc.storageos.volumecontroller.impl.StorageGroupPolicyLimitsParam) VolumeURIHLU(com.emc.storageos.volumecontroller.impl.VolumeURIHLU)

Example 22 with VolumeURIHLU

use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.

the class VmaxExportOperations method createVolumeGroup.

// //////////// VMAX specific export helpers ////////////////
private CIMObjectPath createVolumeGroup(StorageSystem storage, String groupName, VolumeURIHLU[] volumeURIHLUs, TaskCompleter taskCompleter, boolean addVolumes) throws Exception {
    _log.debug("{} createVolumeGroup START...", storage.getSerialNumber());
    CIMObjectPath volumeGroupObjectPath = null;
    int index = 0;
    String[] volumeNames = new String[volumeURIHLUs.length];
    String policyName = null;
    // Flag to indicate whether or not we need to use the EMCForce flag on this operation.
    // We currently use this flag when dealing with RP Volumes as they are tagged for RP and the
    // operation on these volumes would fail otherwise.
    boolean setOnce = false;
    boolean forceFlag = false;
    boolean disableCompression = false;
    for (VolumeURIHLU volURIHlu : volumeURIHLUs) {
        String volumeNativeId = _helper.getBlockObjectNativeId(volURIHlu.getVolumeURI());
        volumeNames[index++] = volumeNativeId;
        if (null == policyName && storage.checkIfVmax3()) {
            policyName = _helper.getVMAX3FastSettingForVolume(volURIHlu.getVolumeURI(), volURIHlu.getAutoTierPolicyName(), volURIHlu.getCompression());
            if (_helper.checkVolumeAssociatedWithAnySGWithPolicy(volumeNativeId, storage, policyName)) {
                // A volume cannot be in multiple fast managed storage groups. Reset the fast policy
                policyName = Constants.NONE.toString();
            }
        }
        // The force flag only needs to be set once
        if (!setOnce) {
            setOnce = true;
            forceFlag = ExportUtils.useEMCForceFlag(_dbClient, volURIHlu.getVolumeURI());
            disableCompression = _helper.disableVMAX3Compression(volURIHlu.getVolumeURI(), storage);
        }
    }
    CIMArgument[] inArgs = null;
    String truncatedGroupName = groupName.length() >= 64 ? StringUtils.substring(groupName, 0, 63) : groupName;
    if (storage.checkIfVmax3()) {
        _helper.removeVolumeFromParkingSLOStorageGroup(storage, volumeNames, forceFlag);
        _log.info("Done invoking remove volumes from parking SLO storage group before export");
        policyName = _helper.getVMAX3FastSettingWithRightNoneString(storage, policyName);
        String[] tokens = policyName.split(Constants.SMIS_PLUS_REGEX);
        inArgs = _helper.getCreateVolumeGroupInputArguments(storage, truncatedGroupName, tokens[0], tokens[2], tokens[1], addVolumes ? volumeNames : null, disableCompression);
    } else {
        inArgs = _helper.getCreateVolumeGroupInputArguments(storage, truncatedGroupName, addVolumes ? volumeNames : null);
    }
    CIMArgument[] outArgs = new CIMArgument[5];
    try {
        _helper.invokeMethod(storage, _cimPath.getControllerConfigSvcPath(storage), "CreateGroup", inArgs, outArgs);
        volumeGroupObjectPath = _cimPath.getCimObjectPathFromOutputArgs(outArgs, "MaskingGroup");
        ExportOperationContext.insertContextOperation(taskCompleter, VmaxExportOperationContext.OPERATION_CREATE_STORAGE_GROUP, groupName, volumeURIHLUs);
    } catch (WBEMException we) {
        // If the VG by the same name exists, the WBEM exception thrown is CIM_ERR_FAILED.
        _log.info("{} Problem when trying to create volume group ... going to look up volume group.", storage.getSystemType(), we);
        volumeGroupObjectPath = handleCreateMaskingGroupException(storage, truncatedGroupName, inArgs, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
        if (volumeGroupObjectPath == null) {
            _log.info("{} Problem looking up volume group.", storage.getSerialNumber(), we);
            throw we;
        } else {
            _log.info("{} Found volume group.", storage.getSerialNumber());
        }
    }
    _log.debug("{} createVolumeGroup END...", storage.getSerialNumber());
    return volumeGroupObjectPath;
}
Also used : CIMObjectPath(javax.cim.CIMObjectPath) WBEMException(javax.wbem.WBEMException) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) ContainmentConstraint(com.emc.storageos.db.client.constraint.ContainmentConstraint) VolumeURIHLU(com.emc.storageos.volumecontroller.impl.VolumeURIHLU) CIMArgument(javax.cim.CIMArgument)

Example 23 with VolumeURIHLU

use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.

the class VmaxExportOperations method exportMaskRollback.

/**
 * Export mask operation rollback method.
 *
 * @param storage
 *            storage device
 * @param taskCompleter
 *            task completer
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
private void exportMaskRollback(StorageSystem storage, ExportOperationContext context, TaskCompleter taskCompleter) throws Exception {
    // Go through each operation and roll it back.
    if (context != null && context.getOperations() != null) {
        WBEMClient client = _helper.getConnection(storage).getCimClient();
        ListIterator li = context.getOperations().listIterator(context.getOperations().size());
        while (li.hasPrevious()) {
            ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
            // Flag to indicate whether or not we need to use the EMCForce flag on this operation.
            // We currently use this flag when dealing with RP Volumes as they are tagged for RP and the
            // operation on these volumes would fail otherwise.
            // 
            // IMPORTANT NOTE: Default is FALSE, each rollback method will need to determine if it should be set to
            // true if it is needed.
            boolean forceFlag = false;
            try {
                switch(operation.getOperation()) {
                    case VmaxExportOperationContext.OPERATION_ADD_INITIATORS_TO_INITIATOR_GROUP:
                        // remove initiators from the initiator group
                        List<Initiator> initiatorList = (List<Initiator>) operation.getArgs().get(0);
                        CIMObjectPath initiatorGroupPath = (CIMObjectPath) operation.getArgs().get(1);
                        CIMArgument[] inArgs = _helper.getRemoveInitiatorsFromMaskingGroupInputArguments(storage, initiatorGroupPath, initiatorList);
                        CIMArgument[] outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                        break;
                    case VmaxExportOperationContext.OPERATION_ADD_INITIATOR_GROUPS_TO_INITIATOR_GROUP:
                        // remove initiator groups from cascaded initiator group
                        CIMObjectPath childInitiatorGroup = (CIMObjectPath) operation.getArgs().get(0);
                        CIMObjectPath parentInitiatorGroup = (CIMObjectPath) operation.getArgs().get(1);
                        inArgs = _helper.getRemoveIGFromCIG(childInitiatorGroup, parentInitiatorGroup);
                        outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                        break;
                    case VmaxExportOperationContext.OPERATION_CREATE_CASCADING_STORAGE_GROUP:
                    case VmaxExportOperationContext.OPERATION_CREATE_STORAGE_GROUP:
                        // Delete storage group
                        String groupName = (String) operation.getArgs().get(0);
                        // .get(2) arg is different depending on the operation, but for now we don't need it so we
                        // won't get it.
                        _helper.deleteMaskingGroup(storage, groupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
                        break;
                    case VmaxExportOperationContext.OPERATION_CREATE_PORT_GROUP:
                        // Delete port group
                        groupName = (String) operation.getArgs().get(0);
                        _helper.deleteMaskingGroup(storage, groupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_TargetMaskingGroup);
                        break;
                    case VmaxExportOperationContext.OPERATION_ADD_TIER_TO_STORAGE_GROUP:
                        // Remove tier policy from storage group
                        String policyName = (String) operation.getArgs().get(0);
                        CIMObjectPath[] volumeGroupPaths = (CIMObjectPath[]) operation.getArgs().get(1);
                        for (CIMObjectPath volumeGroupPath : volumeGroupPaths) {
                            _helper.removeVolumeGroupFromPolicyAndLimitsAssociation(client, storage, volumeGroupPath);
                        }
                        break;
                    case VmaxExportOperationContext.OPERATION_ADD_STORAGE_GROUP_TO_CASCADING_STORAGE_GROUP:
                        // Remove storage group from cascading storage group
                        groupName = (String) operation.getArgs().get(0);
                        forceFlag = (boolean) operation.getArgs().get(2);
                        CIMObjectPath[] volumeGroupPathList = (CIMObjectPath[]) operation.getArgs().get(1);
                        inArgs = _helper.modifyCascadedStorageGroupInputArguments(storage, groupName, volumeGroupPathList, forceFlag);
                        outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                        break;
                    case VmaxExportOperationContext.OPERATION_CREATE_CASCADED_INITIATOR_GROUP:
                    case VmaxExportOperationContext.OPERATION_CREATE_INITIATOR_GROUP:
                        // Remove initiator group
                        groupName = (String) operation.getArgs().get(0);
                        _helper.deleteMaskingGroup(storage, groupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_InitiatorMaskingGroup);
                        break;
                    case VmaxExportOperationContext.OPERATION_CREATE_MASKING_VIEW:
                        // Remove masking view
                        String maskName = (String) operation.getArgs().get(0);
                        // Find the mask using the name
                        boolean foundMaskInDb = false;
                        ExportMask exportMask = null;
                        URIQueryResultList uriQueryList = new URIQueryResultList();
                        _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getExportMaskByNameConstraint(maskName), uriQueryList);
                        while (uriQueryList.iterator().hasNext()) {
                            URI uri = uriQueryList.iterator().next();
                            exportMask = _dbClient.queryObject(ExportMask.class, uri);
                            if (exportMask != null && !exportMask.getInactive() && exportMask.getStorageDevice().equals(storage.getId())) {
                                foundMaskInDb = true;
                                // given name for any storage array.
                                break;
                            }
                        }
                        // If we have the mask, check to see if we need to use the force flag
                        if (foundMaskInDb) {
                            for (String volURI : exportMask.getUserAddedVolumes().values()) {
                                forceFlag = ExportUtils.useEMCForceFlag(_dbClient, URI.create(volURI));
                                if (forceFlag) {
                                    break;
                                }
                            }
                        }
                        inArgs = _helper.getDeleteMaskingViewInputArguments(storage, maskName, forceFlag);
                        outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "DeleteMaskingView", inArgs, outArgs, null);
                        break;
                    case VmaxExportOperationContext.OPERATION_ADD_PORTS_TO_PORT_GROUP:
                        // Remove ports from port group
                        groupName = (String) operation.getArgs().get(0);
                        List<URI> targetURIList = (List<URI>) operation.getArgs().get(1);
                        inArgs = _helper.getRemoveTargetPortsFromMaskingGroupInputArguments(storage, groupName, targetURIList);
                        outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                        break;
                    case VmaxExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_GROUP:
                        // Remove volumes from storage group
                        groupName = (String) operation.getArgs().get(0);
                        forceFlag = (boolean) operation.getArgs().get(2);
                        VolumeURIHLU[] volumeList = (VolumeURIHLU[]) operation.getArgs().get(1);
                        List<URI> volumesInSG = new ArrayList<>();
                        for (VolumeURIHLU volumeUriHlu : volumeList) {
                            volumesInSG.add(volumeUriHlu.getVolumeURI());
                        }
                        inArgs = _helper.getRemoveVolumesFromMaskingGroupInputArguments(storage, groupName, volumesInSG, forceFlag);
                        outArgs = new CIMArgument[5];
                        _helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, null);
                        break;
                    case VmaxExportOperationContext.OPERATION_ADD_EXISTING_INITIATOR_TO_EXPORT_GROUP:
                        URI initiator = (URI) operation.getArgs().get(0);
                        _log.info("Not removing initiator: {} because it already existed in the masking view", initiator);
                        // Ensure the task completer does not remove it from ViPR ExportMask/Group.
                        ((ExportMaskRemoveInitiatorCompleter) taskCompleter).removeInitiator(initiator);
                        break;
                    default:
                }
            } catch (Exception e) {
                _log.error("Exception caught while running rollback", e);
                throw e;
            }
        }
    }
}
Also used : ExportMask(com.emc.storageos.db.client.model.ExportMask) CIMObjectPath(javax.cim.CIMObjectPath) ArrayList(java.util.ArrayList) ListIterator(java.util.ListIterator) URI(java.net.URI) ExportMaskRemoveInitiatorCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportMaskRemoveInitiatorCompleter) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) SmisException(com.emc.storageos.volumecontroller.impl.smis.SmisException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) WBEMException(javax.wbem.WBEMException) Initiator(com.emc.storageos.db.client.model.Initiator) ExportOperationContextOperation(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) WBEMClient(javax.wbem.client.WBEMClient) CIMArgument(javax.cim.CIMArgument) VolumeURIHLU(com.emc.storageos.volumecontroller.impl.VolumeURIHLU)

Example 24 with VolumeURIHLU

use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.

the class VmaxExportOperations method createMaskingView.

private void createMaskingView(StorageSystem storage, URI exportMaskURI, String maskingViewName, CIMObjectPath volumeGroupPath, VolumeURIHLU[] volumeURIHLUs, CIMObjectPath targetPortGroupPath, CIMObjectPath initiatorGroupPath, TaskCompleter taskCompleter) throws Exception {
    _log.info("{} createMaskingView START...", storage.getSerialNumber());
    // Flag to indicate whether or not we need to use the EMCForce flag on this operation.
    // We currently use this flag when dealing with RP Volumes as they are tagged for RP and the
    // operation on these volumes would fail otherwise.
    boolean forceFlag = false;
    List<String> deviceNumbers = new ArrayList<String>();
    for (VolumeURIHLU volURIHlu : volumeURIHLUs) {
        String hlu = volURIHlu.getHLU();
        // LUN_UNASSIGNED value (as a hex string).
        if (hlu != null && !hlu.equalsIgnoreCase(ExportGroup.LUN_UNASSIGNED_STR)) {
            deviceNumbers.add(hlu);
        }
        // The force flag only needs to be set once
        if (!forceFlag) {
            forceFlag = ExportUtils.useEMCForceFlag(_dbClient, volURIHlu.getVolumeURI());
        }
    }
    String[] deviceNumbersStr = {};
    CIMArgument[] inMVArgs = _helper.getCreateMaskingViewInputArguments(volumeGroupPath, targetPortGroupPath, initiatorGroupPath, deviceNumbers.toArray(deviceNumbersStr), maskingViewName, forceFlag);
    CIMArgument[] outMVArgs = new CIMArgument[5];
    try {
        _helper.invokeMethod(storage, _cimPath.getControllerConfigSvcPath(storage), "CreateMaskingView", inMVArgs, outMVArgs);
        CIMObjectPath cimJobPath = _cimPath.getCimObjectPathFromOutputArgs(outMVArgs, "Job");
        if (cimJobPath != null) {
            ControllerServiceImpl.enqueueJob(new QueueJob(new SmisCreateMaskingViewJob(cimJobPath, storage.getId(), exportMaskURI, volumeURIHLUs, volumeGroupPath, taskCompleter)));
        } else {
            // simulated environments
            throw new WBEMException("No output argument was returned from CreateMaskingView operation");
        }
    // Rollback context is set in the job upon completion.
    } catch (WBEMException we) {
        _log.info("{} Problem when trying to create masking view ... going to look up masking view.", storage.getSerialNumber(), we);
        boolean handleException = false;
        try {
            handleException = handleCreateMaskingViewException(storage, maskingViewName);
        } catch (Exception e) {
            _log.error("Issue trying to handle Export Mask exception", e);
        }
        if (handleException) {
            _log.info("{} Found masking view: {}", storage.getSerialNumber(), maskingViewName);
            taskCompleter.ready(_dbClient);
        } else {
            _log.debug("{} Problem when looking up masking view: {}", storage.getSerialNumber(), maskingViewName);
            throw we;
        }
    }
    _log.info("{} createMaskingView END...", storage.getSerialNumber());
}
Also used : ArrayList(java.util.ArrayList) CIMObjectPath(javax.cim.CIMObjectPath) SmisCreateMaskingViewJob(com.emc.storageos.volumecontroller.impl.smis.job.SmisCreateMaskingViewJob) WBEMException(javax.wbem.WBEMException) SmisException(com.emc.storageos.volumecontroller.impl.smis.SmisException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) WBEMException(javax.wbem.WBEMException) QueueJob(com.emc.storageos.volumecontroller.impl.job.QueueJob) VolumeURIHLU(com.emc.storageos.volumecontroller.impl.VolumeURIHLU) CIMArgument(javax.cim.CIMArgument)

Example 25 with VolumeURIHLU

use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.

the class VmaxExportOperations method getVolumesThatBelongToPolicy.

/**
 * Convenience method that collects volumes from the array that match the storage group.
 *
 * @param volumeURIHLUs
 *            volume objects
 * @param storageGroupPolicyLimitsParam
 *            storage group attributes
 * @return thinned-out list of volume objects that correspond to the supplied policy, or null
 */
private VolumeURIHLU[] getVolumesThatBelongToPolicy(VolumeURIHLU[] volumeURIHLUs, StorageGroupPolicyLimitsParam storageGroupPolicyLimitsParam, StorageSystem storage) {
    VolumeURIHLU[] result = null;
    Set<VolumeURIHLU> volumeURIHLUSet = new HashSet<VolumeURIHLU>();
    for (VolumeURIHLU volumeURIHLU : volumeURIHLUs) {
        StorageGroupPolicyLimitsParam tmpKey = new StorageGroupPolicyLimitsParam(volumeURIHLU.getAutoTierPolicyName(), volumeURIHLU.getHostIOLimitBandwidth(), volumeURIHLU.getHostIOLimitIOPs(), storage);
        if (tmpKey.equals(storageGroupPolicyLimitsParam)) {
            volumeURIHLUSet.add(volumeURIHLU);
        }
    }
    if (!volumeURIHLUSet.isEmpty()) {
        result = new VolumeURIHLU[volumeURIHLUSet.size()];
        result = volumeURIHLUSet.toArray(result);
    }
    return result;
}
Also used : StorageGroupPolicyLimitsParam(com.emc.storageos.volumecontroller.impl.StorageGroupPolicyLimitsParam) VolumeURIHLU(com.emc.storageos.volumecontroller.impl.VolumeURIHLU) Sets.newHashSet(com.google.common.collect.Sets.newHashSet) HashSet(java.util.HashSet)

Aggregations

VolumeURIHLU (com.emc.storageos.volumecontroller.impl.VolumeURIHLU)35 URI (java.net.URI)26 ArrayList (java.util.ArrayList)22 BlockObject (com.emc.storageos.db.client.model.BlockObject)19 ExportMask (com.emc.storageos.db.client.model.ExportMask)18 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)17 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)14 HashMap (java.util.HashMap)14 HashSet (java.util.HashSet)13 CIMObjectPath (javax.cim.CIMObjectPath)13 Initiator (com.emc.storageos.db.client.model.Initiator)9 WBEMException (javax.wbem.WBEMException)9 AlternateIdConstraint (com.emc.storageos.db.client.constraint.AlternateIdConstraint)8 StorageGroupPolicyLimitsParam (com.emc.storageos.volumecontroller.impl.StorageGroupPolicyLimitsParam)7 CIMInstance (javax.cim.CIMInstance)7 Volume (com.emc.storageos.db.client.model.Volume)6 ContainmentConstraint (com.emc.storageos.db.client.constraint.ContainmentConstraint)5 StringSet (com.emc.storageos.db.client.model.StringSet)5 SmisException (com.emc.storageos.volumecontroller.impl.smis.SmisException)5 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)4