use of com.emc.storageos.model.block.export.VolumeParam in project coprhd-controller by CoprHD.
the class ExportGroupService method validateBlockSnapshotsForExportGroupCreate.
/**
* Validate the BlockSnapshot exports from the request param.
*
* @param param the export group create request param.
*/
private void validateBlockSnapshotsForExportGroupCreate(ExportCreateParam param) {
if (param != null) {
List<URI> blockObjURIs = new ArrayList<URI>();
for (VolumeParam volParam : param.getVolumes()) {
blockObjURIs.add(volParam.getId());
}
// validate the RP BlockSnapshots for ExportGroup create
validateDuplicateRPBlockSnapshotsForExport(blockObjURIs);
// Validate VPLEX backend snapshots for export.
validateVPLEXBlockSnapshotsForExport(blockObjURIs);
}
}
use of com.emc.storageos.model.block.export.VolumeParam in project coprhd-controller by CoprHD.
the class ExportGroupService method validateVolumeLunIdParam.
/**
* While creating an export group, a user has the choice of supplying
* Host Lun Units corresponding to the volumes being added to the export
* group. This function makes sure that either the user has not supplied any
* HLUs (in which case the underlying storage device assigns them) or if the
* user has supplied them, then (s)he has supplied HLUs for ALL volumes. *
*/
private void validateVolumeLunIdParam(List<VolumeParam> volumes) {
int numDeviceNumbers = 0;
int volumeListSize = 0;
if (volumes != null && !volumes.isEmpty()) {
volumeListSize = volumes.size();
for (VolumeParam volParam : volumes) {
if (volParam.getLun() != ExportGroup.LUN_UNASSIGNED) {
numDeviceNumbers++;
}
}
}
if (numDeviceNumbers != 0 && numDeviceNumbers != volumeListSize) {
throw APIException.badRequests.invalidVolumeParamsAllOrNoneShouldSpecifyLun(volumes);
}
}
use of com.emc.storageos.model.block.export.VolumeParam in project coprhd-controller by CoprHD.
the class ExportGroupService method validateUpdateIsNotForVPlexBackendVolumes.
/**
* Validate that the update is not attempting to add/remove VPLEX backend volumes to/from a group.
*
* @param param [IN] - ExportUpdateParam holds the update request parameters
* @param exportGroup [IN] - ExportGroup to update
*/
private void validateUpdateIsNotForVPlexBackendVolumes(ExportUpdateParam param, ExportGroup exportGroup) {
if (param.getVolumes() != null) {
if (param.getVolumes().getAdd() != null) {
if (param.getVolumes().getAdd().size() > MAX_VOLUME_COUNT) {
throw APIException.badRequests.exceedingLimit("count", MAX_VOLUME_COUNT);
}
List<URI> addVolumeURIs = new ArrayList<URI>();
for (VolumeParam volParam : param.getVolumes().getAdd()) {
addVolumeURIs.add(volParam.getId());
}
BlockService.validateNoInternalBlockObjects(_dbClient, addVolumeURIs, false);
}
if (param.getVolumes().getRemove() != null && param.getVolumes().getRemove().size() > MAX_VOLUME_COUNT) {
throw APIException.badRequests.exceedingLimit("count", MAX_VOLUME_COUNT);
}
BlockService.validateNoInternalBlockObjects(_dbClient, param.getVolumes().getRemove(), false);
}
}
use of com.emc.storageos.model.block.export.VolumeParam in project coprhd-controller by CoprHD.
the class ExportGroupService method validateBlockObjectsAndGetMap.
/**
* This is a helper function to perform the input validation for an export group
* volumes and snapshots and return the map to be sent to the controller.
*
* @param volumes the input parameter
* @param exportGroup the export group
* @param storageMap an empty map that will be filled in by the function with the
* the block objects to export mapped by storage system
*
* @return a map of block object URI to LUN Id for the objects to be exported.
*/
private Map<URI, Integer> validateBlockObjectsAndGetMap(List<VolumeParam> volumes, ExportGroup exportGroup, Map<URI, Map<URI, Integer>> storageMap) {
if (volumes != null) {
// validate volumes Lun Ids
validateVolumeLunIdParam(volumes);
Map<URI, String> systemURIToSystemTypeMap = new HashMap<>();
// add volumes/snapshot to export group
for (VolumeParam volumeParam : volumes) {
BlockObject block = getAndValidateVolume(exportGroup, volumeParam.getId());
Integer lun = volumeParam.getLun();
if (block != null) {
if (block instanceof BlockSnapshot) {
BlockSnapshot snapshot = (BlockSnapshot) block;
checkIfOpenStackSnapshot(snapshot);
checkForActiveBlockSnapshot(snapshot);
} else if (block instanceof Volume) {
// ignore user specified HLU for cinder volume
if (lun != ExportGroup.LUN_UNASSIGNED && isCinderVolume((Volume) block, systemURIToSystemTypeMap)) {
_log.info("User specified HLU ({}) is ignored for cinder type volume" + " since Cinder API does not take HLU while exporting.", lun);
lun = ExportGroup.LUN_UNASSIGNED;
}
}
}
exportGroup.addVolume(volumeParam.getId(), lun);
}
}
storageMap.putAll(ExportUtils.getStorageToVolumeMap(exportGroup, false, _dbClient));
// get volumes
Map<URI, Integer> volumeMap = new HashMap<URI, Integer>();
for (URI storage : storageMap.keySet()) {
volumeMap.putAll(storageMap.get(storage));
}
return volumeMap;
}
use of com.emc.storageos.model.block.export.VolumeParam in project coprhd-controller by CoprHD.
the class ExportGroupService method createExportGroup.
/**
* Create block export.
* <p>
* Block export method is use to export one or more volumes to one or more hosts. This is a required step for a host to be able to
* access a block volume, although in some scenarios, additional configurations may be required. There are three main types of export
* group to meet the common use cases:
* <ol>
*
* <li>Create an initiator type export group so that a single host can see one or more volumes. An example would be an export group for
* a host boot lun or a private volume that is meant to be used by only one host. The assumption is, in this case the user wants the
* boot or private volume to be accessed via known initiators. For this type of export, the request object is expected to have only
* initiators (i.e. no hosts or clusters). Further, the initiators are expected to belong to the same host. While an initiator type
* export group can belong to only one host, this does not mean the host can only have the initiator type export group. A hosts can be
* part of many export groups of any type. The export group type {@link ExportGroupType#Initiator} should be specified in the request
* for this type of export.</li>
*
* <li>Create an export group so that one or more hosts, which are not part of a cluster, can access one or more volumes. This is the
* use case of a shared data lun. In this case, it is assumed that the user wants all the hosts initiators that are connected to the
* storage array (up to the maximum specified by the virtual pool) to be able to access the volume. The export group type
* {@link ExportGroupType#Host} should be specified in the request for this type of export.</li>
*
* <li>Create an export group so that one or more clusters of hosts can access one or more volumes. This is the same use case of shared
* data lun as the {@link ExportGroupType#Host} use case with the exception that the user is managing a cluster of hosts as opposed to
* individual hosts. In this case, the same assumption about the initiators as in the previous case is made. The export group type
* {@link ExportGroupType#Cluster} should be specified in the request for this type of export.</li>
* </ol>
*
* Note that the above discussion only mentions volumes but mirrors and snapshots can also be used in export groups.
*
* <p>
* Once a block export is created, following incremental changes can be applied to it: - add volume or volume snapshot to the shared
* storage pool - remove volume or volume snapshot from the shared storage pool - add new server to the cluster by adding initiator from
* that server to the block export - remove visibility of shared storage to a server by removing initiators from the block export
*
* <p>
* Similar to block storage provisioning, block export is also created within the scope of a varray. Hence, volumes and snapshots being
* added to a block export must belong to the same varray. Fibre Channel and iSCSI initiators must be part of SANs belonging to the same
* varray as block export.
* <p>
* For Fibre Channel initiators, SAN zones will also be created when the export group is created if the networks are discovered and:
* <ol>
* <li>at least one of the Network Systems can provision the Vsan or Fabric in which the each endpoint exists, and</li>
* <li>the VirtualArray has "auto_san_zoning" set to true.</li>
* </ol>
* The SAN zones each consists of an initiator (from the arguments) and a storage port that is selected. The number of zones created
* will be determined from the number of required initiator/storage-port communication paths.
* <p>
* NOTE: This is an asynchronous operation.
*
* @param param Export creation parameters
* @brief Create block export
* @return Block export details
* @throws ControllerException
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public TaskResourceRep createExportGroup(ExportCreateParam param) throws ControllerException {
// Validate count of number of volumes to export
if (param.getVolumes() != null && param.getVolumes().size() > MAX_VOLUME_COUNT) {
throw APIException.badRequests.exceedingLimit("count", MAX_VOLUME_COUNT);
}
// validate input for the type of export
validateCreateInputForExportType(param);
// backend volumes to a group.
if (param.getVolumes() != null && !param.getVolumes().isEmpty()) {
List<URI> addVolumeURIs = new ArrayList<URI>();
for (VolumeParam volParam : param.getVolumes()) {
addVolumeURIs.add(volParam.getId());
}
BlockService.validateNoInternalBlockObjects(_dbClient, addVolumeURIs, false);
/**
* Validate ExportGroup add volume's nativeId/nativeGuid
*/
validateBlockObjectNativeId(addVolumeURIs);
}
// Validate the project and check its permissions
Project project = queryObject(Project.class, param.getProject(), true);
StorageOSUser user = getUserFromContext();
if (!(_permissionsHelper.userHasGivenRole(user, project.getTenantOrg().getURI(), Role.TENANT_ADMIN) || _permissionsHelper.userHasGivenACL(user, project.getId(), ACL.OWN, ACL.ALL))) {
throw APIException.forbidden.insufficientPermissionsForUser(user.getName());
}
// Validate the varray and check its permissions
VirtualArray neighborhood = _dbClient.queryObject(VirtualArray.class, param.getVarray());
_permissionsHelper.checkTenantHasAccessToVirtualArray(project.getTenantOrg().getURI(), neighborhood);
validateBlockSnapshotsForExportGroupCreate(param);
// prepare the export group object
ExportGroup exportGroup = prepareExportGroup(project, param);
// validate block objects input and package them
Map<URI, Map<URI, Integer>> storageMap = new HashMap<URI, Map<URI, Integer>>();
Map<URI, Integer> volumeMap = validateBlockObjectsAndGetMap(param.getVolumes(), exportGroup, storageMap);
_log.info("Computed storage map: {} volumes in {} storage systems: {}", new Object[] { volumeMap.size(), storageMap.size(), storageMap.keySet().toArray() });
// Validate that there is not already an ExportGroup of the same name, project, and varray.
// If so, this is like because concurrent operations were in the API at the same time and another created
// the ExportGroup.
validateNotSameNameProjectAndVarray(param);
// If ExportPathParameter block is present, and volumes are present, validate have permissions.
// Processing will be in the aysnc. task.
ExportPathParameters pathParam = param.getExportPathParameters();
if (pathParam != null && !volumeMap.keySet().isEmpty()) {
// Only [RESTRICTED_]SYSTEM_ADMIN may override the Vpool export parameters
if ((pathParam.getMaxPaths() != null || pathParam.getMinPaths() != null || pathParam.getPathsPerInitiator() != null) && !_permissionsHelper.userHasGivenRole(user, null, Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN)) {
throw APIException.forbidden.onlySystemAdminsCanOverrideVpoolPathParameters(exportGroup.getLabel());
}
}
validatePortGroupWhenAddVolumesForExportGroup(volumeMap.keySet(), (pathParam != null ? pathParam.getPortGroup() : null), null);
// COP-14028
// Changing the return of a TaskList to return immediately while the underlying tasks are
// being built up. Steps:
// 1. Create a task object ahead of time and persist it for the export group
// 2. Fire off a thread that does the scheduling (planning) of the export operation
// 3. Return to the caller the new Task objects that is in the pending state.
// create export groups in the array but only when the export
// group has both block objects and initiators.
String task = UUID.randomUUID().toString();
Operation.Status status = storageMap.isEmpty() ? Operation.Status.ready : Operation.Status.pending;
_dbClient.createObject(exportGroup);
Operation op = initTaskStatus(exportGroup, task, status, ResourceOperationTypeEnum.CREATE_EXPORT_GROUP);
// persist the export group to the database
auditOp(OperationTypeEnum.CREATE_EXPORT_GROUP, true, AuditLogManager.AUDITOP_BEGIN, param.getName(), neighborhood.getId().toString(), project.getId().toString());
TaskResourceRep taskRes = toTask(exportGroup, task, op);
// call thread that does the work.
CreateExportGroupSchedulingThread.executeApiTask(this, _asyncTaskService.getExecutorService(), _dbClient, neighborhood, project, exportGroup, storageMap, param.getClusters(), param.getHosts(), param.getInitiators(), volumeMap, param.getExportPathParameters(), task, taskRes);
_log.info("Kicked off thread to perform export create scheduling. Returning task: " + taskRes.getId());
return taskRes;
}
Aggregations