Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

feat(shell): support resolve IP address in dsn/utility #337

Merged
merged 48 commits into from
Nov 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
b747c9e
fix bugs
Smityz Nov 5, 2019
e0eadcc
1
Smityz Nov 6, 2019
f01f554
Merge commit 'e0eadccc2c894f0d727ce71b63d6b2e38c4b1359'
Smityz Nov 6, 2019
94a5df4
server_info changed
Smityz Nov 7, 2019
6c83c09
unit test
Smityz Nov 8, 2019
18b4ba8
cpp format
Smityz Nov 8, 2019
b451f8b
1
Smityz Nov 9, 2019
21a9bed
add unit test
Smityz Nov 9, 2019
a65d8a5
format
Smityz Nov 11, 2019
4101e3a
format4
Smityz Nov 11, 2019
91ee474
format4
Smityz Nov 11, 2019
3698f65
fix run-clang-format.sh
Smityz Nov 11, 2019
4df892f
rollback format.sh
Smityz Nov 11, 2019
d24d02e
add unit test
Smityz Nov 12, 2019
75321f6
format
Smityz Nov 12, 2019
b5ae5de
add unit tests && fix bugs
Smityz Nov 12, 2019
5852bdf
add unit test && fix some bugs
Smityz Nov 13, 2019
3c1d65f
1
Smityz Nov 13, 2019
126d6ac
1
Smityz Nov 13, 2019
248e890
Update replication_ddl_client.cpp
Smityz Nov 13, 2019
278b291
1
Smityz Nov 14, 2019
9c29853
1
Smityz Nov 14, 2019
5b5b75e
fix commentary
Smityz Nov 14, 2019
9267fee
1
Smityz Nov 14, 2019
88b8ced
fix private unit test
Smityz Nov 14, 2019
aadde4d
fix private unit test
Smityz Nov 14, 2019
39f11b8
final
Smityz Nov 14, 2019
5ef75e4
Merge branch 'master' into master
acelyc111 Nov 14, 2019
eb92a19
1213
Smityz Nov 14, 2019
a85bf06
format
Smityz Nov 14, 2019
f9a0acc
fomat again
Smityz Nov 14, 2019
dd6d544
delete
Smityz Nov 15, 2019
e486ae4
1
Smityz Nov 15, 2019
e010b3f
change comment
Smityz Nov 15, 2019
0bd206e
2222
Smityz Nov 15, 2019
dd60dbf
1
Smityz Nov 15, 2019
9272cb0
final
Smityz Nov 15, 2019
41d51d3
change private
Smityz Nov 15, 2019
04128bc
change files
Smityz Nov 18, 2019
8765a16
change files
Smityz Nov 18, 2019
f92dc5d
1
Smityz Nov 18, 2019
61e4ceb
test change place
Smityz Nov 18, 2019
da730df
1
Smityz Nov 18, 2019
039ec48
123
Smityz Nov 18, 2019
d5a486b
Update replication_ddl_client.h
Smityz Nov 18, 2019
1524bed
Merge branch 'master' into master
acelyc111 Nov 19, 2019
764e244
Update replication_ddl_client.h
Smityz Nov 19, 2019
dda574f
Update utils.h
Smityz Nov 19, 2019
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
24 changes: 4 additions & 20 deletions include/dsn/dist/replication/replication_ddl_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@

#pragma once

#include <dsn/dist/replication.h>

#include <cctype>
#include <string>
#include <map>
#include <dsn/dist/replication.h>
#include <vector>

#include <dsn/tool-api/task_tracker.h>
#include <dsn/tool-api/async_calls.h>
#include <dsn/utility/errors.h>
#include <vector>

namespace dsn {
namespace replication {
Expand Down Expand Up @@ -117,24 +119,6 @@ class replication_ddl_client
change_dup_status(std::string app_name, int dupid, duplication_status::type status);
error_with<duplication_query_response> query_dup(std::string app_name);

// get host name from ip series
// if can't get a hostname from ip(maybe no hostname or other errors), return UNRESOLVABLE
// if multiple hostname got, return <host1,host2> ...
// we only support ipv4 currently

// ip_network_order -> hostname
static std::string hostname_from_ip(uint32_t ip);
// a.b.c.d -> hostname
static std::string hostname_from_ip(const char *ip);
// a.b.c.d:port1 -> hostname:port1
static std::string hostname_from_ip_port(const char *ip_port);
// ipv4_rpc_address -> hostname:port | non_ipv4 -> "invalid"
static std::string hostname(const dsn::rpc_address &address);
// a.b.c.d,e.f.g.h -> hostname1,hostname2
static std::string list_hostname_from_ip(const char *ip_list);
// a.b.c.d:port1,e.f.g.h:port2 -> hostname1:port2,hostname2:port2
static std::string list_hostname_from_ip_port(const char *ip_port_list);

dsn::error_code do_restore(const std::string &backup_provider_name,
const std::string &cluster_name,
const std::string &policy_name,
Expand Down
38 changes: 38 additions & 0 deletions include/dsn/utility/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <functional>
#include <memory>

#include <dsn/tool-api/rpc_address.h>
#include <dsn/utility/string_view.h>

#define TIME_MS_MAX 0xffffffff
Expand Down Expand Up @@ -77,5 +78,42 @@ int hh_mm_to_seconds(dsn::string_view hhmm);
// eg. `18:10` => `1525947000` when called on May 10, 2018, CST
// Return: -1 when invalid
int64_t hh_mm_today_to_unix_sec(string_view hhmm_of_day);

// get host name from ip series
// if can't get a hostname from ip(maybe no hostname or other errors), return false, and
// hostname_result will be invalid value
// if multiple hostname got and all of them are resolvable return true, otherwise return false.
// and the hostname_result will be "hostname1,hostname2(or ip_address or )..."
// we only support ipv4 currently
// check if a.b.c.d:port can be resolved to hostname:port. If it can be resolved, return true
// and hostname_result
// will be the hostname, or it will be ip address or error message

// valid a.b.c.d -> return TRUE && hostname_result=hostname | invalid a.b.c.d:port1 -> return
// FALSE
// && hostname_result=a.b.c.d
bool hostname_from_ip(const char *ip, std::string *hostname_result);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么不直接写一个新文件 hostname_utils.h/hostname_utils.cpp 啊,utils.h 里的东西太杂了,很难管理


// valid a.b.c.d:port -> return TRUE && hostname_result=hostname:port | invalid a.b.c.d:port1
// ->
// return FALSE && hostname_result=a.b.c.d:port
bool hostname_from_ip_port(const char *ip_port, std::string *hostname_result);

// valid a.b.c.d,e.f.g.h -> return TRUE && hostname_result_list=hostname1,hostname2 | invalid
// a.b.c.d,e.f.g.h -> return TRUE && hostname_result_list=a.b.c.d,e.f.g.h
bool list_hostname_from_ip(const char *ip_port_list, std::string *hostname_result_list);

// valid a.b.c.d:port1,e.f.g.h:port2 -> return TRUE &&
// hostname_result_list=hostname1:port1,hostname2:port2 | invalid a.b.c.d:port1,e.f.g.h:port2 ->
// return TRUE && hostname_result_list=a.b.c.d:port1,e.f.g.h:port2
bool list_hostname_from_ip_port(const char *ip_port_list, std::string *hostname_result_list);

// valid_ipv4_rpc_address return TRUE && hostname_result=hostname:port | invalid_ipv4 -> return
// FALSE
bool hostname(const dsn::rpc_address &address, std::string *hostname_result);

// valid_ip_network_order -> return TRUE && hostname_result=hostname |
// invalid_ip_network_order -> return FALSE
bool hostname_from_ip(uint32_t ip, std::string *hostname_result);
}
}
148 changes: 141 additions & 7 deletions src/core/core/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,24 @@
*/

#include <dsn/utility/utils.h>
#include <dsn/utility/singleton.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <random>
#include <iostream>
#include <fstream>
#include <memory>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include <array>
#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <random>

#include <dsn/service_api_cpp.h>
#include <dsn/utility/singleton.h>
#include <sys/stat.h>
#include <sys/types.h>

#if defined(__linux__)
#include <sys/syscall.h>
Expand Down Expand Up @@ -140,5 +148,131 @@ int64_t hh_mm_today_to_unix_sec(string_view hhmm_of_day)

return get_unix_sec_today_midnight() + sec_of_day;
}
bool hostname_from_ip(uint32_t ip, std::string *hostname_result)
{
struct sockaddr_in addr_in;
addr_in.sin_family = AF_INET;
addr_in.sin_port = 0;
addr_in.sin_addr.s_addr = ip;
char hostname[256];
int err = getnameinfo((struct sockaddr *)(&addr_in),
sizeof(struct sockaddr),
hostname,
sizeof(hostname),
nullptr,
0,
NI_NAMEREQD);
if (err != 0) {
struct in_addr net_addr;
net_addr.s_addr = ip;
char ip_str[256];
inet_ntop(AF_INET, &net_addr, ip_str, sizeof(ip_str));
if (err == EAI_SYSTEM) {
dwarn("got error %s when try to resolve %s", strerror(errno), ip_str);
} else {
dwarn("return error(%s) when try to resolve %s", gai_strerror(err), ip_str);
}
return false;
} else {
*hostname_result = std::string(hostname);
return true;
}
}

bool hostname_from_ip(const char *ip, std::string *hostname_result)
{
uint32_t ip_addr;
if (inet_pton(AF_INET, ip, &ip_addr) != 1) {
// inet_pton() returns 1 on success (network address was successfully converted)
*hostname_result = ip;
return false;
}
if (!hostname_from_ip(ip_addr, hostname_result)) {
*hostname_result = ip;
return false;
}
return true;
}

bool hostname_from_ip_port(const char *ip_port, std::string *hostname_result)
{
dsn::rpc_address addr;
if (!addr.from_string_ipv4(ip_port)) {
dwarn("invalid ip_port(%s)", ip_port);
*hostname_result = ip_port;
return false;
}
if (!hostname(addr, hostname_result)) {
*hostname_result = ip_port;
return false;
}
return true;
}

bool hostname(const rpc_address &address, std::string *hostname_result)
{
if (address.type() != HOST_TYPE_IPV4) {
return false;
}
if (hostname_from_ip(htonl(address.ip()), hostname_result)) {
*hostname_result += ":" + std::to_string(address.port());
return true;
}
return false;
}

bool list_hostname_from_ip(const char *ip_list, std::string *hostname_result_list)
{
std::vector<std::string> splitted_ip;
dsn::utils::split_args(ip_list, splitted_ip, ',');

if (splitted_ip.empty()) {
dwarn("invalid ip_list(%s)", ip_list);
*hostname_result_list = *ip_list;
return false;
}

std::string temp;
std::stringstream result;
bool all_ok = true;
for (int i = 0; i < splitted_ip.size(); ++i) {
result << (i ? "," : "");
if (hostname_from_ip(splitted_ip[i].c_str(), &temp)) {
result << temp;
} else {
result << splitted_ip[i].c_str();
all_ok = false;
}
}
*hostname_result_list = result.str();
return all_ok;
}

bool list_hostname_from_ip_port(const char *ip_port_list, std::string *hostname_result_list)
{
std::vector<std::string> splitted_ip_port;
dsn::utils::split_args(ip_port_list, splitted_ip_port, ',');

if (splitted_ip_port.empty()) {
dwarn("invalid ip_list(%s)", ip_port_list);
*hostname_result_list = *ip_port_list;
return false;
}

std::string temp;
std::stringstream result;
bool all_ok = true;
for (int i = 0; i < splitted_ip_port.size(); ++i) {
result << (i ? "," : "");
if (hostname_from_ip_port(splitted_ip_port[i].c_str(), &temp)) {
result << temp;
} else {
result << splitted_ip_port[i].c_str();
all_ok = false;
}
}
*hostname_result_list = result.str();
return all_ok;
}
}
}
86 changes: 86 additions & 0 deletions src/core/tests/hostname.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (c) 2017-present, Xiaomi, Inc. All rights reserved.
// This source code is licensed under the Apache License Version 2.0, which
// can be found in the LICENSE file in the root directory of this source tree.

#include <dsn/utility/utils.h>

#include <dsn/tool-api/rpc_address.h>
#include <gtest/gtest.h>

namespace dsn {
namespace replication {

TEST(ip_to_hostname, localhost)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上,建议改名 hostname_utils_test.cpp

{
std::string hostname_result;

const std::string success_ip = "127.0.0.1";
const std::string expected_hostname = "localhost";

const std::string success_ip_port = "127.0.0.1:23010";
const std::string expected_hostname_port = "localhost:23010";

const std::string failed_ip = "123.456.789.111";
const std::string failed_ip_port = "123.456.789.111:23010";

const std::string success_ip_list = "127.0.0.1,127.0.0.1,127.0.0.1";
const std::string expected_hostname_list = "localhost,localhost,localhost";

const std::string success_ip_port_list = "127.0.0.1:8080,127.0.0.1:8080,127.0.0.1:8080";
const std::string expected_hostname_port_list = "localhost:8080,localhost:8080,localhost:8080";

rpc_address rpc_example_success, rpc_example_failed;
rpc_example_success.assign_ipv4(success_ip.c_str(), 23010);
rpc_example_failed.assign_ipv4(failed_ip.c_str(), 23010);

// static bool hostname(const rpc_address &address,std::string *hostname_result);
ASSERT_TRUE(dsn::utils::hostname(rpc_example_success, &hostname_result));
ASSERT_STREQ(expected_hostname_port.c_str(), hostname_result.c_str());

ASSERT_FALSE(dsn::utils::hostname(rpc_example_failed, &hostname_result));

// static bool hostname_from_ip(uint32_t ip, std::string* hostname_result);
ASSERT_TRUE(dsn::utils::hostname_from_ip(htonl(rpc_example_success.ip()), &hostname_result));
ASSERT_STREQ(expected_hostname.c_str(), hostname_result.c_str());

ASSERT_FALSE(dsn::utils::hostname_from_ip(htonl(rpc_example_failed.ip()), &hostname_result));

// static bool hostname_from_ip(const char *ip,std::string *hostname_result);
ASSERT_TRUE(dsn::utils::hostname_from_ip(success_ip.c_str(), &hostname_result));
ASSERT_STREQ(expected_hostname.c_str(), hostname_result.c_str());

ASSERT_FALSE(dsn::utils::hostname_from_ip(failed_ip.c_str(), &hostname_result));
ASSERT_STREQ(failed_ip.c_str(), hostname_result.c_str());

// static bool hostname_from_ip_port(const char *ip_port,std::string *hostname_result);
ASSERT_TRUE(dsn::utils::hostname_from_ip_port(success_ip_port.c_str(), &hostname_result));
ASSERT_STREQ(expected_hostname_port.c_str(), hostname_result.c_str());

ASSERT_FALSE(dsn::utils::hostname_from_ip_port(failed_ip_port.c_str(), &hostname_result));
ASSERT_STREQ(failed_ip_port.c_str(), hostname_result.c_str());

// static bool list_hostname_from_ip(const char *ip_port_list,std::string
// *hostname_result_list);
ASSERT_TRUE(dsn::utils::list_hostname_from_ip(success_ip_list.c_str(), &hostname_result));
ASSERT_STREQ(expected_hostname_list.c_str(), hostname_result.c_str());

ASSERT_FALSE(dsn::utils::list_hostname_from_ip("127.0.0.1,127.0.0.23323,111127.0.0.3",
&hostname_result));
ASSERT_STREQ("localhost,127.0.0.23323,111127.0.0.3", hostname_result.c_str());

ASSERT_FALSE(dsn::utils::list_hostname_from_ip("123.456.789.111,127.0.0.1", &hostname_result));
ASSERT_STREQ("123.456.789.111,localhost", hostname_result.c_str());

// static bool list_hostname_from_ip_port(const char *ip_port_list,std::string
// *hostname_result_list);
ASSERT_TRUE(
dsn::utils::list_hostname_from_ip_port(success_ip_port_list.c_str(), &hostname_result));
ASSERT_STREQ(expected_hostname_port_list.c_str(), hostname_result.c_str());

ASSERT_FALSE(dsn::utils::list_hostname_from_ip_port(
"127.0.3333.1:23456,1127.0.0.2:22233,127.0.0.1:8080", &hostname_result));
ASSERT_STREQ("127.0.3333.1:23456,1127.0.0.2:22233,localhost:8080", hostname_result.c_str());
}

} // namespace replication
} // namespace dsn
Loading