]> git.proxmox.com Git - proxmox-backup.git/blame - src/api3/admin/datastore/upload_catar.rs
bin/proxmox-backup-client.rs: implement file name completions - first try ...
[proxmox-backup.git] / src / api3 / admin / datastore / upload_catar.rs
CommitLineData
1629d2ad
DM
1use failure::*;
2
0fe5d605 3use crate::tools;
1629d2ad
DM
4use crate::backup::datastore::*;
5use crate::backup::archive_index::*;
2085142e 6//use crate::server::rest::*;
1629d2ad
DM
7use crate::api::schema::*;
8use crate::api::router::*;
9
2085142e
DM
10use serde_json::Value;
11use std::io::Write;
1629d2ad 12use futures::*;
cf16af2a 13use std::path::PathBuf;
1629d2ad 14
83bdac1e
DM
15use hyper::Body;
16use hyper::http::request::Parts;
17
1629d2ad 18pub struct UploadCaTar {
83bdac1e 19 stream: Body,
1629d2ad
DM
20 index: ArchiveIndexWriter,
21 count: usize,
22}
23
24impl 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 46fn 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(&param, "name")?;
49 let archive_name = tools::required_string_param(&param, "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
84pub 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}