/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.pinsetter.tasks; import static org.quartz.JobBuilder.*; import org.candlepin.common.filter.LoggingFilter; import org.candlepin.controller.AutobindDisabledForOwnerException; import org.candlepin.controller.Entitler; import org.candlepin.model.Consumer; import org.candlepin.model.ConsumerCurator; import org.candlepin.model.Entitlement; import org.candlepin.model.Owner; import org.candlepin.model.OwnerCurator; import org.candlepin.pinsetter.core.model.JobStatus; import org.candlepin.resource.dto.AutobindData; import org.candlepin.util.Util; import org.apache.log4j.MDC; import org.jboss.resteasy.spi.BadRequestException; import com.google.inject.Inject; import com.google.inject.persist.Transactional; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xnap.commons.i18n.I18n; import java.util.Date; import java.util.List; /** * HealEntireOrgJob */ public class HealEntireOrgJob extends UniqueByEntityJob { private static Logger log = LoggerFactory.getLogger(HealEntireOrgJob.class); protected static String prefix = "heal_entire_org_"; protected OwnerCurator ownerCurator; protected Entitler entitler; protected ConsumerCurator consumerCurator; private I18n i18n; @Inject public HealEntireOrgJob(Entitler e, ConsumerCurator c, OwnerCurator o, I18n i18n) { this.entitler = e; this.consumerCurator = c; this.ownerCurator = o; this.i18n = i18n; } @Override public void toExecute(JobExecutionContext ctx) throws JobExecutionException { try { // NOTE: ownerId is actually the owner key here. JobDataMap map = ctx.getMergedJobDataMap(); String ownerId = (String) map.get("ownerId"); Owner owner = ownerCurator.lookupByKey(ownerId); if (owner.autobindDisabled()) { throw new BadRequestException(i18n.tr("Auto-attach is disabled for owner {0}.", owner.getKey())); } Date entitleDate = (Date) map.get("entitle_date"); for (String uuid : ownerCurator.getConsumerUuids(owner).list()) { // Do not send in product IDs. CandlepinPoolManager will take care // of looking up the non or partially compliant products to bind. try { Consumer consumer = consumerCurator.getConsumer(uuid); healSingleConsumer(consumer, entitleDate); } // We want to catch everything and continue. // Perhaps add something to surface errors later catch (Exception e) { log.debug("Healing failed for UUID \"{}\" with message: {}", uuid, e.getMessage()); } } } catch (Exception e) { log.error("EntitlerJob encountered a problem.", e); ctx.setResult(e.getMessage()); throw new JobExecutionException(e.getMessage(), e, false); } } /* * Each consumer heal should be a separate transaction */ @Transactional private void healSingleConsumer(Consumer consumer, Date date) throws AutobindDisabledForOwnerException { List<Entitlement> ents = entitler.bindByProducts(AutobindData.create(consumer).on(date), true); entitler.sendEvents(ents); } public static JobDetail healEntireOrg(String ownerId, Date entitleDate) { JobDataMap map = new JobDataMap(); map.put("ownerId", ownerId); map.put(JobStatus.OWNER_ID, ownerId); map.put(JobStatus.TARGET_TYPE, JobStatus.TargetType.OWNER); map.put(JobStatus.TARGET_ID, ownerId); map.put("entitle_date", entitleDate); map.put(JobStatus.CORRELATION_ID, MDC.get(LoggingFilter.CSID)); JobDetail detail = newJob(HealEntireOrgJob.class) .withIdentity("heal_entire_org_" + Util.generateUUID()) .usingJobData(map) .storeDurably(true) //required if we have to postpone the job .build(); return detail; } }