]>
Commit | Line | Data |
---|---|---|
1629d2ad DM |
1 | use failure::*; |
2 | ||
0fe5d605 | 3 | use crate::tools; |
1629d2ad DM |
4 | use crate::backup::datastore::*; |
5 | use crate::backup::archive_index::*; | |
2085142e | 6 | //use crate::server::rest::*; |
1629d2ad DM |
7 | use crate::api::schema::*; |
8 | use crate::api::router::*; | |
9 | ||
2085142e DM |
10 | use serde_json::Value; |
11 | use std::io::Write; | |
1629d2ad | 12 | use futures::*; |
cf16af2a | 13 | use std::path::PathBuf; |
1629d2ad | 14 | |
83bdac1e DM |
15 | use hyper::Body; |
16 | use hyper::http::request::Parts; | |
17 | ||
1629d2ad | 18 | pub struct UploadCaTar { |
83bdac1e | 19 | stream: Body, |
1629d2ad DM |
20 | index: ArchiveIndexWriter, |
21 | count: usize, | |
22 | } | |
23 | ||
24 | impl Future for UploadCaTar { | |
25 | type Item = (); | |
26 | type Error = failure::Error; | |
27 | ||
28 | fn poll(&mut self) -> Poll<(), failure::Error> { | |
29 | loop { | |
1629d2ad DM |
30 | match try_ready!(self.stream.poll()) { |
31 | Some(chunk) => { | |
32 | self.count += chunk.len(); | |
1629d2ad DM |
33 | if let Err(err) = self.index.write(&chunk) { |
34 | bail!("writing chunk failed - {}", err); | |
35 | } | |
1629d2ad DM |
36 | } |
37 | None => { | |
2085142e | 38 | self.index.close()?; |
1629d2ad DM |
39 | return Ok(Async::Ready(())) |
40 | } | |
41 | } | |
42 | } | |
43 | } | |
44 | } | |
45 | ||
83bdac1e | 46 | fn upload_catar(parts: Parts, req_body: Body, param: Value, _info: &ApiUploadMethod) -> Result<BoxFut, Error> { |
1629d2ad | 47 | |
0fe5d605 DM |
48 | let store = tools::required_string_param(¶m, "name")?; |
49 | let archive_name = tools::required_string_param(¶m, "archive_name")?; | |
1629d2ad | 50 | |
cf16af2a | 51 | println!("Upload {}.catar to {} ({}.aidx)", archive_name, store, archive_name); |
1629d2ad | 52 | |
83bdac1e DM |
53 | let content_type = parts.headers.get(http::header::CONTENT_TYPE) |
54 | .ok_or(format_err!("missing content-type header"))?; | |
55 | ||
56 | if content_type != "application/x-proxmox-backup-catar" { | |
57 | bail!("got wrong content-type for catar archive upload"); | |
58 | } | |
59 | ||
1629d2ad | 60 | let chunk_size = 4*1024*1024; |
0ee0ad5b DM |
61 | |
62 | let datastore = DataStore::lookup_datastore(store)?; | |
1629d2ad | 63 | |
cf16af2a DM |
64 | let mut full_archive_name = PathBuf::from(archive_name); |
65 | full_archive_name.set_extension("aidx"); | |
66 | ||
67 | let index = datastore.create_archive_writer(&full_archive_name, chunk_size).unwrap(); | |
1629d2ad DM |
68 | |
69 | let upload = UploadCaTar { stream: req_body, index, count: 0}; | |
70 | ||
2085142e | 71 | let resp = upload.and_then(|_| { |
1629d2ad DM |
72 | |
73 | let response = http::Response::builder() | |
74 | .status(200) | |
75 | .body(hyper::Body::empty()) | |
76 | .unwrap(); | |
77 | ||
78 | Ok(response) | |
79 | }); | |
80 | ||
0ee0ad5b | 81 | Ok(Box::new(resp)) |
1629d2ad DM |
82 | } |
83 | ||
84 | pub fn api_method_upload_catar() -> ApiUploadMethod { | |
85 | ApiUploadMethod::new( | |
86 | upload_catar, | |
87 | ObjectSchema::new("Upload .catar backup file.") | |
88 | .required("name", StringSchema::new("Datastore name.")) | |
cf16af2a | 89 | .required("archive_name", StringSchema::new("Backup archive name.")) |
1629d2ad DM |
90 | ) |
91 | } |