validator: add contact-info query to admin port
This commit is contained in:
committed by
mergify[bot]
parent
17d698d20a
commit
685e40cbf2
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5822,6 +5822,7 @@ dependencies = [
|
|||||||
"num_cpus",
|
"num_cpus",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"solana-clap-utils",
|
"solana-clap-utils",
|
||||||
"solana-cli-config",
|
"solana-cli-config",
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
use {
|
use {
|
||||||
crate::validator::{Validator, ValidatorConfig, ValidatorStartProgress},
|
crate::validator::{Validator, ValidatorConfig, ValidatorStartProgress},
|
||||||
solana_client::rpc_client::RpcClient,
|
solana_client::rpc_client::RpcClient,
|
||||||
solana_gossip::{cluster_info::Node, gossip_service::discover_cluster, socketaddr},
|
solana_gossip::{
|
||||||
|
cluster_info::{ClusterInfo, Node},
|
||||||
|
gossip_service::discover_cluster,
|
||||||
|
socketaddr,
|
||||||
|
},
|
||||||
solana_ledger::{blockstore::create_new_ledger, create_new_tmp_ledger},
|
solana_ledger::{blockstore::create_new_ledger, create_new_tmp_ledger},
|
||||||
solana_net_utils::PortRange,
|
solana_net_utils::PortRange,
|
||||||
solana_rpc::rpc::JsonRpcConfig,
|
solana_rpc::rpc::JsonRpcConfig,
|
||||||
@ -628,6 +632,10 @@ impl TestValidator {
|
|||||||
validator.join();
|
validator.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cluster_info(&self) -> Arc<ClusterInfo> {
|
||||||
|
self.validator.as_ref().unwrap().cluster_info.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TestValidator {
|
impl Drop for TestValidator {
|
||||||
|
@ -274,6 +274,7 @@ pub struct Validator {
|
|||||||
tvu: Tvu,
|
tvu: Tvu,
|
||||||
ip_echo_server: Option<solana_net_utils::IpEchoServer>,
|
ip_echo_server: Option<solana_net_utils::IpEchoServer>,
|
||||||
accountsdb_plugin_service: Option<AccountsDbPluginService>,
|
accountsdb_plugin_service: Option<AccountsDbPluginService>,
|
||||||
|
pub cluster_info: Arc<ClusterInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// in the distant future, get rid of ::new()/exit() and use Result properly...
|
// in the distant future, get rid of ::new()/exit() and use Result properly...
|
||||||
@ -863,6 +864,7 @@ impl Validator {
|
|||||||
ip_echo_server,
|
ip_echo_server,
|
||||||
validator_exit: config.validator_exit.clone(),
|
validator_exit: config.validator_exit.clone(),
|
||||||
accountsdb_plugin_service,
|
accountsdb_plugin_service,
|
||||||
|
cluster_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -902,6 +904,8 @@ impl Validator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn join(self) {
|
pub fn join(self) {
|
||||||
|
drop(self.cluster_info);
|
||||||
|
|
||||||
self.poh_service.join().expect("poh_service");
|
self.poh_service.join().expect("poh_service");
|
||||||
drop(self.poh_recorder);
|
drop(self.poh_recorder);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ log = "0.4.11"
|
|||||||
num_cpus = "1.13.0"
|
num_cpus = "1.13.0"
|
||||||
rand = "0.7.0"
|
rand = "0.7.0"
|
||||||
serde = "1.0.112"
|
serde = "1.0.112"
|
||||||
|
serde_json = "1.0.68"
|
||||||
solana-clap-utils = { path = "../clap-utils", version = "=1.8.12" }
|
solana-clap-utils = { path = "../clap-utils", version = "=1.8.12" }
|
||||||
solana-cli-config = { path = "../cli-config", version = "=1.8.12" }
|
solana-cli-config = { path = "../cli-config", version = "=1.8.12" }
|
||||||
solana-client = { path = "../client", version = "=1.8.12" }
|
solana-client = { path = "../client", version = "=1.8.12" }
|
||||||
|
@ -5,12 +5,15 @@ use {
|
|||||||
jsonrpc_ipc_server::{RequestContext, ServerBuilder},
|
jsonrpc_ipc_server::{RequestContext, ServerBuilder},
|
||||||
jsonrpc_server_utils::tokio,
|
jsonrpc_server_utils::tokio,
|
||||||
log::*,
|
log::*,
|
||||||
|
serde::{Deserialize, Serialize},
|
||||||
solana_core::validator::ValidatorStartProgress,
|
solana_core::validator::ValidatorStartProgress,
|
||||||
|
solana_gossip::{cluster_info::ClusterInfo, contact_info::ContactInfo},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
exit::Exit,
|
exit::Exit,
|
||||||
signature::{read_keypair_file, Keypair, Signer},
|
signature::{read_keypair_file, Keypair, Signer},
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
|
fmt::{self, Display},
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
@ -26,9 +29,80 @@ pub struct AdminRpcRequestMetadata {
|
|||||||
pub start_progress: Arc<RwLock<ValidatorStartProgress>>,
|
pub start_progress: Arc<RwLock<ValidatorStartProgress>>,
|
||||||
pub validator_exit: Arc<RwLock<Exit>>,
|
pub validator_exit: Arc<RwLock<Exit>>,
|
||||||
pub authorized_voter_keypairs: Arc<RwLock<Vec<Arc<Keypair>>>>,
|
pub authorized_voter_keypairs: Arc<RwLock<Vec<Arc<Keypair>>>>,
|
||||||
|
pub cluster_info: Arc<RwLock<Option<Arc<ClusterInfo>>>>,
|
||||||
}
|
}
|
||||||
impl Metadata for AdminRpcRequestMetadata {}
|
impl Metadata for AdminRpcRequestMetadata {}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct AdminRpcContactInfo {
|
||||||
|
pub id: String,
|
||||||
|
pub gossip: SocketAddr,
|
||||||
|
pub tvu: SocketAddr,
|
||||||
|
pub tvu_forwards: SocketAddr,
|
||||||
|
pub repair: SocketAddr,
|
||||||
|
pub tpu: SocketAddr,
|
||||||
|
pub tpu_forwards: SocketAddr,
|
||||||
|
pub tpu_vote: SocketAddr,
|
||||||
|
pub rpc: SocketAddr,
|
||||||
|
pub rpc_pubsub: SocketAddr,
|
||||||
|
pub serve_repair: SocketAddr,
|
||||||
|
pub last_updated_timestamp: u64,
|
||||||
|
pub shred_version: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ContactInfo> for AdminRpcContactInfo {
|
||||||
|
fn from(contact_info: ContactInfo) -> Self {
|
||||||
|
let ContactInfo {
|
||||||
|
id,
|
||||||
|
gossip,
|
||||||
|
tvu,
|
||||||
|
tvu_forwards,
|
||||||
|
repair,
|
||||||
|
tpu,
|
||||||
|
tpu_forwards,
|
||||||
|
tpu_vote,
|
||||||
|
rpc,
|
||||||
|
rpc_pubsub,
|
||||||
|
serve_repair,
|
||||||
|
wallclock,
|
||||||
|
shred_version,
|
||||||
|
} = contact_info;
|
||||||
|
Self {
|
||||||
|
id: id.to_string(),
|
||||||
|
last_updated_timestamp: wallclock,
|
||||||
|
gossip,
|
||||||
|
tvu,
|
||||||
|
tvu_forwards,
|
||||||
|
repair,
|
||||||
|
tpu,
|
||||||
|
tpu_forwards,
|
||||||
|
tpu_vote,
|
||||||
|
rpc,
|
||||||
|
rpc_pubsub,
|
||||||
|
serve_repair,
|
||||||
|
shred_version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AdminRpcContactInfo {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
writeln!(f, "Identity: {}", self.id)?;
|
||||||
|
writeln!(f, "Gossip: {}", self.gossip)?;
|
||||||
|
writeln!(f, "TVU: {}", self.tvu)?;
|
||||||
|
writeln!(f, "TVU Forwards: {}", self.tvu_forwards)?;
|
||||||
|
writeln!(f, "Repair: {}", self.repair)?;
|
||||||
|
writeln!(f, "TPU: {}", self.tpu)?;
|
||||||
|
writeln!(f, "TPU Forwards: {}", self.tpu_forwards)?;
|
||||||
|
writeln!(f, "TPU Votes: {}", self.tpu_vote)?;
|
||||||
|
writeln!(f, "RPC: {}", self.rpc)?;
|
||||||
|
writeln!(f, "RPC Pubsub: {}", self.rpc_pubsub)?;
|
||||||
|
writeln!(f, "Serve Repair: {}", self.serve_repair)?;
|
||||||
|
writeln!(f, "Last Updated Timestamp: {}", self.last_updated_timestamp)?;
|
||||||
|
writeln!(f, "Shred Version: {}", self.shred_version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[rpc]
|
#[rpc]
|
||||||
pub trait AdminRpc {
|
pub trait AdminRpc {
|
||||||
type Metadata;
|
type Metadata;
|
||||||
@ -53,6 +127,9 @@ pub trait AdminRpc {
|
|||||||
|
|
||||||
#[rpc(meta, name = "removeAllAuthorizedVoters")]
|
#[rpc(meta, name = "removeAllAuthorizedVoters")]
|
||||||
fn remove_all_authorized_voters(&self, meta: Self::Metadata) -> Result<()>;
|
fn remove_all_authorized_voters(&self, meta: Self::Metadata) -> Result<()>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "contactInfo")]
|
||||||
|
fn contact_info(&self, meta: Self::Metadata) -> Result<AdminRpcContactInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AdminRpcImpl;
|
pub struct AdminRpcImpl;
|
||||||
@ -128,6 +205,16 @@ impl AdminRpc for AdminRpcImpl {
|
|||||||
meta.authorized_voter_keypairs.write().unwrap().clear();
|
meta.authorized_voter_keypairs.write().unwrap().clear();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn contact_info(&self, meta: Self::Metadata) -> Result<AdminRpcContactInfo> {
|
||||||
|
if let Some(cluster_info) = meta.cluster_info.read().unwrap().as_ref() {
|
||||||
|
Ok(cluster_info.my_contact_info().into())
|
||||||
|
} else {
|
||||||
|
Err(jsonrpc_core::error::Error::invalid_params(
|
||||||
|
"Retry once validator start up is complete",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the Admin RPC interface
|
// Start the Admin RPC interface
|
||||||
|
@ -33,7 +33,7 @@ use {
|
|||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::exit,
|
process::exit,
|
||||||
sync::mpsc::channel,
|
sync::{mpsc::channel, Arc, RwLock},
|
||||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -508,6 +508,7 @@ fn main() {
|
|||||||
genesis.max_ledger_shreds = value_of(&matches, "limit_ledger_size");
|
genesis.max_ledger_shreds = value_of(&matches, "limit_ledger_size");
|
||||||
genesis.max_genesis_archive_unpacked_size = Some(u64::MAX);
|
genesis.max_genesis_archive_unpacked_size = Some(u64::MAX);
|
||||||
|
|
||||||
|
let admin_service_cluster_info = Arc::new(RwLock::new(None));
|
||||||
admin_rpc_service::run(
|
admin_rpc_service::run(
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
admin_rpc_service::AdminRpcRequestMetadata {
|
admin_rpc_service::AdminRpcRequestMetadata {
|
||||||
@ -519,6 +520,7 @@ fn main() {
|
|||||||
start_time: std::time::SystemTime::now(),
|
start_time: std::time::SystemTime::now(),
|
||||||
validator_exit: genesis.validator_exit.clone(),
|
validator_exit: genesis.validator_exit.clone(),
|
||||||
authorized_voter_keypairs: genesis.authorized_voter_keypairs.clone(),
|
authorized_voter_keypairs: genesis.authorized_voter_keypairs.clone(),
|
||||||
|
cluster_info: admin_service_cluster_info.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let dashboard = if output == Output::Dashboard {
|
let dashboard = if output == Output::Dashboard {
|
||||||
@ -591,6 +593,7 @@ fn main() {
|
|||||||
|
|
||||||
match genesis.start_with_mint_address(mint_address, socket_addr_space) {
|
match genesis.start_with_mint_address(mint_address, socket_addr_space) {
|
||||||
Ok(test_validator) => {
|
Ok(test_validator) => {
|
||||||
|
*admin_service_cluster_info.write().unwrap() = Some(test_validator.cluster_info());
|
||||||
if let Some(dashboard) = dashboard {
|
if let Some(dashboard) = dashboard {
|
||||||
dashboard.run(Duration::from_millis(250));
|
dashboard.run(Duration::from_millis(250));
|
||||||
}
|
}
|
||||||
|
@ -2054,6 +2054,18 @@ pub fn main() {
|
|||||||
currently running validator instance")
|
currently running validator instance")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("contact-info")
|
||||||
|
.about("Display the validator's contact info")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("output")
|
||||||
|
.long("output")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("MODE")
|
||||||
|
.possible_values(&["json", "json-compact"])
|
||||||
|
.help("Output display mode")
|
||||||
|
)
|
||||||
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("init")
|
SubCommand::with_name("init")
|
||||||
.about("Initialize the ledger directory then exit")
|
.about("Initialize the ledger directory then exit")
|
||||||
@ -2167,6 +2179,26 @@ pub fn main() {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
("contact-info", Some(subcommand_matches)) => {
|
||||||
|
let output_mode = subcommand_matches.value_of("output");
|
||||||
|
let admin_client = admin_rpc_service::connect(&ledger_path);
|
||||||
|
let contact_info = admin_rpc_service::runtime()
|
||||||
|
.block_on(async move { admin_client.await?.contact_info().await })
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
eprintln!("Contact info query failed: {}", err);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
if let Some(mode) = output_mode {
|
||||||
|
match mode {
|
||||||
|
"json" => println!("{}", serde_json::to_string_pretty(&contact_info).unwrap()),
|
||||||
|
"json-compact" => print!("{}", serde_json::to_string(&contact_info).unwrap()),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print!("{}", contact_info);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
("init", _) => Operation::Initialize,
|
("init", _) => Operation::Initialize,
|
||||||
("exit", Some(subcommand_matches)) => {
|
("exit", Some(subcommand_matches)) => {
|
||||||
let min_idle_time = value_t_or_exit!(subcommand_matches, "min_idle_time", usize);
|
let min_idle_time = value_t_or_exit!(subcommand_matches, "min_idle_time", usize);
|
||||||
@ -2685,6 +2717,7 @@ pub fn main() {
|
|||||||
let _ledger_write_guard = lock_ledger(&ledger_path, &mut ledger_lock);
|
let _ledger_write_guard = lock_ledger(&ledger_path, &mut ledger_lock);
|
||||||
|
|
||||||
let start_progress = Arc::new(RwLock::new(ValidatorStartProgress::default()));
|
let start_progress = Arc::new(RwLock::new(ValidatorStartProgress::default()));
|
||||||
|
let admin_service_cluster_info = Arc::new(RwLock::new(None));
|
||||||
admin_rpc_service::run(
|
admin_rpc_service::run(
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
admin_rpc_service::AdminRpcRequestMetadata {
|
admin_rpc_service::AdminRpcRequestMetadata {
|
||||||
@ -2693,6 +2726,7 @@ pub fn main() {
|
|||||||
validator_exit: validator_config.validator_exit.clone(),
|
validator_exit: validator_config.validator_exit.clone(),
|
||||||
start_progress: start_progress.clone(),
|
start_progress: start_progress.clone(),
|
||||||
authorized_voter_keypairs: authorized_voter_keypairs.clone(),
|
authorized_voter_keypairs: authorized_voter_keypairs.clone(),
|
||||||
|
cluster_info: admin_service_cluster_info.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2832,6 +2866,7 @@ pub fn main() {
|
|||||||
start_progress,
|
start_progress,
|
||||||
socket_addr_space,
|
socket_addr_space,
|
||||||
);
|
);
|
||||||
|
*admin_service_cluster_info.write().unwrap() = Some(validator.cluster_info.clone());
|
||||||
|
|
||||||
if let Some(filename) = init_complete_file {
|
if let Some(filename) = init_complete_file {
|
||||||
File::create(filename).unwrap_or_else(|_| {
|
File::create(filename).unwrap_or_else(|_| {
|
||||||
|
Reference in New Issue
Block a user