proxmox-backup-proxy: add task archive rotation
this starts a task once a day at "00:00" that rotates the task log archive if it is bigger than 500k if we want, we can make the schedule/size limit/etc. configurable, but for now it's ok to set fixed values for that Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
c386b06fc6
commit
9a76091785
@ -198,6 +198,7 @@ async fn schedule_tasks() -> Result<(), Error> {
|
|||||||
schedule_datastore_prune().await;
|
schedule_datastore_prune().await;
|
||||||
schedule_datastore_verification().await;
|
schedule_datastore_verification().await;
|
||||||
schedule_datastore_sync_jobs().await;
|
schedule_datastore_sync_jobs().await;
|
||||||
|
schedule_task_log_rotate().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -655,6 +656,101 @@ async fn schedule_datastore_sync_jobs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn schedule_task_log_rotate() {
|
||||||
|
use proxmox_backup::{
|
||||||
|
config::jobstate::{self, Job},
|
||||||
|
server::rotate_task_log_archive,
|
||||||
|
};
|
||||||
|
use proxmox_backup::server::WorkerTask;
|
||||||
|
use proxmox_backup::tools::systemd::time::{
|
||||||
|
parse_calendar_event, compute_next_event};
|
||||||
|
|
||||||
|
let worker_type = "logrotate";
|
||||||
|
let job_id = "task-archive";
|
||||||
|
|
||||||
|
let last = match jobstate::last_run_time(worker_type, job_id) {
|
||||||
|
Ok(time) => time,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("could not get last run time of task log archive rotation: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// schedule daily at 00:00 like normal logrotate
|
||||||
|
let schedule = "00:00";
|
||||||
|
|
||||||
|
let event = match parse_calendar_event(schedule) {
|
||||||
|
Ok(event) => event,
|
||||||
|
Err(err) => {
|
||||||
|
// should not happen?
|
||||||
|
eprintln!("unable to parse schedule '{}' - {}", schedule, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let next = match compute_next_event(&event, last, false) {
|
||||||
|
Ok(Some(next)) => next,
|
||||||
|
Ok(None) => return,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("compute_next_event for '{}' failed - {}", schedule, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let now = proxmox::tools::time::epoch_i64();
|
||||||
|
|
||||||
|
if next > now {
|
||||||
|
// if we never ran the rotation, schedule instantly
|
||||||
|
match jobstate::JobState::load(worker_type, job_id) {
|
||||||
|
Ok(state) => match state {
|
||||||
|
jobstate::JobState::Created { .. } => {},
|
||||||
|
_ => return,
|
||||||
|
},
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut job = match Job::new(worker_type, job_id) {
|
||||||
|
Ok(job) => job,
|
||||||
|
Err(_) => return, // could not get lock
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(err) = WorkerTask::new_thread(
|
||||||
|
worker_type,
|
||||||
|
Some(job_id.to_string()),
|
||||||
|
Userid::backup_userid().clone(),
|
||||||
|
false,
|
||||||
|
move |worker| {
|
||||||
|
job.start(&worker.upid().to_string())?;
|
||||||
|
worker.log(format!("starting task log rotation"));
|
||||||
|
// one entry has normally about ~100-150 bytes
|
||||||
|
let max_size = 500000; // at least 5000 entries
|
||||||
|
let max_files = 20; // at least 100000 entries
|
||||||
|
let result = try_block!({
|
||||||
|
let has_rotated = rotate_task_log_archive(max_size, true, Some(max_files))?;
|
||||||
|
if has_rotated {
|
||||||
|
worker.log(format!("task log archive was rotated"));
|
||||||
|
} else {
|
||||||
|
worker.log(format!("task log archive was not rotated"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
let status = worker.create_state(&result);
|
||||||
|
|
||||||
|
if let Err(err) = job.finish(status) {
|
||||||
|
eprintln!("could not finish job state for {}: {}", worker_type, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
eprintln!("unable to start task log rotation: {}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
async fn run_stat_generator() {
|
async fn run_stat_generator() {
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::path::Path;
|
||||||
use std::io::{Read, Write, BufRead, BufReader};
|
use std::io::{Read, Write, BufRead, BufReader};
|
||||||
use std::panic::UnwindSafe;
|
use std::panic::UnwindSafe;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
@ -339,6 +340,27 @@ fn lock_task_list_files(exclusive: bool) -> Result<std::fs::File, Error> {
|
|||||||
Ok(lock)
|
Ok(lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// checks if the Task Archive is bigger that 'size_threshold' bytes, and
|
||||||
|
/// rotates it if it is
|
||||||
|
pub fn rotate_task_log_archive(size_threshold: u64, compress: bool, max_files: Option<usize>) -> Result<bool, Error> {
|
||||||
|
let _lock = lock_task_list_files(true)?;
|
||||||
|
let path = Path::new(PROXMOX_BACKUP_ARCHIVE_TASK_FN);
|
||||||
|
let metadata = path.metadata()?;
|
||||||
|
if metadata.len() > size_threshold {
|
||||||
|
let mut logrotate = LogRotate::new(PROXMOX_BACKUP_ARCHIVE_TASK_FN, compress).ok_or_else(|| format_err!("could not get archive file names"))?;
|
||||||
|
let backup_user = crate::backup::backup_user()?;
|
||||||
|
logrotate.rotate(
|
||||||
|
CreateOptions::new()
|
||||||
|
.owner(backup_user.uid)
|
||||||
|
.group(backup_user.gid),
|
||||||
|
max_files,
|
||||||
|
)?;
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// atomically read/update the task list, update status of finished tasks
|
// atomically read/update the task list, update status of finished tasks
|
||||||
// new_upid is added to the list when specified.
|
// new_upid is added to the list when specified.
|
||||||
fn update_active_workers(new_upid: Option<&UPID>) -> Result<(), Error> {
|
fn update_active_workers(new_upid: Option<&UPID>) -> Result<(), Error> {
|
||||||
|
Loading…
Reference in New Issue
Block a user