mirror of
https://codeberg.org/Toasterson/solstice-ci.git
synced 2026-04-10 13:20:41 +00:00
Enhance hypervisor image handling with dynamic format detection and raw conversion
This commit improves the hypervisor by: - Adding support for detecting base image formats using `qemu-img info`. - Dynamically setting the base image format for overlay creation. - Automatically converting non-raw images to raw format for bhyve compatibility. - Updating `Cargo.toml` to include `serde_json` for JSON parsing. - Modifying default working directory logic for `ZonesHypervisor`.
This commit is contained in:
parent
f3831dac4a
commit
7918db3468
3 changed files with 82 additions and 5 deletions
|
|
@ -15,6 +15,7 @@ thiserror = "1"
|
|||
tracing = "0.1"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "fs", "io-util"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_yaml = "0.9"
|
||||
config = { version = "0.14", default-features = false, features = ["yaml"] }
|
||||
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls-native-roots", "http2", "gzip", "brotli", "zstd"] }
|
||||
|
|
|
|||
|
|
@ -222,14 +222,37 @@ impl Hypervisor for LibvirtHypervisor {
|
|||
let base = spec.image_path.clone();
|
||||
let overlay = overlay.clone();
|
||||
move || -> miette::Result<()> {
|
||||
// Detect base image format to set -F accordingly (raw or qcow2)
|
||||
let base_fmt_out = std::process::Command::new("qemu-img")
|
||||
.args(["info", "--output=json"])
|
||||
.arg(&base)
|
||||
.output()
|
||||
.map_err(|e| miette::miette!("qemu-img not found or failed: {e}"))?;
|
||||
if !base_fmt_out.status.success() {
|
||||
return Err(miette::miette!(
|
||||
"qemu-img info failed: {}",
|
||||
String::from_utf8_lossy(&base_fmt_out.stderr)
|
||||
));
|
||||
}
|
||||
let base_fmt: String = {
|
||||
let v: serde_json::Value = serde_json::from_slice(&base_fmt_out.stdout)
|
||||
.map_err(|e| miette::miette!("parse qemu-img info json failed: {e}"))?;
|
||||
v.get("format")
|
||||
.and_then(|f| f.as_str())
|
||||
.unwrap_or("raw")
|
||||
.to_string()
|
||||
};
|
||||
|
||||
let out = Command::new("qemu-img")
|
||||
.args(["create","-f","qcow2","-F","qcow2","-b"])
|
||||
.args(["create","-f","qcow2","-F"])
|
||||
.arg(&base_fmt)
|
||||
.args(["-b"])
|
||||
.arg(&base)
|
||||
.arg(&overlay)
|
||||
.arg(&size_arg)
|
||||
.output()
|
||||
.map_err(|e| miette::miette!("qemu-img not found or failed: {e}"))?;
|
||||
if !out.status.success() { return Err(miette::miette!("qemu-img failed: {}", String::from_utf8_lossy(&out.stderr))); }
|
||||
if !out.status.success() { return Err(miette::miette!("qemu-img create failed: {}", String::from_utf8_lossy(&out.stderr))); }
|
||||
Ok(())
|
||||
}
|
||||
}).await.into_diagnostic()??;
|
||||
|
|
@ -361,9 +384,62 @@ pub struct ZonesHypervisor;
|
|||
#[async_trait]
|
||||
impl Hypervisor for ZonesHypervisor {
|
||||
async fn prepare(&self, spec: &VmSpec, ctx: &JobContext) -> Result<VmHandle> {
|
||||
warn!(label = %spec.label, "zones hypervisor not yet implemented; returning noop-like handle");
|
||||
use std::process::Command;
|
||||
let id = format!("zone-{}", ctx.request_id);
|
||||
Ok(VmHandle { id, backend: BackendTag::Zones, work_dir: std::env::temp_dir().join("solstice-zones"), overlay_path: None, seed_iso_path: None })
|
||||
// Create working directory under /var/lib/solstice-ci if possible
|
||||
let work_dir = {
|
||||
let base = std::path::Path::new("/var/lib/solstice-ci");
|
||||
let dir = if base.exists() && base.is_dir() && std::fs::metadata(base).is_ok() {
|
||||
base.join(&id)
|
||||
} else {
|
||||
std::env::temp_dir().join("solstice-zones").join(&id)
|
||||
};
|
||||
let _ = std::fs::create_dir_all(&dir);
|
||||
#[cfg(unix)]
|
||||
let _ = std::fs::set_permissions(&dir, std::fs::Permissions::from_mode(0o700));
|
||||
dir
|
||||
};
|
||||
|
||||
// Detect base image format
|
||||
let base = spec.image_path.clone();
|
||||
let base_fmt = tokio::task::spawn_blocking(move || -> miette::Result<String> {
|
||||
let out = Command::new("qemu-img")
|
||||
.args(["info", "--output=json"]).arg(&base)
|
||||
.output()
|
||||
.map_err(|e| miette::miette!("qemu-img not found or failed: {e}"))?;
|
||||
if !out.status.success() {
|
||||
return Err(miette::miette!("qemu-img info failed: {}", String::from_utf8_lossy(&out.stderr)));
|
||||
}
|
||||
let v: serde_json::Value = serde_json::from_slice(&out.stdout)
|
||||
.map_err(|e| miette::miette!("parse qemu-img info json failed: {e}"))?;
|
||||
Ok(v.get("format").and_then(|f| f.as_str()).unwrap_or("raw").to_string())
|
||||
}).await.into_diagnostic()??;
|
||||
|
||||
// Ensure raw image for bhyve: convert if needed
|
||||
let raw_path = if base_fmt != "raw" {
|
||||
let out_path = work_dir.join("disk.raw");
|
||||
let src = spec.image_path.clone();
|
||||
let dst = out_path.clone();
|
||||
tokio::task::spawn_blocking(move || -> miette::Result<()> {
|
||||
let out = Command::new("qemu-img")
|
||||
.args(["convert", "-O", "raw"])
|
||||
.arg(&src)
|
||||
.arg(&dst)
|
||||
.output()
|
||||
.map_err(|e| miette::miette!("qemu-img convert failed to start: {e}"))?;
|
||||
if !out.status.success() {
|
||||
return Err(miette::miette!("qemu-img convert failed: {}", String::from_utf8_lossy(&out.stderr)));
|
||||
}
|
||||
Ok(())
|
||||
}).await.into_diagnostic()??;
|
||||
info!(label = %spec.label, src = ?spec.image_path, out = ?out_path, "converted image to raw for bhyve");
|
||||
out_path
|
||||
} else {
|
||||
spec.image_path.clone()
|
||||
};
|
||||
|
||||
// Seed ISO creation left to future; for now, return handle with path in overlay_path
|
||||
Ok(VmHandle { id, backend: BackendTag::Zones, work_dir, overlay_path: Some(raw_path), seed_iso_path: None })
|
||||
}
|
||||
async fn start(&self, _vm: &VmHandle) -> Result<()> { Ok(()) }
|
||||
async fn stop(&self, _vm: &VmHandle, _t: Duration) -> Result<()> { Ok(()) }
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ images:
|
|||
# Example Ubuntu image for libvirt/KVM on Linux hosts (commented by default)
|
||||
ubuntu-22.04:
|
||||
source: https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
|
||||
local_path: /var/lib/libvirt/images/ubuntu-22.04-base.qcow2
|
||||
local_path: /var/lib/solstice/images/ubuntu-22.04-base.qcow2
|
||||
decompress: none
|
||||
nocloud: true
|
||||
defaults:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue