use of org.candlepin.model.Consumer in project candlepin by candlepin.
the class DefaultContentAccessCertServiceAdapter method createContentAccessDataPayload.
private byte[] createContentAccessDataPayload(Owner owner, Environment environment) throws IOException {
// fake a product dto as a container for the org content
Set<Product> containerSet = new HashSet<>();
CandlepinQuery<Content> ownerContent = ownerContentCurator.getContentByOwner(owner);
Set<String> entitledProductIds = new HashSet<>();
List<org.candlepin.model.dto.Product> productModels = new ArrayList<>();
Map<String, EnvironmentContent> promotedContent = getPromotedContent(environment);
String contentPrefix = getContentPrefix(owner, environment);
Product container = new Product();
Entitlement emptyEnt = new Entitlement();
Pool emptyPool = new Pool();
Product skuProduct = new Product();
Consumer emptyConsumer = new Consumer();
containerSet.add(container);
container.setId("content_access");
container.setName(" Content Access");
for (Content c : ownerContent) {
container.addContent(c, false);
}
emptyConsumer.setEnvironment(environment);
emptyEnt.setPool(emptyPool);
emptyEnt.setConsumer(emptyConsumer);
emptyPool.setProduct(skuProduct);
emptyPool.setStartDate(new Date());
emptyPool.setEndDate(new Date());
skuProduct.setName("Content Access");
skuProduct.setId("content_access");
entitledProductIds.add("content-access");
org.candlepin.model.dto.Product productModel = v3extensionUtil.mapProduct(container, skuProduct, contentPrefix, promotedContent, emptyConsumer, emptyPool, entitledProductIds);
productModels.add(productModel);
return v3extensionUtil.createEntitlementDataPayload(productModels, emptyConsumer, emptyPool, null);
}
use of org.candlepin.model.Consumer in project candlepin by candlepin.
the class PostBindBonusPoolsOp method execute.
@Override
public boolean execute(BindContext context) {
Consumer consumer = context.getLockedConsumer();
Map<String, Entitlement> entitlements = context.getEntitlementMap();
Map<String, PoolQuantity> poolQuantities = context.getPoolQuantities();
poolManager.handlePostEntitlement(poolManager, consumer, context.getOwner(), entitlements, poolQuantities);
// we might have changed the bonus pool quantities, lets revoke ents if needed.
poolManager.checkBonusPoolQuantities(consumer.getOwnerId(), entitlements);
return true;
}
use of org.candlepin.model.Consumer in project candlepin by candlepin.
the class CandlepinPoolManager method entitleByProductsImpl.
/**
* Performs the work of the entitleByProducts method in its own transaction to help unlock
* pools which can no longer be bound.
* <p></p>
* This method should not be called directly, and is only declared protected to allow the
* @Transactional annotation to function.
*
* @param data
* The autobind data to use for entitling a consumer
*
* @return
* a list of entitlements created as for this autobind operation
*/
@Transactional
protected List<Entitlement> entitleByProductsImpl(AutobindData data) throws EntitlementRefusedException {
Consumer consumer = data.getConsumer();
String[] productIds = data.getProductIds();
Collection<String> fromPools = data.getPossiblePools();
Date entitleDate = data.getOnDate();
String ownerId = consumer.getOwnerId();
List<PoolQuantity> bestPools = new ArrayList<>();
// fromPools will be empty if the dev pool was already created.
if (consumer != null && consumer.isDev() && !fromPools.isEmpty()) {
String poolId = fromPools.iterator().next();
PoolQuantity pq = new PoolQuantity(poolCurator.find(poolId), 1);
bestPools.add(pq);
} else {
bestPools = getBestPools(consumer, productIds, entitleDate, ownerId, null, fromPools);
}
if (bestPools == null) {
return null;
}
return entitleByPools(consumer, convertToMap(bestPools));
}
use of org.candlepin.model.Consumer 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.Consumer in project candlepin by candlepin.
the class CandlepinPoolManager method deletePools.
@Override
@Transactional
@Traceable
@SuppressWarnings("checkstyle:methodlength")
public void deletePools(Collection<Pool> pools, Collection<String> alreadyDeletedPoolIds) {
if (pools == null || pools.isEmpty()) {
return;
}
log.info("Attempting to delete {} pools...", pools.size());
// than they need to be and is resulting in running slow calculations multiple times.
if (alreadyDeletedPoolIds == null) {
alreadyDeletedPoolIds = new HashSet<>();
}
Set<String> poolIds = new HashSet<>();
Set<String> entitlementIds = new HashSet<>();
Owner owner = null;
// Convert pools to pool IDs.
log.info("Fetching related pools and entitlements...");
for (Pool pool : pools) {
if (owner == null) {
owner = pool.getOwner();
}
poolIds.add(pool.getId());
}
// Fetch pools which are derived from the pools we're going to delete...
poolIds.addAll(this.poolCurator.getDerivedPoolIdsForPools(poolIds));
// Fetch related pools and entitlements (recursively)
Collection<String> pids = poolIds;
int cachedSize;
do {
// Fetch entitlement IDs for our set of pools
Collection<String> eids = this.poolCurator.getEntitlementIdsForPools(pids);
// Fetch pools which are derived from these entitlements...
pids = this.poolCurator.getPoolIdsForSourceEntitlements(eids);
// Fetch stack derived pools which will be unentitled when we revoke entitlements
// Impl note: This may occassionally miss stack derived pools in cases where our
// entitlement count exceeds the IN block limitations. In those cases, we'll end
// up doing a recursive call into this method, which sucks, but will still work.
pids.addAll(this.poolCurator.getUnentitledStackDerivedPoolIds(eids));
// Fetch pools which are derived from the pools we're going to delete...
pids.addAll(this.poolCurator.getDerivedPoolIdsForPools(pids));
// Add the new entitlement and pool IDs to our list of things to delete
cachedSize = poolIds.size();
entitlementIds.addAll(eids);
poolIds.addAll(pids);
} while (poolIds.size() != cachedSize);
// TODO: Remove this and stop recursively calling into this method.
if (alreadyDeletedPoolIds != null) {
poolIds.removeAll(alreadyDeletedPoolIds);
}
// Lock pools we're going to delete (also, fetch them for event generation/slow deletes)
pools = this.poolCurator.lockAndLoadByIds(poolIds);
if (!pools.isEmpty()) {
log.info("Locked {} pools for deletion...", pools.size());
// Impl note:
// There is a fair bit of duplicated work between the actions below this block and
// methods like revokeEntitlements. However, the decision was made to decouple these
// methods explicitly to avoid situations such as fetching collections of pools, getting
// entitlements from them (a slow process in itself) and then passing it off to another
// standalone method which repeats the process of fetching pools and related entitlements.
//
// More work can be done in revokeEntitlements to optimize that method and maybe make it
// slightly more generic so that this work can be offloaded to it again. Though, at the time
// of writing, that's no small undertaking. Even changing this method has far-reaching
// consequences when trying to remove direct uses of entities as far as interoperability is
// concerned. Going forward we need to be more aware of the amount of duplication we're
// adding to our code when writing standlone/generic utility methods and linking them
// together, and perhaps take steps to avoid getting into situations like these two methods.
// Fetch the list of pools which are related to the entitlements but are *not* being
// deleted. We'll need to update the quantities on these.
Collection<String> affectedPoolIds = this.poolCurator.getPoolIdsForEntitlements(entitlementIds);
affectedPoolIds.removeAll(poolIds);
// Fetch entitlements (uggh).
// TODO: Stop doing this. Update the bits below to not use the entities directly and
// do the updates via queries.
Collection<Entitlement> entitlements = !entitlementIds.isEmpty() ? this.entitlementCurator.listAllByIds(entitlementIds).list() : Collections.<Entitlement>emptySet();
// Mark remaining dependent entitlements dirty for this consumer
this.entitlementCurator.markDependentEntitlementsDirty(entitlementIds);
// Unlink the pools and entitlements we're about to delete so we don't error out while
// trying to delete entitlements.
this.poolCurator.clearPoolSourceEntitlementRefs(poolIds);
// Revoke/delete entitlements
if (!entitlements.isEmpty()) {
log.info("Revoking {} entitlements...", entitlements.size());
this.entitlementCurator.batchDelete(entitlements);
this.entitlementCurator.flush();
log.info("Entitlements successfully revoked");
} else {
log.info("Skipping entitlement revocation; no entitlements to revoke");
}
// Delete pools
log.info("Deleting {} pools...", pools.size());
this.poolCurator.batchDelete(pools, alreadyDeletedPoolIds);
this.poolCurator.flush();
log.info("Pools successfully deleted");
if (!entitlements.isEmpty()) {
// Update entitlement counts on affected, non-deleted pools
log.info("Updating entitlement counts on remaining, affected pools...");
Map<Consumer, List<Entitlement>> consumerStackedEnts = new HashMap<>();
List<Pool> poolsToSave = new LinkedList<>();
Set<String> stackIds = new HashSet<>();
for (Entitlement entitlement : entitlements) {
// Since we're sifting through these already, let's also sort them into consumer lists
// for some of the other methods we'll be calling later
Consumer consumer = entitlement.getConsumer();
Pool pool = entitlement.getPool();
List<Entitlement> stackedEntitlements = consumerStackedEnts.get(consumer);
if (stackedEntitlements == null) {
stackedEntitlements = new LinkedList<>();
consumerStackedEnts.put(consumer, stackedEntitlements);
}
if (!"true".equals(pool.getAttributeValue(Pool.Attributes.DERIVED_POOL)) && pool.hasProductAttribute(Product.Attributes.STACKING_ID)) {
stackedEntitlements.add(entitlement);
stackIds.add(entitlement.getPool().getStackId());
}
// Update quantities if the entitlement quantity is non-zero
int quantity = entitlement.getQuantity() != null ? entitlement.getQuantity() : 0;
if (quantity != 0) {
// Update the pool quantities if we didn't delete it
if (affectedPoolIds.contains(pool.getId())) {
pool.setConsumed(pool.getConsumed() - quantity);
poolsToSave.add(pool);
}
// Update entitlement counts for affected consumers...
consumer.setEntitlementCount(consumer.getEntitlementCount() - quantity);
// Set the number exported if we're working with a manifest distributor
ConsumerType ctype = this.consumerTypeCurator.getConsumerType(consumer);
if (ctype != null && ctype.isManifest()) {
pool.setExported(pool.getExported() - quantity);
}
}
}
this.poolCurator.updateAll(poolsToSave, false, false);
this.consumerCurator.updateAll(consumerStackedEnts.keySet(), false, false);
this.consumerCurator.flush();
log.info("Entitlement counts successfully updated for {} pools and {} consumers", poolsToSave.size(), consumerStackedEnts.size());
// Update stacked entitlements for affected consumers(???)
if (!stackIds.isEmpty()) {
// Get consumer + pool tuples for stack ids
Map<String, Set<String>> consumerStackDerivedPoolIds = this.poolCurator.getConsumerStackDerivedPoolIdMap(stackIds);
if (!consumerStackDerivedPoolIds.isEmpty()) {
log.info("Updating stacked entitlements for {} consumers...", consumerStackDerivedPoolIds.size());
for (Consumer consumer : consumerStackedEnts.keySet()) {
Set<String> subPoolIds = consumerStackDerivedPoolIds.get(consumer.getId());
if (subPoolIds != null && !subPoolIds.isEmpty()) {
// Resolve pool IDs...
Collection<Pool> subPools = this.poolCurator.listAllByIds(subPoolIds).list();
// Invoke the rules engine to update the affected pools
if (subPools != null && !subPools.isEmpty()) {
log.debug("Updating {} stacking pools for consumer: {}", subPools.size(), consumer);
this.poolRules.updatePoolsFromStack(consumer, subPools, alreadyDeletedPoolIds, true);
}
}
}
}
}
this.consumerCurator.flush();
// Hydrate remaining consumer pools so we can skip some extra work during serialization
Set<Pool> poolsToHydrate = new HashSet<>();
for (Consumer consumer : consumerStackedEnts.keySet()) {
for (Entitlement entitlement : consumer.getEntitlements()) {
poolsToHydrate.add(entitlement.getPool());
}
}
this.productCurator.hydratePoolProvidedProducts(poolsToHydrate);
// Fire post-unbind events for revoked entitlements
log.info("Firing post-unbind events for {} entitlements...", entitlements.size());
for (Entitlement entitlement : entitlements) {
this.enforcer.postUnbind(entitlement.getConsumer(), this, entitlement);
}
// Recalculate status for affected consumers
log.info("Recomputing status for {} consumers", consumerStackedEnts.size());
int i = 0;
for (Consumer consumer : consumerStackedEnts.keySet()) {
this.complianceRules.getStatus(consumer);
if (++i % 1000 == 0) {
this.consumerCurator.flush();
}
}
this.consumerCurator.flush();
log.info("All statuses recomputed");
}
// Impl note:
// We don't need to fire entitlement revocation events, since they're all being revoked as
// a consequence of the pools being deleted.
// Fire pool deletion events
// This part hurts so much. Because we output the whole entity, we have to fetch the bloody
// things before we delete them.
log.info("Firing pool deletion events for {} pools...", pools.size());
for (Pool pool : pools) {
this.sink.queueEvent(this.eventFactory.poolDeleted(pool));
}
} else {
log.info("Skipping pool deletion; no pools to delete");
}
}
Aggregations