Skip to content

Commit

Permalink
python: PyO3 0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianfreyer committed Dec 28, 2018
1 parent 8f6a252 commit b76a456
Show file tree
Hide file tree
Showing 3 changed files with 356 additions and 29 deletions.
2 changes: 1 addition & 1 deletion bindings/python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ rctl = "^0"
path = "../../"

[dependencies.pyo3]
version = "0.2"
version = "0.5"
features = ["extension-module"]
63 changes: 35 additions & 28 deletions bindings/python/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
#![feature(proc_macro, proc_macro_path_invoc, specialization, const_fn)]
#![feature(specialization, const_fn)]
extern crate jail;
extern crate pyo3;
extern crate rctl;

use std::collections::HashMap;

use pyo3::prelude::*;
use pyo3::py::{class, methods, modinit};
use pyo3::types::{PyDict, PyInt, PyString};
use pyo3::PyObjectWithToken;
use pyo3::{exceptions, PyDowncastError};

use jail as native;

#[class]
#[pyclass]
struct JailError {
inner: native::JailError,
token: PyToken,
}

#[methods]
#[pymethods]
impl JailError {
fn __repr__(&self) -> PyResult<String> {
Ok(format!("{}", self.inner))
}
}

#[class]
#[pyclass]
struct RunningJail {
inner: native::RunningJail,
// As Python keeps its own reference counter, and we can't be sure that
Expand All @@ -33,7 +35,7 @@ struct RunningJail {
token: PyToken,
}

#[methods]
#[pymethods]
impl RunningJail {
#[new]
fn __new__(obj: &PyRawObject, jid: i32) -> PyResult<()> {
Expand All @@ -60,7 +62,7 @@ impl RunningJail {
Ok(self
.inner
.ips()
.map_err(|_| exc::SystemError::new("Could not get IP Addresses"))?
.map_err(|_| exceptions::SystemError::py_err("Could not get IP Addresses"))?
.iter()
.map(|addr| format!("{}", addr))
.collect())
Expand All @@ -73,7 +75,7 @@ impl RunningJail {
Ok(self
.inner
.params()
.map_err(|_| exc::SystemError::new("Could not get parameters"))?
.map_err(|_| exceptions::SystemError::py_err("Could not get parameters"))?
.iter()
.filter_map(|(key, value)| {
let object = match value {
Expand Down Expand Up @@ -105,7 +107,7 @@ impl RunningJail {
/// resource limits, etc.
fn stop(&mut self) -> PyResult<Py<StoppedJail>> {
if self.dead {
return Err(exc::ValueError::new(
return Err(exceptions::ValueError::py_err(
"The RunningJail instance is no longer live",
));
}
Expand All @@ -114,23 +116,23 @@ impl RunningJail {
.inner
.clone()
.stop()
.map_err(|_| exc::SystemError::new("Jail stop failed"))?;
.map_err(|_| exceptions::SystemError::py_err("Jail stop failed"))?;
self.dead = true;
self.py().init(|token| StoppedJail { inner, token })
}

/// Kill the Jail.
fn kill(&mut self) -> PyResult<()> {
if self.dead {
return Err(exc::ValueError::new(
return Err(exceptions::ValueError::py_err(
"The RunningJail instance is no longer live",
));
}

self.inner
.clone()
.kill()
.map_err(|_| exc::SystemError::new("Jail stop failed"))?;
.map_err(|_| exceptions::SystemError::py_err("Jail stop failed"))?;
self.dead = true;
Ok(())
}
Expand All @@ -139,30 +141,33 @@ impl RunningJail {
#[getter]
fn get_racct_usage(&self) -> PyResult<HashMap<String, usize>> {
if self.dead {
return Err(exc::ValueError::new(
return Err(exceptions::ValueError::py_err(
"The RunningJail instance is no longer live",
));
}

let usage = self.inner.racct_statistics();
let usage_map = usage.map_err(|e| match e {
native::JailError::RctlError(rctl::Error::InvalidKernelState(s)) => match s {
rctl::State::Disabled => exc::SystemError::new(
rctl::State::Disabled => exceptions::SystemError::py_err(
"Resource accounting is disabled. To enable resource \
accounting, set the `kern.racct.enable` tunable to 1.",
),
rctl::State::NotPresent => exc::SystemError::new(
rctl::State::NotPresent => exceptions::SystemError::py_err(
"Resource accounting is not enabled in the kernel. \
This feature requires the kernel to be compiled with \
`OPTION RACCT` set. Current GENERIC kernels should \
have this option set.",
),
rctl::State::Enabled => exc::SystemError::new(
rctl::State::Enabled => exceptions::SystemError::py_err(
"rctl::Error::InvalidKernelState returned but state \
is enabled. This really shouldn't happen.",
),
rctl::State::Jailed => exceptions::SystemError::py_err(
"Resource accounting isn't available in a jail.",
),
},
_ => exc::SystemError::new("Could not get RACCT accounting information"),
_ => exceptions::SystemError::py_err("Could not get RACCT accounting information"),
})?;

Ok(usage_map
Expand All @@ -172,17 +177,19 @@ impl RunningJail {
}

fn attach(&self) -> PyResult<()> {
self.attach()
.map_err(|_| exc::SystemError::new("jail_attach failed"))
self.inner
.attach()
.map_err(|_| exceptions::SystemError::py_err("jail_attach failed"))
}

fn defer_cleanup(&self) -> PyResult<()> {
self.defer_cleanup()
.map_err(|_| exc::SystemError::new("Could not clear persist flag"))
self.inner
.defer_cleanup()
.map_err(|_| exceptions::SystemError::py_err("Could not clear persist flag"))
}
}

#[class]
#[pyclass]
struct StoppedJail {
inner: native::StoppedJail,
token: PyToken,
Expand All @@ -194,7 +201,7 @@ fn parameter_hashmap(dict: &PyDict) -> PyResult<HashMap<String, native::param::V
.map(|(key, value)| {
let key: PyResult<&PyString> = key
.try_into()
.map_err(|_| exc::TypeError::new("Parameter key must be a string"));
.map_err(|_| exceptions::TypeError::py_err("Parameter key must be a string"));
let key: PyResult<String> = key.and_then(|k| k.extract());

let py_string: Result<&PyString, PyDowncastError> = value.try_into();
Expand All @@ -205,7 +212,7 @@ fn parameter_hashmap(dict: &PyDict) -> PyResult<HashMap<String, native::param::V
} else if let Ok(num) = py_num {
num.extract().map(native::param::Value::Int)
} else {
Err(exc::TypeError::new(
Err(exceptions::TypeError::py_err(
"Only string and integer parameters are supported",
))
};
Expand All @@ -226,7 +233,7 @@ fn parameter_hashmap(dict: &PyDict) -> PyResult<HashMap<String, native::param::V
Ok(converted.into_iter().map(Result::unwrap).collect())
}

#[methods]
#[pymethods]
impl StoppedJail {
#[new]
fn __new__(
Expand Down Expand Up @@ -292,7 +299,7 @@ impl StoppedJail {
.inner
.clone()
.start()
.map_err(|_| exc::SystemError::new("Jail start failed"))?;
.map_err(|_| exceptions::SystemError::py_err("Jail start failed"))?;
self.py().init(|token| RunningJail {
inner,
dead: false,
Expand All @@ -301,8 +308,8 @@ impl StoppedJail {
}
}

#[modinit(_jail)]
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
#[pymodinit(_jail)]
fn jail_modinit(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<RunningJail>()?;
m.add_class::<StoppedJail>()?;
m.add_class::<JailError>()?;
Expand Down
Loading

0 comments on commit b76a456

Please sign in to comment.