mirror of
https://git.proxmox.com/git/proxmox-backup-qemu
synced 2025-10-04 20:49:26 +00:00
use BackupSetup for ProxmoxRestore::new()
This commit is contained in:
parent
76381310d3
commit
aca3c6a306
@ -9,37 +9,10 @@ use serde_json::{json, Value};
|
||||
use proxmox_backup::backup::*;
|
||||
use proxmox_backup::client::*;
|
||||
|
||||
use chrono::{Utc, DateTime};
|
||||
|
||||
use super::BackupSetup;
|
||||
use crate::capi_types::*;
|
||||
use crate::upload_queue::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct BackupSetup {
|
||||
pub host: String,
|
||||
pub store: String,
|
||||
pub user: String,
|
||||
pub chunk_size: u64,
|
||||
pub backup_id: String,
|
||||
pub backup_time: DateTime<Utc>,
|
||||
pub password: Option<String>,
|
||||
pub keyfile: Option<std::path::PathBuf>,
|
||||
pub key_password: Option<String>,
|
||||
pub fingerprint: Option<String>,
|
||||
}
|
||||
|
||||
impl BackupSetup {
|
||||
|
||||
pub(crate) async fn connect(&self) -> Result<Arc<BackupWriter>, Error> {
|
||||
let options = HttpClientOptions::new()
|
||||
.fingerprint(self.fingerprint.clone())
|
||||
.password(self.password.clone());
|
||||
|
||||
let client = HttpClient::new(&self.host, &self.user, options)?;
|
||||
BackupWriter::start(client, &self.store, "vm", &self.backup_id, self.backup_time, false).await
|
||||
}
|
||||
}
|
||||
|
||||
struct ImageUploadInfo {
|
||||
wid: u64,
|
||||
device_name: String,
|
||||
|
61
src/lib.rs
61
src/lib.rs
@ -5,10 +5,9 @@ use std::os::raw::{c_uchar, c_char, c_int, c_void};
|
||||
use std::sync::{Mutex, Condvar};
|
||||
|
||||
use proxmox::try_block;
|
||||
use proxmox_backup::backup::*;
|
||||
use proxmox_backup::client::BackupRepository;
|
||||
|
||||
use chrono::{Utc, TimeZone};
|
||||
use chrono::{DateTime, Utc, TimeZone};
|
||||
|
||||
mod capi_types;
|
||||
use capi_types::*;
|
||||
@ -16,7 +15,6 @@ use capi_types::*;
|
||||
mod upload_queue;
|
||||
|
||||
mod commands;
|
||||
use commands::*;
|
||||
|
||||
mod worker_task;
|
||||
use worker_task::*;
|
||||
@ -55,6 +53,20 @@ macro_rules! raise_error_int {
|
||||
}}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct BackupSetup {
|
||||
pub host: String,
|
||||
pub store: String,
|
||||
pub user: String,
|
||||
pub chunk_size: u64,
|
||||
pub backup_id: String,
|
||||
pub backup_time: DateTime<Utc>,
|
||||
pub password: Option<String>,
|
||||
pub keyfile: Option<std::path::PathBuf>,
|
||||
pub key_password: Option<String>,
|
||||
pub fingerprint: Option<String>,
|
||||
}
|
||||
|
||||
// helper class to implement synchrounous interface
|
||||
struct GotResultCondition {
|
||||
lock: Mutex<bool>,
|
||||
@ -665,14 +677,27 @@ pub extern "C" fn proxmox_backup_disconnect(handle: *mut ProxmoxBackupHandle) {
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
pub extern "C" fn proxmox_restore_connect(
|
||||
repo: *const c_char,
|
||||
snapshot: *const c_char,
|
||||
backup_id: *const c_char,
|
||||
backup_time: u64,
|
||||
password: *const c_char,
|
||||
keyfile: *const c_char,
|
||||
key_password: *const c_char,
|
||||
fingerprint: *const c_char,
|
||||
error: * mut * mut c_char,
|
||||
) -> *mut ProxmoxRestoreHandle {
|
||||
|
||||
let result: Result<_, Error> = try_block!({
|
||||
let repo = unsafe { CStr::from_ptr(repo).to_str()?.to_owned() };
|
||||
let repo: BackupRepository = repo.parse()?;
|
||||
let backup_id = unsafe { CStr::from_ptr(backup_id).to_str()?.to_owned() };
|
||||
|
||||
let backup_time = Utc.timestamp(backup_time as i64, 0);
|
||||
|
||||
let password = if password.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { CStr::from_ptr(password).to_str()?.to_owned() })
|
||||
};
|
||||
|
||||
let keyfile = if keyfile.is_null() {
|
||||
None
|
||||
@ -680,10 +705,32 @@ pub extern "C" fn proxmox_restore_connect(
|
||||
Some(unsafe { CStr::from_ptr(keyfile).to_str().map(std::path::PathBuf::from)? })
|
||||
};
|
||||
|
||||
let snapshot = unsafe { CStr::from_ptr(snapshot).to_string_lossy().into_owned() };
|
||||
let snapshot = BackupDir::parse(&snapshot)?;
|
||||
let key_password = if key_password.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { CStr::from_ptr(key_password).to_str()?.to_owned() })
|
||||
};
|
||||
|
||||
ProxmoxRestore::new(repo, snapshot, keyfile)
|
||||
let fingerprint = if fingerprint.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { CStr::from_ptr(fingerprint).to_str()?.to_owned() })
|
||||
};
|
||||
|
||||
let setup = BackupSetup {
|
||||
host: repo.host().to_owned(),
|
||||
user: repo.user().to_owned(),
|
||||
store: repo.store().to_owned(),
|
||||
chunk_size: PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE, // not used by restore
|
||||
backup_id,
|
||||
password,
|
||||
backup_time,
|
||||
keyfile,
|
||||
key_password,
|
||||
fingerprint,
|
||||
};
|
||||
|
||||
ProxmoxRestore::new(setup)
|
||||
});
|
||||
|
||||
match result {
|
||||
|
@ -4,7 +4,9 @@ use std::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
use proxmox_backup::tools::runtime::block_on;
|
||||
use proxmox_backup::backup::*;
|
||||
use proxmox_backup::client::{HttpClient, HttpClientOptions, BackupReader, BackupRepository, RemoteChunkReader};
|
||||
use proxmox_backup::client::{HttpClient, HttpClientOptions, BackupReader, RemoteChunkReader};
|
||||
|
||||
use super::BackupSetup;
|
||||
|
||||
pub(crate) struct ProxmoxRestore {
|
||||
pub client: Arc<BackupReader>,
|
||||
@ -14,31 +16,28 @@ pub(crate) struct ProxmoxRestore {
|
||||
|
||||
impl ProxmoxRestore {
|
||||
|
||||
pub fn new(
|
||||
repo: BackupRepository,
|
||||
snapshot: BackupDir,
|
||||
keyfile: Option<std::path::PathBuf>,
|
||||
) -> Result<Self, Error> {
|
||||
pub fn new(setup: BackupSetup) -> Result<Self, Error> {
|
||||
|
||||
let host = repo.host().to_owned();
|
||||
let user = repo.user().to_owned();
|
||||
let store = repo.store().to_owned();
|
||||
let backup_type = snapshot.group().backup_type();
|
||||
let backup_id = snapshot.group().backup_id().to_owned();
|
||||
let backup_time = snapshot.backup_time();
|
||||
|
||||
if backup_type != "vm" {
|
||||
bail!("wrong backup type ({} != vm)", backup_type);
|
||||
}
|
||||
|
||||
let crypt_config = match keyfile {
|
||||
let crypt_config = match setup.keyfile {
|
||||
None => None,
|
||||
Some(path) => {
|
||||
let (key, _) = load_and_decrypt_key(&path, &get_encryption_key_password)?;
|
||||
Some(ref path) => {
|
||||
let (key, _) = load_and_decrypt_key(path, & || {
|
||||
match setup.key_password {
|
||||
Some(ref key_password) => Ok(key_password.as_bytes().to_vec()),
|
||||
None => bail!("no key_password specified"),
|
||||
}
|
||||
})?;
|
||||
Some(Arc::new(CryptConfig::new(key)?))
|
||||
}
|
||||
};
|
||||
|
||||
let host = setup.host;
|
||||
let user = setup.user;
|
||||
let store = setup.store;
|
||||
let backup_type = String::from("vm");
|
||||
let backup_id = setup.backup_id;
|
||||
let backup_time = setup.backup_time;
|
||||
|
||||
let result: Result<_, Error> = block_on(async {
|
||||
|
||||
let options = HttpClientOptions::new();
|
||||
@ -174,15 +173,3 @@ impl ProxmoxRestore {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// helper to get encrtyption key password
|
||||
fn get_encryption_key_password() -> Result<Vec<u8>, Error> {
|
||||
use std::env::VarError::*;
|
||||
match std::env::var("PBS_ENCRYPTION_PASSWORD") {
|
||||
Ok(p) => Ok(p.as_bytes().to_vec()),
|
||||
Err(NotUnicode(_)) => bail!("PBS_ENCRYPTION_PASSWORD contains bad characters"),
|
||||
Err(NotPresent) => {
|
||||
bail!("env PBS_ENCRYPTION_PASSWORD not set");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,9 @@ use futures::future::{Future, Either, FutureExt};
|
||||
|
||||
use proxmox_backup::tools::BroadcastFuture;
|
||||
use proxmox_backup::backup::{CryptConfig, load_and_decrypt_key};
|
||||
use proxmox_backup::client::{HttpClient, HttpClientOptions, BackupWriter};
|
||||
|
||||
use super::BackupSetup;
|
||||
use crate::capi_types::*;
|
||||
use crate::commands::*;
|
||||
|
||||
@ -141,11 +143,17 @@ fn backup_worker_task(
|
||||
|
||||
match msg {
|
||||
BackupMessage::Connect { callback_info } => {
|
||||
let client = client.clone();
|
||||
let setup = setup.clone();
|
||||
let client = client.clone();
|
||||
|
||||
let command_future = async move {
|
||||
let writer = setup.connect().await?;
|
||||
let options = HttpClientOptions::new()
|
||||
.fingerprint(setup.fingerprint.clone())
|
||||
.password(setup.password.clone());
|
||||
|
||||
let http = HttpClient::new(&setup.host, &setup.user, options)?;
|
||||
let writer = BackupWriter::start(http, &setup.store, "vm", &setup.backup_id, setup.backup_time, false).await?;
|
||||
|
||||
let mut guard = client.lock().unwrap();
|
||||
*guard = Some(writer);
|
||||
Ok(0)
|
||||
|
Loading…
Reference in New Issue
Block a user