SHA256
Quicksave, working on update logic and stuff
This commit is contained in:
+90
-45
@@ -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();
|
||||||
@@ -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()?;
|
||||||
|
|
||||||
|
|||||||
+5
-9
@@ -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
@@ -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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+63
-12
@@ -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)?
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,23 +170,33 @@ 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() {
|
||||||
@@ -217,3 +235,36 @@ pub fn check_if_run_as_root() -> bool {
|
|||||||
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
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user