Add stop node command to solana-gossip (#3928)

This commit is contained in:
Michael Vines 2019-04-22 14:51:20 -07:00 committed by GitHub
parent 95a16426f3
commit 05bcb7f292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 129 additions and 76 deletions

1
Cargo.lock generated
View File

@ -2483,6 +2483,7 @@ dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"solana 0.14.0", "solana 0.14.0",
"solana-client 0.14.0",
"solana-netutil 0.14.0", "solana-netutil 0.14.0",
"solana-sdk 0.14.0", "solana-sdk 0.14.0",
] ]

View File

@ -41,7 +41,7 @@ Inspect the blockexplorer at [http://beta.testnet.solana.com/](http://beta.testn
Run the following command to join the gossip network and view all the other nodes in the cluster: Run the following command to join the gossip network and view all the other nodes in the cluster:
```bash ```bash
$ solana-gossip --network beta.testnet.solana.com:8001 $ solana-gossip --network beta.testnet.solana.com:8001 spy
``` ```
View the [metrics dashboard]( View the [metrics dashboard](

View File

@ -306,8 +306,7 @@ while [[ $iteration -le $iterations ]]; do
set -x set -x
client_id=/tmp/client-id.json-$$ client_id=/tmp/client-id.json-$$
$solana_keygen -o $client_id || exit $? $solana_keygen -o $client_id || exit $?
$solana_gossip \ $solana_gossip spy --num-nodes-exactly $numNodes || exit $?
--num-nodes-exactly $numNodes || exit $?
rm -rf $client_id rm -rf $client_id
) || flag_error ) || flag_error

View File

@ -12,6 +12,7 @@ homepage = "https://solana.com/"
clap = "2.33.0" clap = "2.33.0"
env_logger = "0.6.1" env_logger = "0.6.1"
solana = { path = "../core", version = "0.14.0" } solana = { path = "../core", version = "0.14.0" }
solana-client = { path = "../client", version = "0.14.0" }
solana-netutil = { path = "../netutil", version = "0.14.0" } solana-netutil = { path = "../netutil", version = "0.14.0" }
solana-sdk = { path = "../sdk", version = "0.14.0" } solana-sdk = { path = "../sdk", version = "0.14.0" }

View File

@ -1,7 +1,9 @@
//! A command-line executable for monitoring a cluster's gossip plane. //! A command-line executable for monitoring a cluster's gossip plane.
use clap::{crate_description, crate_name, crate_version, App, Arg}; use clap::{crate_description, crate_name, crate_version, App, AppSettings, Arg, SubCommand};
use solana::contact_info::ContactInfo;
use solana::gossip_service::discover; use solana::gossip_service::discover;
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use std::error; use std::error;
use std::net::SocketAddr; use std::net::SocketAddr;
@ -22,6 +24,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
let matches = App::new(crate_name!()) let matches = App::new(crate_name!())
.about(crate_description!()) .about(crate_description!())
.version(crate_version!()) .version(crate_version!())
.setting(AppSettings::SubcommandRequiredElseHelp)
.arg( .arg(
Arg::with_name("network") Arg::with_name("network")
.short("n") .short("n")
@ -31,38 +34,58 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.default_value(&network_string) .default_value(&network_string)
.help("Rendezvous with the cluster at this gossip entry point"), .help("Rendezvous with the cluster at this gossip entry point"),
) )
.arg( .subcommand(
Arg::with_name("num_nodes") SubCommand::with_name("spy")
.short("N") .about("Monitor the gossip network")
.long("num-nodes") .setting(AppSettings::DisableVersion)
.value_name("NUM") .arg(
.takes_value(true) Arg::with_name("num_nodes")
.conflicts_with("num_nodes_exactly") .short("N")
.help("Wait for at least NUM nodes to converge"), .long("num-nodes")
.value_name("NUM")
.takes_value(true)
.conflicts_with("num_nodes_exactly")
.help("Wait for at least NUM nodes to converge"),
)
.arg(
Arg::with_name("num_nodes_exactly")
.short("E")
.long("num-nodes-exactly")
.value_name("NUM")
.takes_value(true)
.help("Wait for exactly NUM nodes to converge"),
)
.arg(
Arg::with_name("node_pubkey")
.short("p")
.long("pubkey")
.value_name("PUBKEY")
.takes_value(true)
.validator(pubkey_validator)
.help("Public key of a specific node to wait for"),
)
.arg(
Arg::with_name("timeout")
.long("timeout")
.value_name("SECS")
.takes_value(true)
.help(
"Maximum time to wait for cluster to converge [default: wait forever]",
),
),
) )
.arg( .subcommand(
Arg::with_name("num_nodes_exactly") SubCommand::with_name("stop")
.short("E") .about("Send stop request to a node")
.long("num-nodes-exactly") .setting(AppSettings::DisableVersion)
.value_name("NUM") .arg(
.takes_value(true) Arg::with_name("node_pubkey")
.help("Wait for exactly NUM nodes to converge"), .index(1)
) .required(true)
.arg( .value_name("PUBKEY")
Arg::with_name("node_pubkey") .validator(pubkey_validator)
.short("p") .help("Public key of a specific node to stop"),
.long("pubkey") ),
.value_name("PUBKEY")
.takes_value(true)
.validator(pubkey_validator)
.help("Public key of a specific node to wait for"),
)
.arg(
Arg::with_name("timeout")
.long("timeout")
.value_name("SECS")
.takes_value(true)
.help("Maximum time to wait for cluster to converge [default: wait forever]"),
) )
.get_matches(); .get_matches();
@ -72,48 +95,74 @@ fn main() -> Result<(), Box<dyn error::Error>> {
exit(1) exit(1)
}); });
} }
match matches.subcommand() {
("spy", Some(matches)) => {
let num_nodes_exactly = matches
.value_of("num_nodes_exactly")
.map(|num| num.to_string().parse().unwrap());
let num_nodes = matches
.value_of("num_nodes")
.map(|num| num.to_string().parse().unwrap())
.or(num_nodes_exactly);
let timeout = matches
.value_of("timeout")
.map(|secs| secs.to_string().parse().unwrap());
let pubkey = matches
.value_of("node_pubkey")
.map(|pubkey_str| pubkey_str.parse::<Pubkey>().unwrap());
let num_nodes_exactly = matches let nodes = discover(&network_addr, num_nodes, timeout, pubkey)?;
.value_of("num_nodes_exactly")
.map(|num| num.to_string().parse().unwrap());
let num_nodes = matches
.value_of("num_nodes")
.map(|num| num.to_string().parse().unwrap())
.or(num_nodes_exactly);
let timeout = matches
.value_of("timeout")
.map(|secs| secs.to_string().parse().unwrap());
let pubkey = matches
.value_of("node_pubkey")
.map(|pubkey_str| pubkey_str.parse::<Pubkey>().unwrap());
let nodes = discover(&network_addr, num_nodes, timeout, pubkey)?; if timeout.is_some() {
if let Some(num) = num_nodes {
if timeout.is_some() { if nodes.len() < num {
if let Some(num) = num_nodes { let add = if num_nodes_exactly.is_some() {
if nodes.len() < num { ""
let add = if num_nodes_exactly.is_some() { } else {
"" " or more"
} else { };
" or more" eprintln!(
}; "Error: Insufficient nodes discovered. Expecting {}{}",
num, add,
);
}
}
if let Some(node) = pubkey {
if nodes.iter().find(|x| x.id == node).is_none() {
eprintln!("Error: Could not find node {:?}", node);
}
}
}
if num_nodes_exactly.is_some() && nodes.len() > num_nodes_exactly.unwrap() {
eprintln!( eprintln!(
"Error: Insufficient nodes discovered. Expecting {}{}", "Error: Extra nodes discovered. Expecting exactly {}",
num, add, num_nodes_exactly.unwrap()
); );
} }
} }
if let Some(node) = pubkey { ("stop", Some(matches)) => {
if nodes.iter().find(|x| x.id == node).is_none() { let pubkey = matches
eprintln!("Error: Could not find node {:?}", node); .value_of("node_pubkey")
.unwrap()
.parse::<Pubkey>()
.unwrap();
let nodes = discover(&network_addr, None, None, Some(pubkey))?;
let node = nodes.iter().find(|x| x.id == pubkey).unwrap();
if !ContactInfo::is_valid_address(&node.rpc) {
eprintln!("Error: RPC service is not enabled on node {:?}", pubkey);
}
println!("\nSending stop request to node {:?}", pubkey);
let result = RpcClient::new_socket(node.rpc).fullnode_exit()?;
if result {
println!("Stop signal accepted");
} else {
eprintln!("Error: Stop signal ignored");
} }
} }
_ => unreachable!(),
} }
if num_nodes_exactly.is_some() && nodes.len() > num_nodes_exactly.unwrap() {
eprintln!(
"Error: Extra nodes discovered. Expecting exactly {}",
num_nodes_exactly.unwrap()
);
}
Ok(()) Ok(())
} }

View File

@ -81,12 +81,13 @@ local|tar)
fi fi
./multinode-demo/drone.sh > drone.log 2>&1 & ./multinode-demo/drone.sh > drone.log 2>&1 &
maybePublicAddress= args=()
if $publicNetwork; then if $publicNetwork; then
maybePublicAddress="--public-address" args+=(--public-address)
fi fi
args+=(--enable-rpc-exit)
./multinode-demo/bootstrap-leader.sh $maybePublicAddress > bootstrap-leader.log 2>&1 & ./multinode-demo/bootstrap-leader.sh "${args[@]}" > bootstrap-leader.log 2>&1 &
ln -sTf bootstrap-leader.log fullnode.log ln -sTf bootstrap-leader.log fullnode.log
;; ;;
fullnode|blockstreamer) fullnode|blockstreamer)
@ -116,6 +117,7 @@ local|tar)
fi fi
args+=( args+=(
--enable-rpc-exit
--gossip-port 8001 --gossip-port 8001
--rpc-port 8899 --rpc-port 8899
) )
@ -147,7 +149,9 @@ local|tar)
# Confirm the blockexplorer is now globally accessible # Confirm the blockexplorer is now globally accessible
curl --head "$(curl ifconfig.io)" curl --head "$(curl ifconfig.io)"
fi fi
./multinode-demo/fullnode.sh "${args[@]}" "$entrypointIp":~/solana "$entrypointIp:8001" > fullnode.log 2>&1 &
args+=("$entrypointIp":~/solana "$entrypointIp:8001")
./multinode-demo/fullnode.sh "${args[@]}" > fullnode.log 2>&1 &
;; ;;
*) *)
echo "Error: unknown node type: $nodeType" echo "Error: unknown node type: $nodeType"

View File

@ -89,9 +89,8 @@ echo "+++ $entrypointIp: node count ($numNodes expected)"
nodeArg="num-nodes-exactly" nodeArg="num-nodes-exactly"
fi fi
timeout 2m $solana_gossip \ timeout 2m $solana_gossip --network "$entrypointIp:8001" \
--network "$entrypointIp:8001" \ spy --$nodeArg "$numNodes" \
--$nodeArg "$numNodes" \
) )
echo "--- RPC API: getTransactionCount" echo "--- RPC API: getTransactionCount"