package org.ovirt.engine.core.bll.scheduling; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Singleton; import org.ovirt.engine.core.bll.interfaces.BackendInternal; import org.ovirt.engine.core.bll.job.ExecutionHandler; import org.ovirt.engine.core.bll.scheduling.arem.AffinityRulesEnforcer; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.BackendService; import org.ovirt.engine.core.common.action.MigrateVmParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableImpl; import org.ovirt.engine.core.dao.ClusterDao; import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation; import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton public class AffinityRulesEnforcementManager implements BackendService { protected Logger log = LoggerFactory.getLogger(getClass()); @Inject private AuditLogDirector auditLogDirector; @Inject private ClusterDao clusterDao; @Inject private AffinityRulesEnforcer rulesEnforcer; @Inject private BackendInternal backend; @Inject private SchedulerUtilQuartzImpl scheduler; @PostConstruct protected void wakeup() { auditLogDirector.log(new AuditLogableImpl(), AuditLogType.AFFINITY_RULES_ENFORCEMENT_MANAGER_START); scheduleJobs(getRegularInterval(), getInitialInterval()); } private Integer getInitialInterval() { return Config.<Integer>getValue(ConfigValues.AffinityRulesEnforcementManagerInitialDelay); } /** * Regular interval is used when the manager is migrating VMs and enforcing affinity rules. * * @return - The regular interval from the ConfigValues. */ private Integer getRegularInterval() { return Config.<Integer>getValue(ConfigValues.AffinityRulesEnforcementManagerRegularInterval); } /** * refresh method is called each interval of AffinityRulesEnforcementManager. It will try to find a broken affinity rule, choose a VM then, migrate it in order * to fix the breakage. */ @OnTimerMethodAnnotation("refresh") public void refresh() { log.debug("Affinity Rules Enforcement Manager interval reached."); final List<VM> vmCandidates = new ArrayList<>(); for (Cluster cluster : clusterDao.getWithoutMigratingVms()) { if (!cluster.isInUpgradeMode()) { final VM candidate = rulesEnforcer.chooseNextVmToMigrate(cluster); if (candidate != null) { vmCandidates.add(candidate); } } } // Trigger migrations for (VM vm : vmCandidates) { migrateVM(vm); } } protected void migrateVM(final VM vmToMigrate) { MigrateVmParameters parameters = new MigrateVmParameters(false, vmToMigrate.getId()); parameters.setReason(AuditLogDirector.getMessage( AuditLogType.MIGRATION_REASON_AFFINITY_ENFORCEMENT)); backend.runInternalAction(VdcActionType.BalanceVm, parameters, ExecutionHandler.createInternalJobContext()); } private void scheduleJobs(long regularInterval, long initialInterval) { scheduler.scheduleAFixedDelayJob( this, "refresh", new Class[] {}, new Object[] {}, initialInterval, regularInterval, TimeUnit.MINUTES); } }