]> git.proxmox.com Git - proxmox-backup.git/blame - src/bin/proxmox_backup_client/snapshot.rs
cli: rename command "files" to "snapshot files"
[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
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
164async fn show_notes(param: Value) -> Result<Value, Error> {
165 let repo = extract_repository_from_value(&param)?;
166 let path = tools::required_string_param(&param, "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(&param);
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
220async fn update_notes(param: Value) -> Result<Value, Error> {
221 let repo = extract_repository_from_value(&param)?;
222 let path = tools::required_string_param(&param, "snapshot")?;
223 let notes = tools::required_string_param(&param, "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
242fn 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
258pub 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}