]> git.proxmox.com Git - proxmox-backup.git/blame - src/bin/proxmox_backup_client/snapshot.rs
cli: use new alias feature for "snapshots"
[proxmox-backup.git] / src / bin / proxmox_backup_client / snapshot.rs
CommitLineData
a65e3e4b
DC
1use anyhow::Error;
2use serde_json::{json, Value};
3
4use proxmox::api::{api, cli::*};
731eeef2
DM
5use proxmox_backup::{
6 tools,
7 api2::types::*,
8 backup::{
9 BackupGroup,
10 }
11};
a65e3e4b
DC
12
13use crate::{
731eeef2
DM
14 REPO_URL_SCHEMA,
15 BackupDir,
16 api_datastore_list_snapshots,
17 complete_backup_snapshot,
18 complete_backup_group,
19 complete_repository,
20 connect,
21 extract_repository_from_value,
22 record_repository,
a65e3e4b
DC
23};
24
731eeef2
DM
25#[api(
26 input: {
27 properties: {
28 repository: {
29 schema: REPO_URL_SCHEMA,
30 optional: true,
31 },
32 group: {
33 type: String,
34 description: "Backup group.",
35 optional: true,
36 },
37 "output-format": {
38 schema: OUTPUT_FORMAT,
39 optional: true,
40 },
41 }
42 }
43)]
44/// List backup snapshots.
45async fn list_snapshots(param: Value) -> Result<Value, Error> {
46
47 let repo = extract_repository_from_value(&param)?;
48
49 let output_format = get_output_format(&param);
50
51 let client = connect(&repo)?;
52
53 let group: Option<BackupGroup> = if let Some(path) = param["group"].as_str() {
54 Some(path.parse()?)
55 } else {
56 None
57 };
58
59 let mut data = api_datastore_list_snapshots(&client, repo.store(), group).await?;
60
61 record_repository(&repo);
62
63 let render_snapshot_path = |_v: &Value, record: &Value| -> Result<String, Error> {
64 let item: SnapshotListItem = serde_json::from_value(record.to_owned())?;
65 let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.backup_time)?;
66 Ok(snapshot.relative_path().to_str().unwrap().to_owned())
67 };
68
69 let render_files = |_v: &Value, record: &Value| -> Result<String, Error> {
70 let item: SnapshotListItem = serde_json::from_value(record.to_owned())?;
71 let mut filenames = Vec::new();
72 for file in &item.files {
73 filenames.push(file.filename.to_string());
74 }
75 Ok(tools::format::render_backup_file_list(&filenames[..]))
76 };
77
78 let options = default_table_format_options()
79 .sortby("backup-type", false)
80 .sortby("backup-id", false)
81 .sortby("backup-time", false)
82 .column(ColumnConfig::new("backup-id").renderer(render_snapshot_path).header("snapshot"))
83 .column(ColumnConfig::new("size").renderer(tools::format::render_bytes_human_readable))
84 .column(ColumnConfig::new("files").renderer(render_files))
85 ;
86
87 let info = &proxmox_backup::api2::admin::datastore::API_RETURN_SCHEMA_LIST_SNAPSHOTS;
88
89 format_and_print_result_full(&mut data, info, &output_format, &options);
90
91 Ok(Value::Null)
92}
93
a65e3e4b
DC
94#[api(
95 input: {
96 properties: {
97 repository: {
98 schema: REPO_URL_SCHEMA,
99 optional: true,
100 },
101 snapshot: {
102 type: String,
103 description: "Snapshot path.",
104 },
105 "output-format": {
106 schema: OUTPUT_FORMAT,
107 optional: true,
108 },
109 }
110 }
111)]
112/// Show notes
113async fn show_notes(param: Value) -> Result<Value, Error> {
114 let repo = extract_repository_from_value(&param)?;
115 let path = tools::required_string_param(&param, "snapshot")?;
116
117 let snapshot: BackupDir = path.parse()?;
118 let client = connect(&repo)?;
119
120 let path = format!("api2/json/admin/datastore/{}/notes", repo.store());
121
122 let args = json!({
123 "backup-type": snapshot.group().backup_type(),
124 "backup-id": snapshot.group().backup_id(),
125 "backup-time": snapshot.backup_time(),
126 });
127
128 let output_format = get_output_format(&param);
129
130 let mut result = client.get(&path, Some(args)).await?;
131
132 let notes = result["data"].take();
133
134 if output_format == "text" {
135 if let Some(notes) = notes.as_str() {
136 println!("{}", notes);
137 }
138 } else {
139 format_and_print_result(
140 &json!({
141 "notes": notes,
142 }),
143 &output_format,
144 );
145 }
146
147 Ok(Value::Null)
148}
149
150#[api(
151 input: {
152 properties: {
153 repository: {
154 schema: REPO_URL_SCHEMA,
155 optional: true,
156 },
157 snapshot: {
158 type: String,
159 description: "Snapshot path.",
160 },
161 notes: {
162 type: String,
163 description: "The Notes.",
164 },
165 }
166 }
167)]
168/// Update Notes
169async fn update_notes(param: Value) -> Result<Value, Error> {
170 let repo = extract_repository_from_value(&param)?;
171 let path = tools::required_string_param(&param, "snapshot")?;
172 let notes = tools::required_string_param(&param, "notes")?;
173
174 let snapshot: BackupDir = path.parse()?;
175 let mut client = connect(&repo)?;
176
177 let path = format!("api2/json/admin/datastore/{}/notes", repo.store());
178
179 let args = json!({
180 "backup-type": snapshot.group().backup_type(),
181 "backup-id": snapshot.group().backup_id(),
182 "backup-time": snapshot.backup_time(),
183 "notes": notes,
184 });
185
186 client.put(&path, Some(args)).await?;
187
188 Ok(Value::Null)
189}
190
191fn notes_cli() -> CliCommandMap {
192 CliCommandMap::new()
193 .insert(
194 "show",
195 CliCommand::new(&API_METHOD_SHOW_NOTES)
196 .arg_param(&["snapshot"])
197 .completion_cb("snapshot", complete_backup_snapshot),
198 )
199 .insert(
200 "update",
201 CliCommand::new(&API_METHOD_UPDATE_NOTES)
202 .arg_param(&["snapshot", "notes"])
203 .completion_cb("snapshot", complete_backup_snapshot),
204 )
205}
206
207pub fn snapshot_mgtm_cli() -> CliCommandMap {
731eeef2
DM
208 CliCommandMap::new()
209 .insert("notes", notes_cli())
210 .insert(
211 "list", CliCommand::new(&API_METHOD_LIST_SNAPSHOTS)
212 .arg_param(&["group"])
213 .completion_cb("group", complete_backup_group)
214 .completion_cb("repository", complete_repository)
215 )
a65e3e4b 216}