Skip to content

Commit

Permalink
python: pass driver type and init params
Browse files Browse the repository at this point in the history
  • Loading branch information
Wenzel committed Feb 2, 2021
1 parent 0a4efb1 commit 84949bc
Showing 1 changed file with 94 additions and 5 deletions.
99 changes: 94 additions & 5 deletions python/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use microvmi::api::Introspectable;
use microvmi::api as rapi; // rust api
use microvmi::init;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;

/// microvmi Python module declaration
Expand All @@ -9,17 +10,63 @@ fn microvmi(_py: Python, m: &PyModule) -> PyResult<()> {
env_logger::init();

m.add_class::<Microvmi>()?;
m.add_class::<DriverType>()?;
m.add_class::<DriverInitParam>()?;

Ok(())
}

// fake enum impl for driver type
#[pyclass]
struct DriverType {}

#[pymethods]
impl DriverType {
#[classattr]
const HYPERV: u32 = 0;
#[classattr]
const KVM: u32 = 1;
#[classattr]
const VIRTUALBOX: u32 = 2;
#[classattr]
const XEN: u32 = 3;
}

// this will not be exported to Python
#[derive(Debug, Copy, Clone)]
enum DriverInitParamType {
KVMiUnixSocket = 0,
}

// exposing DriverInitParam to Python is bit more complicated
// as it's an enum with associated data
// the proposed implementation is exposing static method returning an instance an
// initialized instance of DriverInitParam struct
#[pyclass]
#[derive(Clone)]
struct DriverInitParam {
pub param_type: DriverInitParamType,
pub param_data_string: String,
}

#[pymethods]
impl DriverInitParam {
#[staticmethod]
fn kvmi_unix_socket(socket: &str) -> Self {
DriverInitParam {
param_type: DriverInitParamType::KVMiUnixSocket,
param_data_string: socket.to_string(),
}
}
}

/// Main class to interact with libmicrovmi
// A class marked as unsendable will panic when accessed by another thread.
// TODO: make Introspectable trait inherit Send trait, and make the drivers implementation
// compatible
#[pyclass(unsendable)]
struct Microvmi {
_driver: Box<dyn Introspectable>,
_driver: Box<dyn rapi::Introspectable>,
}

#[pymethods]
Expand All @@ -28,8 +75,50 @@ impl Microvmi {
// enums are not available in PyO3 (yet)
/// initializes libmicrovmi from the specified domain name
#[new]
fn new(domain_name: &str) -> Self {
let _driver = init(domain_name, None, None);
Microvmi { _driver }
#[args(domain_name, driver_type = "None", init_param = "None")]
fn new(
domain_name: &str,
driver_type: Option<u32>,
init_param: Option<DriverInitParam>,
) -> PyResult<Self> {
// convert Python DriverType to rust API DriverType
let rust_driver_type: Option<rapi::DriverType> = if let Some(drv_type) = driver_type {
#[allow(clippy::match_single_binding)]
Some(match drv_type {
#[cfg(feature = "hyper-v")]
DriverType::HYPERV => Ok(rapi::DriverType::HyperV),
#[cfg(feature = "kvm")]
DriverType::KVM => Ok(rapi::DriverType::KVM),
#[cfg(feature = "virtualbox")]
DriverType::VIRTUALBOX => Ok(rapi::DriverType::VirtualBox),
#[cfg(feature = "xen")]
DriverType::XEN => Ok(rapi::DriverType::Xen),
_ => Err(PyValueError::new_err(format!(
"Invalid value for DriverType: {}",
drv_type
))),
}?)
} else {
None
};
// convert Python DriverInitParam to rust API DriverinitParam
let rust_init_param: Option<rapi::DriverInitParam> = if let Some(param) = init_param {
Some(
#[allow(unreachable_patterns)]
match param.param_type {
DriverInitParamType::KVMiUnixSocket => {
Ok(rapi::DriverInitParam::KVMiSocket(param.param_data_string))
}
_ => Err(PyValueError::new_err(format!(
"Invalid value for DriverInitParam type: {:?}",
param.param_type
))),
}?,
)
} else {
None
};
let _driver = init(domain_name, rust_driver_type, rust_init_param);
Ok(Microvmi { _driver })
}
}

0 comments on commit 84949bc

Please sign in to comment.