diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs index 9a549fb0..0ef4240b 100644 --- a/pbs-api-types/src/datastore.rs +++ b/pbs-api-types/src/datastore.rs @@ -1060,9 +1060,22 @@ pub struct DatastoreWithNamespace { impl fmt::Display for DatastoreWithNamespace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.ns.is_root() { - write!(f, "{}", self.store) + write!(f, "datastore {}, root namespace", self.store) } else { - write!(f, "{}/{}", self.store, self.ns) + write!(f, "datastore '{}', namespace '{}'", self.store, self.ns) + } + } +} + +impl DatastoreWithNamespace { + pub fn acl_path(&self) -> Vec<&str> { + let mut path: Vec<&str> = vec!["datastore", &self.store]; + + if self.ns.is_root() { + path + } else { + path.extend(self.ns.inner.iter().map(|comp| comp.as_str())); + path } } } diff --git a/pbs-api-types/src/jobs.rs b/pbs-api-types/src/jobs.rs index 87009b3a..368e60e3 100644 --- a/pbs-api-types/src/jobs.rs +++ b/pbs-api-types/src/jobs.rs @@ -9,15 +9,15 @@ use proxmox_schema::*; use crate::{ Authid, BackupNamespace, BackupType, RateLimitConfig, Userid, BACKUP_GROUP_SCHEMA, BACKUP_NAMESPACE_SCHEMA, DATASTORE_SCHEMA, DRIVE_NAME_SCHEMA, MEDIA_POOL_NAME_SCHEMA, - PROXMOX_SAFE_ID_FORMAT, REMOTE_ID_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA, + NS_MAX_DEPTH_SCHEMA, PROXMOX_SAFE_ID_FORMAT, REMOTE_ID_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA, }; const_regex! { /// Regex for verification jobs 'DATASTORE:ACTUAL_JOB_ID' pub VERIFICATION_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):"); - /// Regex for sync jobs 'REMOTE:REMOTE_DATASTORE:LOCAL_DATASTORE:ACTUAL_JOB_ID' - pub SYNC_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):"); + /// Regex for sync jobs 'REMOTE:REMOTE_DATASTORE:LOCAL_DATASTORE:(?:LOCAL_NS_ANCHOR:)ACTUAL_JOB_ID' + pub SYNC_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(?:", BACKUP_NS_RE!(), r"):"); } pub const JOB_ID_SCHEMA: Schema = StringSchema::new("Job ID.") @@ -413,6 +413,10 @@ pub const GROUP_FILTER_LIST_SCHEMA: Schema = store: { schema: DATASTORE_SCHEMA, }, + ns: { + type: BackupNamespace, + optional: true, + }, "owner": { type: Authid, optional: true, @@ -423,10 +427,18 @@ pub const GROUP_FILTER_LIST_SCHEMA: Schema = "remote-store": { schema: DATASTORE_SCHEMA, }, + "remote-ns": { + type: BackupNamespace, + optional: true, + }, "remove-vanished": { schema: REMOVE_VANISHED_BACKUPS_SCHEMA, optional: true, }, + "max-depth": { + schema: NS_MAX_DEPTH_SCHEMA, + optional: true, + }, comment: { optional: true, schema: SINGLE_LINE_COMMENT_SCHEMA, @@ -452,11 +464,17 @@ pub struct SyncJobConfig { pub id: String, pub store: String, #[serde(skip_serializing_if = "Option::is_none")] + pub ns: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub owner: Option, pub remote: String, pub remote_store: String, #[serde(skip_serializing_if = "Option::is_none")] + pub remote_ns: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub remove_vanished: Option, + #[serde(default)] + pub max_depth: usize, #[serde(skip_serializing_if = "Option::is_none")] pub comment: Option, #[serde(skip_serializing_if = "Option::is_none")]