]> git.proxmox.com Git - proxmox-backup.git/blame - src/bin/proxmox_backup_client/snapshot.rs
cli: rename command "forget" to "snapshot forget"
[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
61205f00
DM
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/// List snapshot files.
113async fn list_snapshot_files(param: Value) -> Result<Value, Error> {
114
115 let repo = extract_repository_from_value(&param)?;
116
117 let path = tools::required_string_param(&param, "snapshot")?;
118 let snapshot: BackupDir = path.parse()?;
119
120 let output_format = get_output_format(&param);
121
122 let client = connect(&repo)?;
123
124 let path = format!("api2/json/admin/datastore/{}/files", repo.store());
125
126 let mut result = client.get(&path, Some(json!({
127 "backup-type": snapshot.group().backup_type(),
128 "backup-id": snapshot.group().backup_id(),
129 "backup-time": snapshot.backup_time(),
130 }))).await?;
131
132 record_repository(&repo);
133
134 let info = &proxmox_backup::api2::admin::datastore::API_RETURN_SCHEMA_LIST_SNAPSHOT_FILES;
135
136 let mut data: Value = result["data"].take();
137
138 let options = default_table_format_options();
139
140 format_and_print_result_full(&mut data, info, &output_format, &options);
141
142 Ok(Value::Null)
143}
144
edebd523
DM
145#[api(
146 input: {
147 properties: {
148 repository: {
149 schema: REPO_URL_SCHEMA,
150 optional: true,
151 },
152 snapshot: {
153 type: String,
154 description: "Snapshot path.",
155 },
156 }
157 }
158)]
159/// Forget (remove) backup snapshots.
160async fn forget_snapshots(param: Value) -> Result<Value, Error> {
161
162 let repo = extract_repository_from_value(&param)?;
163
164 let path = tools::required_string_param(&param, "snapshot")?;
165 let snapshot: BackupDir = path.parse()?;
166
167 let mut client = connect(&repo)?;
168
169 let path = format!("api2/json/admin/datastore/{}/snapshots", repo.store());
170
171 let result = client.delete(&path, Some(json!({
172 "backup-type": snapshot.group().backup_type(),
173 "backup-id": snapshot.group().backup_id(),
174 "backup-time": snapshot.backup_time(),
175 }))).await?;
176
177 record_repository(&repo);
178
179 Ok(result)
180}
181
a65e3e4b
DC
182#[api(
183 input: {
184 properties: {
185 repository: {
186 schema: REPO_URL_SCHEMA,
187 optional: true,
188 },
189 snapshot: {
190 type: String,
191 description: "Snapshot path.",
192 },
193 "output-format": {
194 schema: OUTPUT_FORMAT,
195 optional: true,
196 },
197 }
198 }
199)]
200/// Show notes
201async fn show_notes(param: Value) -> Result<Value, Error> {
202 let repo = extract_repository_from_value(&param)?;
203 let path = tools::required_string_param(&param, "snapshot")?;
204
205 let snapshot: BackupDir = path.parse()?;
206 let client = connect(&repo)?;
207
208 let path = format!("api2/json/admin/datastore/{}/notes", repo.store());
209
210 let args = json!({
211 "backup-type": snapshot.group().backup_type(),
212 "backup-id": snapshot.group().backup_id(),
213 "backup-time": snapshot.backup_time(),
214 });
215
216 let output_format = get_output_format(&param);
217
218 let mut result = client.get(&path, Some(args)).await?;
219
220 let notes = result["data"].take();
221
222 if output_format == "text" {
223 if let Some(notes) = notes.as_str() {
224 println!("{}", notes);
225 }
226 } else {
227 format_and_print_result(
228 &json!({
229 "notes": notes,
230 }),
231 &output_format,
232 );
233 }
234
235 Ok(Value::Null)
236}
237
238#[api(
239 input: {
240 properties: {
241 repository: {
242 schema: REPO_URL_SCHEMA,
243 optional: true,
244 },
245 snapshot: {
246 type: String,
247 description: "Snapshot path.",
248 },
249 notes: {
250 type: String,
251 description: "The Notes.",
252 },
253 }
254 }
255)]
256/// Update Notes
257async fn update_notes(param: Value) -> Result<Value, Error> {
258 let repo = extract_repository_from_value(&param)?;
259 let path = tools::required_string_param(&param, "snapshot")?;
260 let notes = tools::required_string_param(&param, "notes")?;
261
262 let snapshot: BackupDir = path.parse()?;
263 let mut client = connect(&repo)?;
264
265 let path = format!("api2/json/admin/datastore/{}/notes", repo.store());
266
267 let args = json!({
268 "backup-type": snapshot.group().backup_type(),
269 "backup-id": snapshot.group().backup_id(),
270 "backup-time": snapshot.backup_time(),
271 "notes": notes,
272 });
273
274 client.put(&path, Some(args)).await?;
275
276 Ok(Value::Null)
277}
278
279fn notes_cli() -> CliCommandMap {
280 CliCommandMap::new()
281 .insert(
282 "show",
283 CliCommand::new(&API_METHOD_SHOW_NOTES)
284 .arg_param(&["snapshot"])
285 .completion_cb("snapshot", complete_backup_snapshot),
286 )
287 .insert(
288 "update",
289 CliCommand::new(&API_METHOD_UPDATE_NOTES)
290 .arg_param(&["snapshot", "notes"])
291 .completion_cb("snapshot", complete_backup_snapshot),
292 )
293}
294
295pub fn snapshot_mgtm_cli() -> CliCommandMap {
731eeef2
DM
296 CliCommandMap::new()
297 .insert("notes", notes_cli())
298 .insert(
61205f00
DM
299 "list",
300 CliCommand::new(&API_METHOD_LIST_SNAPSHOTS)
731eeef2
DM
301 .arg_param(&["group"])
302 .completion_cb("group", complete_backup_group)
303 .completion_cb("repository", complete_repository)
304 )
61205f00
DM
305 .insert(
306 "files",
307 CliCommand::new(&API_METHOD_LIST_SNAPSHOT_FILES)
308 .arg_param(&["snapshot"])
309 .completion_cb("repository", complete_repository)
310 .completion_cb("snapshot", complete_backup_snapshot)
311 )
edebd523
DM
312 .insert(
313 "forget",
314 CliCommand::new(&API_METHOD_FORGET_SNAPSHOTS)
315 .arg_param(&["snapshot"])
316 .completion_cb("repository", complete_repository)
317 .completion_cb("snapshot", complete_backup_snapshot)
318 )
a65e3e4b 319}