mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
ndb - bug#22195
allow bind address for ndbd ndb/include/mgmapi/mgmapi.h: Add support for setting local address in NdbMgmHandle ndb/include/mgmcommon/ConfigRetriever.hpp: Add support for specifying local bindaddress to ConfigRetreiver ndb/include/util/SocketClient.hpp: Add support for setting local address in NdbMgmHandle ndb/src/common/mgmcommon/ConfigRetriever.cpp: Add support for setting local address in NdbMgmHandle ndb/src/common/util/SocketClient.cpp: Add support for setting local address in NdbMgmHandle ndb/src/kernel/vm/Configuration.cpp: Add support for specifying local bindaddress to ndbd ndb/src/mgmapi/mgmapi.cpp: Add support for setting local address in NdbMgmHandle
This commit is contained in:
@@ -231,7 +231,9 @@ extern "C" {
|
|||||||
NDB_MGM_SERVER_NOT_CONNECTED = 1010,
|
NDB_MGM_SERVER_NOT_CONNECTED = 1010,
|
||||||
/** Could not connect to socker */
|
/** Could not connect to socker */
|
||||||
NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011,
|
NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011,
|
||||||
|
/** Could not bind local address */
|
||||||
|
NDB_MGM_BIND_ADDRESS = 1012,
|
||||||
|
|
||||||
/* Alloc node id failures */
|
/* Alloc node id failures */
|
||||||
/** Generic error, retry may succeed */
|
/** Generic error, retry may succeed */
|
||||||
NDB_MGM_ALLOCID_ERROR = 1101,
|
NDB_MGM_ALLOCID_ERROR = 1101,
|
||||||
@@ -515,6 +517,15 @@ extern "C" {
|
|||||||
const char *ndb_mgm_get_connected_host(NdbMgmHandle handle);
|
const char *ndb_mgm_get_connected_host(NdbMgmHandle handle);
|
||||||
const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
|
const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set local bindaddress
|
||||||
|
* @param arg - Srting of form "host[:port]"
|
||||||
|
* @note must be called before connect
|
||||||
|
* @note Error on binding local address will not be reported until connect
|
||||||
|
* @return 0 on success
|
||||||
|
*/
|
||||||
|
int ndb_mgm_set_bindaddress(NdbMgmHandle, const char * arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the connectstring used for a connection
|
* Gets the connectstring used for a connection
|
||||||
*
|
*
|
||||||
|
@@ -28,7 +28,8 @@
|
|||||||
class ConfigRetriever {
|
class ConfigRetriever {
|
||||||
public:
|
public:
|
||||||
ConfigRetriever(const char * _connect_string,
|
ConfigRetriever(const char * _connect_string,
|
||||||
Uint32 version, Uint32 nodeType);
|
Uint32 version, Uint32 nodeType,
|
||||||
|
const char * _bind_address = 0);
|
||||||
~ConfigRetriever();
|
~ConfigRetriever();
|
||||||
|
|
||||||
int do_connect(int no_retries, int retry_delay_in_seconds, int verbose);
|
int do_connect(int no_retries, int retry_delay_in_seconds, int verbose);
|
||||||
|
@@ -37,7 +37,8 @@ public:
|
|||||||
};
|
};
|
||||||
unsigned short get_port() { return m_port; };
|
unsigned short get_port() { return m_port; };
|
||||||
char *get_server_name() { return m_server_name; };
|
char *get_server_name() { return m_server_name; };
|
||||||
NDB_SOCKET_TYPE connect();
|
int bind(const char* toaddress, unsigned short toport);
|
||||||
|
NDB_SOCKET_TYPE connect(const char* toaddress = 0, unsigned short port = 0);
|
||||||
bool close();
|
bool close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -45,7 +45,8 @@
|
|||||||
//****************************************************************************
|
//****************************************************************************
|
||||||
|
|
||||||
ConfigRetriever::ConfigRetriever(const char * _connect_string,
|
ConfigRetriever::ConfigRetriever(const char * _connect_string,
|
||||||
Uint32 version, Uint32 node_type)
|
Uint32 version, Uint32 node_type,
|
||||||
|
const char * _bindaddress)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("ConfigRetriever::ConfigRetriever");
|
DBUG_ENTER("ConfigRetriever::ConfigRetriever");
|
||||||
|
|
||||||
@@ -66,6 +67,15 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string,
|
|||||||
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
|
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_bindaddress)
|
||||||
|
{
|
||||||
|
if (ndb_mgm_set_bindaddress(m_handle, _bindaddress))
|
||||||
|
{
|
||||||
|
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
}
|
||||||
resetError();
|
resetError();
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@ SocketClient::SocketClient(const char *server_name, unsigned short port, SocketA
|
|||||||
{
|
{
|
||||||
m_auth= sa;
|
m_auth= sa;
|
||||||
m_port= port;
|
m_port= port;
|
||||||
m_server_name= strdup(server_name);
|
m_server_name= server_name ? strdup(server_name) : 0;
|
||||||
m_sockfd= NDB_INVALID_SOCKET;
|
m_sockfd= NDB_INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,13 +45,16 @@ SocketClient::init()
|
|||||||
if (m_sockfd != NDB_INVALID_SOCKET)
|
if (m_sockfd != NDB_INVALID_SOCKET)
|
||||||
NDB_CLOSE_SOCKET(m_sockfd);
|
NDB_CLOSE_SOCKET(m_sockfd);
|
||||||
|
|
||||||
memset(&m_servaddr, 0, sizeof(m_servaddr));
|
if (m_server_name)
|
||||||
m_servaddr.sin_family = AF_INET;
|
{
|
||||||
m_servaddr.sin_port = htons(m_port);
|
memset(&m_servaddr, 0, sizeof(m_servaddr));
|
||||||
// Convert ip address presentation format to numeric format
|
m_servaddr.sin_family = AF_INET;
|
||||||
if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
|
m_servaddr.sin_port = htons(m_port);
|
||||||
return false;
|
// Convert ip address presentation format to numeric format
|
||||||
|
if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_sockfd= socket(AF_INET, SOCK_STREAM, 0);
|
m_sockfd= socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (m_sockfd == NDB_INVALID_SOCKET) {
|
if (m_sockfd == NDB_INVALID_SOCKET) {
|
||||||
return false;
|
return false;
|
||||||
@@ -62,8 +65,45 @@ SocketClient::init()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SocketClient::bind(const char* bindaddress, unsigned short localport)
|
||||||
|
{
|
||||||
|
if (m_sockfd == NDB_INVALID_SOCKET)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
struct sockaddr_in local;
|
||||||
|
memset(&local, 0, sizeof(local));
|
||||||
|
local.sin_family = AF_INET;
|
||||||
|
local.sin_port = htons(localport);
|
||||||
|
// Convert ip address presentation format to numeric format
|
||||||
|
if (Ndb_getInAddr(&local.sin_addr, bindaddress))
|
||||||
|
{
|
||||||
|
return errno ? errno : EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int on = 1;
|
||||||
|
if (setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(const char*)&on, sizeof(on)) == -1) {
|
||||||
|
|
||||||
|
int ret = errno;
|
||||||
|
NDB_CLOSE_SOCKET(m_sockfd);
|
||||||
|
m_sockfd= NDB_INVALID_SOCKET;
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (::bind(m_sockfd, (struct sockaddr*)&local, sizeof(local)) == -1)
|
||||||
|
{
|
||||||
|
int ret = errno;
|
||||||
|
NDB_CLOSE_SOCKET(m_sockfd);
|
||||||
|
m_sockfd= NDB_INVALID_SOCKET;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NDB_SOCKET_TYPE
|
NDB_SOCKET_TYPE
|
||||||
SocketClient::connect()
|
SocketClient::connect(const char *toaddress, unsigned short toport)
|
||||||
{
|
{
|
||||||
if (m_sockfd == NDB_INVALID_SOCKET)
|
if (m_sockfd == NDB_INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
@@ -74,6 +114,21 @@ SocketClient::connect()
|
|||||||
return NDB_INVALID_SOCKET;
|
return NDB_INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toaddress)
|
||||||
|
{
|
||||||
|
if (m_server_name)
|
||||||
|
free(m_server_name);
|
||||||
|
m_server_name = strdup(toaddress);
|
||||||
|
m_port = toport;
|
||||||
|
memset(&m_servaddr, 0, sizeof(m_servaddr));
|
||||||
|
m_servaddr.sin_family = AF_INET;
|
||||||
|
m_servaddr.sin_port = htons(toport);
|
||||||
|
// Convert ip address presentation format to numeric format
|
||||||
|
if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
|
||||||
|
return NDB_INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr));
|
const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr));
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
NDB_CLOSE_SOCKET(m_sockfd);
|
NDB_CLOSE_SOCKET(m_sockfd);
|
||||||
|
@@ -58,7 +58,8 @@ NDB_STD_OPTS_VARS;
|
|||||||
// XXX should be my_bool ???
|
// XXX should be my_bool ???
|
||||||
static int _daemon, _no_daemon, _foreground, _initial, _no_start;
|
static int _daemon, _no_daemon, _foreground, _initial, _no_start;
|
||||||
static int _initialstart;
|
static int _initialstart;
|
||||||
static const char* _nowait_nodes;
|
static const char* _nowait_nodes = 0;
|
||||||
|
static const char* _bind_address = 0;
|
||||||
|
|
||||||
extern Uint32 g_start_type;
|
extern Uint32 g_start_type;
|
||||||
extern NdbNodeBitmask g_nowait_nodes;
|
extern NdbNodeBitmask g_nowait_nodes;
|
||||||
@@ -98,6 +99,10 @@ static struct my_option my_long_options[] =
|
|||||||
"Perform initial start",
|
"Perform initial start",
|
||||||
(gptr*) &_initialstart, (gptr*) &_initialstart, 0,
|
(gptr*) &_initialstart, (gptr*) &_initialstart, 0,
|
||||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
||||||
|
{ "bind-address", OPT_NOWAIT_NODES,
|
||||||
|
"Local bind address",
|
||||||
|
(gptr*) &_bind_address, (gptr*) &_bind_address, 0,
|
||||||
|
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
|
||||||
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
static void short_usage_sub(void)
|
static void short_usage_sub(void)
|
||||||
@@ -257,7 +262,9 @@ Configuration::fetch_configuration(){
|
|||||||
|
|
||||||
m_mgmd_port= 0;
|
m_mgmd_port= 0;
|
||||||
m_config_retriever= new ConfigRetriever(getConnectString(),
|
m_config_retriever= new ConfigRetriever(getConnectString(),
|
||||||
NDB_VERSION, NODE_TYPE_DB);
|
NDB_VERSION,
|
||||||
|
NODE_TYPE_DB,
|
||||||
|
_bind_address);
|
||||||
|
|
||||||
if (m_config_retriever->hasError())
|
if (m_config_retriever->hasError())
|
||||||
{
|
{
|
||||||
|
@@ -107,6 +107,7 @@ struct ndb_mgm_handle {
|
|||||||
int mgmd_version_major;
|
int mgmd_version_major;
|
||||||
int mgmd_version_minor;
|
int mgmd_version_minor;
|
||||||
int mgmd_version_build;
|
int mgmd_version_build;
|
||||||
|
char * m_bindaddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
|
#define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
|
||||||
@@ -162,6 +163,7 @@ ndb_mgm_create_handle()
|
|||||||
h->cfg_i = -1;
|
h->cfg_i = -1;
|
||||||
h->errstream = stdout;
|
h->errstream = stdout;
|
||||||
h->m_name = 0;
|
h->m_name = 0;
|
||||||
|
h->m_bindaddress = 0;
|
||||||
|
|
||||||
strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
|
strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
|
||||||
|
|
||||||
@@ -209,6 +211,22 @@ ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int
|
||||||
|
ndb_mgm_set_bindaddress(NdbMgmHandle handle, const char * arg)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("ndb_mgm_set_bindaddress");
|
||||||
|
if (handle->m_bindaddress)
|
||||||
|
free(handle->m_bindaddress);
|
||||||
|
|
||||||
|
if (arg)
|
||||||
|
handle->m_bindaddress = strdup(arg);
|
||||||
|
else
|
||||||
|
handle->m_bindaddress = 0;
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a handle
|
* Destroy a handle
|
||||||
*/
|
*/
|
||||||
@@ -235,6 +253,8 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
|
|||||||
#endif
|
#endif
|
||||||
(*handle)->cfg.~LocalConfig();
|
(*handle)->cfg.~LocalConfig();
|
||||||
my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR));
|
my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
|
if ((*handle)->m_bindaddress)
|
||||||
|
free((*handle)->m_bindaddress);
|
||||||
my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
|
my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
|
||||||
* handle = 0;
|
* handle = 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@@ -427,6 +447,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
|
|||||||
BaseString::snprintf(logname, 64, "mgmapi.log");
|
BaseString::snprintf(logname, 64, "mgmapi.log");
|
||||||
handle->logfile = fopen(logname, "w");
|
handle->logfile = fopen(logname, "w");
|
||||||
#endif
|
#endif
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do connect
|
* Do connect
|
||||||
@@ -434,6 +455,50 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
|
|||||||
LocalConfig &cfg= handle->cfg;
|
LocalConfig &cfg= handle->cfg;
|
||||||
NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
|
NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
|
||||||
Uint32 i;
|
Uint32 i;
|
||||||
|
int binderror = 0;
|
||||||
|
SocketClient s(0, 0);
|
||||||
|
if (!s.init())
|
||||||
|
{
|
||||||
|
fprintf(handle->errstream,
|
||||||
|
"Unable to create socket, "
|
||||||
|
"while trying to connect with connect string: %s\n",
|
||||||
|
cfg.makeConnectString(buf,sizeof(buf)));
|
||||||
|
|
||||||
|
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
|
||||||
|
"Unable to create socket, "
|
||||||
|
"while trying to connect with connect string: %s\n",
|
||||||
|
cfg.makeConnectString(buf,sizeof(buf)));
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->m_bindaddress)
|
||||||
|
{
|
||||||
|
BaseString::snprintf(buf, sizeof(buf), handle->m_bindaddress);
|
||||||
|
unsigned short portno = 0;
|
||||||
|
char * port = strchr(buf, ':');
|
||||||
|
if (port != 0)
|
||||||
|
{
|
||||||
|
portno = atoi(port+1);
|
||||||
|
* port = 0;
|
||||||
|
}
|
||||||
|
int err;
|
||||||
|
if ((err = s.bind(buf, portno)) != 0)
|
||||||
|
{
|
||||||
|
fprintf(handle->errstream,
|
||||||
|
"Unable to bind local address %s errno: %d, "
|
||||||
|
"while trying to connect with connect string: %s\n",
|
||||||
|
handle->m_bindaddress, err,
|
||||||
|
cfg.makeConnectString(buf,sizeof(buf)));
|
||||||
|
|
||||||
|
setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
|
||||||
|
"Unable to bind local address %s errno: %d, "
|
||||||
|
"while trying to connect with connect string: %s\n",
|
||||||
|
handle->m_bindaddress, err,
|
||||||
|
cfg.makeConnectString(buf,sizeof(buf)));
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (sockfd == NDB_INVALID_SOCKET)
|
while (sockfd == NDB_INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
// do all the mgmt servers
|
// do all the mgmt servers
|
||||||
@@ -441,8 +506,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
|
|||||||
{
|
{
|
||||||
if (cfg.ids[i].type != MgmId_TCP)
|
if (cfg.ids[i].type != MgmId_TCP)
|
||||||
continue;
|
continue;
|
||||||
SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port);
|
sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port);
|
||||||
sockfd = s.connect();
|
|
||||||
if (sockfd != NDB_INVALID_SOCKET)
|
if (sockfd != NDB_INVALID_SOCKET)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -450,19 +514,17 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
|
|||||||
break;
|
break;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
{
|
{
|
||||||
char buf[1024];
|
|
||||||
DBUG_PRINT("info",("Unable to connect with connect string: %s",
|
DBUG_PRINT("info",("Unable to connect with connect string: %s",
|
||||||
cfg.makeConnectString(buf,sizeof(buf))));
|
cfg.makeConnectString(buf,sizeof(buf))));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (verbose > 0) {
|
if (verbose > 0) {
|
||||||
char buf[1024];
|
fprintf(handle->errstream,
|
||||||
fprintf(handle->errstream, "Unable to connect with connect string: %s\n",
|
"Unable to connect with connect string: %s\n",
|
||||||
cfg.makeConnectString(buf,sizeof(buf)));
|
cfg.makeConnectString(buf,sizeof(buf)));
|
||||||
verbose= -1;
|
verbose= -1;
|
||||||
}
|
}
|
||||||
if (no_retries == 0) {
|
if (no_retries == 0) {
|
||||||
char buf[1024];
|
|
||||||
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
|
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
|
||||||
"Unable to connect with connect string: %s",
|
"Unable to connect with connect string: %s",
|
||||||
cfg.makeConnectString(buf,sizeof(buf)));
|
cfg.makeConnectString(buf,sizeof(buf)));
|
||||||
|
Reference in New Issue
Block a user