SHA256
Wrapping UI rework and rollback progress addition.
This commit is contained in:
Generated
+1
-28
@@ -240,12 +240,6 @@ dependencies = [
|
|||||||
"hashbrown 0.17.1",
|
"hashbrown 0.17.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.8.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.31.3"
|
version = "0.31.3"
|
||||||
@@ -290,14 +284,12 @@ checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nyanit"
|
name = "nyanit"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix",
|
"nix",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"ratatui-textarea",
|
"ratatui-textarea",
|
||||||
"regex-lite",
|
"regex-lite",
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"termion",
|
"termion",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -490,19 +482,6 @@ dependencies = [
|
|||||||
"syn 3.0.5",
|
"syn 3.0.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.151"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"memchr",
|
|
||||||
"serde",
|
|
||||||
"serde_core",
|
|
||||||
"zmij",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -637,9 +616,3 @@ name = "unicode-width"
|
|||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zmij"
|
|
||||||
version = "1.0.23"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
|
||||||
|
|||||||
+1
-3
@@ -1,11 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nyanit"
|
name = "nyanit"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1", features = ["derive"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
nix = { version = "0.31", features = ["mount"] }
|
nix = { version = "0.31", features = ["mount"] }
|
||||||
ratatui = { version = "0.30", default-features = false, features = ["termion"] }
|
ratatui = { version = "0.30", default-features = false, features = ["termion"] }
|
||||||
ratatui-textarea = { version = "0.9", default-features = false, features = ["termion"] }
|
ratatui-textarea = { version = "0.9", default-features = false, features = ["termion"] }
|
||||||
|
|||||||
+49
-30
@@ -74,27 +74,29 @@ const CURRENT_BOOT_LIST_TEXT: &str = "bzz current";
|
|||||||
// ExitCode::SUCCESS
|
// ExitCode::SUCCESS
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
// #[derive(Debug, PartialEq)]
|
||||||
struct RollbackState {
|
// struct RollbackState {
|
||||||
progress: f64,
|
// progress: f64,
|
||||||
progress_text: String,
|
// progress_text: String,
|
||||||
snapshot_date_time: String,
|
// snapshot_date_time: String,
|
||||||
}
|
// roll_iter: nyan_system::RollBackIterator,
|
||||||
impl RollbackState {
|
// }
|
||||||
// Constructor function
|
// impl RollbackState {
|
||||||
pub fn new(snap_date_time: String) -> Self {
|
// // Constructor function
|
||||||
RollbackState {
|
// pub fn new(snaps_list: Vec<String>, snap_date_time: String) -> Self {
|
||||||
progress: 0.0,
|
// RollbackState {
|
||||||
progress_text: "".into(),
|
// progress: 0.0,
|
||||||
snapshot_date_time: snap_date_time,
|
// progress_text: "".into(),
|
||||||
}
|
// snapshot_date_time: snap_date_time.clone(),
|
||||||
}
|
// roll_iter: nyan_system::RollBackIterator::new(snaps_list, snap_date_time)
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum NyanitState {
|
enum NyanitState {
|
||||||
Init,
|
Init,
|
||||||
RollBack(RollbackState),
|
RollBack,
|
||||||
ConfirmRollback(String),
|
ConfirmRollback(String),
|
||||||
WaitForF2,
|
WaitForF2,
|
||||||
/// list of snapshoots
|
/// list of snapshoots
|
||||||
@@ -138,6 +140,7 @@ struct NyanitTUI<'a> {
|
|||||||
time_counter_sec: u64,
|
time_counter_sec: u64,
|
||||||
textarea: Option<TextArea<'a>>,
|
textarea: Option<TextArea<'a>>,
|
||||||
snaps_list: Vec<String>,
|
snaps_list: Vec<String>,
|
||||||
|
roll_state: Option<nyan_system::RollBackIterator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NyanitTUI<'_> {
|
impl NyanitTUI<'_> {
|
||||||
@@ -151,6 +154,7 @@ impl NyanitTUI<'_> {
|
|||||||
time_counter_sec: 0,
|
time_counter_sec: 0,
|
||||||
textarea: None,
|
textarea: None,
|
||||||
snaps_list: Vec::new(),
|
snaps_list: Vec::new(),
|
||||||
|
roll_state: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +355,7 @@ impl NyanitTUI<'_> {
|
|||||||
let par1 = gen_conf_par(snap_dt.clone());
|
let par1 = gen_conf_par(snap_dt.clone());
|
||||||
frame.render_widget(par1, vertical_chunks[1]);
|
frame.render_widget(par1, vertical_chunks[1]);
|
||||||
}
|
}
|
||||||
NyanitState::RollBack(roll_state) => {
|
NyanitState::RollBack => {
|
||||||
let centered = vertical_chunks[1].centered_vertically(Constraint::Length(9));
|
let centered = vertical_chunks[1].centered_vertically(Constraint::Length(9));
|
||||||
// 1. Create the outer block
|
// 1. Create the outer block
|
||||||
let block = Block::default()
|
let block = Block::default()
|
||||||
@@ -374,10 +378,11 @@ impl NyanitTUI<'_> {
|
|||||||
.split(block_inner_area);
|
.split(block_inner_area);
|
||||||
let gauge = Gauge::default()
|
let gauge = Gauge::default()
|
||||||
.gauge_style(Style::default().fg(Color::LightRed))
|
.gauge_style(Style::default().fg(Color::LightRed))
|
||||||
.ratio(roll_state.progress);
|
.ratio(self.roll_state.as_ref().unwrap().progress);
|
||||||
frame.render_widget(gauge, chunks[0]);
|
frame.render_widget(gauge, chunks[0]);
|
||||||
|
|
||||||
let text = Paragraph::new(roll_state.progress_text.clone()).centered();
|
let text = Paragraph::new(self.roll_state.as_ref().unwrap().progress_text.clone())
|
||||||
|
.centered();
|
||||||
frame.render_widget(text, chunks[2]);
|
frame.render_widget(text, chunks[2]);
|
||||||
}
|
}
|
||||||
NyanitState::EnterPassword => {
|
NyanitState::EnterPassword => {
|
||||||
@@ -489,8 +494,11 @@ impl NyanitTUI<'_> {
|
|||||||
}
|
}
|
||||||
NyanitState::ConfirmRollback(snap_dt) => match e {
|
NyanitState::ConfirmRollback(snap_dt) => match e {
|
||||||
Key::Char('Y') | Key::Char('y') => {
|
Key::Char('Y') | Key::Char('y') => {
|
||||||
let roll_state = RollbackState::new(snap_dt.clone());
|
self.roll_state = Some(nyan_system::RollBackIterator::new(
|
||||||
self.state = NyanitState::RollBack(roll_state);
|
self.snaps_list.clone(),
|
||||||
|
snap_dt.clone(),
|
||||||
|
));
|
||||||
|
self.state = NyanitState::RollBack;
|
||||||
}
|
}
|
||||||
Key::Char(_) => self.state = NyanitState::ChooseSnapshot,
|
Key::Char(_) => self.state = NyanitState::ChooseSnapshot,
|
||||||
_ => (),
|
_ => (),
|
||||||
@@ -500,15 +508,26 @@ impl NyanitTUI<'_> {
|
|||||||
} else {
|
} else {
|
||||||
// Tick time
|
// Tick time
|
||||||
thread::sleep(Duration::from_millis(TICK_TIME_MILLS));
|
thread::sleep(Duration::from_millis(TICK_TIME_MILLS));
|
||||||
|
match self.state {
|
||||||
if let NyanitState::WaitForF2 = self.state {
|
NyanitState::WaitForF2 => {
|
||||||
self.time_counter = self.time_counter.wrapping_add(TICK_TIME_MILLS);
|
self.time_counter = self.time_counter.wrapping_add(TICK_TIME_MILLS);
|
||||||
self.time_counter_sec = self.time_counter / 1000;
|
self.time_counter_sec = self.time_counter / 1000;
|
||||||
// wait for F2
|
// wait for F2
|
||||||
if self.time_counter_sec > WAIT_FOR_F2_SEC {
|
if self.time_counter_sec > WAIT_FOR_F2_SEC {
|
||||||
// boot from root
|
// boot from root
|
||||||
self.state = NyanitState::HandOff;
|
self.state = NyanitState::HandOff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
NyanitState::RollBack => match self.roll_state.as_mut().unwrap().next() {
|
||||||
|
Some(Err(ex)) => {
|
||||||
|
self.state = NyanitState::Error(format!("ROLL BACK ERROR!: {}", ex));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.state = NyanitState::HandOff;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+248
-139
@@ -22,6 +22,7 @@ use nix;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
|
||||||
/// timeout for block deices population
|
/// timeout for block deices population
|
||||||
const WAIT_FOR_BLK_DEVS: u64 = 5u64;
|
const WAIT_FOR_BLK_DEVS: u64 = 5u64;
|
||||||
|
|
||||||
@@ -343,27 +344,12 @@ pub fn subvolume_delete(subvolume: &str) -> Result<(), ExecCommandError> {
|
|||||||
/// vol: "usr" or "var"
|
/// vol: "usr" or "var"
|
||||||
/// dt: datetime
|
/// dt: datetime
|
||||||
///
|
///
|
||||||
fn snap_name_from_dt(vol: &str, dt: &str) -> String {
|
// fn snap_name_from_dt(vol: &str, dt: &str) -> String {
|
||||||
format!("bzz-{}-{}", vol, dt)
|
// format!("bzz-{}-{}", vol, dt)
|
||||||
}
|
// }
|
||||||
|
|
||||||
///
|
#[derive(Debug, PartialEq)]
|
||||||
///
|
enum RollbackIterStates {
|
||||||
/// // Stable Rust example using from_fn
|
|
||||||
fn first_n(n: u64) -> impl Iterator<Item = u64> {
|
|
||||||
let mut count = 0;
|
|
||||||
std::iter::from_fn(move || {
|
|
||||||
if count < n {
|
|
||||||
let val = count;
|
|
||||||
count += 1;
|
|
||||||
Some(val)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
enum RollbackStates {
|
|
||||||
Start,
|
Start,
|
||||||
RenameUsrVarAct,
|
RenameUsrVarAct,
|
||||||
ChangeToRw,
|
ChangeToRw,
|
||||||
@@ -374,125 +360,249 @@ enum RollbackStates {
|
|||||||
Err,
|
Err,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn roll_back_snap(
|
// 1. Define the iterator struct
|
||||||
snaps_list: &Vec<String>,
|
#[derive(Debug, PartialEq)]
|
||||||
target_snap: &str,
|
pub struct RollBackIterator {
|
||||||
) -> impl Iterator<Item = Result<String, ExecCommandError>> {
|
pub progress: f64,
|
||||||
let usr_ro_snap_path = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", target_snap);
|
pub progress_text: String,
|
||||||
let var_ro_snap_path = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", target_snap);
|
snaps_list: Vec<String>,
|
||||||
|
target_snap: String,
|
||||||
let mut roll_state = RollbackStates::Start;
|
usr_ro_snap_path: String,
|
||||||
|
var_ro_snap_path: String,
|
||||||
std::iter::from_fn(move || match roll_state {
|
state: RollbackIterStates,
|
||||||
RollbackStates::Start => {
|
|
||||||
roll_state = RollbackStates::RenameUsrVarAct;
|
|
||||||
Some(Ok("Move usr and var to temporary location".into()))
|
|
||||||
}
|
|
||||||
RollbackStates::RenameUsrVarAct => {
|
|
||||||
let move_res = fs::rename(TMP_ROOT_USR, TMP_ROOT_SNAPS_USR)
|
|
||||||
.and_then(|_| fs::rename(TMP_ROOT_VAR, TMP_ROOT_SNAPS_VAR));
|
|
||||||
if let Err(ex) = move_res {
|
|
||||||
roll_state = RollbackStates::Err;
|
|
||||||
Some(Err(ex.into()))
|
|
||||||
} else {
|
|
||||||
roll_state = RollbackStates::ChangeToRw;
|
|
||||||
Some(Ok("Setting snapshot as current system ...".into()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RollbackStates::ChangeToRw => {
|
|
||||||
let rw_res = snapshot_rw(&usr_ro_snap_path, TMP_ROOT_USR)
|
|
||||||
.and_then(|_| snapshot_rw(&var_ro_snap_path, TMP_ROOT_VAR));
|
|
||||||
if let Err(ex) = rw_res {
|
|
||||||
roll_state = RollbackStates::Err;
|
|
||||||
Some(Err(ex))
|
|
||||||
} else {
|
|
||||||
roll_state = RollbackStates::MoveSubvolums;
|
|
||||||
Some(Ok(
|
|
||||||
"Moving subvolumes from old /usr and /var to new one".into()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RollbackStates::MoveSubvolums => {
|
|
||||||
let mut mv_res = Some(Ok("Removing old /usr and /var".into()));
|
|
||||||
for (vol, svol_path) in SBUVOL_TO_MOVE {
|
|
||||||
let v_from = format!("{}{}{}", TMP_ROOT_SNAPS_PREFIX, vol, svol_path);
|
|
||||||
let v_dest = format!("{}/{}{}", TMP_ROOT, vol, svol_path);
|
|
||||||
if let Err(ex) = fs::rename(v_from, v_dest) {
|
|
||||||
roll_state = RollbackStates::Err;
|
|
||||||
mv_res = Some(Err(ex.into()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roll_state = RollbackStates::RemoveOldVols;
|
|
||||||
mv_res
|
|
||||||
}
|
|
||||||
RollbackStates::RemoveOldVols => {
|
|
||||||
let rem_old_res = subvolume_delete(TMP_ROOT_SNAPS_USR)
|
|
||||||
.and_then(|_| subvolume_delete(TMP_ROOT_SNAPS_VAR));
|
|
||||||
if let Err(ex) = rem_old_res {
|
|
||||||
roll_state = RollbackStates::Err;
|
|
||||||
Some(Err(ex))
|
|
||||||
} else {
|
|
||||||
roll_state = RollbackStates::ClearSnaps;
|
|
||||||
Some(Ok("Clearing snapshots...".into()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RollbackStates::ClearSnaps => {
|
|
||||||
let mut clr_snap_res = Some(Ok("All done!".into()));
|
|
||||||
for snap_date_time in snaps_list.iter().rev() {
|
|
||||||
let usr_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
|
||||||
let var_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
|
||||||
if let Err(ex) =
|
|
||||||
subvolume_delete(&usr_snap).and_then(|_| subvolume_delete(&var_snap))
|
|
||||||
{
|
|
||||||
clr_snap_res = Some(Err(ex));
|
|
||||||
roll_state = RollbackStates::Err;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if snap_date_time == target_snap {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clr_snap_res
|
|
||||||
}
|
|
||||||
RollbackStates::Finish => None,
|
|
||||||
RollbackStates::Err => None,
|
|
||||||
})
|
|
||||||
|
|
||||||
// 1. Rename usr and var to TMP_ROOT_SNAPS/tmp_var|usr
|
|
||||||
// fs::rename(TMP_ROOT_USR, TMP_ROOT_SNAPS_USR)?;
|
|
||||||
// fs::rename(TMP_ROOT_VAR, TMP_ROOT_SNAPS_VAR)?;
|
|
||||||
|
|
||||||
// 2. snapshot desired snaps as RW to /usr and /var
|
|
||||||
// snapshot_rw(&usr_ro_snap_path, TMP_ROOT_USR)?;
|
|
||||||
// snapshot_rw(&var_ro_snap_path, TMP_ROOT_VAR)?;
|
|
||||||
|
|
||||||
// 3. move subvolumes from old /usr and /var
|
|
||||||
// for (vol, svol_path) in SBUVOL_TO_MOVE {
|
|
||||||
// let v_from = format!("{}{}{}", TMP_ROOT_SNAPS_PREFIX, vol, svol_path);
|
|
||||||
// let v_dest = format!("{}/{}{}",TMP_ROOT,vol,svol_path);
|
|
||||||
// fs::rename(v_from, v_dest)?;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 4. removing tmp /usr /var
|
|
||||||
// subvolume_delete(TMP_ROOT_SNAPS_USR)?;
|
|
||||||
// subvolume_delete(TMP_ROOT_SNAPS_VAR)?;
|
|
||||||
|
|
||||||
// 5. Removing all snapshoots made after one we restored, including inself
|
|
||||||
// Iterate in reverse untill we get to target_snap in snaps list
|
|
||||||
// for snap_date_time in snaps_list.iter().rev() {
|
|
||||||
// let usr_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
|
||||||
// let var_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
|
||||||
// subvolume_delete(&usr_snap)?;
|
|
||||||
// subvolume_delete(&var_snap)?;
|
|
||||||
// if snap_date_time == target_snap {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RollBackIterator {
|
||||||
|
pub fn new(snaps_list: Vec<String>, target_snap: String) -> Self {
|
||||||
|
let usr_ro_snap_path = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", &target_snap);
|
||||||
|
let var_ro_snap_path = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "var", &target_snap);
|
||||||
|
Self {
|
||||||
|
progress: 0.0,
|
||||||
|
progress_text: "Starting...".into(),
|
||||||
|
snaps_list: snaps_list,
|
||||||
|
target_snap: target_snap,
|
||||||
|
usr_ro_snap_path: usr_ro_snap_path,
|
||||||
|
var_ro_snap_path: var_ro_snap_path,
|
||||||
|
state: RollbackIterStates::Start,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Implement Iterator for the iterator struct
|
||||||
|
impl Iterator for RollBackIterator {
|
||||||
|
type Item = Result<f64, ExecCommandError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self.state {
|
||||||
|
RollbackIterStates::Start => {
|
||||||
|
self.state = RollbackIterStates::RenameUsrVarAct;
|
||||||
|
self.progress = 0.0;
|
||||||
|
self.progress_text = "Move usr and var to temporary location".into();
|
||||||
|
Some(Ok(self.progress))
|
||||||
|
}
|
||||||
|
RollbackIterStates::RenameUsrVarAct => {
|
||||||
|
let move_res = fs::rename(TMP_ROOT_USR, TMP_ROOT_SNAPS_USR)
|
||||||
|
.and_then(|_| fs::rename(TMP_ROOT_VAR, TMP_ROOT_SNAPS_VAR));
|
||||||
|
if let Err(ex) = move_res {
|
||||||
|
self.state = RollbackIterStates::Err;
|
||||||
|
Some(Err(ex.into()))
|
||||||
|
} else {
|
||||||
|
self.state = RollbackIterStates::ChangeToRw;
|
||||||
|
self.progress_text = "Setting snapshot as current system ...".into();
|
||||||
|
self.progress = 0.1;
|
||||||
|
Some(Ok(self.progress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RollbackIterStates::ChangeToRw => {
|
||||||
|
let rw_res = snapshot_rw(&self.usr_ro_snap_path, TMP_ROOT_USR)
|
||||||
|
.and_then(|_| snapshot_rw(&self.var_ro_snap_path, TMP_ROOT_VAR));
|
||||||
|
if let Err(ex) = rw_res {
|
||||||
|
self.state = RollbackIterStates::Err;
|
||||||
|
Some(Err(ex))
|
||||||
|
} else {
|
||||||
|
self.state = RollbackIterStates::MoveSubvolums;
|
||||||
|
self.progress_text =
|
||||||
|
"Moving subvolumes from old /usr and /var to new one".into();
|
||||||
|
self.progress = 0.2;
|
||||||
|
Some(Ok(self.progress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RollbackIterStates::MoveSubvolums => {
|
||||||
|
self.progress = 0.3;
|
||||||
|
self.progress_text = "Removing old /usr and /var".into();
|
||||||
|
|
||||||
|
let mut mv_res = Some(Ok(self.progress));
|
||||||
|
for (vol, svol_path) in SBUVOL_TO_MOVE {
|
||||||
|
let v_from = format!("{}{}{}", TMP_ROOT_SNAPS_PREFIX, vol, svol_path);
|
||||||
|
let v_dest = format!("{}/{}{}", TMP_ROOT, vol, svol_path);
|
||||||
|
if let Err(ex) = fs::rename(v_from, v_dest) {
|
||||||
|
self.state = RollbackIterStates::Err;
|
||||||
|
mv_res = Some(Err(ex.into()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.state = RollbackIterStates::RemoveOldVols;
|
||||||
|
mv_res
|
||||||
|
}
|
||||||
|
RollbackIterStates::RemoveOldVols => {
|
||||||
|
let rem_old_res = subvolume_delete(TMP_ROOT_SNAPS_USR)
|
||||||
|
.and_then(|_| subvolume_delete(TMP_ROOT_SNAPS_VAR));
|
||||||
|
if let Err(ex) = rem_old_res {
|
||||||
|
self.state = RollbackIterStates::Err;
|
||||||
|
Some(Err(ex))
|
||||||
|
} else {
|
||||||
|
self.state = RollbackIterStates::ClearSnaps;
|
||||||
|
self.progress_text = "Clearing snapshots...".into();
|
||||||
|
self.progress = 0.6;
|
||||||
|
Some(Ok(self.progress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RollbackIterStates::ClearSnaps => {
|
||||||
|
self.progress = 1.0;
|
||||||
|
self.progress_text = "All done!".into();
|
||||||
|
let mut clr_snap_res = Some(Ok(self.progress));
|
||||||
|
for snap_date_time in self.snaps_list.iter().rev() {
|
||||||
|
let usr_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
||||||
|
let var_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
||||||
|
if let Err(ex) =
|
||||||
|
subvolume_delete(&usr_snap).and_then(|_| subvolume_delete(&var_snap))
|
||||||
|
{
|
||||||
|
clr_snap_res = Some(Err(ex));
|
||||||
|
self.state = RollbackIterStates::Err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if snap_date_time == &self.target_snap {
|
||||||
|
self.state = RollbackIterStates::Finish;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clr_snap_res
|
||||||
|
}
|
||||||
|
RollbackIterStates::Finish => None,
|
||||||
|
RollbackIterStates::Err => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn roll_back_snap(
|
||||||
|
// snaps_list: Vec<String>,
|
||||||
|
// target_snap: String,
|
||||||
|
// ) -> impl Iterator<Item = Result<String, ExecCommandError>> {
|
||||||
|
// let usr_ro_snap_path = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", target_snap);
|
||||||
|
// let var_ro_snap_path = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", target_snap);
|
||||||
|
|
||||||
|
// let mut roll_state = RollbackStates::Start;
|
||||||
|
|
||||||
|
// std::iter::from_fn(move || match roll_state {
|
||||||
|
// RollbackStates::Start => {
|
||||||
|
// roll_state = RollbackStates::RenameUsrVarAct;
|
||||||
|
// Some(Ok("Move usr and var to temporary location".into()))
|
||||||
|
// }
|
||||||
|
// RollbackStates::RenameUsrVarAct => {
|
||||||
|
// let move_res = fs::rename(TMP_ROOT_USR, TMP_ROOT_SNAPS_USR)
|
||||||
|
// .and_then(|_| fs::rename(TMP_ROOT_VAR, TMP_ROOT_SNAPS_VAR));
|
||||||
|
// if let Err(ex) = move_res {
|
||||||
|
// roll_state = RollbackStates::Err;
|
||||||
|
// Some(Err(ex.into()))
|
||||||
|
// } else {
|
||||||
|
// roll_state = RollbackStates::ChangeToRw;
|
||||||
|
// Some(Ok("Setting snapshot as current system ...".into()))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// RollbackStates::ChangeToRw => {
|
||||||
|
// let rw_res = snapshot_rw(&usr_ro_snap_path, TMP_ROOT_USR)
|
||||||
|
// .and_then(|_| snapshot_rw(&var_ro_snap_path, TMP_ROOT_VAR));
|
||||||
|
// if let Err(ex) = rw_res {
|
||||||
|
// roll_state = RollbackStates::Err;
|
||||||
|
// Some(Err(ex))
|
||||||
|
// } else {
|
||||||
|
// roll_state = RollbackStates::MoveSubvolums;
|
||||||
|
// Some(Ok(
|
||||||
|
// "Moving subvolumes from old /usr and /var to new one".into()
|
||||||
|
// ))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// RollbackStates::MoveSubvolums => {
|
||||||
|
// let mut mv_res = Some(Ok("Removing old /usr and /var".into()));
|
||||||
|
// for (vol, svol_path) in SBUVOL_TO_MOVE {
|
||||||
|
// let v_from = format!("{}{}{}", TMP_ROOT_SNAPS_PREFIX, vol, svol_path);
|
||||||
|
// let v_dest = format!("{}/{}{}", TMP_ROOT, vol, svol_path);
|
||||||
|
// if let Err(ex) = fs::rename(v_from, v_dest) {
|
||||||
|
// roll_state = RollbackStates::Err;
|
||||||
|
// mv_res = Some(Err(ex.into()));
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// roll_state = RollbackStates::RemoveOldVols;
|
||||||
|
// mv_res
|
||||||
|
// }
|
||||||
|
// RollbackStates::RemoveOldVols => {
|
||||||
|
// let rem_old_res = subvolume_delete(TMP_ROOT_SNAPS_USR)
|
||||||
|
// .and_then(|_| subvolume_delete(TMP_ROOT_SNAPS_VAR));
|
||||||
|
// if let Err(ex) = rem_old_res {
|
||||||
|
// roll_state = RollbackStates::Err;
|
||||||
|
// Some(Err(ex))
|
||||||
|
// } else {
|
||||||
|
// roll_state = RollbackStates::ClearSnaps;
|
||||||
|
// Some(Ok("Clearing snapshots...".into()))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// RollbackStates::ClearSnaps => {
|
||||||
|
// let mut clr_snap_res = Some(Ok("All done!".into()));
|
||||||
|
// for snap_date_time in snaps_list.iter().rev() {
|
||||||
|
// let usr_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
||||||
|
// let var_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
||||||
|
// if let Err(ex) =
|
||||||
|
// subvolume_delete(&usr_snap).and_then(|_| subvolume_delete(&var_snap))
|
||||||
|
// {
|
||||||
|
// clr_snap_res = Some(Err(ex));
|
||||||
|
// roll_state = RollbackStates::Err;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// if snap_date_time == &target_snap {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// clr_snap_res
|
||||||
|
// }
|
||||||
|
// RollbackStates::Finish => None,
|
||||||
|
// RollbackStates::Err => None,
|
||||||
|
// })
|
||||||
|
|
||||||
|
// // 1. Rename usr and var to TMP_ROOT_SNAPS/tmp_var|usr
|
||||||
|
// // fs::rename(TMP_ROOT_USR, TMP_ROOT_SNAPS_USR)?;
|
||||||
|
// // fs::rename(TMP_ROOT_VAR, TMP_ROOT_SNAPS_VAR)?;
|
||||||
|
|
||||||
|
// // 2. snapshot desired snaps as RW to /usr and /var
|
||||||
|
// // snapshot_rw(&usr_ro_snap_path, TMP_ROOT_USR)?;
|
||||||
|
// // snapshot_rw(&var_ro_snap_path, TMP_ROOT_VAR)?;
|
||||||
|
|
||||||
|
// // 3. move subvolumes from old /usr and /var
|
||||||
|
// // for (vol, svol_path) in SBUVOL_TO_MOVE {
|
||||||
|
// // let v_from = format!("{}{}{}", TMP_ROOT_SNAPS_PREFIX, vol, svol_path);
|
||||||
|
// // let v_dest = format!("{}/{}{}",TMP_ROOT,vol,svol_path);
|
||||||
|
// // fs::rename(v_from, v_dest)?;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // 4. removing tmp /usr /var
|
||||||
|
// // subvolume_delete(TMP_ROOT_SNAPS_USR)?;
|
||||||
|
// // subvolume_delete(TMP_ROOT_SNAPS_VAR)?;
|
||||||
|
|
||||||
|
// // 5. Removing all snapshoots made after one we restored, including inself
|
||||||
|
// // Iterate in reverse untill we get to target_snap in snaps list
|
||||||
|
// // for snap_date_time in snaps_list.iter().rev() {
|
||||||
|
// // let usr_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
||||||
|
// // let var_snap = format!("{}/bzz-{}-{}", TMP_ROOT_SNAPS, "usr", snap_date_time);
|
||||||
|
// // subvolume_delete(&usr_snap)?;
|
||||||
|
// // subvolume_delete(&var_snap)?;
|
||||||
|
// // if snap_date_time == target_snap {
|
||||||
|
// // break;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks if pac_lock file exist and returns date-time from it if it does,
|
/// Checks if pac_lock file exist and returns date-time from it if it does,
|
||||||
/// Otherwise return None
|
/// Otherwise return None
|
||||||
@@ -503,8 +613,7 @@ pub fn check_pac_lock() -> Result<Option<String>, ExecCommandError> {
|
|||||||
if pac_lock_path.exists() {
|
if pac_lock_path.exists() {
|
||||||
let snap_dt = fs::read_to_string(pac_lock_path)?;
|
let snap_dt = fs::read_to_string(pac_lock_path)?;
|
||||||
Ok(Some(snap_dt.trim().into()))
|
Ok(Some(snap_dt.trim().into()))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user