server: rustfmt

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2022-04-14 14:01:25 +02:00
parent dc7a5b3491
commit ee0ea73500
9 changed files with 188 additions and 189 deletions

View File

@ -4,10 +4,10 @@ use anyhow::format_err;
use proxmox_router::UserInformation; use proxmox_router::UserInformation;
use pbs_tools::ticket::{self, Ticket};
use pbs_config::{token_shadow, CachedUserInfo};
use pbs_api_types::{Authid, Userid}; use pbs_api_types::{Authid, Userid};
use proxmox_rest_server::{AuthError, extract_cookie}; use pbs_config::{token_shadow, CachedUserInfo};
use pbs_tools::ticket::{self, Ticket};
use proxmox_rest_server::{extract_cookie, AuthError};
use crate::auth_helpers::*; use crate::auth_helpers::*;
@ -53,7 +53,6 @@ pub async fn check_pbs_auth(
headers: &http::HeaderMap, headers: &http::HeaderMap,
method: &hyper::Method, method: &hyper::Method,
) -> Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError> { ) -> Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError> {
// fixme: make all IO async // fixme: make all IO async
let user_info = CachedUserInfo::new()?; let user_info = CachedUserInfo::new()?;

View File

@ -1,16 +1,17 @@
use anyhow::Error; use anyhow::Error;
use serde_json::json; use serde_json::json;
use handlebars::{Handlebars, Helper, Context, RenderError, RenderContext, Output, HelperResult, TemplateError}; use handlebars::{
Context, Handlebars, Helper, HelperResult, Output, RenderContext, RenderError, TemplateError,
};
use proxmox_sys::email::sendmail;
use proxmox_lang::try_block; use proxmox_lang::try_block;
use proxmox_schema::ApiType; use proxmox_schema::ApiType;
use proxmox_sys::email::sendmail;
use pbs_api_types::{ use pbs_api_types::{
User, TapeBackupJobSetup, SyncJobConfig, VerificationJobConfig, APTUpdateInfo, DataStoreConfig, DatastoreNotify, GarbageCollectionStatus, HumanByte, Notify,
APTUpdateInfo, GarbageCollectionStatus, HumanByte, SyncJobConfig, TapeBackupJobSetup, User, Userid, VerificationJobConfig,
Userid, Notify, DatastoreNotify, DataStoreConfig,
}; };
const GC_OK_TEMPLATE: &str = r###" const GC_OK_TEMPLATE: &str = r###"
@ -41,7 +42,6 @@ Please visit the web interface for further details:
"###; "###;
const GC_ERR_TEMPLATE: &str = r###" const GC_ERR_TEMPLATE: &str = r###"
Datastore: {{datastore}} Datastore: {{datastore}}
@ -183,7 +183,7 @@ Please visit the web interface for further details:
"###; "###;
lazy_static::lazy_static!{ lazy_static::lazy_static! {
static ref HANDLEBARS: Handlebars<'static> = { static ref HANDLEBARS: Handlebars<'static> = {
let mut hb = Handlebars::new(); let mut hb = Handlebars::new();
@ -229,18 +229,16 @@ pub struct TapeBackupJobSummary {
pub duration: std::time::Duration, pub duration: std::time::Duration,
} }
fn send_job_status_mail( fn send_job_status_mail(email: &str, subject: &str, text: &str) -> Result<(), Error> {
email: &str,
subject: &str,
text: &str,
) -> Result<(), Error> {
let (config, _) = crate::config::node::config()?; let (config, _) = crate::config::node::config()?;
let from = config.email_from; let from = config.email_from;
// Note: OX has serious problems displaying text mails, // Note: OX has serious problems displaying text mails,
// so we include html as well // so we include html as well
let html = format!("<html><body><pre>\n{}\n<pre>", handlebars::html_escape(text)); let html = format!(
"<html><body><pre>\n{}\n<pre>",
handlebars::html_escape(text)
);
let nodename = proxmox_sys::nodename(); let nodename = proxmox_sys::nodename();
@ -265,9 +263,8 @@ pub fn send_gc_status(
status: &GarbageCollectionStatus, status: &GarbageCollectionStatus,
result: &Result<(), Error>, result: &Result<(), Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
match notify.gc { match notify.gc {
None => { /* send notifications by default */ }, None => { /* send notifications by default */ }
Some(notify) => { Some(notify) => {
if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) { if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
return Ok(()); return Ok(());
@ -285,7 +282,7 @@ pub fn send_gc_status(
let text = match result { let text = match result {
Ok(()) => { Ok(()) => {
let deduplication_factor = if status.disk_bytes > 0 { let deduplication_factor = if status.disk_bytes > 0 {
(status.index_data_bytes as f64)/(status.disk_bytes as f64) (status.index_data_bytes as f64) / (status.disk_bytes as f64)
} else { } else {
1.0 1.0
}; };
@ -302,14 +299,8 @@ pub fn send_gc_status(
}; };
let subject = match result { let subject = match result {
Ok(()) => format!( Ok(()) => format!("Garbage Collect Datastore '{}' successful", datastore,),
"Garbage Collect Datastore '{}' successful", Err(_) => format!("Garbage Collect Datastore '{}' failed", datastore,),
datastore,
),
Err(_) => format!(
"Garbage Collect Datastore '{}' failed",
datastore,
),
}; };
send_job_status_mail(email, &subject, &text)?; send_job_status_mail(email, &subject, &text)?;
@ -323,7 +314,6 @@ pub fn send_verify_status(
job: VerificationJobConfig, job: VerificationJobConfig,
result: &Result<Vec<String>, Error>, result: &Result<Vec<String>, Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let (fqdn, port) = get_server_url(); let (fqdn, port) = get_server_url();
let mut data = json!({ let mut data = json!({
"job": job, "job": job,
@ -349,7 +339,7 @@ pub fn send_verify_status(
}; };
match notify.verify { match notify.verify {
None => { /* send notifications by default */ }, None => { /* send notifications by default */ }
Some(notify) => { Some(notify) => {
if notify == Notify::Never || (result_is_ok && notify == Notify::Error) { if notify == Notify::Never || (result_is_ok && notify == Notify::Error) {
return Ok(()); return Ok(());
@ -358,14 +348,8 @@ pub fn send_verify_status(
} }
let subject = match result { let subject = match result {
Ok(errors) if errors.is_empty() => format!( Ok(errors) if errors.is_empty() => format!("Verify Datastore '{}' successful", job.store,),
"Verify Datastore '{}' successful", _ => format!("Verify Datastore '{}' failed", job.store,),
job.store,
),
_ => format!(
"Verify Datastore '{}' failed",
job.store,
),
}; };
send_job_status_mail(email, &subject, &text)?; send_job_status_mail(email, &subject, &text)?;
@ -379,9 +363,8 @@ pub fn send_sync_status(
job: &SyncJobConfig, job: &SyncJobConfig,
result: &Result<(), Error>, result: &Result<(), Error>,
) -> Result<(), Error> { ) -> Result<(), Error> {
match notify.sync { match notify.sync {
None => { /* send notifications by default */ }, None => { /* send notifications by default */ }
Some(notify) => { Some(notify) => {
if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) { if notify == Notify::Never || (result.is_ok() && notify == Notify::Error) {
return Ok(()); return Ok(());
@ -397,9 +380,7 @@ pub fn send_sync_status(
}); });
let text = match result { let text = match result {
Ok(()) => { Ok(()) => HANDLEBARS.render("sync_ok_template", &data)?,
HANDLEBARS.render("sync_ok_template", &data)?
}
Err(err) => { Err(err) => {
data["error"] = err.to_string().into(); data["error"] = err.to_string().into();
HANDLEBARS.render("sync_err_template", &data)? HANDLEBARS.render("sync_err_template", &data)?
@ -409,13 +390,11 @@ pub fn send_sync_status(
let subject = match result { let subject = match result {
Ok(()) => format!( Ok(()) => format!(
"Sync remote '{}' datastore '{}' successful", "Sync remote '{}' datastore '{}' successful",
job.remote, job.remote, job.remote_store,
job.remote_store,
), ),
Err(_) => format!( Err(_) => format!(
"Sync remote '{}' datastore '{}' failed", "Sync remote '{}' datastore '{}' failed",
job.remote, job.remote, job.remote_store,
job.remote_store,
), ),
}; };
@ -431,7 +410,6 @@ pub fn send_tape_backup_status(
result: &Result<(), Error>, result: &Result<(), Error>,
summary: TapeBackupJobSummary, summary: TapeBackupJobSummary,
) -> Result<(), Error> { ) -> Result<(), Error> {
let (fqdn, port) = get_server_url(); let (fqdn, port) = get_server_url();
let duration: proxmox_time::TimeSpan = summary.duration.into(); let duration: proxmox_time::TimeSpan = summary.duration.into();
let mut data = json!({ let mut data = json!({
@ -444,9 +422,7 @@ pub fn send_tape_backup_status(
}); });
let text = match result { let text = match result {
Ok(()) => { Ok(()) => HANDLEBARS.render("tape_backup_ok_template", &data)?,
HANDLEBARS.render("tape_backup_ok_template", &data)?
}
Err(err) => { Err(err) => {
data["error"] = err.to_string().into(); data["error"] = err.to_string().into();
HANDLEBARS.render("tape_backup_err_template", &data)? HANDLEBARS.render("tape_backup_err_template", &data)?
@ -454,24 +430,10 @@ pub fn send_tape_backup_status(
}; };
let subject = match (result, id) { let subject = match (result, id) {
(Ok(()), Some(id)) => format!( (Ok(()), Some(id)) => format!("Tape Backup '{}' datastore '{}' successful", id, job.store,),
"Tape Backup '{}' datastore '{}' successful", (Ok(()), None) => format!("Tape Backup datastore '{}' successful", job.store,),
id, (Err(_), Some(id)) => format!("Tape Backup '{}' datastore '{}' failed", id, job.store,),
job.store, (Err(_), None) => format!("Tape Backup datastore '{}' failed", job.store,),
),
(Ok(()), None) => format!(
"Tape Backup datastore '{}' successful",
job.store,
),
(Err(_), Some(id)) => format!(
"Tape Backup '{}' datastore '{}' failed",
id,
job.store,
),
(Err(_), None) => format!(
"Tape Backup datastore '{}' failed",
job.store,
),
}; };
send_job_status_mail(email, &subject, &text)?; send_job_status_mail(email, &subject, &text)?;
@ -486,13 +448,15 @@ pub fn send_load_media_email(
to: &str, to: &str,
reason: Option<String>, reason: Option<String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let subject = format!("Load Media '{}' request for drive '{}'", label_text, drive); let subject = format!("Load Media '{}' request for drive '{}'", label_text, drive);
let mut text = String::new(); let mut text = String::new();
if let Some(reason) = reason { if let Some(reason) = reason {
text.push_str(&format!("The drive has the wrong or no tape inserted. Error:\n{}\n\n", reason)); text.push_str(&format!(
"The drive has the wrong or no tape inserted. Error:\n{}\n\n",
reason
));
} }
text.push_str("Please insert the requested media into the backup drive.\n\n"); text.push_str("Please insert the requested media into the backup drive.\n\n");
@ -504,7 +468,6 @@ pub fn send_load_media_email(
} }
fn get_server_url() -> (String, usize) { fn get_server_url() -> (String, usize) {
// user will surely request that they can change this // user will surely request that they can change this
let nodename = proxmox_sys::nodename(); let nodename = proxmox_sys::nodename();
@ -522,9 +485,7 @@ fn get_server_url() -> (String, usize) {
(fqdn, port) (fqdn, port)
} }
pub fn send_updates_available( pub fn send_updates_available(updates: &[&APTUpdateInfo]) -> Result<(), Error> {
updates: &[&APTUpdateInfo],
) -> Result<(), Error> {
// update mails always go to the root@pam configured email.. // update mails always go to the root@pam configured email..
if let Some(email) = lookup_user_email(Userid::root_userid()) { if let Some(email) = lookup_user_email(Userid::root_userid()) {
let nodename = proxmox_sys::nodename(); let nodename = proxmox_sys::nodename();
@ -532,11 +493,14 @@ pub fn send_updates_available(
let (fqdn, port) = get_server_url(); let (fqdn, port) = get_server_url();
let text = HANDLEBARS.render("package_update_template", &json!({ let text = HANDLEBARS.render(
"package_update_template",
&json!({
"fqdn": fqdn, "fqdn": fqdn,
"port": port, "port": port,
"updates": updates, "updates": updates,
}))?; }),
)?;
send_job_status_mail(&email, &subject, &text)?; send_job_status_mail(&email, &subject, &text)?;
} }
@ -545,7 +509,6 @@ pub fn send_updates_available(
/// Lookup users email address /// Lookup users email address
pub fn lookup_user_email(userid: &Userid) -> Option<String> { pub fn lookup_user_email(userid: &Userid) -> Option<String> {
if let Ok(user_config) = pbs_config::user::cached_config() { if let Ok(user_config) = pbs_config::user::cached_config() {
if let Ok(user) = user_config.lookup::<User>("user", userid.as_str()) { if let Ok(user) = user_config.lookup::<User>("user", userid.as_str()) {
return user.email; return user.email;
@ -556,13 +519,14 @@ pub fn lookup_user_email(userid: &Userid) -> Option<String> {
} }
/// Lookup Datastore notify settings /// Lookup Datastore notify settings
pub fn lookup_datastore_notify_settings( pub fn lookup_datastore_notify_settings(store: &str) -> (Option<String>, DatastoreNotify) {
store: &str,
) -> (Option<String>, DatastoreNotify) {
let mut email = None; let mut email = None;
let notify = DatastoreNotify { gc: None, verify: None, sync: None }; let notify = DatastoreNotify {
gc: None,
verify: None,
sync: None,
};
let (config, _digest) = match pbs_config::datastore::config() { let (config, _digest) = match pbs_config::datastore::config() {
Ok(result) => result, Ok(result) => result,
@ -597,9 +561,11 @@ fn handlebars_humam_bytes_helper(
_: &Handlebars, _: &Handlebars,
_: &Context, _: &Context,
_rc: &mut RenderContext, _rc: &mut RenderContext,
out: &mut dyn Output out: &mut dyn Output,
) -> HelperResult { ) -> HelperResult {
let param = h.param(0).map(|v| v.value().as_u64()) let param = h
.param(0)
.map(|v| v.value().as_u64())
.flatten() .flatten()
.ok_or_else(|| RenderError::new("human-bytes: param not found"))?; .ok_or_else(|| RenderError::new("human-bytes: param not found"))?;
@ -613,19 +579,23 @@ fn handlebars_relative_percentage_helper(
_: &Handlebars, _: &Handlebars,
_: &Context, _: &Context,
_rc: &mut RenderContext, _rc: &mut RenderContext,
out: &mut dyn Output out: &mut dyn Output,
) -> HelperResult { ) -> HelperResult {
let param0 = h.param(0).map(|v| v.value().as_f64()) let param0 = h
.param(0)
.map(|v| v.value().as_f64())
.flatten() .flatten()
.ok_or_else(|| RenderError::new("relative-percentage: param0 not found"))?; .ok_or_else(|| RenderError::new("relative-percentage: param0 not found"))?;
let param1 = h.param(1).map(|v| v.value().as_f64()) let param1 = h
.param(1)
.map(|v| v.value().as_f64())
.flatten() .flatten()
.ok_or_else(|| RenderError::new("relative-percentage: param1 not found"))?; .ok_or_else(|| RenderError::new("relative-percentage: param1 not found"))?;
if param1 == 0.0 { if param1 == 0.0 {
out.write("-")?; out.write("-")?;
} else { } else {
out.write(&format!("{:.2}%", (param0*100.0)/param1))?; out.write(&format!("{:.2}%", (param0 * 100.0) / param1))?;
} }
Ok(()) Ok(())
} }

View File

@ -1,5 +1,5 @@
use std::sync::Arc;
use anyhow::Error; use anyhow::Error;
use std::sync::Arc;
use proxmox_sys::task_log; use proxmox_sys::task_log;
@ -17,7 +17,6 @@ pub fn do_garbage_collection_job(
schedule: Option<String>, schedule: Option<String>,
to_stdout: bool, to_stdout: bool,
) -> Result<String, Error> { ) -> Result<String, Error> {
let store = datastore.name().to_string(); let store = datastore.name().to_string();
let (email, notify) = crate::server::lookup_datastore_notify_settings(&store); let (email, notify) = crate::server::lookup_datastore_notify_settings(&store);
@ -50,13 +49,15 @@ pub fn do_garbage_collection_job(
if let Some(email) = email { if let Some(email) = email {
let gc_status = datastore.last_gc_status(); let gc_status = datastore.last_gc_status();
if let Err(err) = crate::server::send_gc_status(&email, notify, &store, &gc_status, &result) { if let Err(err) =
crate::server::send_gc_status(&email, notify, &store, &gc_status, &result)
{
eprintln!("send gc notification failed: {}", err); eprintln!("send gc notification failed: {}", err);
} }
} }
result result
} },
)?; )?;
Ok(upid_str) Ok(upid_str)

View File

@ -42,15 +42,13 @@ use std::path::{Path, PathBuf};
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use proxmox_sys::fs::{ use proxmox_sys::fs::{create_path, file_read_optional_string, replace_file, CreateOptions};
create_path, file_read_optional_string, replace_file, CreateOptions,
};
use proxmox_time::CalendarEvent; use proxmox_time::CalendarEvent;
use pbs_api_types::{JobScheduleStatus, UPID};
use pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M; use pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M;
use pbs_config::{open_backup_lockfile, BackupLockGuard}; use pbs_config::{open_backup_lockfile, BackupLockGuard};
use pbs_api_types::{UPID, JobScheduleStatus};
use proxmox_rest_server::{upid_read_status, worker_is_active_local, TaskState}; use proxmox_rest_server::{upid_read_status, worker_is_active_local, TaskState};

View File

@ -37,7 +37,8 @@ pub mod pull;
pub(crate) async fn reload_proxy_certificate() -> Result<(), Error> { pub(crate) async fn reload_proxy_certificate() -> Result<(), Error> {
let proxy_pid = proxmox_rest_server::read_pid(pbs_buildcfg::PROXMOX_BACKUP_PROXY_PID_FN)?; let proxy_pid = proxmox_rest_server::read_pid(pbs_buildcfg::PROXMOX_BACKUP_PROXY_PID_FN)?;
let sock = proxmox_rest_server::ctrl_sock_from_pid(proxy_pid); let sock = proxmox_rest_server::ctrl_sock_from_pid(proxy_pid);
let _: Value = proxmox_rest_server::send_raw_command(sock, "{\"command\":\"reload-certificate\"}\n") let _: Value =
proxmox_rest_server::send_raw_command(sock, "{\"command\":\"reload-certificate\"}\n")
.await?; .await?;
Ok(()) Ok(())
} }
@ -45,7 +46,8 @@ pub(crate) async fn reload_proxy_certificate() -> Result<(), Error> {
pub(crate) async fn notify_datastore_removed() -> Result<(), Error> { pub(crate) async fn notify_datastore_removed() -> Result<(), Error> {
let proxy_pid = proxmox_rest_server::read_pid(pbs_buildcfg::PROXMOX_BACKUP_PROXY_PID_FN)?; let proxy_pid = proxmox_rest_server::read_pid(pbs_buildcfg::PROXMOX_BACKUP_PROXY_PID_FN)?;
let sock = proxmox_rest_server::ctrl_sock_from_pid(proxy_pid); let sock = proxmox_rest_server::ctrl_sock_from_pid(proxy_pid);
let _: Value = proxmox_rest_server::send_raw_command(sock, "{\"command\":\"datastore-removed\"}\n") let _: Value =
proxmox_rest_server::send_raw_command(sock, "{\"command\":\"datastore-removed\"}\n")
.await?; .await?;
Ok(()) Ok(())
} }
@ -68,7 +70,11 @@ pub fn create_state_dir() -> Result<(), Error> {
let opts = CreateOptions::new() let opts = CreateOptions::new()
.owner(backup_user.uid) .owner(backup_user.uid)
.group(backup_user.gid); .group(backup_user.gid);
create_path(pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M!(), None, Some(opts))?; create_path(
pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M!(),
None,
Some(opts),
)?;
Ok(()) Ok(())
} }

View File

@ -4,11 +4,11 @@ use anyhow::Error;
use proxmox_sys::{task_log, task_warn}; use proxmox_sys::{task_log, task_warn};
use pbs_api_types::{Authid, Operation, PruneOptions, PRIV_DATASTORE_MODIFY};
use pbs_config::CachedUserInfo;
use pbs_datastore::backup_info::BackupInfo; use pbs_datastore::backup_info::BackupInfo;
use pbs_datastore::prune::compute_prune_info; use pbs_datastore::prune::compute_prune_info;
use pbs_datastore::DataStore; use pbs_datastore::DataStore;
use pbs_api_types::{Authid, Operation, PRIV_DATASTORE_MODIFY, PruneOptions};
use pbs_config::CachedUserInfo;
use proxmox_rest_server::WorkerTask; use proxmox_rest_server::WorkerTask;
use crate::server::jobstate::Job; use crate::server::jobstate::Job;
@ -113,7 +113,14 @@ pub fn do_prune_job(
task_log!(worker, "task triggered by schedule '{}'", event_str); task_log!(worker, "task triggered by schedule '{}'", event_str);
} }
let result = prune_datastore(worker.clone(), auth_id, prune_options, &store, datastore, false); let result = prune_datastore(
worker.clone(),
auth_id,
prune_options,
&store,
datastore,
false,
);
let status = worker.create_state(&result); let status = worker.create_state(&result);

View File

@ -8,27 +8,28 @@ use std::sync::{Arc, Mutex};
use std::time::SystemTime; use std::time::SystemTime;
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Error};
use serde_json::json;
use http::StatusCode; use http::StatusCode;
use serde_json::json;
use proxmox_router::HttpError; use proxmox_router::HttpError;
use proxmox_sys::task_log; use proxmox_sys::task_log;
use pbs_api_types::{ use pbs_api_types::{
Authid, GroupFilter, GroupListItem, RateLimitConfig, Remote, Authid, GroupFilter, GroupListItem, Operation, RateLimitConfig, Remote, SnapshotListItem,
Operation, SnapshotListItem,
}; };
use pbs_datastore::{BackupDir, BackupInfo, BackupGroup, DataStore, StoreProgress}; use pbs_client::{
BackupReader, BackupRepository, HttpClient, HttpClientOptions, RemoteChunkReader,
};
use pbs_datastore::data_blob::DataBlob; use pbs_datastore::data_blob::DataBlob;
use pbs_datastore::dynamic_index::DynamicIndexReader; use pbs_datastore::dynamic_index::DynamicIndexReader;
use pbs_datastore::fixed_index::FixedIndexReader; use pbs_datastore::fixed_index::FixedIndexReader;
use pbs_datastore::index::IndexFile; use pbs_datastore::index::IndexFile;
use pbs_datastore::manifest::{ use pbs_datastore::manifest::{
CLIENT_LOG_BLOB_NAME, MANIFEST_BLOB_NAME, ArchiveType, BackupManifest, FileInfo, archive_type archive_type, ArchiveType, BackupManifest, FileInfo, CLIENT_LOG_BLOB_NAME, MANIFEST_BLOB_NAME,
}; };
use pbs_datastore::{BackupDir, BackupGroup, BackupInfo, DataStore, StoreProgress};
use pbs_tools::sha::sha256; use pbs_tools::sha::sha256;
use pbs_client::{BackupReader, BackupRepository, HttpClient, HttpClientOptions, RemoteChunkReader};
use proxmox_rest_server::WorkerTask; use proxmox_rest_server::WorkerTask;
use crate::tools::parallel_handler::ParallelHandler; use crate::tools::parallel_handler::ParallelHandler;
@ -71,7 +72,15 @@ impl PullParameters {
remote_store.to_string(), remote_store.to_string(),
); );
Ok(Self { remote, source, store, owner, remove_vanished, group_filter, limit }) Ok(Self {
remote,
source,
store,
owner,
remove_vanished,
group_filter,
limit,
})
} }
pub async fn client(&self) -> Result<HttpClient, Error> { pub async fn client(&self) -> Result<HttpClient, Error> {
@ -495,7 +504,11 @@ pub async fn pull_snapshot_from(
downloaded_chunks, downloaded_chunks,
) )
.await?; .await?;
task_log!(worker, "re-sync snapshot {:?} done", snapshot.relative_path()); task_log!(
worker,
"re-sync snapshot {:?} done",
snapshot.relative_path()
);
} }
Ok(()) Ok(())
@ -524,13 +537,11 @@ impl SkipInfo {
match self.count { match self.count {
0 => Ok(String::new()), 0 => Ok(String::new()),
1 => Ok(proxmox_time::epoch_to_rfc3339_utc(self.oldest)?), 1 => Ok(proxmox_time::epoch_to_rfc3339_utc(self.oldest)?),
_ => { _ => Ok(format!(
Ok(format!(
"{} .. {}", "{} .. {}",
proxmox_time::epoch_to_rfc3339_utc(self.oldest)?, proxmox_time::epoch_to_rfc3339_utc(self.oldest)?,
proxmox_time::epoch_to_rfc3339_utc(self.newest)?, proxmox_time::epoch_to_rfc3339_utc(self.newest)?,
)) )),
}
} }
} }
} }
@ -553,7 +564,10 @@ pub async fn pull_group(
group: &BackupGroup, group: &BackupGroup,
progress: &mut StoreProgress, progress: &mut StoreProgress,
) -> Result<(), Error> { ) -> Result<(), Error> {
let path = format!("api2/json/admin/datastore/{}/snapshots", params.source.store()); let path = format!(
"api2/json/admin/datastore/{}/snapshots",
params.source.store()
);
let args = json!({ let args = json!({
"backup-type": group.backup_type(), "backup-type": group.backup_type(),
@ -589,7 +603,11 @@ pub async fn pull_group(
// in-progress backups can't be synced // in-progress backups can't be synced
if item.size.is_none() { if item.size.is_none() {
task_log!(worker, "skipping snapshot {} - in-progress backup", snapshot); task_log!(
worker,
"skipping snapshot {} - in-progress backup",
snapshot
);
continue; continue;
} }
@ -607,7 +625,8 @@ pub async fn pull_group(
// get updated auth_info (new tickets) // get updated auth_info (new tickets)
let auth_info = client.login().await?; let auth_info = client.login().await?;
let options = HttpClientOptions::new_non_interactive(auth_info.ticket.clone(), fingerprint.clone()) let options =
HttpClientOptions::new_non_interactive(auth_info.ticket.clone(), fingerprint.clone())
.rate_limit(params.limit.clone()); .rate_limit(params.limit.clone());
let new_client = HttpClient::new( let new_client = HttpClient::new(
@ -658,7 +677,11 @@ pub async fn pull_group(
); );
continue; continue;
} }
task_log!(worker, "delete vanished snapshot {:?}", info.backup_dir.relative_path()); task_log!(
worker,
"delete vanished snapshot {:?}",
info.backup_dir.relative_path()
);
params.store.remove_backup_dir(&info.backup_dir, false)?; params.store.remove_backup_dir(&info.backup_dir, false)?;
} }
} }
@ -698,25 +721,26 @@ pub async fn pull_store(
}); });
let apply_filters = |group: &BackupGroup, filters: &[GroupFilter]| -> bool { let apply_filters = |group: &BackupGroup, filters: &[GroupFilter]| -> bool {
filters filters.iter().any(|filter| group.matches(filter))
.iter()
.any(|filter| group.matches(filter))
}; };
let list:Vec<BackupGroup> = list let list: Vec<BackupGroup> = list
.into_iter() .into_iter()
.map(|item| BackupGroup::new(item.backup_type, item.backup_id)) .map(|item| BackupGroup::new(item.backup_type, item.backup_id))
.collect(); .collect();
let list = if let Some(ref group_filter) = &params.group_filter { let list = if let Some(ref group_filter) = &params.group_filter {
let unfiltered_count = list.len(); let unfiltered_count = list.len();
let list:Vec<BackupGroup> = list let list: Vec<BackupGroup> = list
.into_iter() .into_iter()
.filter(|group| { .filter(|group| apply_filters(group, group_filter))
apply_filters(group, group_filter)
})
.collect(); .collect();
task_log!(worker, "found {} groups to sync (out of {} total)", list.len(), unfiltered_count); task_log!(
worker,
"found {} groups to sync (out of {} total)",
list.len(),
unfiltered_count
);
list list
} else { } else {
task_log!(worker, "found {} groups to sync", total_count); task_log!(worker, "found {} groups to sync", total_count);
@ -737,13 +761,17 @@ pub async fn pull_store(
progress.done_snapshots = 0; progress.done_snapshots = 0;
progress.group_snapshots = 0; progress.group_snapshots = 0;
let (owner, _lock_guard) = match params.store.create_locked_backup_group(&group, &params.owner) { let (owner, _lock_guard) = match params
.store
.create_locked_backup_group(&group, &params.owner)
{
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
task_log!( task_log!(
worker, worker,
"sync group {} failed - group lock failed: {}", "sync group {} failed - group lock failed: {}",
&group, err &group,
err
); );
errors = true; // do not stop here, instead continue errors = true; // do not stop here, instead continue
continue; continue;
@ -756,23 +784,13 @@ pub async fn pull_store(
task_log!( task_log!(
worker, worker,
"sync group {} failed - owner check failed ({} != {})", "sync group {} failed - owner check failed ({} != {})",
&group, params.owner, owner &group,
params.owner,
owner
); );
errors = true; // do not stop here, instead continue errors = true; // do not stop here, instead continue
} else if let Err(err) = pull_group( } else if let Err(err) = pull_group(worker, client, params, &group, &mut progress).await {
worker, task_log!(worker, "sync group {} failed - {}", &group, err,);
client,
params,
&group,
&mut progress,
)
.await
{
task_log!(
worker,
"sync group {} failed - {}",
&group, err,
);
errors = true; // do not stop here, instead continue errors = true; // do not stop here, instead continue
} }
} }
@ -796,10 +814,14 @@ pub async fn pull_store(
local_group.backup_id() local_group.backup_id()
); );
match params.store.remove_backup_group(&local_group) { match params.store.remove_backup_group(&local_group) {
Ok(true) => {}, Ok(true) => {}
Ok(false) => { Ok(false) => {
task_log!(worker, "kept some protected snapshots of group '{}'", local_group); task_log!(
}, worker,
"kept some protected snapshots of group '{}'",
local_group
);
}
Err(err) => { Err(err) => {
task_log!(worker, "{}", err); task_log!(worker, "{}", err);
errors = true; errors = true;

View File

@ -35,8 +35,7 @@ fn commands() -> Vec<(&'static str, Vec<&'static str>)> {
type FunctionMapping = (&'static str, fn() -> String); type FunctionMapping = (&'static str, fn() -> String);
fn function_calls() -> Vec<FunctionMapping> { fn function_calls() -> Vec<FunctionMapping> {
vec![ vec![("Datastores", || {
("Datastores", || {
let config = match pbs_config::datastore::config() { let config = match pbs_config::datastore::config() {
Ok((config, _digest)) => config, Ok((config, _digest)) => config,
_ => return String::from("could not read datastore config"), _ => return String::from("could not read datastore config"),
@ -47,8 +46,7 @@ fn function_calls() -> Vec<FunctionMapping> {
list.push(store.as_str()); list.push(store.as_str());
} }
list.join(", ") list.join(", ")
}) })]
]
} }
pub fn generate_report() -> String { pub fn generate_report() -> String {

View File

@ -1,16 +1,13 @@
use anyhow::{format_err, Error}; use anyhow::{format_err, Error};
use proxmox_sys::task_log;
use pbs_api_types::{Authid, Operation, VerificationJobConfig}; use pbs_api_types::{Authid, Operation, VerificationJobConfig};
use proxmox_rest_server::WorkerTask;
use pbs_datastore::DataStore; use pbs_datastore::DataStore;
use proxmox_rest_server::WorkerTask;
use proxmox_sys::task_log;
use crate::{ use crate::{
backup::{verify_all_backups, verify_filter},
server::jobstate::Job, server::jobstate::Job,
backup::{
verify_filter,
verify_all_backups,
},
}; };
/// Runs a verification job. /// Runs a verification job.
@ -21,7 +18,6 @@ pub fn do_verification_job(
schedule: Option<String>, schedule: Option<String>,
to_stdout: bool, to_stdout: bool,
) -> Result<String, Error> { ) -> Result<String, Error> {
let datastore = DataStore::lookup_datastore(&verification_job.store, Some(Operation::Read))?; let datastore = DataStore::lookup_datastore(&verification_job.store, Some(Operation::Read))?;
let outdated_after = verification_job.outdated_after; let outdated_after = verification_job.outdated_after;
@ -29,9 +25,7 @@ pub fn do_verification_job(
let (email, notify) = crate::server::lookup_datastore_notify_settings(&verification_job.store); let (email, notify) = crate::server::lookup_datastore_notify_settings(&verification_job.store);
let job_id = format!("{}:{}", let job_id = format!("{}:{}", &verification_job.store, job.jobname());
&verification_job.store,
job.jobname());
let worker_type = job.jobtype().to_string(); let worker_type = job.jobtype().to_string();
let upid_str = WorkerTask::new_thread( let upid_str = WorkerTask::new_thread(
&worker_type, &worker_type,
@ -41,9 +35,9 @@ pub fn do_verification_job(
move |worker| { move |worker| {
job.start(&worker.upid().to_string())?; job.start(&worker.upid().to_string())?;
task_log!(worker,"Starting datastore verify job '{}'", job_id); task_log!(worker, "Starting datastore verify job '{}'", job_id);
if let Some(event_str) = schedule { if let Some(event_str) = schedule {
task_log!(worker,"task triggered by schedule '{}'", event_str); task_log!(worker, "task triggered by schedule '{}'", event_str);
} }
let verify_worker = crate::backup::VerifyWorker::new(worker.clone(), datastore); let verify_worker = crate::backup::VerifyWorker::new(worker.clone(), datastore);
@ -63,8 +57,10 @@ pub fn do_verification_job(
task_log!(worker, "\t{}", dir); task_log!(worker, "\t{}", dir);
} }
Err(format_err!("verification failed - please check the log for details")) Err(format_err!(
}, "verification failed - please check the log for details"
))
}
Err(_) => Err(format_err!("verification failed - job aborted")), Err(_) => Err(format_err!("verification failed - job aborted")),
}; };
@ -79,7 +75,9 @@ pub fn do_verification_job(
} }
if let Some(email) = email { if let Some(email) = email {
if let Err(err) = crate::server::send_verify_status(&email, notify, verification_job, &result) { if let Err(err) =
crate::server::send_verify_status(&email, notify, verification_job, &result)
{
eprintln!("send verify notification failed: {}", err); eprintln!("send verify notification failed: {}", err);
} }
} }