package org.ovirt.engine.core.bll; import java.util.Calendar; import java.util.Date; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Singleton; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.BackendService; import org.ovirt.engine.core.common.businessentities.EngineBackupLog; 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.AuditLogable; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableImpl; import org.ovirt.engine.core.dao.EngineBackupLogDao; import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation; import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Responsible for checking that a warm backup is available * raise alerts for no backup or too old backup. */ @Singleton public class EngineBackupAwarenessManager implements BackendService { @Inject private SchedulerUtilQuartzImpl schedulerUtil; private enum BackupScope { DB("db"), FILES("files"); String name; BackupScope(String name) { this.name = name; } public String getName() { return name; } } private static final Logger log = LoggerFactory.getLogger(EngineBackupAwarenessManager.class); private Lock lock = new ReentrantLock(); @Inject private AuditLogDirector auditLogDirector; @Inject private EngineBackupLogDao engineBackupLogDao; /** * Initializes the backup h Check Manager */ @PostConstruct private void initialize() { log.info("Start initializing {}", getClass().getSimpleName()); Integer backupCheckPeriodInHours = Config.<Integer>getValue(ConfigValues.BackupCheckPeriodInHours); // disable feature if value is negative if (backupCheckPeriodInHours > 0) { schedulerUtil.scheduleAFixedDelayJob(this, "backupCheck", new Class[] {}, new Object[] {}, backupCheckPeriodInHours, backupCheckPeriodInHours, TimeUnit.HOURS); log.info("Finished initializing {}", getClass().getSimpleName()); } } @OnTimerMethodAnnotation("backupCheck") public void backupCheck() { // skip backup check if previous operation is not completed yet if (lock.tryLock()) { try { log.info("Backup check started."); doBackupCheck(); log.info("Backup check completed."); } finally { lock.unlock(); } } } private void doBackupCheck() { AuditLogable alert = new AuditLogableImpl(); //try to get last backup record EngineBackupLog lastDbBackup = getLastBackupByScope(BackupScope.DB); EngineBackupLog lastFilesBackup = getLastBackupByScope(BackupScope.FILES); if (lastDbBackup == null || lastFilesBackup == null) { auditLogDirector.log(alert, AuditLogType.ENGINE_NO_FULL_BACKUP); } else { //check time elapsed from last full (db and files) backup Integer backupAlertPeriodInDays = Config.<Integer>getValue(ConfigValues.BackupAlertPeriodInDays); Date lastDbBackupDate = lastDbBackup.getDoneAt(); Date lastFilesBackupDate = lastFilesBackup.getDoneAt(); Date lastFullBackupDate = lastDbBackupDate.compareTo(lastFilesBackupDate) < 0 ? lastDbBackupDate : lastFilesBackupDate; long diffInDays = (Calendar.getInstance().getTimeInMillis() - lastFullBackupDate.getTime()) / TimeUnit.DAYS.toMillis(1); if (diffInDays > backupAlertPeriodInDays) { alert.addCustomValue("Date", lastFullBackupDate.toString()); auditLogDirector.log(alert, AuditLogType.ENGINE_NO_WARM_BACKUP); } } } private EngineBackupLog getLastBackupByScope(BackupScope scope) { return engineBackupLogDao.getLastSuccessfulEngineBackup(scope.getName()); } }