use of javax.wbem.client.WBEMClient in project coprhd-controller by CoprHD.
the class VmaxExportOperations method setVSAFlagForIG.
private void setVSAFlagForIG(StorageSystem storage, CIMObjectPath initiatorGroupPath, boolean VSAFlag) throws Exception {
WBEMClient client = _helper.getConnection(storage).getCimClient();
CIMPropertyFactory factoryRef = (CIMPropertyFactory) ControllerServiceImpl.getBean("CIMPropertyFactory");
CIMInstance toUpdate = new CIMInstance(initiatorGroupPath, new CIMProperty[] { factoryRef.bool(SmisConstants.CP_EMC_VSA_ENABLED, VSAFlag) });
client.modifyInstance(toUpdate, SmisConstants.PS_EMC_VSA_ENABLED);
}
use of javax.wbem.client.WBEMClient in project coprhd-controller by CoprHD.
the class VmaxExportOperations method validateAndUpdateStorageGroupPolicyAndLimits.
/**
* Validates and updates fast policy in storage group.
*
* @param storage
* the storage system
* @param exportMask
* exportMask
* @param childGroupName
* the child group name
* @param volumeURIs
* the volume uris
* @param newVirtualPool
* the new virtual pool where new policy name and host limits can be obtained
* @param phantomSGNames
* the phantom SG names if any
* @param taskCompleter
* task completer
* @return true, if successfully updated policy for SG
* @throws WBEMException
* the wBEM exception
* @throws Exception
* the exception
*/
private boolean validateAndUpdateStorageGroupPolicyAndLimits(StorageSystem storage, ExportMask exportMask, String childGroupName, List<URI> volumeURIs, VirtualPool newVirtualPool, Set<String> phantomSGNames, TaskCompleter taskCompleter) throws WBEMException, Exception {
boolean policyUpdated = false;
boolean isVmax3 = storage.checkIfVmax3();
_log.info("Checking on Storage Group {}", childGroupName);
WBEMClient client = _helper.getConnection(storage).getCimClient();
// we need auto tiering policy object to get its name.
String newPolicyName = ControllerUtils.getFastPolicyNameFromVirtualPool(_dbClient, storage, newVirtualPool);
if (isVmax3) {
newPolicyName = _helper.getVMAX3FastSettingForVolume(volumeURIs.get(0), newPolicyName);
}
StorageGroupPolicyLimitsParam newVirtualPoolPolicyLimits = new StorageGroupPolicyLimitsParam(newPolicyName, newVirtualPool.getHostIOLimitBandwidth(), newVirtualPool.getHostIOLimitIOPs(), newVirtualPool.getCompressionEnabled(), storage);
CIMObjectPath childGroupPath = _cimPath.getMaskingGroupPath(storage, childGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
if (isVmax3) {
/**
* VMAX3 part of multiple exports: volumes will be part of multiple SGs
* One as FAST SG and others as non-FAST SG.
* If the requested SG is non FAST, do nothing. Other export mask's call
* will take care of updating FAST setting.
*/
BlockObject bo = BlockObject.fetch(_dbClient, volumeURIs.get(0));
if (_helper.isVolumePartOfMoreThanOneExport(storage, bo)) {
String currentPolicyName = _helper.getVMAX3FastSettingAssociatedWithVolumeGroup(storage, childGroupPath);
if (Constants.NONE.equalsIgnoreCase(currentPolicyName) && _helper.checkVolumeAssociatedWithAnyFASTSG(bo.getNativeId(), storage)) {
Map<ExportMask, ExportGroup> maskToGroupMap = ExportUtils.getExportMasks(bo, _dbClient);
if (maskToGroupMap.size() > 1) {
_log.info("Volumes {} are part of multiple storage groups. " + "FAST Policy will be (or might already be) changed during other export mask's call.", Joiner.on("\t").join(volumeURIs));
return true;
} else {
_log.error("FAST Policy cannot be updated on this storage group" + " since volumes are already part of another FAST managed storage group.");
return false;
}
}
}
}
if (!isVmax3 && !phantomSGNames.isEmpty() && !_helper.isFastPolicy(_helper.getAutoTieringPolicyNameAssociatedWithVolumeGroup(storage, childGroupPath)) && !_helper.isCascadedSG(storage, childGroupPath)) {
/**
* Phantom SG will be taken into consideration only if MV contains Non-cascaded Non-FAST SG
*/
_log.info("**** Phantom Storage Group ****");
/**
* For Volumes in Phantom SG - Volumes part of Phantom SG will be in Non-cascaded Non-FAST Storage Group
* (CTRL-9064)
*
* We have the phantom SGs having volumes which are part of this Masking view
* Group requested volumes by SG
* volumes in each Phantom SG
* also add an entry with volumes to Non-FAST SG (volumes requested minus volumes already in phantom SG)
*
* For each SG,
* If Phantom SG:
* If it is requested for all volumes
* change the policy associated with phantom SG
* else
* Remove the volumes from that phantom SG
* add them to new/existing phantom SG which is associated with new policy
* Note: if new policy is NONE, we just remove the volumes from phantom SG, no need to add them to another
* phantom SG.
* Since these volumes are already part of Non-FAST SG, they are part of MV.
* Else if it is Non-FAST SG:
* place those volumes in new/existing Phantom SG which is associated with new Policy
*/
Map<String, List<URI>> volumeGroup = new HashMap<String, List<URI>>();
List<URI> volumeURIsOfNonFASTSG = new ArrayList<URI>();
volumeURIsOfNonFASTSG.addAll(volumeURIs);
for (String phantomSGName : phantomSGNames) {
List<URI> volURIs = _helper.findVolumesInStorageGroup(storage, phantomSGName, volumeURIs);
if (!volURIs.isEmpty()) {
volumeGroup.put(phantomSGName, volURIs);
volumeURIsOfNonFASTSG.removeAll(volURIs);
}
}
// put Non-FAST SG with volumes (volumes requested minus volumes already in phantom SG)
if (!volumeURIsOfNonFASTSG.isEmpty()) {
volumeGroup.put(childGroupName, volumeURIsOfNonFASTSG);
}
for (Entry<String, List<URI>> sgNameToVolumes : volumeGroup.entrySet()) {
String sgName = sgNameToVolumes.getKey();
List<URI> volumesInSG = sgNameToVolumes.getValue();
CIMObjectPath sgPath = _cimPath.getMaskingGroupPath(storage, sgName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
// 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;
for (URI volURI : volumesInSG) {
// The force flag only needs to be set once
if (!forceFlag) {
forceFlag = ExportUtils.useEMCForceFlag(_dbClient, volURI);
}
}
/**
* update Policy on this SG. We don't use Phantom SG for IO Limits
*/
String currentPolicyName = _helper.getAutoTieringPolicyNameAssociatedWithVolumeGroup(storage, sgPath);
_log.info("FAST policy name associated with Storage Group {} : {}", sgName, currentPolicyName);
if (!_helper.isFastPolicy(currentPolicyName)) {
/**
* Not a Phantom SG. Create new or use existing Phantom SG for the requested volumes
* Request: non-FAST volumes in SG (associated with MV) to FAST volumes
*/
addVolumesToPhantomStorageGroup(storage, exportMask, volumesInSG, newPolicyName, childGroupName, taskCompleter, forceFlag);
} else {
/**
* phantom SG
*/
_log.info("Checking on Phantom Storage Group {}", sgName);
// check if phantom SG has the same set of volumes as the volume list provided
if (isGivenVolumeListSameAsInStorageGroup(storage, sgPath, volumesInSG)) {
_log.info("Changing Policy on Phantom Storage Group {} since it is requested " + "for all the volumes in the Group.", sgName);
if (!currentPolicyName.equalsIgnoreCase(newPolicyName)) {
if (_helper.isFastPolicy(currentPolicyName)) {
_helper.removeVolumeGroupFromAutoTieringPolicy(storage, sgPath);
}
if (_helper.isFastPolicy(newPolicyName)) {
_log.info("Adding Storage Group {} to FAST Policy {}", sgName, newPolicyName);
addVolumeGroupToAutoTieringPolicy(storage, newPolicyName, sgPath, taskCompleter);
StorageGroupPolicyLimitsParam phantomStorageGroupPolicyLimitsParam = new StorageGroupPolicyLimitsParam(newPolicyName);
String newSGName = generateNewNameForPhantomSG(storage, childGroupName, phantomStorageGroupPolicyLimitsParam);
// update SG name according to new policy
_helper.updateStorageGroupName(client, sgPath, newSGName);
}
} else {
_log.info("Current and new policy names are same '{}'." + " No need to update it on SG.", currentPolicyName);
}
/**
* if new policy is NONE & all volumes in request
* remove phantom SG since it won't be needed anymore
* (because volumes are already part of Non-FAST SG associated with MV)
* Request: FAST volumes to Non-FAST
*/
if (!_helper.isFastPolicy(newPolicyName)) {
removePhantomStorageGroup(storage, client, exportMask.getId(), sgName, sgPath, volumesInSG, forceFlag);
}
} else {
/**
* remove requested volumes from this phantom SG
* add them to the new/existing phantom SG which is associated with target policy
*/
_log.info("Request is made for part of volumes in the Group");
removePhantomStorageGroup(storage, client, exportMask.getId(), sgName, sgPath, volumesInSG, forceFlag);
if (_helper.isFastPolicy(newPolicyName)) {
addVolumesToPhantomStorageGroup(storage, exportMask, volumesInSG, newPolicyName, childGroupName, taskCompleter, forceFlag);
}
}
}
policyUpdated = true;
}
} else {
/**
* Usual flow for regular SGs
*
* check if SG has the same set of volumes as the volume list provided.
*/
if (isGivenVolumeListSameAsInStorageGroup(storage, childGroupPath, volumeURIs)) {
/**
* update Policy and Limits on this SG
*/
_log.info("Request is made for all volumes in the Group. Updating Policy and Limits on this Storage Group..");
CIMInstance childGroupInstance = null;
if (isVmax3) {
childGroupInstance = _helper.getInstance(storage, childGroupPath, false, false, SmisConstants.PS_V3_STORAGE_GROUP_PROPERTIES);
} else {
childGroupInstance = _helper.checkExists(storage, childGroupPath, false, false);
}
StorageGroupPolicyLimitsParam currentStorageGroupPolicyLimits = _helper.createStorageGroupPolicyLimitsParam(storage, childGroupInstance);
String currentPolicyName = currentStorageGroupPolicyLimits.getAutoTierPolicyName();
if (!currentPolicyName.equalsIgnoreCase(newPolicyName)) {
_log.info("FAST policy name associated with Storage Group {} : {}", childGroupName, currentPolicyName);
if (isVmax3) {
newPolicyName = _helper.getVMAX3FastSettingWithRightNoneString(storage, newPolicyName);
CIMInstance toUpdate = new CIMInstance(childGroupInstance.getObjectPath(), _helper.getV3FastSettingProperties(newPolicyName));
_helper.modifyInstance(storage, toUpdate, SmisConstants.PS_V3_FAST_SETTING_PROPERTIES);
_log.info("Modified Storage Group {} FAST Setting to {}", childGroupName, newPolicyName);
} else {
if (_helper.isFastPolicy(currentPolicyName)) {
_helper.removeVolumeGroupFromAutoTieringPolicy(storage, childGroupPath);
}
if (_helper.isFastPolicy(newPolicyName)) {
_log.info("Adding Storage Group {} to FAST Policy {}", childGroupName, newPolicyName);
addVolumeGroupToAutoTieringPolicy(storage, newPolicyName, childGroupPath, taskCompleter);
}
}
} else {
_log.info("Current and new policy names are same '{}'." + " No need to update it on Storage Group.", currentPolicyName);
}
// Even if we don't change policy name on device
// we need to set policyUpdated = true else rollback kicks in
policyUpdated = true;
// Update the compression attributes if it needs to be
if (isVmax3) {
// refresh the SG instance since compression property is enabled by default
// when SG becomes FAST managed.
childGroupInstance = _helper.getInstance(storage, childGroupPath, false, false, SmisConstants.PS_EMC_COMPRESSION);
boolean currentCompressionSetting = SmisUtils.getEMCCompressionForStorageGroup(childGroupInstance);
boolean newCompressionSetting = newVirtualPoolPolicyLimits.getCompression();
if (currentCompressionSetting != newCompressionSetting) {
CIMInstance toUpdate = new CIMInstance(childGroupInstance.getObjectPath(), _helper.getV3CompressionProperties(newCompressionSetting));
_helper.modifyInstance(storage, toUpdate, SmisConstants.PS_EMC_COMPRESSION);
_log.info("Modified Storage Group {} Compression setting to {}", childGroupName, newCompressionSetting);
} else {
_log.info("Current and new compression values are same '{}'." + " No need to update it on Storage Group.", newCompressionSetting);
}
}
// update host io limits if need be
if (!HostIOLimitsParam.isEqualsLimit(currentStorageGroupPolicyLimits.getHostIOLimitBandwidth(), newVirtualPoolPolicyLimits.getHostIOLimitBandwidth())) {
_helper.updateHostIOLimitBandwidth(client, childGroupPath, newVirtualPoolPolicyLimits.getHostIOLimitBandwidth());
policyUpdated = true;
}
if (!HostIOLimitsParam.isEqualsLimit(currentStorageGroupPolicyLimits.getHostIOLimitIOPs(), newVirtualPoolPolicyLimits.getHostIOLimitIOPs())) {
_helper.updateHostIOLimitIOPs(client, childGroupPath, newVirtualPoolPolicyLimits.getHostIOLimitIOPs());
policyUpdated = true;
}
if (policyUpdated) {
Set<Initiator> initiators = ExportMaskUtils.getInitiatorsForExportMask(_dbClient, exportMask, null);
_helper.updateStorageGroupName(client, childGroupPath, generateStorageGroupName(storage, exportMask, initiators, newVirtualPoolPolicyLimits));
}
} else if (isVmax3) {
/**
* Requested for fewer members in a SG
*
* V3 supports moveMembers from one SG to another, provided some conditions met.
* see #helper.moveVolumesFromOneStorageGroupToAnother() for criteria.
*
* validate that current SG is not a parent SG and it is not associated with MV
* check if there is another SG under CSG with new fastSetting & limits
* else create new SG (with new fastSetting, IO limits) and associate it with CSG
* call 'moveMembers' to move volumes from current SG to new SG
*/
_log.info("Request is made for part of volumes in the Group (VMAX3). Moving those volumes to new Storage Group..");
if (!_helper.isCascadedSG(storage, childGroupPath) && !_helper.findStorageGroupsAssociatedWithOtherMaskingViews(storage, childGroupName)) {
String parentGroupName = _helper.getStorageGroupForGivenMaskingView(exportMask.getMaskName(), storage);
Map<StorageGroupPolicyLimitsParam, List<String>> childGroupsByFast = _helper.groupStorageGroupsByAssociation(storage, parentGroupName);
List<String> newChildGroups = childGroupsByFast.get(newVirtualPoolPolicyLimits);
if (newChildGroups != null) {
// remove CSG
newChildGroups.remove(parentGroupName);
}
boolean newGroup = false;
CIMObjectPath newChildGroupPath = null;
String newChildGroupName = null;
if (newChildGroups != null && !newChildGroups.isEmpty()) {
newChildGroupName = newChildGroups.iterator().next();
newChildGroupPath = _cimPath.getMaskingGroupPath(storage, newChildGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
} else {
newGroup = true;
newPolicyName = _helper.getVMAX3FastSettingWithRightNoneString(storage, newPolicyName);
String[] tokens = newPolicyName.split(Constants.SMIS_PLUS_REGEX);
newChildGroupPath = _helper.createVolumeGroupBasedOnSLO(storage, storage, tokens[0], tokens[1], tokens[2]);
// 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;
for (URI volURI : volumeURIs) {
if (!forceFlag) {
forceFlag = ExportUtils.useEMCForceFlag(_dbClient, volURI);
}
}
addGroupsToCascadedVolumeGroup(storage, parentGroupName, newChildGroupPath, null, null, forceFlag);
}
// We could enter the same situation if any of the SG characteristics were modified without ViPR knowledge.
if (childGroupName.equalsIgnoreCase(newChildGroupName)) {
_log.info("Current Storage Group {} has the required charcteristics" + "No need to invoke SMI-S moveMembers method. Performing NO-OP", newChildGroupName);
} else {
SmisJob moveVolumesToSGJob = new SmisSynchSubTaskJob(null, storage.getId(), SmisConstants.MOVE_MEMBERS);
_helper.moveVolumesFromOneStorageGroupToAnother(storage, childGroupPath, newChildGroupPath, volumeURIs, moveVolumesToSGJob);
}
if (newGroup) {
// update host IO limits if need be
if (newVirtualPoolPolicyLimits.isHostIOLimitBandwidthSet()) {
_helper.updateHostIOLimitBandwidth(client, newChildGroupPath, newVirtualPoolPolicyLimits.getHostIOLimitBandwidth());
}
if (newVirtualPoolPolicyLimits.isHostIOLimitIOPsSet()) {
_helper.updateHostIOLimitIOPs(client, newChildGroupPath, newVirtualPoolPolicyLimits.getHostIOLimitIOPs());
}
// Honor the compression settings if needed..
if (!newVirtualPoolPolicyLimits.getCompression()) {
// If the user opted out of compression, and the created SG has compression enabled by default,
// we need to opt out..
CIMInstance newChildGroupInstance = _helper.getInstance(storage, newChildGroupPath, false, false, SmisConstants.PS_EMC_COMPRESSION);
if (SmisUtils.getEMCCompressionForStorageGroup(newChildGroupInstance)) {
CIMInstance toUpdate = new CIMInstance(newChildGroupInstance.getObjectPath(), _helper.getV3CompressionProperties(false));
_helper.modifyInstance(storage, toUpdate, SmisConstants.PS_EMC_COMPRESSION);
}
}
Set<Initiator> initiators = ExportMaskUtils.getInitiatorsForExportMask(_dbClient, exportMask, null);
_helper.updateStorageGroupName(client, newChildGroupPath, generateStorageGroupName(storage, exportMask, initiators, newVirtualPoolPolicyLimits));
}
policyUpdated = true;
} else {
_log.info("Conditions for 'moveMembers' didn't meet for Storage Group {}." + " Hence, cannot move volumes to new Storage Group with new policy and limits.", childGroupName);
}
} else {
_log.info("Given Volume list is not same as the one in Storage Group {}." + " Hence, FAST policy change won't be done on it.", childGroupName);
}
}
return policyUpdated;
}
use of javax.wbem.client.WBEMClient in project coprhd-controller by CoprHD.
the class VmaxExportOperations method removeVolumes.
@Override
public void removeVolumes(StorageSystem storage, URI exportMaskURI, List<URI> volumeURIList, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("{} removeVolumes START...", storage.getSerialNumber());
try {
_log.info("removeVolumes: Export mask id: {}", exportMaskURI);
_log.info("removeVolumes: volumes: {}", Joiner.on(',').join(volumeURIList));
if (initiatorList != null) {
_log.info("removeVolumes: impacted initiators: {}", Joiner.on(",").join(initiatorList));
}
List<? extends BlockObject> blockObjects = BlockObject.fetchAll(_dbClient, volumeURIList);
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(blockObjects);
ctx.setInitiators(initiatorList);
// Allow exceptions to be thrown when not rolling back
ctx.setAllowExceptions(!isRollback);
validator.removeVolumes(ctx).validate();
boolean isVmax3 = storage.checkIfVmax3();
WBEMClient client = _helper.getConnection(storage).getCimClient();
if (isRollback) {
// Get the context from the task completer for this rollback step. The stepId in this case
// will correspond to the rollback step and not the primary execution step. We don't know
// the rollback stepId until execution time, therefore there will be no step data in the
// database corresponding to this stepId. The underlying call to loadStepData will take care
// of finding the founding step (execution) step for this rollback stepId, from which the
// step data can be found.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
exportMaskRollback(storage, context, taskCompleter);
taskCompleter.ready(_dbClient);
return;
} else {
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, no operation on array side
if (null == parentGroupName) {
taskCompleter.ready(_dbClient);
return;
}
Map<String, List<URI>> volumesByGroup = _helper.groupVolumesBasedOnExistingGroups(storage, parentGroupName, volumeURIList);
_log.info("Group Volumes by Storage Group size : {}", volumesByGroup.size());
if (volumesByGroup.size() == 0) {
_log.info("Could not find any groups to which the volumes to remove belong.");
taskCompleter.ready(_dbClient);
return;
}
/**
* For each child Group bucket, remove the volumes from those bucket
*/
for (Entry<String, List<URI>> volumeByGroupEntry : volumesByGroup.entrySet()) {
String childGroupName = volumeByGroupEntry.getKey();
volumeURIList = volumeByGroupEntry.getValue();
_log.info("Processing Group {} with volumes {}", childGroupName, Joiner.on("\t").join(volumeURIList));
/**
* Empty child Storage Groups cannot be associated with Fast Policy.
* hence, verify if storage group size is > 1, if not, then remove the
* child group from Fast Policy, and then proceed with removing the volume from group
*/
if (volumesByGroup.get(childGroupName) != null && volumesByGroup.get(childGroupName).size() == volumeURIList.size() && !_helper.isStorageGroupSizeGreaterThanGivenVolumes(childGroupName, storage, volumeURIList.size())) {
_log.info("Storage Group has no more than {} volumes", volumeURIList.size());
URI blockURI = volumeURIList.get(0);
BlockObject blockObj = BlockObject.fetch(_dbClient, blockURI);
CIMObjectPath maskingGroupPath = _cimPath.getMaskingGroupPath(storage, childGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
String policyName = ControllerUtils.getAutoTieringPolicyName(blockObj.getId(), _dbClient);
if (!isVmax3 && !Constants.NONE.equalsIgnoreCase(policyName)) {
_log.info("Storage Group contains only 1 volume, hence this group will be disassociated from fast, as fast cannot be applied to empty group {}", childGroupName);
_helper.removeVolumeGroupFromPolicyAndLimitsAssociation(client, storage, maskingGroupPath);
}
}
Set<String> volumeDeviceIds = new HashSet<String>();
// 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;
for (URI volURI : volumeURIList) {
BlockObject bo = Volume.fetchExportMaskBlockObject(_dbClient, volURI);
volumeDeviceIds.add(bo.getNativeId());
// The force flag only needs to be set once
if (!forceFlag) {
forceFlag = ExportUtils.useEMCForceFlag(_dbClient, volURI);
}
}
List<CIMObjectPath> volumePaths = new ArrayList<CIMObjectPath>();
// Determine if the volumes are associated with any phantom storage groups.
// If so, we need to remove volumes from those storage groups and potentially remove them.
removeVolumesFromPhantomStorageGroup(storage, client, exportMaskURI, volumeURIList, childGroupName, forceFlag);
// 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);
List<URI> volumesInSG = _helper.findVolumesInStorageGroup(storage, childGroupName, volumeURIList);
if (volumesInSG != null && !volumesInSG.isEmpty()) {
CIMArgument[] inArgs = _helper.getRemoveVolumesFromMaskingGroupInputArguments(storage, childGroupName, volumesInSG, forceFlag);
CIMArgument[] outArgs = new CIMArgument[5];
// If any of the volumes being removed are tied to RecoverPoint, we need to be aware that there
// might be some lag in terminating the remote copy session between VMAX and RP. So we need to
// catch a specific exception in this case and wait/retry.
boolean containsRPVolume = false;
// RecoverPoint related.
for (URI boUri : volumesInSG) {
if (URIUtil.isType(boUri, Volume.class)) {
Volume volume = _dbClient.queryObject(Volume.class, boUri);
if (volume != null && (volume.checkForRp() || RPHelper.isAssociatedToAnyRpVplexTypes(volume, _dbClient))) {
// Determined that the volume is RP related
containsRPVolume = true;
break;
}
}
}
// Initialize the retry/attempt variables
int attempt = 0;
int retries = 1;
if (containsRPVolume) {
// If we are dealing with an RP volume, we need to set the retry count appropriately
retries = MAX_RP_RETRIES;
}
while (attempt++ <= retries) {
try {
_helper.invokeMethodSynchronously(storage, _cimPath.getControllerConfigSvcPath(storage), "RemoveMembers", inArgs, outArgs, new SmisMaskingViewRemoveVolumeJob(null, storage.getId(), volumePaths, parentGroupName, childGroupName, _cimPath, completer));
// If the invoke succeeds without exception, break out of the retry loop.
break;
} catch (SmisException se) {
if (attempt != retries && containsRPVolume && se.getMessage().contains(COPY_SESSION_ERROR)) {
// There is some delay in terminating the remote copy session between VMAX and
// RecoverPoint
// so we need to wait and retry.
_log.warn(String.format("Encountered exception during attempt %s/%s to remove volumes %s from export group. Waiting %s milliseconds before trying again. Error: %s", attempt, MAX_RP_RETRIES, volumesInSG.toString(), RP_WAIT_FOR_RETRY, se.getMessage()));
try {
Thread.sleep(RP_WAIT_FOR_RETRY);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
} else {
// This is not RP related so just re-throw the exception instead of retrying.
throw se;
}
}
}
if (isVmax3) {
// we need to add volumes to parking storage group
URI blockObjectURI = volumeURIList.get(0);
String policyName = _helper.getVMAX3FastSettingForVolume(blockObjectURI, null);
addVolumesToParkingStorageGroup(storage, policyName, volumeDeviceIds);
}
} else {
completer.ready(_dbClient);
}
}
taskCompleter.ready(_dbClient);
}
} catch (Exception e) {
_log.error(String.format("removeVolumes failed - maskName: %s", exportMaskURI.toString()), e);
ServiceError serviceError = null;
if (null != e.getMessage() && e.getMessage().contains("FAST association cannot have an empty storage group")) {
serviceError = DeviceControllerException.errors.concurrentRemoveFromSGCausesEmptySG(e);
} else {
serviceError = DeviceControllerException.errors.jobFailed(e);
}
taskCompleter.error(_dbClient, serviceError);
}
_log.info("{} removeVolumes END...", storage.getSerialNumber());
}
use of javax.wbem.client.WBEMClient in project coprhd-controller by CoprHD.
the class VmaxExportOperations method getMasksWhoseIGsCanBeReused.
/**
* Gets the masks whose IGs can be reused i.e masks that can be skipped from being reused.
*/
private Set<URI> getMasksWhoseIGsCanBeReused(StorageSystem storage, Map<URI, ExportMask> maskMap, List<String> initiatorNamesInRequest) throws Exception {
/**
* When a masking view can be skipped and a new masking view can be created instead?
*
* If Mask has other initiators in addition with requested initiators:
* And if it has cascaded IG with child IGs
* wherein each child IG has some or all of requested initiators, without additional initiators
* or completely different set of initiators.
*/
Set<URI> masksWithReusableIGs = new HashSet<>();
_log.info("Initiators in Request : {} ", Joiner.on(", ").join(initiatorNamesInRequest));
WBEMClient client = _helper.getConnection(storage).getCimClient();
for (URI exportMaskURI : maskMap.keySet()) {
ExportMask mask = maskMap.get(exportMaskURI);
String maskName = mask.getMaskName();
_log.info("Checking if mask {} can be skipped from getting reused", maskName);
// Find all the initiators associated with the MaskingView
CIMInstance instance = _helper.getSymmLunMaskingView(storage, mask);
List<String> initiatorNamesInMask = _helper.getInitiatorsFromLunMaskingInstance(client, instance);
initiatorNamesInMask.removeAll(initiatorNamesInRequest);
if (!initiatorNamesInMask.isEmpty()) {
CIMObjectPath maskingViewPath = _cimPath.getMaskingViewPath(storage, maskName);
CIMObjectPath parentIG = _helper.getInitiatorGroupForGivenMaskingView(maskingViewPath, storage);
if (_helper.isCascadedIG(storage, parentIG)) {
// get all the child IGs
List<CIMObjectPath> childInitiatorGroupPaths = new ArrayList<CIMObjectPath>();
getInitiatorGroupsFromMvOrIg(storage, parentIG, childInitiatorGroupPaths);
boolean allIGsSatisfy = false;
for (CIMObjectPath igPath : childInitiatorGroupPaths) {
List<String> initiatorNamesFromIG = _helper.getInitiatorNamesForInitiatorGroup(storage, igPath);
_log.info("Initiators in IG {}: {}", igPath.toString(), Joiner.on(", ").join(initiatorNamesFromIG));
int initialSize = initiatorNamesFromIG.size();
initiatorNamesFromIG.removeAll(initiatorNamesInRequest);
if (initiatorNamesFromIG.isEmpty() || (initialSize == initiatorNamesFromIG.size())) {
// If IG has some or all of requested initiators, it should not have other initiators
// or completely different set of initiators
allIGsSatisfy = true;
} else {
allIGsSatisfy = false;
// stop processing other child groups
break;
}
}
if (allIGsSatisfy) {
// IGs which are having requested initiators, doesn't contain other initiators.
// (all required initiators are present in single IG or split into multiple child IGs)
// Creating a new masking view is the right thing to do, as we can reuse IGs.
_log.info("Skipping mask {} from getting reused", maskName);
masksWithReusableIGs.add(exportMaskURI);
}
}
// else - Single Non-Cascaded IG has other initiators, MV can be reused
}
// else - MV with same set (or) few initiators can be reused
}
return masksWithReusableIGs;
}
use of javax.wbem.client.WBEMClient in project coprhd-controller by CoprHD.
the class VmaxExportOperations method deleteExportMask.
@Override
public void deleteExportMask(StorageSystem storage, URI exportMaskURI, List<URI> volumeURIList, List<URI> targetURIList, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("{} deleteExportMask START...", storage.getSerialNumber());
try {
_log.info("Export mask id: {}", exportMaskURI);
if (volumeURIList != null) {
_log.info("deleteExportMask: volumes: {}", Joiner.on(',').join(volumeURIList));
}
if (targetURIList != null) {
_log.info("deleteExportMask: assignments: {}", Joiner.on(',').join(targetURIList));
}
if (initiatorList != null) {
_log.info("deleteExportMask: initiators: {}", Joiner.on(',').join(initiatorList));
}
boolean isVmax3 = storage.checkIfVmax3();
WBEMClient client = _helper.getConnection(storage).getCimClient();
String maskingViewName = _helper.getExportMaskName(exportMaskURI);
// Always get the Storage Group from masking View, rather than depending on the name to find out SG.
String groupName = _helper.getStorageGroupForGivenMaskingView(maskingViewName, storage);
/*
* The idea is to remove orphaned child Groups, after deleting masking view. We're getting
* the list of childGroups here because once we call deleteMaskingView, the parent group
* will be automatically deleted.
*
* Run Associator Names to get details of child Storage Groups ,and group them based on
* Fast Policy.
*/
Map<StorageGroupPolicyLimitsParam, List<String>> childGroupsByFast = new HashMap<StorageGroupPolicyLimitsParam, List<String>>();
// if SGs are already removed from masking view manually, then skip this part
if (null != groupName) {
childGroupsByFast = _helper.groupStorageGroupsByAssociation(storage, groupName);
} else {
_log.info("Masking View {} doesn't have any SGs associated, probably removed manually from Array", maskingViewName);
if (isVmax3) {
// If we did not find the storage group associated with the masking view it could be
// the case that were were unexporting volumes and successfully deleted the masking
// but failed at some point thereafter, and now the operation is being retried. If
// that is the case, then for VMAX3 we want to make sure that none of the volumes being
// unexported are still in non parking storage groups. If we find such volume we remove
// them and add them to the parking storage group.
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
if (exportMask == null) {
// If we can't find the mask, there is really no cleanup we can do.
_log.warn("ExportMask {} no longer exists", exportMaskURI);
taskCompleter.ready(_dbClient);
return;
}
// See if any of the mask's volumes are still in a non-parking storage group. Map the
// volumes by group name.
List<URI> volumeURIs = ExportMaskUtils.getVolumeURIs(exportMask);
Map<String, List<URI>> volumesInNonParkingStorageGroup = _helper.getVolumesInNonParkingStorageGroup(storage, volumeURIs);
if (!volumesInNonParkingStorageGroup.isEmpty()) {
Map<String, Set<String>> volumeDeviceIdsMap = new HashMap<>();
for (Entry<String, List<URI>> storageGroupEntry : volumesInNonParkingStorageGroup.entrySet()) {
String storageGroupName = storageGroupEntry.getKey();
List<URI> storageGroupVolumeURIs = storageGroupEntry.getValue();
// then just skip the volume, we cannot clean it up as we may impact other exports.
if (_helper.findStorageGroupsAssociatedWithMultipleParents(storage, storageGroupName) || _helper.findStorageGroupsAssociatedWithOtherMaskingViews(storage, storageGroupName)) {
_log.info("Storage group {} is associated with multiple paranets or other masking views", storageGroupName);
continue;
}
// Otherwise, remove the volumes from the storage group.
_log.info("Removing volumes {} from non parking storage group {}", storageGroupVolumeURIs, storageGroupName);
_helper.removeVolumesFromStorageGroup(storage, storageGroupName, storageGroupVolumeURIs, true);
// parking storage group.
for (URI storageGroupVolumeURI : storageGroupVolumeURIs) {
Volume storageGroupVolume = _dbClient.queryObject(Volume.class, storageGroupVolumeURI);
if (storageGroupVolume != null) {
String policyName = ControllerUtils.getAutoTieringPolicyName(storageGroupVolumeURI, _dbClient);
String policyKey = _helper.getVMAX3FastSettingForVolume(storageGroupVolumeURI, policyName);
if (volumeDeviceIdsMap.containsKey(policyKey)) {
volumeDeviceIdsMap.get(policyKey).add(storageGroupVolume.getNativeId());
} else {
Set<String> volumeDeviceIds = new HashSet<>();
volumeDeviceIds.add(storageGroupVolume.getNativeId());
volumeDeviceIdsMap.put(policyKey, volumeDeviceIds);
}
}
}
}
// Finally for each parking storage group policy, add the volumes associated parking storage group.
for (Entry<String, Set<String>> volumeDeviceIdsMapEntry : volumeDeviceIdsMap.entrySet()) {
_log.info("Adding volumes {} on system {} to parking storage group for policy {}", volumeDeviceIdsMapEntry.getValue(), storage.getNativeGuid(), volumeDeviceIdsMapEntry.getKey());
addVolumesToParkingStorageGroup(storage, volumeDeviceIdsMapEntry.getKey(), volumeDeviceIdsMapEntry.getValue());
}
}
}
taskCompleter.ready(_dbClient);
return;
}
/*
* If a maskingView was created by other instance, can not delete it here during roll back. Hence,
* set task as done.
*/
if (taskCompleter instanceof RollbackExportGroupCreateCompleter) {
/*
* The purpose of rollback is to delete the masking view created by this very ViPR instance as
* part of this workflow, and it should not delete masking view created externally or another ViPR
*/
// Get the context from the task completer, in case this is a rollback.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null) {
exportMaskRollback(storage, context, taskCompleter);
}
} else {
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
List<URI> volumeURIs = ExportMaskUtils.getVolumeURIs(exportMask);
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(volumeURIList, _dbClient);
ctx.setInitiators(initiatorList);
ctx.setAllowExceptions(context == null);
validator.exportMaskDelete(ctx).validate();
if (!deleteMaskingView(storage, exportMaskURI, childGroupsByFast, taskCompleter)) {
// deleteMaskingView call. Simply return from here.
return;
}
for (Map.Entry<StorageGroupPolicyLimitsParam, List<String>> entry : childGroupsByFast.entrySet()) {
_log.info(String.format("Mask %s FAST Policy %s associated with %d Storage Group(s)", maskingViewName, entry.getKey(), entry.getValue().size()));
}
if (groupName != null) {
_log.info("storage group name : {}", groupName);
// delete the CSG explicitly (CTRL-9236)
CIMObjectPath storageGroupPath = _cimPath.getMaskingGroupPath(storage, groupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
// check if the storage group is shared before delete it
if (_helper.checkExists(storage, storageGroupPath, false, false) != null && _helper.checkMaskingGroupShared(storage, storageGroupPath, exportMask.getMaskName())) {
// if the storage group is shared, don't delete the storage group
_log.info("The Storage group {} is shared, so it will not be deleted", groupName);
taskCompleter.ready(_dbClient);
return;
}
if (_helper.isCascadedSG(storage, storageGroupPath)) {
_helper.deleteMaskingGroup(storage, groupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
}
/**
* After successful deletion of masking view, try to remove the child Storage Groups ,which were
* part of cascaded
* Parent Group. If Fast Policy is not enabled, then those child groups can be removed.
* If Fast enabled, then try to find if this child Storage Group is associated with more than 1
* Parent Cascaded
* Group, if yes, then we cannot delete the child Storage Group.
*/
for (Entry<StorageGroupPolicyLimitsParam, List<String>> childGroupByFastEntry : childGroupsByFast.entrySet()) {
for (String childGroupName : childGroupByFastEntry.getValue()) {
_log.info("Processing Group {} deletion with Fast Policy {}", childGroupName, childGroupByFastEntry.getKey());
CIMObjectPath maskingGroupPath = _cimPath.getMaskingGroupPath(storage, childGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
if (!_helper.isFastPolicy(childGroupByFastEntry.getKey().getAutoTierPolicyName())) {
/**
* Remove the volumes from any phantom storage group (CTRL-8217).
*
* Volumes part of Phantom Storage Group will be in Non-CSG Non-FAST Storage Group
*/
if (!_helper.isCascadedSG(storage, maskingGroupPath)) {
// Get volumes which are part of this Storage Group
List<URI> volumesInSG = _helper.findVolumesInStorageGroup(storage, childGroupName, volumeURIs);
// 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;
for (URI volURI : volumesInSG) {
forceFlag = ExportUtils.useEMCForceFlag(_dbClient, volURI);
if (forceFlag) {
break;
}
}
removeVolumesFromPhantomStorageGroup(storage, client, exportMaskURI, volumesInSG, childGroupName, forceFlag);
}
// Delete the Storage Group
_helper.deleteMaskingGroup(storage, childGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
} else if (!_helper.findStorageGroupsAssociatedWithMultipleParents(storage, childGroupName) && !_helper.findStorageGroupsAssociatedWithOtherMaskingViews(storage, childGroupName)) {
// volumeDeviceIds and policyName are required in case of VMAX3 to add volumes back
// to parking to storage group.
Set<String> volumeDeviceIds = new HashSet<String>();
String policyName = childGroupByFastEntry.getKey().getAutoTierPolicyName();
if (isVmax3) {
volumeDeviceIds = _helper.getVolumeDeviceIdsFromStorageGroup(storage, childGroupName);
}
// holds the group, if yes, then we should not delete this group
if (!isVmax3) {
_log.debug("Removing Storage Group {} from Fast Policy {}", childGroupName, childGroupByFastEntry.getKey());
_helper.removeVolumeGroupFromPolicyAndLimitsAssociation(client, storage, maskingGroupPath);
}
_log.debug("Deleting Storage Group {}", childGroupName);
_helper.deleteMaskingGroup(storage, childGroupName, SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup);
if (isVmax3 && !volumeDeviceIds.isEmpty()) {
// We need to add volumes back to appropriate parking storage group.
addVolumesToParkingStorageGroup(storage, policyName, volumeDeviceIds);
}
} else {
_log.info("Storage Group {} is either having more than one parent Storage Group or its part of another existing masking view", childGroupName);
// set Host IO Limits on SG which we reseted before deleting MV
if (childGroupByFastEntry.getKey().isHostIOLimitIOPsSet()) {
_helper.updateHostIOLimitIOPs(client, maskingGroupPath, childGroupByFastEntry.getKey().getHostIOLimitIOPs());
}
if (childGroupByFastEntry.getKey().isHostIOLimitBandwidthSet()) {
_helper.updateHostIOLimitBandwidth(client, maskingGroupPath, childGroupByFastEntry.getKey().getHostIOLimitBandwidth());
}
}
}
}
}
}
taskCompleter.ready(_dbClient);
} catch (Exception e) {
_log.error(String.format("deleteExportMask failed - maskName: %s", exportMaskURI.toString()), e);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
taskCompleter.error(_dbClient, serviceError);
}
_log.info("{} deleteExportMask END...", storage.getSerialNumber());
}
Aggregations