* [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling
@ 2020-09-25 8:43 Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 01/14] add two new schemas for verify jobs Hannes Laimer
` (14 more replies)
0 siblings, 15 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Replaces the first implementation of scheduled verification with a new
job-based version with additional options that may be specified through
the web ui.
Options available for verification jobs:
* schedule when to run the job
* set datastore on which the job should run
* set a number of days after which a verification becomes "outdated"
empty => verifications are valid forever
* specify if already successfuly verified snapshots should be verified
again even if they're not outdated(failed ones will always be done)
Hannes Laimer (14):
add two new schemas for verify jobs
add verify job config
api2: add verify job config endpoint
add do_verification_job function to verify.rs
api2: add verify job admin endpoint
add scheduling for verify jobs
set a diffrent worker_type based on what is going to be
verified(snapshot,group,ds)
ui: add verify job view
ui: add verify job edit window
ui: add task descriptions for the different types of
verify(job,snapshot,group,ds)
remove verify_schedule field from DatastoreConfig
remove verify_schedule field from datastore config endpoint
remove verify-schedule field from DataStoreEdit and DataStoreConfig
remove old verification scheduling from proxmox-backup-proxy.rs
src/api2/admin.rs | 4 +-
src/api2/admin/datastore.rs | 5 +-
src/api2/admin/verify.rs | 107 +++++++++++++
src/api2/config.rs | 2 +
src/api2/config/datastore.rs | 13 --
src/api2/config/verify.rs | 272 +++++++++++++++++++++++++++++++
src/api2/types/mod.rs | 10 ++
src/backup/verify.rs | 91 ++++++++++-
src/bin/proxmox-backup-proxy.rs | 103 +++++-------
src/config.rs | 1 +
src/config/datastore.rs | 6 -
src/config/verify.rs | 186 ++++++++++++++++++++++
www/Makefile | 2 +
www/NavigationTree.js | 6 +
www/Utils.js | 7 +-
www/config/DataStoreConfig.js | 5 +-
www/config/VerifyView.js | 273 ++++++++++++++++++++++++++++++++
www/window/DataStoreEdit.js | 9 --
www/window/VerifyJobEdit.js | 89 +++++++++++
19 files changed, 1089 insertions(+), 102 deletions(-)
create mode 100644 src/api2/admin/verify.rs
create mode 100644 src/api2/config/verify.rs
create mode 100644 src/config/verify.rs
create mode 100644 www/config/VerifyView.js
create mode 100644 www/window/VerifyJobEdit.js
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 01/14] add two new schemas for verify jobs
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 02/14] add verify job config Hannes Laimer
` (13 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/api2/types/mod.rs | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs
index aba307e2..32759055 100644
--- a/src/api2/types/mod.rs
+++ b/src/api2/types/mod.rs
@@ -324,6 +324,16 @@ pub const REMOVE_VANISHED_BACKUPS_SCHEMA: Schema = BooleanSchema::new(
.default(true)
.schema();
+pub const IGNORE_VERIFIED_BACKUPS_SCHEMA: Schema = BooleanSchema::new(
+ "Do not verify backups that are already verified if their verification is not outdated.")
+ .default(true)
+ .schema();
+
+pub const VERIFICATION_OUTDATED_AFTER_SCHEMA: Schema =
+ IntegerSchema::new("Days after that a verification becomes outdated")
+ .minimum(1)
+ .schema();
+
pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (single line).")
.format(&SINGLE_LINE_COMMENT_FORMAT)
.schema();
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 02/14] add verify job config
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 01/14] add two new schemas for verify jobs Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 03/14] api2: add verify job config endpoint Hannes Laimer
` (12 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/config.rs | 1 +
src/config/verify.rs | 186 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 187 insertions(+)
create mode 100644 src/config/verify.rs
diff --git a/src/config.rs b/src/config.rs
index c2ac6da1..ab7fc81a 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -23,6 +23,7 @@ pub mod network;
pub mod remote;
pub mod sync;
pub mod user;
+pub mod verify;
/// Check configuration directory permissions
///
diff --git a/src/config/verify.rs b/src/config/verify.rs
new file mode 100644
index 00000000..f8a52ebd
--- /dev/null
+++ b/src/config/verify.rs
@@ -0,0 +1,186 @@
+use anyhow::{Error};
+use lazy_static::lazy_static;
+use std::collections::HashMap;
+use serde::{Serialize, Deserialize};
+
+use proxmox::api::{
+ api,
+ schema::*,
+ section_config::{
+ SectionConfig,
+ SectionConfigData,
+ SectionConfigPlugin,
+ }
+};
+
+use proxmox::tools::{fs::replace_file, fs::CreateOptions};
+
+use crate::api2::types::*;
+
+lazy_static! {
+ static ref CONFIG: SectionConfig = init();
+}
+
+
+#[api(
+ properties: {
+ id: {
+ schema: JOB_ID_SCHEMA,
+ },
+ store: {
+ schema: DATASTORE_SCHEMA,
+ },
+ "ignore-verified": {
+ optional: true,
+ schema: IGNORE_VERIFIED_BACKUPS_SCHEMA,
+ },
+ "outdated-after": {
+ optional: true,
+ schema: VERIFICATION_OUTDATED_AFTER_SCHEMA,
+ },
+ comment: {
+ optional: true,
+ schema: SINGLE_LINE_COMMENT_SCHEMA,
+ },
+ schedule: {
+ optional: true,
+ schema: VERIFY_SCHEDULE_SCHEMA,
+ },
+ }
+)]
+#[serde(rename_all="kebab-case")]
+#[derive(Serialize,Deserialize)]
+/// Verify Job
+pub struct VerifyJobConfig {
+ pub id: String,
+ pub store: String,
+ pub ignore_verified: bool,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub outdated_after: Option<i64>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub comment: Option<String>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub schedule: Option<String>,
+}
+
+// FIXME: generate duplicate schemas/structs from one listing?
+#[api(
+ properties: {
+ id: {
+ schema: JOB_ID_SCHEMA,
+ },
+ store: {
+ schema: DATASTORE_SCHEMA,
+ },
+ "ignore-verified": {
+ schema: IGNORE_VERIFIED_BACKUPS_SCHEMA,
+ },
+ "outdated-after": {
+ optional: true,
+ schema: VERIFICATION_OUTDATED_AFTER_SCHEMA,
+ },
+ comment: {
+ optional: true,
+ schema: SINGLE_LINE_COMMENT_SCHEMA,
+ },
+ schedule: {
+ optional: true,
+ schema: VERIFY_SCHEDULE_SCHEMA,
+ },
+ "next-run": {
+ description: "Estimated time of the next run (UNIX epoch).",
+ optional: true,
+ type: Integer,
+ },
+ "last-run-state": {
+ description: "Result of the last run.",
+ optional: true,
+ type: String,
+ },
+ "last-run-upid": {
+ description: "Task UPID of the last run.",
+ optional: true,
+ type: String,
+ },
+ "last-run-endtime": {
+ description: "Endtime of the last run.",
+ optional: true,
+ type: Integer,
+ },
+ }
+)]
+#[serde(rename_all="kebab-case")]
+#[derive(Serialize,Deserialize)]
+/// Status of Verify Job
+pub struct VerifyJobStatus {
+ pub id: String,
+ pub store: String,
+ pub ignore_verified: bool,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub outdated_after: Option<i64>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub comment: Option<String>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub schedule: Option<String>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub next_run: Option<i64>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub last_run_state: Option<String>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub last_run_upid: Option<String>,
+ #[serde(skip_serializing_if="Option::is_none")]
+ pub last_run_endtime: Option<i64>,
+}
+
+
+fn init() -> SectionConfig {
+ let obj_schema = match VerifyJobConfig::API_SCHEMA {
+ Schema::Object(ref obj_schema) => obj_schema,
+ _ => unreachable!(),
+ };
+
+ let plugin = SectionConfigPlugin::new("verify".to_string(), Some(String::from("id")), obj_schema);
+ let mut config = SectionConfig::new(&JOB_ID_SCHEMA);
+ config.register_plugin(plugin);
+
+ config
+}
+
+pub const VERIFY_CFG_FILENAME: &str = "/etc/proxmox-backup/verify.cfg";
+pub const VERIFY_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.verify.lck";
+
+pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
+
+ let content = proxmox::tools::fs::file_read_optional_string(VERIFY_CFG_FILENAME)?;
+ let content = content.unwrap_or(String::from(""));
+
+ let digest = openssl::sha::sha256(content.as_bytes());
+ let data = CONFIG.parse(VERIFY_CFG_FILENAME, &content)?;
+ Ok((data, digest))
+}
+
+pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
+ let raw = CONFIG.write(VERIFY_CFG_FILENAME, &config)?;
+
+ let backup_user = crate::backup::backup_user()?;
+ let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640);
+ // set the correct owner/group/permissions while saving file
+ // owner(rw) = root, group(r)= backup
+
+ let options = CreateOptions::new()
+ .perm(mode)
+ .owner(nix::unistd::ROOT)
+ .group(backup_user.gid);
+
+ replace_file(VERIFY_CFG_FILENAME, raw.as_bytes(), options)?;
+
+ Ok(())
+}
+
+// shell completion helper
+pub fn complete_verify_job_id(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
+ match config() {
+ Ok((data, _digest)) => data.sections.iter().map(|(id, _)| id.to_string()).collect(),
+ Err(_) => return vec![],
+ }
+}
\ No newline at end of file
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 03/14] api2: add verify job config endpoint
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 01/14] add two new schemas for verify jobs Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 02/14] add verify job config Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-10-01 10:40 ` Dominik Csapak
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 04/14] add do_verification_job function to verify.rs Hannes Laimer
` (11 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/api2/config.rs | 2 +
src/api2/config/verify.rs | 272 ++++++++++++++++++++++++++++++++++++++
2 files changed, 274 insertions(+)
create mode 100644 src/api2/config/verify.rs
diff --git a/src/api2/config.rs b/src/api2/config.rs
index be7397c8..7a5129c7 100644
--- a/src/api2/config.rs
+++ b/src/api2/config.rs
@@ -4,11 +4,13 @@ use proxmox::list_subdirs_api_method;
pub mod datastore;
pub mod remote;
pub mod sync;
+pub mod verify;
const SUBDIRS: SubdirMap = &[
("datastore", &datastore::ROUTER),
("remote", &remote::ROUTER),
("sync", &sync::ROUTER),
+ ("verify", &verify::ROUTER)
];
pub const ROUTER: Router = Router::new()
diff --git a/src/api2/config/verify.rs b/src/api2/config/verify.rs
new file mode 100644
index 00000000..5e0db40f
--- /dev/null
+++ b/src/api2/config/verify.rs
@@ -0,0 +1,272 @@
+use anyhow::{bail, Error};
+use serde_json::Value;
+use ::serde::{Deserialize, Serialize};
+
+use proxmox::api::{api, Router, RpcEnvironment};
+use proxmox::tools::fs::open_file_locked;
+
+use crate::api2::types::*;
+use crate::config::verify::{self, VerifyJobConfig};
+
+#[api(
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List configured jobs.",
+ type: Array,
+ items: { type: verify::VerifyJobConfig },
+ },
+)]
+/// List all verify jobs
+pub fn list_verify_jobs(
+ _param: Value,
+ mut rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<VerifyJobConfig>, Error> {
+
+ let (config, digest) = verify::config()?;
+
+ let list = config.convert_to_typed_array("verify")?;
+
+ rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
+
+ Ok(list)
+}
+
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ id: {
+ schema: JOB_ID_SCHEMA,
+ },
+ store: {
+ schema: DATASTORE_SCHEMA,
+ },
+ "ignore-verified": {
+ schema: IGNORE_VERIFIED_BACKUPS_SCHEMA,
+ },
+ "outdated-after": {
+ optional: true,
+ schema: VERIFICATION_OUTDATED_AFTER_SCHEMA,
+ },
+ comment: {
+ optional: true,
+ schema: SINGLE_LINE_COMMENT_SCHEMA,
+ },
+ schedule: {
+ optional: true,
+ schema: VERIFY_SCHEDULE_SCHEMA,
+ },
+ }
+ }
+)]
+/// Create a new verify job.
+pub fn create_verify_job(param: Value) -> Result<(), Error> {
+
+ let _lock = open_file_locked(verify::VERIFY_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+
+ let verify_job: verify::VerifyJobConfig = serde_json::from_value(param.clone())?;
+
+ let (mut config, _digest) = verify::config()?;
+
+ if let Some(_) = config.sections.get(&verify_job.id) {
+ bail!("job '{}' already exists.", verify_job.id);
+ }
+
+ config.set_data(&verify_job.id, "verify", &verify_job)?;
+
+ verify::save_config(&config)?;
+
+ crate::config::jobstate::create_state_file("verifyjob", &verify_job.id)?;
+
+ Ok(())
+}
+
+#[api(
+ input: {
+ properties: {
+ id: {
+ schema: JOB_ID_SCHEMA,
+ },
+ },
+ },
+ returns: {
+ description: "The verify job configuration.",
+ type: verify::VerifyJobConfig,
+ },
+)]
+/// Read a verify job configuration.
+pub fn read_verify_job(
+ id: String,
+ mut rpcenv: &mut dyn RpcEnvironment,
+) -> Result<VerifyJobConfig, Error> {
+ let (config, digest) = verify::config()?;
+
+ let verify_job = config.lookup("verify", &id)?;
+ rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
+
+ Ok(verify_job)
+}
+
+#[api()]
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all="kebab-case")]
+#[allow(non_camel_case_types)]
+/// Deletable property name
+pub enum DeletableProperty {
+ /// Delete the comment property.
+ comment,
+ /// Delete the job schedule.
+ schedule,
+ /// Delete outdated_after.
+ outdated_after
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ id: {
+ schema: JOB_ID_SCHEMA,
+ },
+ store: {
+ schema: DATASTORE_SCHEMA,
+ optional: true,
+ },
+ "ignore-verified": {
+ schema: IGNORE_VERIFIED_BACKUPS_SCHEMA,
+ optional: true,
+ },
+ "outdated-after": {
+ optional: true,
+ schema: VERIFICATION_OUTDATED_AFTER_SCHEMA,
+ },
+ comment: {
+ optional: true,
+ schema: SINGLE_LINE_COMMENT_SCHEMA,
+ },
+ schedule: {
+ optional: true,
+ schema: VERIFY_SCHEDULE_SCHEMA,
+ },
+ delete: {
+ description: "List of properties to delete.",
+ type: Array,
+ optional: true,
+ items: {
+ type: DeletableProperty,
+ }
+ },
+ digest: {
+ optional: true,
+ schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
+ },
+ },
+ },
+)]
+/// Update verify job config.
+pub fn update_verify_job(
+ id: String,
+ store: Option<String>,
+ ignore_verified: Option<bool>,
+ outdated_after: Option<i64>,
+ comment: Option<String>,
+ schedule: Option<String>,
+ delete: Option<Vec<DeletableProperty>>,
+ digest: Option<String>,
+) -> Result<(), Error> {
+
+ let _lock = open_file_locked(verify::VERIFY_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+
+ // pass/compare digest
+ let (mut config, expected_digest) = verify::config()?;
+
+ if let Some(ref digest) = digest {
+ let digest = proxmox::tools::hex_to_digest(digest)?;
+ crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
+ }
+
+ let mut data: verify::VerifyJobConfig = config.lookup("verify", &id)?;
+
+ if let Some(delete) = delete {
+ for delete_prop in delete {
+ match delete_prop {
+ DeletableProperty::outdated_after => { data.outdated_after = None; },
+ DeletableProperty::comment => { data.comment = None; },
+ DeletableProperty::schedule => { data.schedule = None; },
+ }
+ }
+ }
+
+ if let Some(comment) = comment {
+ let comment = comment.trim().to_string();
+ if comment.is_empty() {
+ data.comment = None;
+ } else {
+ data.comment = Some(comment);
+ }
+ }
+
+ if let Some(store) = store { data.store = store; }
+ if let Some(ignore_verified) = ignore_verified {
+ data.ignore_verified = ignore_verified;
+ }
+ if outdated_after.is_some() { data.outdated_after = outdated_after }
+ if schedule.is_some() { data.schedule = schedule; }
+
+ config.set_data(&id, "verify", &data)?;
+
+ verify::save_config(&config)?;
+
+ Ok(())
+}
+
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ id: {
+ schema: JOB_ID_SCHEMA,
+ },
+ digest: {
+ optional: true,
+ schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
+ },
+ },
+ },
+)]
+/// Remove a verify job configuration
+pub fn delete_verify_job(id: String, digest: Option<String>) -> Result<(), Error> {
+
+ let _lock = open_file_locked(verify::VERIFY_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+
+ let (mut config, expected_digest) = verify::config()?;
+
+ if let Some(ref digest) = digest {
+ let digest = proxmox::tools::hex_to_digest(digest)?;
+ crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
+ }
+
+ match config.sections.get(&id) {
+ Some(_) => { config.sections.remove(&id); },
+ None => bail!("job '{}' does not exist.", id),
+ }
+
+ verify::save_config(&config)?;
+
+ crate::config::jobstate::remove_state_file("verifyjob", &id)?;
+
+ Ok(())
+}
+
+const ITEM_ROUTER: Router = Router::new()
+ .get(&API_METHOD_READ_VERIFY_JOB)
+ .put(&API_METHOD_UPDATE_VERIFY_JOB)
+ .delete(&API_METHOD_DELETE_VERIFY_JOB);
+
+pub const ROUTER: Router = Router::new()
+ .get(&API_METHOD_LIST_VERIFY_JOBS)
+ .post(&API_METHOD_CREATE_VERIFY_JOB)
+ .match_all("id", &ITEM_ROUTER);
\ No newline at end of file
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 04/14] add do_verification_job function to verify.rs
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (2 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 03/14] api2: add verify job config endpoint Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-10-01 10:40 ` Dominik Csapak
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 05/14] api2: add verify job admin endpoint Hannes Laimer
` (10 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/backup/verify.rs | 91 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 1 deletion(-)
diff --git a/src/backup/verify.rs b/src/backup/verify.rs
index 1fad6187..1f54ebeb 100644
--- a/src/backup/verify.rs
+++ b/src/backup/verify.rs
@@ -5,8 +5,10 @@ use std::time::Instant;
use anyhow::{bail, format_err, Error};
-use crate::server::WorkerTask;
+use crate::server::{WorkerTask, TaskState};
use crate::api2::types::*;
+use crate::config::jobstate::Job;
+use crate::config::verify::VerifyJobConfig;
use super::{
DataStore, DataBlob, BackupGroup, BackupDir, BackupInfo, IndexFile,
@@ -432,3 +434,90 @@ pub fn verify_all_backups(datastore: Arc<DataStore>, worker: Arc<WorkerTask>) ->
Ok(errors)
}
+
+/// Runs a verification job.
+pub fn do_verification_job(
+ mut job: Job,
+ verify_job: VerifyJobConfig,
+ userid: &Userid,
+ schedule: Option<String>,
+) -> Result<String, Error> {
+ let datastore = DataStore::lookup_datastore(&verify_job.store)?;
+
+ let mut backups_to_verify = BackupInfo::list_backups(&datastore.base_path())?;
+
+ if verify_job.ignore_verified {
+ backups_to_verify.retain(|backup_info| {
+ if let Ok((manifest, _)) = datastore.load_manifest(&backup_info.backup_dir) {
+ let verify = manifest.unprotected["verify_state"].clone();
+ if let Ok(verify) = serde_json::from_value::<SnapshotVerifyState>(verify) {
+ let days_since_last_verify =
+ (proxmox::tools::time::epoch_i64() - verify.upid.starttime) / 86400;
+ // if last verification failed we have to verify again since it might be fixed OR
+ // if outdated_after is None, verifications do not become outdated
+ verify.state == VerifyState::Failed || (verify_job.outdated_after.is_some()
+ && days_since_last_verify > verify_job.outdated_after.unwrap())
+ } else { true } // was never verified, therefore we always want to verify
+ } else { false } // manifest could not be loaded, do not verify in that case
+ })
+ }
+
+ let job_id = job.jobname().to_string();
+ let worker_type = job.jobtype().to_string();
+
+ let upid_str = WorkerTask::new_thread(
+ &worker_type,
+ Some(job.jobname().to_string()),
+ userid.clone(),
+ false,
+ move |worker| {
+ job.start(&worker.upid().to_string())?;
+
+ let verified_chunks = Arc::new(Mutex::new(HashSet::with_capacity(1024 * 16)));
+ let corrupt_chunks = Arc::new(Mutex::new(HashSet::with_capacity(64)));
+
+ worker.log(format!("Starting datastore verify job '{}'", job_id));
+ if let Some(event_str) = schedule {
+ worker.log(format!("task triggered by schedule '{}'", event_str));
+ }
+
+ let mut failed_dirs: Vec<String> = Vec::new();
+ for backup_info in backups_to_verify {
+ match verify_backup_dir(
+ datastore.clone(),
+ &backup_info.backup_dir,
+ verified_chunks.clone(),
+ corrupt_chunks.clone(),
+ worker.clone(),
+ ) {
+ Ok(false) => failed_dirs.push(backup_info.backup_dir.to_string()),
+ Err(err) => {
+ let endtime = proxmox::tools::time::epoch_i64();
+ job.finish(TaskState::Error {
+ message: err.to_string(),
+ endtime
+ })?;
+ bail!(err.to_string());
+ },
+ _ => {}
+ }
+ }
+ if !failed_dirs.is_empty() {
+ worker.log("Failed to verify following snapshots:");
+ for dir in failed_dirs {
+ worker.log(format!("\t{}", dir));
+ }
+ let endtime = proxmox::tools::time::epoch_i64();
+ job.finish(TaskState::Error {
+ message: String::from("verification failed - please check the log for details"),
+ endtime
+ })?;
+ bail!("verification failed - please check the log for details");
+ }
+ let endtime = proxmox::tools::time::epoch_i64();
+ job.finish(TaskState::OK { endtime })?;
+ Ok(())
+ })?;
+
+ Ok(upid_str)
+}
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 05/14] api2: add verify job admin endpoint
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (3 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 04/14] add do_verification_job function to verify.rs Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 06/14] add scheduling for verify jobs Hannes Laimer
` (9 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/api2/admin.rs | 4 +-
src/api2/admin/verify.rs | 107 +++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 1 deletion(-)
create mode 100644 src/api2/admin/verify.rs
diff --git a/src/api2/admin.rs b/src/api2/admin.rs
index b927ce1e..79ce29f3 100644
--- a/src/api2/admin.rs
+++ b/src/api2/admin.rs
@@ -3,10 +3,12 @@ use proxmox::list_subdirs_api_method;
pub mod datastore;
pub mod sync;
+pub mod verify;
const SUBDIRS: SubdirMap = &[
("datastore", &datastore::ROUTER),
- ("sync", &sync::ROUTER)
+ ("sync", &sync::ROUTER),
+ ("verify", &verify::ROUTER)
];
pub const ROUTER: Router = Router::new()
diff --git a/src/api2/admin/verify.rs b/src/api2/admin/verify.rs
new file mode 100644
index 00000000..06262efb
--- /dev/null
+++ b/src/api2/admin/verify.rs
@@ -0,0 +1,107 @@
+use anyhow::{format_err, Error};
+
+use proxmox::api::router::SubdirMap;
+use proxmox::{list_subdirs_api_method, sortable};
+use proxmox::api::{api, ApiMethod, Router, RpcEnvironment};
+
+use crate::api2::types::*;
+use crate::backup::do_verification_job;
+use crate::config::jobstate::{Job, JobState};
+use crate::config::verify;
+use crate::config::verify::{VerifyJobConfig, VerifyJobStatus};
+use serde_json::Value;
+use crate::tools::systemd::time::{parse_calendar_event, compute_next_event};
+use crate::server::UPID;
+
+#[api(
+ input: {
+ properties: {},
+ },
+ returns: {
+ description: "List configured jobs and their status.",
+ type: Array,
+ items: { type: verify::VerifyJobStatus },
+ },
+)]
+/// List all verify jobs
+pub fn list_verify_jobs(
+ _param: Value,
+ mut rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<VerifyJobStatus>, Error> {
+
+ let (config, digest) = verify::config()?;
+
+ let mut list: Vec<VerifyJobStatus> = config.convert_to_typed_array("verify")?;
+
+ for job in &mut list {
+ let last_state = JobState::load("verifyjob", &job.id)
+ .map_err(|err| format_err!("could not open statefile for {}: {}", &job.id, err))?;
+
+ let (upid, endtime, state, starttime) = match last_state {
+ JobState::Created { time } => (None, None, None, time),
+ JobState::Started { upid } => {
+ let parsed_upid: UPID = upid.parse()?;
+ (Some(upid), None, None, parsed_upid.starttime)
+ },
+ JobState::Finished { upid, state } => {
+ let parsed_upid: UPID = upid.parse()?;
+ (Some(upid), Some(state.endtime()), Some(state.to_string()), parsed_upid.starttime)
+ },
+ };
+
+ job.last_run_upid = upid;
+ job.last_run_state = state;
+ job.last_run_endtime = endtime;
+
+ let last = job.last_run_endtime.unwrap_or_else(|| starttime);
+
+ job.next_run = (|| -> Option<i64> {
+ let schedule = job.schedule.as_ref()?;
+ let event = parse_calendar_event(&schedule).ok()?;
+ // ignore errors
+ compute_next_event(&event, last, false).unwrap_or_else(|_| None)
+ })();
+ }
+
+ rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
+
+ Ok(list)
+}
+
+#[api(
+ input: {
+ properties: {
+ id: {
+ schema: JOB_ID_SCHEMA,
+ }
+ }
+ }
+)]
+/// Runs a verify job manually.
+fn run_verify_job(
+ id: String,
+ _info: &ApiMethod,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<String, Error> {
+ let (config, _digest) = verify::config()?;
+ let verify_job: VerifyJobConfig = config.lookup("verify", &id)?;
+
+ let userid: Userid = rpcenv.get_user().unwrap().parse()?;
+
+ let job = Job::new("verifyjob", &id)?;
+
+ let upid_str = do_verification_job(job, verify_job, &userid, None)?;
+
+ Ok(upid_str)
+}
+
+#[sortable]
+const VERIFY_INFO_SUBDIRS: SubdirMap = &[("run", &Router::new().post(&API_METHOD_RUN_VERIFY_JOB))];
+
+const VERIFY_INFO_ROUTER: Router = Router::new()
+ .get(&list_subdirs_api_method!(VERIFY_INFO_SUBDIRS))
+ .subdirs(VERIFY_INFO_SUBDIRS);
+
+pub const ROUTER: Router = Router::new()
+ .get(&API_METHOD_LIST_VERIFY_JOBS)
+ .match_all("id", &VERIFY_INFO_ROUTER);
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 06/14] add scheduling for verify jobs
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (4 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 05/14] api2: add verify job admin endpoint Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 07/14] set a diffrent worker_type based on what is going to be verified(snapshot, group, ds) Hannes Laimer
` (8 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/bin/proxmox-backup-proxy.rs | 75 +++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs
index 8a6dfe36..3d2d1929 100644
--- a/src/bin/proxmox-backup-proxy.rs
+++ b/src/bin/proxmox-backup-proxy.rs
@@ -19,6 +19,7 @@ use proxmox_backup::auth_helpers::*;
use proxmox_backup::tools::disks::{ DiskManage, zfs_pool_stats };
use proxmox_backup::api2::pull::do_sync_job;
+use proxmox_backup::backup::do_verification_job;
fn main() -> Result<(), Error> {
proxmox_backup::tools::setup_safe_path_env();
@@ -198,6 +199,7 @@ async fn schedule_tasks() -> Result<(), Error> {
schedule_datastore_prune().await;
schedule_datastore_verification().await;
schedule_datastore_sync_jobs().await;
+ schedule_datastore_verify_jobs().await;
Ok(())
}
@@ -653,6 +655,79 @@ async fn schedule_datastore_sync_jobs() {
}
}
+async fn schedule_datastore_verify_jobs() {
+
+ use proxmox_backup::{
+ config::{ verify::{self, VerifyJobConfig}, jobstate::{self, Job} },
+ tools::systemd::time::{ parse_calendar_event, compute_next_event },
+ };
+
+ let config = match verify::config() {
+ Err(err) => {
+ eprintln!("unable to read verify job config - {}", err);
+ return;
+ }
+ Ok((config, _digest)) => config,
+ };
+
+ for (job_id, (_, job_config)) in config.sections {
+ let job_config: VerifyJobConfig = match serde_json::from_value(job_config) {
+ Ok(c) => c,
+ Err(err) => {
+ eprintln!("verify job config from_value failed - {}", err);
+ continue;
+ }
+ };
+
+ let event_str = match job_config.schedule {
+ Some(ref event_str) => event_str.clone(),
+ None => continue,
+ };
+
+ let event = match parse_calendar_event(&event_str) {
+ Ok(event) => event,
+ Err(err) => {
+ eprintln!("unable to parse schedule '{}' - {}", event_str, err);
+ continue;
+ }
+ };
+
+ let worker_type = "verifyjob";
+
+ let last = match jobstate::last_run_time(worker_type, &job_id) {
+ Ok(time) => time,
+ Err(err) => {
+ eprintln!("could not get last run time of {} {}: {}", worker_type, job_id, err);
+ continue;
+ }
+ };
+
+ let next = match compute_next_event(&event, last, false) {
+ Ok(Some(next)) => next,
+ Ok(None) => continue,
+ Err(err) => {
+ eprintln!("compute_next_event for '{}' failed - {}", event_str, err);
+ continue;
+ }
+ };
+
+ let now = proxmox::tools::time::epoch_i64();
+
+ if next > now { continue; }
+
+ let job = match Job::new(worker_type, &job_id) {
+ Ok(job) => job,
+ Err(_) => continue, // could not get lock
+ };
+
+ let userid = Userid::backup_userid().clone();
+
+ if let Err(err) = do_verification_job(job, job_config, &userid, Some(event_str)) {
+ eprintln!("unable to start datastore verify job {} - {}", &job_id, err);
+ }
+ }
+}
+
async fn run_stat_generator() {
let mut count = 0;
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 07/14] set a diffrent worker_type based on what is going to be verified(snapshot, group, ds)
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (5 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 06/14] add scheduling for verify jobs Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 08/14] ui: add verify job view Hannes Laimer
` (7 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/api2/admin/datastore.rs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs
index af3af0ad..6ae606d9 100644
--- a/src/api2/admin/datastore.rs
+++ b/src/api2/admin/datastore.rs
@@ -486,17 +486,20 @@ pub fn verify(
let mut backup_dir = None;
let mut backup_group = None;
+ let mut worker_type = "verify";
match (backup_type, backup_id, backup_time) {
(Some(backup_type), Some(backup_id), Some(backup_time)) => {
worker_id = format!("{}_{}_{}_{:08X}", store, backup_type, backup_id, backup_time);
let dir = BackupDir::new(backup_type, backup_id, backup_time)?;
backup_dir = Some(dir);
+ worker_type = "verify_snapshot";
}
(Some(backup_type), Some(backup_id), None) => {
worker_id = format!("{}_{}_{}", store, backup_type, backup_id);
let group = BackupGroup::new(backup_type, backup_id);
backup_group = Some(group);
+ worker_type = "verify_group";
}
(None, None, None) => {
worker_id = store.clone();
@@ -508,7 +511,7 @@ pub fn verify(
let to_stdout = if rpcenv.env_type() == RpcEnvironmentType::CLI { true } else { false };
let upid_str = WorkerTask::new_thread(
- "verify",
+ worker_type,
Some(worker_id.clone()),
userid,
to_stdout,
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 08/14] ui: add verify job view
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (6 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 07/14] set a diffrent worker_type based on what is going to be verified(snapshot, group, ds) Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-10-01 10:40 ` Dominik Csapak
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 09/14] ui: add verify job edit window Hannes Laimer
` (6 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
www/Makefile | 1 +
www/NavigationTree.js | 6 +
www/config/VerifyView.js | 273 +++++++++++++++++++++++++++++++++++++++
3 files changed, 280 insertions(+)
create mode 100644 www/config/VerifyView.js
diff --git a/www/Makefile b/www/Makefile
index 90a98b74..48d06266 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -16,6 +16,7 @@ JSSRC= \
config/RemoteView.js \
config/ACLView.js \
config/SyncView.js \
+ config/VerifyView.js \
config/DataStoreConfig.js \
window/UserEdit.js \
window/UserPassword.js \
diff --git a/www/NavigationTree.js b/www/NavigationTree.js
index 0fd9458d..21b9b2a6 100644
--- a/www/NavigationTree.js
+++ b/www/NavigationTree.js
@@ -42,6 +42,12 @@ Ext.define('PBS.store.NavigationStore', {
path: 'pbsSyncJobView',
leaf: true,
},
+ {
+ text: gettext('Verify Jobs'),
+ iconCls: 'fa fa-check-circle',
+ path: 'pbsVerifyJobView',
+ leaf: true,
+ },
{
text: gettext('Subscription'),
iconCls: 'fa fa-support',
diff --git a/www/config/VerifyView.js b/www/config/VerifyView.js
new file mode 100644
index 00000000..e8722eb9
--- /dev/null
+++ b/www/config/VerifyView.js
@@ -0,0 +1,273 @@
+Ext.define('pbs-verify-jobs-status', {
+ extend: 'Ext.data.Model',
+ fields: [
+ 'id', 'store', 'outdated-after', 'schedule',
+ 'next-run', 'last-run-upid', 'last-run-state', 'last-run-endtime',
+ {
+ name: 'duration',
+ calculate: function(data) {
+ let endtime = data['last-run-endtime'];
+ if (!endtime) return undefined;
+ let task = Proxmox.Utils.parse_task_upid(data['last-run-upid']);
+ return endtime - task.starttime;
+ },
+ },
+ ],
+ idProperty: 'id',
+ proxy: {
+ type: 'proxmox',
+ url: '/api2/json/admin/verify',
+ },
+});
+
+Ext.define('PBS.config.VerifyJobView', {
+ extend: 'Ext.grid.GridPanel',
+ alias: 'widget.pbsVerifyJobView',
+
+ stateful: true,
+ stateId: 'grid-verify-jobs',
+
+ title: gettext('Verify Jobs'),
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ addVerifyJob: function() {
+ let me = this;
+ Ext.create('PBS.window.VerifyJobEdit', {
+ listeners: {
+ destroy: function() {
+ me.reload();
+ },
+ },
+ }).show();
+ },
+
+ editVerifyJob: function() {
+ let me = this;
+ let view = me.getView();
+ let selection = view.getSelection();
+ if (selection.length < 1) return;
+
+ Ext.create('PBS.window.VerifyJobEdit', {
+ id: selection[0].data.id,
+ listeners: {
+ destroy: function() {
+ me.reload();
+ },
+ },
+ }).show();
+ },
+
+ openTaskLog: function() {
+ let me = this;
+ let view = me.getView();
+ let selection = view.getSelection();
+ if (selection.length < 1) return;
+
+ let upid = selection[0].data['last-run-upid'];
+ if (!upid) return;
+
+ Ext.create('Proxmox.window.TaskViewer', {
+ upid
+ }).show();
+ },
+
+ runVerifyJob: function() {
+ let me = this;
+ let view = me.getView();
+ let selection = view.getSelection();
+ if (selection.length < 1) return;
+
+ let id = selection[0].data.id;
+ Proxmox.Utils.API2Request({
+ method: 'POST',
+ url: `/admin/verify/${id}/run`,
+ success: function(response, opt) {
+ Ext.create('Proxmox.window.TaskViewer', {
+ upid: response.result.data,
+ taskDone: function(success) {
+ me.reload();
+ },
+ }).show();
+ },
+ failure: function(response, opt) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ },
+ });
+ },
+
+ render_verify_status: function(value, metadata, record) {
+ if (!record.data['last-run-upid']) {
+ return '-';
+ }
+
+ if (!record.data['last-run-endtime']) {
+ metadata.tdCls = 'x-grid-row-loading';
+ return '';
+ }
+
+ let parsed = Proxmox.Utils.parse_task_status(value);
+ let text = value;
+ let icon = '';
+ switch (parsed) {
+ case 'unknown':
+ icon = 'question faded';
+ text = Proxmox.Utils.unknownText;
+ break;
+ case 'error':
+ icon = 'times critical';
+ text = Proxmox.Utils.errorText + ': ' + value;
+ break;
+ case 'warning':
+ icon = 'exclamation warning';
+ break;
+ case 'ok':
+ icon = 'check good';
+ text = gettext("OK");
+ }
+
+ return `<i class="fa fa-${icon}"></i> ${text}`;
+ },
+
+ render_next_run: function(value, metadat, record) {
+ if (!value) return '-';
+
+ let now = new Date();
+ let next = new Date(value*1000);
+
+ if (next < now) {
+ return gettext('pending');
+ }
+ return Proxmox.Utils.render_timestamp(value);
+ },
+
+ render_optional_timestamp: function(value, metadata, record) {
+ if (!value) return '-';
+ return Proxmox.Utils.render_timestamp(value);
+ },
+
+ reload: function() { this.getView().getStore().rstore.load(); },
+
+ init: function(view) {
+ Proxmox.Utils.monStoreErrors(view, view.getStore().rstore);
+ },
+ },
+
+ listeners: {
+ activate: 'reload',
+ itemdblclick: 'editVerifyJob',
+ },
+
+ store: {
+ type: 'diff',
+ autoDestroy: true,
+ autoDestroyRstore: true,
+ sorters: 'id',
+ rstore: {
+ type: 'update',
+ storeid: 'pbs-verify-jobs-status',
+ model: 'pbs-verify-jobs-status',
+ autoStart: true,
+ interval: 5000,
+ },
+ },
+
+ tbar: [
+ {
+ xtype: 'proxmoxButton',
+ text: gettext('Add'),
+ handler: 'addVerifyJob',
+ selModel: false,
+ },
+ {
+ xtype: 'proxmoxButton',
+ text: gettext('Edit'),
+ handler: 'editVerifyJob',
+ disabled: true,
+ },
+ {
+ xtype: 'proxmoxStdRemoveButton',
+ baseurl: '/config/verify/',
+ callback: 'reload',
+ },
+ '-',
+ {
+ xtype: 'proxmoxButton',
+ text: gettext('Log'),
+ handler: 'openTaskLog',
+ enableFn: (rec) => !!rec.data['last-run-upid'],
+ disabled: true,
+ },
+ {
+ xtype: 'proxmoxButton',
+ text: gettext('Run now'),
+ handler: 'runVerifyJob',
+ disabled: true,
+ },
+ ],
+
+ viewConfig: {
+ trackOver: false,
+ },
+
+ columns: [
+ {
+ header: gettext('Verify Job'),
+ width: 100,
+ sortable: true,
+ renderer: Ext.String.htmlEncode,
+ dataIndex: 'id',
+ },
+ {
+ header: gettext('Datastore'),
+ width: 100,
+ sortable: true,
+ dataIndex: 'store',
+ },
+ {
+ header: gettext('Days valid'),
+ width: 50,
+ sortable: true,
+ dataIndex: 'outdated-after',
+ },
+ {
+ header: gettext('Schedule'),
+ sortable: true,
+ dataIndex: 'schedule',
+ },
+ {
+ header: gettext('Status'),
+ dataIndex: 'last-run-state',
+ flex: 1,
+ renderer: 'render_verify_status',
+ },
+ {
+ header: gettext('Last Verification'),
+ sortable: true,
+ minWidth: 200,
+ renderer: 'render_optional_timestamp',
+ dataIndex: 'last-run-endtime',
+ },
+ {
+ text: gettext('Duration'),
+ dataIndex: 'duration',
+ width: 60,
+ renderer: Proxmox.Utils.render_duration,
+ },
+ {
+ header: gettext('Next Run'),
+ sortable: true,
+ minWidth: 200,
+ renderer: 'render_next_run',
+ dataIndex: 'next-run',
+ },
+ {
+ header: gettext('Comment'),
+ hidden: true,
+ sortable: true,
+ renderer: Ext.String.htmlEncode,
+ dataIndex: 'comment',
+ },
+ ],
+});
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 09/14] ui: add verify job edit window
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (7 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 08/14] ui: add verify job view Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 10/14] ui: add task descriptions for the different types of verify(job, snapshot, group, ds) Hannes Laimer
` (5 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
www/Makefile | 1 +
www/window/VerifyJobEdit.js | 89 +++++++++++++++++++++++++++++++++++++
2 files changed, 90 insertions(+)
create mode 100644 www/window/VerifyJobEdit.js
diff --git a/www/Makefile b/www/Makefile
index 48d06266..bca531e8 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -20,6 +20,7 @@ JSSRC= \
config/DataStoreConfig.js \
window/UserEdit.js \
window/UserPassword.js \
+ window/VerifyJobEdit.js \
window/RemoteEdit.js \
window/SyncJobEdit.js \
window/ACLEdit.js \
diff --git a/www/window/VerifyJobEdit.js b/www/window/VerifyJobEdit.js
new file mode 100644
index 00000000..985d2ef6
--- /dev/null
+++ b/www/window/VerifyJobEdit.js
@@ -0,0 +1,89 @@
+Ext.define('PBS.window.VerifyJobEdit', {
+ extend: 'Proxmox.window.Edit',
+ alias: 'widget.pbsVerifyJobEdit',
+ mixins: ['Proxmox.Mixin.CBind'],
+
+ userid: undefined,
+
+ onlineHelp: 'verifyjobs',
+
+ isAdd: true,
+
+ subject: gettext('VerifyJob'),
+
+ fieldDefaults: { labelWidth: 120 },
+
+ cbindData: function(initialConfig) {
+ let me = this;
+
+ let baseurl = '/api2/extjs/config/verify';
+ let id = initialConfig.id;
+
+ me.isCreate = !id;
+ me.url = id ? `${baseurl}/${id}` : baseurl;
+ me.method = id ? 'PUT' : 'POST';
+ me.autoLoad = !!id;
+ return { };
+ },
+
+ items: {
+ xtype: 'inputpanel',
+ column1: [
+ {
+ fieldLabel: gettext('Verify Job ID'),
+ xtype: 'pmxDisplayEditField',
+ name: 'id',
+ renderer: Ext.htmlEncode,
+ allowBlank: false,
+ minLength: 4,
+ cbind: {
+ editable: '{isCreate}',
+ },
+ },
+ {
+ fieldLabel: gettext('Datastore'),
+ xtype: 'pbsDataStoreSelector',
+ allowBlank: false,
+ name: 'store',
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ fieldLabel: gettext('Days valid'),
+ minValue: 1,
+ value: '',
+ allowBlank: true,
+ name: 'outdated-after'
+ },
+ ],
+
+ column2: [
+ {
+ fieldLabel: gettext('Ignore verified'),
+ xtype: 'proxmoxcheckbox',
+ name: 'ignore-verified',
+ uncheckedValue: false,
+ value: true,
+ },
+ {
+ fieldLabel: gettext('Schedule'),
+ xtype: 'pbsCalendarEvent',
+ name: 'schedule',
+ emptyText: gettext('none'),
+ cbind: {
+ deleteEmpty: '{!isCreate}',
+ },
+ },
+ ],
+
+ columnB: [
+ {
+ fieldLabel: gettext('Comment'),
+ xtype: 'proxmoxtextfield',
+ name: 'comment',
+ cbind: {
+ deleteEmpty: '{!isCreate}',
+ },
+ },
+ ],
+ },
+});
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 10/14] ui: add task descriptions for the different types of verify(job, snapshot, group, ds)
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (8 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 09/14] ui: add verify job edit window Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 11/14] remove verify_schedule field from DatastoreConfig Hannes Laimer
` (4 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
www/Utils.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/www/Utils.js b/www/Utils.js
index 7bcf1ba6..3bca7274 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -93,13 +93,14 @@ Ext.define('PBS.Utils', {
Proxmox.Utils.override_task_descriptions({
garbage_collection: ['Datastore', gettext('Garbage collect') ],
sync: ['Datastore', gettext('Remote Sync') ],
+ verify: ['Datastore', gettext('Verification') ],
+ verify_group: ['Group', gettext('Verification') ],
+ verify_snapshot: ['Snapshot', gettext('Verification') ],
syncjob: [gettext('Sync Job'), gettext('Remote Sync') ],
+ verifyjob: [gettext('Verify Job'), gettext('Scheduled Verification') ],
prune: (type, id) => {
return PBS.Utils.render_datastore_worker_id(id, gettext('Prune'));
},
- verify: (type, id) => {
- return PBS.Utils.render_datastore_worker_id(id, gettext('Verify'));
- },
backup: (type, id) => {
return PBS.Utils.render_datastore_worker_id(id, gettext('Backup'));
},
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 11/14] remove verify_schedule field from DatastoreConfig
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (9 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 10/14] ui: add task descriptions for the different types of verify(job, snapshot, group, ds) Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 12/14] remove verify_schedule field from datastore config endpoint Hannes Laimer
` (3 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/config/datastore.rs | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/config/datastore.rs b/src/config/datastore.rs
index 1f5b4f84..7e2ae573 100644
--- a/src/config/datastore.rs
+++ b/src/config/datastore.rs
@@ -44,10 +44,6 @@ pub const DIR_NAME_SCHEMA: Schema = StringSchema::new("Directory name").schema()
optional: true,
schema: PRUNE_SCHEDULE_SCHEMA,
},
- "verify-schedule": {
- optional: true,
- schema: VERIFY_SCHEDULE_SCHEMA,
- },
"keep-last": {
optional: true,
schema: PRUNE_SCHEMA_KEEP_LAST,
@@ -87,8 +83,6 @@ pub struct DataStoreConfig {
#[serde(skip_serializing_if="Option::is_none")]
pub prune_schedule: Option<String>,
#[serde(skip_serializing_if="Option::is_none")]
- pub verify_schedule: Option<String>,
- #[serde(skip_serializing_if="Option::is_none")]
pub keep_last: Option<u64>,
#[serde(skip_serializing_if="Option::is_none")]
pub keep_hourly: Option<u64>,
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 12/14] remove verify_schedule field from datastore config endpoint
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (10 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 11/14] remove verify_schedule field from DatastoreConfig Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 13/14] remove verify-schedule field from DataStoreEdit and DataStoreConfig Hannes Laimer
` (2 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/api2/config/datastore.rs | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index 870324a3..410fe65f 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -75,10 +75,6 @@ pub fn list_datastores(
optional: true,
schema: PRUNE_SCHEDULE_SCHEMA,
},
- "verify-schedule": {
- optional: true,
- schema: VERIFY_SCHEDULE_SCHEMA,
- },
"keep-last": {
optional: true,
schema: PRUNE_SCHEMA_KEEP_LAST,
@@ -177,8 +173,6 @@ pub enum DeletableProperty {
gc_schedule,
/// Delete the prune job schedule.
prune_schedule,
- /// Delete the verify schedule property
- verify_schedule,
/// Delete the keep-last property
keep_last,
/// Delete the keep-hourly property
@@ -212,10 +206,6 @@ pub enum DeletableProperty {
optional: true,
schema: PRUNE_SCHEDULE_SCHEMA,
},
- "verify-schedule": {
- optional: true,
- schema: VERIFY_SCHEDULE_SCHEMA,
- },
"keep-last": {
optional: true,
schema: PRUNE_SCHEMA_KEEP_LAST,
@@ -264,7 +254,6 @@ pub fn update_datastore(
comment: Option<String>,
gc_schedule: Option<String>,
prune_schedule: Option<String>,
- verify_schedule: Option<String>,
keep_last: Option<u64>,
keep_hourly: Option<u64>,
keep_daily: Option<u64>,
@@ -293,7 +282,6 @@ pub fn update_datastore(
DeletableProperty::comment => { data.comment = None; },
DeletableProperty::gc_schedule => { data.gc_schedule = None; },
DeletableProperty::prune_schedule => { data.prune_schedule = None; },
- DeletableProperty::verify_schedule => { data.verify_schedule = None; },
DeletableProperty::keep_last => { data.keep_last = None; },
DeletableProperty::keep_hourly => { data.keep_hourly = None; },
DeletableProperty::keep_daily => { data.keep_daily = None; },
@@ -319,7 +307,6 @@ pub fn update_datastore(
prune_schedule_changed = true;
data.prune_schedule = prune_schedule;
}
- if verify_schedule.is_some() { data.verify_schedule = verify_schedule; }
if keep_last.is_some() { data.keep_last = keep_last; }
if keep_hourly.is_some() { data.keep_hourly = keep_hourly; }
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 13/14] remove verify-schedule field from DataStoreEdit and DataStoreConfig
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (11 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 12/14] remove verify_schedule field from datastore config endpoint Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 14/14] remove old verification scheduling from proxmox-backup-proxy.rs Hannes Laimer
2020-10-01 10:39 ` [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Dominik Csapak
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
www/config/DataStoreConfig.js | 5 ++---
www/window/DataStoreEdit.js | 9 ---------
2 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/www/config/DataStoreConfig.js b/www/config/DataStoreConfig.js
index 685d3d5f..54d7a505 100644
--- a/www/config/DataStoreConfig.js
+++ b/www/config/DataStoreConfig.js
@@ -11,9 +11,8 @@ Ext.define('pbs-datastore-list', {
Ext.define('pbs-data-store-config', {
extend: 'Ext.data.Model',
fields: [
- 'name', 'path', 'comment', 'gc-schedule', 'prune-schedule',
- 'verify-schedule', 'keep-last', 'keep-hourly', 'keep-daily',
- 'keep-weekly', 'keep-monthly', 'keep-yearly',
+ 'name', 'path', 'comment', 'gc-schedule', 'prune-schedule', 'keep-last',
+ 'keep-hourly', 'keep-daily', 'keep-weekly', 'keep-monthly', 'keep-yearly',
],
proxy: {
type: 'proxmox',
diff --git a/www/window/DataStoreEdit.js b/www/window/DataStoreEdit.js
index f565cee5..3cf218f1 100644
--- a/www/window/DataStoreEdit.js
+++ b/www/window/DataStoreEdit.js
@@ -74,15 +74,6 @@ Ext.define('PBS.DataStoreEdit', {
deleteEmpty: '{!isCreate}',
},
},
- {
- xtype: 'pbsCalendarEvent',
- name: 'verify-schedule',
- fieldLabel: gettext("Verify Schedule"),
- emptyText: gettext('none'),
- cbind: {
- deleteEmpty: '{!isCreate}',
- },
- },
],
columnB: [
{
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [pbs-devel] [PATCH v1 proxmox-backup 14/14] remove old verification scheduling from proxmox-backup-proxy.rs
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (12 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 13/14] remove verify-schedule field from DataStoreEdit and DataStoreConfig Hannes Laimer
@ 2020-09-25 8:43 ` Hannes Laimer
2020-10-01 10:39 ` [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Dominik Csapak
14 siblings, 0 replies; 21+ messages in thread
From: Hannes Laimer @ 2020-09-25 8:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/bin/proxmox-backup-proxy.rs | 102 --------------------------------
1 file changed, 102 deletions(-)
diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs
index 3d2d1929..4dd5cfbe 100644
--- a/src/bin/proxmox-backup-proxy.rs
+++ b/src/bin/proxmox-backup-proxy.rs
@@ -197,7 +197,6 @@ async fn schedule_tasks() -> Result<(), Error> {
schedule_datastore_garbage_collection().await;
schedule_datastore_prune().await;
- schedule_datastore_verification().await;
schedule_datastore_sync_jobs().await;
schedule_datastore_verify_jobs().await;
@@ -481,107 +480,6 @@ async fn schedule_datastore_prune() {
}
}
-async fn schedule_datastore_verification() {
- use proxmox_backup::backup::{DataStore, verify_all_backups};
- use proxmox_backup::server::{WorkerTask};
- use proxmox_backup::config::datastore::{self, DataStoreConfig};
- use proxmox_backup::tools::systemd::time::{
- parse_calendar_event, compute_next_event};
-
- let config = match datastore::config() {
- Err(err) => {
- eprintln!("unable to read datastore config - {}", err);
- return;
- }
- Ok((config, _digest)) => config,
- };
-
- for (store, (_, store_config)) in config.sections {
- let datastore = match DataStore::lookup_datastore(&store) {
- Ok(datastore) => datastore,
- Err(err) => {
- eprintln!("lookup_datastore failed - {}", err);
- continue;
- }
- };
-
- let store_config: DataStoreConfig = match serde_json::from_value(store_config) {
- Ok(c) => c,
- Err(err) => {
- eprintln!("datastore config from_value failed - {}", err);
- continue;
- }
- };
-
- let event_str = match store_config.verify_schedule {
- Some(event_str) => event_str,
- None => continue,
- };
-
- let event = match parse_calendar_event(&event_str) {
- Ok(event) => event,
- Err(err) => {
- eprintln!("unable to parse schedule '{}' - {}", event_str, err);
- continue;
- }
- };
-
- let worker_type = "verify";
-
- let last = match lookup_last_worker(worker_type, &store) {
- Ok(Some(upid)) => {
- if proxmox_backup::server::worker_is_active_local(&upid) {
- continue;
- }
- upid.starttime
- }
- Ok(None) => 0,
- Err(err) => {
- eprintln!("lookup_last_job_start failed: {}", err);
- continue;
- }
- };
-
- let next = match compute_next_event(&event, last, false) {
- Ok(Some(next)) => next,
- Ok(None) => continue,
- Err(err) => {
- eprintln!("compute_next_event for '{}' failed - {}", event_str, err);
- continue;
- }
- };
-
- let now = proxmox::tools::time::epoch_i64();
-
- if next > now { continue; }
-
- let worker_id = store.clone();
- let store2 = store.clone();
- if let Err(err) = WorkerTask::new_thread(
- worker_type,
- Some(worker_id),
- Userid::backup_userid().clone(),
- false,
- move |worker| {
- worker.log(format!("starting verification on store {}", store2));
- worker.log(format!("task triggered by schedule '{}'", event_str));
- if let Ok(failed_dirs) = verify_all_backups(datastore, worker.clone()) {
- if failed_dirs.len() > 0 {
- worker.log("Failed to verify following snapshots:");
- for dir in failed_dirs {
- worker.log(format!("\t{}", dir));
- }
- bail!("verification failed - please check the log for details");
- }
- }
- Ok(())
- },
- ) {
- eprintln!("unable to start verification on store {} - {}", store, err);
- }
- }
-}
-
async fn schedule_datastore_sync_jobs() {
use proxmox_backup::{
--
2.20.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
` (13 preceding siblings ...)
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 14/14] remove old verification scheduling from proxmox-backup-proxy.rs Hannes Laimer
@ 2020-10-01 10:39 ` Dominik Csapak
2020-10-01 12:21 ` Dietmar Maurer
14 siblings, 1 reply; 21+ messages in thread
From: Dominik Csapak @ 2020-10-01 10:39 UTC (permalink / raw)
To: pbs-devel
Some high level comments:
* patches need some work on rebase, since there were some code changes
* we sadly cannot simply remove the 'verify-schedule' from the
datastore configs, as we already have packages out there that support
it and it breaks all datastore config parsing
we could fix that either by
- leaving the schedule in place and 'magically' show it as a verifyjob
- have some script that runs in postinst that rewrites the verify
schedules as jobs
- maybe some other method?
* it would be very nice to see which backups were considered for
verification, but skipped by its verify status, else the user
clicks on verification and only gets: Ok
but with no progress or indication what actually happened
* for now i think it's okay to add a separate panel, though
thomas would prefer to somehow merge the syncjob/verifyjob
(and maybe also garbage_collection/prune) into a single
"Job/Schedule" overview
the patches itself look mostly ok though and work
as expected (after correctly rebasing)
i'll also write some comments to the patches directly
On 9/25/20 10:43 AM, Hannes Laimer wrote:
> Replaces the first implementation of scheduled verification with a new
> job-based version with additional options that may be specified through
> the web ui.
>
> Options available for verification jobs:
> * schedule when to run the job
> * set datastore on which the job should run
> * set a number of days after which a verification becomes "outdated"
> empty => verifications are valid forever
> * specify if already successfuly verified snapshots should be verified
> again even if they're not outdated(failed ones will always be done)
>
>
> Hannes Laimer (14):
> add two new schemas for verify jobs
> add verify job config
> api2: add verify job config endpoint
> add do_verification_job function to verify.rs
> api2: add verify job admin endpoint
> add scheduling for verify jobs
> set a diffrent worker_type based on what is going to be
> verified(snapshot,group,ds)
> ui: add verify job view
> ui: add verify job edit window
> ui: add task descriptions for the different types of
> verify(job,snapshot,group,ds)
> remove verify_schedule field from DatastoreConfig
> remove verify_schedule field from datastore config endpoint
> remove verify-schedule field from DataStoreEdit and DataStoreConfig
> remove old verification scheduling from proxmox-backup-proxy.rs
>
> src/api2/admin.rs | 4 +-
> src/api2/admin/datastore.rs | 5 +-
> src/api2/admin/verify.rs | 107 +++++++++++++
> src/api2/config.rs | 2 +
> src/api2/config/datastore.rs | 13 --
> src/api2/config/verify.rs | 272 +++++++++++++++++++++++++++++++
> src/api2/types/mod.rs | 10 ++
> src/backup/verify.rs | 91 ++++++++++-
> src/bin/proxmox-backup-proxy.rs | 103 +++++-------
> src/config.rs | 1 +
> src/config/datastore.rs | 6 -
> src/config/verify.rs | 186 ++++++++++++++++++++++
> www/Makefile | 2 +
> www/NavigationTree.js | 6 +
> www/Utils.js | 7 +-
> www/config/DataStoreConfig.js | 5 +-
> www/config/VerifyView.js | 273 ++++++++++++++++++++++++++++++++
> www/window/DataStoreEdit.js | 9 --
> www/window/VerifyJobEdit.js | 89 +++++++++++
> 19 files changed, 1089 insertions(+), 102 deletions(-)
> create mode 100644 src/api2/admin/verify.rs
> create mode 100644 src/api2/config/verify.rs
> create mode 100644 src/config/verify.rs
> create mode 100644 www/config/VerifyView.js
> create mode 100644 www/window/VerifyJobEdit.js
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [pbs-devel] [PATCH v1 proxmox-backup 03/14] api2: add verify job config endpoint
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 03/14] api2: add verify job config endpoint Hannes Laimer
@ 2020-10-01 10:40 ` Dominik Csapak
0 siblings, 0 replies; 21+ messages in thread
From: Dominik Csapak @ 2020-10-01 10:40 UTC (permalink / raw)
To: pbs-devel
comments inline
On 9/25/20 10:43 AM, Hannes Laimer wrote:
> Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
> ---
> src/api2/config.rs | 2 +
> src/api2/config/verify.rs | 272 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 274 insertions(+)
> create mode 100644 src/api2/config/verify.rs
>
> diff --git a/src/api2/config.rs b/src/api2/config.rs
> index be7397c8..7a5129c7 100644
> --- a/src/api2/config.rs
> +++ b/src/api2/config.rs
> @@ -4,11 +4,13 @@ use proxmox::list_subdirs_api_method;
> pub mod datastore;
> pub mod remote;
> pub mod sync;
> +pub mod verify;
>
> const SUBDIRS: SubdirMap = &[
> ("datastore", &datastore::ROUTER),
> ("remote", &remote::ROUTER),
> ("sync", &sync::ROUTER),
> + ("verify", &verify::ROUTER)
> ];
>
> pub const ROUTER: Router = Router::new()
> diff --git a/src/api2/config/verify.rs b/src/api2/config/verify.rs
> new file mode 100644
> index 00000000..5e0db40f
> --- /dev/null
> +++ b/src/api2/config/verify.rs
> @@ -0,0 +1,272 @@
> +use anyhow::{bail, Error};
> +use serde_json::Value;
> +use ::serde::{Deserialize, Serialize};
> +
> +use proxmox::api::{api, Router, RpcEnvironment};
> +use proxmox::tools::fs::open_file_locked;
> +
> +use crate::api2::types::*;
> +use crate::config::verify::{self, VerifyJobConfig};
> +
> +#[api(
> + input: {
> + properties: {},
> + },
> + returns: {
> + description: "List configured jobs.",
> + type: Array,
> + items: { type: verify::VerifyJobConfig },
> + },
> +)]
> +/// List all verify jobs
> +pub fn list_verify_jobs(
> + _param: Value,
> + mut rpcenv: &mut dyn RpcEnvironment,
> +) -> Result<Vec<VerifyJobConfig>, Error> {
> +
> + let (config, digest) = verify::config()?;
> +
> + let list = config.convert_to_typed_array("verify")?;
> +
> + rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
> +
> + Ok(list)
> +}
> +
> +
> +#[api(
> + protected: true,
> + input: {
> + properties: {
> + id: {
> + schema: JOB_ID_SCHEMA,
> + },
> + store: {
> + schema: DATASTORE_SCHEMA,
> + },
> + "ignore-verified": {
> + schema: IGNORE_VERIFIED_BACKUPS_SCHEMA,
i would find it more sensible to have this also optional, as is
already has default anyway
also i would probably make it an Option in the struct also,
since there is a documented default and a not serialized option
takes less space in the config
> + },
> + "outdated-after": {
> + optional: true,
> + schema: VERIFICATION_OUTDATED_AFTER_SCHEMA,
> + },
> + comment: {
> + optional: true,
> + schema: SINGLE_LINE_COMMENT_SCHEMA,
> + },
> + schedule: {
> + optional: true,
> + schema: VERIFY_SCHEDULE_SCHEMA,
> + },
> + }
> + }
> +)]
> +/// Create a new verify job.
> +pub fn create_verify_job(param: Value) -> Result<(), Error> {
> +
> + let _lock = open_file_locked(verify::VERIFY_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
> +
> + let verify_job: verify::VerifyJobConfig = serde_json::from_value(param.clone())?;
> +
> + let (mut config, _digest) = verify::config()?;
> +
> + if let Some(_) = config.sections.get(&verify_job.id) {
> + bail!("job '{}' already exists.", verify_job.id);
> + }
> +
> + config.set_data(&verify_job.id, "verify", &verify_job)?;
> +
> + verify::save_config(&config)?;
> +
> + crate::config::jobstate::create_state_file("verifyjob", &verify_job.id)?;
> +
> + Ok(())
> +}
> +
> +#[api(
> + input: {
> + properties: {
> + id: {
> + schema: JOB_ID_SCHEMA,
> + },
> + },
> + },
> + returns: {
> + description: "The verify job configuration.",
> + type: verify::VerifyJobConfig,
> + },
> +)]
> +/// Read a verify job configuration.
> +pub fn read_verify_job(
> + id: String,
> + mut rpcenv: &mut dyn RpcEnvironment,
> +) -> Result<VerifyJobConfig, Error> {
> + let (config, digest) = verify::config()?;
> +
> + let verify_job = config.lookup("verify", &id)?;
> + rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
> +
> + Ok(verify_job)
> +}
> +
> +#[api()]
> +#[derive(Serialize, Deserialize)]
> +#[serde(rename_all="kebab-case")]
> +#[allow(non_camel_case_types)]
> +/// Deletable property name
> +pub enum DeletableProperty {
> + /// Delete the comment property.
> + comment,
> + /// Delete the job schedule.
> + schedule,
> + /// Delete outdated_after.
> + outdated_after > +}
> +
> +#[api(
> + protected: true,
> + input: {
> + properties: {
> + id: {
> + schema: JOB_ID_SCHEMA,
> + },
> + store: {
> + schema: DATASTORE_SCHEMA,
> + optional: true,
> + },
> + "ignore-verified": {
> + schema: IGNORE_VERIFIED_BACKUPS_SCHEMA,
> + optional: true,
> + },
> + "outdated-after": {
> + optional: true,
> + schema: VERIFICATION_OUTDATED_AFTER_SCHEMA,
> + },
> + comment: {
> + optional: true,
> + schema: SINGLE_LINE_COMMENT_SCHEMA,
> + },
> + schedule: {
> + optional: true,
> + schema: VERIFY_SCHEDULE_SCHEMA,
> + },
> + delete: {
> + description: "List of properties to delete.",
> + type: Array,
> + optional: true,
> + items: {
> + type: DeletableProperty,
> + }
> + },
> + digest: {
> + optional: true,
> + schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
> + },
> + },
> + },
> +)]
> +/// Update verify job config.
> +pub fn update_verify_job(
> + id: String,
> + store: Option<String>,
> + ignore_verified: Option<bool>,
> + outdated_after: Option<i64>,
> + comment: Option<String>,
> + schedule: Option<String>,
> + delete: Option<Vec<DeletableProperty>>,
> + digest: Option<String>,
> +) -> Result<(), Error> {
> +
> + let _lock = open_file_locked(verify::VERIFY_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
> +
> + // pass/compare digest
> + let (mut config, expected_digest) = verify::config()?;
> +
> + if let Some(ref digest) = digest {
> + let digest = proxmox::tools::hex_to_digest(digest)?;
> + crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
> + }
> +
> + let mut data: verify::VerifyJobConfig = config.lookup("verify", &id)?;
> +
> + if let Some(delete) = delete {
> + for delete_prop in delete {
> + match delete_prop {
> + DeletableProperty::outdated_after => { data.outdated_after = None; },
> + DeletableProperty::comment => { data.comment = None; },
> + DeletableProperty::schedule => { data.schedule = None; },
> + }
> + }
> + }
> +
> + if let Some(comment) = comment {
> + let comment = comment.trim().to_string();
> + if comment.is_empty() {
> + data.comment = None;
> + } else {
> + data.comment = Some(comment);
> + }
> + }
> +
> + if let Some(store) = store { data.store = store; }
> + if let Some(ignore_verified) = ignore_verified {
> + data.ignore_verified = ignore_verified;
> + }
> + if outdated_after.is_some() { data.outdated_after = outdated_after }
> + if schedule.is_some() { data.schedule = schedule; }
> +
> + config.set_data(&id, "verify", &data)?;
> +
> + verify::save_config(&config)?;
> +
> + Ok(())
> +}
> +
> +#[api(
> + protected: true,
> + input: {
> + properties: {
> + id: {
> + schema: JOB_ID_SCHEMA,
> + },
> + digest: {
> + optional: true,
> + schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
> + },
> + },
> + },
> +)]
> +/// Remove a verify job configuration
> +pub fn delete_verify_job(id: String, digest: Option<String>) -> Result<(), Error> {
> +
> + let _lock = open_file_locked(verify::VERIFY_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
> +
> + let (mut config, expected_digest) = verify::config()?;
> +
> + if let Some(ref digest) = digest {
> + let digest = proxmox::tools::hex_to_digest(digest)?;
> + crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
> + }
> +
> + match config.sections.get(&id) {
> + Some(_) => { config.sections.remove(&id); },
> + None => bail!("job '{}' does not exist.", id),
> + }
> +
> + verify::save_config(&config)?;
> +
> + crate::config::jobstate::remove_state_file("verifyjob", &id)?;
> +
> + Ok(())
> +}
> +
> +const ITEM_ROUTER: Router = Router::new()
> + .get(&API_METHOD_READ_VERIFY_JOB)
> + .put(&API_METHOD_UPDATE_VERIFY_JOB)
> + .delete(&API_METHOD_DELETE_VERIFY_JOB);
> +
> +pub const ROUTER: Router = Router::new()
> + .get(&API_METHOD_LIST_VERIFY_JOBS)
> + .post(&API_METHOD_CREATE_VERIFY_JOB)
> + .match_all("id", &ITEM_ROUTER);
> \ No newline at end of file
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [pbs-devel] [PATCH v1 proxmox-backup 04/14] add do_verification_job function to verify.rs
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 04/14] add do_verification_job function to verify.rs Hannes Laimer
@ 2020-10-01 10:40 ` Dominik Csapak
0 siblings, 0 replies; 21+ messages in thread
From: Dominik Csapak @ 2020-10-01 10:40 UTC (permalink / raw)
To: pbs-devel
high-level: i am not sure i would put that code here
it makes the verify code even more intertwined with the worker-tasks
which is not something that is optimal (the verify code should have no
dependency on a worker task imho)
some comments inline
On 9/25/20 10:43 AM, Hannes Laimer wrote:
> Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
> ---
> src/backup/verify.rs | 91 +++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 90 insertions(+), 1 deletion(-)
>
> diff --git a/src/backup/verify.rs b/src/backup/verify.rs
> index 1fad6187..1f54ebeb 100644
> --- a/src/backup/verify.rs
> +++ b/src/backup/verify.rs
> @@ -5,8 +5,10 @@ use std::time::Instant;
>
> use anyhow::{bail, format_err, Error};
>
> -use crate::server::WorkerTask;
> +use crate::server::{WorkerTask, TaskState};
> use crate::api2::types::*;
> +use crate::config::jobstate::Job;
> +use crate::config::verify::VerifyJobConfig;
>
> use super::{
> DataStore, DataBlob, BackupGroup, BackupDir, BackupInfo, IndexFile,
> @@ -432,3 +434,90 @@ pub fn verify_all_backups(datastore: Arc<DataStore>, worker: Arc<WorkerTask>) ->
>
> Ok(errors)
> }
> +
> +/// Runs a verification job.
> +pub fn do_verification_job(
> + mut job: Job,
> + verify_job: VerifyJobConfig,
> + userid: &Userid,
> + schedule: Option<String>,
> +) -> Result<String, Error> {
> + let datastore = DataStore::lookup_datastore(&verify_job.store)?;
> +
> + let mut backups_to_verify = BackupInfo::list_backups(&datastore.base_path())?;
> +
> + if verify_job.ignore_verified {
> + backups_to_verify.retain(|backup_info| {
> + if let Ok((manifest, _)) = datastore.load_manifest(&backup_info.backup_dir) {
> + let verify = manifest.unprotected["verify_state"].clone();
> + if let Ok(verify) = serde_json::from_value::<SnapshotVerifyState>(verify) {
> + let days_since_last_verify =
> + (proxmox::tools::time::epoch_i64() - verify.upid.starttime) / 86400;
> + // if last verification failed we have to verify again since it might be fixed OR
> + // if outdated_after is None, verifications do not become outdated
> + verify.state == VerifyState::Failed || (verify_job.outdated_after.is_some()
> + && days_since_last_verify > verify_job.outdated_after.unwrap())
after talking some days ago with thomas, it may not be the best way to
try to re-verify failed backups so maybe we can simply drop this and
only verify 'non-verified' backups
> + } else { true } // was never verified, therefore we always want to verify
> + } else { false } // manifest could not be loaded, do not verify in that case
> + })
> + }
> +
> + let job_id = job.jobname().to_string();
> + let worker_type = job.jobtype().to_string();
> +
> + let upid_str = WorkerTask::new_thread(
> + &worker_type,
> + Some(job.jobname().to_string()),
> + userid.clone(),
> + false,
> + move |worker| {
> + job.start(&worker.upid().to_string())?;
> +
> + let verified_chunks = Arc::new(Mutex::new(HashSet::with_capacity(1024 * 16)));
> + let corrupt_chunks = Arc::new(Mutex::new(HashSet::with_capacity(64)));
> +
> + worker.log(format!("Starting datastore verify job '{}'", job_id));
> + if let Some(event_str) = schedule {
> + worker.log(format!("task triggered by schedule '{}'", event_str));
> + }
> +
> + let mut failed_dirs: Vec<String> = Vec::new();
> + for backup_info in backups_to_verify {
> + match verify_backup_dir(
> + datastore.clone(),
> + &backup_info.backup_dir,
> + verified_chunks.clone(),
> + corrupt_chunks.clone(),
> + worker.clone(),
> + ) {
> + Ok(false) => failed_dirs.push(backup_info.backup_dir.to_string()),
> + Err(err) => {
> + let endtime = proxmox::tools::time::epoch_i64();
> + job.finish(TaskState::Error {
> + message: err.to_string(),
> + endtime
> + })?;
> + bail!(err.to_string());
here you can use our 'try_block' macro, i would it do it like so:
let result = proxmox::try_block!({
// basically the whole 'real' worker code
// this can use '?'/bail to bubble up errors
});
// here goes only one regular job.finish call
> + },
> + _ => {}
> + }
> + }
> + if !failed_dirs.is_empty() {
> + worker.log("Failed to verify following snapshots:");
> + for dir in failed_dirs {
> + worker.log(format!("\t{}", dir));
> + }
> + let endtime = proxmox::tools::time::epoch_i64();
> + job.finish(TaskState::Error {
> + message: String::from("verification failed - please check the log for details"),
> + endtime
> + })?;
> + bail!("verification failed - please check the log for details");
> + }
> + let endtime = proxmox::tools::time::epoch_i64();
> + job.finish(TaskState::OK { endtime })?;
> + Ok(())
> + })?;
> +
> + Ok(upid_str)
> +}
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [pbs-devel] [PATCH v1 proxmox-backup 08/14] ui: add verify job view
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 08/14] ui: add verify job view Hannes Laimer
@ 2020-10-01 10:40 ` Dominik Csapak
0 siblings, 0 replies; 21+ messages in thread
From: Dominik Csapak @ 2020-10-01 10:40 UTC (permalink / raw)
To: pbs-devel
i'd
make the 'days-valid' columns bigger, by default only 'D...' is visible
add the 'ignore verified' as column also
rest looks good (altough we should refactor some of the
renderer/calculations if we add another schedule panel)
On 9/25/20 10:43 AM, Hannes Laimer wrote:
> Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
> ---
> www/Makefile | 1 +
> www/NavigationTree.js | 6 +
> www/config/VerifyView.js | 273 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 280 insertions(+)
> create mode 100644 www/config/VerifyView.js
>
> diff --git a/www/Makefile b/www/Makefile
> index 90a98b74..48d06266 100644
> --- a/www/Makefile
> +++ b/www/Makefile
> @@ -16,6 +16,7 @@ JSSRC= \
> config/RemoteView.js \
> config/ACLView.js \
> config/SyncView.js \
> + config/VerifyView.js \
> config/DataStoreConfig.js \
> window/UserEdit.js \
> window/UserPassword.js \
> diff --git a/www/NavigationTree.js b/www/NavigationTree.js
> index 0fd9458d..21b9b2a6 100644
> --- a/www/NavigationTree.js
> +++ b/www/NavigationTree.js
> @@ -42,6 +42,12 @@ Ext.define('PBS.store.NavigationStore', {
> path: 'pbsSyncJobView',
> leaf: true,
> },
> + {
> + text: gettext('Verify Jobs'),
> + iconCls: 'fa fa-check-circle',
> + path: 'pbsVerifyJobView',
> + leaf: true,
> + },
> {
> text: gettext('Subscription'),
> iconCls: 'fa fa-support',
> diff --git a/www/config/VerifyView.js b/www/config/VerifyView.js
> new file mode 100644
> index 00000000..e8722eb9
> --- /dev/null
> +++ b/www/config/VerifyView.js
> @@ -0,0 +1,273 @@
> +Ext.define('pbs-verify-jobs-status', {
> + extend: 'Ext.data.Model',
> + fields: [
> + 'id', 'store', 'outdated-after', 'schedule',
> + 'next-run', 'last-run-upid', 'last-run-state', 'last-run-endtime',
> + {
> + name: 'duration',
> + calculate: function(data) {
> + let endtime = data['last-run-endtime'];
> + if (!endtime) return undefined;
> + let task = Proxmox.Utils.parse_task_upid(data['last-run-upid']);
> + return endtime - task.starttime;
> + },
> + },
> + ],
> + idProperty: 'id',
> + proxy: {
> + type: 'proxmox',
> + url: '/api2/json/admin/verify',
> + },
> +});
> +
> +Ext.define('PBS.config.VerifyJobView', {
> + extend: 'Ext.grid.GridPanel',
> + alias: 'widget.pbsVerifyJobView',
> +
> + stateful: true,
> + stateId: 'grid-verify-jobs',
> +
> + title: gettext('Verify Jobs'),
> +
> + controller: {
> + xclass: 'Ext.app.ViewController',
> +
> + addVerifyJob: function() {
> + let me = this;
> + Ext.create('PBS.window.VerifyJobEdit', {
> + listeners: {
> + destroy: function() {
> + me.reload();
> + },
> + },
> + }).show();
> + },
> +
> + editVerifyJob: function() {
> + let me = this;
> + let view = me.getView();
> + let selection = view.getSelection();
> + if (selection.length < 1) return;
> +
> + Ext.create('PBS.window.VerifyJobEdit', {
> + id: selection[0].data.id,
> + listeners: {
> + destroy: function() {
> + me.reload();
> + },
> + },
> + }).show();
> + },
> +
> + openTaskLog: function() {
> + let me = this;
> + let view = me.getView();
> + let selection = view.getSelection();
> + if (selection.length < 1) return;
> +
> + let upid = selection[0].data['last-run-upid'];
> + if (!upid) return;
> +
> + Ext.create('Proxmox.window.TaskViewer', {
> + upid
> + }).show();
> + },
> +
> + runVerifyJob: function() {
> + let me = this;
> + let view = me.getView();
> + let selection = view.getSelection();
> + if (selection.length < 1) return;
> +
> + let id = selection[0].data.id;
> + Proxmox.Utils.API2Request({
> + method: 'POST',
> + url: `/admin/verify/${id}/run`,
> + success: function(response, opt) {
> + Ext.create('Proxmox.window.TaskViewer', {
> + upid: response.result.data,
> + taskDone: function(success) {
> + me.reload();
> + },
> + }).show();
> + },
> + failure: function(response, opt) {
> + Ext.Msg.alert(gettext('Error'), response.htmlStatus);
> + },
> + });
> + },
> +
> + render_verify_status: function(value, metadata, record) {
> + if (!record.data['last-run-upid']) {
> + return '-';
> + }
> +
> + if (!record.data['last-run-endtime']) {
> + metadata.tdCls = 'x-grid-row-loading';
> + return '';
> + }
> +
> + let parsed = Proxmox.Utils.parse_task_status(value);
> + let text = value;
> + let icon = '';
> + switch (parsed) {
> + case 'unknown':
> + icon = 'question faded';
> + text = Proxmox.Utils.unknownText;
> + break;
> + case 'error':
> + icon = 'times critical';
> + text = Proxmox.Utils.errorText + ': ' + value;
> + break;
> + case 'warning':
> + icon = 'exclamation warning';
> + break;
> + case 'ok':
> + icon = 'check good';
> + text = gettext("OK");
> + }
> +
> + return `<i class="fa fa-${icon}"></i> ${text}`;
> + },
> +
> + render_next_run: function(value, metadat, record) {
> + if (!value) return '-';
> +
> + let now = new Date();
> + let next = new Date(value*1000);
> +
> + if (next < now) {
> + return gettext('pending');
> + }
> + return Proxmox.Utils.render_timestamp(value);
> + },
> +
> + render_optional_timestamp: function(value, metadata, record) {
> + if (!value) return '-';
> + return Proxmox.Utils.render_timestamp(value);
> + },
> +
> + reload: function() { this.getView().getStore().rstore.load(); },
> +
> + init: function(view) {
> + Proxmox.Utils.monStoreErrors(view, view.getStore().rstore);
> + },
> + },
> +
> + listeners: {
> + activate: 'reload',
> + itemdblclick: 'editVerifyJob',
> + },
> +
> + store: {
> + type: 'diff',
> + autoDestroy: true,
> + autoDestroyRstore: true,
> + sorters: 'id',
> + rstore: {
> + type: 'update',
> + storeid: 'pbs-verify-jobs-status',
> + model: 'pbs-verify-jobs-status',
> + autoStart: true,
> + interval: 5000,
> + },
> + },
> +
> + tbar: [
> + {
> + xtype: 'proxmoxButton',
> + text: gettext('Add'),
> + handler: 'addVerifyJob',
> + selModel: false,
> + },
> + {
> + xtype: 'proxmoxButton',
> + text: gettext('Edit'),
> + handler: 'editVerifyJob',
> + disabled: true,
> + },
> + {
> + xtype: 'proxmoxStdRemoveButton',
> + baseurl: '/config/verify/',
> + callback: 'reload',
> + },
> + '-',
> + {
> + xtype: 'proxmoxButton',
> + text: gettext('Log'),
> + handler: 'openTaskLog',
> + enableFn: (rec) => !!rec.data['last-run-upid'],
> + disabled: true,
> + },
> + {
> + xtype: 'proxmoxButton',
> + text: gettext('Run now'),
> + handler: 'runVerifyJob',
> + disabled: true,
> + },
> + ],
> +
> + viewConfig: {
> + trackOver: false,
> + },
> +
> + columns: [
> + {
> + header: gettext('Verify Job'),
> + width: 100,
> + sortable: true,
> + renderer: Ext.String.htmlEncode,
> + dataIndex: 'id',
> + },
> + {
> + header: gettext('Datastore'),
> + width: 100,
> + sortable: true,
> + dataIndex: 'store',
> + },
> + {
> + header: gettext('Days valid'),
> + width: 50,
> + sortable: true,
> + dataIndex: 'outdated-after',
> + },
> + {
> + header: gettext('Schedule'),
> + sortable: true,
> + dataIndex: 'schedule',
> + },
> + {
> + header: gettext('Status'),
> + dataIndex: 'last-run-state',
> + flex: 1,
> + renderer: 'render_verify_status',
> + },
> + {
> + header: gettext('Last Verification'),
> + sortable: true,
> + minWidth: 200,
> + renderer: 'render_optional_timestamp',
> + dataIndex: 'last-run-endtime',
> + },
> + {
> + text: gettext('Duration'),
> + dataIndex: 'duration',
> + width: 60,
> + renderer: Proxmox.Utils.render_duration,
> + },
> + {
> + header: gettext('Next Run'),
> + sortable: true,
> + minWidth: 200,
> + renderer: 'render_next_run',
> + dataIndex: 'next-run',
> + },
> + {
> + header: gettext('Comment'),
> + hidden: true,
> + sortable: true,
> + renderer: Ext.String.htmlEncode,
> + dataIndex: 'comment',
> + },
> + ],
> +});
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling
2020-10-01 10:39 ` [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Dominik Csapak
@ 2020-10-01 12:21 ` Dietmar Maurer
2020-10-02 6:35 ` Dominik Csapak
0 siblings, 1 reply; 21+ messages in thread
From: Dietmar Maurer @ 2020-10-01 12:21 UTC (permalink / raw)
To: Proxmox Backup Server development discussion, Dominik Csapak
> * we sadly cannot simply remove the 'verify-schedule' from the
> datastore configs, as we already have packages out there that support
> it and it breaks all datastore config parsing
I have no problem with that! We are first beta, so there is absolutely no need
to be compatible.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling
2020-10-01 12:21 ` Dietmar Maurer
@ 2020-10-02 6:35 ` Dominik Csapak
0 siblings, 0 replies; 21+ messages in thread
From: Dominik Csapak @ 2020-10-02 6:35 UTC (permalink / raw)
To: Dietmar Maurer, Proxmox Backup Server development discussion
On 10/1/20 2:21 PM, Dietmar Maurer wrote:
>> * we sadly cannot simply remove the 'verify-schedule' from the
>> datastore configs, as we already have packages out there that support
>> it and it breaks all datastore config parsing
>
> I have no problem with that! We are first beta, so there is absolutely no need
> to be compatible.
>
mhmm ok, but it breaks all functionality... e.g. if i have in any
datastore a 'verify-schedule' now, i cannot do anything
after the update until i manually go into the config file and delete
that line, even for a beta, not a great experience
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2020-10-02 6:36 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-25 8:43 [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 01/14] add two new schemas for verify jobs Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 02/14] add verify job config Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 03/14] api2: add verify job config endpoint Hannes Laimer
2020-10-01 10:40 ` Dominik Csapak
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 04/14] add do_verification_job function to verify.rs Hannes Laimer
2020-10-01 10:40 ` Dominik Csapak
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 05/14] api2: add verify job admin endpoint Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 06/14] add scheduling for verify jobs Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 07/14] set a diffrent worker_type based on what is going to be verified(snapshot, group, ds) Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 08/14] ui: add verify job view Hannes Laimer
2020-10-01 10:40 ` Dominik Csapak
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 09/14] ui: add verify job edit window Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 10/14] ui: add task descriptions for the different types of verify(job, snapshot, group, ds) Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 11/14] remove verify_schedule field from DatastoreConfig Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 12/14] remove verify_schedule field from datastore config endpoint Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 13/14] remove verify-schedule field from DataStoreEdit and DataStoreConfig Hannes Laimer
2020-09-25 8:43 ` [pbs-devel] [PATCH v1 proxmox-backup 14/14] remove old verification scheduling from proxmox-backup-proxy.rs Hannes Laimer
2020-10-01 10:39 ` [pbs-devel] [PATCH v1 proxmox-backup 00/14] add job based verify scheduling Dominik Csapak
2020-10-01 12:21 ` Dietmar Maurer
2020-10-02 6:35 ` Dominik Csapak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox