2019-01-15 10:38:26 +00:00
|
|
|
use failure::*;
|
|
|
|
|
2019-01-17 11:14:02 +00:00
|
|
|
use crate::tools;
|
2019-01-15 10:38:26 +00:00
|
|
|
use crate::backup::datastore::*;
|
|
|
|
use crate::backup::archive_index::*;
|
2019-01-16 09:19:49 +00:00
|
|
|
//use crate::server::rest::*;
|
2019-01-15 10:38:26 +00:00
|
|
|
use crate::api::schema::*;
|
|
|
|
use crate::api::router::*;
|
|
|
|
|
2019-01-16 09:19:49 +00:00
|
|
|
use serde_json::Value;
|
|
|
|
use std::io::Write;
|
2019-01-15 10:38:26 +00:00
|
|
|
use futures::*;
|
2019-01-16 12:58:36 +00:00
|
|
|
use std::path::PathBuf;
|
2019-01-15 10:38:26 +00:00
|
|
|
|
2019-01-17 11:43:29 +00:00
|
|
|
use hyper::Body;
|
|
|
|
use hyper::http::request::Parts;
|
|
|
|
|
2019-01-15 10:38:26 +00:00
|
|
|
pub struct UploadCaTar {
|
2019-01-17 11:43:29 +00:00
|
|
|
stream: Body,
|
2019-01-15 10:38:26 +00:00
|
|
|
index: ArchiveIndexWriter,
|
|
|
|
count: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Future for UploadCaTar {
|
|
|
|
type Item = ();
|
|
|
|
type Error = failure::Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<(), failure::Error> {
|
|
|
|
loop {
|
|
|
|
match try_ready!(self.stream.poll()) {
|
|
|
|
Some(chunk) => {
|
|
|
|
self.count += chunk.len();
|
|
|
|
if let Err(err) = self.index.write(&chunk) {
|
|
|
|
bail!("writing chunk failed - {}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
2019-01-16 09:19:49 +00:00
|
|
|
self.index.close()?;
|
2019-01-15 10:38:26 +00:00
|
|
|
return Ok(Async::Ready(()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-17 11:43:29 +00:00
|
|
|
fn upload_catar(parts: Parts, req_body: Body, param: Value, _info: &ApiUploadMethod) -> Result<BoxFut, Error> {
|
2019-01-15 10:38:26 +00:00
|
|
|
|
2019-01-18 07:33:11 +00:00
|
|
|
let store = tools::required_string_param(¶m, "store")?;
|
2019-01-17 11:14:02 +00:00
|
|
|
let archive_name = tools::required_string_param(¶m, "archive_name")?;
|
2019-01-15 10:38:26 +00:00
|
|
|
|
2019-01-16 12:58:36 +00:00
|
|
|
println!("Upload {}.catar to {} ({}.aidx)", archive_name, store, archive_name);
|
2019-01-15 10:38:26 +00:00
|
|
|
|
2019-01-17 11:43:29 +00:00
|
|
|
let content_type = parts.headers.get(http::header::CONTENT_TYPE)
|
|
|
|
.ok_or(format_err!("missing content-type header"))?;
|
|
|
|
|
|
|
|
if content_type != "application/x-proxmox-backup-catar" {
|
|
|
|
bail!("got wrong content-type for catar archive upload");
|
|
|
|
}
|
|
|
|
|
2019-01-15 10:38:26 +00:00
|
|
|
let chunk_size = 4*1024*1024;
|
2019-01-17 11:03:38 +00:00
|
|
|
|
|
|
|
let datastore = DataStore::lookup_datastore(store)?;
|
2019-01-15 10:38:26 +00:00
|
|
|
|
2019-01-16 12:58:36 +00:00
|
|
|
let mut full_archive_name = PathBuf::from(archive_name);
|
|
|
|
full_archive_name.set_extension("aidx");
|
|
|
|
|
|
|
|
let index = datastore.create_archive_writer(&full_archive_name, chunk_size).unwrap();
|
2019-01-15 10:38:26 +00:00
|
|
|
|
|
|
|
let upload = UploadCaTar { stream: req_body, index, count: 0};
|
|
|
|
|
2019-01-16 09:19:49 +00:00
|
|
|
let resp = upload.and_then(|_| {
|
2019-01-15 10:38:26 +00:00
|
|
|
|
|
|
|
let response = http::Response::builder()
|
|
|
|
.status(200)
|
|
|
|
.body(hyper::Body::empty())
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
Ok(response)
|
|
|
|
});
|
|
|
|
|
2019-01-17 11:03:38 +00:00
|
|
|
Ok(Box::new(resp))
|
2019-01-15 10:38:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn api_method_upload_catar() -> ApiUploadMethod {
|
|
|
|
ApiUploadMethod::new(
|
|
|
|
upload_catar,
|
|
|
|
ObjectSchema::new("Upload .catar backup file.")
|
2019-01-18 07:33:11 +00:00
|
|
|
.required("store", StringSchema::new("Datastore name."))
|
2019-01-16 12:58:36 +00:00
|
|
|
.required("archive_name", StringSchema::new("Backup archive name."))
|
2019-01-15 10:38:26 +00:00
|
|
|
)
|
|
|
|
}
|