Skip to content

Commit

Permalink
fix: services and greenboot functionality
Browse files Browse the repository at this point in the history
Services are orchestretated in a way that greenboot runs before
systemd-update-done.services and the rollback bindsto the same service
to ensure that rollback only runs when a system is updated.
boot_counter now terminates at 0 and motd is witteen in /etc/motd.d/.
Log as modified for better readability.

Signed-off-by: Sayan Paul <[email protected]>
  • Loading branch information
say-paul committed Jul 11, 2023
1 parent 61c1794 commit c3de62a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 51 deletions.
10 changes: 4 additions & 6 deletions dist/systemd/system/greenboot-rollback.service
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@

[Unit]
Description=Greenboot rollback
DefaultDependencies=no
Before=multi-user.target ostree-finalize-staged.service greenboot.service
Wants=local-fs.target
After=local-fs.target
ConditionNeedsUpdate=|/etc
ConditionNeedsUpdate=|/var
Requires=dbus.service
RequiresMountsFor=/boot
After=systemd-update-done.service
BindsTo=systemd-update-done.service

[Service]
Type=oneshot
Expand Down
5 changes: 4 additions & 1 deletion dist/systemd/system/greenboot.service
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
[Unit]
Description=greenboot Health Checks Runner
Before=boot-complete.target
DefaultDependencies=no
Before=boot-complete.target systemd-update-done.service
OnFailureJobMode=fail
RequiresMountsFor=/boot
RequiresMountsFor=/etc

[Service]
Type=oneshot
Expand Down
2 changes: 1 addition & 1 deletion greenboot.spec
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
%global __cargo_is_lib() false
%global forgeurl https://github.com/fedora-iot/greenboot

Version: 1.0.1
Version: 1.1.09

%forgemeta

Expand Down
104 changes: 61 additions & 43 deletions src/handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,30 @@ use std::str;
pub fn handle_reboot(force: bool) -> Result<(), Error> {
if !force {
match get_boot_counter() {
Some(t) if t <= -1 => bail!("boot_counter is less than equal to -1"),
Some(t) if t <= 0 => bail!("countdown ended, check greenboot-rollback status"),
None => bail!("boot_counter is not set"),
_ => {}
}
}
log::info!("restarting system");
Command::new("systemctl").arg("reboot").status()?;
Ok(())
let status = Command::new("systemctl").arg("reboot").status()?;
if status.success() {
return Ok(());
}
bail!("systemd returned error");
}

pub fn handle_rollback() -> Result<(), Error> {
match get_boot_counter() {
Some(-1) => {
Some(t) if t <= 0 => {
log::info!("Greenboot will now attempt rollback");
let status = Command::new("rpm-ostree").arg("rollback").status()?;
if status.success() {
return Ok(());
}
bail!(status.to_string());
}
_ => bail!("boot_counter is either unset or not equal to -1"),
_ => bail!("boot_counter is either unset or not equal to 0"),
}
}

Expand All @@ -38,44 +41,38 @@ pub fn set_boot_counter(reboot_count: i32) -> Result<()> {
Ok(())
}
None => {
Command::new("grub2-editenv")
.arg("-")
.arg("set")
.arg(format!("boot_counter={reboot_count}"))
.status()?;
log::info!("boot_counter={reboot_count}");
Ok(())
if set_grub_var("boot_counter", reboot_count) {
log::info!("boot_counter={reboot_count}");
return Ok(());
}
bail!("grub returned error");
}
}
}

pub fn unset_boot_counter() -> Result<()> {
Command::new("grub2-editenv")
let status = Command::new("grub2-editenv")
.arg("-")
.arg("unset")
.arg("boot_counter")
.status()?;
Ok(())
if status.success() {
return Ok(());
}
bail!("grub retruned error")
}

pub fn handle_boot_success(success: bool) -> Result<()> {
if success {
Command::new("grub2-editenv")
.arg("-")
.arg("set")
.arg("boot_success=1")
.status()?;
Command::new("grub2-editenv")
.arg("-")
.arg("unset")
.arg("boot_counter")
.status()?;
} else {
Command::new("grub2-editenv")
.arg("-")
.arg("set")
.arg("boot_success=0")
.status()?;
if !set_grub_var("boot_success", 1) {
bail!("unable to mark boot as success, grub retruned error")
}
match unset_boot_counter() {
Ok(_) => return Ok(()),
Err(e) => bail!("unable to remove boot_counter, {e}"),
}
} else if !set_grub_var("boot_success", 0) {
bail!("unable to mark boot as failure, grub retruned error")
}
Ok(())
}
Expand All @@ -86,7 +83,7 @@ pub fn handle_motd(state: &str) -> Result<(), Error> {
let mut motd_file = OpenOptions::new()
.create(true)
.write(true)
.open("/run/motd.d/boot-status")?;
.open("/etc/motd.d/boot-status")?;
motd_file.write_all(motd.as_bytes())?;
Ok(())
}
Expand All @@ -98,25 +95,46 @@ pub fn get_boot_counter() -> Option<i32> {
}
let grub_vars = grub_vars.unwrap();
let grub_vars = match str::from_utf8(&grub_vars.stdout[..]) {
Ok(vars) => vars.split('\n'),
Err(_) => {
log::error!("Unable to fetch grub variables");
Ok(vars) => vars.lines(),
Err(e) => {
log::error!("Unable to fetch grub variables, {e}");
return None;
}
};

for var in grub_vars {
if var.contains("boot_counter") {
let boot_counter = var.split('=').last();

match boot_counter.unwrap().parse::<i32>() {
Ok(count) => return Some(count),
Err(_) => {
log::error!("boot_counter not a valid integer");
return None;
}
let (k, v) = if let Some(kv) = var.split_once('=') {
kv
} else {
continue;
};
if k != "boot_counter" {
continue;
}
match v.parse::<i32>() {
Ok(count) => return Some(count),
Err(_) => {
log::error!("boot_counter not a valid integer");
return None;
}
}
}
None
}

fn set_grub_var(key: &str, val: i32) -> bool {
match Command::new("grub2-editenv")
.arg("-")
.arg("set")
.arg(format!("{key}={val}"))
.status()
{
Ok(status) => {
if status.success() {
return true;
}
false
}
Err(_) => false,
}
}

0 comments on commit c3de62a

Please sign in to comment.