Search in sources :

Example 51 with ValidationResult

use of org.candlepin.policy.ValidationResult in project candlepin by candlepin.

the class EntitlementRules method filterPools.

@Override
@SuppressWarnings("checkstyle:indentation")
public List<Pool> filterPools(Consumer consumer, List<Pool> pools, boolean showAll) {
    JsonJsContext args = new JsonJsContext(objectMapper);
    Map<String, ValidationResult> resultMap = new HashMap<>();
    ConsumerType ctype = this.consumerTypeCurator.getConsumerType(consumer);
    if (!ctype.isType(ConsumerTypeEnum.SHARE)) {
        Stream<PoolDTO> poolStream = pools == null ? Stream.empty() : pools.stream().map(this.translator.getStreamMapper(Pool.class, PoolDTO.class));
        Stream<EntitlementDTO> entStream = consumer.getEntitlements() == null ? Stream.empty() : consumer.getEntitlements().stream().map(this.translator.getStreamMapper(Entitlement.class, EntitlementDTO.class));
        args.put("consumer", this.translator.translate(consumer, ConsumerDTO.class));
        args.put("hostConsumer", this.translator.translate(getHost(consumer, pools), ConsumerDTO.class));
        args.put("consumerEntitlements", entStream.collect(Collectors.toSet()));
        args.put("standalone", config.getBoolean(ConfigProperties.STANDALONE));
        args.put("pools", poolStream.collect(Collectors.toSet()));
        args.put("caller", CallerType.LIST_POOLS.getLabel());
        args.put("log", log, false);
        String json = jsRules.runJsFunction(String.class, "validate_pools_list", args);
        TypeReference<Map<String, ValidationResult>> typeref = new TypeReference<Map<String, ValidationResult>>() {
        };
        try {
            resultMap = objectMapper.toObject(json, typeref);
        } catch (Exception e) {
            throw new RuleExecutionException(e);
        }
    }
    List<Pool> filteredPools = new LinkedList<>();
    for (Pool pool : pools) {
        ValidationResult result;
        if (ctype.isType(ConsumerTypeEnum.SHARE)) {
            result = new ValidationResult();
            resultMap.put(pool.getId(), result);
            validatePoolSharingEligibility(result, pool);
        } else {
            result = resultMap.get(pool.getId());
        }
        finishValidation(result, pool, 1);
        if (result.isSuccessful() && (!result.hasWarnings() || showAll)) {
            filteredPools.add(pool);
        } else if (log.isDebugEnabled()) {
            log.debug("Omitting pool due to failed rules: " + pool.getId());
            if (result.hasErrors()) {
                log.debug("\tErrors: " + result.getErrors());
            }
            if (result.hasWarnings()) {
                log.debug("\tWarnings: " + result.getWarnings());
            }
        }
    }
    return filteredPools;
}
Also used : HashMap(java.util.HashMap) PoolDTO(org.candlepin.dto.rules.v1.PoolDTO) ValidationResult(org.candlepin.policy.ValidationResult) RuleExecutionException(org.candlepin.policy.js.RuleExecutionException) LinkedList(java.util.LinkedList) EntitlementDTO(org.candlepin.dto.rules.v1.EntitlementDTO) ConsumerDTO(org.candlepin.dto.rules.v1.ConsumerDTO) JsonJsContext(org.candlepin.policy.js.JsonJsContext) Pool(org.candlepin.model.Pool) TypeReference(com.fasterxml.jackson.core.type.TypeReference) RuleExecutionException(org.candlepin.policy.js.RuleExecutionException) ConsumerType(org.candlepin.model.ConsumerType) Map(java.util.Map) HashMap(java.util.HashMap)

Example 52 with ValidationResult

use of org.candlepin.policy.ValidationResult in project candlepin by candlepin.

the class CandlepinPoolManager method getBestPools.

@Override
public List<PoolQuantity> getBestPools(Consumer consumer, String[] productIds, Date entitleDate, String ownerId, String serviceLevelOverride, Collection<String> fromPools) throws EntitlementRefusedException {
    Map<String, ValidationResult> failedResults = new HashMap<>();
    Date activePoolDate = entitleDate;
    if (entitleDate == null) {
        activePoolDate = new Date();
    }
    PoolFilterBuilder poolFilter = new PoolFilterBuilder();
    poolFilter.addIdFilters(fromPools);
    List<Pool> allOwnerPools = this.listAvailableEntitlementPools(consumer, null, ownerId, null, null, activePoolDate, false, poolFilter, null, false, false, null).getPageData();
    List<Pool> filteredPools = new LinkedList<>();
    // We have to check compliance status here so we can replace an empty
    // array of product IDs with the array the consumer actually needs. (i.e. during
    // a healing request)
    ComplianceStatus compliance = complianceRules.getStatus(consumer, entitleDate, false);
    if (productIds == null || productIds.length == 0) {
        log.debug("No products specified for bind, checking compliance to see what is needed.");
        Set<String> tmpSet = new HashSet<>();
        tmpSet.addAll(compliance.getNonCompliantProducts());
        tmpSet.addAll(compliance.getPartiallyCompliantProducts().keySet());
        productIds = tmpSet.toArray(new String[] {});
    }
    if (log.isDebugEnabled()) {
        log.debug("Attempting for products on date: {}", entitleDate);
        for (String productId : productIds) {
            log.debug("  {}", productId);
        }
    }
    // Bulk fetch our provided product IDs so we're not hitting the DB several times
    // for this lookup.
    Map<String, Set<String>> providedProductIds = this.poolCurator.getProvidedProductIds(allOwnerPools);
    for (Pool pool : allOwnerPools) {
        boolean providesProduct = false;
        // We want to complete partial stacks if possible, even if they do not provide any products
        Product poolProduct = pool.getProduct();
        String stackingId = poolProduct.getAttributeValue(Product.Attributes.STACKING_ID);
        if (stackingId != null && compliance.getPartialStacks().containsKey(stackingId)) {
            providesProduct = true;
        } else {
            Set<String> poolProvidedProductIds = providedProductIds.get(pool.getId());
            String poolProductId = pool.getProduct() != null ? pool.getProduct().getId() : null;
            if (poolProductId != null) {
                // Add the base product to our list of "provided" products
                if (poolProvidedProductIds != null) {
                    poolProvidedProductIds.add(poolProductId);
                } else {
                    poolProvidedProductIds = Collections.singleton(poolProductId);
                }
            }
            if (poolProvidedProductIds != null) {
                for (String productId : productIds) {
                    if (poolProvidedProductIds.contains(productId)) {
                        providesProduct = true;
                        break;
                    }
                }
            }
        }
        if (providesProduct) {
            ValidationResult result = enforcer.preEntitlement(consumer, pool, 1, CallerType.BEST_POOLS);
            if (result.hasErrors() || result.hasWarnings()) {
                failedResults.put(pool.getId(), result);
                log.debug("Pool filtered from candidates due to rules failure: {}", pool.getId());
            } else {
                filteredPools.add(pool);
            }
        }
    }
    // Only throw refused exception if we actually hit the rules:
    if (filteredPools.size() == 0 && !failedResults.isEmpty()) {
        throw new EntitlementRefusedException(failedResults);
    }
    List<PoolQuantity> enforced = autobindRules.selectBestPools(consumer, productIds, filteredPools, compliance, serviceLevelOverride, poolCurator.retrieveServiceLevelsForOwner(ownerId, true), false);
    // Sort the resulting pools to avoid deadlocks
    Collections.sort(enforced);
    return enforced;
}
Also used : PoolQuantity(org.candlepin.model.PoolQuantity) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) ComplianceStatus(org.candlepin.policy.js.compliance.ComplianceStatus) EntitlementRefusedException(org.candlepin.policy.EntitlementRefusedException) Product(org.candlepin.model.Product) ValidationResult(org.candlepin.policy.ValidationResult) Date(java.util.Date) LinkedList(java.util.LinkedList) PoolFilterBuilder(org.candlepin.model.PoolFilterBuilder) Pool(org.candlepin.model.Pool) HashSet(java.util.HashSet)

Example 53 with ValidationResult

use of org.candlepin.policy.ValidationResult in project candlepin by candlepin.

the class CandlepinPoolManager method adjustEntitlementQuantity.

@Override
@Transactional
public /*
     * NOTE: please refer to the comment on create entitlements with respect to locking.
     */
Entitlement adjustEntitlementQuantity(Consumer consumer, Entitlement entitlement, Integer quantity) throws EntitlementRefusedException {
    int change = quantity - entitlement.getQuantity();
    if (change == 0) {
        return entitlement;
    }
    // Because there are several paths to this one place where entitlements
    // are updated, we cannot be positive the caller obtained a lock on the
    // pool when it was read. As such we're going to reload it with a lock
    // before starting this process.
    log.debug("Updating entitlement, Locking pool: {}", entitlement.getPool().getId());
    Pool pool = poolCurator.lockAndLoad(entitlement.getPool());
    if (pool == null) {
        throw new RuntimeException("Unable to lock pool for entitlement: " + entitlement);
    }
    log.debug("Locked pool: {} consumed: {}", pool, pool.getConsumed());
    ValidationResult result = enforcer.update(consumer, entitlement, change);
    if (!result.isSuccessful()) {
        log.warn("Entitlement not updated: {} for pool: {}", result.getErrors().toString(), pool.getId());
        Map<String, ValidationResult> errorMap = new HashMap<>();
        errorMap.put(pool.getId(), result);
        throw new EntitlementRefusedException(errorMap);
    }
    /*
         * Grab an exclusive lock on the consumer to prevent deadlock.
         */
    consumer = consumerCurator.lockAndLoad(consumer);
    ConsumerType ctype = this.consumerTypeCurator.getConsumerType(consumer);
    // Persist the entitlement after it has been updated.
    log.info("Processing entitlement and persisting.");
    entitlement.setQuantity(entitlement.getQuantity() + change);
    entitlementCurator.merge(entitlement);
    pool.setConsumed(pool.getConsumed() + change);
    if (ctype != null && ctype.isManifest()) {
        pool.setExported(pool.getExported() + change);
    }
    poolCurator.merge(pool);
    consumer.setEntitlementCount(consumer.getEntitlementCount() + change);
    Map<String, Entitlement> entMap = new HashMap<>();
    entMap.put(pool.getId(), entitlement);
    Map<String, PoolQuantity> poolQuantityMap = new HashMap<>();
    poolQuantityMap.put(pool.getId(), new PoolQuantity(pool, change));
    Owner owner = ownerCurator.find(consumer.getOwnerId());
    // the only thing we do here is decrement bonus pool quantity
    enforcer.postEntitlement(this, consumer, owner, entMap, new ArrayList<>(), true, poolQuantityMap);
    // we might have changed the bonus pool quantities, revoke ents if needed.
    checkBonusPoolQuantities(consumer.getOwnerId(), entMap);
    // if shared ents, update shared pool quantity
    if (ctype != null && ctype.isType(ConsumerTypeEnum.SHARE)) {
        pool.setShared(pool.getShared() + change);
        List<Pool> sharedPools = poolCurator.listBySourceEntitlement(entitlement).list();
        for (Pool p : sharedPools) {
            setPoolQuantity(p, entitlement.getQuantity().longValue());
        }
    } else {
        this.entitlementCurator.markEntitlementsDirty(Arrays.asList(entitlement.getId()));
    }
    /*
         * If the consumer is not a distributor or share, check consumer's new compliance
         * status and save. the getStatus call does that internally.
         * all consumer's entitlement count are updated though, so we need to update irrespective
         * of the consumer type.
         */
    complianceRules.getStatus(consumer, null, false, false);
    consumerCurator.update(consumer);
    poolCurator.flush();
    return entitlement;
}
Also used : PoolQuantity(org.candlepin.model.PoolQuantity) Owner(org.candlepin.model.Owner) HashMap(java.util.HashMap) EntitlementRefusedException(org.candlepin.policy.EntitlementRefusedException) ValidationResult(org.candlepin.policy.ValidationResult) Pool(org.candlepin.model.Pool) ConsumerType(org.candlepin.model.ConsumerType) Entitlement(org.candlepin.model.Entitlement) Transactional(com.google.inject.persist.Transactional)

Example 54 with ValidationResult

use of org.candlepin.policy.ValidationResult in project candlepin by candlepin.

the class PreEntitlementRulesCheckOp method checkResults.

private EntitlementRefusedException checkResults() {
    boolean success = true;
    for (Map.Entry<String, ValidationResult> entry : results.entrySet()) {
        ValidationResult result = entry.getValue();
        if (!result.isSuccessful()) {
            log.warn("Entitlement not granted: {} for pool: {}", result.getErrors().toString(), entry.getKey());
            success = false;
        }
    }
    if (!success) {
        return new EntitlementRefusedException(results);
    }
    return null;
}
Also used : EntitlementRefusedException(org.candlepin.policy.EntitlementRefusedException) ValidationResult(org.candlepin.policy.ValidationResult) Map(java.util.Map)

Example 55 with ValidationResult

use of org.candlepin.policy.ValidationResult in project candlepin by candlepin.

the class ManifestEntitlementRulesTest method preEntitlementShouldNotAllowListOfDerivedPools.

@Test
public void preEntitlementShouldNotAllowListOfDerivedPools() {
    Consumer c = this.createMockConsumer(true);
    Product prod = TestUtil.createProduct();
    Pool p = TestUtil.createPool(prod);
    p.setAttribute(Product.Attributes.VIRT_ONLY, "true");
    p.setAttribute(Pool.Attributes.DERIVED_POOL, "true");
    p.setId("poolId");
    ValidationResult results = enforcer.preEntitlement(c, p, 1, CallerType.LIST_POOLS);
    assertNotNull(results);
    assertEquals(1, results.getErrors().size());
    ValidationError error = results.getErrors().get(0);
    assertEquals("pool.not.available.to.manifest.consumers", error.getResourceKey());
}
Also used : Consumer(org.candlepin.model.Consumer) Product(org.candlepin.model.Product) Pool(org.candlepin.model.Pool) ValidationError(org.candlepin.policy.ValidationError) ValidationResult(org.candlepin.policy.ValidationResult) Test(org.junit.Test)

Aggregations

ValidationResult (org.candlepin.policy.ValidationResult)116 Pool (org.candlepin.model.Pool)111 Test (org.junit.Test)105 Product (org.candlepin.model.Product)38 Consumer (org.candlepin.model.Consumer)36 ConsumerType (org.candlepin.model.ConsumerType)22 HashSet (java.util.HashSet)19 Entitlement (org.candlepin.model.Entitlement)15 ActivationKey (org.candlepin.model.activationkeys.ActivationKey)14 ValidationError (org.candlepin.policy.ValidationError)13 ArrayList (java.util.ArrayList)11 LinkedList (java.util.LinkedList)11 ConsumerCapability (org.candlepin.model.ConsumerCapability)11 Date (java.util.Date)10 HashMap (java.util.HashMap)9 Matchers.anyString (org.mockito.Matchers.anyString)9 List (java.util.List)8 EntitlementRefusedException (org.candlepin.policy.EntitlementRefusedException)8 PreUnbindHelper (org.candlepin.policy.js.entitlement.PreUnbindHelper)8 PoolQuantity (org.candlepin.model.PoolQuantity)7