]> git.proxmox.com Git - proxmox-backup.git/commitdiff
src/api2/admin/datastore.rs: impl list_backup_groups
authorDietmar Maurer <dietmar@proxmox.com>
Sat, 2 Mar 2019 10:29:05 +0000 (11:29 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Sat, 2 Mar 2019 10:29:05 +0000 (11:29 +0100)
src/api2/admin/datastore.rs
src/bin/proxmox-backup-client.rs

index 041597fdcc848e1c5488d86d07c6069b9f14c9a4..dccbed74ed68140c8a12f0a56aa83f28a8acc680 100644 (file)
@@ -7,6 +7,7 @@ use serde_json::{json, Value};
 use std::collections::{HashSet, HashMap};
 use chrono::{DateTime, Datelike, Local};
 use std::path::PathBuf;
+use std::sync::Arc;
 
 //use hyper::StatusCode;
 //use hyper::rt::{Future, Stream};
@@ -50,6 +51,39 @@ fn mark_selections<F: Fn(DateTime<Local>, &BackupInfo) -> String> (
     }
 }
 
+fn get_group_list(
+    param: Value,
+    _info: &ApiMethod,
+    _rpcenv: &mut RpcEnvironment,
+) -> Result<Value, Error> {
+
+    let store = param["store"].as_str().unwrap();
+
+    let datastore = DataStore::lookup_datastore(store)?;
+
+    let backup_list =  datastore.list_backups()?;
+
+    let group_hash = group_backups(backup_list);
+
+    let mut groups = vec![];
+
+    for (_group_id, mut list) in group_hash {
+
+        list.sort_unstable_by(|a, b| b.backup_dir.backup_time.cmp(&a.backup_dir.backup_time)); // new backups first
+
+        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(),
+            "num_backups": list.len() as u64,
+        }));
+    }
+
+    Ok(json!(groups))
+}
 
 fn prune(
     param: Value,
@@ -249,17 +283,22 @@ fn get_datastore_list(
 
 pub fn router() -> Router {
 
+    let store_schema: Arc<Schema> = Arc::new(
+        StringSchema::new("Datastore name.").into()
+    );
+
     let datastore_info = Router::new()
         .get(ApiMethod::new(
             |_,_,_| Ok(json!([
                 {"subdir": "backups" },
                 {"subdir": "catar" },
                 {"subdir": "gc" },
+                {"subdir": "groups" },
                 {"subdir": "status" },
                 {"subdir": "prune" },
            ])),
             ObjectSchema::new("Directory index.")
-                .required("store", StringSchema::new("Datastore name.")))
+                .required("store", store_schema.clone()))
         )
         .subdir(
             "backups",
@@ -267,7 +306,7 @@ pub fn router() -> Router {
                 .get(ApiMethod::new(
                     get_backup_list,
                     ObjectSchema::new("List backups.")
-                        .required("store", StringSchema::new("Datastore name.")))))
+                        .required("store", store_schema.clone()))))
         .subdir(
             "catar",
             Router::new()
@@ -278,6 +317,13 @@ pub fn router() -> Router {
             Router::new()
                 .get(api_method_garbage_collection_status())
                 .post(api_method_start_garbage_collection()))
+        .subdir(
+            "groups",
+            Router::new()
+                .get(ApiMethod::new(
+                    get_group_list,
+                    ObjectSchema::new("List backup groups.")
+                        .required("store", store_schema.clone()))))
         .subdir(
             "prune",
             Router::new()
index c48e22b4e55c2769570991341762d38d09e95e6d..a0d8c271b4349e543b33937477650da7c446320d 100644 (file)
@@ -135,6 +135,45 @@ fn list_backups(
     Ok(Value::Null)
 }
 
+fn list_backup_groups(
+    param: Value,
+    _info: &ApiMethod,
+    _rpcenv: &mut RpcEnvironment,
+) -> Result<Value, Error> {
+
+    let repo_url = tools::required_string_param(&param, "repository")?;
+    let repo = BackupRepository::parse(repo_url)?;
+
+    let mut client = HttpClient::new(&repo.host, &repo.user);
+
+    let path = format!("api2/json/admin/datastore/{}/groups", repo.store);
+
+    let result = client.get(&path)?;
+
+    // fixme: implement and use output formatter instead ..
+    let list = result["data"].as_array().unwrap();
+
+    for item in list {
+
+        let id = item["backup_id"].as_str().unwrap();
+        let btype = item["backup_type"].as_str().unwrap();
+        let epoch = item["last_backup"].as_i64().unwrap();
+        let last_backup = Local.timestamp(epoch, 0);
+        let num_backups = item["num_backups"].as_u64().unwrap();
+
+        let group = BackupGroup {
+            backup_type: btype.to_string(),
+            backup_id: id.to_string(),
+        };
+
+        let path = group.group_path().to_str().unwrap().to_owned();
+        println!("{} | {} | {}", path, last_backup.format("%c"), num_backups);
+    }
+
+    //Ok(result)
+    Ok(Value::Null)
+}
+
 fn start_garbage_collection(
     param: Value,
     _info: &ApiMethod,
@@ -318,8 +357,8 @@ fn main() {
 
     let list_cmd_def = CliCommand::new(
         ApiMethod::new(
-            list_backups,
-            ObjectSchema::new("List backups.")
+            list_backup_groups,
+            ObjectSchema::new("List backup groups.")
                 .required("repository", repo_url_schema.clone())
         ))
         .arg_param(vec!["repository"]);