src/api2/admin/datastore/backup.rs: implement config file upload
This commit is contained in:
parent
1c0472e88f
commit
39d6846e1e
@ -150,6 +150,10 @@ fn upgrade_to_backup_protocol(
|
||||
fn backup_api() -> Router {
|
||||
|
||||
let router = Router::new()
|
||||
.subdir(
|
||||
"config", Router::new()
|
||||
.upload(api_method_upload_config())
|
||||
)
|
||||
.subdir(
|
||||
"dynamic_chunk", Router::new()
|
||||
.upload(api_method_upload_dynamic_chunk())
|
||||
|
@ -185,3 +185,65 @@ fn upload_speedtest(
|
||||
|
||||
Ok(Box::new(resp))
|
||||
}
|
||||
|
||||
pub fn api_method_upload_config() -> ApiAsyncMethod {
|
||||
ApiAsyncMethod::new(
|
||||
upload_config,
|
||||
ObjectSchema::new("Upload configuration file.")
|
||||
.required("file-name", crate::api2::types::BACKUP_ARCHIVE_NAME_SCHEMA.clone())
|
||||
.required("size", IntegerSchema::new("File size.")
|
||||
.minimum(1)
|
||||
.maximum(1024*1024*16)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fn upload_config(
|
||||
_parts: Parts,
|
||||
req_body: Body,
|
||||
param: Value,
|
||||
_info: &ApiAsyncMethod,
|
||||
rpcenv: Box<RpcEnvironment>,
|
||||
) -> Result<BoxFut, Error> {
|
||||
|
||||
let mut file_name = tools::required_string_param(¶m, "file-name")?.to_owned();
|
||||
let size = tools::required_integer_param(¶m, "size")? as usize;
|
||||
|
||||
if !file_name.ends_with(".conf") {
|
||||
bail!("wrong config file extension: '{}'", file_name);
|
||||
} else {
|
||||
file_name.push_str(".zstd");
|
||||
}
|
||||
|
||||
let env: &BackupEnvironment = rpcenv.as_ref();
|
||||
|
||||
let mut path = env.datastore.base_path();
|
||||
path.push(env.backup_dir.relative_path());
|
||||
path.push(&file_name);
|
||||
|
||||
let env2 = env.clone();
|
||||
let env3 = env.clone();
|
||||
|
||||
let resp = req_body
|
||||
.map_err(Error::from)
|
||||
.concat2()
|
||||
.and_then(move |data| {
|
||||
if size != data.len() {
|
||||
bail!("got configuration file with unexpected length ({} != {})", size, data.len());
|
||||
}
|
||||
|
||||
let data = zstd::block::compress(&data, 0)?;
|
||||
|
||||
tools::file_set_contents(&path, &data, None)?;
|
||||
|
||||
env2.debug(format!("upload config {:?} ({} bytes, comp: {})", path, size, data.len()));
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.and_then(move |_| {
|
||||
Ok(env3.format_response(Ok(Value::Null)))
|
||||
})
|
||||
;
|
||||
|
||||
Ok(Box::new(resp))
|
||||
}
|
||||
|
@ -431,6 +431,31 @@ impl BackupClient {
|
||||
self.h2.clone().post("finish", None).map(|_| ())
|
||||
}
|
||||
|
||||
pub fn upload_config(
|
||||
&self,
|
||||
file_name: &str,
|
||||
src_path: std::path::PathBuf,
|
||||
) -> impl Future<Item=(), Error=Error> {
|
||||
|
||||
let h2 = self.h2.clone();
|
||||
let file_name = file_name.to_owned();
|
||||
|
||||
let task = tokio::fs::File::open(src_path)
|
||||
.map_err(Error::from)
|
||||
.and_then(|file| {
|
||||
let contents = vec![];
|
||||
tokio::io::read_to_end(file, contents)
|
||||
.map_err(Error::from)
|
||||
.and_then(move |(_, contents)| {
|
||||
let param = json!({"size": contents.len(), "file-name": file_name });
|
||||
h2.upload("config", Some(param), contents)
|
||||
.map(|_| {})
|
||||
})
|
||||
});
|
||||
|
||||
task
|
||||
}
|
||||
|
||||
pub fn upload_stream(
|
||||
&self,
|
||||
archive_name: &str,
|
||||
|
Loading…
Reference in New Issue
Block a user