Skip to content

Commit 468fd04

Browse files
committed
init: Use host $PATH in init.sh
Currently all kernel target commands use host environment variables. However, init.sh uses a hard coded $PATH. This gap is most noticible on nix/nixos systems b/c nothing exists in the hard coded path. So kernel target guests are unable to find qemu-ga. Plug this gap by templatizing init.sh and filling in with host $PATH. Note init.sh.template now needs to be careful about escaping `{`, as that's reserved by TinyTemplate now. This closes #79.
1 parent 5c08c6f commit 468fd04

File tree

4 files changed

+44
-18
lines changed

4 files changed

+44
-18
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ clap = { version = "4.0.26", features = ["derive", "string"] }
1515
console = "0.15.5"
1616
env_logger = "0.10.0"
1717
itertools = "0.10.5"
18-
lazy_static = "1.4.0"
1918
log = "0.4.17"
2019
qapi = { version = "0.14.0", features = ["qmp", "qga"] }
2120
rand = "0.8.5"
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
set -eu
1717

18-
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
18+
export PATH={ path }
1919

20-
log() {
20+
log() \{
2121
if [[ -e /dev/kmsg ]]; then
2222
echo "<6>vmtest: $*" >/dev/kmsg
2323
else
@@ -83,14 +83,14 @@ vport=
8383
for dir in /sys/class/virtio-ports/*; do
8484
if [[ "$(cat "$dir/name")" == "org.qemu.guest_agent.0" ]]; then
8585
vport_name=$(basename "$dir")
86-
vport="/dev/${vport_name}"
86+
vport="/dev/$\{vport_name}"
8787
fi
8888
done
8989
if [[ -z "$vport" ]]; then
9090
log "Failed to locate qemu-guest-agent virtio-port"
9191
exit 1
9292
fi
93-
log "Located qemu-guest-agent virtio port: ${vport}"
93+
log "Located qemu-guest-agent virtio port: $\{vport}"
9494

9595
# Send QGA logs out via kmsg if possible
9696
qga_logs=

src/qemu.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::output::Output;
2929
use crate::qga::QgaWrapper;
3030
use crate::{Mount, Target, VMConfig};
3131

32-
const INIT_SCRIPT: &str = include_str!("init/init.sh");
32+
const INIT_TEMPLATE: &str = include_str!("init/init.sh.template");
3333
const COMMAND_TEMPLATE: &str = include_str!("init/command.template");
3434
// Needs to be `/dev/root` for kernel to "find" the 9pfs as rootfs
3535
const ROOTFS_9P_FS_MOUNT_TAG: &str = "/dev/root";
@@ -87,8 +87,32 @@ struct CommandContext {
8787
command_output_port_name: String,
8888
}
8989

90+
/// Used by templating engine to render init.sh
91+
#[derive(Serialize)]
92+
struct InitContext {
93+
/// $PATH the guest should use
94+
path: String,
95+
}
96+
9097
const QEMU_DEFAULT_ARGS: &[&str] = &["-nodefaults", "-display", "none"];
9198

99+
/// Gets instance of template engine
100+
///
101+
/// Unfortunately cannot be done as a lazy_static or OnceCell b/c TinyTemplate
102+
/// internally uses some !Sync stuff.
103+
fn get_templates() -> TinyTemplate<'static> {
104+
// Disable HTML escaping (b/c we're not dealing with HTML)
105+
let mut tt = TinyTemplate::new();
106+
tt.set_default_formatter(&format_unescaped);
107+
108+
// We are ok panicing here b/c there should never be a runtime
109+
// error compiling the template. Any errors are trivial bugs.
110+
tt.add_template("cmd", COMMAND_TEMPLATE).unwrap();
111+
tt.add_template("init", INIT_TEMPLATE).unwrap();
112+
113+
tt
114+
}
115+
92116
/// Whether or not the host supports KVM
93117
fn host_supports_kvm(arch: &str) -> bool {
94118
arch == ARCH && Path::new("/dev/kvm").exists()
@@ -134,6 +158,18 @@ fn guest_init_path(guest_temp_dir: PathBuf, host_init_path: PathBuf) -> Result<P
134158
Ok(guest_init_path)
135159
}
136160

161+
/// Generates init.sh that guest will use as pid 1
162+
fn init_script() -> String {
163+
let path = match env::var("PATH") {
164+
Ok(p) => p,
165+
Err(_) => "/bin:/sbin:/usr/bin:/usr/sbin".to_string(),
166+
};
167+
168+
// Ignore errors cuz only trivial bugs are possible
169+
let context = InitContext { path };
170+
get_templates().render("init", &context).unwrap()
171+
}
172+
137173
// Given a rootfs, generate a tempfile with the init script inside.
138174
// Returns the tempfile and the path to the init script inside the guest.
139175
// When rootfs is /, both the tempfile filename and guest init path are equal.
@@ -152,7 +188,7 @@ fn gen_init(rootfs: &Path) -> Result<(NamedTempFile, PathBuf)> {
152188
.context("Failed to create tempfile")?;
153189

154190
host_init
155-
.write_all(INIT_SCRIPT.as_bytes())
191+
.write_all(init_script().as_bytes())
156192
.context("Failed to write init to tmpfs")?;
157193

158194
// Set write bits on script
@@ -743,14 +779,6 @@ impl Qemu {
743779

744780
/// Generates a bash script that runs `self.command`
745781
fn command_script(&self) -> String {
746-
// Disable HTML escaping (b/c we're not dealing with HTML)
747-
let mut tt = TinyTemplate::new();
748-
tt.set_default_formatter(&format_unescaped);
749-
750-
// We are ok panicing here b/c there should never be a runtime
751-
// error compiling the template. Any errors are trivial bugs.
752-
tt.add_template("cmd", COMMAND_TEMPLATE).unwrap();
753-
754782
let context = CommandContext {
755783
// Only `cd` for kernel targets that share userspace with host
756784
should_cd: !self.image && self.rootfs == Target::default_rootfs(),
@@ -759,8 +787,8 @@ impl Qemu {
759787
command_output_port_name: COMMAND_OUTPUT_PORT_NAME.into(),
760788
};
761789

762-
// Same as above, ignore errors cuz only trivial bugs are possible
763-
tt.render("cmd", &context).unwrap()
790+
// Ignore errors cuz only trivial bugs are possible
791+
get_templates().render("cmd", &context).unwrap()
764792
}
765793

766794
/// Run this target's command inside the VM

0 commit comments

Comments
 (0)