Add DNS resolution to cli tools

This commit is contained in:
Michael Vines 2019-04-13 19:34:27 -07:00 committed by Grimes
parent 6859907df9
commit 0767c0c07f
13 changed files with 100 additions and 57 deletions

3
Cargo.lock generated
View File

@ -2200,6 +2200,7 @@ dependencies = [
"solana-drone 0.13.0",
"solana-logger 0.13.0",
"solana-metrics 0.13.0",
"solana-netutil 0.13.0",
"solana-sdk 0.13.0",
]
@ -2388,6 +2389,7 @@ dependencies = [
"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)",
"solana 0.13.0",
"solana-netutil 0.13.0",
"solana-sdk 0.13.0",
]
@ -2690,6 +2692,7 @@ dependencies = [
"solana-client 0.13.0",
"solana-drone 0.13.0",
"solana-logger 0.13.0",
"solana-netutil 0.13.0",
"solana-sdk 0.13.0",
"solana-vote-api 0.13.0",
"solana-vote-signer 0.13.0",

View File

@ -16,6 +16,7 @@ solana-client = { path = "../client", version = "0.13.0" }
solana-drone = { path = "../drone", version = "0.13.0" }
solana-logger = { path = "../logger", version = "0.13.0" }
solana-metrics = { path = "../metrics", version = "0.13.0" }
solana-netutil = { path = "../netutil", version = "0.13.0" }
solana-sdk = { path = "../sdk", version = "0.13.0" }
[features]

View File

@ -117,14 +117,14 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
let mut args = Config::default();
if let Some(addr) = matches.value_of("network") {
args.network_addr = addr.parse().unwrap_or_else(|e| {
eprintln!("failed to parse network: {}", e);
args.network_addr = solana_netutil::parse_host_port(addr).unwrap_or_else(|e| {
eprintln!("failed to parse network address: {}", e);
exit(1)
});
}
if let Some(addr) = matches.value_of("drone") {
args.drone_addr = addr.parse().unwrap_or_else(|e| {
args.drone_addr = solana_netutil::parse_host_port(addr).unwrap_or_else(|e| {
eprintln!("failed to parse drone address: {}", e);
exit(1)
});

View File

@ -161,7 +161,7 @@ This will dump all the threads stack traces into gdb.txt
In this example the client connects to our public testnet. To run validators on the testnet you would need to open udp ports `8000-10000`.
```bash
$ ./multinode-demo/client.sh --network $(dig +short testnet.solana.com):8001 --duration 60
$ ./multinode-demo/client.sh --network testnet.solana.com:8001 --duration 60
```
You can observe the effects of your client's transactions on our [dashboard](https://metrics.solana.com:3000/d/testnet/testnet-hud?orgId=2&from=now-30m&to=now&refresh=5s&var-testnet=testnet)

View File

@ -26,14 +26,7 @@ Prebuilt binaries are available for Linux x86_64 (Ubuntu 18.04 recommended).
MacOS or WSL users may build from source.
### Validator Setup
The shell commands in this section assume the following environment variables are
set:
```bash
$ export ip=$(dig +short beta.testnet.solana.com)
```
#### Obtaining The Software
##### Bootstrap with `solana-install`
The `solana-install` tool can be used to easily install and upgrade the cluster
@ -82,8 +75,8 @@ just restarting itself before debugging further.
Receive an airdrop of lamports from the testnet drone:
```bash
$ solana-wallet -n ${ip:?} airdrop 123
$ solana-wallet -n ${ip:?} balance
$ solana-wallet -n beta.testnet.solana.com airdrop 123
$ solana-wallet -n beta.testnet.solana.com balance
```
Fetch the current testnet transaction count over JSON RPC:
@ -95,7 +88,7 @@ Inspect the blockexplorer at http://beta.testnet.solana.com/ for activity.
Run the following command to join the gossip network and view all the other nodes in the cluster:
```bash
$ RUST_LOG=info solana-gossip --network ${ip:?}:8001
$ solana-gossip --network beta.testnet.solana.com:8001
```
### Starting The Validator
@ -103,24 +96,24 @@ The following command will start a new validator node.
If this is a `solana-install`-installation:
```bash
$ fullnode-x.sh --public-address --poll-for-new-genesis-block ${ip:?}
$ fullnode-x.sh --public-address --poll-for-new-genesis-block beta.testnet.solana.com:8001
```
Alternatively, the `solana-install run` command can be used to run the validator
node while periodically checking for and applying software updates:
```bash
$ solana-install run fullnode-x.sh --public-address --poll-for-new-genesis-block ${ip:?}
$ solana-install run fullnode-x.sh --public-address --poll-for-new-genesis-block beta.testnet.solana.com:8001
```
When not using `solana-install`:
```bash
$ USE_INSTALL=1 ./multinode-demo/fullnode-x.sh --public-address --poll-for-new-genesis-block ${ip:?}
$ USE_INSTALL=1 ./multinode-demo/fullnode-x.sh --public-address --poll-for-new-genesis-block beta.testnet.solana.com:8001
```
Then from another console, confirm the IP address if your node is now visible in
the gossip network by running:
```bash
$ RUST_LOG=info solana-gossip --network ${ip:?}:8001
$ solana-gossip --network beta.testnet.solana.com:8001
```
Congratulations, you're now participating in the testnet cluster!

View File

@ -187,9 +187,9 @@ fn main() {
if matches.is_present("enable_rpc_exit") {
fullnode_config.rpc_config.enable_fullnode_exit = true;
}
fullnode_config.rpc_config.drone_addr = matches
.value_of("rpc_drone_address")
.map(|address| address.parse().expect("failed to parse drone address"));
fullnode_config.rpc_config.drone_addr = matches.value_of("rpc_drone_address").map(|address| {
solana_netutil::parse_host_port(address).expect("failed to parse drone address")
});
let dynamic_port_range = parse_port_range(matches.value_of("dynamic_port_range").unwrap())
.expect("invalid dynamic_port_range");
@ -214,7 +214,8 @@ fn main() {
fullnode_config.account_paths = None;
}
let cluster_entrypoint = matches.value_of("network").map(|network| {
let gossip_addr = network.parse().expect("failed to parse network address");
let gossip_addr =
solana_netutil::parse_host_port(network).expect("failed to parse network address");
ContactInfo::new_gossip_entry_point(&gossip_addr)
});
let (_signer_service, _signer_addr) = if let Some(signer_addr) = matches.value_of("signer") {

View File

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

View File

@ -67,8 +67,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.get_matches();
if let Some(addr) = matches.value_of("network") {
network_addr = addr.parse().unwrap_or_else(|e| {
eprintln!("failed to parse network: {}", e);
network_addr = solana_netutil::parse_host_port(addr).unwrap_or_else(|e| {
eprintln!("failed to parse network address: {}", e);
exit(1)
});
}

View File

@ -78,19 +78,7 @@ find_leader() {
leader_address=127.0.0.1:8001 # Default to local leader
elif [[ -z $2 ]]; then
leader=$1
declare leader_ip
if [[ $leader =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then
leader_ip=$leader
else
leader_ip=$(dig +short "${leader%:*}" | head -n1)
if [[ -z $leader_ip ]]; then
usage "Error: unable to resolve IP address for $leader"
fi
fi
leader_address=$leader_ip:8001
leader_address=$leader:8001
shift=1
else
leader=$1

View File

@ -7,7 +7,7 @@ use rand::{thread_rng, Rng};
use reqwest;
use socket2::{Domain, SockAddr, Socket, Type};
use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, UdpSocket};
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, ToSocketAddrs, UdpSocket};
use std::os::unix::io::AsRawFd;
/// A data type representing a public Udp socket
@ -70,6 +70,31 @@ pub fn parse_port_range(port_range: &str) -> Option<PortRange> {
Some((start_port, end_port))
}
pub fn parse_host(host: &str) -> Result<IpAddr, String> {
let ips: Vec<_> = (host, 0)
.to_socket_addrs()
.map_err(|err| err.to_string())?
.map(|socket_address| socket_address.ip())
.collect();
if ips.is_empty() {
Err(format!("Unable to resolve host: {}", host))
} else {
Ok(ips[0])
}
}
pub fn parse_host_port(host_port: &str) -> Result<SocketAddr, String> {
let addrs: Vec<_> = host_port
.to_socket_addrs()
.map_err(|err| err.to_string())?
.collect();
if addrs.is_empty() {
Err(format!("Unable to resolve host: {}", host_port))
} else {
Ok(addrs[0])
}
}
fn find_eth0ish_ip_addr(
ifaces: &mut Vec<datalink::NetworkInterface>,
enable_ipv6: bool,
@ -334,6 +359,22 @@ mod tests {
assert_eq!(parse_port_range("2-1"), None);
}
#[test]
fn test_parse_host() {
parse_host("localhost:1234").unwrap_err();
parse_host("localhost").unwrap();
parse_host("127.0.0.0:1234").unwrap_err();
parse_host("127.0.0.0").unwrap();
}
#[test]
fn test_parse_host_port() {
parse_host_port("localhost:1234").unwrap();
parse_host_port("localhost").unwrap_err();
parse_host_port("127.0.0.0:1234").unwrap();
parse_host_port("127.0.0.0").unwrap_err();
}
#[test]
fn test_bind() {
assert_eq!(bind_in_range((2000, 2001)).unwrap().0, 2000);

View File

@ -78,7 +78,9 @@ fn main() {
let network_addr = matches
.value_of("network")
.map(|network| network.parse().expect("failed to parse network address"))
.map(|network| {
solana_netutil::parse_host_port(network).expect("failed to parse network address")
})
.unwrap();
let leader_info = ContactInfo::new_gossip_entry_point(&network_addr);
@ -94,6 +96,5 @@ fn main() {
.unwrap();
replicator.run();
replicator.close();
}

View File

@ -20,6 +20,7 @@ solana-budget-api = { path = "../programs/budget_api", version = "0.13.0" }
solana-client = { path = "../client", version = "0.13.0" }
solana-drone = { path = "../drone", version = "0.13.0" }
solana-logger = { path = "../logger", version = "0.13.0" }
solana-netutil = { path = "../netutil", version = "0.13.0" }
solana-sdk = { path = "../sdk", version = "0.13.0" }
solana-vote-api = { path = "../programs/vote_api", version = "0.13.0" }
solana-vote-signer = { path = "../vote-signer", version = "0.13.0" }

View File

@ -7,28 +7,31 @@ use solana_wallet::wallet::{parse_command, process_command, WalletConfig, Wallet
use std::error;
pub fn parse_args(matches: &ArgMatches<'_>) -> Result<WalletConfig, Box<dyn error::Error>> {
let host = matches
.value_of("host")
.unwrap()
.parse()
.or_else(|_| Err(WalletError::BadParameter("Invalid host".to_string())))?;
let host = solana_netutil::parse_host(matches.value_of("host").unwrap()).or_else(|err| {
Err(WalletError::BadParameter(format!(
"Invalid host: {:?}",
err
)))
})?;
let drone_host = if let Some(drone_host) = matches.value_of("drone_host") {
Some(
drone_host
.parse()
.or_else(|_| Err(WalletError::BadParameter("Invalid drone host".to_string())))?,
)
Some(solana_netutil::parse_host(drone_host).or_else(|err| {
Err(WalletError::BadParameter(format!(
"Invalid drone host: {:?}",
err
)))
})?)
} else {
None
};
let rpc_host = if let Some(rpc_host) = matches.value_of("rpc_host") {
Some(
rpc_host
.parse()
.or_else(|_| Err(WalletError::BadParameter("Invalid rpc host".to_string())))?,
)
Some(solana_netutil::parse_host(rpc_host).or_else(|err| {
Err(WalletError::BadParameter(format!(
"Invalid rpc host: {:?}",
err
)))
})?)
} else {
None
};
@ -37,13 +40,23 @@ pub fn parse_args(matches: &ArgMatches<'_>) -> Result<WalletConfig, Box<dyn erro
.value_of("drone_port")
.unwrap()
.parse()
.or_else(|_| Err(WalletError::BadParameter("Invalid drone port".to_string())))?;
.or_else(|err| {
Err(WalletError::BadParameter(format!(
"Invalid drone port: {:?}",
err
)))
})?;
let rpc_port = matches
.value_of("rpc_port")
.unwrap()
.parse()
.or_else(|_| Err(WalletError::BadParameter("Invalid rpc port".to_string())))?;
.or_else(|err| {
Err(WalletError::BadParameter(format!(
"Invalid rpc port: {:?}",
err
)))
})?;
let mut path = dirs::home_dir().expect("home directory");
let id_path = if matches.is_present("keypair") {