use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class CreateExportGroupUpdateSchedulingThread method run.
@Override
public void run() {
_log.info("Starting scheduling for export group update thread...");
try {
Map<URI, Integer> newVolumesMap = exportGroupService.getUpdatedVolumesMap(exportUpdateParam, exportGroup);
Map<URI, Map<URI, Integer>> storageMap = exportGroupService.computeAndValidateVolumes(newVolumesMap, exportGroup, exportUpdateParam);
_log.info("Updated volumes belong to storage systems: {}", Joiner.on(',').join(storageMap.keySet()));
// Convert the storageMap to a list of added and removed Block Objects
newVolumesMap.clear();
for (Map.Entry<URI, Map<URI, Integer>> entry : storageMap.entrySet()) {
newVolumesMap.putAll(entry.getValue());
}
Map<URI, Integer> addedBlockObjectsMap = new HashMap<URI, Integer>();
Map<URI, Integer> removedBlockObjectsMap = new HashMap<URI, Integer>();
ExportUtils.getAddedAndRemovedBlockObjects(newVolumesMap, exportGroup, addedBlockObjectsMap, removedBlockObjectsMap);
_log.info("Added volumes: {}", Joiner.on(',').join(addedBlockObjectsMap.keySet()));
_log.info("Removed volumes: {}", Joiner.on(',').join(removedBlockObjectsMap.keySet()));
// If ExportPathParameter block is present, and volumes are added, capture ExportPathParameters arguments.
// This looks weird, but isn't. We use the added volumes from ExportCreateParam instead of addedBlockObjectsMap
// because the user may want to change the parameters for volumes that are already exported. In this way,
// the same volume can have different parameters to different hosts.
Map<URI, Integer> addedVolumeParams = exportGroupService.getChangedVolumes(exportUpdateParam, true);
ExportPathParams exportPathParam = null;
if (exportUpdateParam.getExportPathParameters() != null && !addedVolumeParams.keySet().isEmpty()) {
exportPathParam = exportGroupService.validateAndCreateExportPathParam(exportUpdateParam.getExportPathParameters(), exportGroup, addedVolumeParams.keySet());
exportGroupService.validatePortGroupWhenAddVolumesForExportGroup(addedVolumeParams.keySet(), exportUpdateParam.getExportPathParameters().getPortGroup(), exportGroup);
exportGroupService.addBlockObjectsToPathParamMap(addedVolumeParams.keySet(), exportPathParam.getId(), exportGroup);
} else if (!addedVolumeParams.keySet().isEmpty()) {
// exportPathParam is null
exportGroupService.validatePortGroupWhenAddVolumesForExportGroup(addedVolumeParams.keySet(), null, exportGroup);
}
// Remove the block objects being deleted from any existing path parameters.
exportGroupService.removeBlockObjectsFromPathParamMap(removedBlockObjectsMap.keySet(), exportGroup);
Set<URI> addedClusters = new HashSet<>();
Set<URI> removedClusters = new HashSet<>();
Set<URI> addedHosts = new HashSet<>();
Set<URI> removedHosts = new HashSet<>();
Set<URI> addedInitiators = new HashSet<>();
Set<URI> removedInitiators = new HashSet<>();
// Validate updated entries
List<URI> newInitiators = StringSetUtil.stringSetToUriList(exportGroup.getInitiators());
List<URI> newHosts = StringSetUtil.stringSetToUriList(exportGroup.getHosts());
List<URI> newClusters = StringSetUtil.stringSetToUriList(exportGroup.getClusters());
exportGroupService.validateClientsAndUpdate(exportGroup, project, storageMap.keySet(), exportUpdateParam, newClusters, newHosts, newInitiators, addedClusters, removedClusters, addedHosts, removedHosts, addedInitiators, removedInitiators);
_log.info("All clients were successfully validated");
dbClient.persistObject(exportGroup);
if (exportPathParam != null) {
dbClient.createObject(exportPathParam);
}
// push it to storage devices
BlockExportController exportController = exportGroupService.getExportController();
_log.info("Submitting export group update request.");
exportController.exportGroupUpdate(exportGroup.getId(), addedBlockObjectsMap, removedBlockObjectsMap, addedClusters, removedClusters, addedHosts, removedHosts, addedInitiators, removedInitiators, task);
} catch (Exception ex) {
if (ex instanceof ServiceCoded) {
dbClient.error(ExportGroup.class, taskRes.getResource().getId(), taskRes.getOpId(), (ServiceCoded) ex);
} else {
dbClient.error(ExportGroup.class, taskRes.getResource().getId(), taskRes.getOpId(), InternalServerErrorException.internalServerErrors.unexpectedErrorExportGroupPlacement(ex));
}
_log.error(ex.getMessage(), ex);
taskRes.setMessage(ex.getMessage());
}
_log.info("Ending export group update scheduling thread...");
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class ExportGroupService method pathsAdjustmentPreview.
/**
* Paths Adjustment Preview
*
* This call does a PORT Allocation which is used for a path adjustment preview operation.
* If the user is satisfied with the ports that are selected, they will invoke the provisioning through a
* separate API.
*
* Inputs are the the Export Group URI, Storage System URI, an optional Varray URI, and the ExportPath parameters.
* There is also a boolean that specifies the allocation should start assuming the existing paths are used (or not).
*
* @param id the URN of a ViPR export group to be updated; ports will be allocated in this context
* @param param -- ExportPortAllocateParam block containing Storage System URI, Varray URI, ExportPathParameters
*
* @brief Preview port allocation paths for export
* @return a PortAllocatePreviewRestRep rest response which contains the new or existing paths that will be provisioned
* or kept; the removed paths; and any other Export Groups that will be affected.
* @throws ControllerException
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/paths-adjustment-preview")
@CheckPermission(roles = { Role.TENANT_ADMIN }, acls = { ACL.OWN, ACL.ALL })
public ExportPathsAdjustmentPreviewRestRep pathsAdjustmentPreview(@PathParam("id") URI id, ExportPathsAdjustmentPreviewParam param) throws ControllerException {
// Basic validation of ExportGroup and update request
ExportGroup exportGroup = queryObject(ExportGroup.class, id, true);
if (exportGroup.checkInternalFlags(DataObject.Flag.DELETION_IN_PROGRESS)) {
throw BadRequestException.badRequests.deletionInProgress(exportGroup.getClass().getSimpleName(), exportGroup.getLabel());
}
validateExportGroupNoPendingEvents(exportGroup);
validateHostsInExportGroup(exportGroup, param.getHosts());
// Validate storage system
ArgValidator.checkUri(param.getStorageSystem());
StorageSystem system = queryObject(StorageSystem.class, param.getStorageSystem(), true);
// Get the virtual array, default to Export Group varray. Validate it matches.
URI varray = param.getVirtualArray();
if (varray != null) {
boolean validVarray = varray.equals(exportGroup.getVirtualArray());
if (exportGroup.getAltVirtualArrays() != null && varray.toString().equals(exportGroup.getAltVirtualArrays().get(system.getId().toString()))) {
validVarray = true;
}
if (!validVarray) {
throw APIException.badRequests.varrayNotInExportGroup(varray.toString());
}
} else {
varray = exportGroup.getVirtualArray();
}
// Validate the hosts, if supplied.
for (URI hostId : param.getHosts()) {
// Throw exception of thoe hostId is invalid
queryObject(Host.class, hostId, true);
}
// Get the initiators and validate the ExportMasks are usable.
ExportPathsAdjustmentPreviewRestRep response = new ExportPathsAdjustmentPreviewRestRep();
String storageSystem = system.getNativeGuid();
if (Type.vplex.equals(Type.valueOf(system.getSystemType()))) {
String vplexCluster = ConnectivityUtil.getVplexClusterForVarray(varray, system.getId(), _dbClient);
storageSystem = storageSystem + STORAGE_SYSTEM_CLUSTER + vplexCluster;
}
response.setStorageSystem(storageSystem);
List<Initiator> initiators = getInitiators(exportGroup);
StringSetMap existingPathMap = new StringSetMap();
StringSet storagePorts = new StringSet();
validatePathAdjustment(exportGroup, initiators, system, varray, param.getHosts(), response, existingPathMap, param.getUseExistingPaths(), storagePorts);
try {
// Manufacture an ExportPathParams structure from the REST ExportPathParameters structure
ExportPathParams pathParam = new ExportPathParams(param.getExportPathParameters(), exportGroup);
if (!storagePorts.isEmpty()) {
// check if storage ports are specified
StringSet paramPorts = pathParam.getStoragePorts();
if (paramPorts != null && !paramPorts.isEmpty()) {
if (!storagePorts.containsAll(paramPorts)) {
_log.error("Selected ports are not in the port group");
throw APIException.badRequests.pathAdjustmentSelectedPortsNotInPortGroup(Joiner.on(',').join(paramPorts), Joiner.on(',').join(storagePorts));
}
} else {
pathParam.setStoragePorts(storagePorts);
}
}
// Call the storage port allocator/assigner for all initiators (host or cluster) in
// the Export Group. Pass in the existing paths if requested in the parameters.
List<URI> volumes = StringSetUtil.stringSetToUriList(exportGroup.getVolumes().keySet());
Map<URI, List<URI>> zoningMap = _blockStorageScheduler.assignStoragePorts(system, varray, initiators, pathParam, (param.getUseExistingPaths() ? existingPathMap : new StringSetMap()), volumes);
for (Entry<URI, List<URI>> entry : zoningMap.entrySet()) {
InitiatorPortMapRestRep zone = new InitiatorPortMapRestRep();
Initiator initiator = queryObject(Initiator.class, entry.getKey(), false);
zone.setInitiator(HostMapper.map(initiator));
for (URI portURI : entry.getValue()) {
StoragePort port = queryObject(StoragePort.class, portURI, false);
zone.getStoragePorts().add(toNamedRelatedResource(port, port.getPortName()));
}
response.getAdjustedPaths().add(zone);
}
addRetainedPathsFromHosts(response, existingPathMap, param.getHosts());
Collections.sort(response.getAdjustedPaths(), response.new InitiatorPortMapRestRepComparator());
calculateRemovedPaths(response, zoningMap, exportGroup, system, varray, param.getHosts());
response.logResponse(_log);
return response;
} catch (ControllerException ex) {
_log.error(ex.getLocalizedMessage());
throw (ex);
}
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class ExportGroupService method validatePortAssignment.
/**
* Verifies that StoragePorts can be assigned for a StorageSystem given a set of Initiators.
* This will verify that the numPaths variable is not too low or too high to allow assignment.
*
* @param storageSystem
* @param varray VirtualArray of ExportGroup
* @param blockScheduler
* @param initiators List<Initiators>
* @param exportPathParameters Optional export path parameters to affect validation
* @param numPaths
*/
private void validatePortAssignment(StorageSystem storageSystem, URI varray, BlockStorageScheduler blockScheduler, List<Initiator> initiators, Collection<URI> volumes, URI exportGroupURI, ExportPathParameters exportPathParameters) {
try {
ExportPathParams pathParams = blockScheduler.calculateExportPathParamForVolumes(volumes, 0, storageSystem.getId(), exportGroupURI);
if (exportPathParameters != null) {
// Override the path parameters for the validity check.
if (exportPathParameters.getMaxPaths() != null) {
pathParams.setMaxPaths(exportPathParameters.getMaxPaths());
}
if (exportPathParameters.getMinPaths() != null) {
pathParams.setMinPaths(exportPathParameters.getMinPaths());
}
if (exportPathParameters.getPathsPerInitiator() != null) {
pathParams.setPathsPerInitiator(exportPathParameters.getPathsPerInitiator());
}
if (!NullColumnValueGetter.isNullURI(exportPathParameters.getPortGroup())) {
URI pgURI = exportPathParameters.getPortGroup();
if (!NullColumnValueGetter.isNullURI(pgURI)) {
StoragePortGroup portGroup = _dbClient.queryObject(StoragePortGroup.class, pgURI);
if (portGroup != null) {
pathParams.setStoragePorts(portGroup.getStoragePorts());
pathParams.setPortGroup(pgURI);
}
}
}
}
blockScheduler.assignStoragePorts(storageSystem, varray, initiators, pathParams, null, volumes);
} catch (ControllerException ex) {
_log.error(ex.getLocalizedMessage());
throw (ex);
}
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class ExportGroupService method validateAndCreateExportPathParam.
/**
* Validate the the optional path parameters are valid for the ExportGroup.
*
* @param param -- ExportPathParameters block
* @param exportGroup -- ExportGroup
* @param blockObjectURIs -- Collection of block object URIs, used only for validating ports
* @return ExportPathParam suitable for persistence
*/
ExportPathParams validateAndCreateExportPathParam(ExportPathParameters param, ExportGroup exportGroup, Collection<URI> blockObjectURIs) {
// If minPaths is specified, or pathsPerInitiator is specified, maxPaths must be specified
if ((param.getMinPaths() != null || param.getPathsPerInitiator() != null) && param.getMaxPaths() == null) {
throw APIException.badRequests.maxPathsRequired();
}
ExportPathParams pathParam = new ExportPathParams();
pathParam.setId(URIUtil.createId(ExportPathParams.class));
if (param.getMaxPaths() != null) {
ArgValidator.checkFieldMinimum(param.getMaxPaths(), 1, "max_paths");
if (param.getMinPaths() != null) {
ArgValidator.checkFieldMinimum(param.getMinPaths(), 1, "min_paths");
} else {
// Defaults to one path if not suppiled
param.setMinPaths(1);
}
if (param.getPathsPerInitiator() != null) {
ArgValidator.checkFieldMinimum(param.getPathsPerInitiator(), 1, "paths_per_initiator");
} else {
// Defaults to one path if not supplied
param.setPathsPerInitiator(1);
}
// minPaths must be <= than maxPaths.
if (param.getMinPaths() > param.getMaxPaths()) {
throw APIException.badRequests.minPathsGreaterThanMaxPaths();
}
// pathsPerInitiator must be <= maxPaths.
if (param.getPathsPerInitiator() > param.getMaxPaths()) {
throw APIException.badRequests.pathsPerInitiatorGreaterThanMaxPaths();
}
// Collect the list of Storage Systems used by the block objects.
Set<URI> storageArrays = new HashSet<URI>();
for (URI blockObjectURI : blockObjectURIs) {
BlockObject blockObject = BlockObject.fetch(_dbClient, blockObjectURI);
if (blockObject == null) {
continue;
}
storageArrays.add(blockObject.getStorageController());
}
// validate storage ports if they are supplied
validateExportPathParmPorts(param, exportGroup, storageArrays);
pathParam.setMaxPaths(param.getMaxPaths());
pathParam.setMinPaths(param.getMinPaths());
pathParam.setPathsPerInitiator(param.getPathsPerInitiator());
if (param.getStoragePorts() != null) {
pathParam.setStoragePorts(StringSetUtil.uriListToStringSet(param.getStoragePorts()));
}
// Validate there are no existing exports for the hosts involved that we could not override.
validateNoConflictingExports(exportGroup, storageArrays, pathParam);
}
if (!NullColumnValueGetter.isNullURI(param.getPortGroup())) {
// Check if the use port group config setting is on
String value = customConfigHandler.getComputedCustomConfigValue(CustomConfigConstants.VMAX_USE_PORT_GROUP_ENABLED, Type.vmax.name(), null);
if (Boolean.FALSE.toString().equalsIgnoreCase(value)) {
throw APIException.badRequests.portGroupSettingIsOff();
}
URI pgURI = param.getPortGroup();
ArgValidator.checkFieldUriType(pgURI, StoragePortGroup.class, "portGroupId");
StoragePortGroup portGroup = _dbClient.queryObject(StoragePortGroup.class, pgURI);
if (portGroup == null || !portGroup.isUsable()) {
throw APIException.badRequests.portGroupInvalid(pgURI.toString());
}
pathParam.setPortGroup(pgURI);
}
pathParam.setExplicitlyCreated(false);
return pathParam;
}
use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.
the class BlockStorageScheduler method getPrezoningPathParam.
/**
* This function changes the exportPaths parameter to be used when allocating from pre-zoned ports. When additional
* paths can be added to the pre-zoned ones, the pre-zoned ports allocation need not verify paths requirements.
* When additional paths cannot be added, then pre-zoned ports allocation need not verify paths requirements.
* This function ensures the proper paths parameters are passed to pre-zoned ports allocation.
*
* @param virtualArrayUri -- the export virtual array
* @param exportPathParams -- the required paths
* @param storage TODO
* @param backend TODO
* @return the paths parameter for allocating pre-zoned ports.
*/
private ExportPathParams getPrezoningPathParam(URI virtualArrayUri, ExportPathParams exportPathParams, StorageSystem storage, boolean backend) {
ExportPathParams prezoningPathParams = new ExportPathParams(exportPathParams.getMaxPaths(), exportPathParams.getMinPaths(), exportPathParams.getPathsPerInitiator(), exportPathParams.returnExportGroupType());
if (!allocateFromPrezonedPortsOnly(virtualArrayUri, null, false)) {
// If the application is expected to supply missing paths, then the export path needs to be
// changed to avoid failure on minPath check when prezoned paths do not meet the requirements
prezoningPathParams.setMinPaths(0);
prezoningPathParams.setAllowFewerPorts(true);
}
return prezoningPathParams;
}
Aggregations