in src/shell/commands/node_management.cpp [511:626]
bool remote_command(command_executor *e, shell_context *sc, arguments args)
{
static struct option long_options[] = {{"node_type", required_argument, 0, 't'},
{"node_list", required_argument, 0, 'l'},
{"resolve_ip", no_argument, 0, 'r'},
{0, 0, 0, 0}};
std::string type;
std::string nodes;
optind = 0;
bool resolve_ip = false;
while (true) {
int option_index = 0;
int c;
c = getopt_long(args.argc, args.argv, "t:l:r", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 't':
type = optarg;
break;
case 'l':
nodes = optarg;
break;
case 'r':
resolve_ip = true;
break;
default:
return false;
}
}
if (!type.empty() && !nodes.empty()) {
fprintf(stderr, "can not specify both node_type and node_list\n");
return false;
}
if (type.empty() && nodes.empty()) {
type = "all";
}
if (!type.empty() && type != "all" && type != "meta-server" && type != "replica-server") {
fprintf(stderr, "invalid type, should be: all | meta-server | replica-server\n");
return false;
}
if (optind == args.argc) {
fprintf(stderr, "command not specified\n");
return false;
}
std::string cmd = args.argv[optind];
std::vector<std::string> arguments;
for (int i = optind + 1; i < args.argc; i++) {
arguments.push_back(args.argv[i]);
}
std::vector<node_desc> node_list;
if (!type.empty()) {
if (!fill_nodes(sc, type, node_list)) {
fprintf(stderr, "prepare nodes failed, type = %s\n", type.c_str());
return true;
}
} else {
std::vector<std::string> tokens;
dsn::utils::split_args(nodes.c_str(), tokens, ',');
if (tokens.empty()) {
fprintf(stderr, "can't parse node from node_list\n");
return true;
}
for (std::string &token : tokens) {
dsn::rpc_address node;
if (!node.from_string_ipv4(token.c_str())) {
fprintf(stderr, "parse %s as a ip:port node failed\n", token.c_str());
return true;
}
node_list.emplace_back("user-specified", node);
}
}
fprintf(stderr, "COMMAND: %s", cmd.c_str());
for (auto &s : arguments) {
fprintf(stderr, " %s", s.c_str());
}
fprintf(stderr, "\n\n");
std::vector<std::pair<bool, std::string>> results =
call_remote_command(sc, node_list, cmd, arguments);
int succeed = 0;
int failed = 0;
// TODO (yingchun) output is hard to read, need do some refactor
for (int i = 0; i < node_list.size(); ++i) {
node_desc &n = node_list[i];
std::string hostname;
if (resolve_ip) {
dsn::utils::hostname_from_ip_port(n.address.to_string(), &hostname);
} else {
hostname = n.address.to_string();
}
fprintf(stderr, "CALL [%s] [%s] ", n.desc.c_str(), hostname.c_str());
if (results[i].first) {
fprintf(stderr, "succeed: %s\n", results[i].second.c_str());
succeed++;
} else {
fprintf(stderr, "failed: %s\n", results[i].second.c_str());
failed++;
}
}
fprintf(stderr, "\nSucceed count: %d\n", succeed);
fprintf(stderr, "Failed count: %d\n", failed);
return true;
}