aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2024-02-13 17:54:03 +0100
committerHimbeerserverDE <himbeerserverde@gmail.com>2024-02-13 17:54:03 +0100
commitfa6d350c9f40b68bc58b937c98ab3c4890617f02 (patch)
tree9781bf465ccac9493ef33b88636b7b76e6722a59
parent86d53c781bef28b317b5afb59aaaef84b1092d84 (diff)
fix snapshot and backup dirs not pointing to the correct mountpoint in server mode
-rw-r--r--hbak/src/main.rs14
-rw-r--r--hbak_common/src/proto.rs59
-rw-r--r--hbak_common/src/system.rs12
-rw-r--r--hbakd/src/main.rs12
4 files changed, 64 insertions, 33 deletions
diff --git a/hbak/src/main.rs b/hbak/src/main.rs
index 51c6e17..9ea0332 100644
--- a/hbak/src/main.rs
+++ b/hbak/src/main.rs
@@ -382,11 +382,12 @@ fn sync(
return Err(RemoteError::AccessDenied);
}
- if snapshot.backup_path().exists() {
+ if snapshot.backup_path(Mode::Client).exists() {
return Err(RemoteError::Immutable);
}
- let file = File::create(snapshot.streaming_path()).map_err(|_| RemoteError::RxError)?;
+ let file = File::create(snapshot.streaming_path(Mode::Client))
+ .map_err(|_| RemoteError::RxError)?;
println!("Receiving {} from {}", snapshot, remote_node.address);
@@ -394,8 +395,11 @@ fn sync(
};
let rx_finish = |snapshot: Snapshot| {
- fs::rename(snapshot.streaming_path(), snapshot.backup_path())
- .map_err(|_| RemoteError::RxError)?;
+ fs::rename(
+ snapshot.streaming_path(Mode::Client),
+ snapshot.backup_path(Mode::Client),
+ )
+ .map_err(|_| RemoteError::RxError)?;
println!("Received {} from {}", snapshot, remote_node.address);
@@ -445,7 +449,7 @@ fn restore(local_node: &LocalNode, address: &str, subvols: &[String]) -> Result<
return Err(RemoteError::AccessDenied);
}
- if snapshot.snapshot_path().exists() {
+ if snapshot.snapshot_path(Mode::Client).exists() {
return Err(RemoteError::Immutable);
}
diff --git a/hbak_common/src/proto.rs b/hbak_common/src/proto.rs
index a7d7da9..d4c4708 100644
--- a/hbak_common/src/proto.rs
+++ b/hbak_common/src/proto.rs
@@ -14,8 +14,10 @@ use chrono::prelude::*;
use serde::{Deserialize, Serialize};
use sys_mount::{Mount, UnmountDrop, UnmountFlags};
-pub const SNAPSHOT_DIR: &str = "/mnt/hbak/snapshots";
-pub const BACKUP_DIR: &str = "/mnt/hbak/backups";
+pub const SNAPSHOT_DIR_C: &str = "/mnt/hbak/snapshots";
+pub const SNAPSHOT_DIR_S: &str = "/mnt/hbakd/snapshots";
+pub const BACKUP_DIR_C: &str = "/mnt/hbak/backups";
+pub const BACKUP_DIR_S: &str = "/mnt/hbakd/backups";
/// A `Snapshot` uniquely identifies a full or incremental btrfs snapshot
/// of a node via the node name, subvolume name and creation date.
@@ -53,10 +55,10 @@ impl Snapshot {
/// Converts the `Snapshot` to its local storage location,
/// i.e. a member of the `/mnt/hbak/snapshots` directory
/// of its node's own snapshots.
- pub fn snapshot_path(&self) -> PathBuf {
+ pub fn snapshot_path(&self, mode: Mode) -> PathBuf {
let mut path_buf = PathBuf::new();
- path_buf.push(SNAPSHOT_DIR);
+ path_buf.push(mode.snapshot_dir());
path_buf.push(self.to_string());
path_buf
@@ -65,10 +67,10 @@ impl Snapshot {
/// Converts the `Snapshot` to its remote storage location,
/// i.e. a member of the `/mnt/hbak/backups` directory
/// where other nodes may store it.
- pub fn backup_path(&self) -> PathBuf {
+ pub fn backup_path(&self, mode: Mode) -> PathBuf {
let mut path_buf = PathBuf::new();
- path_buf.push(BACKUP_DIR);
+ path_buf.push(mode.backup_dir());
path_buf.push(self.to_string());
path_buf
@@ -83,10 +85,10 @@ impl Snapshot {
/// This behavior allows partial or failed transmissions to be retried
/// and is used to prevent (malicious) overwriting of existing snapshots
/// that have fully been written.
- pub fn streaming_path(&self) -> PathBuf {
+ pub fn streaming_path(&self, mode: Mode) -> PathBuf {
let mut path_buf = PathBuf::new();
- path_buf.push(BACKUP_DIR);
+ path_buf.push(mode.backup_dir());
path_buf.push(format!("{self}.part"));
path_buf
@@ -283,12 +285,28 @@ impl Mode {
Self::Server => MOUNTPOINTS,
}
}
+
+ /// Returns the correct snapshot directory for the `Mode`.
+ pub fn snapshot_dir(&self) -> &'static str {
+ match self {
+ Self::Client => SNAPSHOT_DIR_C,
+ Self::Server => SNAPSHOT_DIR_S,
+ }
+ }
+
+ /// Returns the correct backup directory for the `Mode`.
+ pub fn backup_dir(&self) -> &'static str {
+ match self {
+ Self::Client => SNAPSHOT_DIR_C,
+ Self::Server => SNAPSHOT_DIR_S,
+ }
+ }
}
/// A `LocalNode` represents the current machine.
pub struct LocalNode {
config: NodeConfig,
- mountpoint: &'static str,
+ mode: Mode,
_btrfs: UnmountDrop<Mount>,
}
@@ -305,7 +323,7 @@ impl LocalNode {
Ok(Self {
config,
- mountpoint,
+ mode,
_btrfs: Mount::builder().data("compress=zstd").mount_autodrop(
device,
mountpoint,
@@ -319,6 +337,11 @@ impl LocalNode {
&self.config
}
+ /// Returns the [`Mode`] (network client or server) of the `LocalNode`.
+ pub fn mode(&self) -> Mode {
+ self.mode
+ }
+
/// Reports whether the `LocalNode` is the origin of the specified subvolume.
pub fn owns_subvol(&self, subvol: &String) -> bool {
self.config().subvols.contains(subvol)
@@ -340,14 +363,14 @@ impl LocalNode {
return Err(LocalNodeError::ForeignSubvolume(subvol));
}
- let src = Path::new(self.mountpoint).join(&subvol);
+ let src = Path::new(self.mode.mountpoint()).join(&subvol);
let snapshot = Snapshot {
node_name: self.name().to_string(),
subvol,
is_incremental,
taken: Utc::now().naive_utc(),
};
- let dst = snapshot.snapshot_path();
+ let dst = snapshot.snapshot_path(self.mode);
if dst.exists() {
return Err(LocalNodeError::SnapshotExists(snapshot));
@@ -375,7 +398,7 @@ impl LocalNode {
return Err(LocalNodeError::ForeignSubvolume(subvol));
}
- let snapshots = fs::read_dir(SNAPSHOT_DIR)?;
+ let snapshots = fs::read_dir(self.mode.snapshot_dir())?;
let mut all_snapshots = Vec::new();
for snapshot in snapshots {
all_snapshots.push(Snapshot::try_from(&*snapshot?.path())?);
@@ -437,7 +460,7 @@ impl LocalNode {
&self,
snapshot: &Snapshot,
) -> Result<SnapshotStream<BufReader<ChildStdout>>, LocalNodeError> {
- let src = snapshot.snapshot_path();
+ let src = snapshot.snapshot_path(self.mode);
let cmd = Command::new("btrfs")
.arg("send")
.arg("--compressed-data")
@@ -468,7 +491,7 @@ impl LocalNode {
} else {
Ok(Box::new(BufReader::with_capacity(
CHUNKSIZE,
- File::open(snapshot.backup_path())?,
+ File::open(snapshot.backup_path(self.mode))?,
)))
}
}
@@ -480,7 +503,7 @@ impl LocalNode {
mut stream: SnapshotStream<B>,
snapshot: &Snapshot,
) -> Result<(), LocalNodeError> {
- let dst = snapshot.backup_path();
+ let dst = snapshot.backup_path(self.mode);
let mut file = BufWriter::with_capacity(CHUNKSIZE, File::create(dst)?);
io::copy(&mut stream, &mut file)?;
@@ -492,7 +515,7 @@ impl LocalNode {
pub fn all_backups(&self, volume: Option<&Volume>) -> Result<Vec<Snapshot>, LocalNodeError> {
let mut all_backups = Vec::new();
- let backups = fs::read_dir(BACKUP_DIR)?;
+ let backups = fs::read_dir(self.mode.backup_dir())?;
for backup in backups {
let backup = backup?;
@@ -636,7 +659,7 @@ impl LocalNode {
pub fn recover(
&self,
) -> Result<(Child, RecoveryStream<BufWriter<ChildStdin>, &str>), LocalNodeError> {
- let dst = SNAPSHOT_DIR;
+ let dst = self.mode.snapshot_dir();
let mut cmd = Command::new("btrfs")
.arg("receive")
.arg(dst)
diff --git a/hbak_common/src/system.rs b/hbak_common/src/system.rs
index 408c415..1f0c9d4 100644
--- a/hbak_common/src/system.rs
+++ b/hbak_common/src/system.rs
@@ -1,5 +1,5 @@
use crate::config::NodeConfig;
-use crate::proto::{BACKUP_DIR, SNAPSHOT_DIR};
+use crate::proto::{BACKUP_DIR_C, SNAPSHOT_DIR_C};
use crate::LocalNodeError;
use std::fs;
@@ -61,7 +61,7 @@ fn init_btrfs(device: &str) -> Result<(), LocalNodeError> {
if !Command::new("btrfs")
.arg("subvolume")
.arg("create")
- .arg(SNAPSHOT_DIR)
+ .arg(SNAPSHOT_DIR_C)
.spawn()?
.wait()?
.success()
@@ -72,7 +72,7 @@ fn init_btrfs(device: &str) -> Result<(), LocalNodeError> {
if !Command::new("btrfs")
.arg("subvolume")
.arg("create")
- .arg(BACKUP_DIR)
+ .arg(BACKUP_DIR_C)
.spawn()?
.wait()?
.success()
@@ -113,7 +113,7 @@ fn deinit_btrfs() -> Result<(), LocalNodeError> {
if !Command::new("btrfs")
.arg("subvolume")
.arg("delete")
- .arg(BACKUP_DIR)
+ .arg(BACKUP_DIR_C)
.spawn()?
.wait()?
.success()
@@ -125,7 +125,7 @@ fn deinit_btrfs() -> Result<(), LocalNodeError> {
.arg("subvolume")
.arg("list")
.arg("-o")
- .arg(SNAPSHOT_DIR)
+ .arg(SNAPSHOT_DIR_C)
.output()?;
if !output.status.success() {
return Err(LocalNodeError::BtrfsCmd);
@@ -156,7 +156,7 @@ fn deinit_btrfs() -> Result<(), LocalNodeError> {
if !Command::new("btrfs")
.arg("subvolume")
.arg("delete")
- .arg(SNAPSHOT_DIR)
+ .arg(SNAPSHOT_DIR_C)
.spawn()?
.wait()?
.success()
diff --git a/hbakd/src/main.rs b/hbakd/src/main.rs
index 87763df..c1427fc 100644
--- a/hbakd/src/main.rs
+++ b/hbakd/src/main.rs
@@ -141,11 +141,12 @@ fn handle_client(local_node: &LocalNode, stream: TcpStream) -> Result<(), Networ
return Err(RemoteError::AccessDenied);
}
- if snapshot.backup_path().exists() {
+ if snapshot.backup_path(Mode::Server).exists() {
return Err(RemoteError::Immutable);
}
- let file = File::create(snapshot.streaming_path()).map_err(|_| RemoteError::RxError)?;
+ let file = File::create(snapshot.streaming_path(Mode::Server))
+ .map_err(|_| RemoteError::RxError)?;
println!(
"[info] <{}@{}> Receiving {}",
@@ -156,8 +157,11 @@ fn handle_client(local_node: &LocalNode, stream: TcpStream) -> Result<(), Networ
};
let rx_finish = |snapshot: Snapshot| {
- fs::rename(snapshot.streaming_path(), snapshot.backup_path())
- .map_err(|_| RemoteError::RxError)?;
+ fs::rename(
+ snapshot.streaming_path(Mode::Server),
+ snapshot.backup_path(Mode::Server),
+ )
+ .map_err(|_| RemoteError::RxError)?;
println!(
"[info] <{}@{}> Received {}",