add support for multiple offers per node #9
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1184,7 +1184,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "detee-shared"
|
||||
version = "0.1.0"
|
||||
source = "git+ssh://git@gitea.detee.cloud/testnet/proto.git?branch=credits_app#01e93d3a2e4502c0e8e72026e8a1c55810961815"
|
||||
source = "git+ssh://git@gitea.detee.cloud/testnet/proto.git?branch=offers#4753a17fa29393b3f99b6dfcdcec48d935e6ebd9"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"prost",
|
||||
|
@ -37,7 +37,7 @@ detee-sgx = { git = "ssh://git@gitea.detee.cloud/testnet/detee-sgx.git", branch
|
||||
shadow-rs = { version = "1.1.1", features = ["metadata"] }
|
||||
serde_default_utils = "0.3.1"
|
||||
|
||||
detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto.git", branch = "credits_app" }
|
||||
detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto.git", branch = "offers" }
|
||||
# detee-shared = { path = "../detee-shared" }
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::u64::MAX;
|
||||
|
||||
use super::grpc::{self, proto};
|
||||
use super::{injector, Distro, Dtrfs, Error, VmSshArgs, DEFAULT_ARCHLINUX, DEFAULT_DTRFS};
|
||||
use crate::config::Config;
|
||||
@ -138,16 +140,24 @@ impl Request {
|
||||
}?;
|
||||
|
||||
let mut node_list_iter = node_list.iter();
|
||||
let mut final_request = self.calculate_vm_request(
|
||||
Config::get_detee_wallet()?,
|
||||
node_list_iter.next().ok_or(Error::NoValidNodeFound)?,
|
||||
);
|
||||
let mut final_request: proto::NewVmReq =
|
||||
proto::NewVmReq { locked_nano: MAX, ..Default::default() };
|
||||
|
||||
while let Some(node) = node_list_iter.next() {
|
||||
let new_vm_req = self.calculate_vm_request(Config::get_detee_wallet()?, node);
|
||||
for offer in node.offers.iter() {
|
||||
if let Some(new_vm_req) =
|
||||
self.calculate_vm_request(Config::get_detee_wallet()?, &node.node_pubkey, offer)
|
||||
{
|
||||
if new_vm_req.locked_nano < final_request.locked_nano {
|
||||
final_request = new_vm_req;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if final_request.node_pubkey.is_empty() {
|
||||
return Err(Error::NoValidNodeFound);
|
||||
}
|
||||
|
||||
Ok(final_request)
|
||||
}
|
||||
@ -155,10 +165,14 @@ impl Request {
|
||||
fn calculate_vm_request(
|
||||
&self,
|
||||
admin_pubkey: String,
|
||||
node: &proto::VmNodeListResp,
|
||||
) -> proto::NewVmReq {
|
||||
let memory_per_cpu = node.memory_mib / node.vcpus;
|
||||
let disk_per_cpu = node.disk_mib / node.vcpus;
|
||||
node_pubkey: &str,
|
||||
offer: &proto::VmNodeOffer,
|
||||
) -> Option<proto::NewVmReq> {
|
||||
if offer.vcpus == 0 {
|
||||
return None;
|
||||
}
|
||||
let memory_per_cpu = offer.memory_mib / offer.vcpus;
|
||||
let disk_per_cpu = offer.disk_mib / offer.vcpus;
|
||||
let mut vcpus = self.vcpus;
|
||||
if vcpus < (self.memory_gib * 1024).div_ceil(memory_per_cpu as u32) {
|
||||
vcpus = (self.memory_gib * 1024).div_ceil(memory_per_cpu as u32);
|
||||
@ -170,6 +184,13 @@ impl Request {
|
||||
let memory_mib = vcpus * memory_per_cpu as u32;
|
||||
let disk_size_mib = vcpus * disk_per_cpu as u32;
|
||||
|
||||
if memory_mib > offer.memory_mib as u32
|
||||
|| disk_size_mib > offer.disk_mib as u32
|
||||
|| vcpus > offer.vcpus as u32
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let (extra_ports, public_ipv4): (Vec<u32>, bool) = match &self.ipv4 {
|
||||
IPv4Config::PublishPorts(vec) => (vec.to_vec(), false),
|
||||
IPv4Config::PublicIPv4 => (Vec::new(), true),
|
||||
@ -190,14 +211,14 @@ impl Request {
|
||||
disk_size_mib,
|
||||
public_ipv4,
|
||||
self.hours,
|
||||
node.price,
|
||||
offer.price,
|
||||
);
|
||||
|
||||
let brain_req = proto::NewVmReq {
|
||||
uuid: String::new(),
|
||||
hostname: self.hostname.clone(),
|
||||
admin_pubkey,
|
||||
node_pubkey: node.node_pubkey.clone(),
|
||||
node_pubkey: node_pubkey.to_string(),
|
||||
extra_ports,
|
||||
public_ipv4,
|
||||
public_ipv6: self.public_ipv6,
|
||||
@ -208,15 +229,15 @@ impl Request {
|
||||
kernel_sha,
|
||||
dtrfs_url,
|
||||
dtrfs_sha,
|
||||
price_per_unit: node.price,
|
||||
price_per_unit: offer.price,
|
||||
locked_nano: nanocredits,
|
||||
};
|
||||
|
||||
info!(
|
||||
"Node {} can offer the VM at {} nanocredits for {} hours. Spec: {} vCPUs, {} MiB mem, {} MiB disk.",
|
||||
node.ip, brain_req.locked_nano, self.hours, brain_req.vcpus, brain_req.memory_mib, brain_req.disk_size_mib
|
||||
node_pubkey, brain_req.locked_nano, self.hours, brain_req.vcpus, brain_req.memory_mib, brain_req.disk_size_mib
|
||||
);
|
||||
|
||||
brain_req
|
||||
Some(brain_req)
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,15 @@ impl crate::HumanOutput for VmNodeListResp {
|
||||
"This node is located in the city {}, within the region of {}, in {}",
|
||||
self.city, self.region, self.country
|
||||
);
|
||||
println!("The price multiplier for the node is {}.", self.price);
|
||||
if self.offers.len() > 0 {
|
||||
println!("The node is offering the following offers:");
|
||||
}
|
||||
for offer in self.offers.iter() {
|
||||
println!(
|
||||
" - {} vcpus, {} MiB of memory, {} MiB of storage at a price per unit of {}",
|
||||
offer.vcpus, offer.memory_mib, offer.disk_mib, offer.price
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,17 +248,27 @@ pub struct TabledVmNode {
|
||||
|
||||
impl From<proto::VmNodeListResp> for TabledVmNode {
|
||||
fn from(brain_node: proto::VmNodeListResp) -> Self {
|
||||
let (mut vcpus, mut memory_mib, mut disk_mib): (u64, u64, u64) = (0, 0, 0);
|
||||
let mut price = 0;
|
||||
for offer in brain_node.offers.iter() {
|
||||
vcpus = vcpus.saturating_add(offer.vcpus);
|
||||
memory_mib = memory_mib.saturating_add(offer.memory_mib);
|
||||
disk_mib = disk_mib.saturating_add(offer.disk_mib);
|
||||
if offer.price > price {
|
||||
price = offer.price;
|
||||
}
|
||||
}
|
||||
Self {
|
||||
operator: brain_node.operator,
|
||||
location: brain_node.city + ", " + &brain_node.region + ", " + &brain_node.country,
|
||||
main_ip: brain_node.ip,
|
||||
price: format!("{} nano/min", brain_node.price),
|
||||
price: format!("{} nano/min", price),
|
||||
reports: brain_node.reports.len(),
|
||||
vcpus: brain_node.vcpus,
|
||||
memory_mib: brain_node.memory_mib,
|
||||
disk_mib: brain_node.disk_mib,
|
||||
public_ipv4: brain_node.public_ipv4,
|
||||
public_ipv6: brain_node.public_ipv6,
|
||||
vcpus,
|
||||
memory_mib,
|
||||
disk_mib,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -426,16 +436,20 @@ pub fn print_node_offers(location: Location) -> Result<Vec<NodeOffer>, Error> {
|
||||
let node_list = block_on(grpc::get_node_list(req))?;
|
||||
let mut offers: Vec<NodeOffer> = Vec::new();
|
||||
for node in node_list.iter() {
|
||||
let mem_per_cpu = node.memory_mib / node.vcpus;
|
||||
let disk_per_cpu = node.disk_mib / node.vcpus;
|
||||
for i in 1..node.vcpus {
|
||||
for offer in node.offers.iter() {
|
||||
if offer.vcpus == 0 || offer.memory_mib == 0 || offer.disk_mib == 0 {
|
||||
continue;
|
||||
}
|
||||
let mem_per_cpu = offer.memory_mib / offer.vcpus;
|
||||
let disk_per_cpu = offer.disk_mib / offer.vcpus;
|
||||
for i in 1..offer.vcpus + 1 {
|
||||
let price_per_month = calculate_nanocredits(
|
||||
(node.vcpus * i) as u32,
|
||||
i as u32,
|
||||
(mem_per_cpu * i) as u32,
|
||||
(disk_per_cpu * i) as u32,
|
||||
false,
|
||||
732,
|
||||
node.price,
|
||||
offer.price,
|
||||
) as f64
|
||||
/ 1_000_000_000_f64;
|
||||
let price_per_hour = price_per_month / 732_f64;
|
||||
@ -453,6 +467,7 @@ pub fn print_node_offers(location: Location) -> Result<Vec<NodeOffer>, Error> {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
offers.sort_by_key(|n| n.cost_m as u64);
|
||||
Ok(offers)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user