qcow2 SAL + rhai script to test functionality
This commit is contained in:
139
packages/system/virt/src/rhai/qcow2.rs
Normal file
139
packages/system/virt/src/rhai/qcow2.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
use crate::qcow2;
|
||||
use crate::qcow2::{BuildBaseResult, Qcow2Error, Qcow2Snapshot};
|
||||
use rhai::{Array, Dynamic, Engine, EvalAltResult, Map};
|
||||
use serde_json::Value;
|
||||
|
||||
// Convert Qcow2Error to Rhai error
|
||||
fn qcow2_error_to_rhai<T>(result: Result<T, Qcow2Error>) -> Result<T, Box<EvalAltResult>> {
|
||||
result.map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("qcow2 error: {}", e).into(),
|
||||
rhai::Position::NONE,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
// Convert serde_json::Value to Rhai Dynamic recursively (maps, arrays, scalars)
|
||||
fn json_to_dynamic(v: &Value) -> Dynamic {
|
||||
match v {
|
||||
Value::Null => Dynamic::UNIT,
|
||||
Value::Bool(b) => (*b).into(),
|
||||
Value::Number(n) => {
|
||||
if let Some(i) = n.as_i64() {
|
||||
i.into()
|
||||
} else {
|
||||
// Avoid float dependency differences; fall back to string
|
||||
n.to_string().into()
|
||||
}
|
||||
}
|
||||
Value::String(s) => s.clone().into(),
|
||||
Value::Array(arr) => {
|
||||
let mut a = Array::new();
|
||||
for item in arr {
|
||||
a.push(json_to_dynamic(item));
|
||||
}
|
||||
a.into()
|
||||
}
|
||||
Value::Object(obj) => {
|
||||
let mut m = Map::new();
|
||||
for (k, val) in obj {
|
||||
m.insert(k.into(), json_to_dynamic(val));
|
||||
}
|
||||
m.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wrappers exposed to Rhai
|
||||
|
||||
pub fn qcow2_create(path: &str, size_gb: i64) -> Result<String, Box<EvalAltResult>> {
|
||||
qcow2_error_to_rhai(qcow2::create(path, size_gb))
|
||||
}
|
||||
|
||||
pub fn qcow2_info(path: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let v = qcow2_error_to_rhai(qcow2::info(path))?;
|
||||
Ok(json_to_dynamic(&v))
|
||||
}
|
||||
|
||||
pub fn qcow2_snapshot_create(path: &str, name: &str) -> Result<(), Box<EvalAltResult>> {
|
||||
qcow2_error_to_rhai(qcow2::snapshot_create(path, name))
|
||||
}
|
||||
|
||||
pub fn qcow2_snapshot_delete(path: &str, name: &str) -> Result<(), Box<EvalAltResult>> {
|
||||
qcow2_error_to_rhai(qcow2::snapshot_delete(path, name))
|
||||
}
|
||||
|
||||
pub fn qcow2_snapshot_list(path: &str) -> Result<Array, Box<EvalAltResult>> {
|
||||
let snaps = qcow2_error_to_rhai(qcow2::snapshot_list(path))?;
|
||||
let mut arr = Array::new();
|
||||
for s in snaps {
|
||||
arr.push(snapshot_to_map(&s).into());
|
||||
}
|
||||
Ok(arr)
|
||||
}
|
||||
|
||||
fn snapshot_to_map(s: &Qcow2Snapshot) -> Map {
|
||||
let mut m = Map::new();
|
||||
if let Some(id) = &s.id {
|
||||
m.insert("id".into(), id.clone().into());
|
||||
} else {
|
||||
m.insert("id".into(), Dynamic::UNIT);
|
||||
}
|
||||
if let Some(name) = &s.name {
|
||||
m.insert("name".into(), name.clone().into());
|
||||
} else {
|
||||
m.insert("name".into(), Dynamic::UNIT);
|
||||
}
|
||||
if let Some(v) = s.vm_state_size {
|
||||
m.insert("vm_state_size".into(), v.into());
|
||||
} else {
|
||||
m.insert("vm_state_size".into(), Dynamic::UNIT);
|
||||
}
|
||||
if let Some(v) = s.date_sec {
|
||||
m.insert("date_sec".into(), v.into());
|
||||
} else {
|
||||
m.insert("date_sec".into(), Dynamic::UNIT);
|
||||
}
|
||||
if let Some(v) = s.date_nsec {
|
||||
m.insert("date_nsec".into(), v.into());
|
||||
} else {
|
||||
m.insert("date_nsec".into(), Dynamic::UNIT);
|
||||
}
|
||||
if let Some(v) = s.vm_clock_nsec {
|
||||
m.insert("vm_clock_nsec".into(), v.into());
|
||||
} else {
|
||||
m.insert("vm_clock_nsec".into(), Dynamic::UNIT);
|
||||
}
|
||||
m
|
||||
}
|
||||
|
||||
pub fn qcow2_build_ubuntu_24_04_base(
|
||||
dest_dir: &str,
|
||||
size_gb: i64,
|
||||
) -> Result<Map, Box<EvalAltResult>> {
|
||||
// size_gb: pass None if <=0
|
||||
let size_opt = if size_gb > 0 { Some(size_gb) } else { None };
|
||||
let r: BuildBaseResult = qcow2_error_to_rhai(qcow2::build_ubuntu_24_04_base(dest_dir, size_opt))?;
|
||||
let mut m = Map::new();
|
||||
m.insert("base_image_path".into(), r.base_image_path.into());
|
||||
m.insert("snapshot".into(), r.snapshot.into());
|
||||
m.insert("url".into(), r.url.into());
|
||||
if let Some(sz) = r.resized_to_gb {
|
||||
m.insert("resized_to_gb".into(), sz.into());
|
||||
} else {
|
||||
m.insert("resized_to_gb".into(), Dynamic::UNIT);
|
||||
}
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
// Module registration
|
||||
|
||||
pub fn register_qcow2_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
||||
engine.register_fn("qcow2_create", qcow2_create);
|
||||
engine.register_fn("qcow2_info", qcow2_info);
|
||||
engine.register_fn("qcow2_snapshot_create", qcow2_snapshot_create);
|
||||
engine.register_fn("qcow2_snapshot_delete", qcow2_snapshot_delete);
|
||||
engine.register_fn("qcow2_snapshot_list", qcow2_snapshot_list);
|
||||
engine.register_fn("qcow2_build_ubuntu_24_04_base", qcow2_build_ubuntu_24_04_base);
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user