2007-04-11 12:54:22 +04:00
/*
standalone ctdb daemon
Copyright ( C ) Andrew Tridgell 2006
2007-05-31 07:50:53 +04:00
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
2007-07-10 09:29:31 +04:00
the Free Software Foundation ; either version 3 of the License , or
2007-05-31 07:50:53 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
2007-04-11 12:54:22 +04:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2007-05-31 07:50:53 +04:00
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
2007-07-10 09:29:31 +04:00
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2007-04-11 12:54:22 +04:00
*/
2015-10-26 08:50:46 +03:00
# include "replace.h"
2007-04-11 12:54:22 +04:00
# include "system/filesys.h"
2008-01-17 03:33:23 +03:00
# include "system/time.h"
2007-04-11 16:19:46 +04:00
# include "system/wait.h"
2007-10-16 05:29:33 +04:00
# include "system/network.h"
2018-04-16 12:05:54 +03:00
# include "system/syslog.h"
2015-10-26 08:50:46 +03:00
# include <popt.h>
# include <talloc.h>
/* Allow use of deprecated function tevent_loop_allow_nesting() */
# define TEVENT_DEPRECATED
# include <tevent.h>
# include "lib/util/debug.h"
# include "lib/util/samba_util.h"
# include "ctdb_private.h"
2015-03-17 06:30:18 +03:00
# include "common/reqid.h"
2015-10-23 06:11:53 +03:00
# include "common/system.h"
2015-10-23 06:17:34 +03:00
# include "common/common.h"
2018-05-10 10:32:33 +03:00
# include "common/path.h"
2015-11-11 07:41:10 +03:00
# include "common/logging.h"
2018-04-13 12:18:27 +03:00
# include "common/logging_conf.h"
# include "ctdb_config.h"
2007-04-11 15:17:36 +04:00
2008-10-17 00:56:12 +04:00
int script_log_level ;
2010-06-22 17:22:34 +04:00
bool fast_start ;
2007-04-11 12:54:22 +04:00
2007-06-07 16:06:19 +04:00
/*
called by the transport layer when a packet comes in
*/
static void ctdb_recv_pkt ( struct ctdb_context * ctdb , uint8_t * data , uint32_t length )
{
struct ctdb_req_header * hdr = ( struct ctdb_req_header * ) data ;
2010-09-29 04:38:41 +04:00
CTDB_INCREMENT_STAT ( ctdb , node_packets_recv ) ;
2007-06-07 16:06:19 +04:00
/* up the counter for this source node, so we know its alive */
2007-09-04 04:09:58 +04:00
if ( ctdb_validate_pnn ( ctdb , hdr - > srcnode ) ) {
2007-06-07 16:06:19 +04:00
/* as a special case, redirected calls don't increment the rx_cnt */
if ( hdr - > operation ! = CTDB_REQ_CALL | |
2015-10-29 08:26:29 +03:00
( ( struct ctdb_req_call_old * ) hdr ) - > hopcount = = 0 ) {
2007-06-07 16:06:19 +04:00
ctdb - > nodes [ hdr - > srcnode ] - > rx_cnt + + ;
}
}
ctdb_input_pkt ( ctdb , hdr ) ;
}
static const struct ctdb_upcalls ctdb_upcalls = {
. recv_pkt = ctdb_recv_pkt ,
. node_dead = ctdb_node_dead ,
. node_connected = ctdb_node_connected
} ;
2018-04-18 03:36:05 +03:00
static struct ctdb_context * ctdb_init ( struct tevent_context * ev )
{
int ret ;
struct ctdb_context * ctdb ;
ctdb = talloc_zero ( ev , struct ctdb_context ) ;
if ( ctdb = = NULL ) {
DBG_ERR ( " Memory error \n " ) ;
return NULL ;
}
ctdb - > ev = ev ;
2018-04-18 03:51:26 +03:00
2018-04-18 03:36:05 +03:00
/* Wrap early to exercise code. */
ret = reqid_init ( ctdb , INT_MAX - 200 , & ctdb - > idr ) ;
if ( ret ! = 0 ) {
D_ERR ( " reqid_init failed (%s) \n " , strerror ( ret ) ) ;
talloc_free ( ctdb ) ;
return NULL ;
}
ret = srvid_init ( ctdb , & ctdb - > srv ) ;
if ( ret ! = 0 ) {
D_ERR ( " srvid_init failed (%s) \n " , strerror ( ret ) ) ;
talloc_free ( ctdb ) ;
return NULL ;
}
2018-05-10 10:32:33 +03:00
ctdb - > daemon . name = path_socket ( ctdb , " ctdbd " ) ;
if ( ctdb - > daemon . name = = NULL ) {
DBG_ERR ( " Memory allocation error \n " ) ;
talloc_free ( ctdb ) ;
return NULL ;
}
ctdbd_pidfile = path_pidfile ( ctdb , " ctdbd " ) ;
if ( ctdbd_pidfile = = NULL ) {
DBG_ERR ( " Memory allocation error \n " ) ;
2018-04-18 03:36:05 +03:00
talloc_free ( ctdb ) ;
return NULL ;
}
2018-04-18 07:44:01 +03:00
gettimeofday ( & ctdb - > ctdbd_start_time , NULL ) ;
gettimeofday ( & ctdb - > last_recovery_started , NULL ) ;
gettimeofday ( & ctdb - > last_recovery_finished , NULL ) ;
ctdb - > recovery_mode = CTDB_RECOVERY_NORMAL ;
ctdb - > upcalls = & ctdb_upcalls ;
2018-04-18 03:36:05 +03:00
ctdb - > statistics . statistics_start_time = timeval_current ( ) ;
2018-04-18 07:44:01 +03:00
ctdb - > capabilities = CTDB_CAP_DEFAULT ;
/*
* Initialise this node ' s PNN to the unknown value . This will
* be set to the correct value by either ctdb_add_node ( ) as
* part of loading the nodes file or by
* ctdb_tcp_listen_automatic ( ) when the transport is
* initialised . At some point we should de - optimise this and
* pull it out into ctdb_start_daemon ( ) so it is done clearly
* and only in one place .
*/
ctdb - > pnn = CTDB_UNKNOWN_PNN ;
ctdb - > do_checkpublicip = true ;
2018-04-18 03:36:05 +03:00
return ctdb ;
}
2007-06-07 16:06:19 +04:00
2007-05-29 09:26:38 +04:00
2007-04-11 12:54:22 +04:00
/*
main program
*/
int main ( int argc , const char * argv [ ] )
{
2018-04-18 03:57:54 +03:00
struct ctdb_context * ctdb = NULL ;
2018-11-06 06:06:14 +03:00
int interactive_opt = 0 ;
bool interactive = false ;
2007-04-11 12:54:22 +04:00
struct poptOption popt_options [ ] = {
POPT_AUTOHELP
2018-11-06 06:06:14 +03:00
{ " interactive " , ' i ' , POPT_ARG_NONE , & interactive_opt , 0 ,
2018-10-18 09:50:09 +03:00
" don't fork, log to stderr " , NULL } ,
2007-04-11 12:54:22 +04:00
POPT_TABLEEND
} ;
2007-05-29 06:49:25 +04:00
int opt , ret ;
2007-04-11 12:54:22 +04:00
const char * * extra_argv ;
poptContext pc ;
2015-10-26 08:50:09 +03:00
struct tevent_context * ev ;
2018-04-26 13:32:30 +03:00
const char * ctdb_base ;
2018-04-13 12:18:27 +03:00
struct conf_context * conf ;
const char * logging_location ;
2018-10-17 13:24:07 +03:00
const char * test_mode ;
2018-04-13 12:18:27 +03:00
bool ok ;
2007-04-11 12:54:22 +04:00
2018-04-18 03:57:54 +03:00
/*
* Basic setup
*/
talloc_enable_null_tracking ( ) ;
fault_setup ( ) ;
ev = tevent_context_init ( NULL ) ;
if ( ev = = NULL ) {
fprintf ( stderr , " tevent_context_init() failed \n " ) ;
exit ( 1 ) ;
2018-03-05 13:19:30 +03:00
}
2018-04-18 03:57:54 +03:00
tevent_loop_allow_nesting ( ev ) ;
2018-03-07 04:11:53 +03:00
2018-04-18 03:57:54 +03:00
ctdb = ctdb_init ( ev ) ;
if ( ctdb = = NULL ) {
fprintf ( stderr , " Failed to init ctdb \n " ) ;
exit ( 1 ) ;
}
/* Default value for CTDB_BASE - don't override */
setenv ( " CTDB_BASE " , CTDB_ETCDIR , 0 ) ;
ctdb_base = getenv ( " CTDB_BASE " ) ;
if ( ctdb_base = = NULL ) {
D_ERR ( " CTDB_BASE not set \n " ) ;
exit ( 1 ) ;
2018-02-21 06:46:39 +03:00
}
2018-04-18 03:57:54 +03:00
/*
* Command - line option handling
*/
2007-04-11 12:54:22 +04:00
pc = poptGetContext ( argv [ 0 ] , argc , argv , popt_options , POPT_CONTEXT_KEEP_FIRST ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
default :
fprintf ( stderr , " Invalid option %s: %s \n " ,
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
2018-04-18 03:57:54 +03:00
goto fail ;
2007-04-11 12:54:22 +04:00
}
}
2016-11-28 01:51:48 +03:00
/* If there are extra arguments then exit with usage message */
2007-04-11 12:54:22 +04:00
extra_argv = poptGetArgs ( pc ) ;
if ( extra_argv ) {
extra_argv + + ;
2016-11-28 01:51:48 +03:00
if ( extra_argv [ 0 ] ) {
poptPrintHelp ( pc , stdout , 0 ) ;
2018-04-18 03:57:54 +03:00
goto fail ;
2016-11-28 01:51:48 +03:00
}
2007-04-11 12:54:22 +04:00
}
2018-11-06 06:06:14 +03:00
interactive = ( interactive_opt ! = 0 ) ;
2018-04-13 12:18:27 +03:00
/*
* Configuration file handling
*/
ret = ctdbd_config_load ( ctdb , & conf ) ;
if ( ret ! = 0 ) {
2018-08-31 02:06:51 +03:00
/* ctdbd_config_load() logs the failure */
2018-04-13 12:18:27 +03:00
goto fail ;
}
2018-04-18 03:57:54 +03:00
/*
* Logging setup / options
*/
2016-11-18 06:52:38 +03:00
2018-10-17 13:24:07 +03:00
test_mode = getenv ( " CTDB_TEST_MODE " ) ;
2018-04-13 12:18:27 +03:00
/* Log to stderr (ignoring configuration) when running as interactive */
2016-11-29 09:52:00 +03:00
if ( interactive ) {
2018-04-13 12:18:27 +03:00
logging_location = " file: " ;
2018-06-26 11:39:09 +03:00
setenv ( " CTDB_INTERACTIVE " , " true " , 1 ) ;
2018-04-13 12:18:27 +03:00
} else {
logging_location = logging_conf_location ( conf ) ;
2016-11-29 09:52:00 +03:00
}
2018-10-17 13:24:07 +03:00
if ( strcmp ( logging_location , " syslog " ) ! = 0 & & test_mode = = NULL ) {
2018-04-16 12:05:54 +03:00
/* This can help when CTDB logging is misconfigured */
syslog ( LOG_DAEMON | LOG_NOTICE ,
" CTDB logging to location %s " ,
2018-04-13 12:18:27 +03:00
logging_location ) ;
2018-04-16 12:05:54 +03:00
}
2016-11-30 08:46:19 +03:00
/* Initialize logging and set the debug level */
2018-04-13 12:18:27 +03:00
ok = ctdb_logging_init ( ctdb ,
logging_location ,
logging_conf_log_level ( conf ) ) ;
if ( ! ok ) {
2018-04-18 03:57:54 +03:00
goto fail ;
2016-11-18 06:52:38 +03:00
}
2018-04-13 12:18:27 +03:00
setenv ( " CTDB_LOGGING " , logging_location , 1 ) ;
2016-11-30 08:46:19 +03:00
setenv ( " CTDB_DEBUGLEVEL " , debug_level_to_string ( DEBUGLEVEL ) , 1 ) ;
2016-11-18 06:52:38 +03:00
2018-04-13 12:18:27 +03:00
script_log_level = debug_level_from_string (
ctdb_config . script_log_level ) ;
2008-10-17 00:56:12 +04:00
2018-04-18 03:57:54 +03:00
D_NOTICE ( " CTDB starting on node \n " ) ;
2007-06-07 16:06:19 +04:00
2018-04-18 03:57:54 +03:00
/*
* Cluster setup / options
*/
2007-06-07 16:06:19 +04:00
2018-04-13 12:18:27 +03:00
ret = ctdb_set_transport ( ctdb , ctdb_config . transport ) ;
2007-06-02 04:03:28 +04:00
if ( ret = = - 1 ) {
2018-04-18 03:57:54 +03:00
D_ERR ( " ctdb_set_transport failed - %s \n " , ctdb_errstr ( ctdb ) ) ;
goto fail ;
2007-06-02 04:03:28 +04:00
}
2022-01-10 11:18:14 +03:00
if ( ctdb_config . cluster_lock ! = NULL ) {
ctdb - > recovery_lock = ctdb_config . cluster_lock ;
} else if ( ctdb_config . recovery_lock ! = NULL ) {
ctdb - > recovery_lock = ctdb_config . recovery_lock ;
} else {
D_WARNING ( " Cluster lock not set \n " ) ;
2018-04-18 03:57:54 +03:00
}
2007-06-02 04:03:28 +04:00
/* tell ctdb what address to listen on */
2018-04-13 12:18:27 +03:00
if ( ctdb_config . node_address ) {
ret = ctdb_set_address ( ctdb , ctdb_config . node_address ) ;
2007-06-02 04:03:28 +04:00
if ( ret = = - 1 ) {
2018-04-18 03:57:54 +03:00
D_ERR ( " ctdb_set_address failed - %s \n " ,
ctdb_errstr ( ctdb ) ) ;
goto fail ;
2007-06-02 04:03:28 +04:00
}
}
/* tell ctdb what nodes are available */
2018-04-26 13:32:30 +03:00
ctdb - > nodes_file = talloc_asprintf ( ctdb , " %s/nodes " , ctdb_base ) ;
2018-03-14 07:34:57 +03:00
if ( ctdb - > nodes_file = = NULL ) {
2018-04-18 03:57:54 +03:00
DBG_ERR ( " Out of memory \n " ) ;
goto fail ;
2013-10-21 12:33:10 +04:00
}
2008-02-19 06:44:48 +03:00
ctdb_load_nodes_file ( ctdb ) ;
2007-06-02 04:03:28 +04:00
2018-04-18 03:57:54 +03:00
/*
* Database setup / options
*/
2018-04-13 12:18:27 +03:00
ctdb - > db_directory = ctdb_config . dbdir_volatile ;
2018-11-30 04:44:26 +03:00
ok = directory_exist ( ctdb - > db_directory ) ;
if ( ! ok ) {
D_ERR ( " Volatile database directory %s does not exist \n " ,
ctdb - > db_directory ) ;
goto fail ;
}
2018-04-13 12:18:27 +03:00
ctdb - > db_directory_persistent = ctdb_config . dbdir_persistent ;
2018-11-30 04:44:26 +03:00
ok = directory_exist ( ctdb - > db_directory_persistent ) ;
if ( ! ok ) {
D_ERR ( " Persistent database directory %s does not exist \n " ,
ctdb - > db_directory_persistent ) ;
goto fail ;
}
2018-04-13 12:18:27 +03:00
ctdb - > db_directory_state = ctdb_config . dbdir_state ;
2018-11-30 04:44:26 +03:00
ok = directory_exist ( ctdb - > db_directory_state ) ;
if ( ! ok ) {
D_ERR ( " State database directory %s does not exist \n " ,
ctdb - > db_directory_state ) ;
goto fail ;
}
2018-04-13 12:18:27 +03:00
if ( ctdb_config . lock_debug_script ! = NULL ) {
ret = setenv ( " CTDB_DEBUG_LOCKS " ,
ctdb_config . lock_debug_script ,
1 ) ;
if ( ret ! = 0 ) {
D_ERR ( " Failed to set up lock debugging (%s) \n " ,
2018-05-22 14:23:33 +03:00
strerror ( errno ) ) ;
2018-04-13 12:18:27 +03:00
goto fail ;
}
}
2018-04-18 03:57:54 +03:00
/*
* Legacy setup / options
*/
2018-04-13 12:18:27 +03:00
ctdb - > start_as_disabled = ( int ) ctdb_config . start_as_disabled ;
ctdb - > start_as_stopped = ( int ) ctdb_config . start_as_stopped ;
2018-04-18 03:57:54 +03:00
/* set ctdbd capabilities */
2018-04-13 12:18:27 +03:00
if ( ! ctdb_config . lmaster_capability ) {
2018-04-18 03:57:54 +03:00
ctdb - > capabilities & = ~ CTDB_CAP_LMASTER ;
}
2018-04-13 12:18:27 +03:00
if ( ! ctdb_config . recmaster_capability ) {
2018-04-18 03:57:54 +03:00
ctdb - > capabilities & = ~ CTDB_CAP_RECMASTER ;
}
2018-08-20 06:35:33 +03:00
ctdb - > do_setsched = ctdb_config . realtime_scheduling ;
2018-04-18 03:57:54 +03:00
/*
* Miscellaneous setup
*/
ctdb_tunables_set_defaults ( ctdb ) ;
2018-03-09 08:27:32 +03:00
ctdb - > event_script_dir = talloc_asprintf ( ctdb ,
2018-05-15 06:39:15 +03:00
" %s/events/legacy " ,
2018-04-26 13:32:30 +03:00
ctdb_base ) ;
2018-03-09 08:27:32 +03:00
if ( ctdb - > event_script_dir = = NULL ) {
DBG_ERR ( " Out of memory \n " ) ;
2018-04-18 03:57:54 +03:00
goto fail ;
2007-08-15 08:44:03 +04:00
}
2018-03-29 07:25:47 +03:00
ctdb - > notification_script = talloc_asprintf ( ctdb ,
" %s/notify.sh " ,
ctdb_base ) ;
2018-03-29 06:58:49 +03:00
if ( ctdb - > notification_script = = NULL ) {
D_ERR ( " Unable to set notification script \n " ) ;
2018-04-18 03:57:54 +03:00
goto fail ;
2009-03-31 07:23:31 +04:00
}
2018-04-18 03:57:54 +03:00
/*
* Testing and debug options
*/
2018-10-17 13:24:07 +03:00
if ( test_mode ! = NULL ) {
2018-04-05 08:37:42 +03:00
ctdb - > do_setsched = false ;
ctdb - > do_checkpublicip = false ;
fast_start = true ;
}
2007-04-29 18:19:40 +04:00
/* start the protocol running (as a child) */
2020-01-29 08:08:56 +03:00
return ctdb_start_daemon ( ctdb , interactive , test_mode ! = NULL ) ;
2018-04-18 03:57:54 +03:00
fail :
talloc_free ( ctdb ) ;
exit ( 1 ) ;
2007-04-11 12:54:22 +04:00
}