2015-11-23 08:18:16 +03:00
/*
ctdb ip takeover code
Copyright ( C ) Ronnie Sahlberg 2007
Copyright ( C ) Andrew Tridgell 2007
Copyright ( C ) Martin Schwenke 2011
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "replace.h"
# include "system/network.h"
# include "lib/util/debug.h"
# include "common/logging.h"
2023-08-04 15:47:51 +03:00
# include "common/path.h"
# include "protocol/protocol_util.h"
# include "lib/util/smb_strtox.h"
# include "lib/util/memory.h"
2015-11-23 08:18:16 +03:00
# include "server/ipalloc_private.h"
2023-08-04 15:47:51 +03:00
struct home_node {
ctdb_sock_addr addr ;
uint32_t pnn ;
} ;
static struct home_node * ipalloc_get_home_nodes ( TALLOC_CTX * mem_ctx )
{
char * line = NULL ;
size_t len = 0 ;
char * fname = NULL ;
FILE * fp = NULL ;
struct home_node * result = NULL ;
fname = path_etcdir_append ( mem_ctx , " home_nodes " ) ;
if ( fname = = NULL ) {
goto fail ;
}
fp = fopen ( fname , " r " ) ;
if ( fp = = NULL ) {
goto fail ;
}
TALLOC_FREE ( fname ) ;
while ( true ) {
size_t num_nodes = talloc_array_length ( result ) ;
char * saveptr = NULL , * addrstr = NULL , * nodestr = NULL ;
struct home_node hn = {
. pnn = CTDB_UNKNOWN_PNN ,
} ;
struct home_node * tmp = NULL ;
ssize_t n = 0 ;
int ret ;
n = getline ( & line , & len , fp ) ;
if ( n < 0 ) {
if ( ! feof ( fp ) ) {
/* real error */
goto fail ;
}
break ;
}
if ( ( n > 0 ) & & ( line [ n - 1 ] = = ' \n ' ) ) {
line [ n - 1 ] = ' \0 ' ;
}
addrstr = strtok_r ( line , " \t " , & saveptr ) ;
if ( addrstr = = NULL ) {
continue ;
}
nodestr = strtok_r ( NULL , " \t " , & saveptr ) ;
if ( nodestr = = NULL ) {
continue ;
}
ret = ctdb_sock_addr_from_string ( addrstr , & hn . addr , false ) ;
if ( ret ! = 0 ) {
DBG_WARNING ( " Could not parse %s: %s \n " ,
addrstr ,
strerror ( ret ) ) ;
goto fail ;
}
hn . pnn = smb_strtoul ( nodestr ,
NULL ,
10 ,
& ret ,
SMB_STR_FULL_STR_CONV ) ;
if ( ret ! = 0 ) {
DBG_WARNING ( " Could not parse \" %s \" \n " , nodestr ) ;
goto fail ;
}
tmp = talloc_realloc ( mem_ctx ,
result ,
struct home_node ,
num_nodes + 1 ) ;
if ( tmp = = NULL ) {
goto fail ;
}
result = tmp ;
result [ num_nodes ] = hn ;
}
fclose ( fp ) ;
fp = NULL ;
return result ;
fail :
if ( fp ! = NULL ) {
fclose ( fp ) ;
fp = NULL ;
}
SAFE_FREE ( line ) ;
TALLOC_FREE ( fname ) ;
TALLOC_FREE ( result ) ;
return NULL ;
}
2015-11-23 08:18:16 +03:00
bool ipalloc_deterministic ( struct ipalloc_state * ipalloc_state )
{
2023-08-04 15:47:51 +03:00
struct home_node * home_nodes = ipalloc_get_home_nodes ( ipalloc_state ) ;
size_t num_home_nodes = talloc_array_length ( home_nodes ) ;
2015-11-23 08:18:16 +03:00
struct public_ip_list * t ;
2023-08-04 16:35:46 +03:00
int i ;
uint32_t numnodes ;
2015-11-23 08:18:16 +03:00
numnodes = ipalloc_state - > num ;
DEBUG ( DEBUG_NOTICE , ( " Deterministic IPs enabled. Resetting all ip allocations \n " ) ) ;
/* Allocate IPs to nodes in a modulo fashion so that IPs will
* always be allocated the same way for a specific set of
* available / unavailable nodes .
*/
for ( i = 0 , t = ipalloc_state - > all_ips ; t ! = NULL ; t = t - > next , i + + ) {
2023-08-04 15:47:51 +03:00
size_t j ;
2015-11-23 08:18:16 +03:00
t - > pnn = i % numnodes ;
2023-08-04 15:47:51 +03:00
for ( j = 0 ; j < num_home_nodes ; j + + ) {
struct home_node * hn = & home_nodes [ j ] ;
if ( ctdb_sock_addr_same_ip ( & t - > addr , & hn - > addr ) ) {
if ( hn - > pnn > = numnodes ) {
DBG_WARNING ( " pnn % " PRIu32
" too large \n " ,
hn - > pnn ) ;
break ;
}
t - > pnn = hn - > pnn ;
break ;
}
}
2015-11-23 08:18:16 +03:00
}
/* IP failback doesn't make sense with deterministic
* IPs , since the modulo step above implicitly fails
* back IPs to their " home " node .
*/
2016-06-21 09:34:44 +03:00
if ( ipalloc_state - > no_ip_failback ) {
2016-12-15 06:09:16 +03:00
D_WARNING ( " WARNING: 'NoIPFailback' set but ignored - "
" incompatible with 'Deterministic IPs \n " ) ;
2015-11-23 08:18:16 +03:00
}
unassign_unsuitable_ips ( ipalloc_state ) ;
basic_allocate_unassigned ( ipalloc_state ) ;
/* No failback here! */
2023-08-04 15:47:51 +03:00
TALLOC_FREE ( home_nodes ) ;
2015-11-23 08:18:16 +03:00
return true ;
}