diff --git a/configfile.c b/configfile.c index 488b0063..8a4c4fcb 100644 --- a/configfile.c +++ b/configfile.c @@ -210,6 +210,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList * memset(options->node_name, 0, sizeof(options->node_name)); memset(options->conninfo, 0, sizeof(options->conninfo)); memset(options->pg_bindir, 0, sizeof(options->pg_bindir)); + memset(options->pgdata, 0, sizeof(options->pgdata)); options->replication_type = REPLICATION_TYPE_PHYSICAL; /* @@ -350,7 +351,10 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList * _( "value for \"replication_user\" must contain fewer than " STR(NAMEDATALEN) " characters")); } else if (strcmp(name, "pg_bindir") == 0) - strncpy(options->pg_bindir, value, MAXLEN); + strncpy(options->pg_bindir, value, MAXPGPATH); + else if (strcmp(name, "pgdata") == 0) + strncpy(options->pgdata, value, MAXPGPATH); + else if (strcmp(name, "replication_type") == 0) { if (strcmp(value, "physical") == 0) diff --git a/configfile.h b/configfile.h index e66a7a4e..d7474c29 100644 --- a/configfile.h +++ b/configfile.h @@ -54,7 +54,8 @@ typedef struct char node_name[MAXLEN]; char conninfo[MAXLEN]; char replication_user[NAMEDATALEN]; - char pg_bindir[MAXLEN]; + char pg_bindir[MAXPGPATH]; + char pgdata[MAXPGPATH]; int replication_type; /* log settings */ @@ -118,7 +119,7 @@ typedef struct #define T_CONFIGURATION_OPTIONS_INITIALIZER { \ /* node information */ \ - UNKNOWN_NODE_ID, "", "", "", "", REPLICATION_TYPE_PHYSICAL, \ + UNKNOWN_NODE_ID, "", "", "", "", "", REPLICATION_TYPE_PHYSICAL, \ /* log settings */ \ "", "", "", DEFAULT_LOG_STATUS_INTERVAL, \ /* standby clone settings */ \ diff --git a/repmgr-action-node.c b/repmgr-action-node.c index 06040140..15a71730 100644 --- a/repmgr-action-node.c +++ b/repmgr-action-node.c @@ -19,7 +19,7 @@ static void format_archive_dir(char *archive_dir); static t_server_action parse_server_action(const char *action); static void _do_node_service_check(void); -static void _do_node_service_list(void); +static void _do_node_service_list(t_server_action action); void do_node_status(void) @@ -292,13 +292,15 @@ do_node_check(void) void do_node_service(void) { - t_server_action action = parse_server_action(runtime_options.action); + t_server_action action; + + action = parse_server_action(runtime_options.action); if (action == ACTION_UNKNOWN) { log_error(_("unknown value \"%s\" provided for parameter --action"), runtime_options.action); - log_hint(_("valid values are \"start\", \"stop\" and \"restart\"")); + log_hint(_("valid values are \"start\", \"stop\", \"restart\", \"reload\" and \"promote\"")); exit(ERR_BAD_CONFIG); } @@ -312,10 +314,19 @@ do_node_service(void) if (runtime_options.list == true) { - return _do_node_service_list(); + return _do_node_service_list(action); } + // do we need data directory? + // - service command defined for action ? -> no + // -> yes + // - pgdata defined in config? OK + // + // - connection available? + // -> get data dir OK (superuser connection issue) + + // perform action... // --dry-run: print only } @@ -328,12 +339,42 @@ _do_node_service_check(void) static void -_do_node_service_list(void) +_do_node_service_list(t_server_action action) { char command[MAXLEN] = ""; - char *data_dir = runtime_options.data_dir; + char data_dir[MAXPGPATH] = ""; + bool data_dir_required = false; + + /* do we need to provide a data directory for any of the actions? */ + if (data_dir_required_for_action(ACTION_START)) + data_dir_required = true; + + if (data_dir_required_for_action(ACTION_STOP)) + data_dir_required = true; + + if (data_dir_required_for_action(ACTION_RESTART)) + data_dir_required = true; + + if (data_dir_required_for_action(ACTION_RELOAD)) + data_dir_required = true; + + if (data_dir_required_for_action(ACTION_PROMOTE)) + data_dir_required = true; + + if (data_dir_required == true) + { + get_node_data_directory(data_dir); + } + + /* show command for specific action only */ + if (action != ACTION_NONE) + { + get_server_action(action, command, data_dir); + printf("%s\n", command); + return; + } puts(_("Following commands would be executed for each action:")); puts(""); diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c index 42525b2b..c2cca016 100644 --- a/repmgr-action-standby.c +++ b/repmgr-action-standby.c @@ -1282,7 +1282,7 @@ do_standby_follow(void) * If --wait provided, loop for up `primary_response_timeout` * seconds before giving up */ - + // XXX ??? primary_follow_timeout for (timer = 0; timer < config_file_options.primary_follow_timeout; timer++) { primary_conn = get_primary_connection_quiet(local_conn, @@ -1327,8 +1327,6 @@ do_standby_follow(void) exit(ERR_BAD_CONFIG); } - - /* * If 9.4 or later, and replication slots in use, we'll need to create a * slot on the new primary diff --git a/repmgr-client-global.h b/repmgr-client-global.h index 026b2ffc..d7cfdbab 100644 --- a/repmgr-client-global.h +++ b/repmgr-client-global.h @@ -169,6 +169,6 @@ extern bool remote_command(const char *host, const char *user, const char *comma /* server control functions */ extern void get_server_action(t_server_action action, char *script, char *data_dir); - - +extern bool data_dir_required_for_action(t_server_action action); +extern void get_node_data_directory(char *data_dir_buf); #endif diff --git a/repmgr-client.c b/repmgr-client.c index fb9b8b71..1b6a7f0d 100644 --- a/repmgr-client.c +++ b/repmgr-client.c @@ -1185,6 +1185,7 @@ check_cli_parameters(const int action) { case STANDBY_CLONE: case STANDBY_FOLLOW: + case NODE_SERVICE: break; default: item_list_append_format(&cli_warnings, @@ -1372,7 +1373,7 @@ action_name(const int action) case NODE_RESTORE_CONFIG: return "NODE RESTORE-CONFIG"; case NODE_SERVICE: - return "NODE_SERVICE"; + return "NODE SERVICE"; case CLUSTER_SHOW: return "CLUSTER SHOW"; @@ -2565,7 +2566,7 @@ get_server_action(t_server_action action, char *script, char *data_dir) { PQExpBufferData command; - if (data_dir == NULL) + if (data_dir == NULL || data_dir[0] == '\0') data_dir = "(none provided)"; switch(action) @@ -2673,7 +2674,8 @@ get_server_action(t_server_action action, char *script, char *data_dir) { if (config_file_options.service_reload_command[0] != '\0') { - maxlen_snprintf(script, "%s", config_file_options.service_reload_command); + maxlen_snprintf(script, "%s", + config_file_options.service_reload_command); } else { @@ -2704,7 +2706,8 @@ get_server_action(t_server_action action, char *script, char *data_dir) { if (config_file_options.service_promote_command[0] != '\0') { - maxlen_snprintf(script, "%s", config_file_options.service_promote_command); + maxlen_snprintf(script, "%s", + config_file_options.service_promote_command); } else { @@ -2737,3 +2740,88 @@ get_server_action(t_server_action action, char *script, char *data_dir) return; } +bool +data_dir_required_for_action(t_server_action action) +{ + switch(action) + { + case ACTION_NONE: + return false; + + case ACTION_START: + if (config_file_options.service_start_command[0] != '\0') + { + return false; + } + return true; + + case ACTION_STOP: + if (config_file_options.service_stop_command[0] != '\0') + { + return false; + } + return true; + + case ACTION_RESTART: + if (config_file_options.service_restart_command[0] != '\0') + { + return false; + } + return true; + + case ACTION_RELOAD: + if (config_file_options.service_reload_command[0] != '\0') + { + return false; + } + return true; + + case ACTION_PROMOTE: + if (config_file_options.service_promote_command[0] != '\0') + { + return false; + } + return true; + + default: + return false; + } + + return false; +} + + +// optionally pass conn? +void +get_node_data_directory(char *data_dir_buf) +{ + PGconn *conn = NULL; + bool success = false; + + if (config_file_options.pgdata[0] != '\0') + { + strncpy(data_dir_buf, config_file_options.pgdata, MAXPGPATH); + return; + } + + if (strlen(config_file_options.conninfo)) + conn = establish_db_connection(config_file_options.conninfo, true); + else + conn = establish_db_connection_by_params(&source_conninfo, true); + + success = get_pg_setting(conn, "data_directory", data_dir_buf); + + PQfinish(conn); + + if (success == true) + return; + + if (runtime_options.data_dir[0] != '\0') + { + strncpy(data_dir_buf, runtime_options.data_dir, MAXPGPATH); + return; + } + + + return; +} diff --git a/repmgr.conf.sample b/repmgr.conf.sample index 4a99895c..a1c31153 100644 --- a/repmgr.conf.sample +++ b/repmgr.conf.sample @@ -40,6 +40,12 @@ # Optional configuration items # ============================================================================= +#------------------------------------------------------------------------------ +# General settings +#------------------------------------------------------------------------------ + +#pgdata # The node's data directory; usually only required + # if the repmgr user is not a superuser #------------------------------------------------------------------------------ # Replication settings