Quicksave, working on update logic and stuff

This commit is contained in:
2026-08-27 16:53:56 +02:00
parent 7bd95a826e
commit a6e0134d2e
5 changed files with 317 additions and 122 deletions
+92 -47
View File
@@ -18,17 +18,17 @@
hive-up daemon logic hive-up daemon logic
*/ */
use std::os::unix::net::UnixDatagram;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::thread; use std::thread;
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::os::unix::net::UnixDatagram;
use crate::hive_config;
use crate::hive_config::HiveConfig; use crate::hive_config::HiveConfig;
use crate::hive_db::{self, HiveDb}; use crate::hive_db::{self, HiveDb};
use crate::hive_config; use crate::hive_intercom::{self, BzzReq, BzzResp, IntercomError};
use crate::hive_system; use crate::hive_system;
use crate::hive_intercom::{self, IntercomError, BzzReq, BzzResp};
#[derive(Debug)] #[derive(Debug)]
pub enum DaemonError { pub enum DaemonError {
@@ -58,7 +58,6 @@ impl From<hive_config::ConfigError> for DaemonError {
} }
} }
impl From<hive_system::ExecCommandError> for DaemonError { impl From<hive_system::ExecCommandError> for DaemonError {
fn from(err: hive_system::ExecCommandError) -> Self { fn from(err: hive_system::ExecCommandError) -> Self {
DaemonError::ExecCommandError(err) DaemonError::ExecCommandError(err)
@@ -88,54 +87,94 @@ fn get_timestamp_sec() -> u64 {
} }
/// bloking function. Bloaks for configured socker recv timeout /// bloking function. Bloaks for configured socker recv timeout
fn process_remoute(bzz_db: &mut HiveDb, listening_socket: &UnixDatagram, recv_buf: &mut [u8]) -> Result<(), DaemonError> { fn process_remoute(
bzz_db: &mut HiveDb,
listening_socket: &UnixDatagram,
recv_buf: &mut [u8],
) -> Result<(), DaemonError> {
// waiting on socket recv_from untill timeout (also using this as a timer) // waiting on socket recv_from untill timeout (also using this as a timer)
match hive_intercom::socket_recv(&listening_socket, recv_buf) { match hive_intercom::socket_recv(&listening_socket, recv_buf) {
// we get some request to process // we get some request to process
Ok((bzz_req, client_addr)) => { Ok((bzz_req, client_addr)) => {
match bzz_req { match bzz_req {
// return awailable updates number // return awailable updates number
BzzReq::UpdatesAvailable => { BzzReq::UpdatesAvailable => {
let resp = BzzResp::UpdatesAvailable(bzz_db.updates_available);
if let Err(ex) =
hive_intercom::socket_send(&listening_socket, &client_addr, resp)
{
println!("Error while ansvering cli request: {}", ex);
}
}
// we should apply updates if any on reboot
BzzReq::ScheduleUpdate => {
// but only if we have actually any updates
if bzz_db.updates_available > 0 {
bzz_db.update_on_reboot = true;
// keep it simple Kira
// lets just return err from the loop if something wrong with db
hive_db::write_db(&bzz_db)?;
// signal remoute that evertyhing go OK
if let Err(ex) = hive_intercom::socket_send(
&listening_socket,
&client_addr,
BzzResp::Finish,
) {
println!("Error while ansvering cli request: {}", ex);
}
}
}
BzzReq::CheckForUpdates => {
let resp = BzzResp::Working(1);
if let Err(ex) =
hive_intercom::socket_send(&listening_socket, &client_addr, resp)
{
println!("Error while ansvering cli request: {}", ex);
} else {
// perform update check
println!("Cheking for updates...");
// now that may fail because of bad internet and idealy we
// want to just log error and retry in other time
bzz_db.updates_available = match hive_system::check_updates() {
Ok(updates_num) => updates_num,
Err(ex) => {
println!("Error while shecking for updates: {}", ex);
0u32
}
};
hive_db::write_db(&bzz_db)?;
println!(
"Found {} packages that needs to be updated.",
bzz_db.updates_available
);
// send evailable updates numbet to client
let resp = BzzResp::UpdatesAvailable(bzz_db.updates_available); let resp = BzzResp::UpdatesAvailable(bzz_db.updates_available);
if let Err(ex) = hive_intercom::socket_send(&listening_socket,&client_addr, resp) { if let Err(ex) =
hive_intercom::socket_send(&listening_socket, &client_addr, resp)
{
println!("Error while ansvering cli request: {}", ex); println!("Error while ansvering cli request: {}", ex);
} }
},
// we should apply updates if any on reboot
BzzReq::ScheduleUpdate => {
// but only if we have actually any updates
if bzz_db.updates_available > 0 {
bzz_db.update_on_reboot = true;
// keep it simple Kira
// lets just return err from the loop if something wrong with db
hive_db::write_db(&bzz_db)?;
// signal remoute that evertyhing go OK
if let Err(ex) = hive_intercom::socket_send(&listening_socket,&client_addr, BzzResp::Finish) {
println!("Error while ansvering cli request: {}", ex);
}
}
} }
} }
Ok(())
}
// if time out - do nothing
Err(IntercomError::Timeout) => {
Ok(())
}
// if some actual IO error then return it
Err(IntercomError::IoError(ex)) => Err(ex.into()),
// if other kinds of errors - log and continue
Err(ex) => {
println!("Got error while listenin to unix socket: {}", ex);
print!("Sleeping for 1 secong and continue...");
thread::sleep(Duration::from_secs(1));
Ok(())
} }
Ok(())
} }
// if time out - do nothing
Err(IntercomError::Timeout) => Ok(()),
// if some actual IO error then return it
Err(IntercomError::IoError(ex)) => Err(ex.into()),
// if other kinds of errors - log and continue
Err(ex) => {
println!("Got error while listenin to unix socket: {}", ex);
print!("Sleeping for 1 secong and continue...");
thread::sleep(Duration::from_secs(1));
Ok(())
}
}
} }
// doing what daemons usually beezz // doing what daemons usually beezz
fn do_local_work(config: &HiveConfig, bzz_db: &mut HiveDb)-> Result<(), DaemonError> { fn do_local_work(config: &HiveConfig, bzz_db: &mut HiveDb) -> Result<(), DaemonError> {
// if updates check is turned on // if updates check is turned on
if config.update.updates_check_interval != 0 { if config.update.updates_check_interval != 0 {
let timestamp = get_timestamp_sec(); let timestamp = get_timestamp_sec();
@@ -150,7 +189,7 @@ fn do_local_work(config: &HiveConfig, bzz_db: &mut HiveDb)-> Result<(), DaemonEr
if hours_since_update_check > config.update.updates_check_interval { if hours_since_update_check > config.update.updates_check_interval {
// perform update check // perform update check
println!("Cheking for updates..."); println!("Cheking for updates...");
// now that may fail because of bad internet and idealy we // now that may fail because of bad internet and idealy we
// want to just log error and retry in other time // want to just log error and retry in other time
bzz_db.updates_available = match hive_system::check_updates() { bzz_db.updates_available = match hive_system::check_updates() {
Ok(updates_num) => updates_num, Ok(updates_num) => updates_num,
@@ -160,14 +199,21 @@ fn do_local_work(config: &HiveConfig, bzz_db: &mut HiveDb)-> Result<(), DaemonEr
} }
}; };
hive_db::write_db(&bzz_db)?; hive_db::write_db(&bzz_db)?;
println!("Found {} packages that needs to be updated.", bzz_db.updates_available); println!(
"Found {} packages that needs to be updated.",
bzz_db.updates_available
);
// if auto download for updates is enabled and there is some updates - download them // if auto download for updates is enabled and there is some updates - download them
if config.update.download_updates && bzz_db.updates_available != 0 { if config.update.download_updates && bzz_db.updates_available != 0 {
println!("Downloadin updates..."); println!("Downloadin updates...");
match hive_system::download_updates() { match hive_system::download_updates() {
Ok(()) => {println!("Updates downloaded...");}, Ok(()) => {
Err(ex) => {println!("Error downloading updates: {}", ex);} println!("Updates downloaded...");
}
Err(ex) => {
println!("Error downloading updates: {}", ex);
}
} }
} }
@@ -184,7 +230,6 @@ pub fn run(
term_flag: Arc<AtomicBool>, term_flag: Arc<AtomicBool>,
reload_flag: Arc<AtomicBool>, reload_flag: Arc<AtomicBool>,
) -> Result<(), DaemonError> { ) -> Result<(), DaemonError> {
// reading db from disk // reading db from disk
let mut bzz_db = hive_db::read_db()?; let mut bzz_db = hive_db::read_db()?;
@@ -194,7 +239,7 @@ pub fn run(
// init udp unix socket for communication with cli and such // init udp unix socket for communication with cli and such
let listening_socket = hive_intercom::socket_bind(1)?; let listening_socket = hive_intercom::socket_bind(1)?;
let mut recv_buf: Vec<u8> = Vec::with_capacity(1024); let mut recv_buf: Vec<u8> = Vec::with_capacity(1024);
// main loop (I love loops) (No please just do recursion properly) // main loop (I love loops) (No please just do recursion properly)
while keep_going { while keep_going {
process_remoute(&mut bzz_db, &listening_socket, recv_buf.as_mut_slice())?; process_remoute(&mut bzz_db, &listening_socket, recv_buf.as_mut_slice())?;
+6 -10
View File
@@ -18,9 +18,8 @@
Functions fot system interaction Functions fot system interaction
*/ */
use serde::{Deserialize, Serialize};
use serde::{Serialize, Deserialize}; use std::fs;
use std::{fs, io};
use toml; use toml;
const CONFIG_PATH: &str = "/etc/hive_up.toml"; const CONFIG_PATH: &str = "/etc/hive_up.toml";
@@ -49,7 +48,6 @@ pub struct UpdateConfig {
pub auto_update: bool, pub auto_update: bool,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum ConfigError { pub enum ConfigError {
IoError(std::io::Error), IoError(std::io::Error),
@@ -82,10 +80,10 @@ impl std::fmt::Display for ConfigError {
ConfigError::IoError(e) => write!(f, "IO Error: {}", e), ConfigError::IoError(e) => write!(f, "IO Error: {}", e),
ConfigError::TomlParseError(e) => { ConfigError::TomlParseError(e) => {
write!(f, "TOML parse error: {}", e) write!(f, "TOML parse error: {}", e)
}, }
ConfigError::TomlSerError(e) => { ConfigError::TomlSerError(e) => {
write!(f, "TOML serialize error: {}", e) write!(f, "TOML serialize error: {}", e)
}, }
} }
} }
} }
@@ -95,11 +93,10 @@ impl std::error::Error for ConfigError {}
pub fn read_config() -> Result<HiveConfig, ConfigError> { pub fn read_config() -> Result<HiveConfig, ConfigError> {
let file_content = fs::read_to_string(CONFIG_PATH)?; let file_content = fs::read_to_string(CONFIG_PATH)?;
let config:HiveConfig = toml::from_str(&file_content)?; let config: HiveConfig = toml::from_str(&file_content)?;
Ok(config) Ok(config)
} }
pub fn change_updates_check_interval(new_interval: u64) -> Result<HiveConfig, ConfigError> { pub fn change_updates_check_interval(new_interval: u64) -> Result<HiveConfig, ConfigError> {
let mut config: HiveConfig = read_config()?; let mut config: HiveConfig = read_config()?;
config.update.updates_check_interval = new_interval; config.update.updates_check_interval = new_interval;
@@ -107,5 +104,4 @@ pub fn change_updates_check_interval(new_interval: u64) -> Result<HiveConfig, Co
fs::write(CONFIG_PATH, conf_str)?; fs::write(CONFIG_PATH, conf_str)?;
Ok(config) Ok(config)
}
}
+38 -14
View File
@@ -26,7 +26,7 @@ use std::time::Duration;
pub const SOCKET_DIR: &str = "/run/hive-up"; pub const SOCKET_DIR: &str = "/run/hive-up";
pub const SOCKET_PATH: &str = "/run/hive-up/hive-intercom.soc"; pub const SOCKET_PATH: &str = "/run/hive-up/hive-intercom.soc";
pub const CLINET_READ_TIMEOUT: u64 = 5; pub const CLINET_READ_TIMEOUT_SECONDS: u64 = 88;
#[derive(Debug)] #[derive(Debug)]
pub enum IntercomError { pub enum IntercomError {
@@ -83,7 +83,9 @@ impl std::error::Error for IntercomError {}
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum BzzResp { pub enum BzzResp {
Working, /// signalls progress of a task as u16 integer.
/// interpretation is up to you.
Working(u16),
Finish, Finish,
UpdatesAvailable(u32), UpdatesAvailable(u32),
Error(String), Error(String),
@@ -93,6 +95,7 @@ pub enum BzzResp {
#[repr(u8)] #[repr(u8)]
pub enum BzzReq { pub enum BzzReq {
UpdatesAvailable, UpdatesAvailable,
CheckForUpdates,
ScheduleUpdate, ScheduleUpdate,
} }
@@ -113,7 +116,11 @@ pub fn socket_bind(read_timeout_sec: u64) -> Result<UnixDatagram, std::io::Error
} }
// for daemon side // for daemon side
pub fn socket_send(socket: &UnixDatagram, client_addr: &SocketAddr, resp: BzzResp) -> Result<(), IntercomError> { pub fn socket_send(
socket: &UnixDatagram,
client_addr: &SocketAddr,
resp: BzzResp,
) -> Result<(), IntercomError> {
let resp_buff = postcard::to_stdvec(&resp)?; let resp_buff = postcard::to_stdvec(&resp)?;
socket.send_to_addr(resp_buff.as_slice(), client_addr)?; socket.send_to_addr(resp_buff.as_slice(), client_addr)?;
Ok(()) Ok(())
@@ -141,28 +148,36 @@ pub fn socket_recv(
fn send_and_recv(request: BzzReq) -> Result<BzzResp, IntercomError> { fn send_and_recv(request: BzzReq) -> Result<BzzResp, IntercomError> {
let socket = UnixDatagram::unbound()?; let socket = UnixDatagram::unbound()?;
socket.connect(SOCKET_PATH)?; socket.connect(SOCKET_PATH)?;
socket.set_read_timeout(Some(Duration::from_secs(CLINET_READ_TIMEOUT)))?; socket.set_read_timeout(Some(Duration::from_secs(CLINET_READ_TIMEOUT_SECONDS)))?;
let encoded_buf = postcard::to_stdvec(&request)?; let encoded_buf = postcard::to_stdvec(&request)?;
socket.send(encoded_buf.as_slice())?; socket.send(encoded_buf.as_slice())?;
let mut recv_buf: Vec<u8> = Vec::with_capacity(1024); let mut recv_buf: Vec<u8> = Vec::with_capacity(1024);
match socket.recv(recv_buf.as_mut_slice()) {
Ok(rec_count) => { loop {
if rec_count != 0 { match socket.recv(recv_buf.as_mut_slice()) {
println!("DEBUG: Total bytes recieved {}", rec_count); Ok(rec_count) => {
let decoded_resp: BzzResp = postcard::from_bytes(&recv_buf)?; if rec_count != 0 {
Ok(decoded_resp) println!("DEBUG: Total bytes recieved {}", rec_count);
} else { let decoded_resp: BzzResp = postcard::from_bytes(&recv_buf)?;
Err(IntercomError::ConnectionClosed) if let BzzResp::Working(progress) = decoded_resp {
println!("Working... {}", progress);
continue;
} else {
return Ok(decoded_resp);
}
} else {
return Err(IntercomError::ConnectionClosed);
}
} }
Err(e) => return Err(e.into()),
} }
Err(e) => Err(e.into()),
} }
} }
fn updates_available() -> Result<u32, IntercomError> { pub fn client_updates_available() -> Result<u32, IntercomError> {
let resp = send_and_recv(BzzReq::UpdatesAvailable)?; let resp = send_and_recv(BzzReq::UpdatesAvailable)?;
match resp { match resp {
BzzResp::UpdatesAvailable(updates_count) => Ok(updates_count), BzzResp::UpdatesAvailable(updates_count) => Ok(updates_count),
@@ -170,3 +185,12 @@ fn updates_available() -> Result<u32, IntercomError> {
_ => Err(IntercomError::UnexpectedResponse), _ => Err(IntercomError::UnexpectedResponse),
} }
} }
pub fn client_check_for_updates() -> Result<u32, IntercomError> {
let resp = send_and_recv(BzzReq::CheckForUpdates)?;
match resp {
BzzResp::UpdatesAvailable(updates_count) => Ok(updates_count),
BzzResp::Error(ex) => Err(IntercomError::ServerError(ex)),
_ => Err(IntercomError::UnexpectedResponse),
}
}
+66 -15
View File
@@ -22,7 +22,6 @@ use std::fs;
use std::process::Command; use std::process::Command;
use time_format; use time_format;
const SNAPS_DIR: &str = "/bzz_snaps"; const SNAPS_DIR: &str = "/bzz_snaps";
#[derive(Debug)] #[derive(Debug)]
@@ -140,11 +139,21 @@ pub fn check_updates() -> Result<u32, ExecCommandError> {
// Check for updates // Check for updates
let out = Command::new("pacman").arg("-Qu").output()?; let out = Command::new("pacman").arg("-Qu").output()?;
if out.status.success() { if out.status.success() {
Ok(String::from_utf8(out.stdout)?.lines().count().try_into().unwrap()) Ok(String::from_utf8(out.stdout)?
.lines()
.count()
.try_into()
.unwrap())
} else { } else {
if let Some(code) = out.status.code() && code == 1 { Ok(0) } if let Some(code) = out.status.code()
else { && code == 1
Err(ExecCommandError::Other(format!("pacman -Qu failed: {}", String::from_utf8(out.stderr)?))) {
Ok(0)
} else {
Err(ExecCommandError::Other(format!(
"pacman -Qu failed: {}",
String::from_utf8(out.stderr)?
)))
} }
} }
} }
@@ -152,7 +161,7 @@ pub fn check_updates() -> Result<u32, ExecCommandError> {
/// ///
/// sudo pacman -Suw --noconfirm --noprogressbar /// sudo pacman -Suw --noconfirm --noprogressbar
/// Download updates (need to check for updates first) /// Download updates (need to check for updates first)
/// ///
pub fn download_updates() -> Result<(), ExecCommandError> { pub fn download_updates() -> Result<(), ExecCommandError> {
exec_command("pacman", &vec!["-Suw", "--noconfirm", "--noprogressbar"]) exec_command("pacman", &vec!["-Suw", "--noconfirm", "--noprogressbar"])
} }
@@ -160,24 +169,34 @@ pub fn download_updates() -> Result<(), ExecCommandError> {
/// ///
/// sudo pacman -Su --noconfirm --noprogressbar /// sudo pacman -Su --noconfirm --noprogressbar
/// Perform updates /// Perform updates
/// ///
pub fn do_updates() -> Result<(), ExecCommandError> { pub fn pkg_upgrade() -> Result<(), ExecCommandError> {
exec_command("pacman", &vec!["-Su", "--noconfirm", "--noprogressbar"]) exec_command("pacman", &vec!["-Su", "--noconfirm", "--noprogressbar"])
} }
/// ///
/// bcachefs subvolume snapshot -r / /snap1 /// bcachefs subvolume snapshot -r / /snap1
/// -r creates read only snapshot /// -r creates read only snapshot
/// returns snapshot name on sucess /// returns snapshot time on sucess
///
pub fn snapshot_root() -> Result<String, ExecCommandError> { pub fn snapshot_root() -> Result<String, ExecCommandError> {
use std::path::Path;
// if snaps dir path do not exist - create it
let snaps_path = Path::new(SNAPS_DIR);
if !snaps_path.exists() {
fs::create_dir(snaps_path)?;
}
let ts = time_format::now().unwrap(); let ts = time_format::now().unwrap();
let local_time = time_format::strftime_local("%Y-%m-%dT%H:%M:%S", ts).unwrap(); let local_time = time_format::strftime_local("%Y-%m-%dT%H:%M:%S", ts).unwrap();
let snapshot_name = format!("{}/bzz-{}",SNAPS_DIR,local_time); let snapshot_name = format!("{}/bzz-{}", SNAPS_DIR, local_time);
exec_command("bcachefs", &vec!["subvolume", "snapshot", "-r", "/", &snapshot_name])?; exec_command(
"bcachefs",
&vec!["subvolume", "snapshot", "-r", "/", &snapshot_name],
)?;
Ok(snapshot_name) Ok(local_time)
} }
//const TMP_ROOT: &str = "/mnt/bee-root"; //const TMP_ROOT: &str = "/mnt/bee-root";
@@ -208,7 +227,6 @@ pub fn list_bzzpss_snaps() -> Result<Vec<String>, ExecCommandError> {
Ok(res) Ok(res)
} }
pub fn check_if_run_as_root() -> bool { pub fn check_if_run_as_root() -> bool {
use nix::unistd::Uid; use nix::unistd::Uid;
if Uid::effective().is_root() { if Uid::effective().is_root() {
@@ -216,4 +234,37 @@ pub fn check_if_run_as_root() -> bool {
} else { } else {
false false
} }
} }
#[derive(Debug)]
pub enum SysUpgradeError {
SnapshotError(ExecCommandError),
PkgUpgradeErr((String, ExecCommandError)),
}
impl std::fmt::Display for SysUpgradeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
SysUpgradeError::SnapshotError(e) => write!(f, "Snapshot creation error: {}", e),
SysUpgradeError::PkgUpgradeErr((_, e)) => write!(f, "Packages upgrade error: {}", e),
}
}
}
// Implement std::error::Error
impl std::error::Error for SysUpgradeError {}
///
/// Perform system upgrade
/// Reruns root snapshot name on success
/// In case of upgrade error SysUpgradeError::PkgUpgradeErr contains snapshot time is str format
///
pub fn sys_upgrade() -> Result<String, SysUpgradeError> {
// snapshooting root
let snap_time = snapshot_root().map_err(SysUpgradeError::SnapshotError)?;
// try to perform packages upgrade
match pkg_upgrade() {
Ok(_) => Ok(snap_time),
Err(ex) => Err(SysUpgradeError::PkgUpgradeErr((snap_time, ex))),
}
}
+115 -36
View File
@@ -18,33 +18,109 @@ use clap::{Args, Parser};
use signal_hook::{consts::SIGINT, iterator::Signals}; use signal_hook::{consts::SIGINT, iterator::Signals};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::{error::Error, thread, time::Duration}; use std;
mod hive_system; mod hive_system;
use hive_system::ExecCommandError;
mod hive_config; mod hive_config;
use hive_config::{HiveConfig, KernelConfig};
use crate::hive_system::SysUpgradeError;
mod daemon; mod daemon;
mod hive_db; mod hive_db;
mod hive_intercom; mod hive_intercom;
#[derive(Debug)]
pub enum HiveUpError {
IoError(std::io::Error),
HiveSystemCommandError(hive_system::ExecCommandError),
HiveDbError(hive_db::DBError),
HiveConfigError(hive_config::ConfigError),
HiveIntercomError(hive_intercom::IntercomError),
HiveDaemonErr(daemon::DaemonError),
Other(String),
}
impl From<std::io::Error> for HiveUpError {
fn from(err: std::io::Error) -> Self {
HiveUpError::IoError(err)
}
}
impl From<hive_system::ExecCommandError> for HiveUpError {
fn from(err: hive_system::ExecCommandError) -> Self {
HiveUpError::HiveSystemCommandError(err)
}
}
impl From<hive_db::DBError> for HiveUpError {
fn from(err: hive_db::DBError) -> Self {
HiveUpError::HiveDbError(err)
}
}
impl From<hive_config::ConfigError> for HiveUpError {
fn from(err: hive_config::ConfigError) -> Self {
HiveUpError::HiveConfigError(err)
}
}
impl From<hive_intercom::IntercomError> for HiveUpError {
fn from(err: hive_intercom::IntercomError) -> Self {
HiveUpError::HiveIntercomError(err)
}
}
impl From<daemon::DaemonError> for HiveUpError {
fn from(err: daemon::DaemonError) -> Self {
HiveUpError::HiveDaemonErr(err)
}
}
impl From<String> for HiveUpError {
fn from(err: String) -> Self {
HiveUpError::Other(err)
}
}
impl From<&str> for HiveUpError {
fn from(err: &str) -> Self {
HiveUpError::Other(err.to_string())
}
}
impl std::fmt::Display for HiveUpError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
HiveUpError::IoError(e) => write!(f, "IO Error: {}", e),
HiveUpError::HiveSystemCommandError(e) => write!(f, "ExecCommandError: {}", e),
HiveUpError::HiveDbError(ex) => write!(f, "DBError: {}", ex),
HiveUpError::HiveConfigError(ex) => write!(f, "Config error: {}", ex),
HiveUpError::HiveIntercomError(e) => write!(f, "IntercomError: {}", e),
HiveUpError::HiveDaemonErr(e) => write!(f, "HiveDaemonErr: {}", e),
HiveUpError::Other(msg) => write!(f, "Error: {}", msg),
}
}
}
// Implement std::error::Error
impl std::error::Error for HiveUpError {}
// Define the mutually exclusive group // Define the mutually exclusive group
#[derive(Args, Debug)] #[derive(Args, Debug)]
#[group(required = true, multiple = false)] // 'multiple = false' enforces exclusivity #[group(required = true, multiple = false)] // 'multiple = false' enforces exclusivity
struct HiveUpMode { struct HiveUpMode {
/// Check for updates, prints number of updates available /// Check for updates, prints number of updates available
#[arg(long)] #[arg(long)]
check: bool, check_updates: bool,
/// Perform system update /// Check for available updates, prints number of updates available
#[arg(long)] #[arg(long)]
update: bool, updates_available: bool,
/// Boot update /// Perform system upgrade
#[arg(long)] #[arg(long)]
boot_update: bool, upgrade: bool,
/// Run hive-up in daemon mode /// Run hive-up in daemon mode
#[arg(long)] #[arg(long)]
@@ -60,7 +136,7 @@ struct Cli {
mode: HiveUpMode, mode: HiveUpMode,
} }
fn main() -> Result<(), String> { fn main() -> Result<(), HiveUpError> {
// registering signals handling // registering signals handling
let term_flag: Arc<AtomicBool> = Arc::new(AtomicBool::new(false)); let term_flag: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
let reload_flag = Arc::new(AtomicBool::new(false)); let reload_flag = Arc::new(AtomicBool::new(false));
@@ -71,39 +147,42 @@ fn main() -> Result<(), String> {
let args = Cli::parse(); let args = Cli::parse();
if !hive_system::check_if_run_as_root() { if !hive_system::check_if_run_as_root() {
return Err("Error: This program requires root privileges.".to_string()); return Err("Error: This program requires root privileges.".into());
} }
// read config // read config
let bzz_config = match hive_config::read_config() { let bzz_config = hive_config::read_config()?;
Ok(conf) => conf,
Err(ex) => {
return Err(format!("Error reading hive-up config file: {}", ex));
}
};
// Logic to check which one was set // Check CMD flags
if args.mode.check { if args.mode.check_updates {
match hive_system::check_updates() { let up_num = hive_intercom::client_check_for_updates()?;
Ok(up_num) => println!("Updates awailable: {}", up_num), println!("Updates awailable: {}", up_num);
Err(ex) => println!("Error: {}", ex), } else if args.mode.updates_available {
let up_num = hive_intercom::client_updates_available()?;
println!("Updates awailable: {}", up_num);
} else if args.mode.upgrade {
let mut bzz_db = hive_db::read_db()?;
if bzz_db.update_on_reboot {
println!("Starting full system upgrade");
match hive_system::sys_upgrade() {
Ok(snap_time) => {
bzz_db.update_status = true;
bzz_db.update_on_reboot = false;
bzz_db.last_snapshot_time = snap_time;
hive_db::write_db(&bzz_db)?;
}
Err(SysUpgradeError::PkgUpgradeErr((snap_time, ex))) => {
bzz_db.update_status = false;
bzz_db.update_on_reboot = false;
bzz_db.last_snapshot_time = snap_time;
hive_db::write_db(&bzz_db)?;
return Err(ex.into());
}
Err(ex) => return Err(ex.to_string().into()),
}
} }
} else if args.mode.boot_update {
// update boot
println!("update mode");
} else if args.mode.update {
println!("update mode");
} else if args.mode.daemon { } else if args.mode.daemon {
if let Err(ex) = daemon::run(bzz_config, term_flag.clone(), reload_flag.clone()) { daemon::run(bzz_config, term_flag.clone(), reload_flag.clone())?;
return Err(format!("Hive-Up daemon error: {}", ex));
}
// let snaps = hive_system::list_bzzpss_snaps().unwrap();
// println!("Snaps num: {}", snaps.len());
// for sn in snaps {
// println!("Snap: {}", sn);
// }
} }
Ok(()) Ok(())
} }