SHA256
Compare commits
2
Commits
a6e0134d2e
...
c61d283177
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
c61d283177 | ||
|
|
eb6ef2a19f |
@@ -22,7 +22,13 @@ 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";
|
||||||
|
const EFI_BOOT_MOUNT_POINT: &str = "/beefi";
|
||||||
|
const EFI_PARTLABEL: &str = "bee-efi";
|
||||||
|
const BOOT_MENU_LABEL: &str = "Kira OS";
|
||||||
|
const UKI_IMAGE_NAME: &str = "\\EFI\\kira-linux-lts.efi";
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CommandFailed {
|
pub struct CommandFailed {
|
||||||
@@ -268,3 +274,93 @@ pub fn sys_upgrade() -> Result<String, SysUpgradeError> {
|
|||||||
Err(ex) => Err(SysUpgradeError::PkgUpgradeErr((snap_time, ex))),
|
Err(ex) => Err(SysUpgradeError::PkgUpgradeErr((snap_time, ex))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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)?;
|
||||||
|
|
||||||
|
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())
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// We need to use lsblk to find out parent device, or read topology from sysfs
|
||||||
|
/// (basename $(readlink -f /sys/class/block/sda1/..))
|
||||||
|
/// But lsblk approach looks more reasonable
|
||||||
|
/// NAME="/dev/nvme0n1p1" PARTLABEL="nyazefi" PARTN="1" PKNAME="/dev/nvme0n1"
|
||||||
|
/// lsblk -P -p -Q 'PARTLABEL=="nyazefi"' -o NAME,PARTLABEL,PARTN,PKNAME
|
||||||
|
/// Returns: touple of partition number and parent device as Strings (part_num, par_dev)
|
||||||
|
/// Returns Error if no efi partition was found
|
||||||
|
///
|
||||||
|
|
||||||
|
fn get_efi_part_info() -> Result<(String,String), ExecCommandError> {
|
||||||
|
use regex::Regex;
|
||||||
|
let re = Regex::new(r#"^PARTN="([0-9]+)" PKNAME="([0-9a-Z]+)"$"#).unwrap();
|
||||||
|
|
||||||
|
let lsblk_query = format!("PARTLABEL==\"{}\"", EFI_PARTLABEL);
|
||||||
|
let lsblk_args: Vec<&str> = vec!["-P", "-p", "-Q", &lsblk_query, "-o", "PARTN,PKNAME"];
|
||||||
|
let lsblk_res = exec_command_out("lsblk", &lsblk_args)?;
|
||||||
|
|
||||||
|
if let Some(captured) = re.captures(&lsblk_res) {
|
||||||
|
// let part_no = captured[1];
|
||||||
|
// let parent_dev = captured[2];
|
||||||
|
Ok((captured[1].to_string(), captured[2].to_string()))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Err(ExecCommandError::Other(format!("No EFI partition (with PARTLABEL={}) was found!", EFI_PARTLABEL)))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// efibootmgr
|
||||||
|
/// Assuming boot partition has "bee-efi" PARTLABEL
|
||||||
|
///
|
||||||
|
/// Generaly lets just add new record with date. Label modification not allways works?
|
||||||
|
/// May add deletion of old record latel
|
||||||
|
/// sudo efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "Kira OS" --loader '\EFI\nyanlinux\kira-bzz.efi' --unicode 'initrd=\EFI\initrd.img'
|
||||||
|
|
||||||
|
pub fn boot_record_update(maybe_kernel_cmd: Option<&str>) -> Result<(), ExecCommandError> {
|
||||||
|
|
||||||
|
let (efi_partno, efi_parent_dev) = get_efi_part_info()?;
|
||||||
|
|
||||||
|
let local_date = time_format::strftime_local("%Y-%m-%d", time_format::now().unwrap()).unwrap();
|
||||||
|
let boot_label = format!("{} {}", BOOT_MENU_LABEL, local_date);
|
||||||
|
|
||||||
|
let mut efibootmgr_args: Vec<&str> = vec!["--create", "--disk", &efi_parent_dev, "--part", &efi_partno, "--label", &boot_label, "--loader", UKI_IMAGE_NAME];
|
||||||
|
if let Some(kernel_cmd) = maybe_kernel_cmd {
|
||||||
|
efibootmgr_args.push("--unicode");
|
||||||
|
efibootmgr_args.push(kernel_cmd);
|
||||||
|
}
|
||||||
|
exec_command("efibootmgr", &efibootmgr_args)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+64
-36
@@ -14,16 +14,17 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use clap::{Args, Parser};
|
use clap::{Args, Parser, Subcommand};
|
||||||
use signal_hook::{consts::SIGINT, iterator::Signals};
|
use signal_hook::{consts::SIGINT, iterator::Signals};
|
||||||
|
use std;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std;
|
|
||||||
|
|
||||||
mod hive_system;
|
mod hive_system;
|
||||||
|
|
||||||
mod hive_config;
|
mod hive_config;
|
||||||
|
|
||||||
|
use crate::hive_config::HiveConfig;
|
||||||
use crate::hive_system::SysUpgradeError;
|
use crate::hive_system::SysUpgradeError;
|
||||||
|
|
||||||
mod daemon;
|
mod daemon;
|
||||||
@@ -108,34 +109,72 @@ 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)]
|
||||||
struct HiveUpMode {
|
struct RemoteArgs {
|
||||||
/// Check for updates, prints number of updates available
|
/// Ask daemon to chack for updates
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
check_updates: bool,
|
check_updates: bool,
|
||||||
|
|
||||||
/// Check for available updates, prints number of updates available
|
/// Ask daemon if there is any updates available
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
updates_available: bool,
|
updates_avail: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
#[group(required = true, multiple = false)]
|
||||||
|
struct CliArgs {
|
||||||
/// Perform system upgrade
|
/// Perform system upgrade
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
upgrade: bool,
|
upgrade: bool,
|
||||||
|
/// Install new kernel into boot partition
|
||||||
/// Run hive-up in daemon mode
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
daemon: bool,
|
update_boot: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug)]
|
||||||
|
#[group(required = true)] // 'multiple = false' enforces exclusivity
|
||||||
|
enum HiveUpMode {
|
||||||
|
/// Perform local operations
|
||||||
|
Cli(CliArgs),
|
||||||
|
/// Ask hive-up daemon something
|
||||||
|
Remote(RemoteArgs),
|
||||||
|
/// Run hive-up in daemon mode
|
||||||
|
Daemon,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update program fot Kira Linux :3
|
/// Update program fot Kira Linux :3
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(author, version, about)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
/// hive-up operation mode
|
/// hive-up operation mode
|
||||||
#[command(flatten)]
|
#[command(subcommand)]
|
||||||
mode: HiveUpMode,
|
mode: HiveUpMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), HiveUpError> {
|
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));
|
||||||
@@ -153,36 +192,25 @@ fn main() -> Result<(), HiveUpError> {
|
|||||||
// read config
|
// read config
|
||||||
let bzz_config = hive_config::read_config()?;
|
let bzz_config = hive_config::read_config()?;
|
||||||
|
|
||||||
// Check CMD flags
|
match args.mode {
|
||||||
if args.mode.check_updates {
|
HiveUpMode::Daemon => daemon::run(bzz_config, term_flag.clone(), reload_flag.clone())?,
|
||||||
|
HiveUpMode::Cli(cli_args) => {
|
||||||
|
if cli_args.upgrade {
|
||||||
|
cli_upgrade(bzz_config)?;
|
||||||
|
} else if cli_args.update_boot {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HiveUpMode::Remote(remote_args) => {
|
||||||
|
if remote_args.check_updates {
|
||||||
let up_num = hive_intercom::client_check_for_updates()?;
|
let up_num = hive_intercom::client_check_for_updates()?;
|
||||||
println!("Updates awailable: {}", up_num);
|
println!("Updates awailable: {}", up_num);
|
||||||
} else if args.mode.updates_available {
|
} else if remote_args.updates_avail {
|
||||||
let up_num = hive_intercom::client_updates_available()?;
|
let up_num = hive_intercom::client_updates_available()?;
|
||||||
println!("Updates awailable: {}", up_num);
|
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.daemon {
|
|
||||||
daemon::run(bzz_config, term_flag.clone(), reload_flag.clone())?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user