Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(network): perform random interval network churns #94

Merged
merged 2 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,8 +684,14 @@ impl TestnetDeploy {
// The VM list includes the genesis node and the build machine, hence the subtraction of 2
// from the total VM count. After that, add one node for genesis, since this machine only
// runs a single node.
let mut node_count = (vm_list.len() - 2) as u16 * node_instance_count.unwrap_or(0);
node_count += 1;
let node_count = {
let vms_to_ignore = if build_inventory.is_empty() { 1 } else { 2 };
let mut node_count =
(vm_list.len() - vms_to_ignore) as u16 * node_instance_count.unwrap_or(0);
node_count += 1;
node_count
};

let inventory = DeploymentInventory {
name: name.to_string(),
node_count,
Expand Down
109 changes: 80 additions & 29 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,36 +359,62 @@ enum LogstashCommands {
#[derive(Subcommand, Debug)]
enum NetworkCommands {
/// Restart nodes in the testnet to simulate the churn of nodes.
ChurnNodes {
#[clap(name = "churn", subcommand)]
ChurnCommands(ChurnCommands),
/// Modifies the log levels for all the safenode services through RPC requests.
UpdateNodeLogLevel {
/// The name of the environment
#[arg(short = 'n', long)]
name: String,
/// The log level to set.
///
/// Example: --log-level SN_LOG=all,RUST_LOG=libp2p=debug
#[clap(long)]
log_level: String,
/// The number of nodes to update concurrently.
#[clap(long, short = 'c', default_value_t = 10)]
concurrent_updates: usize,
},
}

#[derive(Subcommand, Debug)]
enum ChurnCommands {
/// Churn nodes at fixed intervals.
FixedInterval {
/// The name of the environment.
#[arg(short = 'n', long)]
name: String,
/// The interval at which the nodes should be restarted.
/// The interval between each node churn.
#[clap(long, value_parser = |t: &str| -> Result<Duration> { Ok(t.parse().map(Duration::from_secs)?)}, default_value = "60")]
interval: Duration,
/// The number of nodes to restart concurrently per VM.
#[clap(long, short = 'c', default_value_t = 2)]
concurrent_churns: usize,
/// Set to false to restart the node with a different PeerId.
/// Whether to retain the same PeerId on restart.
#[clap(long, default_value_t = false)]
retain_peer_id: bool,
/// The number of time each node in the network is restarted.
#[clap(long, default_value_t = 1)]
churn_cycles: usize,
},
/// Modifies the log levels for all the safenode services through RPC requests.
UpdateNodeLogLevel {
/// The name of the environment
/// Churn nodes at random intervals.
RandomInterval {
/// The name of the environment.
#[arg(short = 'n', long)]
name: String,
/// The log level to set.
///
/// Example: --log-level SN_LOG=all,RUST_LOG=libp2p=debug
#[clap(long)]
log_level: String,
/// The number of nodes to update concurrently.
#[clap(long, short = 'c', default_value_t = 10)]
concurrent_updates: usize,
/// The time frame in which the churn_count nodes are restarted.
/// Nodes are restarted at a rate of churn_count/time_frame with random delays between each restart.
#[clap(long, value_parser = |t: &str| -> Result<Duration> { Ok(t.parse().map(Duration::from_secs)?)}, default_value = "600")]
time_frame: Duration,
/// Number of nodes to restart in the given time frame.
#[clap(long, default_value_t = 10)]
churn_count: usize,
/// Whether to retain the same PeerId on restart.
#[clap(long, default_value_t = false)]
retain_peer_id: bool,
/// The number of time each node in the network is restarted.
#[clap(long, default_value_t = 1)]
churn_cycles: usize,
},
}

Expand Down Expand Up @@ -561,28 +587,53 @@ async fn main() -> Result<()> {
Ok(())
}
},
Commands::Network(NetworkCommands::ChurnNodes {
name,
interval,
concurrent_churns,
retain_peer_id,
churn_cycles,
}) => {
Commands::Network(NetworkCommands::ChurnCommands(churn_cmds)) => {
let name = match &churn_cmds {
ChurnCommands::FixedInterval { name, .. } => name,
ChurnCommands::RandomInterval { name, .. } => name,
};
let inventory_path = get_data_directory()?.join(format!("{name}-inventory.json"));
if !inventory_path.exists() {
return Err(eyre!("There is no inventory for the {name} testnet")
.suggestion("Please run the inventory command to generate it"));
}

let inventory = DeploymentInventory::read(&inventory_path)?;
network_commands::perform_network_churns(
inventory,
interval,
concurrent_churns,
retain_peer_id,
churn_cycles,
)
.await?;

match churn_cmds {
ChurnCommands::FixedInterval {
name: _,
interval,
concurrent_churns,
retain_peer_id,
churn_cycles,
} => {
network_commands::perform_fixed_interval_network_churn(
inventory,
interval,
concurrent_churns,
retain_peer_id,
churn_cycles,
)
.await?;
}
ChurnCommands::RandomInterval {
name: _,
time_frame,
churn_count,
retain_peer_id,
churn_cycles,
} => {
network_commands::perform_random_interval_network_churn(
inventory,
time_frame,
churn_count,
retain_peer_id,
churn_cycles,
)
.await?;
}
}
Ok(())
}
Commands::Network(NetworkCommands::UpdateNodeLogLevel {
Expand Down
Loading
Loading