mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 13:11:31 +00:00
utilize async processing for console and child exit events
This commit is contained in:
@ -26,6 +26,7 @@ fn main() -> Result<()> {
|
||||
vifs: vec![],
|
||||
filesystems: vec![],
|
||||
extra_keys: vec![],
|
||||
event_channels: vec![],
|
||||
};
|
||||
let domid = client.create(&config)?;
|
||||
println!("created domain {}", domid);
|
||||
|
@ -11,7 +11,7 @@ use crate::error::{Error, Result};
|
||||
use crate::x86::X86BootSetup;
|
||||
use log::{trace, warn};
|
||||
|
||||
use std::fs::{read, File, OpenOptions};
|
||||
use std::fs::read;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::thread;
|
||||
@ -59,6 +59,11 @@ pub struct DomainNetworkInterface<'a> {
|
||||
#[derive(Debug)]
|
||||
pub struct DomainConsole {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DomainEventChannel<'a> {
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DomainConfig<'a> {
|
||||
pub backend_domid: u32,
|
||||
@ -72,6 +77,7 @@ pub struct DomainConfig<'a> {
|
||||
pub consoles: Vec<DomainConsole>,
|
||||
pub vifs: Vec<DomainNetworkInterface<'a>>,
|
||||
pub filesystems: Vec<DomainFilesystem<'a>>,
|
||||
pub event_channels: Vec<DomainEventChannel<'a>>,
|
||||
pub extra_keys: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
@ -99,90 +105,6 @@ impl XenClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy(&mut self, domid: u32) -> Result<()> {
|
||||
if let Err(err) = self.destroy_store(domid) {
|
||||
warn!("failed to destroy store for domain {}: {}", domid, err);
|
||||
}
|
||||
self.call.destroy_domain(domid)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy_store(&mut self, domid: u32) -> Result<()> {
|
||||
let dom_path = self.store.get_domain_path(domid)?;
|
||||
let vm_path = self.store.read_string(&format!("{}/vm", dom_path))?;
|
||||
if vm_path.is_empty() {
|
||||
return Err(Error::DomainNonExistent);
|
||||
}
|
||||
|
||||
let mut backend_paths: Vec<String> = Vec::new();
|
||||
let console_frontend_path = format!("{}/console", dom_path);
|
||||
let console_backend_path = self
|
||||
.store
|
||||
.read_string_optional(format!("{}/backend", console_frontend_path).as_str())?;
|
||||
|
||||
for device_category in self
|
||||
.store
|
||||
.list_any(format!("{}/device", dom_path).as_str())?
|
||||
{
|
||||
for device_id in self
|
||||
.store
|
||||
.list_any(format!("{}/device/{}", dom_path, device_category).as_str())?
|
||||
{
|
||||
let device_path = format!("{}/device/{}/{}", dom_path, device_category, device_id);
|
||||
let backend_path = self
|
||||
.store
|
||||
.read_string(format!("{}/backend", device_path).as_str())?;
|
||||
backend_paths.push(backend_path);
|
||||
}
|
||||
}
|
||||
|
||||
for backend in &backend_paths {
|
||||
let state_path = format!("{}/state", backend);
|
||||
let online_path = format!("{}/online", backend);
|
||||
let mut tx = self.store.transaction()?;
|
||||
let state = tx.read_string(&state_path)?;
|
||||
if state.is_empty() {
|
||||
break;
|
||||
}
|
||||
tx.write_string(&online_path, "0")?;
|
||||
if !state.is_empty() && u32::from_str(&state).unwrap_or(0) != 6 {
|
||||
tx.write_string(&state_path, "5")?;
|
||||
}
|
||||
tx.commit()?;
|
||||
|
||||
let mut count: u32 = 0;
|
||||
loop {
|
||||
if count >= 100 {
|
||||
warn!("unable to safely destroy backend: {}", backend);
|
||||
break;
|
||||
}
|
||||
let state = self.store.read_string(&state_path)?;
|
||||
let state = i64::from_str(&state).unwrap_or(-1);
|
||||
if state == 6 {
|
||||
break;
|
||||
}
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut tx = self.store.transaction()?;
|
||||
let mut backend_removals: Vec<String> = Vec::new();
|
||||
backend_removals.extend_from_slice(backend_paths.as_slice());
|
||||
if let Some(backend) = console_backend_path {
|
||||
backend_removals.push(backend);
|
||||
}
|
||||
for path in &backend_removals {
|
||||
let path = PathBuf::from(path);
|
||||
let parent = path.parent().ok_or(Error::PathParentNotFound)?;
|
||||
tx.rm(parent.to_str().ok_or(Error::PathStringConversion)?)?;
|
||||
}
|
||||
tx.rm(&vm_path)?;
|
||||
tx.rm(&dom_path)?;
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init(&mut self, domid: u32, domain: &CreateDomain, config: &DomainConfig) -> Result<()> {
|
||||
trace!(
|
||||
"XenClient init domid={} domain={:?} config={:?}",
|
||||
@ -401,6 +323,18 @@ impl XenClient {
|
||||
vif,
|
||||
)?;
|
||||
}
|
||||
|
||||
for channel in &config.event_channels {
|
||||
let id = self
|
||||
.call
|
||||
.evtchn_alloc_unbound(domid, config.backend_domid)?;
|
||||
let channel_path = format!("{}/evtchn/{}", dom_path, channel.name);
|
||||
self.store
|
||||
.write_string(&format!("{}/name", channel_path), channel.name)?;
|
||||
self.store
|
||||
.write_string(&format!("{}/channel", channel_path), &id.to_string())?;
|
||||
}
|
||||
|
||||
self.call.unpause_domain(domid)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -673,7 +607,91 @@ impl XenClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn open_console(&mut self, domid: u32) -> Result<(File, File)> {
|
||||
pub fn destroy(&mut self, domid: u32) -> Result<()> {
|
||||
if let Err(err) = self.destroy_store(domid) {
|
||||
warn!("failed to destroy store for domain {}: {}", domid, err);
|
||||
}
|
||||
self.call.destroy_domain(domid)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy_store(&mut self, domid: u32) -> Result<()> {
|
||||
let dom_path = self.store.get_domain_path(domid)?;
|
||||
let vm_path = self.store.read_string(&format!("{}/vm", dom_path))?;
|
||||
if vm_path.is_empty() {
|
||||
return Err(Error::DomainNonExistent);
|
||||
}
|
||||
|
||||
let mut backend_paths: Vec<String> = Vec::new();
|
||||
let console_frontend_path = format!("{}/console", dom_path);
|
||||
let console_backend_path = self
|
||||
.store
|
||||
.read_string_optional(format!("{}/backend", console_frontend_path).as_str())?;
|
||||
|
||||
for device_category in self
|
||||
.store
|
||||
.list_any(format!("{}/device", dom_path).as_str())?
|
||||
{
|
||||
for device_id in self
|
||||
.store
|
||||
.list_any(format!("{}/device/{}", dom_path, device_category).as_str())?
|
||||
{
|
||||
let device_path = format!("{}/device/{}/{}", dom_path, device_category, device_id);
|
||||
let backend_path = self
|
||||
.store
|
||||
.read_string(format!("{}/backend", device_path).as_str())?;
|
||||
backend_paths.push(backend_path);
|
||||
}
|
||||
}
|
||||
|
||||
for backend in &backend_paths {
|
||||
let state_path = format!("{}/state", backend);
|
||||
let online_path = format!("{}/online", backend);
|
||||
let mut tx = self.store.transaction()?;
|
||||
let state = tx.read_string(&state_path)?;
|
||||
if state.is_empty() {
|
||||
break;
|
||||
}
|
||||
tx.write_string(&online_path, "0")?;
|
||||
if !state.is_empty() && u32::from_str(&state).unwrap_or(0) != 6 {
|
||||
tx.write_string(&state_path, "5")?;
|
||||
}
|
||||
tx.commit()?;
|
||||
|
||||
let mut count: u32 = 0;
|
||||
loop {
|
||||
if count >= 100 {
|
||||
warn!("unable to safely destroy backend: {}", backend);
|
||||
break;
|
||||
}
|
||||
let state = self.store.read_string(&state_path)?;
|
||||
let state = i64::from_str(&state).unwrap_or(-1);
|
||||
if state == 6 {
|
||||
break;
|
||||
}
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut tx = self.store.transaction()?;
|
||||
let mut backend_removals: Vec<String> = Vec::new();
|
||||
backend_removals.extend_from_slice(backend_paths.as_slice());
|
||||
if let Some(backend) = console_backend_path {
|
||||
backend_removals.push(backend);
|
||||
}
|
||||
for path in &backend_removals {
|
||||
let path = PathBuf::from(path);
|
||||
let parent = path.parent().ok_or(Error::PathParentNotFound)?;
|
||||
tx.rm(parent.to_str().ok_or(Error::PathStringConversion)?)?;
|
||||
}
|
||||
tx.rm(&vm_path)?;
|
||||
tx.rm(&dom_path)?;
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_console_path(&mut self, domid: u32) -> Result<String> {
|
||||
let dom_path = self.store.get_domain_path(domid)?;
|
||||
let console_tty_path = format!("{}/console/tty", dom_path);
|
||||
let mut tty: Option<String> = None;
|
||||
@ -687,8 +705,6 @@ impl XenClient {
|
||||
let Some(tty) = tty else {
|
||||
return Err(Error::TtyNotFound);
|
||||
};
|
||||
let read = OpenOptions::new().read(true).write(false).open(&tty)?;
|
||||
let write = OpenOptions::new().read(false).write(true).open(&tty)?;
|
||||
Ok((read, write))
|
||||
Ok(tty)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user