refactor actor model
implementing actor model inspire from snp daemon migrated from grpc server model to grpc client model for actor and brain integration basic channel communication for actors and grpc deleted unused proto file
This commit is contained in:
parent
fd297488e2
commit
169bff5803
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -303,12 +303,14 @@ dependencies = [
|
|||||||
"detee-shared",
|
"detee-shared",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
"log",
|
||||||
"prost",
|
"prost",
|
||||||
"prost-types",
|
"prost-types",
|
||||||
"rand",
|
"rand",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"tar",
|
"tar",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tonic-build",
|
"tonic-build",
|
||||||
]
|
]
|
||||||
@ -316,7 +318,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "detee-shared"
|
name = "detee-shared"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+ssh://git@gitea.detee.cloud/noormohammedb/detee-shared#78c84299947e887fe8d8c737656318f409c7f0b4"
|
source = "git+ssh://git@gitea.detee.cloud/noormohammedb/detee-shared#3e783b11bab6894b6f98bd3c6ce44e8bf5b1f78b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"prost",
|
"prost",
|
||||||
|
@ -9,15 +9,17 @@ prost = "0.13.4"
|
|||||||
prost-types = "0.13.4"
|
prost-types = "0.13.4"
|
||||||
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread", "fs"] }
|
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread", "fs"] }
|
||||||
tonic = "0.12.3"
|
tonic = "0.12.3"
|
||||||
|
|
||||||
detee-shared = { git = "ssh://git@gitea.detee.cloud/noormohammedb/detee-shared" }
|
|
||||||
# detee-shared = { path = "../detee-shared" }
|
|
||||||
chrono = "0.4.39"
|
chrono = "0.4.39"
|
||||||
reqwest = "0.12.12"
|
reqwest = "0.12.12"
|
||||||
flate2 = "1.0.35"
|
flate2 = "1.0.35"
|
||||||
tar = "0.4.43"
|
tar = "0.4.43"
|
||||||
anyhow = "1.0.95"
|
anyhow = "1.0.95"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
tokio-stream = "0.1.17"
|
||||||
|
|
||||||
|
detee-shared = { git = "ssh://git@gitea.detee.cloud/noormohammedb/detee-shared" }
|
||||||
|
# detee-shared = { path = "../detee-shared" }
|
||||||
|
log = "0.4.25"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tonic-build = "0.12.3"
|
tonic-build = "0.12.3"
|
||||||
|
19
daemon.proto
19
daemon.proto
@ -1,19 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
package deamon;
|
|
||||||
|
|
||||||
message Empty {
|
|
||||||
}
|
|
||||||
|
|
||||||
message NewContainerReq {
|
|
||||||
repeated string port = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message NewContainerRes {
|
|
||||||
string status = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
service DaemonService {
|
|
||||||
rpc CreateContainer (NewContainerReq) returns (NewContainerRes);
|
|
||||||
// rpc ListContainer (NodeFilters) returns (stream NodeListResp);
|
|
||||||
|
|
||||||
}
|
|
219
src/grpc.rs
219
src/grpc.rs
@ -1,141 +1,102 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use detee_shared::pb::daemon::brain_sgx_daemon_client::BrainSgxDaemonClient;
|
||||||
|
use detee_shared::pb::daemon::daemon_message::Msg;
|
||||||
|
use detee_shared::pb::daemon::{BrainMessage, DaemonMessage};
|
||||||
|
use detee_shared::pb::shared::ContainerContracts;
|
||||||
|
use detee_shared::pb::shared::{Pubkey, RegisterNodeReq};
|
||||||
|
use tokio::sync::mpsc::Receiver;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
use tokio::task::JoinSet;
|
||||||
|
use tokio_stream::wrappers::ReceiverStream;
|
||||||
|
use tokio_stream::StreamExt;
|
||||||
|
use tonic::transport::Channel;
|
||||||
|
|
||||||
use std::sync::Arc;
|
pub struct ConnectionData {
|
||||||
use std::{net::SocketAddr, str::FromStr};
|
pub brain_url: String,
|
||||||
use tokio::sync::RwLock;
|
pub brain_msg_tx: Sender<BrainMessage>,
|
||||||
use tonic::transport::Server;
|
pub daemon_msg_rx: Receiver<DaemonMessage>,
|
||||||
|
pub daemon_msg_tx: Sender<DaemonMessage>,
|
||||||
use detee_shared::pb::daemon::daemon_service_server::{
|
|
||||||
DaemonService as DaemonServicePB, DaemonServiceServer as DaemonServiceServerPB,
|
|
||||||
};
|
|
||||||
use detee_shared::pb::daemon::{
|
|
||||||
ContainerFilters, ContainerInspectResp, ContainerListResp, DeleteContainerRes, NewContainerRes,
|
|
||||||
};
|
|
||||||
use detee_shared::pb::shared::Container as ContainerPB;
|
|
||||||
|
|
||||||
use detee_shared::types::shared::Container as ContainerConfig;
|
|
||||||
|
|
||||||
use crate::utils::handle_package;
|
|
||||||
use crate::DaemonState;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DaemonServer {
|
|
||||||
pub data: Arc<RwLock<DaemonState>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DaemonServer {
|
pub async fn register_node(config: &crate::Config) -> Result<Vec<ContainerContracts>> {
|
||||||
pub fn new(data: Arc<RwLock<DaemonState>>) -> Self {
|
let mut client = BrainSgxDaemonClient::connect(config.brain_url.clone()).await?;
|
||||||
Self { data }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn start(&self) -> Result<()> {
|
log::debug!("registering node with brain");
|
||||||
let port: String = std::env::var("PORT").unwrap_or_else(|_| "33400".to_string());
|
|
||||||
|
|
||||||
let addr = SocketAddr::from_str(format!("0.0.0.0:{port}").as_str())?;
|
let req = RegisterNodeReq {
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
let daemon_server = DaemonServiceServerPB::new(DaemonServer::new(self.data.clone()));
|
let mut container_contracts = vec![];
|
||||||
|
|
||||||
println!("Listening on {}", addr);
|
let mut grpc_stream = client.register_node(req).await?.into_inner();
|
||||||
|
while let Some(stream_update) = grpc_stream.next().await {
|
||||||
Server::builder()
|
match stream_update {
|
||||||
.add_service(daemon_server)
|
Ok(contract) => {
|
||||||
.serve(addr)
|
container_contracts.push(contract);
|
||||||
.await?;
|
}
|
||||||
Ok(())
|
Err(e) => {
|
||||||
}
|
println!("Brain disconnected from register_node: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
|
||||||
impl DaemonServicePB for DaemonServer {
|
|
||||||
async fn create_container(
|
|
||||||
&self,
|
|
||||||
request: tonic::Request<ContainerPB>,
|
|
||||||
) -> Result<tonic::Response<NewContainerRes>, tonic::Status> {
|
|
||||||
let req_data = request.into_inner();
|
|
||||||
|
|
||||||
if req_data.package_url.is_none() || req_data.resource.is_none() {
|
|
||||||
return Err(tonic::Status::data_loss("missing some data in request"));
|
|
||||||
}
|
}
|
||||||
let unarchive_dir = handle_package(req_data.package_url.clone().unwrap_or_default())
|
|
||||||
.await
|
|
||||||
.map_err(|err| tonic::Status::internal(err.to_string()))?;
|
|
||||||
|
|
||||||
let req_container: ContainerConfig = req_data.into();
|
|
||||||
let container_uuid = req_container.uuid.clone().unwrap_or_default().uuid;
|
|
||||||
|
|
||||||
let mapped_ports = self
|
|
||||||
.data
|
|
||||||
.write()
|
|
||||||
.await
|
|
||||||
.create_new_container(req_container, unarchive_dir)
|
|
||||||
.await
|
|
||||||
.map_err(|err| tonic::Status::internal(err.to_string()))?;
|
|
||||||
|
|
||||||
let mapped_ports = mapped_ports
|
|
||||||
.into_iter()
|
|
||||||
.map(|(host, container)| detee_shared::pb::shared::MappedPort {
|
|
||||||
host_port: host.into(),
|
|
||||||
container_port: container.into(),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
return Ok(tonic::Response::new(NewContainerRes {
|
|
||||||
container_id: Some(detee_shared::pb::shared::Uuid {
|
|
||||||
uuid: container_uuid,
|
|
||||||
}),
|
|
||||||
status: "success".to_string(),
|
|
||||||
ip_address: "".to_string(),
|
|
||||||
mapped_ports,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
log::info!(
|
||||||
|
"Brain registration succcessful, with contract count: {}",
|
||||||
|
container_contracts.len()
|
||||||
|
);
|
||||||
|
|
||||||
async fn delete_container(
|
Ok(container_contracts)
|
||||||
&self,
|
}
|
||||||
req: tonic::Request<ContainerFilters>,
|
|
||||||
) -> Result<tonic::Response<DeleteContainerRes>, tonic::Status> {
|
pub async fn connect_and_run(conn_data: ConnectionData) -> Result<()> {
|
||||||
let req_data = req.into_inner();
|
let client = BrainSgxDaemonClient::connect(conn_data.brain_url).await?;
|
||||||
if req_data.container_id.is_none() {
|
|
||||||
return Err(tonic::Status::data_loss("missing container id"));
|
let mut streaming_tasks = JoinSet::new();
|
||||||
}
|
|
||||||
self.data
|
streaming_tasks.spawn(receive_messages(client.clone(), conn_data.brain_msg_tx));
|
||||||
.write()
|
|
||||||
.await
|
let task_output = streaming_tasks.join_next().await;
|
||||||
.delete_container(
|
println!("exiting: {task_output:?}");
|
||||||
req_data.admin_pubkey,
|
Ok(())
|
||||||
req_data.container_id.unwrap_or_default().uuid,
|
}
|
||||||
)
|
|
||||||
.await
|
pub async fn receive_messages(
|
||||||
.map_err(|err| tonic::Status::internal(err.to_string()))?;
|
mut client: BrainSgxDaemonClient<Channel>,
|
||||||
|
tx: Sender<BrainMessage>,
|
||||||
return Ok(tonic::Response::new(DeleteContainerRes {
|
) -> Result<()> {
|
||||||
..Default::default()
|
let pubkey = "node_pubkey".to_owned();
|
||||||
}));
|
|
||||||
}
|
log::debug!("starting to listen for messages from brain");
|
||||||
|
let mut grpc_stream = client.brain_messages(Pubkey { pubkey }).await?.into_inner();
|
||||||
async fn inspect_container(
|
|
||||||
&self,
|
while let Some(stream_update) = grpc_stream.next().await {
|
||||||
req: tonic::Request<detee_shared::pb::shared::Uuid>,
|
match stream_update {
|
||||||
) -> Result<tonic::Response<ContainerInspectResp>, tonic::Status> {
|
Ok(msg) => {
|
||||||
dbg!(req);
|
log::info!("Received message from brain: {msg:?}");
|
||||||
return Ok(tonic::Response::new(ContainerInspectResp {
|
let _ = tx.send(msg).await?;
|
||||||
..Default::default()
|
}
|
||||||
}));
|
Err(e) => {
|
||||||
}
|
println!("Brain disconnected from brain_messaages: {e}");
|
||||||
|
}
|
||||||
// async fn container_log(
|
}
|
||||||
// &self,
|
}
|
||||||
// req: tonic::Request<detee_shared::pb::shared::Uuid>,
|
println!("brain_messages is about to exit");
|
||||||
// ) -> Result<tonic::Response<Self::ContainerLogStream>, tonic::Status> {
|
Ok(())
|
||||||
// todo!()
|
}
|
||||||
// }
|
|
||||||
|
pub async fn send_messages(
|
||||||
async fn list_containers(
|
mut client: BrainSgxDaemonClient<Channel>,
|
||||||
&self,
|
rx: Receiver<DaemonMessage>,
|
||||||
req: tonic::Request<ContainerFilters>,
|
tx: Sender<DaemonMessage>,
|
||||||
) -> Result<tonic::Response<ContainerListResp>, tonic::Status> {
|
) -> Result<()> {
|
||||||
dbg!(req);
|
let pubkey = "node_pubkey".to_owned();
|
||||||
return Ok(tonic::Response::new(ContainerListResp {
|
|
||||||
..Default::default()
|
let rx_stream = ReceiverStream::new(rx);
|
||||||
}));
|
tx.send(DaemonMessage {
|
||||||
}
|
msg: Some(Msg::Pubkey(Pubkey { pubkey })),
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
client.daemon_messages(rx_stream).await?;
|
||||||
|
log::debug!("send_newvm_resp is about to exit");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
93
src/main.rs
93
src/main.rs
@ -3,18 +3,95 @@ pub mod data;
|
|||||||
pub mod grpc;
|
pub mod grpc;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
pub use data::DaemonState;
|
use std::time::Duration;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use grpc::DaemonServer;
|
pub use data::DaemonState;
|
||||||
use tokio::sync::RwLock;
|
use detee_shared::pb::daemon::BrainMessage;
|
||||||
|
use detee_shared::pb::daemon::DaemonMessage;
|
||||||
|
use detee_shared::pb::shared::ContainerContracts;
|
||||||
|
use tokio::sync::mpsc::Receiver;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
|
pub struct Config {
|
||||||
|
pub brain_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
let brain_url =
|
||||||
|
std::env::var("BRAIN_URL").unwrap_or_else(|_| "http://127.0.0.1:31337".to_string());
|
||||||
|
Self { brain_url }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ContainerHandler {
|
||||||
|
receiver: Receiver<BrainMessage>,
|
||||||
|
sender: Sender<DaemonMessage>,
|
||||||
|
config: Config,
|
||||||
|
// res: state::Resources,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContainerHandler {
|
||||||
|
pub fn new(receiver: Receiver<BrainMessage>, sender: Sender<DaemonMessage>) -> Self {
|
||||||
|
Self {
|
||||||
|
receiver,
|
||||||
|
sender,
|
||||||
|
config: Config::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_contracts(&mut self, contracts: Vec<ContainerContracts>) -> () {
|
||||||
|
dbg!(&contracts);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run(mut self) -> () {
|
||||||
|
while let Some(brain_msg) = self.receiver.recv().await {
|
||||||
|
match brain_msg.msg {
|
||||||
|
Some(msg) => {
|
||||||
|
dbg!(&msg);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
log::error!("Brain disconnected");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!("Detee daemon");
|
println!("Detee daemon");
|
||||||
|
|
||||||
DaemonServer::new(Arc::new(RwLock::new(DaemonState::default())))
|
loop {
|
||||||
.start()
|
let (brain_msg_tx, brain_msg_rx) = tokio::sync::mpsc::channel(6);
|
||||||
.await?;
|
let (daemon_msg_tx, daemon_msg_rx) = tokio::sync::mpsc::channel(6);
|
||||||
Ok(())
|
|
||||||
|
let mut container_handler = ContainerHandler::new(brain_msg_rx, daemon_msg_tx.clone());
|
||||||
|
let brain_url = container_handler.config.brain_url.clone();
|
||||||
|
|
||||||
|
match grpc::register_node(&container_handler.config).await {
|
||||||
|
Ok(container_contracts) => container_handler.handle_contracts(container_contracts),
|
||||||
|
|
||||||
|
Err(e) => log::error!("Failed to connect to brain: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
container_handler.run().await;
|
||||||
|
});
|
||||||
|
|
||||||
|
log::info!("Connecting to brain...");
|
||||||
|
if let Err(e) = grpc::connect_and_run(grpc::ConnectionData {
|
||||||
|
brain_url,
|
||||||
|
brain_msg_tx,
|
||||||
|
daemon_msg_rx,
|
||||||
|
daemon_msg_tx,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
log::error!("The connection broke: {e}");
|
||||||
|
}
|
||||||
|
sleep(Duration::from_secs(3)).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user