]>
Commit | Line | Data |
---|---|---|
a65e3e4b DC |
1 | use anyhow::Error; |
2 | use serde_json::{json, Value}; | |
3 | ||
4 | use proxmox::api::{api, cli::*}; | |
731eeef2 DM |
5 | use proxmox_backup::{ |
6 | tools, | |
7 | api2::types::*, | |
8 | backup::{ | |
9 | BackupGroup, | |
10 | } | |
11 | }; | |
a65e3e4b DC |
12 | |
13 | use 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. | |
45 | async fn list_snapshots(param: Value) -> Result<Value, Error> { | |
46 | ||
47 | let repo = extract_repository_from_value(¶m)?; | |
48 | ||
49 | let output_format = get_output_format(¶m); | |
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. | |
113 | async fn list_snapshot_files(param: Value) -> Result<Value, Error> { | |
114 | ||
115 | let repo = extract_repository_from_value(¶m)?; | |
116 | ||
117 | let path = tools::required_string_param(¶m, "snapshot")?; | |
118 | let snapshot: BackupDir = path.parse()?; | |
119 | ||
120 | let output_format = get_output_format(¶m); | |
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 | ||
a65e3e4b DC |
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 | "output-format": { | |
157 | schema: OUTPUT_FORMAT, | |
158 | optional: true, | |
159 | }, | |
160 | } | |
161 | } | |
162 | )] | |
163 | /// Show notes | |
164 | async fn show_notes(param: Value) -> Result<Value, Error> { | |
165 | let repo = extract_repository_from_value(¶m)?; | |
166 | let path = tools::required_string_param(¶m, "snapshot")?; | |
167 | ||
168 | let snapshot: BackupDir = path.parse()?; | |
169 | let client = connect(&repo)?; | |
170 | ||
171 | let path = format!("api2/json/admin/datastore/{}/notes", repo.store()); | |
172 | ||
173 | let args = json!({ | |
174 | "backup-type": snapshot.group().backup_type(), | |
175 | "backup-id": snapshot.group().backup_id(), | |
176 | "backup-time": snapshot.backup_time(), | |
177 | }); | |
178 | ||
179 | let output_format = get_output_format(¶m); | |
180 | ||
181 | let mut result = client.get(&path, Some(args)).await?; | |
182 | ||
183 | let notes = result["data"].take(); | |
184 | ||
185 | if output_format == "text" { | |
186 | if let Some(notes) = notes.as_str() { | |
187 | println!("{}", notes); | |
188 | } | |
189 | } else { | |
190 | format_and_print_result( | |
191 | &json!({ | |
192 | "notes": notes, | |
193 | }), | |
194 | &output_format, | |
195 | ); | |
196 | } | |
197 | ||
198 | Ok(Value::Null) | |
199 | } | |
200 | ||
201 | #[api( | |
202 | input: { | |
203 | properties: { | |
204 | repository: { | |
205 | schema: REPO_URL_SCHEMA, | |
206 | optional: true, | |
207 | }, | |
208 | snapshot: { | |
209 | type: String, | |
210 | description: "Snapshot path.", | |
211 | }, | |
212 | notes: { | |
213 | type: String, | |
214 | description: "The Notes.", | |
215 | }, | |
216 | } | |
217 | } | |
218 | )] | |
219 | /// Update Notes | |
220 | async fn update_notes(param: Value) -> Result<Value, Error> { | |
221 | let repo = extract_repository_from_value(¶m)?; | |
222 | let path = tools::required_string_param(¶m, "snapshot")?; | |
223 | let notes = tools::required_string_param(¶m, "notes")?; | |
224 | ||
225 | let snapshot: BackupDir = path.parse()?; | |
226 | let mut client = connect(&repo)?; | |
227 | ||
228 | let path = format!("api2/json/admin/datastore/{}/notes", repo.store()); | |
229 | ||
230 | let args = json!({ | |
231 | "backup-type": snapshot.group().backup_type(), | |
232 | "backup-id": snapshot.group().backup_id(), | |
233 | "backup-time": snapshot.backup_time(), | |
234 | "notes": notes, | |
235 | }); | |
236 | ||
237 | client.put(&path, Some(args)).await?; | |
238 | ||
239 | Ok(Value::Null) | |
240 | } | |
241 | ||
242 | fn notes_cli() -> CliCommandMap { | |
243 | CliCommandMap::new() | |
244 | .insert( | |
245 | "show", | |
246 | CliCommand::new(&API_METHOD_SHOW_NOTES) | |
247 | .arg_param(&["snapshot"]) | |
248 | .completion_cb("snapshot", complete_backup_snapshot), | |
249 | ) | |
250 | .insert( | |
251 | "update", | |
252 | CliCommand::new(&API_METHOD_UPDATE_NOTES) | |
253 | .arg_param(&["snapshot", "notes"]) | |
254 | .completion_cb("snapshot", complete_backup_snapshot), | |
255 | ) | |
256 | } | |
257 | ||
258 | pub fn snapshot_mgtm_cli() -> CliCommandMap { | |
731eeef2 DM |
259 | CliCommandMap::new() |
260 | .insert("notes", notes_cli()) | |
261 | .insert( | |
61205f00 DM |
262 | "list", |
263 | CliCommand::new(&API_METHOD_LIST_SNAPSHOTS) | |
731eeef2 DM |
264 | .arg_param(&["group"]) |
265 | .completion_cb("group", complete_backup_group) | |
266 | .completion_cb("repository", complete_repository) | |
267 | ) | |
61205f00 DM |
268 | .insert( |
269 | "files", | |
270 | CliCommand::new(&API_METHOD_LIST_SNAPSHOT_FILES) | |
271 | .arg_param(&["snapshot"]) | |
272 | .completion_cb("repository", complete_repository) | |
273 | .completion_cb("snapshot", complete_backup_snapshot) | |
274 | ) | |
275 | ||
a65e3e4b | 276 | } |