Search in sources :

Example 36 with PoolQuantity

use of org.candlepin.model.PoolQuantity in project candlepin by candlepin.

the class Entitler method getDryRun.

/**
 * Entitles the given Consumer to the given Product. Will seek out pools
 * which provide access to this product, either directly or as a child, and
 * select the best one based on a call to the rules engine.
 *
 * @param consumer The consumer being entitled.
 * @return List of Entitlements
 */
public List<PoolQuantity> getDryRun(Consumer consumer, Owner owner, String serviceLevelOverride) {
    List<PoolQuantity> result = new ArrayList<>();
    try {
        if (consumer.isDev()) {
            if (config.getBoolean(ConfigProperties.STANDALONE) || !poolCurator.hasActiveEntitlementPools(consumer.getOwnerId(), null)) {
                throw new ForbiddenException(i18n.tr("Development units may only be used on hosted servers" + " and with orgs that have active subscriptions."));
            }
            // Look up the dev pool for this consumer, and if not found
            // create one. If a dev pool already exists, remove it and
            // create a new one.
            String sku = consumer.getFact("dev_sku");
            Pool devPool = poolCurator.findDevPool(consumer);
            if (devPool != null) {
                poolManager.deletePool(devPool);
            }
            devPool = poolManager.createPool(assembleDevPool(consumer, owner, sku));
            result.add(new PoolQuantity(devPool, 1));
        } else {
            result = poolManager.getBestPools(consumer, null, null, owner.getId(), serviceLevelOverride, null);
        }
        log.debug("Created Pool Quantity list: {}", result);
    } catch (EntitlementRefusedException e) {
        // to the process
        if (log.isDebugEnabled()) {
            log.debug("consumer {} dry-run errors:", consumer.getUuid());
            for (Entry<String, ValidationResult> entry : e.getResults().entrySet()) {
                log.debug("errors for pool id: {}", entry.getKey());
                for (ValidationError error : entry.getValue().getErrors()) {
                    log.debug(error.getResourceKey());
                }
            }
        }
    }
    return result;
}
Also used : PoolQuantity(org.candlepin.model.PoolQuantity) ForbiddenException(org.candlepin.common.exceptions.ForbiddenException) Entry(java.util.Map.Entry) EntitlementRefusedException(org.candlepin.policy.EntitlementRefusedException) ArrayList(java.util.ArrayList) Pool(org.candlepin.model.Pool) ValidationError(org.candlepin.policy.ValidationError)

Example 37 with PoolQuantity

use of org.candlepin.model.PoolQuantity in project candlepin by candlepin.

the class EntitlementCertificateGenerator method generateEntitlementCertificate.

/**
 * Generates a new entitlement certificate for the given entitlement and pool.
 *
 * @param pool
 *  The pool for which to generate an entitlement certificate
 *
 * @param entitlement
 *  The entitlement to use when generating the certificate
 *
 * @return
 *  The newly generate entitlement certificate
 */
@Transactional
public EntitlementCertificate generateEntitlementCertificate(Pool pool, Entitlement entitlement) {
    Map<String, Product> products = new HashMap<>();
    Map<String, Entitlement> entitlements = new HashMap<>();
    Map<String, PoolQuantity> poolQuantities = new HashMap<>();
    products.put(pool.getId(), pool.getProduct());
    entitlements.put(pool.getId(), entitlement);
    poolQuantities.put(pool.getId(), new PoolQuantity(pool, entitlement.getQuantity()));
    return this.generateEntitlementCertificates(entitlement.getConsumer(), products, poolQuantities, entitlements, true).get(pool.getId());
}
Also used : PoolQuantity(org.candlepin.model.PoolQuantity) HashMap(java.util.HashMap) Product(org.candlepin.model.Product) Entitlement(org.candlepin.model.Entitlement) Transactional(com.google.inject.persist.Transactional)

Example 38 with PoolQuantity

use of org.candlepin.model.PoolQuantity 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 39 with PoolQuantity

use of org.candlepin.model.PoolQuantity 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 40 with PoolQuantity

use of org.candlepin.model.PoolQuantity in project candlepin by candlepin.

the class HandleEntitlementsOp method execute.

/**
 * associates the pools, consumers with entitlements, and persists the entities as needed.
 * also computes all the consumed counts.
 * @param context
 */
@Override
public boolean execute(BindContext context) {
    Consumer consumer = context.getLockedConsumer();
    ConsumerType ctype = context.getConsumerType();
    Map<String, Entitlement> entitlementMap = context.getEntitlementMap();
    Map<String, PoolQuantity> lockedPools = context.getPoolQuantities();
    List<Pool> poolsToSave = new LinkedList<>();
    for (Entry<String, PoolQuantity> entry : lockedPools.entrySet()) {
        Entitlement ent = entitlementMap.get(entry.getKey());
        Pool pool = entry.getValue().getPool();
        Integer quantity = ent.getQuantity();
        pool.getEntitlements().add(ent);
        ent.setPool(pool);
        ent.setConsumer(consumer);
        ent.setOwner(pool.getOwner());
        pool.setConsumed(pool.getConsumed() + quantity);
        if (ctype.isManifest()) {
            pool.setExported(pool.getExported() + quantity);
        } else if (ctype.isType(ConsumerTypeEnum.SHARE)) {
            pool.setShared(pool.getShared() + quantity);
        }
        consumer.addEntitlement(ent);
        consumer.setEntitlementCount(consumer.getEntitlementCount() + quantity);
        poolsToSave.add(pool);
    }
    entitlementCurator.saveAll(entitlementMap.values(), false, false);
    poolCurator.updateAll(poolsToSave, false, false);
    return true;
}
Also used : PoolQuantity(org.candlepin.model.PoolQuantity) Consumer(org.candlepin.model.Consumer) Pool(org.candlepin.model.Pool) ConsumerType(org.candlepin.model.ConsumerType) Entitlement(org.candlepin.model.Entitlement) LinkedList(java.util.LinkedList)

Aggregations

PoolQuantity (org.candlepin.model.PoolQuantity)75 Pool (org.candlepin.model.Pool)65 Test (org.junit.Test)52 Entitlement (org.candlepin.model.Entitlement)34 LinkedList (java.util.LinkedList)30 Product (org.candlepin.model.Product)28 HashMap (java.util.HashMap)27 ArrayList (java.util.ArrayList)21 Consumer (org.candlepin.model.Consumer)12 List (java.util.List)11 ConsumerType (org.candlepin.model.ConsumerType)11 Matchers.anyString (org.mockito.Matchers.anyString)11 Date (java.util.Date)8 Set (java.util.Set)8 HashSet (java.util.HashSet)7 EntitlementRefusedException (org.candlepin.policy.EntitlementRefusedException)7 ValidationResult (org.candlepin.policy.ValidationResult)7 Subscription (org.candlepin.model.dto.Subscription)6 Matchers.anyLong (org.mockito.Matchers.anyLong)6 PoolFilterBuilder (org.candlepin.model.PoolFilterBuilder)5