forked from ghe0/brain-to-surreal
listing contracts
This commit is contained in:
parent
1cf091d801
commit
751e81ce37
91
src/db.rs
91
src/db.rs
@ -9,6 +9,10 @@ use surrealdb::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
static DB: LazyLock<Surreal<Client>> = LazyLock::new(Surreal::init);
|
static DB: LazyLock<Surreal<Client>> = LazyLock::new(Surreal::init);
|
||||||
|
const ACCOUNT: &str = "account";
|
||||||
|
const OPERATOR: &str = "operator";
|
||||||
|
const VM_CONTRACT: &str = "vm_contract";
|
||||||
|
const VM_NODE: &str = "vm_node";
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -48,7 +52,7 @@ pub async fn migration0(old_data: &old_brain::BrainData) -> surrealdb::Result<()
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn account(address: &str) -> Result<Account, Error> {
|
pub async fn account(address: &str) -> Result<Account, Error> {
|
||||||
let id = ("account", address);
|
let id = (ACCOUNT, address);
|
||||||
let account: Option<Account> = DB.select(id).await?;
|
let account: Option<Account> = DB.select(id).await?;
|
||||||
let account = match account {
|
let account = match account {
|
||||||
Some(account) => account,
|
Some(account) => account,
|
||||||
@ -59,6 +63,37 @@ pub async fn account(address: &str) -> Result<Account, Error> {
|
|||||||
Ok(account)
|
Ok(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn vm_contract_by_uuid(uuid: &str) -> Result<Option<VmContract>, Error> {
|
||||||
|
let id = (VM_CONTRACT, uuid);
|
||||||
|
let contract: Option<VmContract> = DB.select(id).await?;
|
||||||
|
Ok(contract)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn vm_contracts_by_admin(admin: &str) -> Result<Vec<VmContract>, Error> {
|
||||||
|
let mut result =
|
||||||
|
DB.query(format!("select * from {VM_CONTRACT} where in = {ACCOUNT}:{admin};")).await?;
|
||||||
|
let contracts: Vec<VmContract> = result.take(0)?;
|
||||||
|
Ok(contracts)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn vm_contracts_by_operator(operator: &str) -> Result<Vec<VmContract>, Error> {
|
||||||
|
let mut result = DB
|
||||||
|
.query(format!(
|
||||||
|
"select ->{OPERATOR}->{VM_NODE}<-{VM_CONTRACT}.* as contracts from {ACCOUNT}:{operator};"
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Wrapper {
|
||||||
|
contracts: Vec<VmContract>,
|
||||||
|
}
|
||||||
|
let c: Option<Wrapper> = result.take(0)?;
|
||||||
|
match c {
|
||||||
|
Some(c) => Ok(c.contracts),
|
||||||
|
None => Ok(Vec::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// I am not deleting this example cause I might need it later.
|
// I am not deleting this example cause I might need it later.
|
||||||
//
|
//
|
||||||
// async fn get_wallet_contracts() -> surrealdb::Result<Vec<Wallet>> {
|
// async fn get_wallet_contracts() -> surrealdb::Result<Vec<Wallet>> {
|
||||||
@ -106,26 +141,44 @@ pub struct VmNode {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct VmContract {
|
pub struct VmContract {
|
||||||
id: RecordId,
|
pub id: RecordId,
|
||||||
#[serde(rename = "in")]
|
#[serde(rename = "in")]
|
||||||
admin: RecordId,
|
pub admin: RecordId,
|
||||||
#[serde(rename = "out")]
|
#[serde(rename = "out")]
|
||||||
vm_node: RecordId,
|
pub vm_node: RecordId,
|
||||||
state: String,
|
pub state: String,
|
||||||
hostname: String,
|
pub hostname: String,
|
||||||
mapped_ports: Vec<(u32, u32)>,
|
pub mapped_ports: Vec<(u32, u32)>,
|
||||||
public_ipv4: String,
|
pub public_ipv4: String,
|
||||||
public_ipv6: String,
|
pub public_ipv6: String,
|
||||||
disk_size_gb: u32,
|
pub disk_size_gb: u32,
|
||||||
vcpus: u32,
|
pub vcpus: u32,
|
||||||
memory_mb: u32,
|
pub memory_mb: u32,
|
||||||
dtrfs_sha: String,
|
pub dtrfs_sha: String,
|
||||||
kernel_sha: String,
|
pub kernel_sha: String,
|
||||||
created_at: Datetime,
|
pub created_at: Datetime,
|
||||||
updated_at: Datetime,
|
pub updated_at: Datetime,
|
||||||
price_per_unit: u64,
|
pub price_per_unit: u64,
|
||||||
locked_nano: u64,
|
pub locked_nano: u64,
|
||||||
collected_at: Datetime,
|
pub collected_at: Datetime,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VmContract {
|
||||||
|
/// total hardware units of this VM
|
||||||
|
fn total_units(&self) -> u64 {
|
||||||
|
// TODO: Optimize this based on price of hardware.
|
||||||
|
// I tried, but this can be done better.
|
||||||
|
// Storage cost should also be based on tier
|
||||||
|
(self.vcpus as u64 * 10)
|
||||||
|
+ ((self.memory_mb + 256) as u64 / 200)
|
||||||
|
+ (self.disk_size_gb as u64 / 10)
|
||||||
|
+ (!self.public_ipv4.is_empty() as u64 * 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns price per minute in nanoLP
|
||||||
|
pub fn price_per_minute(&self) -> u64 {
|
||||||
|
self.total_units() * self.price_per_unit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
79
src/grpc.rs
79
src/grpc.rs
@ -13,6 +13,8 @@ use detee_shared::{
|
|||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio_stream::wrappers::ReceiverStream;
|
||||||
// use tokio::sync::mpsc;
|
// use tokio::sync::mpsc;
|
||||||
// use tokio_stream::{wrappers::ReceiverStream, Stream};
|
// use tokio_stream::{wrappers::ReceiverStream, Stream};
|
||||||
use tokio_stream::Stream;
|
use tokio_stream::Stream;
|
||||||
@ -26,6 +28,34 @@ impl From<db::Account> for AccountBalance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<db::VmContract> for VmContract {
|
||||||
|
fn from(contract: db::VmContract) -> Self {
|
||||||
|
let mut exposed_ports = Vec::new();
|
||||||
|
for port in contract.mapped_ports.iter() {
|
||||||
|
exposed_ports.push(port.0);
|
||||||
|
}
|
||||||
|
VmContract {
|
||||||
|
uuid: contract.id.key().to_string(),
|
||||||
|
dtrfs_sha: contract.dtrfs_sha.clone(),
|
||||||
|
kernel_sha: contract.kernel_sha.clone(),
|
||||||
|
memory_mb: contract.memory_mb,
|
||||||
|
vcpus: contract.vcpus,
|
||||||
|
created_at: contract.created_at.to_string(),
|
||||||
|
disk_size_gb: contract.disk_size_gb,
|
||||||
|
public_ipv6: contract.public_ipv6.clone(),
|
||||||
|
public_ipv4: contract.public_ipv4.clone(),
|
||||||
|
updated_at: contract.updated_at.to_string(),
|
||||||
|
exposed_ports,
|
||||||
|
node_pubkey: contract.vm_node.key().to_string(),
|
||||||
|
nano_per_minute: contract.price_per_minute(),
|
||||||
|
locked_nano: contract.locked_nano,
|
||||||
|
admin_pubkey: contract.admin.key().to_string(),
|
||||||
|
hostname: contract.hostname.clone(),
|
||||||
|
collected_at: contract.hostname.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<db::Error> for tonic::Status {
|
impl From<db::Error> for tonic::Status {
|
||||||
fn from(e: db::Error) -> Self {
|
fn from(e: db::Error) -> Self {
|
||||||
Self::internal(format!("Internal error: {e}"))
|
Self::internal(format!("Internal error: {e}"))
|
||||||
@ -281,32 +311,29 @@ impl BrainVmCli for BrainVmCliMock {
|
|||||||
"CLI {} requested ListVMVmContractsStream. As operator: {}",
|
"CLI {} requested ListVMVmContractsStream. As operator: {}",
|
||||||
req.wallet, req.as_operator
|
req.wallet, req.as_operator
|
||||||
);
|
);
|
||||||
todo!();
|
let mut contracts = Vec::new();
|
||||||
// let mut contracts = Vec::new();
|
if !req.uuid.is_empty() {
|
||||||
// if !req.uuid.is_empty() {
|
if let Some(specific_contract) = db::vm_contract_by_uuid(&req.uuid).await? {
|
||||||
// if let Ok(specific_contract) = self.data.find_contract_by_uuid(&req.uuid) {
|
if specific_contract.admin.key().to_string() == req.wallet {
|
||||||
// if specific_contract.admin_pubkey == req.wallet {
|
contracts.push(specific_contract.into());
|
||||||
// contracts.push(specific_contract);
|
}
|
||||||
// }
|
// TODO: allow operator to inspect contracts
|
||||||
// // TODO: allow operator to inspect contracts
|
}
|
||||||
// }
|
} else {
|
||||||
// } else {
|
if req.as_operator {
|
||||||
// if req.as_operator {
|
contracts.append(&mut db::vm_contracts_by_operator(&req.wallet).await?.into());
|
||||||
// contracts.append(&mut self.data.find_vm_contracts_by_operator(&req.wallet));
|
} else {
|
||||||
// } else {
|
contracts.append(&mut db::vm_contracts_by_admin(&req.wallet).await?.into());
|
||||||
// contracts.append(&mut self.data.find_vm_contracts_by_admin(&req.wallet));
|
}
|
||||||
// }
|
}
|
||||||
// }
|
let (tx, rx) = mpsc::channel(6);
|
||||||
// let (tx, rx) = mpsc::channel(6);
|
tokio::spawn(async move {
|
||||||
// tokio::spawn(async move {
|
for contract in contracts {
|
||||||
// for contract in contracts {
|
let _ = tx.send(Ok(contract.into())).await;
|
||||||
// let _ = tx.send(Ok(contract.into())).await;
|
}
|
||||||
// }
|
});
|
||||||
// });
|
let output_stream = ReceiverStream::new(rx);
|
||||||
// let output_stream = ReceiverStream::new(rx);
|
Ok(Response::new(Box::pin(output_stream) as Self::ListVmContractsStream))
|
||||||
// Ok(Response::new(
|
|
||||||
// Box::pin(output_stream) as Self::ListVmContractsStream
|
|
||||||
// ))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_vm_nodes(
|
async fn list_vm_nodes(
|
||||||
|
Loading…
Reference in New Issue
Block a user