/*
* Copyright 2008-2013 EMC Corporation
* Copyright 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.emc.storageos.api.service.impl.resource;
import static com.emc.storageos.api.mapper.BlockMapper.toVirtualPoolResource;
import static com.emc.storageos.api.mapper.DbObjectMapper.toNamedRelatedResource;
import java.net.URI;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.emc.storageos.api.mapper.DbObjectMapper;
import com.emc.storageos.api.service.authorization.PermissionsHelper;
import com.emc.storageos.api.service.impl.placement.VirtualPoolUtil;
import com.emc.storageos.api.service.impl.resource.cinder.QosService;
import com.emc.storageos.api.service.impl.resource.utils.CapacityUtils;
import com.emc.storageos.api.service.impl.resource.utils.GeoVisibilityHelper;
import com.emc.storageos.api.service.impl.response.FilterIterator;
import com.emc.storageos.api.service.impl.response.ResRepFilter;
import com.emc.storageos.api.service.impl.response.SearchedResRepList;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.constraint.AlternateIdConstraint;
import com.emc.storageos.db.client.constraint.ContainmentConstraint;
import com.emc.storageos.db.client.constraint.URIQueryResultList;
import com.emc.storageos.db.client.model.Bucket;
import com.emc.storageos.db.client.model.FilePolicy;
import com.emc.storageos.db.client.model.FileShare;
import com.emc.storageos.db.client.model.QosSpecification;
import com.emc.storageos.db.client.model.QuotaOfCinder;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StringMap;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.StringSetMap;
import com.emc.storageos.db.client.model.TenantOrg;
import com.emc.storageos.db.client.model.VirtualArray;
import com.emc.storageos.db.client.model.VirtualPool;
import com.emc.storageos.db.client.model.VirtualPool.ProvisioningType;
import com.emc.storageos.db.client.model.VirtualPool.Type;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.model.VpoolProtectionVarraySettings;
import com.emc.storageos.db.client.model.VpoolRemoteCopyProtectionSettings;
import com.emc.storageos.db.common.VdcUtil;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.model.BulkIdParam;
import com.emc.storageos.model.RelatedResourceRep;
import com.emc.storageos.model.ResourceTypeEnum;
import com.emc.storageos.model.auth.ACLAssignmentChanges;
import com.emc.storageos.model.auth.ACLAssignments;
import com.emc.storageos.model.pools.StoragePoolList;
import com.emc.storageos.model.pools.VirtualArrayAssignmentChanges;
import com.emc.storageos.model.pools.VirtualArrayAssignments;
import com.emc.storageos.model.quota.QuotaInfo;
import com.emc.storageos.model.quota.QuotaUpdateParam;
import com.emc.storageos.model.search.SearchResultResourceRep;
import com.emc.storageos.model.vpool.CapacityResponse;
import com.emc.storageos.model.vpool.ProtocolChanges;
import com.emc.storageos.model.vpool.StoragePoolAssignmentChanges;
import com.emc.storageos.model.vpool.StoragePoolAssignments;
import com.emc.storageos.model.vpool.VirtualPoolCommonParam;
import com.emc.storageos.model.vpool.VirtualPoolList;
import com.emc.storageos.model.vpool.VirtualPoolPoolUpdateParam;
import com.emc.storageos.model.vpool.VirtualPoolUpdateParam;
import com.emc.storageos.protectioncontroller.impl.recoverpoint.RPHelper;
import com.emc.storageos.security.authentication.StorageOSUser;
import com.emc.storageos.security.authorization.Role;
import com.emc.storageos.security.geo.GeoServiceClient;
import com.emc.storageos.services.OperationTypeEnum;
import com.emc.storageos.svcs.errorhandling.resources.APIException;
import com.emc.storageos.volumecontroller.impl.monitoring.RecordableBourneEvent;
import com.emc.storageos.volumecontroller.impl.monitoring.RecordableEventManager;
import com.emc.storageos.volumecontroller.impl.monitoring.cim.enums.RecordType;
import com.emc.storageos.volumecontroller.impl.smis.srdf.SRDFUtils;
import com.emc.storageos.volumecontroller.impl.utils.AttributeMatcherFramework;
import com.emc.storageos.volumecontroller.impl.utils.ImplicitPoolMatcher;
import com.emc.storageos.volumecontroller.impl.utils.ImplicitUnManagedObjectsMatcher;
import com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public abstract class VirtualPoolService extends TaggedResource {
protected static final String EVENT_SERVICE_TYPE = "VPOOL";
protected static final String EVENT_SERVICE_SOURCE = "VirtualPoolService";
protected static final String VPOOL_CREATED_DESCRIPTION = "Virtual Pool Created";
protected static final String VPOOL_UPDATED_DESCRIPTION = "Virtual Pool Updated";
protected static final String VPOOL_DELETED_DESCRIPTION = "Virtual Pool Deleted";
protected static final String VPOOL_PROTOCOL_NFS = "NFS";
protected static final String VPOOL_PROTOCOL_CIFS = "CIFS";
protected static final String VPOOL_PROTOCOL_NFSv4 = "NFSv4";
protected static final String VPOOL_PROTOCOL_FC = "FC";
protected static final String VPOOL_PROTOCOL_ISCSI = "iSCSI";
protected static final String VPOOL_PROTOCOL_SCALEIO = "ScaleIO";
protected static final String VPOOL_PROTOCOL_RBD = "RBD";
protected static final String VPOOL_PROVISIONING_TYPE = "provisioning_type";
protected static final String VPOOL_PROTOCOLS = "protocols";
protected static final String VPOOL_NAME = "name";
protected static final String VPOOL_DESCRIPTION = "description";
private static final Logger _log = LoggerFactory.getLogger(VirtualPoolService.class);
@Override
public String getServiceType() {
return EVENT_SERVICE_TYPE;
}
private static Set<String> fileProtocols = new HashSet<String>();
private static Set<String> blockProtocols = new HashSet<String>();
static {
// Initialize file type protocols
fileProtocols.add(VPOOL_PROTOCOL_NFS);
fileProtocols.add(VPOOL_PROTOCOL_CIFS);
fileProtocols.add(VPOOL_PROTOCOL_NFSv4);
// initialize block protocols
blockProtocols.add(VPOOL_PROTOCOL_FC);
blockProtocols.add(VPOOL_PROTOCOL_ISCSI);
blockProtocols.add(VPOOL_PROTOCOL_SCALEIO);
blockProtocols.add(VPOOL_PROTOCOL_RBD);
}
@Autowired
private RecordableEventManager _evtMgr;
@Autowired
protected GeoVisibilityHelper _geoHelper;
protected AttributeMatcherFramework _matcherFramework;
/**
* This method is used to set the common VirtualPool create params in
* VirtualPool model.
*
* @param vpool : VirtualPool object to populate params.
* @param param : VirtualPoolCreate params.
* @throws DatabaseException
*/
protected void populateCommonVirtualPoolCreateParams(VirtualPool vpool,
VirtualPoolCommonParam param) throws DatabaseException {
// Validate the name for not null and non-empty values
// ArgValidator.checkFieldNotEmpty(param.getName(), VPOOL_NAME);
if (StringUtils.isNotEmpty(param.getName())) {
vpool.setLabel(param.getName());
}
if (StringUtils.isNotEmpty(param.getDescription())) {
vpool.setDescription(param.getDescription());
}
ArgValidator.checkFieldNotEmpty(param.getProvisionType(), VPOOL_PROVISIONING_TYPE);
ArgValidator.checkFieldValueFromEnum(param.getProvisionType(), VPOOL_PROVISIONING_TYPE,
EnumSet.of(ProvisioningType.Thick, ProvisioningType.Thin));
vpool.setId(URIUtil.createId(VirtualPool.class));
if (null != param.getProvisionType()) {
vpool.setSupportedProvisioningType(param.getProvisionType());
}
vpool.setMaxNativeSnapshots(0);
vpool.setProtocols(new StringSet());
// Validate the protocols for not null and non-empty values
ArgValidator.checkFieldNotEmpty(param.getProtocols(), VPOOL_PROTOCOLS);
// Validate the protocols for type of VirtualPool.
validateVirtualPoolProtocol(vpool.getType(), param.getProtocols());
vpool.getProtocols().addAll(param.getProtocols());
// validate and set neighborhoods
if (param.getVarrays() != null) {
vpool.setVirtualArrays(new StringSet());
for (String neighborhood : param.getVarrays()) {
URI neighborhoodURI = URI.create(neighborhood);
ArgValidator.checkUri(neighborhoodURI);
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, neighborhoodURI);
ArgValidator.checkEntity(varray, neighborhoodURI, isIdEmbeddedInURL(neighborhoodURI));
vpool.getVirtualArrays().add(neighborhood);
}
}
// Set the useMatchedPools flag.
vpool.setUseMatchedPools(param.getUseMatchedPools());
}
protected void validateVirtualPoolProtocol(String type, Set<String> protocols) {
if (null != protocols && !protocols.isEmpty()) {
// Validate the protocols for type of VirtualPool.
switch (VirtualPool.Type.lookup(type)) {
case file:
if (!fileProtocols.containsAll(protocols)) {
throw APIException.badRequests.invalidProtocolsForVirtualPool(type, protocols, VPOOL_PROTOCOL_NFS,
VPOOL_PROTOCOL_CIFS, VPOOL_PROTOCOL_NFSv4);
}
break;
case block:
if (!blockProtocols.containsAll(protocols)) {
throw APIException.badRequests.invalidProtocolsForVirtualPool(type, protocols, VPOOL_PROTOCOL_FC,
VPOOL_PROTOCOL_ISCSI, VPOOL_PROTOCOL_SCALEIO, VPOOL_PROTOCOL_RBD);
}
default:
break;
}
}
}
/**
* This method is responsible to populate common VirtualPoolUpdateParams.
*
* @param vpool : id of VirtualPool to update.
* @param param : VirtualPoolParam to update.
*/
protected void populateCommonVirtualPoolUpdateParams(VirtualPool vpool,
VirtualPoolUpdateParam param) {
if (param.getName() != null && !param.getName().isEmpty()) {
if (!param.getName().equalsIgnoreCase(vpool.getLabel())) {
checkForDuplicateName(param.getName(), VirtualPool.class);
}
vpool.setLabel(param.getName());
}
ArgValidator.checkFieldValueWithExpected(!VirtualPool.ProvisioningType.NONE.name()
.equalsIgnoreCase(param.getProvisionType()), VPOOL_PROVISIONING_TYPE, param.getProvisionType(),
VirtualPool.ProvisioningType.Thick, VirtualPool.ProvisioningType.Thin);
if (null != param.getProtocolChanges()) {
if (null != param.getProtocolChanges().getAdd()) {
validateVirtualPoolProtocol(vpool.getType(), param.getProtocolChanges().getAdd().getProtocols());
vpool.addProtocols(param.getProtocolChanges().getAdd().getProtocols());
}
if (null != param.getProtocolChanges().getRemove()) {
validateVirtualPoolProtocol(vpool.getType(), param.getProtocolChanges().getRemove().getProtocols());
vpool.removeProtocols(param.getProtocolChanges().getRemove().getProtocols());
}
// There should be at least one protocol associated with vPool all the time.
if (vpool.getProtocols().isEmpty()) {
throw APIException.badRequests.cannotRemoveAllValues(VPOOL_PROTOCOLS, "vPool");
}
}
if (null != param.getProvisionType()) {
vpool.setSupportedProvisioningType(param.getProvisionType());
}
StringSetMap arrayInfo = vpool.getArrayInfo();
if (null == arrayInfo) {
vpool.setArrayInfo(new StringSetMap());
}
// Validate that the neighborhoods to be assigned to the storage pool
// reference existing neighborhoods in the database and add them to
// the storage pool.
if (null != param.getVarrayChanges()) {
VirtualArrayAssignments addedNH = param.getVarrayChanges().getAdd();
if ((addedNH != null) && (!addedNH.getVarrays().isEmpty())) {
VirtualArrayService.checkVirtualArrayURIs(addedNH.getVarrays(), _dbClient);
vpool.addVirtualArrays(addedNH.getVarrays());
}
// Validate that the neighborhoods to be unassigned from the storage
// pool reference existing neighborhoods in the database and remove
// them from the storage pool.
VirtualArrayAssignments removedNH = param.getVarrayChanges().getRemove();
if ((removedNH != null) && (!removedNH.getVarrays().isEmpty())) {
VirtualArrayService.checkVirtualArrayURIs(removedNH.getVarrays(), _dbClient);
vpool.removeVirtualArrays(removedNH.getVarrays());
}
}
if (null != param.getDescription()) {
vpool.setDescription(param.getDescription());
}
if (null != param.getUseMatchedPools()) {
// if changing from matched pools to assigned pools, verify that pools with resources
// are not removed
if (!param.getUseMatchedPools() && vpool.getUseMatchedPools()) {
checkPoolsWithResources(null, vpool, _dbClient);
}
vpool.setUseMatchedPools(param.getUseMatchedPools());
}
}
/**
* Check for the removal of virtual arrays from the vpool.
* 1) The remaining vpool Virtual arrays' pools should cover the virtual pool's assigned pools
* OR
* 2) Virtual array should not have virtual pool resources
*
* @param varrayChanges
* @param vpool
*/
protected boolean checkVirtualArraysWithVPoolResources(VirtualArrayAssignmentChanges varrayChanges, VirtualPool vpool) {
boolean isModified = false;
if (varrayChanges != null && varrayChanges.getRemove() != null) {
Set<String> removedVarrays = varrayChanges.getRemove().getVarrays();
if (vpool.getVirtualArrays() == null || vpool.getVirtualArrays().isEmpty()) {
return isModified;
}
// find out the varrays which will be associated with the vpool after the remove operation
// and find their storage pools.
Set<String> vpoolVarrays = (StringSet) vpool.getVirtualArrays().clone();
vpoolVarrays.removeAll(removedVarrays);
if (varrayChanges.getAdd() != null && !varrayChanges.getAdd().getVarrays().isEmpty()) {
vpoolVarrays.addAll(varrayChanges.getAdd().getVarrays());
}
Set<String> vpoolPools = getVarrayPools(vpoolVarrays);
Set<String> removedPools = getVarrayPools(removedVarrays);
removedPools.removeAll(vpoolPools);
// If the vpool has assigned pool, then they should be within the remaining varray pools, else error.
Set<String> vpoolAssignedPools = vpool.getAssignedStoragePools();
if (!vpool.getUseMatchedPools() && vpoolAssignedPools != null && !vpoolAssignedPools.isEmpty()) {
for (String poolURI : vpoolAssignedPools) {
if (!vpoolPools.contains(poolURI)) {
throw APIException.badRequests.cannotRemoveVArrayWithPools(removedVarrays);
}
}
}
// Error if the varrays have vpool resources
Set<String> resourceVArrays = getVArraysWithVPoolResources(vpool, removedVarrays, _dbClient);
if (!resourceVArrays.isEmpty()) {
throw APIException.badRequests.cannotRemoveVArrayWithVPoolResources(resourceVArrays);
}
}
return isModified;
}
// Get the vpools of the virtual arrays
private Set<String> getVarrayPools(Set<String> vArrays) {
Set<String> poolURIs = new StringSet();
Iterator<String> vArrayItr = vArrays.iterator();
while (vArrayItr.hasNext()) {
URIQueryResultList vArrayPoolsQueryResult = new URIQueryResultList();
_dbClient.queryByConstraint(AlternateIdConstraint.Factory
.getVirtualArrayStoragePoolsConstraint(vArrayItr.next()),
vArrayPoolsQueryResult);
Iterator<URI> poolIterator = vArrayPoolsQueryResult.iterator();
while (poolIterator.hasNext()) {
poolURIs.add(poolIterator.next().toString());
}
}
return poolURIs;
}
/**
* Check VirtualPoolUpdate has any attributes set.
*
* @param param
* @return
*/
protected boolean checkAttributeValuesChanged(VirtualPoolUpdateParam param, VirtualPool vpool) {
return checkVirtualPoolProtocolsChanged(vpool.getProtocols(), param.getProtocolChanges())
|| VirtualPoolUtil.checkForVirtualPoolAttributeModification(vpool.getSupportedProvisioningType(), param.getProvisionType())
|| VirtualPoolUtil.checkSystemTypeChanged(vpool.getArrayInfo(), param.getSystemType())
|| checkVirtualArraysWithVPoolResources(param.getVarrayChanges(), vpool);
}
/**
* check the if there is any change vpool minPortSpeed attribute.
*
* @param minPortSpeed
* @param paramMinPortSpeed
*/
private boolean checkVirtualPoolMinPortSpeed(Integer minPortSpeed, Integer paramMinPortSpeed) {
boolean isModified = false;
if (null != minPortSpeed) {
if (paramMinPortSpeed == null) {
isModified = false;
} else if (paramMinPortSpeed != minPortSpeed) {
isModified = true;
}
} else {
if (null != paramMinPortSpeed) {
isModified = true;
}
}
return isModified;
}
/**
* Check if there is any change in the vpool protocols attribute.
*
* @param protocols
* @param protocolChanges
* @return true if all passed URIs reference an existing storage pool in the
* DB, false otherwise.
*/
protected static boolean checkVirtualPoolProtocolsChanged(StringSet protocols, ProtocolChanges protocolChanges) {
boolean isModified = false;
// If protocols in DB are not null
if (null != protocols) {
// Check if we are adding any new protocol
if (null != protocolChanges && null != protocolChanges.getAdd()) {
if (Sets.union(protocols, protocolChanges.getAdd().getProtocols()).size() != protocols.size()) {
isModified = true;
}
}
// Check if we are removing any existing protocol
if (null != protocolChanges && null != protocolChanges.getRemove()) {
if (!Sets.intersection(protocols, protocolChanges.getRemove().getProtocols()).isEmpty()) {
isModified = true;
}
}
} else {
// There are no protocols in db but passed in params have some
// values.
if (null != protocolChanges) {
isModified = true;
}
}
return isModified;
}
/**
* This method allows user to assign matching pools to VirtualPool.
*
* @param id : the URN of a ViPR VirtualPool.
* @param param : Pool Update param
* @return : update VirtualPool.
*/
protected VirtualPool updateVirtualPoolWithAssignedStoragePools(URI id, VirtualPoolPoolUpdateParam param) {
ArgValidator.checkUri(id);
VirtualPool vpool = queryResource(id);
ArgValidator.checkEntity(vpool, id, isIdEmbeddedInURL(id));
if (param.getStoragePoolAssignmentChanges() != null) {
// Validate whether all the pools with virtual pool resources are part of the assigned pools
checkPoolsWithResources(param.getStoragePoolAssignmentChanges(), vpool, _dbClient);
StoragePoolAssignments addedAssignedPools = param.getStoragePoolAssignmentChanges().getAdd();
if ((addedAssignedPools != null) && (!addedAssignedPools.getStoragePools().isEmpty())) {
validateAssignedPoolInMatchedPools(addedAssignedPools.getStoragePools(), vpool);
vpool.updateAssignedStoragePools(addedAssignedPools.getStoragePools());
}
// Validate that the storage pools to be unassigned from the storage
// pool reference existing storage pools in the database and remove
// them from the storage pool.
StoragePoolAssignments removedPool = param.getStoragePoolAssignmentChanges().getRemove();
if ((removedPool != null) && (!removedPool.getStoragePools().isEmpty())) {
checkUnassignedPoolURIs(removedPool.getStoragePools(), vpool, _dbClient);
_log.debug("Removing pools {} from the virtual pool {}", removedPool.getStoragePools(), id);
vpool.removeAssignedStoragePools(removedPool.getStoragePools());
}
// adding supported vpools to unmanaged volumes/file systems
if (vpool.getType().equals(VirtualPool.Type.file.name())) {
ImplicitUnManagedObjectsMatcher.matchVirtualPoolsWithUnManagedFileSystems(vpool,
_dbClient);
} else if (vpool.getType().equals(VirtualPool.Type.block.name())) {
Set<URI> allSrdfTargetVPools = SRDFUtils.fetchSRDFTargetVirtualPools(_dbClient);
Set<URI> allRpTargetVpools = RPHelper.fetchRPTargetVirtualPools(_dbClient);
ImplicitUnManagedObjectsMatcher.matchVirtualPoolsWithUnManagedVolumes(vpool, allSrdfTargetVPools, allRpTargetVpools, _dbClient, false);
}
_dbClient.updateAndReindexObject(vpool);
}
return vpool;
}
/**
* Validates passed in unassigned pool uris are in the assigned pools or
* not. If it is in the assigned matched pools then we can allow the user to
* delete else throw an exception.
*
* @param unAssignedPoolURIs The set of storage pools URIs to validate
* @param vpool
* @param dbClient A reference to a DB client.
* @return true if all passed URIs reference an existing storage pool in the
* DB, false otherwise.
*/
public static void checkUnassignedPoolURIs(Set<String> unAssignedPoolURIs, VirtualPool vpool, DbClient dbClient) {
Set<String> badURIs = new HashSet<String>();
StringSet assignedPoolsInDB = vpool.getAssignedStoragePools();
for (Iterator<String> assignedPoolURIsIter = unAssignedPoolURIs.iterator(); assignedPoolURIsIter.hasNext();) {
String poolURI = assignedPoolURIsIter.next().toString();
if (null != assignedPoolsInDB && !assignedPoolsInDB.contains(poolURI)) {
badURIs.add(poolURI);
break;
}
}
if (!badURIs.isEmpty()) {
throw APIException.badRequests.theURIsOfParametersAreNotValid("pools", badURIs);
}
}
/**
* Check whether the pools with vpool resources are part of the assigned pools.
* We should not allow removal of pools with resources.
*
* @param poolAssignmentChanges
* @param vpool
* @param dbClient
*/
public void checkPoolsWithResources(StoragePoolAssignmentChanges poolAssignmentChanges, VirtualPool vpool, DbClient dbClient) {
Set<String> poolsToCheck = new StringSet();
// Find the pools which need to be checked for resources.
if (vpool.getMatchedStoragePools() == null) {
throw APIException.badRequests.invalidParameterNoMatchingPoolsExistToAssignPools(vpool.getId());
}
Set<String> vPoolMatchedPools = (StringSet) vpool.getMatchedStoragePools().clone();
if (vpool.getAssignedStoragePools() != null && !vpool.getAssignedStoragePools().isEmpty()) {
vPoolMatchedPools.removeAll(vpool.getAssignedStoragePools());
}
if (poolAssignmentChanges != null && poolAssignmentChanges.getAdd() != null) {
if (poolAssignmentChanges.getAdd().getStoragePools() != null && !poolAssignmentChanges.getAdd().getStoragePools().isEmpty()) {
vPoolMatchedPools.removeAll(poolAssignmentChanges.getAdd().getStoragePools());
}
}
poolsToCheck.addAll(vPoolMatchedPools);
if (poolAssignmentChanges != null && poolAssignmentChanges.getRemove() != null) {
if (poolAssignmentChanges.getRemove().getStoragePools() != null
&& !poolAssignmentChanges.getRemove().getStoragePools().isEmpty()) {
poolsToCheck.addAll(poolAssignmentChanges.getRemove().getStoragePools());
}
}
Set<String> resourcePools = getPoolsWithVPoolResources(vpool, poolsToCheck, dbClient);
if (!resourcePools.isEmpty()) {
Set<String> poolNames = new StringSet();
for (String poolUri : resourcePools) {
StoragePool pool = dbClient.queryObject(StoragePool.class, URI.create(poolUri));
poolNames.add(pool.getPoolName());
}
throw APIException.badRequests.cannotRemovePoolWithResources(poolNames);
}
}
/**
* Calculate the storage pools which have the vpool resources.
* 1) Get list of vpool resources
* 2) For each of the vpool's matched pool, get the pool resources
* 3) If there is resource in storage pool which is also in the vpool resource list, add to the pool list
*
* @param vpool
* @param dbClient
* @return List of storage pools with vpool resources.
*/
public static Set<String> getPoolsWithVPoolResources(VirtualPool vpool, Set<String> pools, DbClient dbClient) {
Set<String> resourcePools = new StringSet();
_log.debug("Getting the storage pools with resources of virtual pool {}.", vpool.getLabel());
if (null != pools && !pools.isEmpty()) {
Iterator<String> poolItr = pools.iterator();
while (poolItr.hasNext()) {
String matchedPool = poolItr.next();
URI poolURI = URI.create(matchedPool);
URIQueryResultList poolResourcesResultList = new URIQueryResultList();
URIQueryResultList vpoolResourcesResultList = new URIQueryResultList();
if (VirtualPool.Type.block.name().equals(vpool.getType())) {
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getStoragePoolVolumeConstraint(poolURI), poolResourcesResultList);
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getVirtualPoolVolumeConstraint(vpool.getId()), vpoolResourcesResultList);
} else if (VirtualPool.Type.file.name().equals(vpool.getType())) {
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getStoragePoolFileshareConstraint(poolURI), poolResourcesResultList);
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getVirtualPoolFileshareConstraint(vpool.getId()), vpoolResourcesResultList);
} else if (VirtualPool.Type.object.name().equals(vpool.getType())) {
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getStoragePoolBucketConstraint(poolURI), poolResourcesResultList);
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getVirtualPoolBucketConstraint(vpool.getId()), vpoolResourcesResultList);
}
// Create a set of vpoolResourcesResultList
HashSet<URI> vpoolResourceSet = new HashSet<URI>();
for (URI vpoolResource : vpoolResourcesResultList) {
vpoolResourceSet.add(vpoolResource);
}
// Now look up if there are pool resources in the vpool resources set.
for (URI poolResource : poolResourcesResultList) {
if (vpoolResourceSet.contains(poolResource)) {
boolean inactive = false;
if (VirtualPool.Type.block.name().equals(vpool.getType())) {
Volume resource = dbClient.queryObject(Volume.class, poolResource);
inactive = resource.getInactive();
} else if (VirtualPool.Type.file.name().equals(vpool.getType())) {
FileShare resource = dbClient.queryObject(FileShare.class, poolResource);
inactive = resource.getInactive();
}
if (!inactive) {
_log.info("Found vpool resource {} in the storage pool {}", poolResource, matchedPool);
resourcePools.add(matchedPool);
break;
}
}
}
}
}
return resourcePools;
}
/**
* Calculate the virtual arrays which have the vpool resources.
* 1) Get list of vpool resources
* 2) Get the resources for each of the passed in virtual array
* 3) If there is resource in virtual array which is also in the vpool resource list, add to the virtual array list
*
* @param vpool
* @param varrays
* @param dbClient
* @return List of virtual arrays with vpool resources.
*/
public static Set<String> getVArraysWithVPoolResources(VirtualPool vpool, Set<String> varrays, DbClient dbClient) {
Set<String> resourcePools = new StringSet();
_log.debug("Getting the virtual arrays with resources of virtual pool {}.", vpool.getLabel());
if (null != varrays && !varrays.isEmpty()) {
Iterator<String> varrayItr = varrays.iterator();
while (varrayItr.hasNext()) {
String varray = varrayItr.next();
URI varrayURI = URI.create(varray);
URIQueryResultList varrayResourcesResultList = new URIQueryResultList();
URIQueryResultList vpoolResourcesResultList = new URIQueryResultList();
if (VirtualPool.Type.block.name().equals(vpool.getType())) {
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getVirtualArrayVolumeConstraint(varrayURI), varrayResourcesResultList);
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getVirtualPoolVolumeConstraint(vpool.getId()), vpoolResourcesResultList);
} else if (VirtualPool.Type.file.name().equals(vpool.getType())) {
dbClient.queryByConstraint(AlternateIdConstraint.Factory.getVirtualArrayFileSharesConstraint(varrayURI.toString()),
varrayResourcesResultList);
dbClient.queryByConstraint(ContainmentConstraint.Factory
.getVirtualPoolFileshareConstraint(vpool.getId()), vpoolResourcesResultList);
} else if (VirtualPool.Type.object.name().equals(vpool.getType())) {
dbClient.queryByConstraint(ContainmentConstraint.Factory.getVirtualArrayBucketsConstraint(varrayURI),
varrayResourcesResultList);
dbClient.queryByConstraint(ContainmentConstraint.Factory.getVirtualPoolBucketConstraint(vpool.getId()),
vpoolResourcesResultList);
}
// Create a set of vpoolResourcesResultList
HashSet<URI> vpoolResourceSet = new HashSet<URI>();
for (URI vpoolResource : vpoolResourcesResultList) {
vpoolResourceSet.add(vpoolResource);
}
// Now look up if there are varray resources in the vpool resources set.
for (URI varrayResource : varrayResourcesResultList) {
if (vpoolResourceSet.contains(varrayResource)) {
boolean inactive = false;
if (VirtualPool.Type.block.name().equals(vpool.getType())) {
Volume resource = dbClient.queryObject(Volume.class, varrayResource);
inactive = resource.getInactive();
} else if (VirtualPool.Type.file.name().equals(vpool.getType())) {
FileShare resource = dbClient.queryObject(FileShare.class, varrayResource);
inactive = resource.getInactive();
} else if (VirtualPool.Type.object.name().equals(vpool.getType())) {
Bucket resource = dbClient.queryObject(Bucket.class, varrayResource);
inactive = resource.getInactive();
}
if (!inactive) {
_log.info("Found vpool resource {} in the varray {}", varrayResource, varray);
resourcePools.add(varray);
break;
}
}
}
}
}
return resourcePools;
}
/**
* Verify whether the assigned pool is in matched pools or not. If it is in
* matched pool list, then add it to VirtualPool Else throw exception.
*
* @param assignedPoolList
* @param vpool
*/
public void validateAssignedPoolInMatchedPools(Set<String> assignedPoolList, VirtualPool vpool) {
for (Iterator<String> assignedPoolItr = assignedPoolList.iterator(); assignedPoolItr.hasNext();) {
String poolStr = assignedPoolItr.next();
StoragePool pool = _dbClient.queryObject(StoragePool.class, URI.create(poolStr));
ArgValidator.checkFieldNotNull(pool, "pool");
if (vpool.getMatchedStoragePools() == null) {
throw APIException.badRequests.invalidParameterNoMatchingPoolsExistToAssignPools(vpool.getId());
}
if (!vpool.getMatchedStoragePools().contains(poolStr)) {
throw APIException.badRequests.invalidParameterAssignedPoolNotInMatchedPools(poolStr);
}
}
}
protected VirtualPoolList getVirtualPoolList(VirtualPool.Type type, String shortVdcId, String tenantId) {
URIQueryResultList vpoolList = new URIQueryResultList();
VirtualPoolList list = new VirtualPoolList();
TenantOrg tenant_input = null;
// if input tenant is not empty, but user have no access to it, return empty list.
if (!StringUtils.isEmpty(tenantId)) {
tenant_input = getTenantIfHaveAccess(tenantId);
if (tenant_input == null) {
return list;
}
}
StorageOSUser user = getUserFromContext();
List<VirtualPool> vpoolObjects = null;
if (_geoHelper.isLocalVdcId(shortVdcId)) {
_log.debug("retrieving virtual pools via the dbclient");
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getVpoolTypeVpoolConstraint(type), vpoolList);
List<URI> allowed = new ArrayList<URI>();
for (URI vpool : vpoolList) {
allowed.add(vpool);
}
vpoolObjects = _dbClient.queryObject(VirtualPool.class, allowed);
} else {
_log.debug("retrieving virtual pools via the geoclient");
GeoServiceClient geoClient = _geoHelper.getClient(shortVdcId);
try {
// TODO: query by constraint isn't working on the geosvc
// List<URI> resultList = geoClient.queryByConstraint(AlternateIdConstraint.Factory.getVpoolTypeVpoolConstraint(type),
// URIQueryResultList.class);
Iterator<URI> uriIter = geoClient.queryByType(VirtualPool.class, true);
List<URI> resultList = Lists.newArrayList(uriIter);
Iterator<VirtualPool> iter = geoClient.queryObjects(VirtualPool.class, resultList);
vpoolObjects = Lists.newArrayList(); // iter);
while (iter.hasNext()) {
VirtualPool p = iter.next();
if (type.toString().equals(p.getType())) {
vpoolObjects.add(p);
}
}
} catch (Exception ex) {
// TODO: revisit this exception
_log.error("error retrieving virtual pools from vdc " + shortVdcId, ex);
throw APIException.internalServerErrors.genericApisvcError("error retrieving remote pools", ex);
}
}
// full list if role is {Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR} AND no tenant restriction from input
// else only return the list, which input tenant has access.
if (_permissionsHelper.userHasGivenRole(user,
null, Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR)) {
for (VirtualPool virtualPool : vpoolObjects) {
if (tenant_input == null || _permissionsHelper.tenantHasUsageACL(tenant_input.getId(), virtualPool)) {
list.getVirtualPool().add(toVirtualPoolResource(virtualPool));
}
}
} else {
// otherwise, filter by only authorized to use
URI tenant = null;
if (tenant_input == null) {
tenant = URI.create(user.getTenantId());
} else {
tenant = tenant_input.getId();
}
Set<VirtualPool> vpoolSet = new HashSet<VirtualPool>();
for (VirtualPool virtualPool : vpoolObjects) {
if (_permissionsHelper.tenantHasUsageACL(tenant, virtualPool)) {
vpoolSet.add(virtualPool);
}
}
// if no tenant specified in request, also adding vpools which sub-tenants of the user have access to.
if (tenant_input == null) {
List<URI> subtenants = _permissionsHelper.getSubtenantsWithRoles(user);
for (VirtualPool virtualPool : vpoolObjects) {
if (_permissionsHelper.tenantHasUsageACL(subtenants, virtualPool)) {
vpoolSet.add(virtualPool);
}
}
}
for (VirtualPool virtualPool : vpoolSet) {
list.getVirtualPool().add(toVirtualPoolResource(virtualPool));
}
}
return list;
}
protected VirtualPool getVirtualPool(VirtualPool.Type type, URI id) {
ArgValidator.checkUri(id);
VirtualPool vpool = null;
if (_geoHelper.isLocalURI(id)) {
_log.debug("retrieving vpool via dbclient");
vpool = _permissionsHelper.getObjectById(id, VirtualPool.class);
} else {
_log.debug("retrieving vpool via geoclient");
String shortVdcId = VdcUtil.getVdcId(VirtualPool.class, id).toString();
// TODO: do we want to leverage caching like the native lookup
GeoServiceClient geoClient = _geoHelper.getClient(shortVdcId);
try {
vpool = geoClient.queryObject(VirtualPool.class, id);
} catch (Exception ex) {
// TODO: revisit this exception
_log.error("error retrieving virtual pools from vdc " + shortVdcId, ex);
throw APIException.internalServerErrors.genericApisvcError("error retrieving remote pool", ex);
}
}
ArgValidator.checkEntityNotNull(vpool, id, isIdEmbeddedInURL(id));
if (!vpool.getType().equals(type.name())) {
throw APIException.badRequests.invalidParameterNoSuchVirtualPoolOfType(id, type.toString());
}
return vpool;
}
protected Response deleteVirtualPool(VirtualPool.Type type, URI id) {
ArgValidator.checkUri(id);
VirtualPool vpool = _dbClient.queryObject(VirtualPool.class, id);
ArgValidator.checkEntityNotNull(vpool, id, isIdEmbeddedInURL(id));
//for block service cinder if there is QuotaOfCinder entries
//we need to remove before the virtual pool removal
if(vpool.getType().equalsIgnoreCase(Type.block.name())){
List<URI> quotas = _dbClient.queryByType(QuotaOfCinder.class, true);
for (URI quota : quotas) {
QuotaOfCinder quotaObj = _dbClient.queryObject(QuotaOfCinder.class, quota);
if ((quotaObj.getVpool() != null) &&
(quotaObj.getVpool().toString().equalsIgnoreCase(vpool.getId().toString()))) {
_log.debug("Deleting related Vpool for quota object {}.",vpool.getId().toString());
_dbClient.removeObject(quotaObj);
}
}
}
if (vpool.getType().equalsIgnoreCase(Type.file.name())) {
// check if any file policies are assigned to the vpool
if ((vpool.getFilePolicies() != null) && !(vpool.getFilePolicies().isEmpty())) {
throw APIException.badRequests.cannotDeleteVpoolAssignedFilePolicy(vpool.getLabel());
}
// if file policy is assigned to project level then also it has file vpool associated with it.
// In this scenario association is only way.so need to iterate through all the policy to get vpool reference.
List<URI> filePolicyList = _dbClient.queryByType(FilePolicy.class, true);
for (URI filePolicy : filePolicyList) {
FilePolicy policyObj = _dbClient.queryObject(FilePolicy.class, filePolicy);
if ((policyObj.getAssignedResources() != null) && (policyObj.getFilePolicyVpool() != null) &&
(policyObj.getFilePolicyVpool().toString().equalsIgnoreCase(vpool.getId().toString()))) {
throw APIException.badRequests.cannotDeleteVpoolAssignedFilePolicy(vpool.getLabel());
}
}
}
if (!vpool.getType().equals(type.name())) {
throw APIException.badRequests.providedVirtualPoolNotCorrectType();
}
QosSpecification qosSpecification = null;
// Check if Virtual Pool type equals block type
if(vpool.getType().equalsIgnoreCase(Type.block.name())){
// Get the QoS for the VirtualPool, otherwise throw exception
qosSpecification = QosService.getQos(vpool.getId(), _dbClient);
}
// make sure vpool is unused by volumes/fileshares
ArgValidator.checkReference(VirtualPool.class, id, checkForDelete(vpool));
// Check if vpool is set as a continuous copies vpool
checkIfVpoolIsSetAsContinuousCopiesVpool(vpool);
// Additional check for VirtualPool that may be hidden in another VirtualPool via the
// protection settings
URIQueryResultList settingsResultList = new URIQueryResultList();
_dbClient.queryByConstraint(
AlternateIdConstraint.Factory.getVpoolProtectionVarraySettingsConstraint(id.toString()),
settingsResultList);
Iterator<URI> settingsListItr = settingsResultList.iterator();
while (settingsListItr.hasNext()) {
final URI settingId = settingsListItr.next();
VpoolProtectionVarraySettings setting = _dbClient.queryObject(VpoolProtectionVarraySettings.class, settingId);
ArgValidator.checkEntity(setting, settingId, isIdEmbeddedInURL(settingId));
}
if (vpool.getProtectionVarraySettings() != null) {
// Delete all settings associated with the protection settings
deleteVPoolProtectionVArraySettings(vpool);
}
if (vpool.getFileRemoteCopySettings() != null) {
// Delete all settings associated with the protection settings
deleteFileVPoolRemoteCopyProtectionSettings(vpool);
}
// We also check to see if this virtual pool is specified as the HA virtual pool
// for some other virtual pool that specifies VPLEX distributed high availability.
// If this is the case, we disallow the deletion.
List<URI> vpoolURIs = _dbClient.queryByType(VirtualPool.class, true);
Iterator<VirtualPool> vpoolsIter = _dbClient.queryIterativeObjects(VirtualPool.class, vpoolURIs);
while (vpoolsIter.hasNext()) {
VirtualPool activeVPool = vpoolsIter.next();
if (!activeVPool.getId().equals(id)) {
StringMap haMap = activeVPool.getHaVarrayVpoolMap();
if ((haMap != null) && (!haMap.isEmpty()) && (haMap.values().contains(id.toString()))) {
// There is an active vpool that specifies the vpool being
// deleted as the VPLEX HA vpool, so deleting this vpool
// is not allowed.
throw APIException.badRequests.cantDeleteVPlexHaVPool(activeVPool.getLabel());
}
}
}
if(vpool.getType().equalsIgnoreCase(Type.block.name()) && qosSpecification != null){
// Remove Qos associated to this Virtual Pool
_dbClient.removeObject(qosSpecification);
}
_dbClient.markForDeletion(vpool);
recordOperation(OperationTypeEnum.DELETE_VPOOL, VPOOL_DELETED_DESCRIPTION, vpool);
return Response.ok().build();
}
/**
* Deletes all VpoolProtectionVarraySettings objects associated with a VirtualPool.
*
* @param vpool the VirtualPool from which to delete the
* VpoolProtectionVarraySettings.
*/
protected void deleteVPoolProtectionVArraySettings(VirtualPool vpool) {
// Delete all settings associated with the protection settings
if (VirtualPool.vPoolSpecifiesProtection(vpool)) {
for (String protectionVirtualArray : vpool.getProtectionVarraySettings().keySet()) {
deleteVPoolProtectionVArraySettings(vpool.getProtectionVarraySettings().get(protectionVirtualArray));
}
vpool.getProtectionVarraySettings().clear();
}
}
/**
* Deletes all File Replication VpoolRemoteCopyProtectionSettings objects associated with a VirtualPool.
*
* @param vpool the VirtualPool from which to delete the
* VpoolRemoteCopyProtectionSettings.
*/
protected void deleteFileVPoolRemoteCopyProtectionSettings(VirtualPool vpool) {
// Delete all settings associated with the protection settings
if (vpool.getFileRemoteCopySettings() != null && !vpool.getFileRemoteCopySettings().isEmpty()) {
for (String protectionVirtualArray : vpool.getFileRemoteCopySettings().keySet()) {
String strRemoteSettings = vpool.getFileRemoteCopySettings().get(protectionVirtualArray);
URI uriRemoteSettings = URI.create(strRemoteSettings);
VpoolRemoteCopyProtectionSettings remoteSettings = _dbClient.queryObject(VpoolRemoteCopyProtectionSettings.class, uriRemoteSettings);
if (remoteSettings != null && !remoteSettings.getInactive()) {
_dbClient.markForDeletion(remoteSettings);
}
}
vpool.getFileRemoteCopySettings().clear();
}
}
/**
* Deletes a <code>VpoolProtectionVarraySettings</code> object from
* the database.
*
* @param uri the URI representing the <code>VpoolProtectionVarraySettings</code> to delete
*/
protected void deleteVPoolProtectionVArraySettings(String uri) {
if (uri != null && !uri.isEmpty()) {
URI settingURI = URI.create(uri);
ArgValidator.checkUri(settingURI);
VpoolProtectionVarraySettings setting = _dbClient.queryObject(VpoolProtectionVarraySettings.class, settingURI);
if (setting == null) {
throw APIException.badRequests.unableToFindEntity(settingURI);
}
// Mark the VpoolProtectionVarraySettings for deletion
_dbClient.markForDeletion(setting);
}
}
@Override
protected VirtualPool queryResource(URI id) {
VirtualPool vpool = _permissionsHelper.getObjectById(id, VirtualPool.class);
ArgValidator.checkEntityNotNull(vpool, id, isIdEmbeddedInURL(id));
return vpool;
}
protected ACLAssignments getAclsOnVirtualPool(VirtualPool.Type type, URI id) {
VirtualPool vpool = queryResource(id);
ArgValidator.checkEntityNotNull(vpool, id, isIdEmbeddedInURL(id));
if (!vpool.getType().equals(type.name())) {
throw APIException.badRequests.providedVirtualPoolNotCorrectType();
}
ACLAssignments response = new ACLAssignments();
response.setAssignments(_permissionsHelper.convertToACLEntries(vpool.getAcls()));
return response;
}
protected ACLAssignments updateAclsOnVirtualPool(VirtualPool.Type type, URI id, ACLAssignmentChanges changes) {
VirtualPool vpool = queryResource(id);
ArgValidator.checkEntityNotNull(vpool, id, isIdEmbeddedInURL(id));
if (!vpool.getType().equals(type.name())) {
throw APIException.badRequests.providedVirtualPoolNotCorrectType();
}
_permissionsHelper.updateACLs(vpool, changes,
new PermissionsHelper.UsageACLFilter(_permissionsHelper, vpool.getType()));
_dbClient.updateAndReindexObject(vpool);
auditOp(OperationTypeEnum.MODIFY_VPOOL_ACL, true, null, vpool.getId().toString(), vpool.getLabel(), vpool.getType());
return getAclsOnVirtualPool(type, id);
}
/**
* Determines the storage pools the satisfy the VirtualPool with the passed URI.
* This method returns the pools which are valid means the pools will be
* used for placement. Pools will be returned based on the
* useMatchedStoragePools flag. if useMatchedStoragePools = true, returns
* the matched storage pools. else returns assigned storage pools. after
* that, we should remove the invalid matched pools from matched/assigned
* pool if there are any such pools exists. valid Pools =
* (matchedStoragePools/assignedStoragePools - invalidMatchedPools)
*
* @param id the URN of a ViPR VirtualPool.
* @return A reference to a VirtualPoolStoragePool, which contains a list of the URIs
* of the storage pools that satisfy the VirtualPool.
*/
protected StoragePoolList getStoragePoolsForVirtualPool(URI id) {
// Get the vpool with the passed id.
ArgValidator.checkUri(id);
StoragePoolList poolList = new StoragePoolList();
VirtualPool vpool = queryResource(id);
ArgValidator.checkEntity(vpool, id, isIdEmbeddedInURL(id));
List<StoragePool> validPools = VirtualPool.getValidStoragePools(vpool, _dbClient, false);
Iterator<StoragePool> poolIterator = validPools.iterator();
while (poolIterator.hasNext()) {
StoragePool pool = poolIterator.next();
poolList.getPools().add(toNamedRelatedResource(pool, pool.getNativeGuid()));
}
return poolList;
}
/**
* Refresh the matching pools by running implicit pool matcher algorithm and
* find if there are any new matched pools exists in the environment.
* Returns the new matched pools to user.
*
* @param id the URN of a ViPR VirtualPool.
* @return : list of pools.
*/
protected StoragePoolList refreshMatchedPools(VirtualPool.Type type, URI id) {
ArgValidator.checkUri(id);
StoragePoolList poolList = new StoragePoolList();
VirtualPool vpool = queryResource(id);
ArgValidator.checkEntityNotNull(vpool, id, isIdEmbeddedInURL(id));
if (!vpool.getType().equals(type.name())) {
throw APIException.badRequests.providedVirtualPoolNotCorrectType();
}
StringBuffer errorMessage = new StringBuffer();
ImplicitPoolMatcher.matchVirtualPoolWithAllStoragePools(vpool, _dbClient, _coordinator, errorMessage);
_dbClient.updateAndReindexObject(vpool);
StringSet matchedPools = vpool.getMatchedStoragePools();
if (null != matchedPools && !matchedPools.isEmpty()) {
Iterator<String> vpoolItr = matchedPools.iterator();
while (vpoolItr.hasNext()) {
URI poolURI = URI.create(vpoolItr.next());
StoragePool pool = _dbClient.queryObject(StoragePool.class, poolURI);
if (pool == null) {
continue;
}
poolList.getPools().add(toNamedRelatedResource(pool));
}
}
return poolList;
}
public QuotaInfo updateQuota(VirtualPool vpool,
QuotaUpdateParam param) throws DatabaseException {
// don't allow quota updates on inactive vpools
ArgValidator.checkEntity(vpool, vpool.getId(), isIdEmbeddedInURL(vpool.getId()));
vpool.setQuotaEnabled(param.getEnable());
if (param.getEnable()) {
long quota_gb = (param.getQuotaInGb() != null) ? param.getQuotaInGb() : vpool.getQuota();
ArgValidator.checkFieldMinimum(quota_gb, 0, "quota_gb", "GB");
vpool.setQuota(quota_gb);
}
_dbClient.persistObject(vpool);
return getQuota(vpool);
}
protected QuotaInfo getQuota(VirtualPool vpool) {
QuotaInfo quotaInfo = new QuotaInfo();
double capacity = CapacityUtils.getVirtualPoolCapacity(_dbClient, vpool.getId(), VirtualPool.Type.lookup(vpool.getType()));
quotaInfo.setQuotaInGb(vpool.getQuota());
quotaInfo.setEnabled(vpool.getQuotaEnabled());
quotaInfo.setCurrentCapacityInGb((long) Math.ceil(capacity / CapacityUtils.GB));
quotaInfo.setLimitedResource(DbObjectMapper.toNamedRelatedResource(vpool));
return quotaInfo;
}
/**
* Returns capacity metrics for a given pair of VirtualPool and Neighborhood. The
* method returns set of metrics for capacity available for storage
* provisioning: - usable_gb : total storage capacity - free_gb : free
* storage capacity - used_gb : used storage capacity - subscribed_gb :
* subscribed storage capacity (may be larger than usable capacity) -
* percent_used : percent of usable capacity which is used -
* percent_subscribed : percent of usable capacity which is subscribed (may
* be more than 100) Subscribed and percent subscribed is returned only for
* block vpool.
*
* @param vpool
* @param vArrayId
* @return CapacityResponse instance
*/
protected CapacityResponse getCapacityForVirtualPoolAndVirtualArray(VirtualPool vpool, URI vArrayId) {
VirtualArray varray = _permissionsHelper.getObjectById(vArrayId, VirtualArray.class);
ArgValidator.checkEntity(varray, vArrayId, isIdEmbeddedInURL(vArrayId));
// Check permissions: check that varray is accessible to user's
// tenant
final StorageOSUser user = getUserFromContext();
final URI tenant = URI.create(user.getTenantId());
if (!(_permissionsHelper.userHasGivenRole(user, null, Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR) || _permissionsHelper
.tenantHasUsageACL(tenant, varray))) {
throw APIException.forbidden.insufficientPermissionsForUser(user.getName());
}
return CapacityUtils.getCapacityForVirtualPoolAndVirtualArray(vpool, vArrayId, _dbClient, _coordinator);
}
/**
* Record Bourne Event for the completed operations
*
* @param type
* @param type
* @param description
* @param vpool
*/
private void recordVirtualPoolEvent(String type, String description, URI vpool) {
RecordableBourneEvent event = new RecordableBourneEvent(
/* String */type,
/* tenant id */null,
/* user id ?? */URI.create("ViPR-User"),
/* project ID */null,
/* VirtualPool */vpool,
/* service */EVENT_SERVICE_TYPE,
/* resource id */vpool,
/* description */description,
/* timestamp */System.currentTimeMillis(),
/* extensions */"",
/* native guid */null,
/* record type */RecordType.Event.name(),
/* Event Source */EVENT_SERVICE_SOURCE,
/* Operational Status codes */"",
/* Operational Status Descriptions */"");
try {
_evtMgr.recordEvents(event);
} catch (Exception ex) {
_log.error("Failed to record event. Event description: {}. Error: {}.", description, ex);
}
}
public void setMatcherFramework(AttributeMatcherFramework matcherFramework) {
_matcherFramework = matcherFramework;
}
public void recordOperation(OperationTypeEnum opType, String evDesc, Object... extParam) {
String evType;
evType = opType.getEvType(true);
_log.info("opType: {} detail: {}", opType.toString(), evType + ':' + evDesc);
VirtualPool vpool = (VirtualPool) extParam[0];
recordVirtualPoolEvent(evType, evDesc, vpool.getId());
StringBuilder protocols = new StringBuilder();
if (vpool.getProtocols() != null) {
for (String proto : vpool.getProtocols()) {
protocols.append(" ");
protocols.append(proto);
}
}
StringBuilder neighborhoods = new StringBuilder();
if (vpool.getVirtualArrays() != null) {
for (String neighborhood : vpool.getVirtualArrays()) {
neighborhoods.append(" ");
neighborhoods.append(neighborhood);
}
}
switch (opType) {
case CREATE_VPOOL:
auditOp(opType, true, null, vpool.getId().toString(), vpool.getLabel(), vpool.getType(), protocols.toString(),
neighborhoods.toString(), vpool.getSupportedProvisioningType(),
vpool.getAutoTierPolicyName(), vpool.getDriveType(), vpool.getHighAvailability());
break;
case UPDATE_VPOOL:
auditOp(opType, true, null, vpool.getId().toString(), vpool.getLabel(), vpool.getType(), protocols.toString(),
neighborhoods.toString(), vpool.getSupportedProvisioningType(), vpool.getAutoTierPolicyName(),
vpool.getDriveType());
break;
case DELETE_VPOOL:
auditOp(opType, true, null, vpool.getId().toString(), vpool.getLabel(), vpool.getType());
break;
default:
_log.error("unrecognized vpool operation type");
}
}
@SuppressWarnings("unchecked")
@Override
public Class<VirtualPool> getResourceClass() {
return VirtualPool.class;
}
@Override
protected BulkIdParam queryBulkIds() {
BulkIdParam ret = new BulkIdParam();
URIQueryResultList vpoolList = new URIQueryResultList();
_dbClient.queryByConstraint(
AlternateIdConstraint.Factory.getVpoolTypeVpoolConstraint(getVirtualPoolType()), vpoolList);
ret.setIds(new ArrayList<URI>());
for (URI vpool : vpoolList) {
ret.getIds().add(vpool);
}
return ret;
}
protected abstract Type getVirtualPoolType();
/**
* VirtualPool is not a zone level resource
*/
@Override
protected boolean isZoneLevelResource() {
return true;
}
@Override
protected ResourceTypeEnum getResourceType() {
return ResourceTypeEnum.VPOOL;
}
public static class VirtualPoolResRepFilter<E extends RelatedResourceRep> extends ResRepFilter<E> {
public VirtualPoolResRepFilter(StorageOSUser user, PermissionsHelper permissionsHelper) {
super(user, permissionsHelper);
}
@Override
public boolean isAccessible(E resrep) {
URI id = resrep.getId();
VirtualPool resource = _permissionsHelper.getObjectById(id, VirtualPool.class);
if (resource == null) {
return false;
}
return isVirtualPoolAccessible(resource);
}
}
/**
* Get object specific permissions filter
*/
@Override
public ResRepFilter<? extends RelatedResourceRep> getPermissionFilter(StorageOSUser user,
PermissionsHelper permissionsHelper) {
return new VirtualPoolResRepFilter<SearchResultResourceRep>(user, permissionsHelper);
}
/**
* Gives systemType of the given vPool
*
* @param virtualPool
* @return {@link String} vpool's systemType
*/
public static String getSystemType(VirtualPool virtualPool) {
String systemType = null;
if (virtualPool != null && virtualPool.getArrayInfo() != null && virtualPool.getArrayInfo().containsKey(VirtualPoolCapabilityValuesWrapper.SYSTEM_TYPE)) {
for (String sysType : virtualPool.getArrayInfo().get(VirtualPoolCapabilityValuesWrapper.SYSTEM_TYPE)) {
systemType = sysType;
break;
}
}
return systemType;
}
@Override
protected SearchedResRepList getTagSearchResults(String tag, URI tenant) {
SearchedResRepList list = super.getTagSearchResults(tag, tenant);
return filterResultsList(getUserFromContext(), list);
}
@Override
protected SearchedResRepList getNamedSearchResults(String name, URI projectId) {
SearchedResRepList list = super.getNamedSearchResults(name, projectId);
return filterResultsList(getUserFromContext(), list);
}
/**
* Filters the SearchedResRepList by VirtualPoolType (e.g., block or file)
*
* @param user the current user
* @param list a list of resource matching the search
* @return a list filtered by virtual pool type
*/
protected SearchedResRepList filterResultsList(StorageOSUser user, SearchedResRepList list) {
SearchedResRepList filteredResRepList = new SearchedResRepList();
Iterator<SearchResultResourceRep> _queryResultIterator = list.iterator();
ResRepFilter<SearchResultResourceRep> resrepFilter =
new VirtualPoolTypeFilter<SearchResultResourceRep>(user,
_permissionsHelper, this.getVirtualPoolType());
filteredResRepList.setResult(
new FilterIterator<SearchResultResourceRep>(_queryResultIterator, resrepFilter));
return filteredResRepList;
}
/**
* Filters the SearchedResRepList by VirtualPoolType (e.g., block or file)
*/
public static class VirtualPoolTypeFilter<E extends RelatedResourceRep> extends ResRepFilter<E> {
private Type poolType;
public VirtualPoolTypeFilter(StorageOSUser user, PermissionsHelper permissionsHelper, Type poolType) {
super(user, permissionsHelper);
this.poolType = poolType;
}
@Override
public boolean isAccessible(E resrep) {
URI id = resrep.getId();
VirtualPool resource = _permissionsHelper.getObjectById(id, VirtualPool.class);
if (resource.getType().equals(poolType.name())) {
return true;
}
return false;
}
}
/**
* This method checks if the passed vpool is set as the continuous copies vpool for any of the vpool.
* If yes it throws an exception with virtual pool names where it is used as continuous copies vpool.
*
* @param vpool The reference to Virtual Pool
*/
public void checkIfVpoolIsSetAsContinuousCopiesVpool(VirtualPool vpool) {
String virtualPoolNames = VirtualPool.isContinuousCopiesVpool(vpool, _dbClient);
if (virtualPoolNames.length() != 0) {
throw APIException.badRequests.virtualPoolIsSetAsContinuousCopiesVpool(vpool.getLabel(), virtualPoolNames);
}
}
}