Search in sources :

Example 1 with Subscription

use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.

the class CandlepinPoolManager method refreshPoolsWithRegeneration.

/*
     * We need to update/regen entitlements in the same transaction we update pools
     * so we don't miss anything
     */
@Transactional
@SuppressWarnings("checkstyle:methodlength")
@Traceable
void refreshPoolsWithRegeneration(SubscriptionServiceAdapter subAdapter, @TraceableParam("owner") Owner owner, boolean lazy) {
    Date now = new Date();
    owner = this.resolveOwner(owner);
    log.info("Refreshing pools for owner: {}", owner);
    Map<String, Subscription> subscriptionMap = new HashMap<>();
    Map<String, ProductData> productMap = new HashMap<>();
    Map<String, ContentData> contentMap = new HashMap<>();
    // Resolve all our subscriptions, products and content to ensure we don't have bad or
    // duplicate inbound data
    log.debug("Fetching subscriptions from adapter...");
    List<Subscription> subscriptions = subAdapter.getSubscriptions(owner);
    log.debug("Done. Processing subscriptions...");
    for (Subscription subscription : subscriptions) {
        if (subscription == null) {
            continue;
        }
        if (subscription.getId() == null) {
            log.error("subscription does not contain a mappable ID: {}", subscription);
            throw new IllegalStateException("subscription does not contain a mappable ID: " + subscription);
        }
        Subscription existingSub = subscriptionMap.get(subscription.getId());
        if (existingSub != null && !existingSub.equals(subscription)) {
            log.warn("Multiple versions of the same subscription received during refresh; " + "discarding duplicate: {} => {}, {}", subscription.getId(), existingSub, subscription);
            continue;
        }
        subscriptionMap.put(subscription.getId(), subscription);
        List<ProductData> products = new LinkedList<>();
        products.add(subscription.getProduct());
        products.add(subscription.getDerivedProduct());
        products.addAll(subscription.getProvidedProducts());
        products.addAll(subscription.getDerivedProvidedProducts());
        for (ProductData product : products) {
            if (product == null) {
                // forward.
                continue;
            }
            if (product.getId() == null) {
                log.error("product does not contain a mappable Red Hat ID: {}", product);
                throw new IllegalStateException("product does not contain a mappable Red Hat ID: " + product);
            }
            // Product is coming from an upstream source; lock it so only upstream can make
            // further changes to it.
            product.setLocked(true);
            ProductData existingProduct = productMap.get(product.getId());
            if (existingProduct != null && !existingProduct.equals(product)) {
                log.warn("Multiple versions of the same product received during refresh; " + "discarding duplicate: {} => {}, {}", product.getId(), existingProduct, product);
            } else {
                productMap.put(product.getId(), product);
                Collection<ProductContentData> pcdCollection = product.getProductContent();
                if (pcdCollection != null) {
                    for (ProductContentData pcd : pcdCollection) {
                        if (pcd == null) {
                            log.error("product contains a null product-content mapping: {}", product);
                            throw new IllegalStateException("product contains a null product-content mapping: " + product);
                        }
                        ContentData content = pcd.getContent();
                        // population validation for us.
                        if (content == null || content.getId() == null) {
                            log.error("product contains a null or incomplete product-content mapping: {}", product);
                            throw new IllegalStateException("product contains a null or incomplete " + "product-content mapping: " + product);
                        }
                        // We need to lock the incoming content here, but doing so will affect
                        // the equality comparison for products. We'll correct them later.
                        ContentData existingContent = contentMap.get(content.getId());
                        if (existingContent != null && !existingContent.equals(content)) {
                            log.warn("Multiple versions of the same content received during refresh; " + "discarding duplicate: {} => {}, {}", content.getId(), existingContent, content);
                        } else {
                            contentMap.put(content.getId(), content);
                        }
                    }
                }
            }
        }
    }
    // Persist content changes
    log.debug("Importing {} content...", contentMap.size());
    // TODO: Find a more efficient way of doing this, preferably within this method
    for (ContentData cdata : contentMap.values()) {
        cdata.setLocked(true);
    }
    Map<String, Content> importedContent = this.contentManager.importContent(owner, contentMap, productMap.keySet()).getImportedEntities();
    log.debug("Importing {} product(s)...", productMap.size());
    ImportResult<Product> importResult = this.productManager.importProducts(owner, productMap, importedContent);
    Map<String, Product> importedProducts = importResult.getImportedEntities();
    Map<String, Product> updatedProducts = importResult.getUpdatedEntities();
    log.debug("Refreshing {} pool(s)...", subscriptionMap.size());
    Iterator<Map.Entry<String, Subscription>> subsIterator = subscriptionMap.entrySet().iterator();
    while (subsIterator.hasNext()) {
        Map.Entry<String, Subscription> entry = subsIterator.next();
        Subscription sub = entry.getValue();
        if (now.after(sub.getEndDate())) {
            log.info("Skipping expired subscription: {}", sub);
            subsIterator.remove();
            continue;
        }
        log.debug("Processing subscription: {}", sub);
        Pool pool = this.convertToMasterPoolImpl(sub, owner, importedProducts);
        this.refreshPoolsForMasterPool(pool, false, lazy, updatedProducts);
    }
    // delete pools whose subscription disappeared:
    log.debug("Deleting pools for absent subscriptions...");
    List<Pool> poolsToDelete = new ArrayList<>();
    for (Pool pool : poolCurator.getPoolsFromBadSubs(owner, subscriptionMap.keySet())) {
        if (this.isManaged(pool)) {
            poolsToDelete.add(pool);
        }
    }
    deletePools(poolsToDelete);
    // TODO: break this call into smaller pieces. There may be lots of floating pools
    log.debug("Updating floating pools...");
    List<Pool> floatingPools = poolCurator.getOwnersFloatingPools(owner);
    updateFloatingPools(floatingPools, lazy, updatedProducts);
    log.info("Refresh pools for owner: {} completed in: {}ms", owner.getKey(), System.currentTimeMillis() - now.getTime());
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Product(org.candlepin.model.Product) Entry(java.util.Map.Entry) ProductContentData(org.candlepin.model.dto.ProductContentData) ContentData(org.candlepin.model.dto.ContentData) Pool(org.candlepin.model.Pool) SourceSubscription(org.candlepin.model.SourceSubscription) Subscription(org.candlepin.model.dto.Subscription) ProductContentData(org.candlepin.model.dto.ProductContentData) ProductData(org.candlepin.model.dto.ProductData) Date(java.util.Date) LinkedList(java.util.LinkedList) Content(org.candlepin.model.Content) Map(java.util.Map) HashMap(java.util.HashMap) Traceable(org.candlepin.util.Traceable) Transactional(com.google.inject.persist.Transactional)

Example 2 with Subscription

use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.

the class Refresher method run.

public void run() {
    // If products were specified on the refresher, lookup any subscriptions
    // using them, regardless of organization, and trigger a refresh for those
    // specific subscriptions.
    Set<Subscription> subscriptions = new HashSet<>();
    for (Product product : products) {
        // TODO: This adapter call is not implemented in prod, and cannot be. We plan
        // to fix this whole code path in near future by looking for pools using the
        // given products to be refreshed.
        List<Subscription> subs = subAdapter.getSubscriptions(product.toDTO());
        log.debug("Will refresh {} subscriptions in all orgs using product: ", subs.size(), product.getId());
        if (log.isDebugEnabled()) {
            for (Subscription s : subs) {
                Owner so = s.getOwner();
                if (so == null || so.getKey() == null) {
                    log.debug("  Received a subscription without a well-defined owner: {}", s.getId());
                    continue;
                }
                if (!this.owners.containsKey(so.getKey())) {
                    log.debug("    {}", s);
                }
            }
        }
        subscriptions.addAll(subs);
    }
    for (Subscription subscription : subscriptions) {
        // drop any subs for owners in our owners list. we'll get them with the full
        // refreshPools call.
        Owner so = subscription.getOwner();
        // This probably shouldn't ever happen, but let's make sure it doesn't anyway.
        if (so == null || so.getKey() == null) {
            log.error("Received a subscription without a well-defined owner: {}", subscription.getId());
            continue;
        }
        if (this.owners.containsKey(so.getKey())) {
            log.debug("Skipping subscription \"{}\" for owner: {}", subscription.getId(), so);
            continue;
        }
        /*
             * on the off chance that this is actually a new subscription, make
             * the required pools. this shouldn't happen; we should really get a
             * refresh pools by owner call for it, but why not handle it, just
             * in case!
             *
             * Regenerate certificates here, that way if it fails, the whole
             * thing rolls back. We don't want to refresh without marking ents
             * dirty, they will never get regenerated
             */
        Pool masterPool = poolManager.convertToMasterPool(subscription);
        poolManager.refreshPoolsForMasterPool(masterPool, true, lazy, Collections.<String, Product>emptyMap());
    }
    for (Owner owner : this.owners.values()) {
        poolManager.refreshPoolsWithRegeneration(this.subAdapter, owner, this.lazy);
        poolManager.recalculatePoolQuantitiesForOwner(owner);
        ownerManager.refreshContentAccessMode(this.ownerAdapter, owner);
        ownerManager.updateRefreshDate(owner);
    }
}
Also used : Owner(org.candlepin.model.Owner) Product(org.candlepin.model.Product) Pool(org.candlepin.model.Pool) Subscription(org.candlepin.model.dto.Subscription) HashSet(java.util.HashSet)

Example 3 with Subscription

use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.

the class SubscriptionReconcilerTest method testQuantMatchAllLower.

@Test
public void testQuantMatchAllLower() {
    Subscription testSub1 = createSubscription(owner, "test-prod-1", "up1", "ue1", "uc1", 25);
    Subscription testSub2 = createSubscription(owner, "test-prod-1", "up1", "ue2", "uc1", 20);
    Subscription testSub3 = createSubscription(owner, "test-prod-1", "up1", "ue3", "uc1", 15);
    Subscription testSub12 = createSubscription(owner, "test-prod-1", "up1", "ue12", "uc3", 23);
    Subscription testSub13 = createSubscription(owner, "test-prod-1", "up1", "ue13", "uc3", 17);
    Subscription testSub14 = createSubscription(owner, "test-prod-1", "up1", "ue14", "uc3", 10);
    createPoolsFor(testSub1, testSub2, testSub3);
    reconciler.reconcile(owner, Arrays.asList(testSub12, testSub13, testSub14));
    // Quantities 25, 20, 15 should be replaced by new pools with 23, 17, 10:
    assertUpstream(testSub12, testSub1.getId());
    assertUpstream(testSub13, testSub2.getId());
    assertUpstream(testSub14, testSub3.getId());
}
Also used : Subscription(org.candlepin.model.dto.Subscription) Test(org.junit.Test)

Example 4 with Subscription

use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.

the class SubscriptionReconcilerTest method createSubscription.

private Subscription createSubscription(Owner daOwner, String productId, String poolId, String entId, String conId, long quantity) {
    ProductData pdata = new ProductData();
    pdata.setId(productId);
    pdata.setName(productId);
    Subscription sub = new Subscription();
    sub.setProduct(pdata);
    sub.setUpstreamPoolId(poolId);
    sub.setUpstreamEntitlementId(entId);
    sub.setUpstreamConsumerId(conId);
    sub.setQuantity(quantity);
    sub.setOwner(daOwner);
    sub.setId("" + index++);
    return sub;
}
Also used : ProductData(org.candlepin.model.dto.ProductData) Subscription(org.candlepin.model.dto.Subscription)

Example 5 with Subscription

use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.

the class SubscriptionReconcilerTest method oneExistsOneNew.

@Test
public void oneExistsOneNew() {
    Subscription testSub2 = createSubscription(owner, "test-prod-1", "up1", "ue2", "uc1", 20);
    Subscription testSub3 = createSubscription(owner, "test-prod-1", "up1", "ue3", "uc1", 15);
    createPoolsFor(testSub2);
    reconciler.reconcile(owner, Arrays.asList(testSub2, testSub3));
    assertUpstream(testSub2, testSub2.getId());
    assertUpstream(testSub3, testSub3.getId());
}
Also used : Subscription(org.candlepin.model.dto.Subscription) Test(org.junit.Test)

Aggregations

Subscription (org.candlepin.model.dto.Subscription)101 Test (org.junit.Test)77 Pool (org.candlepin.model.Pool)60 Product (org.candlepin.model.Product)48 SourceSubscription (org.candlepin.model.SourceSubscription)36 LinkedList (java.util.LinkedList)35 ArrayList (java.util.ArrayList)34 Owner (org.candlepin.model.Owner)33 ConsumerInstalledProduct (org.candlepin.model.ConsumerInstalledProduct)27 HashMap (java.util.HashMap)20 HashSet (java.util.HashSet)18 Matchers.anyString (org.mockito.Matchers.anyString)18 Entitlement (org.candlepin.model.Entitlement)16 Date (java.util.Date)15 PoolType (org.candlepin.model.Pool.PoolType)13 ImportSubscriptionServiceAdapter (org.candlepin.service.impl.ImportSubscriptionServiceAdapter)13 List (java.util.List)11 OwnerServiceAdapter (org.candlepin.service.OwnerServiceAdapter)11 ConsumerType (org.candlepin.model.ConsumerType)10 ProductData (org.candlepin.model.dto.ProductData)9