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::backup::*;
|
||||||
use proxmox_backup::client::*;
|
use proxmox_backup::client::*;
|
||||||
|
|
||||||
use chrono::{Utc, DateTime};
|
use super::BackupSetup;
|
||||||
|
|
||||||
use crate::capi_types::*;
|
use crate::capi_types::*;
|
||||||
use crate::upload_queue::*;
|
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 {
|
struct ImageUploadInfo {
|
||||||
wid: u64,
|
wid: u64,
|
||||||
device_name: String,
|
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 std::sync::{Mutex, Condvar};
|
||||||
|
|
||||||
use proxmox::try_block;
|
use proxmox::try_block;
|
||||||
use proxmox_backup::backup::*;
|
|
||||||
use proxmox_backup::client::BackupRepository;
|
use proxmox_backup::client::BackupRepository;
|
||||||
|
|
||||||
use chrono::{Utc, TimeZone};
|
use chrono::{DateTime, Utc, TimeZone};
|
||||||
|
|
||||||
mod capi_types;
|
mod capi_types;
|
||||||
use capi_types::*;
|
use capi_types::*;
|
||||||
@ -16,7 +15,6 @@ use capi_types::*;
|
|||||||
mod upload_queue;
|
mod upload_queue;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
use commands::*;
|
|
||||||
|
|
||||||
mod worker_task;
|
mod worker_task;
|
||||||
use 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
|
// helper class to implement synchrounous interface
|
||||||
struct GotResultCondition {
|
struct GotResultCondition {
|
||||||
lock: Mutex<bool>,
|
lock: Mutex<bool>,
|
||||||
@ -665,14 +677,27 @@ pub extern "C" fn proxmox_backup_disconnect(handle: *mut ProxmoxBackupHandle) {
|
|||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn proxmox_restore_connect(
|
pub extern "C" fn proxmox_restore_connect(
|
||||||
repo: *const c_char,
|
repo: *const c_char,
|
||||||
snapshot: *const c_char,
|
backup_id: *const c_char,
|
||||||
|
backup_time: u64,
|
||||||
|
password: *const c_char,
|
||||||
keyfile: *const c_char,
|
keyfile: *const c_char,
|
||||||
|
key_password: *const c_char,
|
||||||
|
fingerprint: *const c_char,
|
||||||
error: * mut * mut c_char,
|
error: * mut * mut c_char,
|
||||||
) -> *mut ProxmoxRestoreHandle {
|
) -> *mut ProxmoxRestoreHandle {
|
||||||
|
|
||||||
let result: Result<_, Error> = try_block!({
|
let result: Result<_, Error> = try_block!({
|
||||||
let repo = unsafe { CStr::from_ptr(repo).to_str()?.to_owned() };
|
let repo = unsafe { CStr::from_ptr(repo).to_str()?.to_owned() };
|
||||||
let repo: BackupRepository = repo.parse()?;
|
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() {
|
let keyfile = if keyfile.is_null() {
|
||||||
None
|
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)? })
|
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 key_password = if key_password.is_null() {
|
||||||
let snapshot = BackupDir::parse(&snapshot)?;
|
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 {
|
match result {
|
||||||
|
@ -4,7 +4,9 @@ use std::os::unix::fs::OpenOptionsExt;
|
|||||||
|
|
||||||
use proxmox_backup::tools::runtime::block_on;
|
use proxmox_backup::tools::runtime::block_on;
|
||||||
use proxmox_backup::backup::*;
|
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(crate) struct ProxmoxRestore {
|
||||||
pub client: Arc<BackupReader>,
|
pub client: Arc<BackupReader>,
|
||||||
@ -14,31 +16,28 @@ pub(crate) struct ProxmoxRestore {
|
|||||||
|
|
||||||
impl ProxmoxRestore {
|
impl ProxmoxRestore {
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(setup: BackupSetup) -> Result<Self, Error> {
|
||||||
repo: BackupRepository,
|
|
||||||
snapshot: BackupDir,
|
|
||||||
keyfile: Option<std::path::PathBuf>,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
|
|
||||||
let host = repo.host().to_owned();
|
let crypt_config = match setup.keyfile {
|
||||||
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 {
|
|
||||||
None => None,
|
None => None,
|
||||||
Some(path) => {
|
Some(ref path) => {
|
||||||
let (key, _) = load_and_decrypt_key(&path, &get_encryption_key_password)?;
|
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)?))
|
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 result: Result<_, Error> = block_on(async {
|
||||||
|
|
||||||
let options = HttpClientOptions::new();
|
let options = HttpClientOptions::new();
|
||||||
@ -174,15 +173,3 @@ impl ProxmoxRestore {
|
|||||||
Ok(())
|
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::tools::BroadcastFuture;
|
||||||
use proxmox_backup::backup::{CryptConfig, load_and_decrypt_key};
|
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::capi_types::*;
|
||||||
use crate::commands::*;
|
use crate::commands::*;
|
||||||
|
|
||||||
@ -141,11 +143,17 @@ fn backup_worker_task(
|
|||||||
|
|
||||||
match msg {
|
match msg {
|
||||||
BackupMessage::Connect { callback_info } => {
|
BackupMessage::Connect { callback_info } => {
|
||||||
let client = client.clone();
|
|
||||||
let setup = setup.clone();
|
let setup = setup.clone();
|
||||||
|
let client = client.clone();
|
||||||
|
|
||||||
let command_future = async move {
|
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();
|
let mut guard = client.lock().unwrap();
|
||||||
*guard = Some(writer);
|
*guard = Some(writer);
|
||||||
Ok(0)
|
Ok(0)
|
||||||
|
Loading…
Reference in New Issue
Block a user