1 Commits
6 changed files with 157 additions and 121 deletions
Generated
+9 -41
View File
@@ -2,15 +2,6 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "1.0.0"
@@ -220,12 +211,12 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hive-up"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"clap",
"nix",
"postcard",
"regex",
"regex-lite",
"serde",
"serde_json",
"signal-hook",
@@ -235,9 +226,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.14.1"
version = "2.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb"
checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
dependencies = [
"equivalent",
"hashbrown",
@@ -326,33 +317,10 @@ dependencies = [
]
[[package]]
name = "regex"
version = "1.13.1"
name = "regex-lite"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973"
[[package]]
name = "rustc_version"
@@ -470,9 +438,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "3.0.4"
version = "3.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9"
dependencies = [
"proc-macro2",
"quote",
+3 -3
View File
@@ -1,13 +1,13 @@
[package]
name = "hive-up"
version = "0.1.1"
version = "0.1.2"
edition = "2024"
[dependencies]
clap = { version = "4.6", features = ["derive"] }
nix = { version = "0", features = ["user"] }
postcard = { version = "1.1", features = ["use-std"] }
regex = "1"
regex-lite = "0.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0"
signal-hook = "0.4"
@@ -19,7 +19,7 @@ lto = true
debug = false
incremental = false
codegen-units = 1
opt-level = 2
opt-level = "s"
strip = true
[registry]
+58 -1
View File
@@ -1,3 +1,60 @@
# hive-up
Program to manage update process of Kira Linux. Creating snapshots. Dealing with pacman fail, etc.
Program to manage update process of Kira Linux. Creating snapshots. Dealing with pacman fail, etc.
There should be some documantation here.
hive-up uses `/var/lib/hive-up/hyve-db.json` file as database for stuff
And `/etc/hive-up.toml` as config file.
As an daemon hive-up righ now doing only periodical checks for updates.
```text
Usage: hive-up <COMMAND>
Commands:
cli Perform local operations
remote Ask hive-up daemon something
daemon Run hive-up in daemon mode
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
```
For cli mode:
```text
Usage: hive-up cli <--upgrade|--update-boot|--init-boot-menu|--init-boot>
Options:
--upgrade Perform system upgrade
--update-boot Install new kernel into boot partition
--init-boot-menu Cleans up and recreates UFI boot menu
--init-boot Cleans up and recreates UFI boot menu and /EFI dir content
-h, --help Print help
```
For remote mode:
```text
Usage: hive-up remote <--check-updates|--updates-avail|--schedule-update>
Options:
--check-updates Ask daemon to check for updates
--updates-avail Ask daemon if there is any updates available
--schedule-update Ask daemon to perform system update on next reboot
-h, --help Print help
```
`hive-up daemon` - do not have any flags for now.
`hive-up cli --upgrade` - generally not supposed to be called by user. It get called by system service manager (dinit) after hive-up service stop (on reboot or system shutdown)
When `hive-up cli --upgrade` is called, it checks if `update_on_reboot` flag is set in **DB** or `auto_update` flag checked in **config**, and if `updates_available` in **DB** is non zero. Update routine continue only if this conditios are met.
1. It creates snapshots of `/usr` and `/var` subvolumes
2. It sets `update_status` to **false** in **DB**
3. Performs update, and if everything was fine sets `update_status` to **true** in **DB**
After this, system reboots, and on system boot Nyanit figures up what to do with failed updates if any
+2 -12
View File
@@ -62,7 +62,8 @@ pub struct HiveDb {
pub update_check_timestamp: u64,
/// non zero if there is updates that can bee applied, showing numbers of packages that can be updated
pub updates_available: u32,
/// true if last update fas successful
/// true if last update was successful
/// if it is false - nyanit need to roll back snapshots
pub update_status: bool,
/// datetime of last snapshot in format "%Y-%m-%dT%H:%M:%S"
pub last_snapshot_time: String,
@@ -101,15 +102,4 @@ pub fn write_db(db: &HiveDb) -> Result<(), DBError> {
Ok(())
}
///
/// writes new last update check time to db
/// and returns old db value on success
///
pub fn update_last_check_update_time(new_timestamp: u64) -> Result<u64, DBError> {
let mut db = read_db()?;
let old_value = db.update_check_timestamp;
db.update_check_timestamp = new_timestamp;
write_db(&db)?;
Ok(old_value)
}
+81 -63
View File
@@ -184,12 +184,31 @@ pub fn pkg_upgrade() -> Result<(), ExecCommandError> {
exec_command("pacman", &vec!["-Su", "--noconfirm", "--noprogressbar"])
}
///
/// bcachefs subvolume snapshot -r / /snap1
/// creates read only snapshoy of "subvolume" and places it into "target"]
/// bcachefs subvolume snapshot -r /subvolume /target
/// -r creates read only snapshot
/// returns snapshot time on sucess
///
pub fn snapshot_root() -> Result<String, ExecCommandError> {
pub fn snapshot(subvolume: &str, target: &str) -> Result<(), ExecCommandError> {
exec_command(
"bcachefs",
&vec!["subvolume", "snapshot", "-r", subvolume, target],
)?;
Ok(())
}
///
///
/// bcachefs subvolume snapshot -r /target /SNAPS_DIR/bzz-target-yyyy-mm-ddTHH-MM-SS
/// Creates read only snapshots of /usr and /var subvolumes
/// And places them to /SNAPS_DIR/bzz-usr-yyyy-mm-ddTHH-MM-SS and /SNAPS_DIR/bzz-var-yyyy-mm-ddTHH-MM-SS
/// returns snapshot time on sucess
///
pub fn snapshot_system() -> Result<String, ExecCommandError> {
use std::path::Path;
// if snaps dir path do not exist - create it
let snaps_path = Path::new(SNAPS_DIR);
@@ -199,43 +218,42 @@ pub fn snapshot_root() -> Result<String, ExecCommandError> {
let ts = time_format::now().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 usr_snapshot_name = format!("{}/bzz-usr-{}", SNAPS_DIR, local_time);
let var_snapshot_name = format!("{}/bzz-var-{}", SNAPS_DIR, local_time);
exec_command(
"bcachefs",
&vec!["subvolume", "snapshot", "-r", "/", &snapshot_name],
)?;
snapshot("/usr", &usr_snapshot_name)?;
snapshot("/var", &var_snapshot_name)?;
Ok(local_time)
}
//const TMP_ROOT: &str = "/mnt/bee-root";
pub fn list_bzzpss_snaps() -> Result<Vec<String>, ExecCommandError> {
use regex::Regex;
use std::path::Path;
// pub fn list_bzzpss_snaps() -> Result<Vec<String>, ExecCommandError> {
// use regex::Regex;
// use std::path::Path;
// root snapshoot in a form of bzz-yyyy-mm-ddTHH-MM-SS
let re = Regex::new(r"^bzz-[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}-[0-9]{2}-[0-9]{2}$").unwrap();
// // root snapshoot in a form of bzz-yyyy-mm-ddTHH-MM-SS
// let re = Regex::new(r"^bzz-[a-z]+-[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}-[0-9]{2}-[0-9]{2}$").unwrap();
let mut res: Vec<String> = Vec::new();
// if snaps dir path do not exist return empty list
if !Path::new(SNAPS_DIR).exists() {
return Ok(res);
}
// let mut res: Vec<String> = Vec::new();
// // if snaps dir path do not exist return empty list
// if !Path::new(SNAPS_DIR).exists() {
// return Ok(res);
// }
for maybe_entry in fs::read_dir(SNAPS_DIR)? {
let entry = maybe_entry?;
if entry.file_type()?.is_dir() {
if let Some(dir_name) = entry.file_name().to_str()
&& re.is_match(dir_name)
{
res.push(dir_name.to_string());
}
}
}
res.sort();
Ok(res)
}
// for maybe_entry in fs::read_dir(SNAPS_DIR)? {
// let entry = maybe_entry?;
// if entry.file_type()?.is_dir() {
// if let Some(dir_name) = entry.file_name().to_str()
// && re.is_match(dir_name)
// {
// res.push(dir_name.to_string());
// }
// }
// }
// res.sort();
// Ok(res)
// }
pub fn check_if_run_as_root() -> bool {
use nix::unistd::Uid;
@@ -271,7 +289,7 @@ impl std::error::Error for SysUpgradeError {}
///
pub fn sys_upgrade() -> Result<String, SysUpgradeError> {
// snapshooting root
let snap_time = snapshot_root().map_err(SysUpgradeError::SnapshotError)?;
let snap_time = snapshot_system().map_err(SysUpgradeError::SnapshotError)?;
// try to perform packages upgrade
match pkg_upgrade() {
Ok(_) => Ok(snap_time),
@@ -281,37 +299,37 @@ pub fn sys_upgrade() -> Result<String, SysUpgradeError> {
/// Gets device node aka /dev/sda1 from gpr partition label
/// blkid -s PARTLABEL --match-token PARTLABEL="bzz-primary"
pub fn find_partlabel(partlabel: &str) -> Result<Option<String>, ExecCommandError> {
let out = Command::new("/usr/bin/blkid")
.args([
"-s",
"PARTLABEL",
"-t",
format!("PARTLABEL=\"{}\"", partlabel).as_str(),
])
.output()?;
if out.status.success() {
let out_text = String::from_utf8(out.stdout)?;
// pub fn find_partlabel(partlabel: &str) -> Result<Option<String>, ExecCommandError> {
// let out = Command::new("/usr/bin/blkid")
// .args([
// "-s",
// "PARTLABEL",
// "-t",
// format!("PARTLABEL=\"{}\"", partlabel).as_str(),
// ])
// .output()?;
// if out.status.success() {
// let out_text = String::from_utf8(out.stdout)?;
let split_res = out_text.split_once(':').ok_or_else(|| {
ExecCommandError::Other(format!("Unexpected blkid output format: \"{}\"", out_text))
})?;
// let split_res = out_text.split_once(':').ok_or_else(|| {
// ExecCommandError::Other(format!("Unexpected blkid output format: \"{}\"", out_text))
// })?;
Ok(Some(split_res.0.to_string()))
} else {
if let Some(code) = out.status.code()
&& code == 2
{
Ok(None)
} else {
Err(ExecCommandError::Other(format!(
"Error while looking for partlabel={}: \"{}\"",
partlabel,
String::from_utf8(out.stderr).unwrap_or_else(|ex| ex.to_string())
)))
}
}
}
// Ok(Some(split_res.0.to_string()))
// } else {
// if let Some(code) = out.status.code()
// && code == 2
// {
// Ok(None)
// } else {
// Err(ExecCommandError::Other(format!(
// "Error while looking for partlabel={}: \"{}\"",
// partlabel,
// String::from_utf8(out.stderr).unwrap_or_else(|ex| ex.to_string())
// )))
// }
// }
// }
///
/// We need to use lsblk to find out parent device, or read topology from sysfs
@@ -327,7 +345,7 @@ pub fn find_partlabel(partlabel: &str) -> Result<Option<String>, ExecCommandErro
///
///
fn get_efi_part_info() -> Result<(String, String), ExecCommandError> {
use regex::Regex;
use regex_lite::Regex;
let re = Regex::new(r#"^PARTN="([0-9]+)" PKNAME="([0-9a-Z]+)"$"#).unwrap();
let lsblk_query = format!("PARTLABEL==\"{}\"", EFI_PARTLABEL);
@@ -351,7 +369,7 @@ fn get_efi_part_info() -> Result<(String, String), ExecCommandError> {
/// Boot0000* Nyan
///
fn list_efi_bootnums() -> Result<Vec<String>, ExecCommandError> {
use regex::Regex;
use regex_lite::Regex;
let re = Regex::new(r#"^Boot([0-9A-F]{4})\* "#).unwrap();
let str_res = exec_command_out("efibootmgr", &vec![])?;
@@ -444,7 +462,7 @@ pub fn init_efi_boot_record(maybe_kernel_cmd: &Option<String>) -> Result<(), Exe
/// Result is a sorted vector of string
///
fn list_installed_kernels() -> Result<Vec<String>, ExecCommandError> {
use regex::Regex;
use regex_lite::Regex;
let re = Regex::new(r#"^[0-9]+\.[0-9]+\.[0-9]+-[0-9]-kira-lts"#).unwrap();
let mut kernel_dirs: Vec<String> = Vec::new();
+4 -1
View File
@@ -163,8 +163,11 @@ struct Cli {
fn cli_upgrade(bzz_config: HiveConfig) -> Result<(), HiveUpError> {
let mut bzz_db = hive_db::read_db()?;
if bzz_db.update_on_reboot || bzz_config.update.auto_update {
if (bzz_db.updates_available !=0) && (bzz_db.update_on_reboot || bzz_config.update.auto_update) {
println!("Starting full system upgrade");
bzz_db.update_status = false;
hive_db::write_db(&bzz_db)?;
match hive_system::sys_upgrade() {
Ok(snap_time) => {
bzz_db.update_status = true;