/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package models.virtualpool; import static com.emc.vipr.client.core.util.ResourceUtils.defaultList; import static com.emc.vipr.client.core.util.ResourceUtils.uris; import java.net.URI; import java.util.List; import java.util.Map; import java.util.Set; import models.DriveTypes; import models.PoolAssignmentTypes; import models.StorageSystemTypes; import org.apache.commons.lang.StringUtils; import play.data.validation.Required; import play.data.validation.Validation; import util.TenantUtils; import util.VirtualArrayUtils; import util.VirtualPoolUtils; import util.builders.ACLUpdateBuilder; import util.builders.VirtualPoolBuilder; import util.builders.VirtualPoolUpdateBuilder; import com.emc.storageos.model.auth.ACLEntry; import com.emc.storageos.model.quota.QuotaInfo; import com.emc.storageos.model.quota.QuotaUpdateParam; import com.emc.storageos.model.vpool.VirtualPoolCommonRestRep; import com.emc.vipr.client.core.ACLResources; import com.emc.vipr.client.core.QuotaResources; import com.emc.vipr.client.core.util.ResourceUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; /** * Base form for file/block virtual pools. */ public abstract class VirtualPoolCommonForm<T extends VirtualPoolCommonRestRep> extends BaseVirtualPoolForm<T> { // Indicates if there are resources associated to the pool (which affects what can be changed) public Integer numResources; public String poolType; @Required public String provisioningType; @Required public List<String> virtualArrays; @Required public Set<String> protocols; @Required public String systemType; public boolean enableQuota; public Long quota; public String poolAssignment; public List<String> storagePools; public boolean enableTenants; public List<String> tenants; public boolean isLocked() { return (numResources != null) && (numResources > 0); } public boolean isManualPoolAssignment() { return PoolAssignmentTypes.MANUAL.equals(poolAssignment); } @Override public void validate(String formName) { super.validate(formName); if (enableQuota) { Validation.min(formName + ".quota", quota, 1); } if (isManualPoolAssignment()) { Validation.required(String.format("%s.storagePools", formName), storagePools); } if (enableTenants) { Validation.required(String.format("%s.tenants", formName), tenants); } } /** * Applies the common fields to a virtual pool builder. This is used when creating a new pool or when retrieving * matching pools. * * @param builder * the virtual pool builder. */ protected void applyCommon(VirtualPoolBuilder builder) { builder.setName(name); builder.setDescription(description); builder.setVirtualArrays(virtualArrays); builder.setProvisioningType(provisioningType); builder.setPoolAssignmentType(poolAssignment); builder.setSystemType(systemType); builder.setProtocols(protocols); } /** * Applies the common fields on a virtual pool update builder. * * @param builder * the virtual pool builder. */ protected void applyCommon(VirtualPoolUpdateBuilder builder) { builder.setName(name); builder.setDescription(description); builder.setPoolAssignmentType(poolAssignment); builder.setVirtualArrays(defaultList(virtualArrays)); // Cannot update certain fields if locked if (!isLocked()) { builder.setProvisioningType(provisioningType); builder.setSystemType(systemType); builder.setProtocols(defaultSet(protocols)); } } /** * Loads the common fields from a virtual pool. * * @param virtualPool * the virtual pool. */ protected void loadCommon(VirtualPoolCommonRestRep virtualPool) { id = ResourceUtils.stringId(virtualPool); name = virtualPool.getName(); description = virtualPool.getDescription(); poolType = virtualPool.getType(); numResources = virtualPool.getNumResources(); provisioningType = virtualPool.getProvisioningType(); virtualArrays = ResourceUtils.stringRefIds(virtualPool.getVirtualArrays()); protocols = defaultSet(virtualPool.getProtocols()); systemType = virtualPool.getSystemType(); poolAssignment = isTrue(virtualPool.getUseMatchedPools()) ? PoolAssignmentTypes.AUTOMATIC : PoolAssignmentTypes.MANUAL; storagePools = ResourceUtils.stringRefIds(virtualPool.getAssignedStoragePools()); } /** * Loads the quota information from the provide QuotaResources (either the block or file virtual pool resources). * * @param resources * the resources from which to load the quota. */ protected void loadQuota(QuotaResources resources) { URI virtualPoolId = ResourceUtils.uri(id); if (virtualPoolId != null) { QuotaInfo quotaInfo = resources.getQuota(virtualPoolId); if (quotaInfo != null) { enableQuota = quotaInfo.getEnabled(); quota = quotaInfo.getQuotaInGb(); } } } /** * Saves the quota value using the provided QuotaResources (either the block or file virtual pool resources). * * @param resources * the resources on which to save the quota. */ protected void saveQuota(QuotaResources resources) { URI virtualPoolId = ResourceUtils.uri(id); if (virtualPoolId != null) { QuotaUpdateParam update = new QuotaUpdateParam(isTrue(enableQuota), quota); resources.updateQuota(virtualPoolId, update); } } /** * Loads the tenant ACL information from the provided ACLResources. * * @param resources * the resources from which to load the ACLs. */ protected void loadTenantACLs(ACLResources resources) { tenants = Lists.newArrayList(); URI virtualPoolId = ResourceUtils.uri(id); if (virtualPoolId != null) { for (ACLEntry acl : resources.getACLs(virtualPoolId)) { if (StringUtils.isNotBlank(acl.getTenant())) { tenants.add(acl.getTenant()); } } } enableTenants = !tenants.isEmpty(); } /** * Saves the tenant ACL information using the provided ACLResources. * * @param resources * the resources on which to save the tenant ACLs. */ protected void saveTenantACLs(ACLResources resources) { // Only allow a user than can read all tenants and update ACLs do this if (TenantUtils.canReadAllTenants() && VirtualPoolUtils.canUpdateACLs()) { URI virtualPoolId = ResourceUtils.uri(id); if (virtualPoolId != null) { Set<String> tenantIds = Sets.newHashSet(); if (isTrue(enableTenants) && (tenants != null)) { tenantIds.addAll(tenants); } ACLUpdateBuilder builder = new ACLUpdateBuilder(resources.getACLs(virtualPoolId)); builder.setTenants(tenantIds); resources.updateACLs(virtualPoolId, builder.getACLUpdate()); } } } /** * Saves the storage pools associated with the given pool. * * @param pool * the virtual pool. */ protected T saveStoragePools(T pool) { Set<String> oldValues = Sets.newHashSet(ResourceUtils.stringRefIds(pool.getAssignedStoragePools())); Set<String> newValues = Sets.newHashSet(); if (isFalse(pool.getUseMatchedPools())) { if (storagePools != null) { newValues.addAll(storagePools); } } Set<String> add = Sets.difference(newValues, oldValues); Set<String> remove = Sets.difference(oldValues, newValues); // Don't bother updating if there is nothing to add/remove if (!add.isEmpty() || !remove.isEmpty()) { pool = updateStoragePools(add, remove); } return pool; } /** * Updates the storage pools assigned to this virtual pool. * * @param add * the pools to add. * @param remove * the pools to remove. * @return the updated virtual pool. */ protected abstract T updateStoragePools(Set<String> add, Set<String> remove); /** * Gets the virtual pool attributes based on the selected virtual arrays. * * @return the map of virtual pool attributes. */ public Map<String, Set<String>> getVirtualPoolAttributes() { Map<String, Set<String>> allAttributes = VirtualArrayUtils.getAvailableAttributes(uris(virtualArrays)); Map<String, Set<String>> attributes = Maps.newHashMap(); attributes.put("driveType", Sets.newHashSet(allAttributes.get(VirtualArrayUtils.ATTRIBUTE_DRIVE_TYPES))); attributes.get("driveType").add(DriveTypes.NONE); attributes.put("protocols", Sets.newHashSet(allAttributes.get(VirtualArrayUtils.ATTRIBUTE_PROTOCOLS))); attributes.put("raidLevels", Sets.newHashSet(allAttributes.get(VirtualArrayUtils.ATTRIBUTE_RAID_LEVELS))); attributes.put("systemType", Sets.newHashSet(allAttributes.get(VirtualArrayUtils.ATTRIBUTE_SYSTEM_TYPES))); attributes.get("systemType").add(StorageSystemTypes.NONE); return attributes; } protected static boolean isTrue(Boolean value) { return Boolean.TRUE.equals(value); } protected static boolean isFalse(Boolean value) { return Boolean.FALSE.equals(value); } protected static <T> Set<T> defaultSet(Set<T> set) { if (set == null) { set = Sets.newHashSet(); } return set; } }