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/>.
*/
2016-05-23 13:23:18 +03:00
# include <talloc.h>
2015-11-23 08:18:16 +03:00
# include "replace.h"
# include "system/network.h"
# include "lib/util/debug.h"
# include "common/logging.h"
2016-05-23 13:23:18 +03:00
# include "common/rb_tree.h"
2015-11-23 08:18:16 +03:00
# include "server/ipalloc_private.h"
2016-05-23 13:23:18 +03:00
static void * add_ip_callback ( void * parm , void * data )
{
struct public_ip_list * this_ip = parm ;
struct public_ip_list * prev_ip = data ;
if ( prev_ip = = NULL ) {
return parm ;
}
if ( this_ip - > pnn = = - 1 ) {
this_ip - > pnn = prev_ip - > pnn ;
}
return parm ;
}
static int getips_count_callback ( void * param , void * data )
{
struct public_ip_list * * ip_list = ( struct public_ip_list * * ) param ;
struct public_ip_list * new_ip = ( struct public_ip_list * ) data ;
new_ip - > next = * ip_list ;
* ip_list = new_ip ;
return 0 ;
}
/* Nodes only know about those public addresses that they are
* configured to serve and no individual node has a full list of all
* public addresses configured across the cluster . Therefore , a
* merged list of all public addresses needs to be built so that IP
* allocation can be done . */
static struct public_ip_list *
2016-06-21 14:09:39 +03:00
create_merged_ip_list ( struct ipalloc_state * ipalloc_state ,
struct ctdb_public_ip_list * known_ips )
2016-05-23 13:23:18 +03:00
{
int i , j ;
struct public_ip_list * ip_list ;
struct ctdb_public_ip_list * public_ips ;
struct trbt_tree * ip_tree ;
ip_tree = trbt_create ( ipalloc_state , 0 ) ;
2016-06-21 14:09:39 +03:00
if ( known_ips = = NULL ) {
2016-05-23 13:23:18 +03:00
DEBUG ( DEBUG_ERR , ( " Known public IPs not set \n " ) ) ;
return NULL ;
}
for ( i = 0 ; i < ipalloc_state - > num ; i + + ) {
2016-06-21 14:09:39 +03:00
public_ips = & known_ips [ i ] ;
2016-05-23 13:23:18 +03:00
for ( j = 0 ; j < public_ips - > num ; j + + ) {
struct public_ip_list * tmp_ip ;
/* This is returned as part of ip_list */
tmp_ip = talloc_zero ( ipalloc_state , struct public_ip_list ) ;
if ( tmp_ip = = NULL ) {
DEBUG ( DEBUG_ERR ,
( __location__ " out of memory \n " ) ) ;
talloc_free ( ip_tree ) ;
return NULL ;
}
/* Do not use information about IP addresses hosted
* on other nodes , it may not be accurate */
if ( public_ips - > ip [ j ] . pnn = = i ) {
tmp_ip - > pnn = public_ips - > ip [ j ] . pnn ;
} else {
tmp_ip - > pnn = - 1 ;
}
tmp_ip - > addr = public_ips - > ip [ j ] . addr ;
tmp_ip - > next = NULL ;
trbt_insertarray32_callback ( ip_tree ,
IP_KEYLEN , ip_key ( & public_ips - > ip [ j ] . addr ) ,
add_ip_callback ,
tmp_ip ) ;
}
}
ip_list = NULL ;
trbt_traversearray32 ( ip_tree , IP_KEYLEN , getips_count_callback , & ip_list ) ;
talloc_free ( ip_tree ) ;
return ip_list ;
}
2016-05-23 13:23:18 +03:00
bool ipalloc_set_public_ips ( struct ipalloc_state * ipalloc_state ,
struct ctdb_public_ip_list * known_ips ,
struct ctdb_public_ip_list * available_ips )
{
ipalloc_state - > available_public_ips = available_ips ;
2016-06-21 14:09:39 +03:00
ipalloc_state - > all_ips = create_merged_ip_list ( ipalloc_state ,
known_ips ) ;
2016-05-23 13:23:18 +03:00
return ( ipalloc_state - > all_ips ! = NULL ) ;
2016-05-23 13:23:18 +03:00
}
2015-11-23 08:18:16 +03:00
/* The calculation part of the IP allocation algorithm. */
bool ipalloc ( struct ipalloc_state * ipalloc_state )
{
2016-01-14 13:20:21 +03:00
bool ret = false ;
2015-11-23 08:18:16 +03:00
switch ( ipalloc_state - > algorithm ) {
case IPALLOC_LCP2 :
ret = ipalloc_lcp2 ( ipalloc_state ) ;
break ;
case IPALLOC_DETERMINISTIC :
ret = ipalloc_deterministic ( ipalloc_state ) ;
break ;
case IPALLOC_NONDETERMINISTIC :
ret = ipalloc_nondeterministic ( ipalloc_state ) ;
break ;
}
/* at this point ->pnn is the node which will own each IP
or - 1 if there is no node that can cover this ip
*/
return ret ;
}