mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 21:00:55 +00:00
daemon: rework to not use protobuf inside the crate
This commit is contained in:
parent
660b555be7
commit
71dcaa7b77
@ -16,7 +16,7 @@ members = [
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.0.2"
|
version = "0.0.3"
|
||||||
homepage = "https://krata.dev"
|
homepage = "https://krata.dev"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
repository = "https://github.com/edera-dev/krata"
|
repository = "https://github.com/edera-dev/krata"
|
||||||
|
@ -16,7 +16,7 @@ cli-tables = { workspace = true }
|
|||||||
crossterm = { workspace = true }
|
crossterm = { workspace = true }
|
||||||
ctrlc = { workspace = true, features = ["termination"] }
|
ctrlc = { workspace = true, features = ["termination"] }
|
||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
krata = { path = "../krata", version = "0.0.2" }
|
krata = { path = "../krata", version = "0.0.3" }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
prost-reflect = { workspace = true, features = ["serde"] }
|
prost-reflect = { workspace = true, features = ["serde"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
@ -16,8 +16,8 @@ bytes = { workspace = true }
|
|||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
krata = { path = "../krata", version = "0.0.2" }
|
krata = { path = "../krata", version = "0.0.3" }
|
||||||
krata-runtime = { path = "../runtime", version = "0.0.2" }
|
krata-runtime = { path = "../runtime", version = "0.0.3" }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
prost = { workspace = true }
|
prost = { workspace = true }
|
||||||
redb = { workspace = true }
|
redb = { workspace = true }
|
||||||
@ -33,6 +33,3 @@ name = "kratad"
|
|||||||
[[bin]]
|
[[bin]]
|
||||||
name = "kratad"
|
name = "kratad"
|
||||||
path = "bin/daemon.rs"
|
path = "bin/daemon.rs"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = { workspace = true }
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
use std::io::Result;
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
prost_build::Config::new()
|
|
||||||
.extern_path(".krata.v1.common", "::krata::v1::common")
|
|
||||||
.compile_protos(&["proto/kratad/db.proto"], &["proto/", "../krata/proto"])?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package kratad.db;
|
|
||||||
|
|
||||||
import "krata/v1/common.proto";
|
|
||||||
|
|
||||||
message GuestEntry {
|
|
||||||
string id = 1;
|
|
||||||
krata.v1.common.Guest guest = 2;
|
|
||||||
}
|
|
@ -21,10 +21,7 @@ use tokio_stream::StreamExt;
|
|||||||
use tonic::{Request, Response, Status, Streaming};
|
use tonic::{Request, Response, Status, Streaming};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{db::GuestStore, event::DaemonEventContext};
|
||||||
db::{proto::GuestEntry, GuestStore},
|
|
||||||
event::DaemonEventContext,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ApiError {
|
pub struct ApiError {
|
||||||
message: String,
|
message: String,
|
||||||
@ -96,19 +93,16 @@ impl ControlService for RuntimeControlService {
|
|||||||
self.guests
|
self.guests
|
||||||
.update(
|
.update(
|
||||||
uuid,
|
uuid,
|
||||||
GuestEntry {
|
Guest {
|
||||||
id: uuid.to_string(),
|
id: uuid.to_string(),
|
||||||
guest: Some(Guest {
|
state: Some(GuestState {
|
||||||
id: uuid.to_string(),
|
status: GuestStatus::Starting.into(),
|
||||||
state: Some(GuestState {
|
network: None,
|
||||||
status: GuestStatus::Starting.into(),
|
exit_info: None,
|
||||||
network: None,
|
error_info: None,
|
||||||
exit_info: None,
|
domid: u32::MAX,
|
||||||
error_info: None,
|
|
||||||
domid: u32::MAX,
|
|
||||||
}),
|
|
||||||
spec: Some(spec),
|
|
||||||
}),
|
}),
|
||||||
|
spec: Some(spec),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -132,13 +126,7 @@ impl ControlService for RuntimeControlService {
|
|||||||
let uuid = Uuid::from_str(&request.guest_id).map_err(|error| ApiError {
|
let uuid = Uuid::from_str(&request.guest_id).map_err(|error| ApiError {
|
||||||
message: error.to_string(),
|
message: error.to_string(),
|
||||||
})?;
|
})?;
|
||||||
let Some(mut entry) = self.guests.read(uuid).await.map_err(ApiError::from)? else {
|
let Some(mut guest) = self.guests.read(uuid).await.map_err(ApiError::from)? else {
|
||||||
return Err(ApiError {
|
|
||||||
message: "guest not found".to_string(),
|
|
||||||
}
|
|
||||||
.into());
|
|
||||||
};
|
|
||||||
let Some(ref mut guest) = entry.guest else {
|
|
||||||
return Err(ApiError {
|
return Err(ApiError {
|
||||||
message: "guest not found".to_string(),
|
message: "guest not found".to_string(),
|
||||||
}
|
}
|
||||||
@ -156,7 +144,7 @@ impl ControlService for RuntimeControlService {
|
|||||||
|
|
||||||
guest.state.as_mut().unwrap().status = GuestStatus::Destroying.into();
|
guest.state.as_mut().unwrap().status = GuestStatus::Destroying.into();
|
||||||
self.guests
|
self.guests
|
||||||
.update(uuid, entry)
|
.update(uuid, guest)
|
||||||
.await
|
.await
|
||||||
.map_err(ApiError::from)?;
|
.map_err(ApiError::from)?;
|
||||||
self.guest_reconciler_notify
|
self.guest_reconciler_notify
|
||||||
@ -174,10 +162,7 @@ impl ControlService for RuntimeControlService {
|
|||||||
) -> Result<Response<ListGuestsReply>, Status> {
|
) -> Result<Response<ListGuestsReply>, Status> {
|
||||||
let _ = request.into_inner();
|
let _ = request.into_inner();
|
||||||
let guests = self.guests.list().await.map_err(ApiError::from)?;
|
let guests = self.guests.list().await.map_err(ApiError::from)?;
|
||||||
let guests = guests
|
let guests = guests.into_values().collect::<Vec<Guest>>();
|
||||||
.into_values()
|
|
||||||
.filter_map(|entry| entry.guest)
|
|
||||||
.collect::<Vec<Guest>>();
|
|
||||||
Ok(Response::new(ListGuestsReply { guests }))
|
Ok(Response::new(ListGuestsReply { guests }))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +174,6 @@ impl ControlService for RuntimeControlService {
|
|||||||
let guests = self.guests.list().await.map_err(ApiError::from)?;
|
let guests = self.guests.list().await.map_err(ApiError::from)?;
|
||||||
let guests = guests
|
let guests = guests
|
||||||
.into_values()
|
.into_values()
|
||||||
.filter_map(|entry| entry.guest)
|
|
||||||
.filter(|x| {
|
.filter(|x| {
|
||||||
let comparison_spec = x.spec.as_ref().cloned().unwrap_or_default();
|
let comparison_spec = x.spec.as_ref().cloned().unwrap_or_default();
|
||||||
(!request.name.is_empty() && comparison_spec.name == request.name)
|
(!request.name.is_empty() && comparison_spec.name == request.name)
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
pub mod proto;
|
|
||||||
|
|
||||||
use std::{collections::HashMap, path::Path, sync::Arc};
|
use std::{collections::HashMap, path::Path, sync::Arc};
|
||||||
|
|
||||||
use self::proto::GuestEntry;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use krata::v1::common::Guest;
|
||||||
use log::error;
|
use log::error;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use redb::{Database, ReadableTable, TableDefinition};
|
use redb::{Database, ReadableTable, TableDefinition};
|
||||||
@ -27,24 +25,24 @@ impl GuestStore {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read(&self, id: Uuid) -> Result<Option<GuestEntry>> {
|
pub async fn read(&self, id: Uuid) -> Result<Option<Guest>> {
|
||||||
let read = self.database.begin_read()?;
|
let read = self.database.begin_read()?;
|
||||||
let table = read.open_table(GUESTS)?;
|
let table = read.open_table(GUESTS)?;
|
||||||
let Some(entry) = table.get(id.to_u128_le())? else {
|
let Some(entry) = table.get(id.to_u128_le())? else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let bytes = entry.value();
|
let bytes = entry.value();
|
||||||
Ok(Some(GuestEntry::decode(bytes)?))
|
Ok(Some(Guest::decode(bytes)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list(&self) -> Result<HashMap<Uuid, GuestEntry>> {
|
pub async fn list(&self) -> Result<HashMap<Uuid, Guest>> {
|
||||||
let mut guests: HashMap<Uuid, GuestEntry> = HashMap::new();
|
let mut guests: HashMap<Uuid, Guest> = HashMap::new();
|
||||||
let read = self.database.begin_read()?;
|
let read = self.database.begin_read()?;
|
||||||
let table = read.open_table(GUESTS)?;
|
let table = read.open_table(GUESTS)?;
|
||||||
for result in table.iter()? {
|
for result in table.iter()? {
|
||||||
let (key, value) = result?;
|
let (key, value) = result?;
|
||||||
let uuid = Uuid::from_u128_le(key.value());
|
let uuid = Uuid::from_u128_le(key.value());
|
||||||
let state = match GuestEntry::decode(value.value()) {
|
let state = match Guest::decode(value.value()) {
|
||||||
Ok(state) => state,
|
Ok(state) => state,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
error!(
|
error!(
|
||||||
@ -59,7 +57,7 @@ impl GuestStore {
|
|||||||
Ok(guests)
|
Ok(guests)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update(&self, id: Uuid, entry: GuestEntry) -> Result<()> {
|
pub async fn update(&self, id: Uuid, entry: Guest) -> Result<()> {
|
||||||
let write = self.database.begin_write()?;
|
let write = self.database.begin_write()?;
|
||||||
{
|
{
|
||||||
let mut table = write.open_table(GUESTS)?;
|
let mut table = write.open_table(GUESTS)?;
|
@ -1 +0,0 @@
|
|||||||
include!(concat!(env!("OUT_DIR"), "/kratad.db.rs"));
|
|
@ -124,11 +124,7 @@ impl DaemonEventGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_exit_code(&mut self, id: Uuid, code: i32) -> Result<()> {
|
async fn handle_exit_code(&mut self, id: Uuid, code: i32) -> Result<()> {
|
||||||
if let Some(mut entry) = self.guests.read(id).await? {
|
if let Some(mut guest) = self.guests.read(id).await? {
|
||||||
let Some(ref mut guest) = entry.guest else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
guest.state = Some(GuestState {
|
guest.state = Some(GuestState {
|
||||||
status: GuestStatus::Exited.into(),
|
status: GuestStatus::Exited.into(),
|
||||||
network: guest.state.clone().unwrap_or_default().network,
|
network: guest.state.clone().unwrap_or_default().network,
|
||||||
@ -137,7 +133,7 @@ impl DaemonEventGenerator {
|
|||||||
domid: guest.state.clone().map(|x| x.domid).unwrap_or(u32::MAX),
|
domid: guest.state.clone().map(|x| x.domid).unwrap_or(u32::MAX),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.guests.update(id, entry).await?;
|
self.guests.update(id, guest).await?;
|
||||||
self.guest_reconciler_notify.send(id).await?;
|
self.guest_reconciler_notify.send(id).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -67,12 +67,7 @@ impl GuestReconciler {
|
|||||||
trace!("reconciling runtime");
|
trace!("reconciling runtime");
|
||||||
let runtime_guests = self.runtime.list().await?;
|
let runtime_guests = self.runtime.list().await?;
|
||||||
let stored_guests = self.guests.list().await?;
|
let stored_guests = self.guests.list().await?;
|
||||||
for (uuid, mut stored_guest_entry) in stored_guests {
|
for (uuid, mut stored_guest) in stored_guests {
|
||||||
let Some(ref mut stored_guest) = stored_guest_entry.guest else {
|
|
||||||
warn!("removing unpopulated guest entry for guest {}", uuid);
|
|
||||||
self.guests.remove(uuid).await?;
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let previous_guest = stored_guest.clone();
|
let previous_guest = stored_guest.clone();
|
||||||
let runtime_guest = runtime_guests.iter().find(|x| x.uuid == uuid);
|
let runtime_guest = runtime_guests.iter().find(|x| x.uuid == uuid);
|
||||||
match runtime_guest {
|
match runtime_guest {
|
||||||
@ -97,10 +92,10 @@ impl GuestReconciler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let changed = *stored_guest != previous_guest;
|
let changed = stored_guest != previous_guest;
|
||||||
|
|
||||||
if changed || initial {
|
if changed || initial {
|
||||||
self.guests.update(uuid, stored_guest_entry).await?;
|
self.guests.update(uuid, stored_guest).await?;
|
||||||
if let Err(error) = self.reconcile(uuid).await {
|
if let Err(error) = self.reconcile(uuid).await {
|
||||||
error!("failed to reconcile guest {}: {}", uuid, error);
|
error!("failed to reconcile guest {}: {}", uuid, error);
|
||||||
}
|
}
|
||||||
@ -110,7 +105,7 @@ impl GuestReconciler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn reconcile(&self, uuid: Uuid) -> Result<()> {
|
pub async fn reconcile(&self, uuid: Uuid) -> Result<()> {
|
||||||
let Some(mut entry) = self.guests.read(uuid).await? else {
|
let Some(mut guest) = self.guests.read(uuid).await? else {
|
||||||
warn!(
|
warn!(
|
||||||
"notified of reconcile for guest {} but it didn't exist",
|
"notified of reconcile for guest {} but it didn't exist",
|
||||||
uuid
|
uuid
|
||||||
@ -120,18 +115,14 @@ impl GuestReconciler {
|
|||||||
|
|
||||||
info!("reconciling guest {}", uuid);
|
info!("reconciling guest {}", uuid);
|
||||||
|
|
||||||
let Some(ref mut guest) = entry.guest else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
self.events
|
self.events
|
||||||
.send(DaemonEvent::GuestChanged(GuestChangedEvent {
|
.send(DaemonEvent::GuestChanged(GuestChangedEvent {
|
||||||
guest: Some(guest.clone()),
|
guest: Some(guest.clone()),
|
||||||
}))?;
|
}))?;
|
||||||
|
|
||||||
let result = match guest.state.as_ref().map(|x| x.status()).unwrap_or_default() {
|
let result = match guest.state.as_ref().map(|x| x.status()).unwrap_or_default() {
|
||||||
GuestStatus::Starting => self.start(uuid, guest).await,
|
GuestStatus::Starting => self.start(uuid, &mut guest).await,
|
||||||
GuestStatus::Destroying | GuestStatus::Exited => self.destroy(uuid, guest).await,
|
GuestStatus::Destroying | GuestStatus::Exited => self.destroy(uuid, &mut guest).await,
|
||||||
_ => Ok(false),
|
_ => Ok(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -160,7 +151,7 @@ impl GuestReconciler {
|
|||||||
if destroyed {
|
if destroyed {
|
||||||
self.guests.remove(uuid).await?;
|
self.guests.remove(uuid).await?;
|
||||||
} else {
|
} else {
|
||||||
self.guests.update(uuid, entry.clone()).await?;
|
self.guests.update(uuid, guest.clone()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.events.send(event)?;
|
self.events.send(event)?;
|
||||||
|
@ -13,8 +13,8 @@ anyhow = { workspace = true }
|
|||||||
env_logger = { workspace = true }
|
env_logger = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
ipnetwork = { workspace = true }
|
ipnetwork = { workspace = true }
|
||||||
krata = { path = "../krata", version = "0.0.2" }
|
krata = { path = "../krata", version = "0.0.3" }
|
||||||
krata-xenstore = { path = "../xen/xenstore", version = "0.0.2" }
|
krata-xenstore = { path = "../xen/xenstore", version = "0.0.3" }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
nix = { workspace = true, features = ["ioctl", "process", "fs"] }
|
nix = { workspace = true, features = ["ioctl", "process", "fs"] }
|
||||||
|
@ -16,7 +16,7 @@ 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", version = "0.0.2" }
|
krata = { path = "../krata", version = "0.0.3" }
|
||||||
krata-advmac = { workspace = true }
|
krata-advmac = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
@ -12,18 +12,18 @@ resolver = "2"
|
|||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
backhand = { workspace = true }
|
backhand = { workspace = true }
|
||||||
ipnetwork = { workspace = true }
|
ipnetwork = { workspace = true }
|
||||||
krata = { path = "../krata", version = "0.0.2" }
|
krata = { path = "../krata", version = "0.0.3" }
|
||||||
krata-advmac = { workspace = true }
|
krata-advmac = { workspace = true }
|
||||||
krata-oci = { path = "../oci", version = "0.0.2" }
|
krata-oci = { path = "../oci", version = "0.0.3" }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
loopdev-3 = { workspace = true }
|
loopdev-3 = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
uuid = { workspace = true }
|
uuid = { workspace = true }
|
||||||
krata-xenclient = { path = "../xen/xenclient", version = "0.0.2" }
|
krata-xenclient = { path = "../xen/xenclient", version = "0.0.3" }
|
||||||
krata-xenevtchn = { path = "../xen/xenevtchn", version = "0.0.2" }
|
krata-xenevtchn = { path = "../xen/xenevtchn", version = "0.0.3" }
|
||||||
krata-xengnt = { path = "../xen/xengnt", version = "0.0.2" }
|
krata-xengnt = { path = "../xen/xengnt", version = "0.0.3" }
|
||||||
krata-xenstore = { path = "../xen/xenstore", version = "0.0.2" }
|
krata-xenstore = { path = "../xen/xenstore", version = "0.0.3" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "kratart"
|
name = "kratart"
|
||||||
|
@ -13,8 +13,8 @@ elf = { workspace = true }
|
|||||||
flate2 = { workspace = true }
|
flate2 = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
krata-xencall = { path = "../xencall", version = "0.0.2" }
|
krata-xencall = { path = "../xencall", version = "0.0.3" }
|
||||||
krata-xenstore = { path = "../xenstore", version = "0.0.2" }
|
krata-xenstore = { path = "../xenstore", version = "0.0.3" }
|
||||||
memchr = { workspace = true }
|
memchr = { workspace = true }
|
||||||
slice-copy = { workspace = true }
|
slice-copy = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
|
Loading…
Reference in New Issue
Block a user