#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn dir_size(p: &std::path::Path) -> u64 {
let mut total = 0;
if let Ok(rd) = std::fs::read_dir(p) {
for e in rd.flatten() {
let m = match e.metadata() {
Ok(m) => m,
Err(_) => continue,
};
if m.is_dir() {
total += dir_size(&e.path());
} else {
total += m.len();
}
}
}
total
}
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn main() {
use std::time::{Duration, Instant};
use supermachine::{builder, Image, VmConfig};
let mib = 64u64; let dockerfile = format!(
"FROM alpine\n\
RUN mkdir -p /data && dd if=/dev/urandom of=/data/blob bs=1M count={mib} 2>/dev/null \
&& sha256sum /data/blob | cut -d' ' -f1 > /data/blob.sha \
&& echo committed-density-ok > /data/marker\n"
);
let df = builder::parse(&dockerfile).expect("parse");
let ctx = std::env::temp_dir().join("sm-density-ctx");
let _ = std::fs::create_dir_all(&ctx);
let build_dest = std::env::temp_dir().join("sm-density-build");
let _ = std::fs::remove_dir_all(&build_dest);
let commit_dir = std::env::temp_dir().join("sm-density-commit");
let _ = std::fs::remove_dir_all(&commit_dir);
let base = Image::from_oci("alpine").expect("from_oci");
eprintln!("=== build (snapshot-layer) ===");
let t0 = Instant::now();
let out = builder::build_linear(&df, &base, &ctx, &build_dest).expect("build_linear");
eprintln!("build took {:?}", t0.elapsed());
let snap_bytes = dir_size(&build_dest);
let restore_snap_bytes = std::fs::metadata(build_dest.join("restore.snap"))
.map(|m| m.len())
.unwrap_or(0);
eprintln!("=== verify snapshot-layer image has the RUN output ===");
let vm = out.image.start(&VmConfig::new()).expect("start snap-layer");
std::thread::sleep(Duration::from_millis(4000));
let o = vm
.exec_builder()
.argv([
"/bin/sh",
"-c",
"cat /data/marker; stat -c%s /data/blob; \
if [ \"$(sha256sum /data/blob | cut -d' ' -f1)\" = \"$(cat /data/blob.sha)\" ]; \
then echo SHA-OK; else echo SHA-BAD; fi",
])
.output()
.expect("exec verify snap");
let snap_check = String::from_utf8_lossy(&o.stdout).trim_end().to_string();
eprintln!("snap-layer: {snap_check:?}");
drop(vm);
eprintln!("=== commit -> read-only squashfs -> KVM-bootable image ===");
let tc = Instant::now();
let (commit, bootable) =
builder::commit_kvm_bootable(&out.image, &commit_dir).expect("commit_kvm_bootable");
eprintln!(
"commit took {:?}; squashfs={} MiB sha={}",
tc.elapsed(),
commit.bytes / (1024 * 1024),
&commit.sha256[..16]
);
eprintln!("=== boot FRESH from committed image, verify same FS ===");
let vm2 = bootable.start(&VmConfig::new()).expect("start committed");
std::thread::sleep(Duration::from_millis(4000));
let o2 = vm2
.exec_builder()
.argv([
"/bin/sh",
"-c",
"cat /data/marker; stat -c%s /data/blob; \
if [ \"$(sha256sum /data/blob | cut -d' ' -f1)\" = \"$(cat /data/blob.sha)\" ]; \
then echo SHA-OK; else echo SHA-BAD; fi",
])
.output()
.expect("exec verify committed");
let committed_check = String::from_utf8_lossy(&o2.stdout).trim_end().to_string();
eprintln!("committed: {committed_check:?}");
drop(vm2);
let committed_squashfs_bytes = commit.bytes;
eprintln!("--- artifact sizes ---");
eprintln!(
"snapshot-layer image total (build_dest): {} MiB",
snap_bytes / (1024 * 1024)
);
eprintln!(
" of which restore.snap (full guest-RAM dump): {} MiB",
restore_snap_bytes / (1024 * 1024)
);
eprintln!(
"committed squashfs (read-only, shareable): {} MiB",
committed_squashfs_bytes / (1024 * 1024)
);
let pass = snap_check.contains("committed-density-ok")
&& snap_check.contains("SHA-OK")
&& committed_check.contains("committed-density-ok")
&& committed_check.contains("SHA-OK")
&& committed_check.contains(&(mib * 1024 * 1024).to_string());
eprintln!(
"=== COMMIT DENSITY LOOP: {} ===",
if pass { "PASS" } else { "FAIL" }
);
}
#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
fn main() {
eprintln!("kvm_commit_density is Linux/x86_64 only");
}