From c9f61ec72f196ed94d05835f1635c697eb0c73a8 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Mon, 8 Jan 2024 23:23:26 -0800 Subject: [PATCH] introduce xencl for high-level interaction with xen --- Cargo.toml | 3 +- xencl/Cargo.toml | 15 +++++++++ xencl/examples/simple.rs | 9 ++++++ xencl/src/lib.rs | 68 +++++++++++++++++++++++++++++++++++++++ xenstore/examples/list.rs | 2 +- xenstore/src/client.rs | 13 ++++++-- 6 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 xencl/Cargo.toml create mode 100644 xencl/examples/simple.rs create mode 100644 xencl/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index a846165..c9dac42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "xenstore", "xenevtchn", - "xencall" + "xencall", + "xencl" ] resolver = "2" diff --git a/xencl/Cargo.toml b/xencl/Cargo.toml new file mode 100644 index 0000000..c058cf2 --- /dev/null +++ b/xencl/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "xencl" +version = "0.0.1" +edition = "2021" +resolver = "2" + +[dependencies.xenstore] +path = "../xenstore" + +[lib] +path = "src/lib.rs" + +[[example]] +name = "xencl-simple" +path = "examples/simple.rs" diff --git a/xencl/examples/simple.rs b/xencl/examples/simple.rs new file mode 100644 index 0000000..ba18160 --- /dev/null +++ b/xencl/examples/simple.rs @@ -0,0 +1,9 @@ +use std::collections::HashMap; +use xencl::{XenClient, XenClientError}; + +fn main() -> Result<(), XenClientError> { + let mut client = XenClient::open()?; + let entries: HashMap = HashMap::new(); + client.create(2, entries)?; + Ok(()) +} diff --git a/xencl/src/lib.rs b/xencl/src/lib.rs new file mode 100644 index 0000000..838e3d9 --- /dev/null +++ b/xencl/src/lib.rs @@ -0,0 +1,68 @@ +use std::collections::HashMap; +use std::error::Error; +use std::fmt::{Display, Formatter}; +use xenstore::bus::XsdBusError; +use xenstore::client::{XsdClient, XsdInterface}; + +pub struct XenClient { + store: XsdClient, +} + +#[derive(Debug)] +pub struct XenClientError { + message: String, +} + +impl XenClientError { + pub fn new(msg: &str) -> XenClientError { + XenClientError { + message: msg.to_string(), + } + } +} + +impl Display for XenClientError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.message) + } +} + +impl Error for XenClientError { + fn description(&self) -> &str { + &self.message + } +} + +impl From for XenClientError { + fn from(value: std::io::Error) -> Self { + XenClientError::new(value.to_string().as_str()) + } +} + +impl From for XenClientError { + fn from(value: XsdBusError) -> Self { + XenClientError::new(value.to_string().as_str()) + } +} + +impl XenClient { + pub fn open() -> Result { + let store = XsdClient::open()?; + Ok(XenClient { store }) + } + + pub fn create( + &mut self, + domid: u32, + entries: HashMap, + ) -> Result<(), XenClientError> { + let domain = self.store.get_domain_path(domid)?; + let mut tx = self.store.transaction()?; + for (key, value) in entries { + let path = format!("{}/{}", domain, key); + tx.write(path.as_str(), value.into_bytes())?; + } + tx.commit()?; + Ok(()) + } +} diff --git a/xenstore/examples/list.rs b/xenstore/examples/list.rs index 9843427..9827d03 100644 --- a/xenstore/examples/list.rs +++ b/xenstore/examples/list.rs @@ -29,7 +29,7 @@ fn list_recursive(client: &mut XsdClient, level: usize, path: &str) -> Result<() } fn main() -> Result<(), XsdBusError> { - let mut client = XsdClient::new()?; + let mut client = XsdClient::open()?; list_recursive(&mut client, 0, "/")?; Ok(()) } diff --git a/xenstore/src/client.rs b/xenstore/src/client.rs index f31577b..6a4dd28 100644 --- a/xenstore/src/client.rs +++ b/xenstore/src/client.rs @@ -1,7 +1,7 @@ use crate::bus::{XsdBusError, XsdSocket}; use crate::sys::{ - XSD_DIRECTORY, XSD_MKDIR, XSD_READ, XSD_RM, XSD_TRANSACTION_END, XSD_TRANSACTION_START, - XSD_WRITE, + XSD_DIRECTORY, XSD_GET_DOMAIN_PATH, XSD_MKDIR, XSD_READ, XSD_RM, XSD_TRANSACTION_END, + XSD_TRANSACTION_START, XSD_WRITE, }; use std::ffi::CString; @@ -18,7 +18,7 @@ pub trait XsdInterface { } impl XsdClient { - pub fn new() -> Result { + pub fn open() -> Result { let socket = XsdSocket::dial()?; Ok(XsdClient { socket }) } @@ -55,6 +55,13 @@ impl XsdClient { let tx = response.parse_string()?.parse::()?; Ok(XsdTransaction { client: self, tx }) } + + pub fn get_domain_path(&mut self, domid: u32) -> Result { + let response = + self.socket + .send_single(0, XSD_GET_DOMAIN_PATH, domid.to_string().as_str())?; + response.parse_string() + } } pub struct XsdTransaction<'a> {