diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index 9e9b2e23..9487bcf4 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -60,21 +60,34 @@ fn group_backups(backup_list: Vec) -> HashMap Result { + store: String, +) -> Result, Error> { - let store = param["store"].as_str().unwrap(); - - let datastore = DataStore::lookup_datastore(store)?; + let datastore = DataStore::lookup_datastore(&store)?; let backup_list = BackupInfo::list_backups(&datastore.base_path())?; let group_hash = group_backups(backup_list); - let mut groups = vec![]; + let mut groups = Vec::new(); for (_group_id, mut list) in group_hash { @@ -83,16 +96,17 @@ fn list_groups( let info = &list[0]; let group = info.backup_dir.group(); - groups.push(json!({ - "backup-type": group.backup_type(), - "backup-id": group.backup_id(), - "last-backup": info.backup_dir.backup_time().timestamp(), - "backup-count": list.len() as u64, - "files": info.files, - })); + let result_item = GroupListItem { + backup_type: group.backup_type().to_string(), + backup_id: group.backup_id().to_string(), + last_backup: info.backup_dir.backup_time().timestamp(), + backup_count: list.len() as u64, + files: info.files.clone(), + }; + groups.push(result_item); } - Ok(json!(groups)) + Ok(groups) } fn list_snapshot_files ( @@ -652,15 +666,7 @@ const DATASTORE_INFO_SUBDIRS: SubdirMap = &[ ( "groups", &Router::new() - .get( - &ApiMethod::new( - &ApiHandler::Sync(&list_groups), - &ObjectSchema::new( - "List backup groups.", - &sorted!([ ("store", false, &DATASTORE_SCHEMA) ]), - ) - ) - ) + .get(&API_METHOD_LIST_GROUPS) ), ( "prune", diff --git a/src/api2/pull.rs b/src/api2/pull.rs index 7028593a..072df5db 100644 --- a/src/api2/pull.rs +++ b/src/api2/pull.rs @@ -299,17 +299,12 @@ pub async fn pull_store( let mut result = client.get(&path, None).await?; - let list = result["data"].as_array_mut().unwrap(); + let mut list: Vec = serde_json::from_value(result["data"].take())?; list.sort_unstable_by(|a, b| { - let a_id = a["backup-id"].as_str().unwrap(); - let a_backup_type = a["backup-type"].as_str().unwrap(); - let b_id = b["backup-id"].as_str().unwrap(); - let b_backup_type = b["backup-type"].as_str().unwrap(); - - let type_order = a_backup_type.cmp(b_backup_type); + let type_order = a.backup_type.cmp(&b.backup_type); if type_order == std::cmp::Ordering::Equal { - a_id.cmp(b_id) + a.backup_id.cmp(&b.backup_id) } else { type_order } @@ -318,13 +313,9 @@ pub async fn pull_store( let mut errors = false; for item in list { - - let id = item["backup-id"].as_str().unwrap(); - let btype = item["backup-type"].as_str().unwrap(); - - let group = BackupGroup::new(btype, id); + let group = BackupGroup::new(&item.backup_type, &item.backup_id); if let Err(err) = pull_group(worker, client, src_repo, tgt_store.clone(), &group).await { - worker.log(format!("sync group {}/{} failed - {}", btype, id, err)); + worker.log(format!("sync group {}/{} failed - {}", item.backup_type, item.backup_id, err)); errors = true; // continue } diff --git a/src/api2/types.rs b/src/api2/types.rs index 86decc7b..8a3d6ea4 100644 --- a/src/api2/types.rs +++ b/src/api2/types.rs @@ -192,6 +192,40 @@ pub const PROXMOX_USER_ID_SCHEMA: Schema = StringSchema::new("User ID") // Complex type definitions +#[api( + properties: { + "backup-type": { + schema: BACKUP_TYPE_SCHEMA, + }, + "backup-id": { + schema: BACKUP_ID_SCHEMA, + }, + "last-backup": { + schema: BACKUP_TIME_SCHEMA, + }, + "backup-count": { + type: Integer, + }, + files: { + items: { + schema: BACKUP_ARCHIVE_NAME_SCHEMA + }, + }, + }, +)] +#[derive(Serialize, Deserialize)] +#[serde(rename_all="kebab-case")] +/// Basic information about a backup group. +pub struct GroupListItem { + pub backup_type: String, // enum + pub backup_id: String, + pub last_backup: i64, + /// Number of contained snapshots + pub backup_count: u64, + /// List of contained archive files. + pub files: Vec, +} + #[api( properties: { "backup-type": {