use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.
the class VNXeExportOperations method addVolumes.
@Override
public void addVolumes(StorageSystem storage, URI exportMaskUri, VolumeURIHLU[] volumeURIHLUs, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_logger.info("{} addVolume START...", storage.getSerialNumber());
List<URI> mappedVolumes = new ArrayList<URI>();
ExportMask exportMask = null;
try {
_logger.info("addVolumes: Export mask id: {}", exportMaskUri);
_logger.info("addVolumes: volume-HLU pairs: {}", Joiner.on(',').join(volumeURIHLUs));
if (initiatorList != null) {
_logger.info("addVolumes: initiators impacted: {}", Joiner.on(',').join(initiatorList));
}
ExportOperationContext context = new VNXeExportOperationContext();
taskCompleter.updateWorkflowStepContext(context);
VNXeApiClient apiClient = getVnxeClient(storage);
exportMask = _dbClient.queryObject(ExportMask.class, exportMaskUri);
if (exportMask == null || exportMask.getInactive()) {
throw new DeviceControllerException("Invalid ExportMask URI: " + exportMaskUri);
}
List<Initiator> initiators = ExportUtils.getExportMaskInitiators(exportMask, _dbClient);
Collection<VNXeHostInitiator> vnxeInitiators = prepareInitiators(initiators).values();
VNXeBase host = apiClient.prepareHostsForExport(vnxeInitiators);
String opId = taskCompleter.getOpId();
Set<String> processedCGs = new HashSet<String>();
for (VolumeURIHLU volURIHLU : volumeURIHLUs) {
URI volUri = volURIHLU.getVolumeURI();
String hlu = volURIHLU.getHLU();
_logger.info(String.format("hlu %s", hlu));
BlockObject blockObject = BlockObject.fetch(_dbClient, volUri);
VNXeExportResult result = null;
Integer newhlu = -1;
if (hlu != null && !hlu.isEmpty() && !hlu.equals(ExportGroup.LUN_UNASSIGNED_STR)) {
newhlu = Integer.valueOf(hlu);
}
// COP-25254 this method could be called when create vplex volumes from snapshot. in this case
// the volume passed in is an internal volume, representing the snapshot. we need to find the snapshot
// with the same nativeGUID, then export the snapshot.
BlockObject snapshot = findSnapshotByInternalVolume(blockObject);
boolean isVplexVolumeFromSnap = false;
URI vplexBackendVol = null;
if (snapshot != null) {
blockObject = snapshot;
exportMask.addVolume(volUri, newhlu);
isVplexVolumeFromSnap = true;
vplexBackendVol = volUri;
volUri = blockObject.getId();
}
String cgName = VNXeUtils.getBlockObjectCGName(blockObject, _dbClient);
if (cgName != null && !processedCGs.contains(cgName)) {
processedCGs.add(cgName);
VNXeUtils.getCGLock(workflowService, storage, cgName, opId);
}
String nativeId = blockObject.getNativeId();
if (URIUtil.isType(volUri, Volume.class)) {
result = apiClient.exportLun(host, nativeId, newhlu);
exportMask.addVolume(volUri, result.getHlu());
if (result.isNewAccess()) {
mappedVolumes.add(volUri);
}
} else if (URIUtil.isType(volUri, BlockSnapshot.class)) {
result = apiClient.exportSnap(host, nativeId, newhlu);
exportMask.addVolume(volUri, result.getHlu());
if (result.isNewAccess()) {
mappedVolumes.add(volUri);
}
String snapWWN = setSnapWWN(apiClient, blockObject, nativeId);
if (isVplexVolumeFromSnap) {
Volume backendVol = _dbClient.queryObject(Volume.class, vplexBackendVol);
backendVol.setWWN(snapWWN);
_dbClient.updateObject(backendVol);
}
}
}
ExportOperationContext.insertContextOperation(taskCompleter, VNXeExportOperationContext.OPERATION_ADD_VOLUMES_TO_HOST_EXPORT, mappedVolumes);
_dbClient.updateObject(exportMask);
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_002);
taskCompleter.ready(_dbClient);
} catch (Exception e) {
_logger.error("Add volumes error: ", e);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("addVolume", e.getMessage());
taskCompleter.error(_dbClient, error);
}
_logger.info("{} addVolumes END...", storage.getSerialNumber());
}
use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.
the class SmisMaskingViewAddVolumeJob method updateStatus.
@Override
public void updateStatus(JobContext jobContext) throws Exception {
DbClient dbClient = jobContext.getDbClient();
JobStatus jobStatus = getJobStatus();
_log.info("Updating status of SmisMaskingViewAddVolumeJob");
try {
if (jobStatus == JobStatus.SUCCESS) {
StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, getStorageSystemURI());
CimConnection cimConnection = jobContext.getCimConnectionFactory().getConnection(storageSystem);
List<URI> volumeUriList = new ArrayList<URI>();
// Now perform RP protection tagging, if required for the
// objects being added.
SmisCommandHelper helper = jobContext.getSmisCommandHelper();
for (VolumeURIHLU volumeUriHlu : _volumeURIHLUs) {
BlockObject bo = Volume.fetchExportMaskBlockObject(dbClient, volumeUriHlu.getVolumeURI());
if (bo != null && bo instanceof Volume) {
Volume volume = (Volume) bo;
if (volume != null && volume.checkForRp()) {
List<CIMObjectPath> volumePathList = new ArrayList<CIMObjectPath>();
volumePathList.add(helper.getVolumeMember(storageSystem, volume));
helper.setRecoverPointTag(storageSystem, volumePathList, true);
}
}
volumeUriList.add(volumeUriHlu.getVolumeURI());
}
// for proper roll back , that is volume removal, if exception is thrown during update
if (_newCreatedGroup != null) {
helper.setHostIOLimits(cimConnection.getCimClient(), _newCreatedGroup, _volumeURIHLUs);
}
String[] volumeNames = ExportMaskUtils.getBlockObjectAlternateNames(volumeUriList, dbClient);
CIMObjectPath[] volumes = _cimPath.getVolumePaths(storageSystem, volumeNames);
_log.info("{} volumes processed for HLU updation", volumes.length);
// Now set the HLU on the volume URIs, if they haven't been set// by user.
ExportMaskOperationsHelper.setHLUFromProtocolControllersOnAddVolume(dbClient, cimConnection, _exportMaskURI, _volumeURIHLUs, volumes, getTaskCompleter());
}
} catch (WBEMException e) {
_log.error(String.format("updateHostIOLimits failed - new created group: %s", _newCreatedGroup.toString()), e);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
getTaskCompleter().error(dbClient, serviceError);
} catch (Exception e) {
_log.error("Caught an exception while trying to updateStatus for SmisMaskingViewAddVolumeJob", e);
setPostProcessingErrorStatus("Encountered an internal error during add volume to masking view job status processing : " + e.getMessage());
} finally {
super.updateStatus(jobContext);
}
}
use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.
the class ExportMaskOperationsHelper method setHLUFromProtocolControllers.
/**
* During an export group operation e.g. creating one with initiators and volumes or when
* adding volume(s) to an existing export group the user has the option of supplying HLUs
* (Host Lun Unit) for the corresponding volumes. If the user does not supply HLUs, the
* underlying array generates them. This helper function displays those array generated
* HLUs during a GET/volume/exports operation. If the user has supplied the HLUs, this
* function does nothing.
*
* @throws DeviceControllerException
*/
public static void setHLUFromProtocolControllers(DbClient dbClient, CimConnection cimConnection, URI exportMaskURI, VolumeURIHLU[] volumeURIHLUs, Collection<CIMObjectPath> protocolControllers, TaskCompleter taskCompleter) throws DeviceControllerException {
long startTime = System.currentTimeMillis();
boolean hasNullHLU = volumeURIHLUsHasNullHLU(volumeURIHLUs);
if (!hasNullHLU || protocolControllers.isEmpty()) {
return;
}
try {
ExportMask mask = dbClient.queryObject(ExportMask.class, exportMaskURI);
Map<String, URI> deviceIdToURI = new HashMap<String, URI>();
for (VolumeURIHLU vuh : volumeURIHLUs) {
BlockObject volume = BlockObject.fetch(dbClient, vuh.getVolumeURI());
// with the ExportMask that do not yet have an HLU set
if (!mask.checkIfVolumeHLUSet(vuh.getVolumeURI())) {
deviceIdToURI.put(volume.getNativeId(), volume.getId());
}
}
boolean requiresUpdate = false;
CloseableIterator<CIMInstance> protocolControllerForUnitIter;
for (CIMObjectPath protocolController : protocolControllers) {
_log.info(String.format("setHLUFromProtocolControllers -- protocolController=%s", protocolController.toString()));
protocolControllerForUnitIter = null;
try {
protocolControllerForUnitIter = cimConnection.getCimClient().referenceInstances(protocolController, CIM_PROTOCOL_CONTROLLER_FOR_UNIT, null, false, PS_DEVICE_NUMBER);
while (protocolControllerForUnitIter.hasNext()) {
CIMInstance pcu = protocolControllerForUnitIter.next();
CIMObjectPath pcuPath = pcu.getObjectPath();
CIMProperty<CIMObjectPath> dependentVolumePropery = (CIMProperty<CIMObjectPath>) pcuPath.getKey(CP_DEPENDENT);
CIMObjectPath dependentVolumePath = dependentVolumePropery.getValue();
String deviceId = dependentVolumePath.getKey(CP_DEVICE_ID).getValue().toString();
URI volumeURI = deviceIdToURI.get(deviceId);
if (volumeURI != null) {
String deviceNumber = CIMPropertyFactory.getPropertyValue(pcu, CP_DEVICE_NUMBER);
_log.info(String.format("setHLUFromProtocolControllers -- volumeURI=%s --> %s", volumeURI.toString(), deviceNumber));
mask.addVolume(volumeURI, (int) Long.parseLong(deviceNumber, 16));
requiresUpdate = true;
}
}
} finally {
if (protocolControllerForUnitIter != null) {
protocolControllerForUnitIter.close();
}
}
}
if (requiresUpdate) {
dbClient.persistObject(mask);
}
} catch (Exception e) {
_log.error("Unexpected error: setHLUFromProtocolControllers failed.", e);
ServiceError error = DeviceControllerErrors.smis.methodFailed("setHLUFromProtocolControllers", e.getMessage());
taskCompleter.error(dbClient, error);
} finally {
long totalTime = System.currentTimeMillis() - startTime;
_log.info(String.format("setHLUFromProtocolControllers took %f seconds", (double) totalTime / (double) 1000));
}
}
use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.
the class VmaxExportOperations method createOrSelectStorageGroup.
private CIMObjectPath createOrSelectStorageGroup(StorageSystem storage, URI exportMaskURI, Collection<Initiator> initiators, VolumeURIHLU[] volumeURIHLUs, String parentGroupName, Map<StorageGroupPolicyLimitsParam, CIMObjectPath> newlyCreatedChildVolumeGroups, TaskCompleter taskCompleter) throws Exception {
List<CIMObjectPath> childVolumeGroupsToBeAddedToParentGroup = new ArrayList<CIMObjectPath>();
String groupName = null;
CIMObjectPath groupPath = null;
ExportMask mask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
// group volumes based on policy
ListMultimap<StorageGroupPolicyLimitsParam, VolumeURIHLU> policyToVolumeGroup = ArrayListMultimap.create();
WBEMClient client = _helper.getConnection(storage).getCimClient();
/**
* 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) ..
*
* For each Group {
* 1. Create a Storage Group.
* 2. Associate Fast Policy, bandwidth and IOPs ,based on the Group key.
*
* On failure ,remove the storage group, disassociate the added properties.
* }
*/
for (VolumeURIHLU volumeUriHLU : volumeURIHLUs) {
StorageGroupPolicyLimitsParam sgPolicyLimitsParam = null;
URI boUri = volumeUriHLU.getVolumeURI();
BlockObject bo = BlockObject.fetch(_dbClient, boUri);
boolean fastAssociatedAlready = false;
// Export fast volumes to 2 different nodes.
if (_helper.isFastPolicy(volumeUriHLU.getAutoTierPolicyName())) {
fastAssociatedAlready = _helper.checkVolumeAssociatedWithAnySGWithPolicy(bo.getNativeId(), storage, volumeUriHLU.getAutoTierPolicyName());
}
// 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);
sgPolicyLimitsParam = new StorageGroupPolicyLimitsParam(Constants.NONE, volumeUriHLU.getHostIOLimitBandwidth(), volumeUriHLU.getHostIOLimitIOPs(), storage);
} else {
sgPolicyLimitsParam = new StorageGroupPolicyLimitsParam(volumeUriHLU, storage);
}
policyToVolumeGroup.put(sgPolicyLimitsParam, volumeUriHLU);
}
_log.info("{} Groups generated based on grouping volumes by fast policy", policyToVolumeGroup.size());
/**
* Grouped Volumes based on Fast Policy
*/
for (Entry<StorageGroupPolicyLimitsParam, Collection<VolumeURIHLU>> policyToVolumeGroupEntry : policyToVolumeGroup.asMap().entrySet()) {
List<CIMObjectPath> childVolumeGroupsToBeAdded = new ArrayList<CIMObjectPath>();
StorageGroupPolicyLimitsParam storageGroupPolicyLimitsParam = policyToVolumeGroupEntry.getKey();
ListMultimap<String, VolumeURIHLU> expectedVolumeHluMap = ControllerUtils.getVolumeNativeGuids(policyToVolumeGroupEntry.getValue(), _dbClient);
Map<String, Set<String>> existingGroupPaths;
// in case of non-fast always create a new Storage Group
if (!_helper.isFastPolicy(storageGroupPolicyLimitsParam.getAutoTierPolicyName())) {
_log.info("Non-FAST create a new Storage Group");
VolumeURIHLU[] volumeURIHLU = new VolumeURIHLU[policyToVolumeGroupEntry.getValue().size()];
volumeURIHLU = policyToVolumeGroupEntry.getValue().toArray(volumeURIHLU);
groupName = generateStorageGroupName(storage, mask, initiators, storageGroupPolicyLimitsParam);
_log.debug("Group Name Created {}", groupName);
groupPath = createVolumeGroup(storage, groupName, volumeURIHLU, taskCompleter, true);
_log.info("Volume Group {} created on Array", groupPath);
} else // in case of fast enabled, try to find any existing groups which can be reused.
{
/**
* Find any existing Storage Groups can be reused, in
* case of Fast Enabled volumes
*/
_log.info("Running Storage Group Selection Process");
existingGroupPaths = _helper.findAnyStorageGroupsCanBeReUsed(storage, expectedVolumeHluMap, storageGroupPolicyLimitsParam);
if (existingGroupPaths.size() > 0) {
_log.info("Existing Storage Groups Found :" + Joiner.on("\t").join(existingGroupPaths.keySet()));
} else {
_log.info("No existing Storage Groups Found for policy: " + storageGroupPolicyLimitsParam.toString());
}
if (existingGroupPaths.size() > 0) {
childVolumeGroupsToBeAdded.addAll(_helper.constructMaskingGroupPathsFromNames(existingGroupPaths.keySet(), storage));
}
Set<String> volumesInExistingStorageGroups = _helper.constructVolumeNativeGuids(existingGroupPaths.values());
_log.debug("Volumes part of existing reusable Storage Groups {}", Joiner.on("\t").join(volumesInExistingStorageGroups));
// Storage Group needs to be created for those volumes,
// which doesn't fit into
// existing groups.
Set<String> diff = Sets.difference(expectedVolumeHluMap.asMap().keySet(), volumesInExistingStorageGroups);
_log.debug("Remaining Volumes, for which new Storage Group needs to be created", Joiner.on("\t").join(diff));
// need to construct a new group for remaining volumes.
if (!diff.isEmpty()) {
VolumeURIHLU[] volumeURIHLU = ControllerUtils.constructVolumeUriHLUs(diff, expectedVolumeHluMap);
groupName = generateStorageGroupName(storage, mask, initiators, storageGroupPolicyLimitsParam);
_log.debug("Group Name Created :", groupName);
groupPath = createVolumeGroup(storage, groupName, volumeURIHLU, taskCompleter, true);
_log.info("Volume Group {} created on Array {}", groupName, storage.getSerialNumber());
}
}
if (null != groupPath) {
/**
* used later in deleting created groups on failure
*/
newlyCreatedChildVolumeGroups.put(storageGroupPolicyLimitsParam, groupPath);
childVolumeGroupsToBeAdded.add(groupPath);
}
/**
* check whether Storage Group is associated with Fast
* Policy, if not associate
*/
if (_helper.isFastPolicy(storageGroupPolicyLimitsParam.getAutoTierPolicyName())) {
for (CIMObjectPath path : childVolumeGroupsToBeAdded) {
// volumes).
if (!_helper.checkVolumeAssociatedWithPhantomSG(path, storage, storageGroupPolicyLimitsParam.getAutoTierPolicyName()) && !_helper.checkVolumeGroupAssociatedWithPolicy(storage, path, storageGroupPolicyLimitsParam.getAutoTierPolicyName())) {
_log.debug("Adding Volume Group {} to Fast Policy {}", path, storageGroupPolicyLimitsParam.getAutoTierPolicyName());
addVolumeGroupToAutoTieringPolicy(storage, storageGroupPolicyLimitsParam.getAutoTierPolicyName(), path, taskCompleter);
}
}
}
childVolumeGroupsToBeAddedToParentGroup.addAll(childVolumeGroupsToBeAdded);
}
// Avoid duplicate names for the Cascaded VolumeGroup
parentGroupName = _helper.generateGroupName(_helper.getExistingStorageGroupsFromArray(storage), parentGroupName);
CIMObjectPath cascadedGroupPath = createCascadedVolumeGroup(storage, parentGroupName, childVolumeGroupsToBeAddedToParentGroup, taskCompleter);
// for proper roll back , that is volume removal, if exception is thrown during update
for (Entry<StorageGroupPolicyLimitsParam, CIMObjectPath> createdChildVolumeGroupEntry : newlyCreatedChildVolumeGroups.entrySet()) {
CIMObjectPath childGroupPath = createdChildVolumeGroupEntry.getValue();
StorageGroupPolicyLimitsParam storageGroupPolicyLimitsParam = createdChildVolumeGroupEntry.getKey();
if (storageGroupPolicyLimitsParam.isHostIOLimitBandwidthSet()) {
_helper.updateHostIOLimitBandwidth(client, childGroupPath, storageGroupPolicyLimitsParam.getHostIOLimitBandwidth());
}
if (storageGroupPolicyLimitsParam.isHostIOLimitIOPsSet()) {
_helper.updateHostIOLimitIOPs(client, childGroupPath, storageGroupPolicyLimitsParam.getHostIOLimitIOPs());
}
}
return cascadedGroupPath;
}
use of com.emc.storageos.volumecontroller.impl.VolumeURIHLU in project coprhd-controller by CoprHD.
the class VmaxExportOperations method constructVolumeURIHLUFromURIList.
private VolumeURIHLU[] constructVolumeURIHLUFromURIList(List<URI> volumesInSG, String newPolicyName) {
List<VolumeURIHLU> volumeUriHLUs = new ArrayList<VolumeURIHLU>();
for (URI volURI : volumesInSG) {
VolumeURIHLU volumeUriHLU = new VolumeURIHLU(volURI, null, newPolicyName, null);
volumeUriHLUs.add(volumeUriHLU);
}
VolumeURIHLU[] volumeURIHLUArr = new VolumeURIHLU[volumeUriHLUs.size()];
return volumeUriHLUs.toArray(volumeURIHLUArr);
}
Aggregations