extract todo module
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
pub mod cmd;
|
pub mod cmd;
|
||||||
|
pub mod todo;
|
||||||
pub mod zfs;
|
pub mod zfs;
|
||||||
|
|||||||
+8
-74
@@ -8,7 +8,8 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
use zfs_backup::cmd::cryptsetup;
|
use zfs_backup::cmd::cryptsetup;
|
||||||
use zfs_backup::cmd::zfs::zpool_import;
|
use zfs_backup::cmd::zfs::zpool_import;
|
||||||
use zfs_backup::zfs::{Dataset, Snapshot, ZPool};
|
use zfs_backup::todo;
|
||||||
|
use zfs_backup::zfs::ZPool;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
verify_running_as_root()?;
|
verify_running_as_root()?;
|
||||||
@@ -80,7 +81,7 @@ fn do_backup(
|
|||||||
snapshot_tag: String,
|
snapshot_tag: String,
|
||||||
snapshot_interval: String,
|
snapshot_interval: String,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let todos = Todo::plan(local_pool, backup_pool, snapshot_tag, snapshot_interval)
|
let todos = todo::Todo::plan(local_pool, backup_pool, snapshot_tag, snapshot_interval)
|
||||||
.context("planning todos")?;
|
.context("planning todos")?;
|
||||||
|
|
||||||
if todos.is_empty() {
|
if todos.is_empty() {
|
||||||
@@ -96,26 +97,26 @@ fn do_backup(
|
|||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_todos(local: &ZPool, remote: &ZPool, todos: Vec<Todo>) -> Result<()> {
|
fn execute_todos(local: &ZPool, remote: &ZPool, todos: Vec<todo::Todo>) -> Result<()> {
|
||||||
for todo in todos {
|
for todo in todos {
|
||||||
todo.print();
|
todo.print();
|
||||||
match todo {
|
match todo {
|
||||||
Todo::Absolute(dataset, snapshot) => {
|
todo::Todo::Absolute(dataset, snapshot) => {
|
||||||
let handle = local.send_absolute(&dataset, &snapshot)?;
|
let handle = local.send_absolute(&dataset, &snapshot)?;
|
||||||
remote.receive(handle)?;
|
remote.receive(handle)?;
|
||||||
}
|
}
|
||||||
Todo::Incremental(dataset, common_snapshot, recent_snapshot) => {
|
todo::Todo::Incremental(dataset, common_snapshot, recent_snapshot) => {
|
||||||
let handle =
|
let handle =
|
||||||
local.send_incremental(&dataset, &common_snapshot, &recent_snapshot)?;
|
local.send_incremental(&dataset, &common_snapshot, &recent_snapshot)?;
|
||||||
remote.receive(handle)?;
|
remote.receive(handle)?;
|
||||||
}
|
}
|
||||||
Todo::UpToDate(_, _) => (),
|
todo::Todo::UpToDate(_, _) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ask_user_confirmation(todos: &Vec<Todo>) -> Result<bool> {
|
fn ask_user_confirmation(todos: &Vec<todo::Todo>) -> Result<bool> {
|
||||||
println!("Would to the following:");
|
println!("Would to the following:");
|
||||||
|
|
||||||
for todo in todos {
|
for todo in todos {
|
||||||
@@ -179,70 +180,3 @@ fn verify_running_as_root() -> Result<()> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Todo {
|
|
||||||
Absolute(Dataset, Snapshot),
|
|
||||||
Incremental(Dataset, Snapshot, Snapshot),
|
|
||||||
UpToDate(Dataset, Snapshot),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Todo {
|
|
||||||
fn print(&self) {
|
|
||||||
match self {
|
|
||||||
Todo::Absolute(dataset, snapshot) => {
|
|
||||||
println!(" {dataset}@{snapshot} -> [new]")
|
|
||||||
}
|
|
||||||
Todo::Incremental(dataset, last_common_snapshot, recent_snapshot) => {
|
|
||||||
println!(" {dataset}@{last_common_snapshot} -> ...@{recent_snapshot}")
|
|
||||||
}
|
|
||||||
Todo::UpToDate(dataset, snapshot) => {
|
|
||||||
println!(" {dataset}@{snapshot} is already backed up")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn plan(
|
|
||||||
local: &ZPool,
|
|
||||||
remote: &ZPool,
|
|
||||||
snapshot_tag: String,
|
|
||||||
snapshot_interval: String,
|
|
||||||
) -> Result<Vec<Self>> {
|
|
||||||
let mut result = vec![];
|
|
||||||
|
|
||||||
for local_dataset in &local.datasets {
|
|
||||||
let last_snapshot_with_tag =
|
|
||||||
local_dataset.find_last_snapshot_with_tag(&snapshot_tag, &snapshot_interval)?;
|
|
||||||
|
|
||||||
let remote_dataset = local_dataset.change_pool_name(remote);
|
|
||||||
if !remote.contains(&remote_dataset) {
|
|
||||||
result.push(Todo::Absolute(
|
|
||||||
local_dataset.clone(),
|
|
||||||
last_snapshot_with_tag,
|
|
||||||
));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let remote_dataset = remote.get_matching_dataset(local_dataset).unwrap();
|
|
||||||
|
|
||||||
let last_common_snapshot = Snapshot::find_last_common_snapshot_with_tag(
|
|
||||||
local_dataset,
|
|
||||||
&remote_dataset,
|
|
||||||
&snapshot_tag,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let todo = if last_common_snapshot == last_snapshot_with_tag {
|
|
||||||
Todo::UpToDate(local_dataset.clone(), last_common_snapshot)
|
|
||||||
} else {
|
|
||||||
Todo::Incremental(
|
|
||||||
local_dataset.clone(),
|
|
||||||
last_common_snapshot,
|
|
||||||
last_snapshot_with_tag,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
result.push(todo);
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::zfs::Snapshot;
|
||||||
|
use crate::zfs::ZPool;
|
||||||
|
|
||||||
|
use crate::zfs::Dataset;
|
||||||
|
|
||||||
|
pub enum Todo {
|
||||||
|
Absolute(Dataset, Snapshot),
|
||||||
|
Incremental(Dataset, Snapshot, Snapshot),
|
||||||
|
UpToDate(Dataset, Snapshot),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Todo {
|
||||||
|
pub fn print(&self) {
|
||||||
|
match self {
|
||||||
|
Todo::Absolute(dataset, snapshot) => {
|
||||||
|
println!(" {dataset}@{snapshot} -> [new]")
|
||||||
|
}
|
||||||
|
Todo::Incremental(dataset, last_common_snapshot, recent_snapshot) => {
|
||||||
|
println!(" {dataset}@{last_common_snapshot} -> ...@{recent_snapshot}")
|
||||||
|
}
|
||||||
|
Todo::UpToDate(dataset, snapshot) => {
|
||||||
|
println!(" {dataset}@{snapshot} is already backed up")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn plan(
|
||||||
|
local: &ZPool,
|
||||||
|
remote: &ZPool,
|
||||||
|
snapshot_tag: String,
|
||||||
|
snapshot_interval: String,
|
||||||
|
) -> Result<Vec<Self>> {
|
||||||
|
let mut result = vec![];
|
||||||
|
|
||||||
|
for local_dataset in &local.datasets {
|
||||||
|
let last_snapshot_with_tag =
|
||||||
|
local_dataset.find_last_snapshot_with_tag(&snapshot_tag, &snapshot_interval)?;
|
||||||
|
|
||||||
|
let remote_dataset = local_dataset.change_pool_name(remote);
|
||||||
|
if !remote.contains(&remote_dataset) {
|
||||||
|
result.push(Todo::Absolute(
|
||||||
|
local_dataset.clone(),
|
||||||
|
last_snapshot_with_tag,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let remote_dataset = remote.get_matching_dataset(local_dataset).unwrap();
|
||||||
|
|
||||||
|
let last_common_snapshot = Snapshot::find_last_common_snapshot_with_tag(
|
||||||
|
local_dataset,
|
||||||
|
&remote_dataset,
|
||||||
|
&snapshot_tag,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let todo = if last_common_snapshot == last_snapshot_with_tag {
|
||||||
|
Todo::UpToDate(local_dataset.clone(), last_common_snapshot)
|
||||||
|
} else {
|
||||||
|
Todo::Incremental(
|
||||||
|
local_dataset.clone(),
|
||||||
|
last_common_snapshot,
|
||||||
|
last_snapshot_with_tag,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
result.push(todo);
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user