proxmox-backup/src/api3/admin/datastore/upload_catar.rs

92 lines
2.5 KiB
Rust
Raw Normal View History

use failure::*;
use crate::tools;
use crate::backup::datastore::*;
use crate::backup::archive_index::*;
2019-01-16 09:19:49 +00:00
//use crate::server::rest::*;
use crate::api::schema::*;
use crate::api::router::*;
2019-01-16 09:19:49 +00:00
use serde_json::Value;
use std::io::Write;
use futures::*;
use std::path::PathBuf;
use hyper::Body;
use hyper::http::request::Parts;
pub struct UploadCaTar {
stream: Body,
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()?;
return Ok(Async::Ready(()))
}
}
}
}
}
fn upload_catar(parts: Parts, req_body: Body, param: Value, _info: &ApiUploadMethod) -> Result<BoxFut, Error> {
let store = tools::required_string_param(&param, "name")?;
let archive_name = tools::required_string_param(&param, "archive_name")?;
println!("Upload {}.catar to {} ({}.aidx)", archive_name, store, archive_name);
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");
}
let chunk_size = 4*1024*1024;
let datastore = DataStore::lookup_datastore(store)?;
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();
let upload = UploadCaTar { stream: req_body, index, count: 0};
2019-01-16 09:19:49 +00:00
let resp = upload.and_then(|_| {
let response = http::Response::builder()
.status(200)
.body(hyper::Body::empty())
.unwrap();
Ok(response)
});
Ok(Box::new(resp))
}
pub fn api_method_upload_catar() -> ApiUploadMethod {
ApiUploadMethod::new(
upload_catar,
ObjectSchema::new("Upload .catar backup file.")
.required("name", StringSchema::new("Datastore name."))
.required("archive_name", StringSchema::new("Backup archive name."))
)
}