use of org.candlepin.model.Pool in project candlepin by candlepin.
the class CandlepinPoolManager method refreshPoolsForMasterPool.
@Transactional
void refreshPoolsForMasterPool(Pool pool, boolean updateStackDerived, boolean lazy, Map<String, Product> changedProducts) {
// These don't all necessarily belong to this owner
List<Pool> subscriptionPools;
if (pool.getSubscriptionId() != null) {
subscriptionPools = this.poolCurator.getPoolsBySubscriptionId(pool.getSubscriptionId()).list();
} else {
// If we don't have a subscription ID, this *is* the master pool, but we need to use
// the original, hopefully unmodified pool
subscriptionPools = pool.getId() != null ? Collections.<Pool>singletonList(this.poolCurator.find(pool.getId())) : Collections.<Pool>singletonList(pool);
}
log.debug("Found {} pools for subscription {}", subscriptionPools.size(), pool.getSubscriptionId());
if (log.isDebugEnabled()) {
for (Pool p : subscriptionPools) {
log.debug(" owner={} - {}", p.getOwner().getKey(), p);
}
}
// TODO: Should this be performed by poolRules? Seems like that should be a thing.
for (Pool subPool : subscriptionPools) {
Product product = subPool.getProduct();
if (product != null) {
Product update = changedProducts.get(product.getId());
if (update != null) {
subPool.setProduct(update);
}
}
product = subPool.getDerivedProduct();
if (product != null) {
Product update = changedProducts.get(product.getId());
if (update != null) {
subPool.setDerivedProduct(update);
}
}
}
// Cleans up pools on other owners who have migrated subs away
removeAndDeletePoolsOnOtherOwners(subscriptionPools, pool);
// capture the original quantity to check for updates later
Long originalQuantity = pool.getQuantity();
// BZ 1012386: This will regenerate master/derived for bonus scenarios if only one of the
// pair still exists.
createAndEnrichPools(pool, subscriptionPools);
// don't update floating here, we'll do that later so we don't update anything twice
Set<String> updatedMasterPools = updatePoolsForMasterPool(subscriptionPools, pool, originalQuantity, updateStackDerived, changedProducts);
regenerateCertificatesByEntIds(updatedMasterPools, lazy);
}
use of org.candlepin.model.Pool in project candlepin by candlepin.
the class CandlepinPoolManager method getBestPoolsForHost.
/**
* Here we pick uncovered products from the guest where no virt-only
* subscriptions exist, and have the host bind non-zero virt_limit
* subscriptions in order to generate pools for the guest to bind later.
*
* @param guest whose products we want to provide
* @param host to bind entitlements to
* @param entitleDate
* @param owner
* @param serviceLevelOverride
* @return PoolQuantity list to attempt to attach
* @throws EntitlementRefusedException if unable to bind
*/
@Override
@SuppressWarnings("checkstyle:methodlength")
public List<PoolQuantity> getBestPoolsForHost(Consumer guest, Consumer host, Date entitleDate, String ownerId, String serviceLevelOverride, Collection<String> fromPools) throws EntitlementRefusedException {
Map<String, ValidationResult> failedResults = new HashMap<>();
log.debug("Looking up best pools for host: {}", host);
boolean tempLevel = false;
if (StringUtils.isEmpty(host.getServiceLevel())) {
host.setServiceLevel(guest.getServiceLevel());
tempLevel = true;
}
Date activePoolDate = entitleDate;
if (entitleDate == null) {
activePoolDate = new Date();
}
PoolFilterBuilder poolFilter = new PoolFilterBuilder();
poolFilter.addIdFilters(fromPools);
List<Pool> allOwnerPools = this.listAvailableEntitlementPools(host, null, ownerId, null, null, activePoolDate, false, poolFilter, null, false, false, null).getPageData();
log.debug("Found {} total pools in org.", allOwnerPools.size());
logPools(allOwnerPools);
List<Pool> allOwnerPoolsForGuest = this.listAvailableEntitlementPools(guest, null, ownerId, null, null, activePoolDate, false, poolFilter, null, false, false, null).getPageData();
log.debug("Found {} total pools already available for guest", allOwnerPoolsForGuest.size());
logPools(allOwnerPoolsForGuest);
for (Entitlement ent : host.getEntitlements()) {
// filter out pools that are attached, there is no need to
// complete partial stacks, as they are already granting
// virtual pools
log.debug("Removing pool host is already entitled to: {}", ent.getPool());
allOwnerPools.remove(ent.getPool());
}
List<Pool> filteredPools = new LinkedList<>();
ComplianceStatus guestCompliance = complianceRules.getStatus(guest, entitleDate, false);
Set<String> tmpSet = new HashSet<>();
// we only want to heal red products, not yellow
tmpSet.addAll(guestCompliance.getNonCompliantProducts());
log.debug("Guest's non-compliant products: {}", Util.collectionToString(tmpSet));
/*Do not attempt to create subscriptions for products that
already have virt_only pools available to the guest */
Set<String> productsToRemove = getProductsToRemove(allOwnerPoolsForGuest, tmpSet);
log.debug("Guest already will have virt-only pools to cover: {}", Util.collectionToString(productsToRemove));
tmpSet.removeAll(productsToRemove);
String[] productIds = tmpSet.toArray(new String[] {});
if (log.isDebugEnabled()) {
log.debug("Attempting host autobind for guest products: {}", Util.collectionToString(tmpSet));
}
// Bulk fetch our provided and derived provided product IDs so we're not hitting the DB
// several times for this lookup.
Map<String, Set<String>> providedProductIds = this.poolCurator.getProvidedProductIds(allOwnerPools);
Map<String, Set<String>> derivedProvidedProductIds = this.poolCurator.getDerivedProvidedProductIds(allOwnerPools);
for (Pool pool : allOwnerPools) {
boolean providesProduct = false;
// and we only need to check that it's non-zero
if (pool.getProduct().hasAttribute(Product.Attributes.VIRT_LIMIT) && !pool.getProduct().getAttributeValue(Product.Attributes.VIRT_LIMIT).equals("0")) {
Map<String, Set<String>> providedProductMap;
String baseProductId;
// Determine which set of provided products we should use...
if (pool.getDerivedProduct() != null) {
providedProductMap = derivedProvidedProductIds;
baseProductId = pool.getDerivedProduct().getId();
} else {
providedProductMap = providedProductIds;
baseProductId = pool.getProduct().getId();
}
// Add the base product to the list of derived provided products...
Set<String> poolProvidedProductIds = providedProductMap.get(pool.getId());
if (baseProductId != null) {
if (poolProvidedProductIds != null) {
poolProvidedProductIds.add(baseProductId);
} else {
poolProvidedProductIds = Collections.<String>singleton(baseProductId);
}
}
// Check if the pool provides any of the specified products
if (poolProvidedProductIds != null) {
for (String productId : productIds) {
// provides anything for the guest, otherwise we use the parent.
if (poolProvidedProductIds.contains(productId)) {
log.debug("Found virt_limit pool providing product {}: {}", productId, pool);
providesProduct = true;
break;
}
}
}
}
if (providesProduct) {
ValidationResult result = enforcer.preEntitlement(host, pool, 1, CallerType.BEST_POOLS);
if (result.hasErrors() || result.hasWarnings()) {
// Just keep the last one around, if we need it
failedResults.put(pool.getId(), result);
if (log.isDebugEnabled()) {
log.debug("Pool filtered from candidates due to failed rule(s): {}", pool);
log.debug(" warnings: {}", Util.collectionToString(result.getWarnings()));
log.debug(" errors: {}", Util.collectionToString(result.getErrors()));
}
} else {
filteredPools.add(pool);
}
}
}
// Only throw refused exception if we actually hit the rules:
if (filteredPools.size() == 0 && !failedResults.isEmpty()) {
throw new EntitlementRefusedException(failedResults);
}
ComplianceStatus hostCompliance = complianceRules.getStatus(host, entitleDate, false);
log.debug("Host pools being sent to rules: {}", filteredPools.size());
logPools(filteredPools);
List<PoolQuantity> enforced = autobindRules.selectBestPools(host, productIds, filteredPools, hostCompliance, serviceLevelOverride, poolCurator.retrieveServiceLevelsForOwner(ownerId, true), true);
if (log.isDebugEnabled()) {
log.debug("Host selectBestPools returned {} pools: ", enforced.size());
for (PoolQuantity poolQuantity : enforced) {
log.debug(" " + poolQuantity.getPool());
}
}
if (tempLevel) {
host.setServiceLevel("");
// complianceRules.getStatus may have persisted the host with the temp service level,
// so we need to be certain we undo that.
consumerCurator.update(host);
}
return enforced;
}
use of org.candlepin.model.Pool in project candlepin by candlepin.
the class CandlepinPoolManager method createAndEnrichPools.
public List<Pool> createAndEnrichPools(Subscription sub, List<Pool> existingPools) {
List<Pool> pools = poolRules.createAndEnrichPools(sub, existingPools);
log.debug("Creating {} pools for subscription: {}", pools.size(), sub);
for (Pool pool : pools) {
createPool(pool);
}
return pools;
}
use of org.candlepin.model.Pool in project candlepin by candlepin.
the class CandlepinPoolManager method revokeEntitlements.
/**
* Revokes the given set of entitlements.
*
* @param entsToRevoke entitlements to revoke
* @param alreadyDeletedPools pools to skip deletion as they have already been deleted
* @param regenCertsAndStatuses if this revocation should also trigger regeneration of certificates
* and recomputation of statuses. For performance reasons some callers might
* choose to set this to false.
*/
@Transactional
@Traceable
public void revokeEntitlements(List<Entitlement> entsToRevoke, Set<String> alreadyDeletedPools, boolean regenCertsAndStatuses) {
if (CollectionUtils.isEmpty(entsToRevoke)) {
return;
}
log.debug("Starting batch revoke of {} entitlements", entsToRevoke.size());
if (log.isTraceEnabled()) {
log.trace("Entitlements IDs: {}", getEntIds(entsToRevoke));
}
Set<Pool> poolsToDelete = this.poolCurator.listBySourceEntitlements(entsToRevoke);
log.debug("Found {} additional pools to delete from source entitlements", poolsToDelete.size());
if (log.isTraceEnabled()) {
log.trace("Additional pool IDs: {}", getPoolIds(poolsToDelete));
}
List<Pool> poolsToLock = new ArrayList<>();
poolsToLock.addAll(poolsToDelete);
for (Entitlement ent : entsToRevoke) {
poolsToLock.add(ent.getPool());
// associated pool as well.
if (ent.getPool() != null && ent.getPool().isDevelopmentPool()) {
poolsToDelete.add(ent.getPool());
}
}
poolCurator.lockAndLoad(poolsToLock);
log.info("Batch revoking {} entitlements", entsToRevoke.size());
entsToRevoke = new ArrayList<>(entsToRevoke);
for (Pool pool : poolsToDelete) {
for (Entitlement ent : pool.getEntitlements()) {
ent.setDeletedFromPool(true);
entsToRevoke.add(ent);
}
}
log.debug("Adjusting consumed quantities on pools");
List<Pool> poolsToSave = new ArrayList<>();
Set<String> entIdsToRevoke = new HashSet<>();
for (Entitlement ent : entsToRevoke) {
// or just continue silently ignoring them?
if (ent == null || ent.getId() == null) {
continue;
}
// Collect the entitlement IDs to revoke seeing as we are iterating over them anyway.
entIdsToRevoke.add(ent.getId());
// We need to trigger lazy load of provided products
// to have access to those products later in this method.
Pool pool = ent.getPool();
int entQuantity = ent.getQuantity() != null ? ent.getQuantity() : 0;
pool.setConsumed(pool.getConsumed() - entQuantity);
Consumer consumer = ent.getConsumer();
ConsumerType ctype = this.consumerTypeCurator.getConsumerType(consumer);
if (ctype != null) {
if (ctype.isManifest()) {
pool.setExported(pool.getExported() - entQuantity);
} else if (ctype.isType(ConsumerTypeEnum.SHARE)) {
pool.setShared(pool.getShared() - entQuantity);
}
}
consumer.setEntitlementCount(consumer.getEntitlementCount() - entQuantity);
consumerCurator.update(consumer);
poolsToSave.add(pool);
}
poolCurator.updateAll(poolsToSave, false, false);
/*
* Before deleting the entitlements, we need to find out if there are any
* modifier entitlements that need to have their certificates regenerated
*/
if (regenCertsAndStatuses) {
log.debug("Marking dependent entitlements as dirty...");
int update = this.entitlementCurator.markDependentEntitlementsDirty(entIdsToRevoke);
log.debug("{} dependent entitlements marked dirty.", update);
}
log.info("Starting batch delete of pools");
poolCurator.batchDelete(poolsToDelete, alreadyDeletedPools);
log.info("Starting batch delete of entitlements");
entitlementCurator.batchDelete(entsToRevoke);
log.info("Starting delete flush");
entitlementCurator.flush();
log.info("All deletes flushed successfully");
Map<Consumer, List<Entitlement>> consumerSortedEntitlements = entitlementCurator.getDistinctConsumers(entsToRevoke);
filterAndUpdateStackingEntitlements(consumerSortedEntitlements, alreadyDeletedPools);
// post unbind actions
for (Entitlement ent : entsToRevoke) {
enforcer.postUnbind(ent.getConsumer(), this, ent);
}
if (!regenCertsAndStatuses) {
log.info("Regeneration and status computation was not requested finishing batch revoke");
sendDeletedEvents(entsToRevoke);
return;
}
log.info("Recomputing status for {} consumers.", consumerSortedEntitlements.size());
int i = 1;
for (Consumer consumer : consumerSortedEntitlements.keySet()) {
if (i++ % 1000 == 0) {
consumerCurator.flush();
}
complianceRules.getStatus(consumer);
}
consumerCurator.flush();
log.info("All statuses recomputed.");
sendDeletedEvents(entsToRevoke);
}
use of org.candlepin.model.Pool in project candlepin by candlepin.
the class CandlepinPoolManager method getProductsToRemove.
/**
* Do not attempt to create subscriptions for products that
* already have virt_only pools available to the guest
*/
private Set<String> getProductsToRemove(List<Pool> allOwnerPoolsForGuest, Set<String> tmpSet) {
Set<String> productsToRemove = new HashSet<>();
// 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(allOwnerPoolsForGuest);
for (Pool pool : allOwnerPoolsForGuest) {
if (pool.getProduct() != null && (pool.getProduct().hasAttribute(Product.Attributes.VIRT_ONLY) || pool.hasAttribute(Pool.Attributes.VIRT_ONLY))) {
Set<String> poolProvidedProductIds = providedProductIds.get(pool.getId());
String poolProductId = pool.getProduct().getId();
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 prodId : tmpSet) {
if (poolProvidedProductIds.contains(prodId)) {
productsToRemove.add(prodId);
}
}
}
}
}
return productsToRemove;
}
Aggregations