utilize async processing for console and child exit events

This commit is contained in:
2024-02-23 03:25:06 +00:00
parent c582f15c54
commit 3af9ffec34
16 changed files with 364 additions and 167 deletions

View File

@@ -1,11 +1,6 @@
use std::{
io::{self, Read, Write},
process::exit,
thread,
};
use anyhow::{anyhow, Result};
use termion::raw::IntoRawMode;
use crate::console::XenConsole;
use super::ControllerContext;
@@ -18,49 +13,15 @@ impl ControllerConsole<'_> {
ControllerConsole { context }
}
pub fn perform(&mut self, id: &str) -> Result<()> {
pub async fn perform(&mut self, id: &str) -> Result<()> {
let info = self
.context
.resolve(id)?
.ok_or_else(|| anyhow!("unable to resolve container: {}", id))?;
let domid = info.domid;
let (mut read, mut write) = self.context.xen.open_console(domid)?;
let mut stdin = io::stdin();
let is_tty = termion::is_tty(&stdin);
let mut stdout_for_exit = io::stdout().into_raw_mode()?;
thread::spawn(move || {
let mut buffer = vec![0u8; 60];
loop {
let size = stdin.read(&mut buffer).expect("failed to read stdin");
if is_tty && size == 1 && buffer[0] == 0x1d {
stdout_for_exit
.suspend_raw_mode()
.expect("failed to disable raw mode");
stdout_for_exit.flush().expect("failed to flush stdout");
exit(0);
}
write
.write_all(&buffer[0..size])
.expect("failed to write to domain console");
write.flush().expect("failed to flush domain console");
}
});
let mut buffer = vec![0u8; 256];
if is_tty {
let mut stdout = io::stdout().into_raw_mode()?;
loop {
let size = read.read(&mut buffer)?;
stdout.write_all(&buffer[0..size])?;
stdout.flush()?;
}
} else {
let mut stdout = io::stdout();
loop {
let size = read.read(&mut buffer)?;
stdout.write_all(&buffer[0..size])?;
stdout.flush()?;
}
}
let tty = self.context.xen.get_console_path(domid)?;
let console = XenConsole::new(&tty).await?;
console.attach().await?;
Ok(())
}
}

View File

@@ -4,10 +4,11 @@ use advmac::MacAddr6;
use anyhow::{anyhow, Result};
use ipnetwork::Ipv4Network;
use krata::{
LaunchInfo, LaunchNetwork, LaunchNetworkIpv4, LaunchNetworkIpv6, LaunchNetworkResolver,
LaunchChannels, LaunchInfo, LaunchNetwork, LaunchNetworkIpv4, LaunchNetworkIpv6,
LaunchNetworkResolver,
};
use uuid::Uuid;
use xenclient::{DomainConfig, DomainDisk, DomainNetworkInterface};
use xenclient::{DomainConfig, DomainDisk, DomainEventChannel, DomainNetworkInterface};
use xenstore::client::XsdInterface;
use crate::image::{name::ImageName, ImageCompiler, ImageInfo};
@@ -75,6 +76,9 @@ impl ControllerLaunch<'_> {
}),
env: request.env,
run: request.run,
channels: LaunchChannels {
exit: "krata-exit".to_string(),
},
};
let cfgblk = ConfigBlock::new(&uuid, &image_info)?;
@@ -133,6 +137,7 @@ impl ControllerLaunch<'_> {
script: None,
}],
filesystems: vec![],
event_channels: vec![DomainEventChannel { name: "krata-exit" }],
extra_keys: vec![
("krata/uuid".to_string(), uuid.to_string()),
(