mirror of
https://github.com/vhaudiquet/ecrou.git
synced 2026-11-12 22:22:44 +00:00
fix(guest): diagnose and fail on mount errors in the init
A virtiofs mount that failed (bad fsconfig, missing share) was swallowed: the payload ran without its data and the only symptom was a confusing failure downstream. The init now names the share tag and target on the console and exits 126 - the same contract as an unreachable workdir - instead of booting a run that cannot do its job.
This commit is contained in:
1 parent
f3cbf16180
commit
6bece1098b
1 file changed
+18
-4
@@ -65,7 +65,9 @@ pub fn sh_quote(s: &str) -> String {
|
||||
|
||||
/// Render the guest init. The payload runs as a child (never `exec`):
|
||||
/// the init must outlive it to write the exit code and power the
|
||||
/// machine off.
|
||||
/// machine off. A share that fails to mount is named on the console
|
||||
/// and ends the init with exit 126: a run without its shares is not
|
||||
/// the run that was asked for.
|
||||
pub fn init_script(
|
||||
shares: &[GuestShare],
|
||||
payload: &[String],
|
||||
@@ -81,11 +83,11 @@ pub fn init_script(
|
||||
set -u\n\n\
|
||||
mount_share() {\n\
|
||||
\x20 tag=\"$1\"; target=\"$2\"; ro=\"$3\"\n\
|
||||
\x20 mkdir -p \"$target\"\n\
|
||||
\x20 mkdir -p \"$target\" || { echo \"ecrou: cannot create share target '$target'\" >&2; exit 126; }\n\
|
||||
\x20 if [ \"$ro\" = \"ro\" ]; then\n\
|
||||
\x20 mount -t virtiofs -o ro \"$tag\" \"$target\"\n\
|
||||
\x20 mount -t virtiofs -o ro \"$tag\" \"$target\" || { echo \"ecrou: failed to mount share '$tag' at '$target' (read-only)\" >&2; exit 126; }\n\
|
||||
\x20 else\n\
|
||||
\x20 mount -t virtiofs \"$tag\" \"$target\"\n\
|
||||
\x20 mount -t virtiofs \"$tag\" \"$target\" || { echo \"ecrou: failed to mount share '$tag' at '$target'\" >&2; exit 126; }\n\
|
||||
\x20 fi\n\
|
||||
}\n\n",
|
||||
);
|
||||
@@ -177,6 +179,18 @@ mod tests {
|
||||
assert_eq!(sh_quote("new\nline"), "'new\nline'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_failed_share_mount_is_diagnosed_and_fatal() {
|
||||
let script = init_script(&[], &["true".into()], "/", "m", GuestStdio::Console, None);
|
||||
assert!(
|
||||
script.contains("failed to mount share '$tag' at '$target'"),
|
||||
"{script}"
|
||||
);
|
||||
assert!(script.contains("cannot create share target"), "{script}");
|
||||
// The diagnosis ends the init: nothing runs without its shares.
|
||||
assert!(script.contains(">&2; exit 126; }"), "{script}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mounts_each_share_with_its_ro_flag() {
|
||||
let shares = vec![
|
||||
|
||||
Reference in new issue
Block a user