add support for multiple offers per node
This commit is contained in:
		
							parent
							
								
									f7df59e068
								
							
						
					
					
						commit
						e799e32d37
					
				
							
								
								
									
										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,27 +140,36 @@ 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);
 | 
			
		||||
            if new_vm_req.locked_nano < final_request.locked_nano {
 | 
			
		||||
                final_request = new_vm_req;
 | 
			
		||||
            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)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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> {
 | 
			
		||||
        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 +181,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 +208,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 +226,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,31 +436,33 @@ 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 {
 | 
			
		||||
            let price_per_month = calculate_nanocredits(
 | 
			
		||||
                (node.vcpus * i) as u32,
 | 
			
		||||
                (mem_per_cpu * i) as u32,
 | 
			
		||||
                (disk_per_cpu * i) as u32,
 | 
			
		||||
                false,
 | 
			
		||||
                732,
 | 
			
		||||
                node.price,
 | 
			
		||||
            ) as f64
 | 
			
		||||
                / 1_000_000_000_f64;
 | 
			
		||||
            let price_per_hour = price_per_month / 732_f64;
 | 
			
		||||
            let price_per_month = (price_per_month * 100.0).round() / 100.0;
 | 
			
		||||
            let price_per_hour = (price_per_hour * 1000.0).round() / 1000.0;
 | 
			
		||||
            offers.push(NodeOffer {
 | 
			
		||||
                location: node.city.clone() + ", " + &node.region + ", " + &node.country,
 | 
			
		||||
                vcpus: i,
 | 
			
		||||
                mem: i * mem_per_cpu,
 | 
			
		||||
                disk: i * disk_per_cpu,
 | 
			
		||||
                cost_h: price_per_hour,
 | 
			
		||||
                cost_m: price_per_month,
 | 
			
		||||
                ipv4: node.public_ipv4,
 | 
			
		||||
                // ipv6: node.public_ipv6,
 | 
			
		||||
            });
 | 
			
		||||
        for offer in node.offers.iter() {
 | 
			
		||||
            let mem_per_cpu = offer.memory_mib / offer.vcpus;
 | 
			
		||||
            let disk_per_cpu = offer.disk_mib / offer.vcpus;
 | 
			
		||||
            for i in 1..offer.vcpus {
 | 
			
		||||
                let price_per_month = calculate_nanocredits(
 | 
			
		||||
                    i as u32,
 | 
			
		||||
                    (mem_per_cpu * i) as u32,
 | 
			
		||||
                    (disk_per_cpu * i) as u32,
 | 
			
		||||
                    false,
 | 
			
		||||
                    732,
 | 
			
		||||
                    offer.price,
 | 
			
		||||
                ) as f64
 | 
			
		||||
                    / 1_000_000_000_f64;
 | 
			
		||||
                let price_per_hour = price_per_month / 732_f64;
 | 
			
		||||
                let price_per_month = (price_per_month * 100.0).round() / 100.0;
 | 
			
		||||
                let price_per_hour = (price_per_hour * 1000.0).round() / 1000.0;
 | 
			
		||||
                offers.push(NodeOffer {
 | 
			
		||||
                    location: node.city.clone() + ", " + &node.region + ", " + &node.country,
 | 
			
		||||
                    vcpus: i,
 | 
			
		||||
                    mem: i * mem_per_cpu,
 | 
			
		||||
                    disk: i * disk_per_cpu,
 | 
			
		||||
                    cost_h: price_per_hour,
 | 
			
		||||
                    cost_m: price_per_month,
 | 
			
		||||
                    ipv4: node.public_ipv4,
 | 
			
		||||
                    // ipv6: node.public_ipv6,
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    offers.sort_by_key(|n| n.cost_m as u64);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user