krata: api cleanup and improvements

This commit is contained in:
Alex Zenla 2024-03-24 05:25:48 +00:00
parent 7543fccfaf
commit cb6839b0f6
No known key found for this signature in database
GPG Key ID: 067B238899B51269
7 changed files with 99 additions and 69 deletions

View File

@ -1,13 +1,24 @@
syntax = "proto3"; syntax = "proto3";
package krata.common;
option java_multiple_files = true; option java_multiple_files = true;
option java_package = "dev.krata.proto.common"; option java_package = "dev.krata.proto.common";
option java_outer_classname = "CommonProto"; option java_outer_classname = "CommonProto";
package krata.common; message Guest {
string id = 1;
GuestSpec spec = 2;
GuestState state = 3;
}
message GuestOciImageSpec { message GuestSpec {
string image = 1; string name = 1;
GuestImageSpec image = 2;
uint32 vcpus = 3;
uint64 mem = 4;
repeated GuestEnvVar env = 5;
repeated string run = 6;
} }
message GuestImageSpec { message GuestImageSpec {
@ -16,13 +27,30 @@ message GuestImageSpec {
} }
} }
message GuestSpec { message GuestOciImageSpec {
string name = 1; string image = 1;
GuestImageSpec image = 2; }
uint32 vcpus = 3;
uint64 mem = 4; message GuestEnvVar {
repeated string env = 5; string key = 1;
repeated string run = 6; string value = 2;
}
message GuestState {
GuestStatus status = 1;
GuestNetworkState network = 2;
GuestExitInfo exit_info = 3;
GuestErrorInfo error_info = 4;
}
enum GuestStatus {
GUEST_STATUS_UNKNOWN = 0;
GUEST_STATUS_STARTING = 1;
GUEST_STATUS_STARTED = 2;
GUEST_STATUS_EXITED = 3;
GUEST_STATUS_DESTROYING = 4;
GUEST_STATUS_DESTROYED = 5;
GUEST_STATUS_FAILED = 6;
} }
message GuestNetworkState { message GuestNetworkState {
@ -37,26 +65,3 @@ message GuestExitInfo {
message GuestErrorInfo { message GuestErrorInfo {
string message = 1; string message = 1;
} }
enum GuestStatus {
GUEST_STATUS_UNKNOWN = 0;
GUEST_STATUS_STARTING = 1;
GUEST_STATUS_STARTED = 2;
GUEST_STATUS_EXITED = 3;
GUEST_STATUS_DESTROYING = 4;
GUEST_STATUS_DESTROYED = 5;
GUEST_STATUS_FAILED = 6;
}
message GuestState {
GuestStatus status = 1;
GuestNetworkState network = 2;
GuestExitInfo exit_info = 3;
GuestErrorInfo error_info = 4;
}
message Guest {
string id = 1;
GuestSpec spec = 2;
GuestState state = 3;
}

View File

@ -1,13 +1,22 @@
syntax = "proto3"; syntax = "proto3";
package krata.control;
option java_multiple_files = true; option java_multiple_files = true;
option java_package = "dev.krata.proto.control"; option java_package = "dev.krata.proto.control";
option java_outer_classname = "ControlProto"; option java_outer_classname = "ControlProto";
package krata.control;
import "krata/common.proto"; import "krata/common.proto";
service ControlService {
rpc CreateGuest(CreateGuestRequest) returns (CreateGuestReply);
rpc DestroyGuest(DestroyGuestRequest) returns (DestroyGuestReply);
rpc ResolveGuest(ResolveGuestRequest) returns (ResolveGuestReply);
rpc ListGuests(ListGuestsRequest) returns (ListGuestsReply);
rpc ConsoleData(stream ConsoleDataRequest) returns (stream ConsoleDataReply);
rpc WatchEvents(WatchEventsRequest) returns (stream WatchEventsReply);
}
message CreateGuestRequest { message CreateGuestRequest {
krata.common.GuestSpec spec = 1; krata.common.GuestSpec spec = 1;
} }
@ -16,12 +25,12 @@ message CreateGuestReply {
string guest_id = 1; string guest_id = 1;
} }
message ListGuestsRequest {} message DestroyGuestRequest {
string guest_id = 1;
message ListGuestsReply {
repeated krata.common.Guest guests = 1;
} }
message DestroyGuestReply {}
message ResolveGuestRequest { message ResolveGuestRequest {
string name = 1; string name = 1;
} }
@ -30,11 +39,11 @@ message ResolveGuestReply {
krata.common.Guest guest = 1; krata.common.Guest guest = 1;
} }
message DestroyGuestRequest { message ListGuestsRequest {}
string guest_id = 1;
}
message DestroyGuestReply {} message ListGuestsReply {
repeated krata.common.Guest guests = 1;
}
message ConsoleDataRequest { message ConsoleDataRequest {
string guest_id = 1; string guest_id = 1;
@ -47,21 +56,12 @@ message ConsoleDataReply {
message WatchEventsRequest {} message WatchEventsRequest {}
message GuestChangedEvent {
krata.common.Guest guest = 1;
}
message WatchEventsReply { message WatchEventsReply {
oneof event { oneof event {
GuestChangedEvent guest_changed = 1; GuestChangedEvent guest_changed = 1;
} }
} }
service ControlService { message GuestChangedEvent {
rpc CreateGuest(CreateGuestRequest) returns (CreateGuestReply); krata.common.Guest guest = 1;
rpc DestroyGuest(DestroyGuestRequest) returns (DestroyGuestReply);
rpc ListGuests(ListGuestsRequest) returns (ListGuestsReply);
rpc ResolveGuest(ResolveGuestRequest) returns (ResolveGuestReply);
rpc ConsoleData(stream ConsoleDataRequest) returns (stream ConsoleDataReply);
rpc WatchEvents(WatchEventsRequest) returns (stream WatchEventsReply);
} }

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -28,6 +30,6 @@ pub struct LaunchNetwork {
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct LaunchInfo { pub struct LaunchInfo {
pub network: Option<LaunchNetwork>, pub network: Option<LaunchNetwork>,
pub env: Option<Vec<String>>, pub env: HashMap<String, String>,
pub run: Option<Vec<String>>, pub run: Option<Vec<String>>,
} }

View File

@ -1,7 +1,12 @@
use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
use krata::{ use krata::{
common::{guest_image_spec::Image, GuestImageSpec, GuestOciImageSpec, GuestSpec, GuestStatus}, common::{
guest_image_spec::Image, GuestEnvVar, GuestImageSpec, GuestOciImageSpec, GuestSpec,
GuestStatus,
},
control::{ control::{
control_service_client::ControlServiceClient, watch_events_reply::Event, CreateGuestRequest, control_service_client::ControlServiceClient, watch_events_reply::Event, CreateGuestRequest,
}, },
@ -46,7 +51,13 @@ impl LauchCommand {
}), }),
vcpus: self.cpus, vcpus: self.cpus,
mem: self.mem, mem: self.mem,
env: self.env.unwrap_or_default(), env: env_map(&self.env.unwrap_or_default())
.iter()
.map(|(key, value)| GuestEnvVar {
key: key.clone(),
value: value.clone(),
})
.collect(),
run: self.run, run: self.run,
}), }),
}; };
@ -121,3 +132,13 @@ async fn wait_guest_started(id: &str, events: EventStream) -> Result<()> {
} }
Ok(()) Ok(())
} }
fn env_map(env: &[String]) -> HashMap<String, String> {
let mut map = HashMap::<String, String>::new();
for item in env {
if let Some((key, value)) = item.split_once('=') {
map.insert(key.to_string(), value.to_string());
}
}
map
}

View File

@ -1,4 +1,4 @@
use std::time::Duration; use std::{collections::HashMap, time::Duration};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use krata::{ use krata::{
@ -199,7 +199,11 @@ impl GuestReconciler {
image: &oci.image, image: &oci.image,
vcpus: spec.vcpus, vcpus: spec.vcpus,
mem: spec.mem, mem: spec.mem,
env: empty_vec_optional(spec.env.clone()), env: spec
.env
.iter()
.map(|x| (x.key.clone(), x.value.clone()))
.collect::<HashMap<_, _>>(),
run: empty_vec_optional(spec.run.clone()), run: empty_vec_optional(spec.run.clone()),
debug: false, debug: false,
}) })

View File

@ -405,17 +405,14 @@ impl GuestInit {
let path = cmd.remove(0); let path = cmd.remove(0);
let mut env = vec!["KRATA_CONTAINER=1".to_string(), "TERM=vt100".to_string()]; let mut env = HashMap::new();
if let Some(config_env) = config.env() { if let Some(config_env) = config.env() {
env.extend_from_slice(config_env); env.extend(GuestInit::env_map(config_env));
} }
env.extend(launch.env.clone());
env.insert("KRATA_CONTAINER".to_string(), "1".to_string());
env.insert("TERM".to_string(), "vt100".to_string());
if let Some(extra_env) = &launch.env {
env.extend_from_slice(extra_env.as_slice());
}
let env = GuestInit::env_map(env);
let path = GuestInit::resolve_executable(&env, path.into())?; let path = GuestInit::resolve_executable(&env, path.into())?;
let Some(file_name) = path.file_name() else { let Some(file_name) = path.file_name() else {
return Err(anyhow!("cannot get file name of command path")); return Err(anyhow!("cannot get file name of command path"));
@ -453,7 +450,7 @@ impl GuestInit {
Ok(results) Ok(results)
} }
fn env_map(env: Vec<String>) -> HashMap<String, String> { fn env_map(env: &[String]) -> HashMap<String, String> {
let mut map = HashMap::<String, String>::new(); let mut map = HashMap::<String, String>::new();
for item in env { for item in env {
if let Some((key, value)) = item.split_once('=') { if let Some((key, value)) = item.split_once('=') {

View File

@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::net::IpAddr; use std::net::IpAddr;
use std::{fs, net::Ipv4Addr, str::FromStr}; use std::{fs, net::Ipv4Addr, str::FromStr};
@ -27,7 +28,7 @@ pub struct GuestLaunchRequest<'a> {
pub image: &'a str, pub image: &'a str,
pub vcpus: u32, pub vcpus: u32,
pub mem: u64, pub mem: u64,
pub env: Option<Vec<String>>, pub env: HashMap<String, String>,
pub run: Option<Vec<String>>, pub run: Option<Vec<String>>,
pub debug: bool, pub debug: bool,
} }