use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class VPlexDeviceController method setupNewExportMask.
/**
* Handles setting up a new ExportMask for creation on the VPLEX device.
*
* @param blockObjectMap
* the map of URIs to block volumes for export
* @param vplexSystem
* a StorageSystem object representing the VPLEX system
* @param exportGroup
* the ViPR export group
* @param varrayUri
* -- NOTE: may not be same as ExportGroup varray
* @param exportMasksToCreateOnDevice
* collection of ExportMasks to create
* @param inits
* the host initiators of the host in question
* @param vplexCluster
* String representing the VPLEX cluster in question
* @param opId
* the workflow step id
* @throws Exception
*/
private void setupNewExportMask(Map<URI, Integer> blockObjectMap, StorageSystem vplexSystem, ExportGroup exportGroup, URI varrayUri, List<ExportMask> exportMasksToCreateOnDevice, List<Initiator> initiators, String vplexCluster, String opId) throws Exception {
ExportPathParams pathParams = _blockScheduler.calculateExportPathParamForVolumes(blockObjectMap.keySet(), 0, vplexSystem.getId(), exportGroup.getId());
if (exportGroup.getType() != null) {
pathParams.setExportGroupType(exportGroup.getType());
}
Map<URI, List<URI>> assignments = _blockScheduler.assignStoragePorts(vplexSystem, exportGroup, initiators, null, pathParams, blockObjectMap.keySet(), _networkDeviceController, varrayUri, opId);
List<URI> targets = BlockStorageScheduler.getTargetURIsFromAssignments(assignments);
String maskName = getComputedExportMaskName(vplexSystem, varrayUri, initiators, CustomConfigConstants.VPLEX_STORAGE_VIEW_NAME);
ExportMask exportMask = ExportMaskUtils.initializeExportMask(vplexSystem, exportGroup, initiators, blockObjectMap, targets, assignments, maskName, _dbClient);
exportMask.addToUserCreatedInitiators(initiators);
// Consistency
exportMask.addInitiators(initiators);
_dbClient.updateObject(exportMask);
exportMasksToCreateOnDevice.add(exportMask);
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForAddInitiators.
/**
* Add workflow steps for adding Initiators to a specific varray for the given VPlex.
*
* @param workflow
* -- Workflow steps go into
* @param vplex
* -- Storage system
* @param exportGroup
* -- ExportGroup operation invoked on
* @param varrayURI
* -- Virtual Array URI that the Initiators are in
* @param hostInitiatorURIs
* -- URIs of the Initiators
* @param initiators
* -- list of Initiator objects
* @param hostURI
* -- The hostURI
* @param previousStepId
* -- wait on this step if non-null
* @param opId
* -- step id for our operation
* @return StepId of last step generated
*/
private String addStepsForAddInitiators(Workflow workflow, StorageSystem vplex, ExportGroup exportGroup, URI varrayURI, List<URI> hostInitiatorURIs, List<Initiator> initiators, URI hostURI, String previousStepId, String opId) throws Exception {
String lastStepId = null;
URI vplexURI = vplex.getId();
URI exportURI = exportGroup.getId();
String initListStr = Joiner.on(',').join(hostInitiatorURIs);
// Find the ExportMask for my host.
ExportMask exportMask = VPlexUtil.getExportMaskForHostInVarray(_dbClient, exportGroup, hostURI, vplexURI, varrayURI);
if (exportMask == null) {
_log.info("No export mask found for hostURI: " + hostURI + " varrayURI: " + varrayURI);
Map<URI, Integer> volumeMap = ExportUtils.getExportGroupVolumeMap(_dbClient, vplex, exportGroup);
// Partition the Volumes by varray.
Map<URI, Set<URI>> varrayToVolumes = VPlexUtil.mapBlockObjectsToVarrays(_dbClient, volumeMap.keySet(), vplexURI, exportGroup);
// Filter the volumes by our Varray.
Map<URI, Integer> varrayVolumeMap = ExportMaskUtils.filterVolumeMap(volumeMap, varrayToVolumes.get(varrayURI));
// Create the ExportMask if there are volumes in this varray.
if (!varrayVolumeMap.isEmpty()) {
lastStepId = assembleExportMasksWorkflow(vplexURI, exportURI, varrayURI, hostInitiatorURIs, varrayVolumeMap, true, workflow, previousStepId, opId);
}
} else {
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
_log.info("Refreshing ExportMask {}", exportMask.getMaskName());
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName), _networkDeviceController);
if (exportMask.getVolumes() == null) {
// This can occur in Brownfield scenarios where we have not added any volumes yet to the HA side,
// CTRL10760
_log.info(String.format("No volumes in ExportMask %s (%s), so not adding initiators", exportMask.getMaskName(), exportMask.getId()));
return lastStepId;
}
_log.info(String.format("Adding initiators %s for host %s mask %s (%s)", getInitiatorsWwnsString(initiators), hostURI.toString(), exportMask.getMaskName(), exportMask.getId()));
// Calculate the path parameters for the volumes in this ExportMask
Collection<URI> volumeURIs = new HashSet<URI>();
if (exportMask.getVolumes() != null && !exportMask.getVolumes().isEmpty()) {
volumeURIs = (Collections2.transform(exportMask.getVolumes().keySet(), CommonTransformerFunctions.FCTN_STRING_TO_URI));
} else if (exportGroup.getVolumes() != null && !exportGroup.getVolumes().isEmpty()) {
// Hit this condition
// in CTRL-9944
// (unknown why)
_log.info(String.format("No volumes in ExportMask %s, using ExportGroup %s for ExportPathParam", exportMask.getId(), exportGroup.getId()));
Map<URI, Integer> volumeMap = ExportUtils.getExportGroupVolumeMap(_dbClient, vplex, exportGroup);
// Partition the Volumes by varray. Then use only the volumes in the requested varray.
Map<URI, Set<URI>> varrayToVolumes = VPlexUtil.mapBlockObjectsToVarrays(_dbClient, volumeMap.keySet(), vplexURI, exportGroup);
volumeURIs = varrayToVolumes.get(varrayURI);
} else {
_log.info(String.format("No volumes at all- using default path parameters: %s", exportMask.getId()));
}
ExportPathParams pathParams = _blockScheduler.calculateExportPathParamForVolumes(volumeURIs, exportGroup.getNumPaths(), exportMask.getStorageDevice(), exportGroup.getId());
if (exportGroup.getType() != null) {
pathParams.setExportGroupType(exportGroup.getType());
}
// Assign additional StoragePorts if needed.
Map<URI, List<URI>> assignments = _blockScheduler.assignStoragePorts(vplex, exportGroup, initiators, exportMask.getZoningMap(), pathParams, volumeURIs, _networkDeviceController, varrayURI, opId);
List<URI> newTargetURIs = BlockStorageScheduler.getTargetURIsFromAssignments(assignments);
// Build a list of StoragePort targets to remove during rollback. Do not remove existing storage ports during rollback.
List<URI> rollbackTargetURIs = new ArrayList<URI>();
for (URI target : newTargetURIs) {
if (exportMask.getStoragePorts().contains(target.toString())) {
// Skip the target port if it exists in the ViPR ExportMask
continue;
}
rollbackTargetURIs.add(target);
}
exportMask.addZoningMap(BlockStorageScheduler.getZoneMapFromAssignments(assignments));
_dbClient.updateObject(exportMask);
_log.info(String.format("Adding targets %s for host %s", newTargetURIs.toString(), hostURI.toString()));
// Create a Step to add the SAN Zone
String zoningStepId = workflow.createStepId();
Workflow.Method zoningMethod = zoneAddInitiatorStepMethod(vplexURI, exportURI, hostInitiatorURIs, varrayURI);
Workflow.Method zoningRollbackMethod = zoneRollbackMethod(exportURI, zoningStepId);
zoningStepId = workflow.createStep(ZONING_STEP, String.format("Zone initiator %s to ExportGroup %s(%s)", initListStr, exportGroup.getLabel(), exportURI), previousStepId, vplexURI, vplex.getSystemType(), this.getClass(), zoningMethod, zoningRollbackMethod, zoningStepId);
// Create a Step to add the initiator to the Storage View
String message = String.format("initiators %s to StorageView %s", initListStr, exportGroup.getGeneratedName());
ExportMask sharedExportMask = VPlexUtil.getSharedExportMaskInDb(exportGroup, vplexURI, _dbClient, varrayURI, null, null);
boolean shared = false;
if (null != sharedExportMask && sharedExportMask.getId().equals(exportMask.getId())) {
shared = true;
}
String addInitStep = workflow.createStepId();
ExportMaskAddInitiatorCompleter addInitCompleter = new ExportMaskAddInitiatorCompleter(exportURI, exportMask.getId(), hostInitiatorURIs, newTargetURIs, addInitStep);
Workflow.Method addToViewMethod = storageViewAddInitiatorsMethod(vplexURI, exportURI, exportMask.getId(), hostInitiatorURIs, newTargetURIs, shared, addInitCompleter);
Workflow.Method addToViewRollbackMethod = storageViewAddInitiatorsRollbackMethod(vplexURI, exportURI, exportMask.getId(), hostInitiatorURIs, rollbackTargetURIs, addInitStep);
lastStepId = workflow.createStep("storageView", "Add " + message, zoningStepId, vplexURI, vplex.getSystemType(), this.getClass(), addToViewMethod, addToViewRollbackMethod, addInitStep);
}
return lastStepId;
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class ExternalDeviceExportOperations method addInitiators.
@Override
public void addInitiators(StorageSystem storage, URI exportMaskUri, List<URI> volumeURIs, List<com.emc.storageos.db.client.model.Initiator> initiatorList, List<URI> targetURIList, TaskCompleter taskCompleter) throws DeviceControllerException {
log.info("{} addInitiators START...", storage.getSerialNumber());
try {
log.info("addInitiators: Export mask id: {}", exportMaskUri);
if (volumeURIs != null) {
log.info("addInitiators: volumes : {}", Joiner.on(',').join(volumeURIs));
}
log.info("addInitiators: initiators : {}", Joiner.on(',').join(initiatorList));
log.info("addInitiators: targets : {}", Joiner.on(",").join(targetURIList));
BlockStorageDriver driver = externalDevice.getDriver(storage.getSystemType());
ExportMask exportMask = (ExportMask) dbClient.queryObject(exportMaskUri);
// Get export group uri from task completer
URI exportGroupUri = taskCompleter.getId();
ExportGroup exportGroup = (ExportGroup) dbClient.queryObject(exportGroupUri);
List<URI> volumeUris = ExportMaskUtils.getVolumeURIs(exportMask);
// Prepare volumes
List<StorageVolume> driverVolumes = new ArrayList<>();
Map<String, String> driverVolumeToHLUMap = new HashMap<>();
Map<String, String> volumeNativeIdToUriMap = new HashMap<>();
prepareVolumes(storage, exportMask.getVolumes(), driverVolumes, driverVolumeToHLUMap, volumeNativeIdToUriMap);
// Prepare initiators
List<Initiator> driverInitiators = new ArrayList<>();
prepareInitiators(initiatorList, exportGroup.forCluster(), driverInitiators);
// Prepare target storage ports
List<StoragePort> recommendedPorts = new ArrayList<>();
List<StoragePort> availablePorts = new ArrayList<>();
List<StoragePort> selectedPorts = new ArrayList<>();
// Prepare ports for driver call. Populate lists of recommended and available ports.
Map<String, com.emc.storageos.db.client.model.StoragePort> nativeIdToAvailablePortMap = new HashMap<>();
preparePorts(storage, exportMaskUri, targetURIList, recommendedPorts, availablePorts, nativeIdToAvailablePortMap);
ExportPathParams pathParams = blockScheduler.calculateExportPathParamForVolumes(volumeUris, exportGroup.getNumPaths(), storage.getId(), exportGroupUri);
StorageCapabilities capabilities = new StorageCapabilities();
// Prepare num paths to send to driver
prepareCapabilitiesForAddInitiators(pathParams, exportMask.getZoningMap(), exportGroup.getVirtualArray(), initiatorList, capabilities);
MutableBoolean usedRecommendedPorts = new MutableBoolean(true);
// Ready to call driver
DriverTask task = driver.exportVolumesToInitiators(driverInitiators, driverVolumes, driverVolumeToHLUMap, recommendedPorts, availablePorts, capabilities, usedRecommendedPorts, selectedPorts);
// todo: need to implement support for async case.
if (task.getStatus() == DriverTask.TaskStatus.READY) {
// If driver used recommended ports, we are done.
// Otherwise, if driver did not use recommended ports, we have to get ports selected by driver
// and use them in export mask and zones.
// We will verify driver selected ports against available ports list.
String msg = String.format("addInitiators -- Added initiators: %s . Used recommended ports: %s .", task.getMessage(), usedRecommendedPorts);
log.info(msg);
if (usedRecommendedPorts.isFalse()) {
// process driver selected ports
log.info("Ports selected by driver: {}", selectedPorts);
if (validateSelectedPorts(availablePorts, selectedPorts, pathParams.getPathsPerInitiator())) {
List<com.emc.storageos.db.client.model.StoragePort> selectedPortsForMask = new ArrayList<>();
URI varrayUri = exportGroup.getVirtualArray();
for (StoragePort driverPort : selectedPorts) {
com.emc.storageos.db.client.model.StoragePort port = nativeIdToAvailablePortMap.get(driverPort.getNativeId());
selectedPortsForMask.add(port);
}
updateStoragePortsForAddInitiators((ExportMaskAddInitiatorCompleter) taskCompleter, storage, exportMask, initiatorList, selectedPortsForMask, varrayUri, pathParams);
taskCompleter.ready(dbClient);
} else {
// selected ports are not valid. failure
String errorMsg = "addInitiators -- Ports selected by driver failed validation.";
log.error("addInitiators -- Ports selected by driver failed validation.");
ServiceError serviceError = ExternalDeviceException.errors.addInitiatorsToExportMaskFailed("addInitiators", errorMsg);
taskCompleter.error(dbClient, serviceError);
}
} else {
// Used recommended ports.
taskCompleter.ready(dbClient);
}
} else {
String errorMsg = String.format("addInitiators -- Failed to add initiators to export mask: %s .", task.getMessage());
log.error(errorMsg);
ServiceError serviceError = ExternalDeviceException.errors.addInitiatorsToExportMaskFailed("addInitiators", errorMsg);
taskCompleter.error(dbClient, serviceError);
}
} catch (Exception ex) {
log.error("addInitiators -- Failed to add initiators to export mask. ", ex);
ServiceError serviceError = ExternalDeviceException.errors.addInitiatorsToExportMaskFailed("addInitiators", ex.getMessage());
taskCompleter.error(dbClient, serviceError);
}
log.info("{} addInitiators END...", storage.getSerialNumber());
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class ExternalDeviceExportOperations method createExportMask.
@Override
public void createExportMask(StorageSystem storage, URI exportMaskUri, VolumeURIHLU[] volumeURIHLUs, List<URI> targetURIList, List<com.emc.storageos.db.client.model.Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
log.info("{} createExportMask START...", storage.getSerialNumber());
try {
log.info("createExportMask: Export mask id: {}", exportMaskUri);
log.info("createExportMask: volume-HLU pairs: {}", Joiner.on(',').join(volumeURIHLUs));
log.info("createExportMask: initiators: {}", Joiner.on(',').join(initiatorList));
log.info("createExportMask: assignments: {}", Joiner.on(',').join(targetURIList));
BlockStorageDriver driver = externalDevice.getDriver(storage.getSystemType());
ExportMask exportMask = (ExportMask) dbClient.queryObject(exportMaskUri);
// Get export group uri from task completer
URI exportGroupUri = taskCompleter.getId();
ExportGroup exportGroup = (ExportGroup) dbClient.queryObject(exportGroupUri);
Set<URI> volumeUris = new HashSet<>();
for (VolumeURIHLU volumeURIHLU : volumeURIHLUs) {
URI volumeURI = volumeURIHLU.getVolumeURI();
volumeUris.add(volumeURI);
}
// Prepare volumes
List<StorageVolume> driverVolumes = new ArrayList<>();
Map<String, String> driverVolumeToHLUMap = new HashMap<>();
Map<String, URI> volumeNativeIdToUriMap = new HashMap<>();
prepareVolumes(storage, volumeURIHLUs, driverVolumes, driverVolumeToHLUMap, volumeNativeIdToUriMap);
// Prepare initiators
List<Initiator> driverInitiators = new ArrayList<>();
prepareInitiators(initiatorList, exportGroup.forCluster(), driverInitiators);
// Prepare target storage ports
List<StoragePort> recommendedPorts = new ArrayList<>();
List<StoragePort> availablePorts = new ArrayList<>();
List<StoragePort> selectedPorts = new ArrayList<>();
// Prepare ports for driver call. Populate lists of recommended and available ports.
Map<String, com.emc.storageos.db.client.model.StoragePort> nativeIdToAvailablePortMap = new HashMap<>();
preparePorts(storage, exportMaskUri, targetURIList, recommendedPorts, availablePorts, nativeIdToAvailablePortMap);
ExportPathParams pathParams = blockScheduler.calculateExportPathParamForVolumes(volumeUris, exportGroup.getNumPaths(), storage.getId(), exportGroupUri);
StorageCapabilities capabilities = new StorageCapabilities();
// Prepare num paths to send to driver
prepareCapabilities(pathParams, capabilities);
MutableBoolean usedRecommendedPorts = new MutableBoolean(true);
// Ready to call driver
DriverTask task = driver.exportVolumesToInitiators(driverInitiators, driverVolumes, driverVolumeToHLUMap, recommendedPorts, availablePorts, capabilities, usedRecommendedPorts, selectedPorts);
// todo: need to implement support for async case.
if (task.getStatus() == DriverTask.TaskStatus.READY) {
// If driver used recommended ports, we are done.
// Otherwise, if driver did not use recommended ports, we have to get ports selected by driver
// and use them in export mask and zones.
// We will verify driver selected ports against available ports list.
String msg = String.format("createExportMask -- Created export: %s . Used recommended ports: %s .", task.getMessage(), usedRecommendedPorts);
log.info(msg);
log.info("Recommended ports: {}", recommendedPorts);
log.info("Available ports: {}", availablePorts);
log.info("Selected ports: {}", selectedPorts);
if (usedRecommendedPorts.isFalse()) {
// process driver selected ports
if (validateSelectedPorts(availablePorts, selectedPorts, pathParams.getMinPaths())) {
List<com.emc.storageos.db.client.model.StoragePort> selectedPortsForMask = new ArrayList<>();
for (StoragePort driverPort : selectedPorts) {
com.emc.storageos.db.client.model.StoragePort port = nativeIdToAvailablePortMap.get(driverPort.getNativeId());
selectedPortsForMask.add(port);
}
updateStoragePortsInExportMask(exportMask, exportGroup, selectedPortsForMask);
// Update volumes Lun Ids in export mask based on driver selection
for (String volumeNativeId : driverVolumeToHLUMap.keySet()) {
String targetLunId = driverVolumeToHLUMap.get(volumeNativeId);
URI volumeUri = volumeNativeIdToUriMap.get(volumeNativeId);
exportMask.getVolumes().put(volumeUri.toString(), targetLunId);
}
dbClient.updateObject(exportMask);
taskCompleter.ready(dbClient);
} else {
// selected ports are not valid. failure
String errorMsg = "createExportMask -- Ports selected by driver failed validation.";
log.error("createExportMask -- Ports selected by driver failed validation.");
ServiceError serviceError = ExternalDeviceException.errors.createExportMaskFailed("createExportMask", errorMsg);
taskCompleter.error(dbClient, serviceError);
}
} else {
// Update volumes Lun Ids in export mask based on driver selection
for (String volumeNativeId : driverVolumeToHLUMap.keySet()) {
String targetLunId = driverVolumeToHLUMap.get(volumeNativeId);
URI volumeUri = volumeNativeIdToUriMap.get(volumeNativeId);
exportMask.getVolumes().put(volumeUri.toString(), targetLunId);
}
dbClient.updateObject(exportMask);
taskCompleter.ready(dbClient);
}
} else {
String errorMsg = String.format("createExportMask -- Failed to create export: %s .", task.getMessage());
log.error(errorMsg);
ServiceError serviceError = ExternalDeviceException.errors.createExportMaskFailed("createExportMask", errorMsg);
taskCompleter.error(dbClient, serviceError);
}
} catch (Exception ex) {
log.error("Problem in createExportMask: ", ex);
log.error("createExportMask -- Failed to create export mask. ", ex);
ServiceError serviceError = ExternalDeviceException.errors.createExportMaskFailed("createExportMask", ex.getMessage());
taskCompleter.error(dbClient, serviceError);
}
log.info("{} createExportMask END...", storage.getSerialNumber());
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class ExternalDeviceExportOperations method addVolumes.
@Override
public void addVolumes(StorageSystem storage, URI exportMaskUri, VolumeURIHLU[] volumeURIHLUs, List<com.emc.storageos.db.client.model.Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
log.info("{} addVolumes START...", storage.getSerialNumber());
try {
log.info("addVolumes: Export mask id: {}", exportMaskUri);
log.info("addVolumes: New volumes to add: volume-HLU pairs: {}", Joiner.on(',').join(volumeURIHLUs));
if (initiatorList != null) {
log.info("addVolumes: initiators: {}", Joiner.on(',').join(initiatorList));
}
BlockStorageDriver driver = externalDevice.getDriver(storage.getSystemType());
ExportMask exportMask = (ExportMask) dbClient.queryObject(exportMaskUri);
StringSet maskInitiators = exportMask.getInitiators();
List<String> maskInitiatorList = new ArrayList<>();
for (String initiatorUri : maskInitiators) {
maskInitiatorList.add(initiatorUri);
}
log.info("Export mask existing initiators: {} ", Joiner.on(',').join(maskInitiatorList));
StringSet storagePorts = exportMask.getStoragePorts();
List<URI> portList = new ArrayList<>();
for (String portUri : storagePorts) {
portList.add(URI.create(portUri));
}
log.info("Export mask existing storage ports: {} ", Joiner.on(',').join(portList));
// Get export group uri from task completer
URI exportGroupUri = taskCompleter.getId();
ExportGroup exportGroup = (ExportGroup) dbClient.queryObject(exportGroupUri);
Set<URI> volumeUris = new HashSet<>();
for (VolumeURIHLU volumeURIHLU : volumeURIHLUs) {
URI volumeURI = volumeURIHLU.getVolumeURI();
volumeUris.add(volumeURI);
}
// Prepare volumes. We send to driver only new volumes for the export mask.
List<StorageVolume> driverVolumes = new ArrayList<>();
Map<String, String> driverVolumeToHLUMap = new HashMap<>();
Map<String, URI> volumeNativeIdToUriMap = new HashMap<>();
prepareVolumes(storage, volumeURIHLUs, driverVolumes, driverVolumeToHLUMap, volumeNativeIdToUriMap);
// Prepare initiators
Set<com.emc.storageos.db.client.model.Initiator> initiators = ExportMaskUtils.getInitiatorsForExportMask(dbClient, exportMask, null);
List<Initiator> driverInitiators = new ArrayList<>();
prepareInitiators(initiators, exportGroup.forCluster(), driverInitiators);
// Prepare target storage ports
List<StoragePort> recommendedPorts = new ArrayList<>();
List<StoragePort> availablePorts = new ArrayList<>();
List<StoragePort> selectedPorts = new ArrayList<>();
// Prepare ports for driver call. Populate lists of recommended and available ports.
Map<String, com.emc.storageos.db.client.model.StoragePort> nativeIdToAvailablePortMap = new HashMap<>();
// We use existing ports in the mask as recommended ports.
preparePorts(storage, exportMaskUri, portList, recommendedPorts, availablePorts, nativeIdToAvailablePortMap);
log.info("varray ports: {}", nativeIdToAvailablePortMap);
// For add volumes to existing export mask, we do not allow storage port change in the mask.
// Only ports in the mask are available for driver call.
availablePorts = recommendedPorts;
ExportPathParams pathParams = blockScheduler.calculateExportPathParamForVolumes(volumeUris, exportGroup.getNumPaths(), storage.getId(), exportGroupUri);
StorageCapabilities capabilities = new StorageCapabilities();
// Prepare num paths to send to driver
prepareCapabilities(pathParams, capabilities);
MutableBoolean usedRecommendedPorts = new MutableBoolean(true);
// Ready to call driver
DriverTask task = driver.exportVolumesToInitiators(driverInitiators, driverVolumes, driverVolumeToHLUMap, recommendedPorts, availablePorts, capabilities, usedRecommendedPorts, selectedPorts);
// todo: need to implement support for async case.
if (task.getStatus() == DriverTask.TaskStatus.READY) {
String msg = String.format("Created export for volumes: %s . Used recommended ports: %s .", task.getMessage(), usedRecommendedPorts);
log.info(msg);
log.info("Driver selected storage ports: {} ", Joiner.on(',').join(selectedPorts));
// auto san zoning is enabled, we will fail the request.
if (usedRecommendedPorts.isFalse() && !selectedPorts.containsAll(recommendedPorts)) {
// for auto san zoning enabled we can not support case when selected ports do not include ports which are already in the mask
VirtualArray varray = dbClient.queryObject(VirtualArray.class, exportGroup.getVirtualArray());
log.info("AutoSanZoning for varray {} is {} ", varray.getLabel(), varray.getAutoSanZoning());
if (varray.getAutoSanZoning()) {
String errorMsg = String.format("AutoSanZoning is enabled and driver selected ports do not contain ports from the export mask: %s .", task.getMessage());
log.error(errorMsg);
ServiceError serviceError = ExternalDeviceException.errors.addVolumesToExportMaskFailed("addVolumes", errorMsg);
taskCompleter.error(dbClient, serviceError);
} else {
// auto san zoning is disabled --- add new selected ports to the mask
// we do not care about zoning map in this case
List<com.emc.storageos.db.client.model.StoragePort> selectedPortsForMask = new ArrayList<>();
for (StoragePort driverPort : selectedPorts) {
log.info("Driver selected port: {}", driverPort);
com.emc.storageos.db.client.model.StoragePort port = nativeIdToAvailablePortMap.get(driverPort.getNativeId());
if (port != null) {
// add all ports, StringSet in the mask will ignore duplicates
log.info("System port: {}", port);
selectedPortsForMask.add(port);
}
}
for (com.emc.storageos.db.client.model.StoragePort port : selectedPortsForMask) {
exportMask.addTarget(port.getId());
}
dbClient.updateObject(exportMask);
taskCompleter.ready(dbClient);
}
} else {
// Update volumes Lun Ids in export mask based on driver selection
for (String volumeNativeId : driverVolumeToHLUMap.keySet()) {
String targetLunId = driverVolumeToHLUMap.get(volumeNativeId);
URI volumeUri = volumeNativeIdToUriMap.get(volumeNativeId);
exportMask.getVolumes().put(volumeUri.toString(), targetLunId);
}
dbClient.updateObject(exportMask);
taskCompleter.ready(dbClient);
}
} else {
String errorMsg = String.format("Failed to add volumes to export mask: %s .", task.getMessage());
log.error(errorMsg);
ServiceError serviceError = ExternalDeviceException.errors.addVolumesToExportMaskFailed("addVolumes", errorMsg);
taskCompleter.error(dbClient, serviceError);
}
} catch (Exception ex) {
log.error("Problem in addVolumes: ", ex);
String errorMsg = String.format("Failed to add volumes to export mask: %s .", ex.getMessage());
log.error(errorMsg);
ServiceError serviceError = ExternalDeviceException.errors.addVolumesToExportMaskFailed("addVolumes", errorMsg);
taskCompleter.error(dbClient, serviceError);
}
log.info("{} addVolumes END...", storage.getSerialNumber());
}
Aggregations