mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 12:50:54 +00:00
krata: event-based network backend startup and api enhancements
This commit is contained in:
parent
63c0feb053
commit
66465793cd
@ -7,11 +7,15 @@ resolver = "2"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
|
log = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
prost = { workspace = true }
|
prost = { workspace = true }
|
||||||
prost-reflect = { workspace = true }
|
prost-reflect = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
tonic = { workspace = true }
|
tonic = { workspace = true }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
tokio-stream = { workspace = true }
|
||||||
|
tower = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
use crate::{dial::ControlDialAddress, v1::control::control_service_client::ControlServiceClient};
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use krata::{dial::ControlDialAddress, v1::control::control_service_client::ControlServiceClient};
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use tokio::net::UnixStream;
|
use tokio::net::UnixStream;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::v1::control::{watch_events_reply::Event, WatchEventsReply};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use krata::v1::control::{watch_events_reply::Event, WatchEventsReply};
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use tokio::{sync::broadcast, task::JoinHandle};
|
use tokio::{sync::broadcast, task::JoinHandle};
|
||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
@ -1,10 +1,13 @@
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use prost_reflect::DescriptorPool;
|
use prost_reflect::DescriptorPool;
|
||||||
|
|
||||||
pub mod dial;
|
|
||||||
pub mod launchcfg;
|
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
|
|
||||||
|
pub mod client;
|
||||||
|
pub mod dial;
|
||||||
|
pub mod events;
|
||||||
|
pub mod launchcfg;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub mod ethtool;
|
pub mod ethtool;
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use krata::v1::control::control_service_client::ControlServiceClient;
|
use krata::{events::EventStream, v1::control::control_service_client::ControlServiceClient};
|
||||||
|
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tonic::transport::Channel;
|
use tonic::transport::Channel;
|
||||||
|
|
||||||
use crate::{console::StdioConsoleStream, events::EventStream};
|
use crate::console::StdioConsoleStream;
|
||||||
|
|
||||||
use super::resolve_guest;
|
use super::resolve_guest;
|
||||||
|
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use krata::v1::{
|
use krata::{
|
||||||
common::GuestStatus,
|
events::EventStream,
|
||||||
control::{
|
v1::{
|
||||||
control_service_client::ControlServiceClient, watch_events_reply::Event,
|
common::GuestStatus,
|
||||||
DestroyGuestRequest,
|
control::{
|
||||||
|
control_service_client::ControlServiceClient, watch_events_reply::Event,
|
||||||
|
DestroyGuestRequest,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use tonic::{transport::Channel, Request};
|
use tonic::{transport::Channel, Request};
|
||||||
|
|
||||||
use crate::{cli::resolve_guest, events::EventStream};
|
use crate::cli::resolve_guest;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
pub struct DestroyCommand {
|
pub struct DestroyCommand {
|
||||||
|
@ -2,20 +2,24 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use krata::v1::{
|
use krata::{
|
||||||
common::{
|
events::EventStream,
|
||||||
guest_image_spec::Image, GuestEnvVar, GuestImageSpec, GuestOciImageSpec, GuestSpec,
|
v1::{
|
||||||
GuestStatus,
|
common::{
|
||||||
},
|
guest_image_spec::Image, GuestImageSpec, GuestOciImageSpec, GuestSpec, GuestStatus,
|
||||||
control::{
|
GuestTaskSpec, GuestTaskSpecEnvVar,
|
||||||
control_service_client::ControlServiceClient, watch_events_reply::Event, CreateGuestRequest,
|
},
|
||||||
|
control::{
|
||||||
|
control_service_client::ControlServiceClient, watch_events_reply::Event,
|
||||||
|
CreateGuestRequest,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tonic::{transport::Channel, Request};
|
use tonic::{transport::Channel, Request};
|
||||||
|
|
||||||
use crate::{console::StdioConsoleStream, events::EventStream};
|
use crate::console::StdioConsoleStream;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
pub struct LauchCommand {
|
pub struct LauchCommand {
|
||||||
@ -51,14 +55,17 @@ impl LauchCommand {
|
|||||||
}),
|
}),
|
||||||
vcpus: self.cpus,
|
vcpus: self.cpus,
|
||||||
mem: self.mem,
|
mem: self.mem,
|
||||||
env: env_map(&self.env.unwrap_or_default())
|
task: Some(GuestTaskSpec {
|
||||||
.iter()
|
environment: env_map(&self.env.unwrap_or_default())
|
||||||
.map(|(key, value)| GuestEnvVar {
|
.iter()
|
||||||
key: key.clone(),
|
.map(|(key, value)| GuestTaskSpecEnvVar {
|
||||||
value: value.clone(),
|
key: key.clone(),
|
||||||
})
|
value: value.clone(),
|
||||||
.collect(),
|
})
|
||||||
run: self.run,
|
.collect(),
|
||||||
|
command: self.run,
|
||||||
|
}),
|
||||||
|
annotations: vec![],
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
let response = client
|
let response = client
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use clap::{Parser, ValueEnum};
|
use clap::{Parser, ValueEnum};
|
||||||
use cli_tables::Table;
|
use cli_tables::Table;
|
||||||
use krata::v1::{
|
use krata::{
|
||||||
common::{guest_image_spec::Image, Guest},
|
events::EventStream,
|
||||||
control::{
|
v1::{
|
||||||
control_service_client::ControlServiceClient, ListGuestsRequest, ResolveGuestRequest,
|
common::{guest_image_spec::Image, Guest},
|
||||||
|
control::{
|
||||||
|
control_service_client::ControlServiceClient, ListGuestsRequest, ResolveGuestRequest,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tonic::{transport::Channel, Request};
|
use tonic::{transport::Channel, Request};
|
||||||
|
|
||||||
use crate::{
|
use crate::format::{guest_state_text, kv2line, proto2dynamic, proto2kv};
|
||||||
events::EventStream,
|
|
||||||
format::{guest_state_text, kv2line, proto2dynamic, proto2kv},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(ValueEnum, Clone, Debug, PartialEq, Eq)]
|
#[derive(ValueEnum, Clone, Debug, PartialEq, Eq)]
|
||||||
enum ListFormat {
|
enum ListFormat {
|
||||||
@ -106,13 +106,13 @@ impl ListCommand {
|
|||||||
.state
|
.state
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|x| x.network.as_ref())
|
.and_then(|x| x.network.as_ref())
|
||||||
.map(|x| x.ipv4.as_str())
|
.map(|x| x.guest_ipv4.as_str())
|
||||||
.unwrap_or("unknown");
|
.unwrap_or("unknown");
|
||||||
let ipv6 = guest
|
let ipv6 = guest
|
||||||
.state
|
.state
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|x| x.network.as_ref())
|
.and_then(|x| x.network.as_ref())
|
||||||
.map(|x| x.ipv6.as_str())
|
.map(|x| x.guest_ipv6.as_str())
|
||||||
.unwrap_or("unknown");
|
.unwrap_or("unknown");
|
||||||
let Some(spec) = guest.spec else {
|
let Some(spec) = guest.spec else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -7,13 +7,15 @@ pub mod watch;
|
|||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use krata::v1::control::{
|
use krata::{
|
||||||
control_service_client::ControlServiceClient, ResolveGuestRequest, WatchEventsRequest,
|
client::ControlClientProvider,
|
||||||
|
events::EventStream,
|
||||||
|
v1::control::{
|
||||||
|
control_service_client::ControlServiceClient, ResolveGuestRequest, WatchEventsRequest,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use tonic::{transport::Channel, Request};
|
use tonic::{transport::Channel, Request};
|
||||||
|
|
||||||
use crate::{client::ControlClientProvider, events::EventStream};
|
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
attach::AttachCommand, destroy::DestroyCommand, launch::LauchCommand, list::ListCommand,
|
attach::AttachCommand, destroy::DestroyCommand, launch::LauchCommand, list::ListCommand,
|
||||||
resolve::ResolveCommand, watch::WatchCommand,
|
resolve::ResolveCommand, watch::WatchCommand,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Parser, ValueEnum};
|
use clap::{Parser, ValueEnum};
|
||||||
use krata::v1::{common::Guest, control::watch_events_reply::Event};
|
use krata::{
|
||||||
|
events::EventStream,
|
||||||
|
v1::{common::Guest, control::watch_events_reply::Event},
|
||||||
|
};
|
||||||
use prost_reflect::ReflectMessage;
|
use prost_reflect::ReflectMessage;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::format::{guest_state_text, kv2line, proto2dynamic, proto2kv};
|
||||||
events::EventStream,
|
|
||||||
format::{guest_state_text, kv2line, proto2dynamic, proto2kv},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(ValueEnum, Clone, Debug, PartialEq, Eq)]
|
#[derive(ValueEnum, Clone, Debug, PartialEq, Eq)]
|
||||||
enum WatchFormat {
|
enum WatchFormat {
|
||||||
|
@ -4,9 +4,12 @@ use crossterm::{
|
|||||||
terminal::{disable_raw_mode, enable_raw_mode, is_raw_mode_enabled},
|
terminal::{disable_raw_mode, enable_raw_mode, is_raw_mode_enabled},
|
||||||
tty::IsTty,
|
tty::IsTty,
|
||||||
};
|
};
|
||||||
use krata::v1::{
|
use krata::{
|
||||||
common::GuestStatus,
|
events::EventStream,
|
||||||
control::{watch_events_reply::Event, ConsoleDataReply, ConsoleDataRequest},
|
v1::{
|
||||||
|
common::GuestStatus,
|
||||||
|
control::{watch_events_reply::Event, ConsoleDataReply, ConsoleDataRequest},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
@ -16,8 +19,6 @@ use tokio::{
|
|||||||
use tokio_stream::{Stream, StreamExt};
|
use tokio_stream::{Stream, StreamExt};
|
||||||
use tonic::Streaming;
|
use tonic::Streaming;
|
||||||
|
|
||||||
use crate::events::EventStream;
|
|
||||||
|
|
||||||
pub struct StdioConsoleStream;
|
pub struct StdioConsoleStream;
|
||||||
|
|
||||||
impl StdioConsoleStream {
|
impl StdioConsoleStream {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod client;
|
|
||||||
pub mod console;
|
pub mod console;
|
||||||
pub mod events;
|
|
||||||
pub mod format;
|
pub mod format;
|
||||||
|
@ -105,6 +105,7 @@ impl ControlService for RuntimeControlService {
|
|||||||
network: None,
|
network: None,
|
||||||
exit_info: None,
|
exit_info: None,
|
||||||
error_info: None,
|
error_info: None,
|
||||||
|
domid: u32::MAX,
|
||||||
}),
|
}),
|
||||||
spec: Some(spec),
|
spec: Some(spec),
|
||||||
}),
|
}),
|
||||||
|
@ -124,6 +124,7 @@ impl DaemonEventGenerator {
|
|||||||
network: guest.state.clone().unwrap_or_default().network,
|
network: guest.state.clone().unwrap_or_default().network,
|
||||||
exit_info: Some(GuestExitInfo { code }),
|
exit_info: Some(GuestExitInfo { code }),
|
||||||
error_info: None,
|
error_info: None,
|
||||||
|
domid: guest.state.clone().map(|x| x.domid).unwrap_or(u32::MAX),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.guests.update(id, entry).await?;
|
self.guests.update(id, entry).await?;
|
||||||
|
@ -8,7 +8,7 @@ use krata::v1::{
|
|||||||
},
|
},
|
||||||
control::GuestChangedEvent,
|
control::GuestChangedEvent,
|
||||||
};
|
};
|
||||||
use kratart::{launch::GuestLaunchRequest, Runtime};
|
use kratart::{launch::GuestLaunchRequest, GuestInfo, Runtime};
|
||||||
use log::{error, info, trace, warn};
|
use log::{error, info, trace, warn};
|
||||||
use tokio::{select, sync::mpsc::Receiver, task::JoinHandle, time::sleep};
|
use tokio::{select, sync::mpsc::Receiver, task::JoinHandle, time::sleep};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@ -92,10 +92,7 @@ impl GuestReconciler {
|
|||||||
} else {
|
} else {
|
||||||
state.status = GuestStatus::Started.into();
|
state.status = GuestStatus::Started.into();
|
||||||
}
|
}
|
||||||
state.network = Some(GuestNetworkState {
|
state.network = Some(guestinfo_to_networkstate(runtime));
|
||||||
ipv4: runtime.ipv4.map(|x| x.ip().to_string()).unwrap_or_default(),
|
|
||||||
ipv6: runtime.ipv6.map(|x| x.ip().to_string()).unwrap_or_default(),
|
|
||||||
});
|
|
||||||
stored_guest.state = Some(state);
|
stored_guest.state = Some(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,6 +184,8 @@ impl GuestReconciler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let task = spec.task.as_ref().cloned().unwrap_or_default();
|
||||||
|
|
||||||
let info = self
|
let info = self
|
||||||
.runtime
|
.runtime
|
||||||
.launch(GuestLaunchRequest {
|
.launch(GuestLaunchRequest {
|
||||||
@ -199,24 +198,22 @@ impl GuestReconciler {
|
|||||||
image: &oci.image,
|
image: &oci.image,
|
||||||
vcpus: spec.vcpus,
|
vcpus: spec.vcpus,
|
||||||
mem: spec.mem,
|
mem: spec.mem,
|
||||||
env: spec
|
env: task
|
||||||
.env
|
.environment
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| (x.key.clone(), x.value.clone()))
|
.map(|x| (x.key.clone(), x.value.clone()))
|
||||||
.collect::<HashMap<_, _>>(),
|
.collect::<HashMap<_, _>>(),
|
||||||
run: empty_vec_optional(spec.run.clone()),
|
run: empty_vec_optional(task.command.clone()),
|
||||||
debug: false,
|
debug: false,
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
info!("started guest {}", uuid);
|
info!("started guest {}", uuid);
|
||||||
guest.state = Some(GuestState {
|
guest.state = Some(GuestState {
|
||||||
status: GuestStatus::Started.into(),
|
status: GuestStatus::Started.into(),
|
||||||
network: Some(GuestNetworkState {
|
network: Some(guestinfo_to_networkstate(&info)),
|
||||||
ipv4: info.ipv4.map(|x| x.ip().to_string()).unwrap_or_default(),
|
|
||||||
ipv6: info.ipv6.map(|x| x.ip().to_string()).unwrap_or_default(),
|
|
||||||
}),
|
|
||||||
exit_info: None,
|
exit_info: None,
|
||||||
error_info: None,
|
error_info: None,
|
||||||
|
domid: info.domid,
|
||||||
});
|
});
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@ -232,6 +229,7 @@ impl GuestReconciler {
|
|||||||
network: None,
|
network: None,
|
||||||
exit_info: None,
|
exit_info: None,
|
||||||
error_info: None,
|
error_info: None,
|
||||||
|
domid: guest.state.as_ref().map(|x| x.domid).unwrap_or(u32::MAX),
|
||||||
});
|
});
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
@ -244,3 +242,14 @@ fn empty_vec_optional<T>(value: Vec<T>) -> Option<Vec<T>> {
|
|||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn guestinfo_to_networkstate(info: &GuestInfo) -> GuestNetworkState {
|
||||||
|
GuestNetworkState {
|
||||||
|
guest_ipv4: info.guest_ipv4.map(|x| x.to_string()).unwrap_or_default(),
|
||||||
|
guest_ipv6: info.guest_ipv6.map(|x| x.to_string()).unwrap_or_default(),
|
||||||
|
guest_mac: info.guest_mac.as_ref().cloned().unwrap_or_default(),
|
||||||
|
gateway_ipv4: info.gateway_ipv4.map(|x| x.to_string()).unwrap_or_default(),
|
||||||
|
gateway_ipv6: info.gateway_ipv6.map(|x| x.to_string()).unwrap_or_default(),
|
||||||
|
gateway_mac: info.gateway_mac.as_ref().cloned().unwrap_or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
use krataguest::init::GuestInit;
|
use krataguest::{death, init::GuestInit};
|
||||||
|
use log::error;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@ -19,6 +20,9 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut guest = GuestInit::new();
|
let mut guest = GuestInit::new();
|
||||||
guest.init().await?;
|
if let Err(error) = guest.init().await {
|
||||||
|
error!("failed to initialize guest: {}", error);
|
||||||
|
death(127).await?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use std::time::Duration;
|
use crate::{
|
||||||
|
childwait::{ChildEvent, ChildWait},
|
||||||
use crate::childwait::{ChildEvent, ChildWait};
|
death,
|
||||||
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use nix::{libc::c_int, unistd::Pid};
|
use nix::unistd::Pid;
|
||||||
use tokio::{select, time::sleep};
|
use tokio::select;
|
||||||
use xenstore::{XsdClient, XsdInterface};
|
|
||||||
|
|
||||||
pub struct GuestBackground {
|
pub struct GuestBackground {
|
||||||
child: Pid,
|
child: Pid,
|
||||||
@ -35,19 +35,8 @@ impl GuestBackground {
|
|||||||
|
|
||||||
async fn child_event(&mut self, event: ChildEvent) -> Result<()> {
|
async fn child_event(&mut self, event: ChildEvent) -> Result<()> {
|
||||||
if event.pid == self.child {
|
if event.pid == self.child {
|
||||||
self.death(event.status).await?;
|
death(event.status).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn death(&mut self, code: c_int) -> Result<()> {
|
|
||||||
let store = XsdClient::open().await?;
|
|
||||||
store
|
|
||||||
.write_string("krata/guest/exit-code", &code.to_string())
|
|
||||||
.await?;
|
|
||||||
drop(store);
|
|
||||||
loop {
|
|
||||||
sleep(Duration::from_secs(1)).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
|
use std::{os::raw::c_int, time::Duration};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
use xenstore::{XsdClient, XsdInterface};
|
||||||
|
|
||||||
pub mod background;
|
pub mod background;
|
||||||
pub mod childwait;
|
pub mod childwait;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
|
|
||||||
|
pub async fn death(code: c_int) -> Result<()> {
|
||||||
|
let store = XsdClient::open().await?;
|
||||||
|
store
|
||||||
|
.write_string("krata/guest/exit-code", &code.to_string())
|
||||||
|
.await?;
|
||||||
|
drop(store);
|
||||||
|
loop {
|
||||||
|
sleep(Duration::from_secs(1)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,15 +13,16 @@ clap = { workspace = true }
|
|||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
etherparse = { workspace = true }
|
etherparse = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
|
krata = { path = "../krata" }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
rtnetlink = { workspace = true }
|
rtnetlink = { workspace = true }
|
||||||
smoltcp = { workspace = true }
|
smoltcp = { workspace = true }
|
||||||
|
tonic = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
tokio-tun = { workspace = true }
|
tokio-tun = { workspace = true }
|
||||||
udp-stream = { workspace = true }
|
udp-stream = { workspace = true }
|
||||||
uuid = { workspace = true }
|
uuid = { workspace = true }
|
||||||
xenstore = { path = "../xen/xenstore" }
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "kratanet"
|
name = "kratanet"
|
||||||
@ -33,7 +34,3 @@ path = "bin/network.rs"
|
|||||||
[[example]]
|
[[example]]
|
||||||
name = "ping"
|
name = "ping"
|
||||||
path = "examples/ping.rs"
|
path = "examples/ping.rs"
|
||||||
|
|
||||||
[[example]]
|
|
||||||
name = "autonet"
|
|
||||||
path = "examples/autonet.rs"
|
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
|
use krata::dial::ControlDialAddress;
|
||||||
use kratanet::NetworkService;
|
use kratanet::NetworkService;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct NetworkArgs {}
|
struct NetworkArgs {
|
||||||
|
#[arg(short, long, default_value = "unix:///var/lib/krata/daemon.socket")]
|
||||||
|
connection: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main(flavor = "multi_thread", worker_threads = 10)]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||||
let _ = NetworkArgs::parse();
|
let args = NetworkArgs::parse();
|
||||||
let mut service = NetworkService::new().await?;
|
let control_dial_address = ControlDialAddress::from_str(&args.connection)?;
|
||||||
|
let mut service = NetworkService::new(control_dial_address).await?;
|
||||||
service.watch().await
|
service.watch().await
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use kratanet::autonet::AutoNetworkCollector;
|
|
||||||
use tokio::time::sleep;
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> Result<()> {
|
|
||||||
let mut collector = AutoNetworkCollector::new().await?;
|
|
||||||
loop {
|
|
||||||
let changeset = collector.read_changes().await?;
|
|
||||||
println!("{:?}", changeset);
|
|
||||||
sleep(Duration::from_secs(2)).await;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,24 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::Result;
|
||||||
|
use krata::{
|
||||||
|
events::EventStream,
|
||||||
|
v1::{
|
||||||
|
common::Guest,
|
||||||
|
control::{
|
||||||
|
control_service_client::ControlServiceClient, watch_events_reply::Event,
|
||||||
|
ListGuestsRequest, WatchEventsRequest,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use log::warn;
|
||||||
use smoltcp::wire::{EthernetAddress, Ipv4Cidr, Ipv6Cidr};
|
use smoltcp::wire::{EthernetAddress, Ipv4Cidr, Ipv6Cidr};
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use std::{collections::HashMap, str::FromStr, time::Duration};
|
||||||
|
use tokio::{select, sync::broadcast::Receiver, time::sleep};
|
||||||
|
use tonic::transport::Channel;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use xenstore::{XsdClient, XsdInterface, XsdTransaction};
|
|
||||||
|
|
||||||
pub struct AutoNetworkCollector {
|
pub struct AutoNetworkWatcher {
|
||||||
client: XsdClient,
|
control: ControlServiceClient<Channel>,
|
||||||
|
pub events: EventStream,
|
||||||
known: HashMap<Uuid, NetworkMetadata>,
|
known: HashMap<Uuid, NetworkMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,116 +49,88 @@ pub struct AutoNetworkChangeset {
|
|||||||
pub removed: Vec<NetworkMetadata>,
|
pub removed: Vec<NetworkMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AutoNetworkCollector {
|
impl AutoNetworkWatcher {
|
||||||
pub async fn new() -> Result<AutoNetworkCollector> {
|
pub async fn new(mut control: ControlServiceClient<Channel>) -> Result<AutoNetworkWatcher> {
|
||||||
Ok(AutoNetworkCollector {
|
let watch_events_response = control.watch_events(WatchEventsRequest {}).await?;
|
||||||
client: XsdClient::open().await?,
|
|
||||||
|
Ok(AutoNetworkWatcher {
|
||||||
|
control,
|
||||||
|
events: EventStream::open(watch_events_response.into_inner()).await?,
|
||||||
known: HashMap::new(),
|
known: HashMap::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read(&mut self) -> Result<Vec<NetworkMetadata>> {
|
pub async fn read(&mut self) -> Result<Vec<NetworkMetadata>> {
|
||||||
let mut networks = Vec::new();
|
let mut all_guests: HashMap<Uuid, Guest> = HashMap::new();
|
||||||
let tx = self.client.transaction().await?;
|
for guest in self
|
||||||
for domid_string in tx.list("/local/domain").await? {
|
.control
|
||||||
let Ok(domid) = domid_string.parse::<u32>() else {
|
.list_guests(ListGuestsRequest {})
|
||||||
|
.await?
|
||||||
|
.into_inner()
|
||||||
|
.guests
|
||||||
|
{
|
||||||
|
let Ok(uuid) = Uuid::from_str(&guest.id) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
all_guests.insert(uuid, guest);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut networks: Vec<NetworkMetadata> = Vec::new();
|
||||||
|
for (uuid, guest) in &all_guests {
|
||||||
|
let Some(ref state) = guest.state else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let dom_path = format!("/local/domain/{}", domid_string);
|
if state.domid == u32::MAX {
|
||||||
let Some(uuid_string) = tx.read_string(&format!("{}/krata/uuid", dom_path)).await?
|
continue;
|
||||||
else {
|
}
|
||||||
|
|
||||||
|
let Some(ref network) = state.network else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(uuid) = uuid_string.parse::<Uuid>() else {
|
let Ok(guest_ipv4_cidr) = Ipv4Cidr::from_str(&network.guest_ipv4) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(guest) =
|
let Ok(guest_ipv6_cidr) = Ipv6Cidr::from_str(&network.guest_ipv6) else {
|
||||||
AutoNetworkCollector::read_network_side(uuid, &tx, &dom_path, "guest").await
|
|
||||||
else {
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(gateway) =
|
let Ok(guest_mac) = EthernetAddress::from_str(&network.guest_mac) else {
|
||||||
AutoNetworkCollector::read_network_side(uuid, &tx, &dom_path, "gateway").await
|
continue;
|
||||||
else {
|
};
|
||||||
|
|
||||||
|
let Ok(gateway_ipv4_cidr) = Ipv4Cidr::from_str(&network.gateway_ipv4) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(gateway_ipv6_cidr) = Ipv6Cidr::from_str(&network.gateway_ipv6) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(gateway_mac) = EthernetAddress::from_str(&network.gateway_mac) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
networks.push(NetworkMetadata {
|
networks.push(NetworkMetadata {
|
||||||
domid,
|
domid: state.domid,
|
||||||
uuid,
|
uuid: *uuid,
|
||||||
guest,
|
guest: NetworkSide {
|
||||||
gateway,
|
ipv4: guest_ipv4_cidr,
|
||||||
|
ipv6: guest_ipv6_cidr,
|
||||||
|
mac: guest_mac,
|
||||||
|
},
|
||||||
|
gateway: NetworkSide {
|
||||||
|
ipv4: gateway_ipv4_cidr,
|
||||||
|
ipv6: gateway_ipv6_cidr,
|
||||||
|
mac: gateway_mac,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
tx.commit().await?;
|
|
||||||
Ok(networks)
|
Ok(networks)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_network_side(
|
|
||||||
uuid: Uuid,
|
|
||||||
tx: &XsdTransaction,
|
|
||||||
dom_path: &str,
|
|
||||||
side: &str,
|
|
||||||
) -> Result<NetworkSide> {
|
|
||||||
let side_path = format!("{}/krata/network/{}", dom_path, side);
|
|
||||||
let Some(ipv4) = tx.read_string(&format!("{}/ipv4", side_path)).await? else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"krata domain {} is missing {} ipv4 network entry",
|
|
||||||
uuid,
|
|
||||||
side
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(ipv6) = tx.read_string(&format!("{}/ipv6", side_path)).await? else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"krata domain {} is missing {} ipv6 network entry",
|
|
||||||
uuid,
|
|
||||||
side
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(mac) = tx.read_string(&format!("{}/mac", side_path)).await? else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"krata domain {} is missing {} mac address entry",
|
|
||||||
uuid,
|
|
||||||
side
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(ipv4) = Ipv4Cidr::from_str(&ipv4) else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"krata domain {} has invalid {} ipv4 network cidr entry: {}",
|
|
||||||
uuid,
|
|
||||||
side,
|
|
||||||
ipv4
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(ipv6) = Ipv6Cidr::from_str(&ipv6) else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"krata domain {} has invalid {} ipv6 network cidr entry: {}",
|
|
||||||
uuid,
|
|
||||||
side,
|
|
||||||
ipv6
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(mac) = EthernetAddress::from_str(&mac) else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"krata domain {} has invalid {} mac address entry: {}",
|
|
||||||
uuid,
|
|
||||||
side,
|
|
||||||
mac
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(NetworkSide { ipv4, ipv6, mac })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn read_changes(&mut self) -> Result<AutoNetworkChangeset> {
|
pub async fn read_changes(&mut self) -> Result<AutoNetworkChangeset> {
|
||||||
let mut seen: Vec<Uuid> = Vec::new();
|
let mut seen: Vec<Uuid> = Vec::new();
|
||||||
let mut added: Vec<NetworkMetadata> = Vec::new();
|
let mut added: Vec<NetworkMetadata> = Vec::new();
|
||||||
@ -179,6 +164,27 @@ impl AutoNetworkCollector {
|
|||||||
Ok(AutoNetworkChangeset { added, removed })
|
Ok(AutoNetworkChangeset { added, removed })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn wait(&mut self, receiver: &mut Receiver<Event>) -> Result<()> {
|
||||||
|
loop {
|
||||||
|
select! {
|
||||||
|
x = receiver.recv() => match x {
|
||||||
|
Ok(Event::GuestChanged(_)) => {
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
|
||||||
|
Err(error) => {
|
||||||
|
warn!("failed to receive event: {}", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_ = sleep(Duration::from_secs(10)) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mark_unknown(&mut self, uuid: Uuid) -> Result<bool> {
|
pub fn mark_unknown(&mut self, uuid: Uuid) -> Result<bool> {
|
||||||
Ok(self.known.remove(&uuid).is_some())
|
Ok(self.known.remove(&uuid).is_some())
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
use std::{collections::HashMap, time::Duration};
|
use std::{collections::HashMap, time::Duration};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use autonet::{AutoNetworkChangeset, AutoNetworkCollector, NetworkMetadata};
|
use autonet::{AutoNetworkChangeset, AutoNetworkWatcher, NetworkMetadata};
|
||||||
use futures::{future::join_all, TryFutureExt};
|
use futures::{future::join_all, TryFutureExt};
|
||||||
use hbridge::HostBridge;
|
use hbridge::HostBridge;
|
||||||
|
use krata::{
|
||||||
|
client::ControlClientProvider,
|
||||||
|
dial::ControlDialAddress,
|
||||||
|
v1::{common::Guest, control::control_service_client::ControlServiceClient},
|
||||||
|
};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use tokio::{task::JoinHandle, time::sleep};
|
use tokio::{task::JoinHandle, time::sleep};
|
||||||
|
use tonic::transport::Channel;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use vbridge::VirtualBridge;
|
use vbridge::VirtualBridge;
|
||||||
|
|
||||||
@ -26,17 +32,22 @@ const HOST_BRIDGE_MTU: usize = 1500;
|
|||||||
pub const EXTRA_MTU: usize = 20;
|
pub const EXTRA_MTU: usize = 20;
|
||||||
|
|
||||||
pub struct NetworkService {
|
pub struct NetworkService {
|
||||||
|
pub control: ControlServiceClient<Channel>,
|
||||||
|
pub guests: HashMap<Uuid, Guest>,
|
||||||
pub backends: HashMap<Uuid, JoinHandle<()>>,
|
pub backends: HashMap<Uuid, JoinHandle<()>>,
|
||||||
pub bridge: VirtualBridge,
|
pub bridge: VirtualBridge,
|
||||||
pub hbridge: HostBridge,
|
pub hbridge: HostBridge,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkService {
|
impl NetworkService {
|
||||||
pub async fn new() -> Result<NetworkService> {
|
pub async fn new(control_address: ControlDialAddress) -> Result<NetworkService> {
|
||||||
|
let control = ControlClientProvider::dial(control_address).await?;
|
||||||
let bridge = VirtualBridge::new()?;
|
let bridge = VirtualBridge::new()?;
|
||||||
let hbridge =
|
let hbridge =
|
||||||
HostBridge::new(HOST_BRIDGE_MTU + EXTRA_MTU, "krata0".to_string(), &bridge).await?;
|
HostBridge::new(HOST_BRIDGE_MTU + EXTRA_MTU, "krata0".to_string(), &bridge).await?;
|
||||||
Ok(NetworkService {
|
Ok(NetworkService {
|
||||||
|
control,
|
||||||
|
guests: HashMap::new(),
|
||||||
backends: HashMap::new(),
|
backends: HashMap::new(),
|
||||||
bridge,
|
bridge,
|
||||||
hbridge,
|
hbridge,
|
||||||
@ -46,18 +57,19 @@ impl NetworkService {
|
|||||||
|
|
||||||
impl NetworkService {
|
impl NetworkService {
|
||||||
pub async fn watch(&mut self) -> Result<()> {
|
pub async fn watch(&mut self) -> Result<()> {
|
||||||
let mut collector = AutoNetworkCollector::new().await?;
|
let mut watcher = AutoNetworkWatcher::new(self.control.clone()).await?;
|
||||||
|
let mut receiver = watcher.events.subscribe();
|
||||||
loop {
|
loop {
|
||||||
let changeset = collector.read_changes().await?;
|
let changeset = watcher.read_changes().await?;
|
||||||
self.process_network_changeset(&mut collector, changeset)
|
self.process_network_changeset(&mut watcher, changeset)
|
||||||
.await?;
|
.await?;
|
||||||
sleep(Duration::from_secs(2)).await;
|
watcher.wait(&mut receiver).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_network_changeset(
|
async fn process_network_changeset(
|
||||||
&mut self,
|
&mut self,
|
||||||
collector: &mut AutoNetworkCollector,
|
collector: &mut AutoNetworkWatcher,
|
||||||
changeset: AutoNetworkChangeset,
|
changeset: AutoNetworkChangeset,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for removal in &changeset.removed {
|
for removal in &changeset.removed {
|
||||||
|
@ -20,7 +20,7 @@ impl NatHandlerContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn reclaim(&self) -> Result<()> {
|
pub async fn reclaim(&self) -> Result<()> {
|
||||||
self.reclaim_sender.try_send(self.key)?;
|
let _ = self.reclaim_sender.try_send(self.key);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +266,12 @@ impl AsyncRawSocketChannel {
|
|||||||
if error.kind() == ErrorKind::WouldBlock {
|
if error.kind() == ErrorKind::WouldBlock {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// device no longer exists
|
||||||
|
if error.raw_os_error() == Some(6) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return Err(anyhow!("failed to read from raw socket: {}", error));
|
return Err(anyhow!("failed to read from raw socket: {}", error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::IpAddr;
|
use std::net::{IpAddr, Ipv6Addr};
|
||||||
use std::{fs, net::Ipv4Addr, str::FromStr};
|
use std::{fs, net::Ipv4Addr, str::FromStr};
|
||||||
|
|
||||||
use advmac::MacAddr6;
|
use advmac::MacAddr6;
|
||||||
@ -113,7 +113,7 @@ impl GuestLauncher {
|
|||||||
];
|
];
|
||||||
let cmdline = cmdline_options.join(" ");
|
let cmdline = cmdline_options.join(" ");
|
||||||
|
|
||||||
let container_mac_string = container_mac.to_string().replace('-', ":");
|
let guest_mac_string = container_mac.to_string().replace('-', ":");
|
||||||
let gateway_mac_string = gateway_mac.to_string().replace('-', ":");
|
let gateway_mac_string = gateway_mac.to_string().replace('-', ":");
|
||||||
|
|
||||||
let mut extra_keys = vec![
|
let mut extra_keys = vec![
|
||||||
@ -140,7 +140,7 @@ impl GuestLauncher {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"krata/network/guest/mac".to_string(),
|
"krata/network/guest/mac".to_string(),
|
||||||
container_mac_string.clone(),
|
guest_mac_string.clone(),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"krata/network/gateway/ipv4".to_string(),
|
"krata/network/gateway/ipv4".to_string(),
|
||||||
@ -182,7 +182,7 @@ impl GuestLauncher {
|
|||||||
],
|
],
|
||||||
consoles: vec![],
|
consoles: vec![],
|
||||||
vifs: vec![DomainNetworkInterface {
|
vifs: vec![DomainNetworkInterface {
|
||||||
mac: &container_mac_string,
|
mac: &guest_mac_string,
|
||||||
mtu: 1500,
|
mtu: 1500,
|
||||||
bridge: None,
|
bridge: None,
|
||||||
script: None,
|
script: None,
|
||||||
@ -199,14 +199,24 @@ impl GuestLauncher {
|
|||||||
domid,
|
domid,
|
||||||
image: request.image.to_string(),
|
image: request.image.to_string(),
|
||||||
loops: vec![],
|
loops: vec![],
|
||||||
ipv4: Some(IpNetwork::new(
|
guest_ipv4: Some(IpNetwork::new(
|
||||||
IpAddr::V4(guest_ipv4),
|
IpAddr::V4(guest_ipv4),
|
||||||
ipv4_network_mask as u8,
|
ipv4_network_mask as u8,
|
||||||
)?),
|
)?),
|
||||||
ipv6: Some(IpNetwork::new(
|
guest_ipv6: Some(IpNetwork::new(
|
||||||
IpAddr::V6(guest_ipv6),
|
IpAddr::V6(guest_ipv6),
|
||||||
ipv6_network_mask as u8,
|
ipv6_network_mask as u8,
|
||||||
)?),
|
)?),
|
||||||
|
guest_mac: Some(guest_mac_string.clone()),
|
||||||
|
gateway_ipv4: Some(IpNetwork::new(
|
||||||
|
IpAddr::V4(Ipv4Addr::from_str(gateway_ipv4)?),
|
||||||
|
ipv4_network_mask as u8,
|
||||||
|
)?),
|
||||||
|
gateway_ipv6: Some(IpNetwork::new(
|
||||||
|
IpAddr::V6(Ipv6Addr::from_str(gateway_ipv6)?),
|
||||||
|
ipv4_network_mask as u8,
|
||||||
|
)?),
|
||||||
|
gateway_mac: Some(gateway_mac_string.clone()),
|
||||||
state: GuestState { exit_code: None },
|
state: GuestState { exit_code: None },
|
||||||
}),
|
}),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
@ -45,8 +45,12 @@ pub struct GuestInfo {
|
|||||||
pub domid: u32,
|
pub domid: u32,
|
||||||
pub image: String,
|
pub image: String,
|
||||||
pub loops: Vec<ContainerLoopInfo>,
|
pub loops: Vec<ContainerLoopInfo>,
|
||||||
pub ipv4: Option<IpNetwork>,
|
pub guest_ipv4: Option<IpNetwork>,
|
||||||
pub ipv6: Option<IpNetwork>,
|
pub guest_ipv6: Option<IpNetwork>,
|
||||||
|
pub guest_mac: Option<String>,
|
||||||
|
pub gateway_ipv4: Option<IpNetwork>,
|
||||||
|
pub gateway_ipv6: Option<IpNetwork>,
|
||||||
|
pub gateway_mac: Option<String>,
|
||||||
pub state: GuestState,
|
pub state: GuestState,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,25 +134,57 @@ impl RuntimeContext {
|
|||||||
.store
|
.store
|
||||||
.read_string(&format!("{}/krata/loops", &dom_path))
|
.read_string(&format!("{}/krata/loops", &dom_path))
|
||||||
.await?;
|
.await?;
|
||||||
let ipv4 = self
|
let guest_ipv4 = self
|
||||||
.xen
|
.xen
|
||||||
.store
|
.store
|
||||||
.read_string(&format!("{}/krata/network/guest/ipv4", &dom_path))
|
.read_string(&format!("{}/krata/network/guest/ipv4", &dom_path))
|
||||||
.await?;
|
.await?;
|
||||||
let ipv6 = self
|
let guest_ipv6 = self
|
||||||
.xen
|
.xen
|
||||||
.store
|
.store
|
||||||
.read_string(&format!("{}/krata/network/guest/ipv6", &dom_path))
|
.read_string(&format!("{}/krata/network/guest/ipv6", &dom_path))
|
||||||
.await?;
|
.await?;
|
||||||
|
let guest_mac = self
|
||||||
|
.xen
|
||||||
|
.store
|
||||||
|
.read_string(&format!("{}/krata/network/guest/mac", &dom_path))
|
||||||
|
.await?;
|
||||||
|
let gateway_ipv4 = self
|
||||||
|
.xen
|
||||||
|
.store
|
||||||
|
.read_string(&format!("{}/krata/network/gateway/ipv4", &dom_path))
|
||||||
|
.await?;
|
||||||
|
let gateway_ipv6 = self
|
||||||
|
.xen
|
||||||
|
.store
|
||||||
|
.read_string(&format!("{}/krata/network/gateway/ipv6", &dom_path))
|
||||||
|
.await?;
|
||||||
|
let gateway_mac = self
|
||||||
|
.xen
|
||||||
|
.store
|
||||||
|
.read_string(&format!("{}/krata/network/gateway/mac", &dom_path))
|
||||||
|
.await?;
|
||||||
|
|
||||||
let ipv4 = if let Some(ipv4) = ipv4 {
|
let guest_ipv4 = if let Some(guest_ipv4) = guest_ipv4 {
|
||||||
IpNetwork::from_str(&ipv4).ok()
|
IpNetwork::from_str(&guest_ipv4).ok()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let ipv6 = if let Some(ipv6) = ipv6 {
|
let guest_ipv6 = if let Some(guest_ipv6) = guest_ipv6 {
|
||||||
IpNetwork::from_str(&ipv6).ok()
|
IpNetwork::from_str(&guest_ipv6).ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let gateway_ipv4 = if let Some(gateway_ipv4) = gateway_ipv4 {
|
||||||
|
IpNetwork::from_str(&gateway_ipv4).ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let gateway_ipv6 = if let Some(gateway_ipv6) = gateway_ipv6 {
|
||||||
|
IpNetwork::from_str(&gateway_ipv6).ok()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -173,8 +209,12 @@ impl RuntimeContext {
|
|||||||
domid,
|
domid,
|
||||||
image,
|
image,
|
||||||
loops,
|
loops,
|
||||||
ipv4,
|
guest_ipv4,
|
||||||
ipv6,
|
guest_ipv6,
|
||||||
|
guest_mac,
|
||||||
|
gateway_ipv4,
|
||||||
|
gateway_ipv6,
|
||||||
|
gateway_mac,
|
||||||
state,
|
state,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ build_and_run() {
|
|||||||
if [ "${KRATA_BUILD_INITRD}" = "1" ]
|
if [ "${KRATA_BUILD_INITRD}" = "1" ]
|
||||||
then
|
then
|
||||||
TARGET_ARCH="$(./hack/build/arch.sh)"
|
TARGET_ARCH="$(./hack/build/arch.sh)"
|
||||||
./hack/initrd/build.sh -q
|
./hack/initrd/build.sh ${CARGO_BUILD_FLAGS}
|
||||||
sudo cp "target/initrd/initrd-${TARGET_ARCH}" "/var/lib/krata/guest/initrd"
|
sudo cp "target/initrd/initrd-${TARGET_ARCH}" "/var/lib/krata/guest/initrd"
|
||||||
fi
|
fi
|
||||||
RUST_TARGET="$(./hack/build/target.sh)"
|
RUST_TARGET="$(./hack/build/target.sh)"
|
||||||
|
@ -17,8 +17,8 @@ message GuestSpec {
|
|||||||
GuestImageSpec image = 2;
|
GuestImageSpec image = 2;
|
||||||
uint32 vcpus = 3;
|
uint32 vcpus = 3;
|
||||||
uint64 mem = 4;
|
uint64 mem = 4;
|
||||||
repeated GuestEnvVar env = 5;
|
GuestTaskSpec task = 5;
|
||||||
repeated string run = 6;
|
repeated GuestSpecAnnotation annotations = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GuestImageSpec {
|
message GuestImageSpec {
|
||||||
@ -31,7 +31,17 @@ message GuestOciImageSpec {
|
|||||||
string image = 1;
|
string image = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GuestEnvVar {
|
message GuestTaskSpec {
|
||||||
|
repeated GuestTaskSpecEnvVar environment = 1;
|
||||||
|
repeated string command = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GuestTaskSpecEnvVar {
|
||||||
|
string key = 1;
|
||||||
|
string value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GuestSpecAnnotation {
|
||||||
string key = 1;
|
string key = 1;
|
||||||
string value = 2;
|
string value = 2;
|
||||||
}
|
}
|
||||||
@ -41,6 +51,7 @@ message GuestState {
|
|||||||
GuestNetworkState network = 2;
|
GuestNetworkState network = 2;
|
||||||
GuestExitInfo exit_info = 3;
|
GuestExitInfo exit_info = 3;
|
||||||
GuestErrorInfo error_info = 4;
|
GuestErrorInfo error_info = 4;
|
||||||
|
uint32 domid = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GuestStatus {
|
enum GuestStatus {
|
||||||
@ -54,8 +65,12 @@ enum GuestStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message GuestNetworkState {
|
message GuestNetworkState {
|
||||||
string ipv4 = 1;
|
string guest_ipv4 = 1;
|
||||||
string ipv6 = 2;
|
string guest_ipv6 = 2;
|
||||||
|
string guest_mac = 3;
|
||||||
|
string gateway_ipv4 = 4;
|
||||||
|
string gateway_ipv6 = 5;
|
||||||
|
string gateway_mac = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GuestExitInfo {
|
message GuestExitInfo {
|
||||||
|
Loading…
Reference in New Issue
Block a user