]>
Commit | Line | Data |
---|---|---|
9e490a74 DM |
1 | use failure::*; |
2 | use std::io::Write; | |
3 | use std::sync::Arc; | |
4 | ||
5 | use chrono::{DateTime, Utc}; | |
6 | use serde_json::{json, Value}; | |
7 | ||
8 | use proxmox::tools::digest_to_hex; | |
9 | ||
10 | use crate::tools::futures::Canceller; | |
11 | ||
12 | use super::{HttpClient, H2Client}; | |
13 | ||
913acb41 | 14 | /// Backup Reader |
9e490a74 DM |
15 | pub struct BackupReader { |
16 | h2: H2Client, | |
17 | canceller: Canceller, | |
18 | } | |
19 | ||
20 | impl Drop for BackupReader { | |
21 | ||
22 | fn drop(&mut self) { | |
23 | self.canceller.cancel(); | |
24 | } | |
25 | } | |
26 | ||
27 | impl BackupReader { | |
28 | ||
29 | fn new(h2: H2Client, canceller: Canceller) -> Arc<Self> { | |
30 | Arc::new(Self { h2, canceller }) | |
31 | } | |
32 | ||
913acb41 | 33 | /// Create a new instance by upgrading the connection at '/api2/json/reader' |
9e490a74 DM |
34 | pub async fn start( |
35 | client: HttpClient, | |
36 | datastore: &str, | |
37 | backup_type: &str, | |
38 | backup_id: &str, | |
39 | backup_time: DateTime<Utc>, | |
40 | debug: bool, | |
41 | ) -> Result<Arc<BackupReader>, Error> { | |
42 | ||
43 | let param = json!({ | |
44 | "backup-type": backup_type, | |
45 | "backup-id": backup_id, | |
46 | "backup-time": backup_time.timestamp(), | |
47 | "store": datastore, | |
48 | "debug": debug, | |
49 | }); | |
50 | let req = HttpClient::request_builder(client.server(), "GET", "/api2/json/reader", Some(param)).unwrap(); | |
51 | ||
52 | let (h2, canceller) = client.start_h2_connection(req, String::from(PROXMOX_BACKUP_READER_PROTOCOL_ID_V1!())).await?; | |
53 | ||
54 | Ok(BackupReader::new(h2, canceller)) | |
55 | } | |
56 | ||
913acb41 | 57 | /// Execute a GET request |
9e490a74 DM |
58 | pub async fn get( |
59 | &self, | |
60 | path: &str, | |
61 | param: Option<Value>, | |
62 | ) -> Result<Value, Error> { | |
63 | self.h2.get(path, param).await | |
64 | } | |
65 | ||
913acb41 | 66 | /// Execute a PUT request |
9e490a74 DM |
67 | pub async fn put( |
68 | &self, | |
69 | path: &str, | |
70 | param: Option<Value>, | |
71 | ) -> Result<Value, Error> { | |
72 | self.h2.put(path, param).await | |
73 | } | |
74 | ||
913acb41 | 75 | /// Execute a POST request |
9e490a74 DM |
76 | pub async fn post( |
77 | &self, | |
78 | path: &str, | |
79 | param: Option<Value>, | |
80 | ) -> Result<Value, Error> { | |
81 | self.h2.post(path, param).await | |
82 | } | |
83 | ||
913acb41 | 84 | /// Execute a GET request and send output to a writer |
9e490a74 DM |
85 | pub async fn download<W: Write + Send>( |
86 | &self, | |
87 | file_name: &str, | |
88 | output: W, | |
89 | ) -> Result<W, Error> { | |
90 | let path = "download"; | |
91 | let param = json!({ "file-name": file_name }); | |
92 | self.h2.download(path, Some(param), output).await | |
93 | } | |
94 | ||
913acb41 DM |
95 | /// Execute a special GET request and send output to a writer |
96 | /// | |
97 | /// This writes random data, and is only useful to test download speed. | |
9e490a74 DM |
98 | pub async fn speedtest<W: Write + Send>( |
99 | &self, | |
100 | output: W, | |
101 | ) -> Result<W, Error> { | |
102 | self.h2.download("speedtest", None, output).await | |
103 | } | |
104 | ||
913acb41 | 105 | /// Download a specific chunk |
9e490a74 DM |
106 | pub async fn download_chunk<W: Write + Send>( |
107 | &self, | |
108 | digest: &[u8; 32], | |
109 | output: W, | |
110 | ) -> Result<W, Error> { | |
111 | let path = "chunk"; | |
112 | let param = json!({ "digest": digest_to_hex(digest) }); | |
113 | self.h2.download(path, Some(param), output).await | |
114 | } | |
115 | ||
116 | pub fn force_close(self) { | |
117 | self.canceller.cancel(); | |
118 | } | |
119 | } |