features: app engine #1
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3796,6 +3796,7 @@ dependencies = [
|
|||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
|
"hex",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"log",
|
"log",
|
||||||
|
@ -22,6 +22,7 @@ env_logger = "0.11.8"
|
|||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
nanoid = "0.4.0"
|
nanoid = "0.4.0"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
|
hex = "0.4.3"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
@ -17,7 +17,11 @@ async fn main() {
|
|||||||
if dotenv::from_filename("/etc/detee/brain/config.ini").is_err() {
|
if dotenv::from_filename("/etc/detee/brain/config.ini").is_err() {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
}
|
}
|
||||||
env_logger::builder().filter_level(log::LevelFilter::Debug).init();
|
env_logger::builder()
|
||||||
|
.filter_level(log::LevelFilter::Trace)
|
||||||
|
.filter_module("tungstenite", log::LevelFilter::Debug)
|
||||||
|
.filter_module("tokio_tungstenite", log::LevelFilter::Debug)
|
||||||
|
.init();
|
||||||
|
|
||||||
let db_url = std::env::var("DB_URL").expect("the environment variable DB_URL is not set");
|
let db_url = std::env::var("DB_URL").expect("the environment variable DB_URL is not set");
|
||||||
let db_user = std::env::var("DB_USER").expect("the environment variable DB_USER is not set");
|
let db_user = std::env::var("DB_USER").expect("the environment variable DB_USER is not set");
|
||||||
|
@ -32,6 +32,7 @@ pub const DELETED_VM: &str = "deleted_vm";
|
|||||||
pub const VM_CONTRACT: &str = "vm_contract";
|
pub const VM_CONTRACT: &str = "vm_contract";
|
||||||
|
|
||||||
pub const ACTIVE_APP: &str = "active_app";
|
pub const ACTIVE_APP: &str = "active_app";
|
||||||
|
pub const APP_NODE: &str = "app_node";
|
||||||
|
|
||||||
pub const ID_ALPHABET: [char; 62] = [
|
pub const ID_ALPHABET: [char; 62] = [
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::constants::{ACCOUNT, ACTIVE_APP};
|
use crate::constants::{ACCOUNT, ACTIVE_APP, APP_NODE};
|
||||||
use crate::db::general::Report;
|
use crate::db::general::Report;
|
||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
use crate::db;
|
||||||
use crate::old_brain;
|
use crate::old_brain;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use surrealdb::engine::remote::ws::Client;
|
use surrealdb::engine::remote::ws::Client;
|
||||||
@ -25,6 +26,14 @@ pub struct AppNode {
|
|||||||
pub offline_minutes: u64,
|
pub offline_minutes: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AppNode {
|
||||||
|
pub async fn register(self, db: &Surreal<Client>) -> Result<AppNode, Error> {
|
||||||
|
db::Account::get_or_create(db, &self.operator.key().to_string()).await?;
|
||||||
|
let app_node: Option<AppNode> = db.upsert(self.id.clone()).content(self).await?;
|
||||||
|
app_node.ok_or(Error::FailedToCreateDBEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct AppNodeWithReports {
|
pub struct AppNodeWithReports {
|
||||||
pub id: RecordId,
|
pub id: RecordId,
|
||||||
@ -88,6 +97,17 @@ pub struct ActiveAppWithNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveAppWithNode {
|
impl ActiveAppWithNode {
|
||||||
|
pub async fn list_by_node(db: &Surreal<Client>, node_pubkey: &str) -> Result<Vec<Self>, Error> {
|
||||||
|
let mut query_result = db
|
||||||
|
.query(format!(
|
||||||
|
"select * from {ACTIVE_APP} where out = {APP_NODE}:{node_pubkey} fetch out;"
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let contract: Vec<Self> = query_result.take(0)?;
|
||||||
|
Ok(contract)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_by_uuid(db: &Surreal<Client>, uuid: &str) -> Result<Option<Self>, Error> {
|
pub async fn get_by_uuid(db: &Surreal<Client>, uuid: &str) -> Result<Option<Self>, Error> {
|
||||||
let contract: Option<Self> =
|
let contract: Option<Self> =
|
||||||
db.query(format!("select * from {ACTIVE_APP}:{uuid} fetch out;")).await?.take(0)?;
|
db.query(format!("select * from {ACTIVE_APP}:{uuid} fetch out;")).await?.take(0)?;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::constants::{ACCOUNT, APP_NODE};
|
||||||
|
use crate::db::prelude as db;
|
||||||
use crate::grpc::{check_sig_from_parts, check_sig_from_req};
|
use crate::grpc::{check_sig_from_parts, check_sig_from_req};
|
||||||
use detee_shared::app_proto::brain_app_cli_server::BrainAppCli;
|
use detee_shared::app_proto::brain_app_cli_server::BrainAppCli;
|
||||||
use detee_shared::app_proto::brain_app_daemon_server::BrainAppDaemon;
|
use detee_shared::app_proto::brain_app_daemon_server::BrainAppDaemon;
|
||||||
@ -10,9 +12,12 @@ use log::info;
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use surrealdb::engine::remote::ws::Client;
|
use surrealdb::engine::remote::ws::Client;
|
||||||
|
use surrealdb::RecordId;
|
||||||
use surrealdb::Surreal;
|
use surrealdb::Surreal;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio_stream::wrappers::ReceiverStream;
|
||||||
use tokio_stream::{Stream, StreamExt};
|
use tokio_stream::{Stream, StreamExt};
|
||||||
use tonic::{Status, Streaming};
|
use tonic::{Response, Status, Streaming};
|
||||||
|
|
||||||
pub struct AppDaemonServer {
|
pub struct AppDaemonServer {
|
||||||
pub db: Arc<Surreal<Client>>,
|
pub db: Arc<Surreal<Client>>,
|
||||||
@ -37,7 +42,36 @@ impl BrainAppDaemon for AppDaemonServer {
|
|||||||
let req = check_sig_from_req(req)?;
|
let req = check_sig_from_req(req)?;
|
||||||
info!("Starting app_node registration process for {:?}", req);
|
info!("Starting app_node registration process for {:?}", req);
|
||||||
|
|
||||||
todo!()
|
let app_node = db::AppNode {
|
||||||
|
id: RecordId::from((APP_NODE, req.node_pubkey.clone())),
|
||||||
|
operator: RecordId::from((ACCOUNT, req.operator_wallet)),
|
||||||
|
country: req.country,
|
||||||
|
region: req.region,
|
||||||
|
city: req.city,
|
||||||
|
ip: req.main_ip,
|
||||||
|
price: req.price,
|
||||||
|
|
||||||
|
avail_mem_mb: 0,
|
||||||
|
avail_vcpus: 0,
|
||||||
|
avail_storage_gbs: 0,
|
||||||
|
avail_ports: 0,
|
||||||
|
max_ports_per_app: 0,
|
||||||
|
offline_minutes: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
app_node.register(&self.db).await?;
|
||||||
|
info!("Sending existing contracts to {}", req.node_pubkey);
|
||||||
|
|
||||||
|
let contracts = db::ActiveAppWithNode::list_by_node(&self.db, &req.node_pubkey).await?;
|
||||||
|
let (tx, rx) = mpsc::channel(6);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
for contract in contracts {
|
||||||
|
let _ = tx.send(Ok(contract.into())).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let resp_stream = ReceiverStream::new(rx);
|
||||||
|
Ok(Response::new(Box::pin(resp_stream)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn brain_messages(
|
async fn brain_messages(
|
||||||
|
@ -250,3 +250,38 @@ impl From<VmNodeResources> for db::VmNodeResources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<db::ActiveAppWithNode> for AppContract {
|
||||||
|
fn from(value: db::ActiveAppWithNode) -> Self {
|
||||||
|
let public_package_mr_enclave =
|
||||||
|
Some(hex::decode(value.mr_enclave.clone()).unwrap_or_default());
|
||||||
|
|
||||||
|
AppContract {
|
||||||
|
uuid: value.id.key().to_string(),
|
||||||
|
package_url: value.package_url,
|
||||||
|
admin_pubkey: value.admin.key().to_string(),
|
||||||
|
node_pubkey: value.app_node.id.key().to_string(),
|
||||||
|
public_ipv4: value.host_ipv4,
|
||||||
|
resource: Some(AppResource {
|
||||||
|
memory_mb: value.memory_mb as u32,
|
||||||
|
disk_mb: value.disk_size_gb as u32,
|
||||||
|
vcpu: value.vcpus as u32,
|
||||||
|
ports: value.mapped_ports.iter().map(|(_, g)| *g as u32).collect(),
|
||||||
|
}),
|
||||||
|
mapped_ports: value
|
||||||
|
.mapped_ports
|
||||||
|
.iter()
|
||||||
|
.map(|(h, g)| MappedPort { host_port: *h as u32, guest_port: *g as u32 })
|
||||||
|
.collect(),
|
||||||
|
|
||||||
|
created_at: value.created_at.to_rfc3339(),
|
||||||
|
updated_at: value.created_at.to_rfc3339(),
|
||||||
|
nano_per_minute: value.price_per_unit,
|
||||||
|
locked_nano: value.locked_nano,
|
||||||
|
collected_at: value.collected_at.to_rfc3339(),
|
||||||
|
hratls_pubkey: value.mr_enclave,
|
||||||
|
public_package_mr_enclave,
|
||||||
|
app_name: value.app_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user