Skip to content

Commit

Permalink
Configure exitcode for reboot/halt on standalone
Browse files Browse the repository at this point in the history
Fixes #557
  • Loading branch information
pfmooney committed Oct 30, 2023
1 parent 4019eb1 commit ba4839f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
6 changes: 6 additions & 0 deletions bin/propolis-standalone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ cpus = 4
bootrom = "/path/to/bootrom/OVMF_CODE.fd"
memory = 1024

# Exit propolis-standalone process with <code> if instance halts (default: 0)
# exit_on_halt = <code>

# Exit propolis-standalone process with <code> if instance reboots (default: unset)
# exit_on_reboot = <code>

[block_dev.alpine_iso]
type = "file"
path = "/path/to/alpine-extended-3.12.0-x86_64.iso"
Expand Down
27 changes: 22 additions & 5 deletions bin/propolis-standalone/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::VecDeque;
use std::fs::File;
use std::io::{Error, ErrorKind, Result};
use std::path::Path;
use std::process::ExitCode;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Condvar, Mutex, MutexGuard};
use std::time::{SystemTime, UNIX_EPOCH};
Expand Down Expand Up @@ -193,6 +194,7 @@ struct InstState {
instance: Option<propolis::Instance>,
state: State,
vcpu_tasks: Vec<propolis::tasks::TaskCtrl>,
exit_code: Option<u8>,
}

struct InstInner {
Expand All @@ -216,6 +218,7 @@ impl Instance {
instance: Some(pinst),
state: State::Initialize,
vcpu_tasks: Vec::new(),
exit_code: None,
}),
boot_gen: AtomicUsize::new(0),
eq: EventQueue::new(),
Expand Down Expand Up @@ -404,8 +407,22 @@ impl Instance {
for mut vcpu_ctrl in guard.vcpu_tasks.drain(..) {
vcpu_ctrl.exit();
}
if guard.exit_code.is_none() {
guard.exit_code = Some(inner.config.main.exit_on_halt);
}
}
State::Reset => {
if let (None, Some(code)) =
(guard.exit_code, inner.config.main.exit_on_reboot)
{
// Emit the configured exit-on-reboot code if one is
// configured an no existing code would already
// supersede it.
guard.exit_code = Some(code);
guard.state = State::Halt;
cur_ev = Some(InstEvent::ReqHalt);
continue;
}
let inst = guard.instance.as_ref().unwrap().lock();
Self::device_state_transition(State::Reset, &inst, false);
inst.machine().reinitialize().unwrap();
Expand All @@ -432,13 +449,14 @@ impl Instance {
}
}

fn wait_destroyed(&self) {
fn wait_destroyed(&self) -> ExitCode {
let guard = self.0.state.lock().unwrap();
let _guard = self
let mut guard = self
.0
.cv
.wait_while(guard, |g| !matches!(g.state, State::Destroy))
.unwrap();
ExitCode::from(guard.exit_code.take().unwrap_or(0))
}

fn vcpu_loop(
Expand Down Expand Up @@ -997,7 +1015,7 @@ struct Args {
restore: bool,
}

fn main() -> anyhow::Result<()> {
fn main() -> anyhow::Result<ExitCode> {
let Args { target, snapshot, restore } = Args::parse();

// Ensure proper setup of USDT probes
Expand Down Expand Up @@ -1058,6 +1076,5 @@ fn main() -> anyhow::Result<()> {
);

// wait for instance to be destroyed
inst.wait_destroyed();
Ok(())
Ok(inst.wait_destroyed())
}
10 changes: 10 additions & 0 deletions crates/propolis-standalone-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ pub struct Main {
pub memory: usize,
pub use_reservoir: Option<bool>,
pub cpuid_profile: Option<String>,
/// Process exitcode to emit if/when instance halts
///
/// Default: 0
#[serde(default)]
pub exit_on_halt: u8,
/// Process exitcode to emit if/when instance reboots
///
/// Default: None, does not exit on reboot
#[serde(default)]
pub exit_on_reboot: Option<u8>,
}

/// A hard-coded device, either enabled by default or accessible locally
Expand Down

0 comments on commit ba4839f

Please sign in to comment.