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