switch from LP to credits and allow slots
This commit is contained in:
		
							parent
							
								
									13a00e2318
								
							
						
					
					
						commit
						252582b9d3
					
				
							
								
								
									
										5
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										5
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -1,7 +1,6 @@
 | 
				
			|||||||
# SPDX-License-Identifier: Apache-2.0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# This file is automatically @generated by Cargo.
 | 
					# This file is automatically @generated by Cargo.
 | 
				
			||||||
# It is not intended for manual editing.
 | 
					# It is not intended for manual editing.
 | 
				
			||||||
 | 
					# SPDX-License-Identifier: Apache-2.0
 | 
				
			||||||
version = 4
 | 
					version = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -1184,7 +1183,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=surreal_brain_app#0b195b4589e4ec689af7ddca27dc051716ecee78"
 | 
					source = "git+ssh://git@gitea.detee.cloud/testnet/proto.git?branch=credits-v2#6d377926408953e8da2c0f4c6625d4fb90ba7652"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bincode",
 | 
					 "bincode",
 | 
				
			||||||
 "prost",
 | 
					 "prost",
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ tokio-retry = "0.3.0"
 | 
				
			|||||||
detee-sgx = { git = "ssh://git@gitea.detee.cloud/testnet/detee-sgx.git", branch = "hratls", features=["hratls", "qvl"] }
 | 
					detee-sgx = { git = "ssh://git@gitea.detee.cloud/testnet/detee-sgx.git", branch = "hratls", features=["hratls", "qvl"] }
 | 
				
			||||||
shadow-rs = { version = "1.1.1", features = ["metadata"] }
 | 
					shadow-rs = { version = "1.1.1", features = ["metadata"] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto.git", branch = "surreal_brain_app" }
 | 
					detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto.git", branch = "credits-v2" }
 | 
				
			||||||
# detee-shared = { path = "../detee-shared" }
 | 
					# detee-shared = { path = "../detee-shared" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[build-dependencies]
 | 
					[build-dependencies]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
// SPDX-License-Identifier: Apache-2.0
 | 
					// SPDX-License-Identifier: Apache-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use clap::{builder::PossibleValue, Arg, Command};
 | 
					use clap::{builder::PossibleValue, Arg, Command};
 | 
				
			||||||
use detee_cli::general::cli_handler::{
 | 
					use detee_cli::{
 | 
				
			||||||
    handle_account, handle_completion, handle_operators, handle_packagers,
 | 
					    general::cli_handler::{handle_account, handle_completion, handle_operators, handle_packagers},
 | 
				
			||||||
 | 
					    sgx::cli_handler::{handle_app, handle_app_nodes},
 | 
				
			||||||
 | 
					    snp::cli_handler::{handle_vm, handle_vm_nodes},
 | 
				
			||||||
 | 
					    *,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use detee_cli::sgx::cli_handler::{handle_app, handle_app_nodes};
 | 
					 | 
				
			||||||
use detee_cli::snp::cli_handler::{handle_vm, handle_vm_nodes};
 | 
					 | 
				
			||||||
use detee_cli::*;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ABOUT: &str = r#"The DeTEE CLI allows you to manage and deploy applications and virtual machines.
 | 
					const ABOUT: &str = r#"The DeTEE CLI allows you to manage and deploy applications and virtual machines.
 | 
				
			||||||
All software runs within Trusted Execution Environments on a distributed network.
 | 
					All software runs within Trusted Execution Environments on a distributed network.
 | 
				
			||||||
@ -53,6 +53,16 @@ fn main() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn clap_cmd() -> Command {
 | 
					fn clap_cmd() -> Command {
 | 
				
			||||||
 | 
					    let snp_locations = [
 | 
				
			||||||
 | 
					                        PossibleValue::new("GB").help("London, England, GB"),
 | 
				
			||||||
 | 
					                        PossibleValue::new("Canada").help("Montréal or Vancouver"),
 | 
				
			||||||
 | 
					                        PossibleValue::new("Montreal").help("Montréal, Quebec, CA"),
 | 
				
			||||||
 | 
					                        PossibleValue::new("Vancouver").help("Vancouver, British Columbia, CA"),
 | 
				
			||||||
 | 
					                        PossibleValue::new("California").help("San Jose, California, US"),
 | 
				
			||||||
 | 
					                        PossibleValue::new("US").help("San Jose, California, US"),
 | 
				
			||||||
 | 
					                        PossibleValue::new("France").help("Paris, Île-de-France, FR"),
 | 
				
			||||||
 | 
					                        PossibleValue::new("Any").help("List offers for any location."),
 | 
				
			||||||
 | 
					                    ];
 | 
				
			||||||
    Command::new("detee-cli")
 | 
					    Command::new("detee-cli")
 | 
				
			||||||
        .version(build::CLAP_LONG_VERSION)
 | 
					        .version(build::CLAP_LONG_VERSION)
 | 
				
			||||||
        .author("https://detee.ltd")
 | 
					        .author("https://detee.ltd")
 | 
				
			||||||
@ -160,7 +170,7 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
                        .help("for how many hours should the app run")
 | 
					                        .help("for how many hours should the app run")
 | 
				
			||||||
                        .default_value("1")
 | 
					                        .default_value("1")
 | 
				
			||||||
                        .value_parser(clap::value_parser!(u64).range(1..5000))
 | 
					                        .value_parser(clap::value_parser!(u64).range(1..5000))
 | 
				
			||||||
                        .long_help("How long should the app run for so it locks up LP accordingly")
 | 
					                        .long_help("How long should the app run for so it locks up credits accordingly")
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    .arg(
 | 
					                    .arg(
 | 
				
			||||||
                        Arg::new("price")
 | 
					                        Arg::new("price")
 | 
				
			||||||
@ -325,17 +335,8 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
                    Arg::new("location")
 | 
					                    Arg::new("location")
 | 
				
			||||||
                    .help("deploy to a specific location")
 | 
					                    .help("deploy to a specific location")
 | 
				
			||||||
                    .long("location")
 | 
					                    .long("location")
 | 
				
			||||||
                    .default_value("Vancouver")
 | 
					                    .default_value("Any")
 | 
				
			||||||
                    .value_parser([
 | 
					                    .value_parser(snp_locations.clone()),
 | 
				
			||||||
                        PossibleValue::new("GB").help("London, England, GB"),
 | 
					 | 
				
			||||||
                        PossibleValue::new("Canada").help("Montréal or Vancouver"),
 | 
					 | 
				
			||||||
                        PossibleValue::new("Montreal").help("Montréal, Quebec, CA"),
 | 
					 | 
				
			||||||
                        PossibleValue::new("Vancouver").help("Vancouver, British Columbia, CA"),
 | 
					 | 
				
			||||||
                        PossibleValue::new("California").help("San Jose, California, US"),
 | 
					 | 
				
			||||||
                        PossibleValue::new("US").help("San Jose, California, US"),
 | 
					 | 
				
			||||||
                        PossibleValue::new("France").help("Paris, Île-de-France, FR"),
 | 
					 | 
				
			||||||
                        PossibleValue::new("Random").help("Just deploy somewhere..."),
 | 
					 | 
				
			||||||
                    ]),
 | 
					 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("vcpus")
 | 
					                    Arg::new("vcpus")
 | 
				
			||||||
@ -347,16 +348,16 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("memory")
 | 
					                    Arg::new("memory")
 | 
				
			||||||
                    .long("memory")
 | 
					                    .long("memory")
 | 
				
			||||||
                    .default_value("1000")
 | 
					                    .default_value("1")
 | 
				
			||||||
                    .value_parser(clap::value_parser!(u32).range(800..123000))
 | 
					                    .value_parser(clap::value_parser!(u32).range(1..500))
 | 
				
			||||||
                    .help("memory in MB")
 | 
					                    .help("memory in GiB")
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("disk")
 | 
					                    Arg::new("disk")
 | 
				
			||||||
                    .long("disk")
 | 
					                    .long("disk")
 | 
				
			||||||
                    .default_value("10")
 | 
					                    .default_value("10")
 | 
				
			||||||
                    .value_parser(clap::value_parser!(u32).range(5..500))
 | 
					                    .value_parser(clap::value_parser!(u32).range(5..500))
 | 
				
			||||||
                    .help("disk size in GB")
 | 
					                    .help("disk size in GiB")
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("distribution")
 | 
					                    Arg::new("distribution")
 | 
				
			||||||
@ -375,8 +376,8 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("price")
 | 
					                    Arg::new("price")
 | 
				
			||||||
                    .long("price")
 | 
					                    .long("price")
 | 
				
			||||||
                    .help("price per unit per minute; check docs")
 | 
					                    .help("maxium accepted price per unit per minute")
 | 
				
			||||||
                    .default_value("20000")
 | 
					                    .default_value("4000")
 | 
				
			||||||
                    .value_parser(clap::value_parser!(u64).range(1..50000000))
 | 
					                    .value_parser(clap::value_parser!(u64).range(1..50000000))
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
@ -437,7 +438,7 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
                .long_about("Allows you to update the hardware or the lifetime".to_string() +
 | 
					                .long_about("Allows you to update the hardware or the lifetime".to_string() +
 | 
				
			||||||
                    "\nAny hardware modifiations will restart the VM." +
 | 
					                    "\nAny hardware modifiations will restart the VM." +
 | 
				
			||||||
                    "\nChanging the lifetime of a VM will not restart." +
 | 
					                    "\nChanging the lifetime of a VM will not restart." +
 | 
				
			||||||
                    "\nIf changing the lifetime to a higher value, LP will locked accordingly.")
 | 
					                    "\nIf changing the lifetime to a higher value, credits will locked accordingly.")
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("uuid")
 | 
					                    Arg::new("uuid")
 | 
				
			||||||
                    .help("supply the uuid of the VM you wish to upgrade")
 | 
					                    .help("supply the uuid of the VM you wish to upgrade")
 | 
				
			||||||
@ -460,15 +461,15 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
                    Arg::new("memory")
 | 
					                    Arg::new("memory")
 | 
				
			||||||
                    .long("memory")
 | 
					                    .long("memory")
 | 
				
			||||||
                    .default_value("0")
 | 
					                    .default_value("0")
 | 
				
			||||||
                    .value_parser(clap::value_parser!(u32).range(0..115000))
 | 
					                    .value_parser(clap::value_parser!(u32).range(0..5000))
 | 
				
			||||||
                    .help("modify the MB of memory reserved")
 | 
					                    .help("modify the GiB of memory reserved")
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("disk")
 | 
					                    Arg::new("disk")
 | 
				
			||||||
                    .long("disk")
 | 
					                    .long("disk")
 | 
				
			||||||
                    .default_value("0")
 | 
					                    .default_value("0")
 | 
				
			||||||
                    .value_parser(clap::value_parser!(u32).range(0..500))
 | 
					                    .value_parser(clap::value_parser!(u32).range(0..500))
 | 
				
			||||||
                    .help("increase the size of the disk in GB")
 | 
					                    .help("increase the size of the disk in GiB")
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("hours")
 | 
					                    Arg::new("hours")
 | 
				
			||||||
@ -501,7 +502,24 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        .subcommand(Command::new("vm-node")
 | 
					        .subcommand(Command::new("vm-node")
 | 
				
			||||||
            .about("info about AMD SEV-SNP servers registerd to DeTEE")
 | 
					            .about("info about AMD SEV-SNP servers registerd to DeTEE")
 | 
				
			||||||
            .subcommand(Command::new("search").about("search nodes based on filters"))
 | 
					            .subcommand(Command::new("search").about("search nodes based on filters")
 | 
				
			||||||
 | 
					                .arg(
 | 
				
			||||||
 | 
					                    Arg::new("location")
 | 
				
			||||||
 | 
					                    .help("deploy to a specific location")
 | 
				
			||||||
 | 
					                    .long("location")
 | 
				
			||||||
 | 
					                    .default_value("Any")
 | 
				
			||||||
 | 
					                    .value_parser(snp_locations.clone()),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .subcommand(Command::new("offers").about("search nodes based on filters")
 | 
				
			||||||
 | 
					                .arg(
 | 
				
			||||||
 | 
					                    Arg::new("location")
 | 
				
			||||||
 | 
					                    .help("deploy to a specific location")
 | 
				
			||||||
 | 
					                    .long("location")
 | 
				
			||||||
 | 
					                    .default_value("Any")
 | 
				
			||||||
 | 
					                    .value_parser(snp_locations),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
            .subcommand(Command::new("inspect").about("get detailed information about a node")
 | 
					            .subcommand(Command::new("inspect").about("get detailed information about a node")
 | 
				
			||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("ip")
 | 
					                    Arg::new("ip")
 | 
				
			||||||
@ -537,7 +555,7 @@ fn clap_cmd() -> Command {
 | 
				
			|||||||
                .arg(
 | 
					                .arg(
 | 
				
			||||||
                    Arg::new("escrow")
 | 
					                    Arg::new("escrow")
 | 
				
			||||||
                    .long("escrow")
 | 
					                    .long("escrow")
 | 
				
			||||||
                    .help("At least 5000 LP is required as escrow")
 | 
					                    .help("At least 5000 credits is required as escrow")
 | 
				
			||||||
                    .long_help("Escrow is used by node operators to guarantee quality.".to_owned() +
 | 
					                    .long_help("Escrow is used by node operators to guarantee quality.".to_owned() +
 | 
				
			||||||
                        "\nBefore adding escrow, make sure you booted a node under your account." +
 | 
					                        "\nBefore adding escrow, make sure you booted a node under your account." +
 | 
				
			||||||
                        "\nWhen all your nodes got decomissioned, your escrow gets automatically returned.")
 | 
					                        "\nWhen all your nodes got decomissioned, your escrow gets automatically returned.")
 | 
				
			||||||
 | 
				
			|||||||
@ -36,10 +36,10 @@ impl super::HumanOutput for AccountData {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if !self.wallet_path.is_empty() {
 | 
					        if !self.wallet_path.is_empty() {
 | 
				
			||||||
            println!("The address of your DeTEE wallet is {}", self.wallet_address);
 | 
					            println!("The address of your DeTEE wallet is {}", self.wallet_address);
 | 
				
			||||||
            println!("The balance of your account is {} LP", self.account_balance);
 | 
					            println!("The balance of your account is {} credits", self.account_balance);
 | 
				
			||||||
            if self.locked_funds != 0.0 {
 | 
					            if self.locked_funds != 0.0 {
 | 
				
			||||||
                println!(
 | 
					                println!(
 | 
				
			||||||
                    "WARNING! {} LP is temporary locked, waiting for a Contract.",
 | 
					                    "WARNING! {} credits is temporary locked, waiting for a Contract.",
 | 
				
			||||||
                    self.locked_funds
 | 
					                    self.locked_funds
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -96,7 +96,7 @@ pub async fn kick_contract(contract_uuid: String, reason: String) -> Result<u64,
 | 
				
			|||||||
        })?)
 | 
					        })?)
 | 
				
			||||||
        .await?
 | 
					        .await?
 | 
				
			||||||
        .into_inner()
 | 
					        .into_inner()
 | 
				
			||||||
        .nano_lp)
 | 
					        .nano_credits)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn ban_user(user_wallet: String) -> Result<(), Error> {
 | 
					pub async fn ban_user(user_wallet: String) -> Result<(), Error> {
 | 
				
			||||||
 | 
				
			|||||||
@ -35,7 +35,7 @@ pub fn register(escrow: u64, email: String) -> Result<crate::SimpleOutput, grpc:
 | 
				
			|||||||
impl crate::HumanOutput for grpc::proto::InspectOperatorResp {
 | 
					impl crate::HumanOutput for grpc::proto::InspectOperatorResp {
 | 
				
			||||||
    fn human_cli_print(&self) {
 | 
					    fn human_cli_print(&self) {
 | 
				
			||||||
        if let Some(op) = &self.operator {
 | 
					        if let Some(op) = &self.operator {
 | 
				
			||||||
            println!("The operator {} supplies {} nanoLP as escrow,", op.pubkey, op.escrow,);
 | 
					            println!("The operator {} supplies {} nanocredits as escrow,", op.pubkey, op.escrow,);
 | 
				
			||||||
            println!(
 | 
					            println!(
 | 
				
			||||||
                "has {} app servers, {} VM servers, and {} total reports for all servers.",
 | 
					                "has {} app servers, {} VM servers, and {} total reports for all servers.",
 | 
				
			||||||
                op.app_nodes, op.vm_nodes, op.reports
 | 
					                op.app_nodes, op.vm_nodes, op.reports
 | 
				
			||||||
@ -77,7 +77,7 @@ pub fn print_operators() -> Result<Vec<grpc::proto::ListOperatorsResp>, grpc::Er
 | 
				
			|||||||
pub fn kick(contract_uuid: String, reason: String) -> Result<crate::SimpleOutput, grpc::Error> {
 | 
					pub fn kick(contract_uuid: String, reason: String) -> Result<crate::SimpleOutput, grpc::Error> {
 | 
				
			||||||
    let nano_lp = block_on(grpc::kick_contract(contract_uuid, reason))?;
 | 
					    let nano_lp = block_on(grpc::kick_contract(contract_uuid, reason))?;
 | 
				
			||||||
    Ok(crate::SimpleOutput::from(
 | 
					    Ok(crate::SimpleOutput::from(
 | 
				
			||||||
        format!("Successfully terminated contract. Refunded {} nanoLP.", nano_lp).as_str(),
 | 
					        format!("Successfully terminated contract. Refunded {} nanocredits.", nano_lp).as_str(),
 | 
				
			||||||
    ))
 | 
					    ))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@ impl crate::HumanOutput for AppContract {
 | 
				
			|||||||
            "The App has {} vCPUS, {}MB of memory and a disk of {} GB.",
 | 
					            "The App has {} vCPUS, {}MB of memory and a disk of {} GB.",
 | 
				
			||||||
            app_resource.vcpus, app_resource.memory_mb, app_resource.disk_size_gb
 | 
					            app_resource.vcpus, app_resource.memory_mb, app_resource.disk_size_gb
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        println!("You have locked {} nanoLP in the contract, that get collected at a rate of {} nanoLP per minute.",
 | 
					        println!("You have locked {} nanocredits in the contract, that get collected at a rate of {} nanocredits per minute.",
 | 
				
			||||||
            self.locked_nano, self.nano_per_minute);
 | 
					            self.locked_nano, self.nano_per_minute);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -48,7 +48,7 @@ pub struct AppContract {
 | 
				
			|||||||
    pub memory_mb: u32,
 | 
					    pub memory_mb: u32,
 | 
				
			||||||
    #[tabled(rename = "Disk (GB)")]
 | 
					    #[tabled(rename = "Disk (GB)")]
 | 
				
			||||||
    pub disk_size_gb: u32,
 | 
					    pub disk_size_gb: u32,
 | 
				
			||||||
    #[tabled(rename = "LP/h")]
 | 
					    #[tabled(rename = "credits/h")]
 | 
				
			||||||
    pub cost_h: String,
 | 
					    pub cost_h: String,
 | 
				
			||||||
    #[tabled(rename = "time left", display_with = "display_mins")]
 | 
					    #[tabled(rename = "time left", display_with = "display_mins")]
 | 
				
			||||||
    pub time_left: u64,
 | 
					    pub time_left: u64,
 | 
				
			||||||
@ -227,7 +227,7 @@ impl crate::HumanOutput for AppDeleteResponse {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub async fn get_app_node(
 | 
					pub async fn get_app_node(
 | 
				
			||||||
    resource: Resource,
 | 
					    resource: Resource,
 | 
				
			||||||
    location: snp::deploy::Location,
 | 
					    location: snp::Location,
 | 
				
			||||||
) -> Result<AppNodeListResp, grpc_brain::Error> {
 | 
					) -> Result<AppNodeListResp, grpc_brain::Error> {
 | 
				
			||||||
    let app_node_filter = AppNodeFilters {
 | 
					    let app_node_filter = AppNodeFilters {
 | 
				
			||||||
        vcpus: resource.vcpus,
 | 
					        vcpus: resource.vcpus,
 | 
				
			||||||
@ -268,7 +268,7 @@ impl From<AppNodeListResp> for TabledAppNode {
 | 
				
			|||||||
            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,
 | 
				
			||||||
            public_ip: brain_node.ip,
 | 
					            public_ip: brain_node.ip,
 | 
				
			||||||
            price: format!("{} nanoLP/min", brain_node.price),
 | 
					            price: format!("{} nanocredits/min", brain_node.price),
 | 
				
			||||||
            reports: brain_node.reports.len(),
 | 
					            reports: brain_node.reports.len(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,6 @@
 | 
				
			|||||||
// SPDX-License-Identifier: Apache-2.0
 | 
					// SPDX-License-Identifier: Apache-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::general;
 | 
					use crate::{cli_print, general, name_generator, snp, SimpleOutput};
 | 
				
			||||||
use crate::name_generator;
 | 
					 | 
				
			||||||
use crate::snp;
 | 
					 | 
				
			||||||
use crate::{cli_print, SimpleOutput};
 | 
					 | 
				
			||||||
use clap::ArgMatches;
 | 
					use clap::ArgMatches;
 | 
				
			||||||
use std::error::Error;
 | 
					use std::error::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,7 +27,14 @@ pub fn handle_vm(matches: &ArgMatches) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub fn handle_vm_nodes(matches: &ArgMatches) {
 | 
					pub fn handle_vm_nodes(matches: &ArgMatches) {
 | 
				
			||||||
    match matches.subcommand() {
 | 
					    match matches.subcommand() {
 | 
				
			||||||
        Some(("search", _)) => cli_print(snp::print_nodes().map_err(Into::into)),
 | 
					        Some(("search", arguments)) => {
 | 
				
			||||||
 | 
					            let location = arguments.get_one::<String>("location").unwrap().as_str();
 | 
				
			||||||
 | 
					            cli_print(snp::search_nodes(location.into()).map_err(Into::into));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Some(("offers", arguments)) => {
 | 
				
			||||||
 | 
					            let location = arguments.get_one::<String>("location").unwrap().as_str();
 | 
				
			||||||
 | 
					            cli_print(snp::print_node_offers(location.into()).map_err(Into::into));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        Some(("inspect", path_subcommand)) => {
 | 
					        Some(("inspect", path_subcommand)) => {
 | 
				
			||||||
            let ip: String = path_subcommand.get_one::<String>("ip").unwrap().clone();
 | 
					            let ip: String = path_subcommand.get_one::<String>("ip").unwrap().clone();
 | 
				
			||||||
            cli_print(snp::inspect_node(ip).map_err(Into::into));
 | 
					            cli_print(snp::inspect_node(ip).map_err(Into::into));
 | 
				
			||||||
@ -69,8 +73,8 @@ fn handle_vm_deploy(matches: &ArgMatches) -> Result<snp::VmSshArgs, Box<dyn Erro
 | 
				
			|||||||
        ipv4,
 | 
					        ipv4,
 | 
				
			||||||
        public_ipv6: false,
 | 
					        public_ipv6: false,
 | 
				
			||||||
        vcpus: *matches.get_one::<u32>("vcpus").unwrap(),
 | 
					        vcpus: *matches.get_one::<u32>("vcpus").unwrap(),
 | 
				
			||||||
        memory_mb: *matches.get_one::<u32>("memory").unwrap(),
 | 
					        memory_gib: *matches.get_one::<u32>("memory").unwrap(),
 | 
				
			||||||
        disk_size_gb: *matches.get_one::<u32>("disk").unwrap(),
 | 
					        disk_size_gib: *matches.get_one::<u32>("disk").unwrap(),
 | 
				
			||||||
        dtrfs: None,
 | 
					        dtrfs: None,
 | 
				
			||||||
        hours: *matches.get_one::<u32>("hours").unwrap(),
 | 
					        hours: *matches.get_one::<u32>("hours").unwrap(),
 | 
				
			||||||
        price: *matches.get_one::<u64>("price").unwrap(),
 | 
					        price: *matches.get_one::<u64>("price").unwrap(),
 | 
				
			||||||
@ -92,10 +96,6 @@ fn handle_vm_update(update_vm_args: &ArgMatches) -> Result<SimpleOutput, Box<dyn
 | 
				
			|||||||
    let uuid = update_vm_args.get_one::<String>("uuid").unwrap().clone();
 | 
					    let uuid = update_vm_args.get_one::<String>("uuid").unwrap().clone();
 | 
				
			||||||
    let hostname = update_vm_args.get_one::<String>("hostname").unwrap().clone();
 | 
					    let hostname = update_vm_args.get_one::<String>("hostname").unwrap().clone();
 | 
				
			||||||
    let memory = *update_vm_args.get_one::<u32>("memory").unwrap();
 | 
					    let memory = *update_vm_args.get_one::<u32>("memory").unwrap();
 | 
				
			||||||
    if memory > 0 && memory < 800 {
 | 
					 | 
				
			||||||
        log::error!("At least 800MB of memory must be assgined to the VM");
 | 
					 | 
				
			||||||
        return Ok(SimpleOutput::from(""));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    snp::update::Request::process_request(
 | 
					    snp::update::Request::process_request(
 | 
				
			||||||
        hostname,
 | 
					        hostname,
 | 
				
			||||||
        &uuid,
 | 
					        &uuid,
 | 
				
			||||||
 | 
				
			|||||||
@ -4,8 +4,7 @@ use super::{
 | 
				
			|||||||
    grpc::{self, proto},
 | 
					    grpc::{self, proto},
 | 
				
			||||||
    injector, Distro, Dtrfs, Error, VmSshArgs, DEFAULT_ARCHLINUX, DEFAULT_DTRFS,
 | 
					    injector, Distro, Dtrfs, Error, VmSshArgs, DEFAULT_ARCHLINUX, DEFAULT_DTRFS,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::config::Config;
 | 
					use crate::{config::Config, utils::block_on};
 | 
				
			||||||
use crate::utils::block_on;
 | 
					 | 
				
			||||||
use log::{debug, info};
 | 
					use log::{debug, info};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -15,44 +14,18 @@ pub enum IPv4Config {
 | 
				
			|||||||
    PublicIPv4,
 | 
					    PublicIPv4,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  TODO: push this out of snp module
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Default)]
 | 
					 | 
				
			||||||
pub struct Location {
 | 
					 | 
				
			||||||
    pub node_ip: Option<String>,
 | 
					 | 
				
			||||||
    pub country: Option<String>,
 | 
					 | 
				
			||||||
    pub region: Option<String>,
 | 
					 | 
				
			||||||
    pub city: Option<String>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<&str> for Location {
 | 
					 | 
				
			||||||
    fn from(s: &str) -> Self {
 | 
					 | 
				
			||||||
        match s {
 | 
					 | 
				
			||||||
            "Canada" => Self { country: Some("CA".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            "Montreal" => Self { city: Some("Montréal".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            "Vancouver" => Self { city: Some("Vancouver".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            "US" => Self { country: Some("US".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            "California" => Self { country: Some("US".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            "France" => Self { country: Some("FR".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            "GB" => Self { country: Some("GB".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            "Random" => Self { ..Default::default() },
 | 
					 | 
				
			||||||
            "DE" => Self { country: Some("DE".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
            _ => Self { city: Some("Vancouver".to_string()), ..Default::default() },
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize)]
 | 
					#[derive(Serialize, Deserialize)]
 | 
				
			||||||
pub struct Request {
 | 
					pub struct Request {
 | 
				
			||||||
    pub hostname: String,
 | 
					    pub hostname: String,
 | 
				
			||||||
    pub hours: u32,
 | 
					    pub hours: u32,
 | 
				
			||||||
    // price per unit per minute
 | 
					    // price per unit per minute
 | 
				
			||||||
    pub price: u64,
 | 
					    pub price: u64,
 | 
				
			||||||
    pub location: Location,
 | 
					    pub location: super::Location,
 | 
				
			||||||
    pub ipv4: IPv4Config,
 | 
					    pub ipv4: IPv4Config,
 | 
				
			||||||
    pub public_ipv6: bool,
 | 
					    pub public_ipv6: bool,
 | 
				
			||||||
    pub vcpus: u32,
 | 
					    pub vcpus: u32,
 | 
				
			||||||
    pub memory_mb: u32,
 | 
					    pub memory_gib: u32,
 | 
				
			||||||
    pub disk_size_gb: u32,
 | 
					    pub disk_size_gib: u32,
 | 
				
			||||||
    pub dtrfs: Option<Dtrfs>,
 | 
					    pub dtrfs: Option<Dtrfs>,
 | 
				
			||||||
    pub distro: Option<Distro>,
 | 
					    pub distro: Option<Distro>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -70,8 +43,8 @@ impl Request {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn deploy(&self) -> Result<VmSshArgs, Error> {
 | 
					    pub fn deploy(&self) -> Result<VmSshArgs, Error> {
 | 
				
			||||||
        let (node_ip, new_vm_resp) = self.send_vm_request()?;
 | 
					        let (vcpus, new_vm_resp) = self.calculate_and_send_request()?;
 | 
				
			||||||
        info!("Got confirmation from the node {node_ip} that VM started.");
 | 
					        info!("Got confirmation from the node that the VM started.");
 | 
				
			||||||
        debug!("IPs and ports assigned by node are: {new_vm_resp:#?}");
 | 
					        debug!("IPs and ports assigned by node are: {new_vm_resp:#?}");
 | 
				
			||||||
        if !new_vm_resp.error.is_empty() {
 | 
					        if !new_vm_resp.error.is_empty() {
 | 
				
			||||||
            return Err(Error::Node(new_vm_resp.error));
 | 
					            return Err(Error::Node(new_vm_resp.error));
 | 
				
			||||||
@ -83,7 +56,7 @@ impl Request {
 | 
				
			|||||||
        let args = new_vm_resp.args.ok_or(Error::NoMeasurement)?;
 | 
					        let args = new_vm_resp.args.ok_or(Error::NoMeasurement)?;
 | 
				
			||||||
        let measurement_args = injector::Args {
 | 
					        let measurement_args = injector::Args {
 | 
				
			||||||
            uuid: new_vm_resp.uuid.clone(),
 | 
					            uuid: new_vm_resp.uuid.clone(),
 | 
				
			||||||
            vcpus: self.vcpus,
 | 
					            vcpus,
 | 
				
			||||||
            kernel: kernel_sha,
 | 
					            kernel: kernel_sha,
 | 
				
			||||||
            initrd: dtrfs_sha,
 | 
					            initrd: dtrfs_sha,
 | 
				
			||||||
            args: args.clone(),
 | 
					            args: args.clone(),
 | 
				
			||||||
@ -107,10 +80,106 @@ impl Request {
 | 
				
			|||||||
        Ok(ssh_args)
 | 
					        Ok(ssh_args)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // returns node IP and data regarding the new VM
 | 
					    /// returns number of vCPUs and response from the daemon
 | 
				
			||||||
    fn send_vm_request(&self) -> Result<(String, proto::NewVmResp), Error> {
 | 
					    fn calculate_and_send_request(&self) -> Result<(u32, proto::NewVmResp), Error> {
 | 
				
			||||||
        let admin_pubkey = Config::get_detee_wallet()?;
 | 
					        let new_vm_req = self.get_cheapest_offer()?;
 | 
				
			||||||
        let node = self.get_node()?;
 | 
					        let vcpus = new_vm_req.vcpus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        eprintln!(
 | 
				
			||||||
 | 
					            "Locking {} credits for {} hours of the following HW spec: {} vCPUs, {} MiB Mem, {} MiB Disk",
 | 
				
			||||||
 | 
					            new_vm_req.locked_nano as f64 / 1_000_000_000_f64,
 | 
				
			||||||
 | 
					            self.hours,
 | 
				
			||||||
 | 
					            new_vm_req.vcpus,
 | 
				
			||||||
 | 
					            new_vm_req.memory_mib,
 | 
				
			||||||
 | 
					            new_vm_req.disk_size_mib
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // eprint!(
 | 
				
			||||||
 | 
					        //     "Node price: {}/unit/minute. Total Units for hardware requested: {}. ",
 | 
				
			||||||
 | 
					        //     node_price as f64 / 1_000_000_000.0,
 | 
				
			||||||
 | 
					        //     total_units,
 | 
				
			||||||
 | 
					        // );
 | 
				
			||||||
 | 
					        // eprintln!(
 | 
				
			||||||
 | 
					        //     "Locking {} LP (offering the VM for {} hours).",
 | 
				
			||||||
 | 
					        //     locked_nano as f64 / 1_000_000_000.0,
 | 
				
			||||||
 | 
					        //     hours
 | 
				
			||||||
 | 
					        // );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let new_vm_resp = block_on(grpc::create_vm(new_vm_req))?;
 | 
				
			||||||
 | 
					        if !new_vm_resp.error.is_empty() {
 | 
				
			||||||
 | 
					            return Err(Error::Node(new_vm_resp.error));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok((vcpus, new_vm_resp))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn get_cheapest_offer(&self) -> Result<proto::NewVmReq, Error> {
 | 
				
			||||||
 | 
					        let (free_ports, offers_ipv4) = match &self.ipv4 {
 | 
				
			||||||
 | 
					            IPv4Config::PublishPorts(vec) => (vec.len() as u32, false),
 | 
				
			||||||
 | 
					            IPv4Config::PublicIPv4 => (0, true),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        let filters = proto::VmNodeFilters {
 | 
				
			||||||
 | 
					            free_ports,
 | 
				
			||||||
 | 
					            offers_ipv4,
 | 
				
			||||||
 | 
					            offers_ipv6: self.public_ipv6,
 | 
				
			||||||
 | 
					            vcpus: self.vcpus,
 | 
				
			||||||
 | 
					            memory_mib: self.memory_gib * 1024,
 | 
				
			||||||
 | 
					            storage_mib: self.disk_size_gib * 1024,
 | 
				
			||||||
 | 
					            country: self.location.country.clone().unwrap_or_default(),
 | 
				
			||||||
 | 
					            region: self.location.region.clone().unwrap_or_default(),
 | 
				
			||||||
 | 
					            city: self.location.city.clone().unwrap_or_default(),
 | 
				
			||||||
 | 
					            ip: self.location.node_ip.clone().unwrap_or_default(),
 | 
				
			||||||
 | 
					            node_pubkey: String::new(),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        let node_list = match block_on(grpc::get_node_list(filters)) {
 | 
				
			||||||
 | 
					            Ok(node_list) => Ok(node_list),
 | 
				
			||||||
 | 
					            Err(e) => {
 | 
				
			||||||
 | 
					                log::error!("Coult not get node from brain: {e:?}");
 | 
				
			||||||
 | 
					                Err(Error::NoValidNodeFound)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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)?,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if vcpus < (self.disk_size_gib * 1024).div_ceil(disk_per_cpu as u32) {
 | 
				
			||||||
 | 
					            vcpus = (self.disk_size_gib * 1024).div_ceil(disk_per_cpu as u32);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let memory_mib = vcpus * memory_per_cpu as u32;
 | 
				
			||||||
 | 
					        let disk_size_mib = vcpus * disk_per_cpu as u32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let nanocredits = super::calculate_nanocredits(
 | 
				
			||||||
 | 
					            vcpus,
 | 
				
			||||||
 | 
					            memory_mib,
 | 
				
			||||||
 | 
					            disk_size_mib,
 | 
				
			||||||
 | 
					            node.public_ipv4,
 | 
				
			||||||
 | 
					            self.hours,
 | 
				
			||||||
 | 
					            node.price,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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),
 | 
				
			||||||
@ -124,63 +193,31 @@ impl Request {
 | 
				
			|||||||
                DEFAULT_DTRFS.dtrfs_sha.clone(),
 | 
					                DEFAULT_DTRFS.dtrfs_sha.clone(),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let locked_nano = super::calculate_nanolp(
 | 
					
 | 
				
			||||||
            self.vcpus,
 | 
					 | 
				
			||||||
            self.memory_mb,
 | 
					 | 
				
			||||||
            self.disk_size_gb,
 | 
					 | 
				
			||||||
            public_ipv4,
 | 
					 | 
				
			||||||
            self.hours,
 | 
					 | 
				
			||||||
            self.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,
 | 
					            node_pubkey: node.node_pubkey.clone(),
 | 
				
			||||||
            extra_ports,
 | 
					            extra_ports,
 | 
				
			||||||
            public_ipv4,
 | 
					            public_ipv4,
 | 
				
			||||||
            public_ipv6: self.public_ipv6,
 | 
					            public_ipv6: self.public_ipv6,
 | 
				
			||||||
            disk_size_gb: self.disk_size_gb,
 | 
					            disk_size_mib,
 | 
				
			||||||
            vcpus: self.vcpus,
 | 
					            vcpus,
 | 
				
			||||||
            memory_mb: self.memory_mb,
 | 
					            memory_mib,
 | 
				
			||||||
            kernel_url,
 | 
					            kernel_url,
 | 
				
			||||||
            kernel_sha,
 | 
					            kernel_sha,
 | 
				
			||||||
            dtrfs_url,
 | 
					            dtrfs_url,
 | 
				
			||||||
            dtrfs_sha,
 | 
					            dtrfs_sha,
 | 
				
			||||||
            price_per_unit: self.price,
 | 
					            price_per_unit: node.price,
 | 
				
			||||||
            locked_nano,
 | 
					            locked_nano: nanocredits,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let new_vm_resp = block_on(grpc::create_vm(brain_req))?;
 | 
					 | 
				
			||||||
        if !new_vm_resp.error.is_empty() {
 | 
					 | 
				
			||||||
            return Err(Error::Node(new_vm_resp.error));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Ok((node.ip, new_vm_resp))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_node(&self) -> Result<proto::VmNodeListResp, Error> {
 | 
					        debug!(
 | 
				
			||||||
        let (free_ports, offers_ipv4) = match &self.ipv4 {
 | 
					            "Node {} can offer the VM at {} nanocredits for {} hours. Spec: {} vCPUs, {} MiB mem, {} MiB disk.",
 | 
				
			||||||
            IPv4Config::PublishPorts(vec) => (vec.len() as u32, false),
 | 
					            node.ip, brain_req.locked_nano, self.hours, brain_req.vcpus, brain_req.memory_mib, brain_req.disk_size_mib
 | 
				
			||||||
            IPv4Config::PublicIPv4 => (0, true),
 | 
					        );
 | 
				
			||||||
        };
 | 
					
 | 
				
			||||||
        let filters = proto::VmNodeFilters {
 | 
					        brain_req
 | 
				
			||||||
            free_ports,
 | 
					 | 
				
			||||||
            offers_ipv4,
 | 
					 | 
				
			||||||
            offers_ipv6: self.public_ipv6,
 | 
					 | 
				
			||||||
            vcpus: self.vcpus,
 | 
					 | 
				
			||||||
            memory_mb: self.memory_mb,
 | 
					 | 
				
			||||||
            storage_gb: self.disk_size_gb,
 | 
					 | 
				
			||||||
            country: self.location.country.clone().unwrap_or_default(),
 | 
					 | 
				
			||||||
            region: self.location.region.clone().unwrap_or_default(),
 | 
					 | 
				
			||||||
            city: self.location.city.clone().unwrap_or_default(),
 | 
					 | 
				
			||||||
            ip: self.location.node_ip.clone().unwrap_or_default(),
 | 
					 | 
				
			||||||
            node_pubkey: String::new(),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        match block_on(grpc::get_one_node(filters)) {
 | 
					 | 
				
			||||||
            Ok(node) => Ok(node),
 | 
					 | 
				
			||||||
            Err(e) => {
 | 
					 | 
				
			||||||
                log::error!("Coult not get node from brain: {e:?}");
 | 
					 | 
				
			||||||
                Err(Error::NoValidNodeFound)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -74,7 +74,7 @@ impl crate::HumanOutput for VmContract {
 | 
				
			|||||||
            "The VM has {} vCPUS, {}MB of memory and a disk of {} GB.",
 | 
					            "The VM has {} vCPUS, {}MB of memory and a disk of {} GB.",
 | 
				
			||||||
            self.vcpus, self.memory_mb, self.disk_size_gb
 | 
					            self.vcpus, self.memory_mb, self.disk_size_gb
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        println!("You have locked {} nanoLP in the contract, that get collected at a rate of {} nanoLP per minute.",
 | 
					        println!("You have locked {} nanocredits in the contract, that get collected at a rate of {} nanocredits per minute.",
 | 
				
			||||||
            self.locked_nano, self.nano_per_minute);
 | 
					            self.locked_nano, self.nano_per_minute);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -182,7 +182,7 @@ pub async fn extend_vm(uuid: String, admin_pubkey: String, locked_nano: u64) ->
 | 
				
			|||||||
        Ok(confirmation) => {
 | 
					        Ok(confirmation) => {
 | 
				
			||||||
            log::debug!("VM contract extension confirmation: {confirmation:?}");
 | 
					            log::debug!("VM contract extension confirmation: {confirmation:?}");
 | 
				
			||||||
            log::info!(
 | 
					            log::info!(
 | 
				
			||||||
                "VM contract got updated. It now has {} LP locked for the VM.",
 | 
					                "VM contract got updated. It now has {} credits locked for the VM.",
 | 
				
			||||||
                locked_nano as f64 / 1_000_000_000.0
 | 
					                locked_nano as f64 / 1_000_000_000.0
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										163
									
								
								src/snp/mod.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										163
									
								
								src/snp/mod.rs
									
									
									
									
									
								
							@ -6,11 +6,10 @@ pub mod grpc;
 | 
				
			|||||||
mod injector;
 | 
					mod injector;
 | 
				
			||||||
pub mod update;
 | 
					pub mod update;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::utils::block_on;
 | 
					 | 
				
			||||||
use crate::utils::shorten_string;
 | 
					 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    config::{self, Config},
 | 
					    config::{self, Config},
 | 
				
			||||||
    snp,
 | 
					    snp,
 | 
				
			||||||
 | 
					    utils::{block_on, display_mib_or_gib, shorten_string},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use grpc::proto;
 | 
					use grpc::proto;
 | 
				
			||||||
use lazy_static::lazy_static;
 | 
					use lazy_static::lazy_static;
 | 
				
			||||||
@ -39,6 +38,32 @@ pub enum Error {
 | 
				
			|||||||
    Injector(#[from] injector::Error),
 | 
					    Injector(#[from] injector::Error),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  TODO: push this out of snp module
 | 
				
			||||||
 | 
					#[derive(Serialize, Deserialize, Default)]
 | 
				
			||||||
 | 
					pub struct Location {
 | 
				
			||||||
 | 
					    pub node_ip: Option<String>,
 | 
				
			||||||
 | 
					    pub country: Option<String>,
 | 
				
			||||||
 | 
					    pub region: Option<String>,
 | 
				
			||||||
 | 
					    pub city: Option<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<&str> for Location {
 | 
				
			||||||
 | 
					    fn from(s: &str) -> Self {
 | 
				
			||||||
 | 
					        match s {
 | 
				
			||||||
 | 
					            "Canada" => Self { country: Some("CA".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "Montreal" => Self { city: Some("Montréal".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "Vancouver" => Self { city: Some("Vancouver".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "US" => Self { country: Some("US".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "California" => Self { country: Some("US".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "France" => Self { country: Some("FR".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "GB" => Self { country: Some("GB".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "DE" => Self { country: Some("DE".to_string()), ..Default::default() },
 | 
				
			||||||
 | 
					            "Any" => Self { ..Default::default() },
 | 
				
			||||||
 | 
					            _ => Self { ..Default::default() },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Serialize, Default)]
 | 
					#[derive(Serialize, Default)]
 | 
				
			||||||
pub struct VmSshArgs {
 | 
					pub struct VmSshArgs {
 | 
				
			||||||
    uuid: String,
 | 
					    uuid: String,
 | 
				
			||||||
@ -157,12 +182,12 @@ pub struct VmContract {
 | 
				
			|||||||
    pub uuid: String,
 | 
					    pub uuid: String,
 | 
				
			||||||
    pub hostname: String,
 | 
					    pub hostname: String,
 | 
				
			||||||
    #[tabled(rename = "Cores")]
 | 
					    #[tabled(rename = "Cores")]
 | 
				
			||||||
    pub vcpus: u32,
 | 
					    pub vcpus: u64,
 | 
				
			||||||
    #[tabled(rename = "Mem (MB)")]
 | 
					    #[tabled(rename = "Mem", display_with = "display_mib_or_gib")]
 | 
				
			||||||
    pub mem: u32,
 | 
					    pub mem: u64,
 | 
				
			||||||
    #[tabled(rename = "Disk")]
 | 
					    #[tabled(rename = "Disk", display_with = "display_mib_or_gib")]
 | 
				
			||||||
    pub disk: u32,
 | 
					    pub disk: u64,
 | 
				
			||||||
    #[tabled(rename = "LP/h")]
 | 
					    #[tabled(rename = "credits/h")]
 | 
				
			||||||
    pub cost_h: f64,
 | 
					    pub cost_h: f64,
 | 
				
			||||||
    #[tabled(rename = "time left", display_with = "display_mins")]
 | 
					    #[tabled(rename = "time left", display_with = "display_mins")]
 | 
				
			||||||
    pub time_left: u64,
 | 
					    pub time_left: u64,
 | 
				
			||||||
@ -189,9 +214,9 @@ impl From<proto::VmContract> for VmContract {
 | 
				
			|||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            uuid: brain_contract.uuid,
 | 
					            uuid: brain_contract.uuid,
 | 
				
			||||||
            hostname: brain_contract.hostname,
 | 
					            hostname: brain_contract.hostname,
 | 
				
			||||||
            vcpus: brain_contract.vcpus,
 | 
					            vcpus: brain_contract.vcpus as u64,
 | 
				
			||||||
            mem: brain_contract.memory_mb,
 | 
					            mem: brain_contract.memory_mb as u64,
 | 
				
			||||||
            disk: brain_contract.disk_size_gb,
 | 
					            disk: brain_contract.disk_size_gb as u64,
 | 
				
			||||||
            location: brain_contract.location,
 | 
					            location: brain_contract.location,
 | 
				
			||||||
            cost_h: (brain_contract.nano_per_minute * 60) as f64 / 1_000_000_000.0,
 | 
					            cost_h: (brain_contract.nano_per_minute * 60) as f64 / 1_000_000_000.0,
 | 
				
			||||||
            time_left: brain_contract.locked_nano / brain_contract.nano_per_minute,
 | 
					            time_left: brain_contract.locked_nano / brain_contract.nano_per_minute,
 | 
				
			||||||
@ -201,10 +226,16 @@ impl From<proto::VmContract> for VmContract {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Tabled, Debug, Serialize, Deserialize)]
 | 
					#[derive(Tabled, Debug, Serialize, Deserialize)]
 | 
				
			||||||
pub struct TabledVmNode {
 | 
					pub struct TabledVmNode {
 | 
				
			||||||
    #[tabled(rename = "Operator")]
 | 
					    #[tabled(rename = "Operator", display_with = "shorten_string")]
 | 
				
			||||||
    pub operator: String,
 | 
					    pub operator: String,
 | 
				
			||||||
    #[tabled(rename = "City, Region, Country")]
 | 
					    #[tabled(rename = "City, Region, Country")]
 | 
				
			||||||
    pub location: String,
 | 
					    pub location: String,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Cores")]
 | 
				
			||||||
 | 
					    pub vcpus: u64,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Mem", display_with = "display_mib_or_gib")]
 | 
				
			||||||
 | 
					    pub memory_mib: u64,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Disk", display_with = "display_mib_or_gib")]
 | 
				
			||||||
 | 
					    pub disk_mib: u64,
 | 
				
			||||||
    #[tabled(rename = "IP")]
 | 
					    #[tabled(rename = "IP")]
 | 
				
			||||||
    pub public_ip: String,
 | 
					    pub public_ip: String,
 | 
				
			||||||
    #[tabled(rename = "Price per unit")]
 | 
					    #[tabled(rename = "Price per unit")]
 | 
				
			||||||
@ -219,8 +250,11 @@ impl From<proto::VmNodeListResp> for TabledVmNode {
 | 
				
			|||||||
            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,
 | 
				
			||||||
            public_ip: brain_node.ip,
 | 
					            public_ip: brain_node.ip,
 | 
				
			||||||
            price: format!("{} nanoLP/min", brain_node.price),
 | 
					            price: format!("{} nano/min", brain_node.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,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -329,21 +363,104 @@ impl super::HumanOutput for Vec<proto::VmNodeListResp> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn print_nodes() -> Result<Vec<proto::VmNodeListResp>, Error> {
 | 
					pub fn search_nodes(location: Location) -> Result<Vec<proto::VmNodeListResp>, Error> {
 | 
				
			||||||
    log::debug!("This will support flags in the future, but we have only one node atm.");
 | 
					    log::debug!("This will support flags in the future, but we have only one node atm.");
 | 
				
			||||||
    let req = proto::VmNodeFilters { ..Default::default() };
 | 
					    let req = proto::VmNodeFilters {
 | 
				
			||||||
 | 
					        city: location.city.unwrap_or_default(),
 | 
				
			||||||
 | 
					        country: location.country.unwrap_or_default(),
 | 
				
			||||||
 | 
					        region: location.region.unwrap_or_default(),
 | 
				
			||||||
 | 
					        ..Default::default()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
    Ok(block_on(grpc::get_node_list(req))?)
 | 
					    Ok(block_on(grpc::get_node_list(req))?)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Tabled, Debug, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub struct NodeOffer {
 | 
				
			||||||
 | 
					    #[tabled(rename = "Location")]
 | 
				
			||||||
 | 
					    pub location: String,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Cores")]
 | 
				
			||||||
 | 
					    pub vcpus: u64,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Mem", display_with = "display_mib_or_gib")]
 | 
				
			||||||
 | 
					    pub mem: u64,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Disk", display_with = "display_mib_or_gib")]
 | 
				
			||||||
 | 
					    pub disk: u64,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Public IPv4", display_with = "display_ip_support")]
 | 
				
			||||||
 | 
					    pub ipv4: bool,
 | 
				
			||||||
 | 
					    #[tabled(rename = "Public IPv6", display_with = "display_ip_support")]
 | 
				
			||||||
 | 
					    pub ipv6: bool,
 | 
				
			||||||
 | 
					    #[tabled(rename = "cost/h")]
 | 
				
			||||||
 | 
					    pub cost_h: f64,
 | 
				
			||||||
 | 
					    #[tabled(rename = "cost/m")]
 | 
				
			||||||
 | 
					    pub cost_m: f64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn display_ip_support(support: &bool) -> String {
 | 
				
			||||||
 | 
					    match support {
 | 
				
			||||||
 | 
					        true => "Available".to_string(),
 | 
				
			||||||
 | 
					        false => "Unavailable".to_string(),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl super::HumanOutput for Vec<NodeOffer> {
 | 
				
			||||||
 | 
					    fn human_cli_print(&self) {
 | 
				
			||||||
 | 
					        let style = tabled::settings::Style::rounded();
 | 
				
			||||||
 | 
					        let mut table = tabled::Table::new(self);
 | 
				
			||||||
 | 
					        table.with(style);
 | 
				
			||||||
 | 
					        println!("{table}");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn print_node_offers(location: Location) -> Result<Vec<NodeOffer>, Error> {
 | 
				
			||||||
 | 
					    log::debug!("This will support flags in the future, but we have only one node atm.");
 | 
				
			||||||
 | 
					    let req = proto::VmNodeFilters {
 | 
				
			||||||
 | 
					        city: location.city.unwrap_or_default(),
 | 
				
			||||||
 | 
					        country: location.country.unwrap_or_default(),
 | 
				
			||||||
 | 
					        region: location.region.unwrap_or_default(),
 | 
				
			||||||
 | 
					        ..Default::default()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    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 * 100.0).round() / 100.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);
 | 
				
			||||||
 | 
					    Ok(offers)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn inspect_node(ip: String) -> Result<proto::VmNodeListResp, Error> {
 | 
					pub fn inspect_node(ip: String) -> Result<proto::VmNodeListResp, Error> {
 | 
				
			||||||
    let req = proto::VmNodeFilters { ip, ..Default::default() };
 | 
					    let req = proto::VmNodeFilters { ip, ..Default::default() };
 | 
				
			||||||
    Ok(block_on(grpc::get_one_node(req))?)
 | 
					    Ok(block_on(grpc::get_one_node(req))?)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn calculate_nanolp(
 | 
					pub fn calculate_nanocredits(
 | 
				
			||||||
    vcpus: u32,
 | 
					    vcpus: u32,
 | 
				
			||||||
    memory_mb: u32,
 | 
					    memory_mb: u32,
 | 
				
			||||||
    disk_size_gb: u32,
 | 
					    disk_size_mib: u32,
 | 
				
			||||||
    public_ipv4: bool,
 | 
					    public_ipv4: bool,
 | 
				
			||||||
    hours: u32,
 | 
					    hours: u32,
 | 
				
			||||||
    node_price: u64,
 | 
					    node_price: u64,
 | 
				
			||||||
@ -351,19 +468,9 @@ pub fn calculate_nanolp(
 | 
				
			|||||||
    // this calculation needs to match the calculation of the network
 | 
					    // this calculation needs to match the calculation of the network
 | 
				
			||||||
    let total_units = (vcpus as u64 * 10)
 | 
					    let total_units = (vcpus as u64 * 10)
 | 
				
			||||||
        + ((memory_mb + 256) as u64 / 200)
 | 
					        + ((memory_mb + 256) as u64 / 200)
 | 
				
			||||||
        + (disk_size_gb as u64 / 10)
 | 
					        + (disk_size_mib as u64 / 1024 / 10)
 | 
				
			||||||
        + (public_ipv4 as u64 * 10);
 | 
					        + (public_ipv4 as u64 * 10);
 | 
				
			||||||
    let locked_nano = hours as u64 * 60 * total_units * node_price;
 | 
					    let locked_nano = hours as u64 * 60 * total_units * node_price;
 | 
				
			||||||
    eprint!(
 | 
					 | 
				
			||||||
        "Node price: {}/unit/minute. Total Units for hardware requested: {}. ",
 | 
					 | 
				
			||||||
        node_price as f64 / 1_000_000_000.0,
 | 
					 | 
				
			||||||
        total_units,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    eprintln!(
 | 
					 | 
				
			||||||
        "Locking {} LP (offering the VM for {} hours).",
 | 
					 | 
				
			||||||
        locked_nano as f64 / 1_000_000_000.0,
 | 
					 | 
				
			||||||
        hours
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    locked_nano
 | 
					    locked_nano
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -12,8 +12,8 @@ use log::{debug, info};
 | 
				
			|||||||
pub struct Request {
 | 
					pub struct Request {
 | 
				
			||||||
    hostname: String,
 | 
					    hostname: String,
 | 
				
			||||||
    vcpus: u32,
 | 
					    vcpus: u32,
 | 
				
			||||||
    memory_mb: u32,
 | 
					    memory_mib: u32,
 | 
				
			||||||
    disk_size_gb: u32,
 | 
					    disk_size_mib: u32,
 | 
				
			||||||
    dtrfs: Option<Dtrfs>,
 | 
					    dtrfs: Option<Dtrfs>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -34,7 +34,7 @@ impl Request {
 | 
				
			|||||||
                Some(Dtrfs::load_from_file(path)?)
 | 
					                Some(Dtrfs::load_from_file(path)?)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let req = Self { hostname, vcpus, memory_mb, disk_size_gb, dtrfs };
 | 
					        let req = Self { hostname, vcpus, memory_mib: memory_mb, disk_size_mib: disk_size_gb, dtrfs };
 | 
				
			||||||
        if req == Self::default() {
 | 
					        if req == Self::default() {
 | 
				
			||||||
            log::info!("Skipping hardware upgrade (no arguments specified).");
 | 
					            log::info!("Skipping hardware upgrade (no arguments specified).");
 | 
				
			||||||
            return Ok(());
 | 
					            return Ok(());
 | 
				
			||||||
@ -55,7 +55,7 @@ impl Request {
 | 
				
			|||||||
        let updated_contract = block_on(grpc::get_contract_by_uuid(uuid))?;
 | 
					        let updated_contract = block_on(grpc::get_contract_by_uuid(uuid))?;
 | 
				
			||||||
        debug!("Got the current contract for the VM after update. {updated_contract:#?}");
 | 
					        debug!("Got the current contract for the VM after update. {updated_contract:#?}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if !(self.vcpus != 0 || self.dtrfs.is_some()) {
 | 
					        if !(self.vcpus != 0 || self.memory_mib != 0 || self.dtrfs.is_some()) {
 | 
				
			||||||
            eprintln!("vCPUs and kernel did not get modified. Secret injection is not required.");
 | 
					            eprintln!("vCPUs and kernel did not get modified. Secret injection is not required.");
 | 
				
			||||||
            return Ok(());
 | 
					            return Ok(());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -90,9 +90,9 @@ impl Request {
 | 
				
			|||||||
            uuid: uuid.to_string(),
 | 
					            uuid: uuid.to_string(),
 | 
				
			||||||
            hostname: self.hostname.clone(),
 | 
					            hostname: self.hostname.clone(),
 | 
				
			||||||
            admin_pubkey: Config::get_detee_wallet()?,
 | 
					            admin_pubkey: Config::get_detee_wallet()?,
 | 
				
			||||||
            disk_size_gb: self.disk_size_gb,
 | 
					            disk_size_mib: self.disk_size_mib * 1024,
 | 
				
			||||||
            vcpus: self.vcpus,
 | 
					            vcpus: self.vcpus,
 | 
				
			||||||
            memory_mb: self.memory_mb,
 | 
					            memory_mib: self.memory_mib * 1024,
 | 
				
			||||||
            kernel_url,
 | 
					            kernel_url,
 | 
				
			||||||
            kernel_sha,
 | 
					            kernel_sha,
 | 
				
			||||||
            dtrfs_url,
 | 
					            dtrfs_url,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										13
									
								
								src/utils.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										13
									
								
								src/utils.rs
									
									
									
									
									
								
							@ -45,6 +45,19 @@ pub fn shorten_string(my_string: &String) -> String {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn display_mib_or_gib(value: &u64) -> String {
 | 
				
			||||||
 | 
					    if *value >= 1024 {
 | 
				
			||||||
 | 
					        if *value < 102400 {
 | 
				
			||||||
 | 
					            let value = (value / 102) as f64;
 | 
				
			||||||
 | 
					            format!("{}G", value / 10_f64)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            format!("{}G", value / 1024)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        format!("{}M", value)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[macro_export]
 | 
					#[macro_export]
 | 
				
			||||||
macro_rules! call_with_follow_redirect {
 | 
					macro_rules! call_with_follow_redirect {
 | 
				
			||||||
    (
 | 
					    (
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user