From 341c2d1bf2b237353a21dd25300c3d4a8d0ca5d3 Mon Sep 17 00:00:00 2001 From: greg Date: Mon, 20 May 2024 21:39:48 +0000 Subject: [PATCH] wip. getting error --- Cargo.lock | 19 ++++++++++ Cargo.toml | 3 +- src/client_config.rs | 6 +-- src/docker.rs | 23 +++++------- src/genesis.rs | 84 ++++++++++++++++++++---------------------- src/kubernetes.rs | 6 +-- src/ledger_helper.rs | 2 - src/main.rs | 75 +++++++++++++++++++------------------ src/startup_scripts.rs | 12 +++--- 9 files changed, 118 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e73d20..6d15f2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4737,6 +4737,24 @@ dependencies = [ "url 2.5.0", ] +[[package]] +name = "solana-clap-v3-utils" +version = "1.18.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab05348a84bbf3e81a70117d24ca46ce62343530ddfe9e8d84fb95a8061d59b" +dependencies = [ + "chrono", + "clap 3.2.25", + "rpassword", + "solana-remote-wallet", + "solana-sdk", + "solana-zk-token-sdk", + "thiserror", + "tiny-bip39", + "uriparse", + "url 2.5.0", +] + [[package]] name = "solana-cli-config" version = "1.18.9" @@ -7136,6 +7154,7 @@ dependencies = [ "rustc_version", "rustls", "solana-accounts-db", + "solana-clap-v3-utils", "solana-core", "solana-ledger", "solana-logger", diff --git a/Cargo.toml b/Cargo.toml index 3b630c4..8202d2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" [dependencies] bzip2 = "0.4.4" -clap = { version = "3.2.22", features = ["cargo"] } +clap = { version = "3.2.22", features = ["cargo"] } console = "0.15.8" git2 = "0.18.3" indicatif = "0.17.8" @@ -20,6 +20,7 @@ rand = "0.8.5" reqwest = { version = "0.11.23", features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] } rustls = { version = "0.21.11", default-features = false, features = ["quic"] } solana-accounts-db = "1.18.8" +solana-clap-v3-utils = "1.18.8" solana-core = "1.18.8" solana-ledger = "1.18.8" solana-logger = "1.18.8" diff --git a/src/client_config.rs b/src/client_config.rs index 7323389..e38ca98 100644 --- a/src/client_config.rs +++ b/src/client_config.rs @@ -6,7 +6,7 @@ pub struct ClientConfig { pub client_type: String, pub client_to_run: String, pub bench_tps_args: Vec, - pub target_node: Option, - pub duration: u64, - pub num_nodes: Option, + pub client_target_node: Option, + pub client_duration_seconds: u64, + pub client_wait_for_n_nodes: Option, } diff --git a/src/docker.rs b/src/docker.rs index 447247f..1846f0f 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -135,7 +135,6 @@ impl DockerConfig { return Err(output.status.to_string().into()); } progress_bar.finish_and_clear(); - info!("{validator_type} image build complete"); Ok(()) } @@ -193,18 +192,14 @@ USER solana COPY --chown=solana:solana {startup_script_directory} /home/solana/k8s-cluster-scripts RUN chmod +x /home/solana/k8s-cluster-scripts/* COPY --chown=solana:solana ./config-k8s/bootstrap-validator /home/solana/ledger -COPY --chown=solana:solana ./{solana_build_directory}/bin/ /home/solana/bin/ +COPY --chown=solana:solana ./{solana_build_directory}/bin/ /home/solana/.cargo/bin/ COPY --chown=solana:solana ./{solana_build_directory}/version.yml /home/solana/ -ENV PATH="/home/solana/bin:${{PATH}}" +ENV PATH="/home/solana/.cargo/bin:${{PATH}}" WORKDIR /home/solana +{} "#, - self.base_image - ); - - let dockerfile = format!( - "{dockerfile}\n{}", - self.insert_client_accounts_if_present(solana_root_path, validator_type)?, + self.base_image, self.insert_client_accounts_if_present(solana_root_path, validator_type)? ); debug!("dockerfile: {dockerfile:?}"); @@ -228,10 +223,10 @@ WORKDIR /home/solana Ok(format!( r#" COPY --chown=solana:solana ./config-k8s/bench-tps-{index}.yml /home/solana/client-accounts.yml - "#, - )) + "# + )) } else { - Err(format!("{:?} does not exist!", bench_tps_path).into()) + Err(format!("{bench_tps_path:?} does not exist!").into()) } } ValidatorType::Bootstrap => { @@ -240,9 +235,9 @@ COPY --chown=solana:solana ./config-k8s/bench-tps-{index}.yml /home/solana/clien Ok(r#" COPY --chown=solana:solana ./config-k8s/client-accounts.yml /home/solana "# - .to_string()) + .to_string()) } else { - Err(format!("{:?} does not exist!", client_accounts_path).into()) + Err(format!("{client_accounts_path:?} does not exist!").into()) } } ValidatorType::Standard | ValidatorType::RPC => Ok("".to_string()), diff --git a/src/genesis.rs b/src/genesis.rs index 640bec0..103b270 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -96,28 +96,24 @@ impl std::fmt::Display for GenesisFlags { } fn append_client_accounts_to_file( - in_file: &PathBuf, //bench-tps-i.yml - out_file: &PathBuf, //client-accounts.yml + bench_tps_account_path: &PathBuf, //bench-tps-i.yml + client_accounts_path: &PathBuf, //client-accounts.yml ) -> io::Result<()> { // Open the bench-tps-i.yml file for reading. - let input = File::open(in_file)?; + let input = File::open(bench_tps_account_path)?; let reader = io::BufReader::new(input); // Open (or create) client-accounts.yml let output = OpenOptions::new() .create(true) .append(true) - .open(out_file)?; + .open(client_accounts_path)?; let mut writer = BufWriter::new(output); - // Enumerate the lines of the input file, starting from 1. - for (index, line) in reader.lines().enumerate().map(|(i, l)| (i + 1, l)) { + // Skip first line since it is a header aka "---" in a yaml + for line in reader.lines().skip(1) { let line = line?; - - // Skip first line since it is a header aka "---" in a yaml - if (index as u64) > 1 { - writeln!(writer, "{line}")?; - } + writeln!(writer, "{line}")?; } Ok(()) @@ -159,10 +155,6 @@ impl Genesis { validator_type: ValidatorType, number_of_accounts: usize, ) -> Result<(), Box> { - if let ValidatorType::Client(_) = validator_type { - return Err("Client valdiator_type in generate_accounts not allowed".into()); - } - info!("generating {number_of_accounts} {validator_type} accounts..."); let account_types = match validator_type { @@ -172,7 +164,7 @@ impl Genesis { ValidatorType::RPC => { vec!["identity"] // no vote or stake account for RPC } - ValidatorType::Client(_) => panic!("Client type not supported"), + ValidatorType::Client(_) => return Err("Client valdiator_type in generate_accounts not allowed".into()), }; let total_accounts_to_generate = number_of_accounts * account_types.len(); @@ -222,36 +214,16 @@ impl Genesis { if number_of_clients == 0 { return Ok(()); } + let client_accounts_file = config_dir.join("client-accounts.yml"); + let progress_bar = new_spinner_progress_bar(); + progress_bar.set_message(format!("{WRITING}Creating and writing client accounts...")); + info!("generating {number_of_clients} client account(s)..."); - let children: Result, _> = (0..number_of_clients) .map(|i| { - info!("client account: {i}"); - let mut args = Vec::new(); - let account_path = config_dir.join(format!("bench-tps-{i}.yml")); - args.push("--write-client-keys".to_string()); - args.push(account_path.into_os_string().into_string().map_err(|err| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("Invalid Unicode data in path: {:?}", err), - ) - })?); - args.push("--target-lamports-per-signature".to_string()); - args.push(target_lamports_per_signature.to_string()); - - if !bench_tps_args.is_empty() { - args.extend(bench_tps_args.to_owned()); - } - - let executable_path = if let DeployMethod::ReleaseChannel(_) = deploy_method { - solana_root_path.join("solana-release/bin/solana-bench-tps") - } else { - solana_root_path.join("farf/bin/solana-bench-tps") - }; - - Self::create_client_account(&args, &executable_path) + Self::create_client_account(i, config_dir, target_lamports_per_signature, bench_tps_args, deploy_method, solana_root_path) }) .collect(); @@ -262,8 +234,6 @@ impl Genesis { } } - let progress_bar = new_spinner_progress_bar(); - progress_bar.set_message(format!("{WRITING}Writing client accounts...")); for i in 0..number_of_clients { let account_path = config_dir.join(format!("bench-tps-{i}.yml")); append_client_accounts_to_file(&account_path, &client_accounts_file)?; @@ -275,9 +245,33 @@ impl Genesis { } fn create_client_account( - args: &Vec, - executable_path: &PathBuf, + client_index: usize, + config_dir: &Path, + target_lamports_per_signature: u64, + bench_tps_args: &[String], + deploy_method: &DeployMethod, + solana_root_path: &Path, ) -> Result> { + info!("client account: {client_index}"); + let mut args = Vec::new(); + let account_path = config_dir.join(format!("bench-tps-{client_index}.yml")); + args.push("--write-client-keys".to_string()); + args.push(account_path.into_os_string().into_string().map_err(|err| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Invalid Unicode data in path: {:?}", err), + ) + })?); + args.push("--target-lamports-per-signature".to_string()); + args.push(target_lamports_per_signature.to_string()); + + args.extend_from_slice(bench_tps_args); + + let executable_path = if let DeployMethod::ReleaseChannel(_) = deploy_method { + solana_root_path.join("solana-release/bin/solana-bench-tps") + } else { + solana_root_path.join("farf/bin/solana-bench-tps") + }; let child = Command::new(executable_path) .args(args) .stdout(Stdio::null()) diff --git a/src/kubernetes.rs b/src/kubernetes.rs index 0c62d58..560bedb 100644 --- a/src/kubernetes.rs +++ b/src/kubernetes.rs @@ -310,15 +310,15 @@ impl<'a> Kubernetes<'a> { flags.push(self.client_config.client_type.clone()); - if let Some(target_node) = self.client_config.target_node { + if let Some(target_node) = self.client_config.client_target_node { flags.push("--target-node".to_string()); flags.push(target_node.to_string()); } flags.push("--duration".to_string()); - flags.push(self.client_config.duration.to_string()); + flags.push(self.client_config.client_duration_seconds.to_string()); - if let Some(num_nodes) = self.client_config.num_nodes { + if let Some(num_nodes) = self.client_config.client_wait_for_n_nodes { flags.push("--num-nodes".to_string()); flags.push(num_nodes.to_string()); } diff --git a/src/ledger_helper.rs b/src/ledger_helper.rs index 9f369b3..e484738 100644 --- a/src/ledger_helper.rs +++ b/src/ledger_helper.rs @@ -1,6 +1,5 @@ use { crate::genesis::DEFAULT_MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, - log::*, solana_accounts_db::hardened_unpack::open_genesis_config, solana_sdk::shred_version::compute_shred_version, std::{error::Error, path::Path}, @@ -25,7 +24,6 @@ impl LedgerHelper { let genesis_config = open_genesis_config(ledger_dir, DEFAULT_MAX_GENESIS_ARCHIVE_UNPACKED_SIZE); let shred_version = compute_shred_version(&genesis_config?.hash(), None); - info!("Shred Version: {}", shred_version); Ok(shred_version) } } diff --git a/src/main.rs b/src/main.rs index 966d66a..4b446bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ use { clap::{command, value_t_or_exit, Arg, ArgGroup}, log::*, + solana_clap_v3_utils::input_parsers::pubkey_of, solana_ledger::blockstore_cleanup_service::{ DEFAULT_MAX_LEDGER_SHREDS, DEFAULT_MIN_MAX_LEDGER_SHREDS, }, - solana_sdk::{pubkey::Pubkey, signature::keypair::read_keypair_file, signer::Signer}, + solana_sdk::{signature::keypair::read_keypair_file, signer::Signer}, std::{fs, path::PathBuf, result::Result}, strum::VariantNames, validator_lab::{ @@ -244,7 +245,7 @@ fn parse_matches() -> clap::ArgMatches { .short('c') .takes_value(true) .default_value("0") - .help("Number of clients ") + .help("Number of clients") ) .arg( Arg::with_name("client_type") @@ -278,25 +279,28 @@ fn parse_matches() -> clap::ArgMatches { to the bench-tps client."), ) .arg( - Arg::with_name("target_node") - .long("target-node") + Arg::with_name("client_target_node") + .long("client-target-node") .takes_value(true) - .help("Client Config. Optional: Specify an exact node to send transactions to. use: --target-node . + .value_name("PUBKEY") + .help("Client Config. Optional: Specify an exact node to send transactions to Not supported yet. TODO..."), ) .arg( - Arg::with_name("duration") - .long("duration") + Arg::with_name("client_duration_seconds") + .long("client-duration-seconds") .takes_value(true) .default_value("7500") - .help("Client Config. Seconds to run benchmark, then exit; default is forever use: --duration "), + .value_name("SECS") + .help("Client Config. Seconds to run benchmark, then exit"), ) .arg( - Arg::with_name("num_nodes") - .long("num-nodes") + Arg::with_name("client_wait_for_n_nodes") + .long("client-wait-for-n-nodes") .short('N') .takes_value(true) - .help("Client Config. Optional: Wait for NUM nodes to converge: --num-nodes "), + .value_name("NUM") + .help("Client Config. Optional: Wait for NUM nodes to converge"), ) // kubernetes config .arg( @@ -370,24 +374,18 @@ async fn main() -> Result<(), Box> { num_clients: value_t_or_exit!(matches, "number_of_clients", usize), client_type: matches .value_of("client_type") - .unwrap_or_default() + .unwrap() .to_string(), client_to_run: matches .value_of("client_to_run") - .unwrap_or_default() + .unwrap() .to_string(), bench_tps_args: parse_and_format_bench_tps_args(matches.value_of("bench_tps_args")), - target_node: match matches.value_of("target_node") { - Some(s) => match s.parse::() { - Ok(pubkey) => Some(pubkey), - Err(e) => return Err(format!("failed to parse pubkey in target_node: {e}").into()), - }, - None => None, - }, - duration: value_t_or_exit!(matches, "duration", u64), - num_nodes: matches - .value_of("num_nodes") - .map(|value_str| value_str.parse().expect("Invalid value for num_nodes")), + client_target_node: pubkey_of(&matches, "client_target_node"), + client_duration_seconds: value_t_or_exit!(matches, "client_duration_seconds", u64), + client_wait_for_n_nodes: matches + .value_of("client_wait_for_n_nodes") + .map(|value_str| value_str.parse().expect("Invalid value for client_wait_for_n_nodes")), }; let deploy_method = if let Some(local_path) = matches.value_of("local_path") { @@ -543,7 +541,7 @@ async fn main() -> Result<(), Box> { } build_config.prepare().await?; - info!("Validator setup prepared successfully"); + info!("Setup Validator Environment"); let config_directory = solana_root.get_root_path().join("config-k8s"); let mut genesis = Genesis::new(config_directory.clone(), genesis_flags); @@ -580,6 +578,7 @@ async fn main() -> Result<(), Box> { let ledger_dir = config_directory.join("bootstrap-validator"); let shred_version = LedgerHelper::get_shred_version(&ledger_dir)?; kub_controller.set_shred_version(shred_version); + info!("Shred Version: {shred_version}"); //unwraps are safe here. since their requirement is enforced by argmatches let docker = DockerConfig::new( @@ -658,7 +657,7 @@ async fn main() -> Result<(), Box> { kub_controller .deploy_secret(bootstrap_validator.secret()) .await?; - info!("Bootstrap Secret deployed"); + info!("Deployed Bootstrap Secret"); // Create Bootstrap labels // Bootstrap needs two labels, one for each service. @@ -701,7 +700,7 @@ async fn main() -> Result<(), Box> { kub_controller .deploy_replicas_set(bootstrap_validator.replica_set()) .await?; - info!("{} deployed", bootstrap_validator.replica_set_name()); + info!("Deployed {}", bootstrap_validator.replica_set_name()); // create and deploy bootstrap-service let bootstrap_service = kub_controller.create_service( @@ -709,7 +708,7 @@ async fn main() -> Result<(), Box> { bootstrap_validator.service_labels(), ); kub_controller.deploy_service(&bootstrap_service).await?; - info!("Bootstrap Balidator Service deployed"); + info!("Deployed Bootstrap Balidator Service"); // load balancer service. only create one and use for all bootstrap/rpc nodes // service selector matches bootstrap selector @@ -721,7 +720,7 @@ async fn main() -> Result<(), Box> { //deploy load balancer kub_controller.deploy_service(&load_balancer).await?; - info!("Load Balancer Service deployed"); + info!("Deployed Load Balancer Service"); // wait for bootstrap replicaset to deploy while !kub_controller @@ -743,7 +742,7 @@ async fn main() -> Result<(), Box> { let rpc_secret = kub_controller.create_rpc_secret(rpc_index, &config_directory)?; rpc_node.set_secret(rpc_secret); kub_controller.deploy_secret(rpc_node.secret()).await?; - info!("RPC Node {rpc_index} Secret deployed"); + info!("Deployed RPC Node {rpc_index} Secret"); let identity_path = config_directory.join(format!("rpc-node-identity-{rpc_index}.json")); @@ -785,14 +784,14 @@ async fn main() -> Result<(), Box> { kub_controller .deploy_replicas_set(rpc_node.replica_set()) .await?; - info!("RPC Node Replica Set ({rpc_index}) deployed"); + info!("Deployed RPC Node Replica Set ({rpc_index})"); let rpc_service = kub_controller.create_service( &format!("rpc-node-service-{rpc_index}"), rpc_node.service_labels(), ); kub_controller.deploy_service(&rpc_service).await?; - info!("RPC Node Service ({rpc_index}) deployed"); + info!("Deployed RPC Node Service ({rpc_index})"); rpc_nodes.push(rpc_node.replica_set_name().clone()); } @@ -818,7 +817,7 @@ async fn main() -> Result<(), Box> { kub_controller.create_validator_secret(validator_index, &config_directory)?; validator.set_secret(validator_secret); kub_controller.deploy_secret(validator.secret()).await?; - info!("Validator {validator_index} Secret deployed"); + info!("Deployed Validator {validator_index} Secret"); let identity_path = config_directory.join(format!("validator-identity-{validator_index}.json")); @@ -852,14 +851,14 @@ async fn main() -> Result<(), Box> { kub_controller .deploy_replicas_set(validator.replica_set()) .await?; - info!("Validator Replica Set ({validator_index}) deployed"); + info!("Deployed Validator Replica Set ({validator_index})"); let validator_service = kub_controller.create_service( &format!("validator-service-{validator_index}"), validator.service_labels(), ); kub_controller.deploy_service(&validator_service).await?; - info!("Validator Service ({validator_index}) deployed"); + info!("Deployed Validator Service ({validator_index})"); } } @@ -874,7 +873,7 @@ async fn main() -> Result<(), Box> { client.set_secret(client_secret); kub_controller.deploy_secret(client.secret()).await?; - info!("Client {client_index} Secret deployed"); + info!("Deployed Client {client_index} Secret"); client.add_label( "client/name", @@ -893,14 +892,14 @@ async fn main() -> Result<(), Box> { kub_controller .deploy_replicas_set(client.replica_set()) .await?; - info!("Client Replica Set ({client_index}) deployed"); + info!("Deployed Client Replica Set ({client_index})"); let client_service = kub_controller.create_service( &format!("client-service-{client_index}"), client.service_labels(), ); kub_controller.deploy_service(&client_service).await?; - info!("Client Service ({client_index}) deployed"); + info!("Deployed Client Service ({client_index})"); } Ok(()) diff --git a/src/startup_scripts.rs b/src/startup_scripts.rs index 7412057..8bc1868 100644 --- a/src/startup_scripts.rs +++ b/src/startup_scripts.rs @@ -32,8 +32,8 @@ source /home/solana/k8s-cluster-scripts/common.sh no_restart=0 # Define the paths to the validator cli. pre 1.18 is `solana-validator`. post 1.18 is `agave-validator` -agave_validator="/home/solana/bin/agave-validator" -solana_validator="/home/solana/bin/solana-validator" +agave_validator="/home/solana/.cargo/bin/agave-validator" +solana_validator="/home/solana/.cargo/bin/solana-validator" # Initialize program variable program="" @@ -238,8 +238,8 @@ ledger_dir=/home/solana/ledger faucet_address=$LOAD_BALANCER_FAUCET_ADDRESS # Define the paths to the validator cli. pre 1.18 is `solana-validator`. post 1.18 is `agave-validator` -agave_validator="/home/solana/bin/agave-validator" -solana_validator="/home/solana/bin/solana-validator" +agave_validator="/home/solana/.cargo/bin/agave-validator" +solana_validator="/home/solana/.cargo/bin/solana-validator" # Initialize program variable program="" @@ -658,8 +658,8 @@ ledger_dir=/home/solana/ledger faucet_address=$LOAD_BALANCER_FAUCET_ADDRESS # Define the paths to the validator cli. pre 1.18 is `solana-validator`. post 1.18 is `agave-validator` -agave_validator="/home/solana/bin/agave-validator" -solana_validator="/home/solana/bin/solana-validator" +agave_validator="/home/solana/.cargo/bin/agave-validator" +solana_validator="/home/solana/.cargo/bin/solana-validator" # Initialize program variable program=""