4 use crate::backup
::datastore
::*;
5 use crate::backup
::archive_index
::*;
6 //use crate::server::rest::*;
7 use crate::api
::schema
::*;
8 use crate::api
::router
::*;
10 use serde_json
::Value
;
13 use std
::path
::PathBuf
;
17 use hyper
::http
::request
::Parts
;
19 pub struct UploadCaTar
{
21 index
: ArchiveIndexWriter
,
25 impl Future
for UploadCaTar
{
27 type Error
= failure
::Error
;
29 fn poll(&mut self) -> Poll
<(), failure
::Error
> {
31 match try_ready
!(self.stream
.poll()) {
33 self.count
+= chunk
.len();
34 if let Err(err
) = self.index
.write(&chunk
) {
35 bail
!("writing chunk failed - {}", err
);
40 return Ok(Async
::Ready(()))
47 fn upload_catar(parts
: Parts
, req_body
: Body
, param
: Value
, _info
: &ApiUploadMethod
) -> Result
<BoxFut
, Error
> {
49 let store
= tools
::required_string_param(¶m
, "store")?
;
50 let archive_name
= tools
::required_string_param(¶m
, "archive_name")?
;
52 let backup_type
= tools
::required_string_param(¶m
, "type")?
;
53 let backup_id
= tools
::required_string_param(¶m
, "id")?
;
54 let backup_time
= tools
::required_integer_param(¶m
, "time")?
;
56 println
!("Upload {}.catar to {} ({}/{}/{}/{}.aidx)", archive_name
, store
,
57 backup_type
, backup_id
, backup_time
, archive_name
);
59 let content_type
= parts
.headers
.get(http
::header
::CONTENT_TYPE
)
60 .ok_or(format_err
!("missing content-type header"))?
;
62 if content_type
!= "application/x-proxmox-backup-catar" {
63 bail
!("got wrong content-type for catar archive upload");
66 let chunk_size
= 4*1024*1024;
68 let datastore
= DataStore
::lookup_datastore(store
)?
;
70 let mut path
= datastore
.create_backup_dir(backup_type
, backup_id
, backup_time
)?
;
72 let mut full_archive_name
= PathBuf
::from(archive_name
);
73 full_archive_name
.set_extension("aidx");
75 path
.push(full_archive_name
);
77 let index
= datastore
.create_archive_writer(path
, chunk_size
).unwrap();
79 let upload
= UploadCaTar { stream: req_body, index, count: 0}
;
81 let resp
= upload
.and_then(|_
| {
83 let response
= http
::Response
::builder()
85 .body(hyper
::Body
::empty())
94 pub fn api_method_upload_catar() -> ApiUploadMethod
{
97 ObjectSchema
::new("Upload .catar backup file.")
98 .required("store", StringSchema
::new("Datastore name."))
99 .required("archive_name", StringSchema
::new("Backup archive name."))
100 .required("type", StringSchema
::new("Backup type.")
101 .format(Arc
::new(ApiStringFormat
::Enum(vec
!["ct".into(), "host".into()]))))
102 .required("id", StringSchema
::new("Backup ID."))
103 .required("time", IntegerSchema
::new("Backup time (Unix epoch.)")
104 .minimum(1547797308))