mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Add logging and repmgr command sanity checks
This commit is contained in:
@@ -26,7 +26,7 @@ include Makefile.global
|
|||||||
|
|
||||||
$(info Building against PostgreSQL $(MAJORVERSION))
|
$(info Building against PostgreSQL $(MAJORVERSION))
|
||||||
|
|
||||||
REPMGR_CLIENT_OBJS = repmgr-client.o config.o
|
REPMGR_CLIENT_OBJS = repmgr-client.o config.o log.o
|
||||||
REPMGRD_OBJS = repmgrd.o
|
REPMGRD_OBJS = repmgrd.o
|
||||||
|
|
||||||
repmgr4: $(REPMGR_CLIENT_OBJS)
|
repmgr4: $(REPMGR_CLIENT_OBJS)
|
||||||
|
|||||||
28
config.c
28
config.c
@@ -22,3 +22,31 @@ progname(void)
|
|||||||
{
|
{
|
||||||
return _progname;
|
return _progname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
item_list_append(ItemList *item_list, char *error_message)
|
||||||
|
{
|
||||||
|
ItemListCell *cell;
|
||||||
|
|
||||||
|
cell = (ItemListCell *) pg_malloc0(sizeof(ItemListCell));
|
||||||
|
|
||||||
|
if (cell == NULL)
|
||||||
|
{
|
||||||
|
//log_err(_("unable to allocate memory; terminating.\n"));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell->string = pg_malloc0(MAXLEN);
|
||||||
|
strncpy(cell->string, error_message, MAXLEN);
|
||||||
|
|
||||||
|
if (item_list->tail)
|
||||||
|
{
|
||||||
|
item_list->tail->next = cell;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item_list->head = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_list->tail = cell;
|
||||||
|
}
|
||||||
|
|||||||
31
config.h
31
config.h
@@ -8,7 +8,34 @@
|
|||||||
#ifndef _REPMGR_CONFIG_H_
|
#ifndef _REPMGR_CONFIG_H_
|
||||||
#define _REPMGR_CONFIG_H_
|
#define _REPMGR_CONFIG_H_
|
||||||
|
|
||||||
void set_progname(const char *argv0);
|
typedef struct
|
||||||
const char * progname(void);
|
{
|
||||||
|
int node_id;
|
||||||
|
char node_name[MAXLEN];
|
||||||
|
char loglevel[MAXLEN];
|
||||||
|
char logfacility[MAXLEN];
|
||||||
|
char logfile[MAXLEN];
|
||||||
|
|
||||||
|
} t_configuration_options;
|
||||||
|
|
||||||
|
typedef struct ItemListCell
|
||||||
|
{
|
||||||
|
struct ItemListCell *next;
|
||||||
|
char *string;
|
||||||
|
} ItemListCell;
|
||||||
|
|
||||||
|
typedef struct ItemList
|
||||||
|
{
|
||||||
|
ItemListCell *head;
|
||||||
|
ItemListCell *tail;
|
||||||
|
} ItemList;
|
||||||
|
|
||||||
|
|
||||||
|
void set_progname(const char *argv0);
|
||||||
|
const char *progname(void);
|
||||||
|
|
||||||
|
void item_list_append(ItemList *item_list, char *error_message);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
31
errcode.h
Normal file
31
errcode.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* errcode.h
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ERRCODE_H_
|
||||||
|
#define _ERRCODE_H_
|
||||||
|
|
||||||
|
/* Exit return codes */
|
||||||
|
|
||||||
|
#define SUCCESS 0
|
||||||
|
#define ERR_BAD_CONFIG 1
|
||||||
|
#define ERR_BAD_RSYNC 2
|
||||||
|
#define ERR_NO_RESTART 4
|
||||||
|
#define ERR_DB_CON 6
|
||||||
|
#define ERR_DB_QUERY 7
|
||||||
|
#define ERR_PROMOTED 8
|
||||||
|
#define ERR_STR_OVERFLOW 10
|
||||||
|
#define ERR_FAILOVER_FAIL 11
|
||||||
|
#define ERR_BAD_SSH 12
|
||||||
|
#define ERR_SYS_FAILURE 13
|
||||||
|
#define ERR_BAD_BASEBACKUP 14
|
||||||
|
#define ERR_INTERNAL 15
|
||||||
|
#define ERR_MONITORING_FAIL 16
|
||||||
|
#define ERR_BAD_BACKUP_LABEL 17
|
||||||
|
#define ERR_SWITCHOVER_FAIL 18
|
||||||
|
#define ERR_BARMAN 19
|
||||||
|
#define ERR_REGISTRATION_SYNC 20
|
||||||
|
|
||||||
|
#endif /* _ERRCODE_H_ */
|
||||||
|
|
||||||
370
log.c
Normal file
370
log.c
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* log.c - Logging methods
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "repmgr.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG
|
||||||
|
#include <syslog.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#define DEFAULT_IDENT "repmgr"
|
||||||
|
#ifdef HAVE_SYSLOG
|
||||||
|
#define DEFAULT_SYSLOG_FACILITY LOG_LOCAL0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* #define REPMGR_DEBUG */
|
||||||
|
|
||||||
|
static int detect_log_facility(const char *facility);
|
||||||
|
static void _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_list ap)
|
||||||
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
||||||
|
|
||||||
|
int log_type = REPMGR_STDERR;
|
||||||
|
int log_level = LOG_NOTICE;
|
||||||
|
int last_log_level = LOG_NOTICE;
|
||||||
|
int verbose_logging = false;
|
||||||
|
int terse_logging = false;
|
||||||
|
/*
|
||||||
|
* Global variable to be set by the main application to ensure any log output
|
||||||
|
* emitted before logger_init is called, is output in the correct format
|
||||||
|
*/
|
||||||
|
int logger_output_mode = OM_DAEMON;
|
||||||
|
|
||||||
|
extern void
|
||||||
|
stderr_log_with_level(const char *level_name, int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arglist;
|
||||||
|
|
||||||
|
va_start(arglist, fmt);
|
||||||
|
_stderr_log_with_level(level_name, level, fmt, arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_stderr_log_with_level(const char *level_name, int level, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store the requested level so that if there's a subsequent
|
||||||
|
* log_hint(), we can suppress that if appropriate.
|
||||||
|
*/
|
||||||
|
last_log_level = level;
|
||||||
|
|
||||||
|
if (log_level >= level)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Format log line prefix with timestamp if in daemon mode */
|
||||||
|
if (logger_output_mode == OM_DAEMON)
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
struct tm *tm;
|
||||||
|
time(&t);
|
||||||
|
tm = localtime(&t);
|
||||||
|
strftime(buf, 100, "[%Y-%m-%d %H:%M:%S]", tm);
|
||||||
|
fprintf(stderr, "%s [%s] ", buf, level_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: ", level_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
log_hint(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (terse_logging == false)
|
||||||
|
{
|
||||||
|
va_start(ap, fmt);
|
||||||
|
_stderr_log_with_level("HINT", last_log_level, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
log_verbose(int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
if (verbose_logging == true)
|
||||||
|
{
|
||||||
|
switch(level)
|
||||||
|
{
|
||||||
|
case LOG_EMERG:
|
||||||
|
_stderr_log_with_level("EMERG", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
case LOG_ALERT:
|
||||||
|
_stderr_log_with_level("ALERT", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
case LOG_CRIT:
|
||||||
|
_stderr_log_with_level("CRIT", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
case LOG_ERROR:
|
||||||
|
_stderr_log_with_level("ERROR", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
case LOG_WARNING:
|
||||||
|
_stderr_log_with_level("WARNING", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
case LOG_NOTICE:
|
||||||
|
_stderr_log_with_level("NOTICE", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
case LOG_INFO:
|
||||||
|
_stderr_log_with_level("INFO", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
case LOG_DEBUG:
|
||||||
|
_stderr_log_with_level("DEBUG", level, fmt, ap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
logger_init(t_configuration_options *opts, const char *ident)
|
||||||
|
{
|
||||||
|
char *level = opts->loglevel;
|
||||||
|
char *facility = opts->logfacility;
|
||||||
|
|
||||||
|
int l;
|
||||||
|
int f;
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG
|
||||||
|
int syslog_facility = DEFAULT_SYSLOG_FACILITY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef REPMGR_DEBUG
|
||||||
|
printf("Logger initialisation (Level: %s, Facility: %s)\n", level, facility);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ident)
|
||||||
|
{
|
||||||
|
ident = DEFAULT_IDENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level && *level)
|
||||||
|
{
|
||||||
|
l = detect_log_level(level);
|
||||||
|
#ifdef REPMGR_DEBUG
|
||||||
|
printf("Assigned level for logger: %d\n", l);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (l >= 0)
|
||||||
|
log_level = l;
|
||||||
|
else
|
||||||
|
stderr_log_warning(_("Invalid log level \"%s\" (available values: DEBUG, INFO, NOTICE, WARNING, ERR, ALERT, CRIT or EMERG)\n"), level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STDERR only logging requested - finish here without setting up any further
|
||||||
|
* logging facility.
|
||||||
|
*/
|
||||||
|
if (logger_output_mode == OM_COMMAND_LINE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (facility && *facility)
|
||||||
|
{
|
||||||
|
|
||||||
|
f = detect_log_facility(facility);
|
||||||
|
#ifdef REPMGR_DEBUG
|
||||||
|
printf("Assigned facility for logger: %d\n", f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (f == 0)
|
||||||
|
{
|
||||||
|
/* No syslog requested, just stderr */
|
||||||
|
#ifdef REPMGR_DEBUG
|
||||||
|
printf(_("Use stderr for logging\n"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (f == -1)
|
||||||
|
{
|
||||||
|
stderr_log_warning(_("Cannot detect log facility %s (use any of LOCAL0, LOCAL1, ..., LOCAL7, USER or STDERR)\n"), facility);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_SYSLOG
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syslog_facility = f;
|
||||||
|
log_type = REPMGR_SYSLOG;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG
|
||||||
|
|
||||||
|
if (log_type == REPMGR_SYSLOG)
|
||||||
|
{
|
||||||
|
setlogmask(LOG_UPTO(log_level));
|
||||||
|
openlog(ident, LOG_CONS | LOG_PID | LOG_NDELAY, syslog_facility);
|
||||||
|
|
||||||
|
stderr_log_notice(_("Setup syslog (level: %s, facility: %s)\n"), level, facility);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (*opts->logfile)
|
||||||
|
{
|
||||||
|
FILE *fd;
|
||||||
|
|
||||||
|
/* Check if we can write to the specified file before redirecting
|
||||||
|
* stderr - if freopen() fails, stderr output will vanish into
|
||||||
|
* the ether and the user won't know what's going on.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fd = fopen(opts->logfile, "a");
|
||||||
|
if (fd == NULL)
|
||||||
|
{
|
||||||
|
stderr_log_error(_("Unable to open specified logfile '%s' for writing: %s\n"), opts->logfile, strerror(errno));
|
||||||
|
stderr_log_error(_("Terminating\n"));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
stderr_log_notice(_("Redirecting logging output to '%s'\n"), opts->logfile);
|
||||||
|
fd = freopen(opts->logfile, "a", stderr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's possible freopen() may still fail due to e.g. a race condition;
|
||||||
|
* as it's not feasible to restore stderr after a failed freopen(),
|
||||||
|
* we'll write to stdout as a last resort.
|
||||||
|
*/
|
||||||
|
if (fd == NULL)
|
||||||
|
{
|
||||||
|
printf(_("Unable to open specified logfile %s for writing: %s\n"), opts->logfile, strerror(errno));
|
||||||
|
printf(_("Terminating\n"));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
logger_shutdown(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYSLOG
|
||||||
|
if (log_type == REPMGR_SYSLOG)
|
||||||
|
closelog();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Indicate whether extra-verbose logging is required. This will
|
||||||
|
* generate a lot of output, particularly debug logging, and should
|
||||||
|
* not be permanently enabled in production.
|
||||||
|
*
|
||||||
|
* NOTE: in previous repmgr versions, this option forced the log
|
||||||
|
* level to INFO.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
logger_set_verbose(void)
|
||||||
|
{
|
||||||
|
verbose_logging = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Indicate whether some non-critical log messages can be omitted.
|
||||||
|
* Currently this includes warnings about irrelevant command line
|
||||||
|
* options and hints.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void logger_set_terse(void)
|
||||||
|
{
|
||||||
|
terse_logging = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
detect_log_level(const char *level)
|
||||||
|
{
|
||||||
|
if (!strcmp(level, "DEBUG"))
|
||||||
|
return LOG_DEBUG;
|
||||||
|
if (!strcmp(level, "INFO"))
|
||||||
|
return LOG_INFO;
|
||||||
|
if (!strcmp(level, "NOTICE"))
|
||||||
|
return LOG_NOTICE;
|
||||||
|
if (!strcmp(level, "WARNING"))
|
||||||
|
return LOG_WARNING;
|
||||||
|
if (!strcmp(level, "ERROR"))
|
||||||
|
return LOG_ERROR;
|
||||||
|
if (!strcmp(level, "ALERT"))
|
||||||
|
return LOG_ALERT;
|
||||||
|
if (!strcmp(level, "CRIT"))
|
||||||
|
return LOG_CRIT;
|
||||||
|
if (!strcmp(level, "EMERG"))
|
||||||
|
return LOG_EMERG;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
detect_log_facility(const char *facility)
|
||||||
|
{
|
||||||
|
int local = 0;
|
||||||
|
|
||||||
|
if (!strncmp(facility, "LOCAL", 5) && strlen(facility) == 6)
|
||||||
|
{
|
||||||
|
local = atoi(&facility[5]);
|
||||||
|
|
||||||
|
switch (local)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return LOG_LOCAL0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return LOG_LOCAL1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return LOG_LOCAL2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
return LOG_LOCAL3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
return LOG_LOCAL4;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
return LOG_LOCAL5;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
return LOG_LOCAL6;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
return LOG_LOCAL7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (!strcmp(facility, "USER"))
|
||||||
|
{
|
||||||
|
return LOG_USER;
|
||||||
|
}
|
||||||
|
else if (!strcmp(facility, "STDERR"))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
128
log.h
Normal file
128
log.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* log.h
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REPMGR_LOG_H_
|
||||||
|
#define _REPMGR_LOG_H_
|
||||||
|
|
||||||
|
#include "repmgr.h"
|
||||||
|
|
||||||
|
#define REPMGR_SYSLOG 1
|
||||||
|
#define REPMGR_STDERR 2
|
||||||
|
|
||||||
|
#define OM_COMMAND_LINE 1
|
||||||
|
#define OM_DAEMON 2
|
||||||
|
|
||||||
|
extern void
|
||||||
|
stderr_log_with_level(const char *level_name, int level, const char *fmt,...)
|
||||||
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
||||||
|
|
||||||
|
#define LOG_EMERG 0 /* system is unusable */
|
||||||
|
#define LOG_ALERT 1 /* action must be taken immediately */
|
||||||
|
#define LOG_CRIT 2 /* critical conditions */
|
||||||
|
#define LOG_ERROR 3 /* error conditions */
|
||||||
|
#define LOG_WARNING 4 /* warning conditions */
|
||||||
|
#define LOG_NOTICE 5 /* normal but significant condition */
|
||||||
|
#define LOG_INFO 6 /* informational */
|
||||||
|
#define LOG_DEBUG 7 /* debug-level messages */
|
||||||
|
|
||||||
|
|
||||||
|
/* Standard error logging */
|
||||||
|
#define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__)
|
||||||
|
#define stderr_log_info(...) stderr_log_with_level("INFO", LOG_INFO, __VA_ARGS__)
|
||||||
|
#define stderr_log_notice(...) stderr_log_with_level("NOTICE", LOG_NOTICE, __VA_ARGS__)
|
||||||
|
#define stderr_log_warning(...) stderr_log_with_level("WARNING", LOG_WARNING, __VA_ARGS__)
|
||||||
|
#define stderr_log_error(...) stderr_log_with_level("ERROR", LOG_ERROR, __VA_ARGS__)
|
||||||
|
#define stderr_log_crit(...) stderr_log_with_level("CRITICAL", LOG_CRIT, __VA_ARGS__)
|
||||||
|
#define stderr_log_alert(...) stderr_log_with_level("ALERT", LOG_ALERT, __VA_ARGS__)
|
||||||
|
#define stderr_log_emerg(...) stderr_log_with_level("EMERGENCY", LOG_EMERG, __VA_ARGS__)
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#define log_debug(...) \
|
||||||
|
if (log_type == REPMGR_SYSLOG) \
|
||||||
|
syslog(LOG_DEBUG, __VA_ARGS__); \
|
||||||
|
else \
|
||||||
|
stderr_log_debug(__VA_ARGS__);
|
||||||
|
|
||||||
|
#define log_info(...) \
|
||||||
|
{ \
|
||||||
|
if (log_type == REPMGR_SYSLOG) syslog(LOG_INFO, __VA_ARGS__); \
|
||||||
|
else stderr_log_info(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define log_notice(...) \
|
||||||
|
{ \
|
||||||
|
if (log_type == REPMGR_SYSLOG) syslog(LOG_NOTICE, __VA_ARGS__); \
|
||||||
|
else stderr_log_notice(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define log_warning(...) \
|
||||||
|
{ \
|
||||||
|
if (log_type == REPMGR_SYSLOG) syslog(LOG_WARNING, __VA_ARGS__); \
|
||||||
|
else stderr_log_warning(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define log_error(...) \
|
||||||
|
{ \
|
||||||
|
if (log_type == REPMGR_SYSLOG) syslog(LOG_ERROR, __VA_ARGS__); \
|
||||||
|
else stderr_log_error(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define log_crit(...) \
|
||||||
|
{ \
|
||||||
|
if (log_type == REPMGR_SYSLOG) syslog(LOG_CRIT, __VA_ARGS__); \
|
||||||
|
else stderr_log_crit(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define log_alert(...) \
|
||||||
|
{ \
|
||||||
|
if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \
|
||||||
|
else stderr_log_alert(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define log_emerg(...) \
|
||||||
|
{ \
|
||||||
|
if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \
|
||||||
|
else stderr_log_alert(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
#define log_debug(...) stderr_log_debug(__VA_ARGS__)
|
||||||
|
#define log_info(...) stderr_log_info(__VA_ARGS__)
|
||||||
|
#define log_notice(...) stderr_log_notice(__VA_ARGS__)
|
||||||
|
#define log_warning(...) stderr_log_warning(__VA_ARGS__)
|
||||||
|
#define log_error(...) stderr_log_error(__VA_ARGS__)
|
||||||
|
#define log_crit(...) stderr_log_crit(__VA_ARGS__)
|
||||||
|
#define log_alert(...) stderr_log_alert(__VA_ARGS__)
|
||||||
|
#define log_emerg(...) stderr_log_emerg(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int detect_log_level(const char *level);
|
||||||
|
|
||||||
|
/* Logger initialisation and shutdown */
|
||||||
|
|
||||||
|
bool logger_init(t_configuration_options * opts, const char *ident);
|
||||||
|
|
||||||
|
bool logger_shutdown(void);
|
||||||
|
|
||||||
|
void logger_set_verbose(void);
|
||||||
|
void logger_set_terse(void);
|
||||||
|
|
||||||
|
void log_hint(const char *fmt, ...)
|
||||||
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
|
||||||
|
void log_verbose(int level, const char *fmt, ...)
|
||||||
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
||||||
|
|
||||||
|
extern int log_type;
|
||||||
|
extern int log_level;
|
||||||
|
extern int verbose_logging;
|
||||||
|
extern int terse_logging;
|
||||||
|
extern int logger_output_mode;
|
||||||
|
|
||||||
|
#endif /* _REPMGR_LOG_H_ */
|
||||||
151
repmgr-client.c
151
repmgr-client.c
@@ -14,15 +14,32 @@
|
|||||||
/* global configuration structures */
|
/* global configuration structures */
|
||||||
t_runtime_options runtime_options = T_RUNTIME_OPTIONS_INITIALIZER;
|
t_runtime_options runtime_options = T_RUNTIME_OPTIONS_INITIALIZER;
|
||||||
|
|
||||||
|
/* Collate command line errors and warnings here for friendlier reporting */
|
||||||
|
ItemList cli_errors = { NULL, NULL };
|
||||||
|
ItemList cli_warnings = { NULL, NULL };
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int optindex;
|
int optindex;
|
||||||
int c, targ;
|
int c, targ;
|
||||||
|
|
||||||
|
char *repmgr_node_type = NULL;
|
||||||
|
char *repmgr_action = NULL;
|
||||||
|
bool valid_repmgr_node_type_found = true;
|
||||||
int action = NO_ACTION;
|
int action = NO_ACTION;
|
||||||
|
char *dummy_action = "";
|
||||||
|
|
||||||
set_progname(argv[0]);
|
set_progname(argv[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell the logger we're a command-line program - this will
|
||||||
|
* ensure any output logged before the logger is initialized
|
||||||
|
* will be formatted correctly
|
||||||
|
*/
|
||||||
|
logger_output_mode = OM_COMMAND_LINE;
|
||||||
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "?Vd:h:p:U:S:D:f:R:w:k:FWIvb:rcL:tm:C:", long_options,
|
while ((c = getopt_long(argc, argv, "?Vd:h:p:U:S:D:f:R:w:k:FWIvb:rcL:tm:C:", long_options,
|
||||||
&optindex)) != -1)
|
&optindex)) != -1)
|
||||||
{
|
{
|
||||||
@@ -75,6 +92,93 @@ main(int argc, char **argv)
|
|||||||
progname());
|
progname());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exit here already if errors in command line options found */
|
||||||
|
if (cli_errors.head != NULL)
|
||||||
|
{
|
||||||
|
exit_with_errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the node type and action; following are valid:
|
||||||
|
*
|
||||||
|
* { MASTER | PRIMARY } REGISTER |
|
||||||
|
* STANDBY {REGISTER | UNREGISTER | CLONE [node] | PROMOTE | FOLLOW [node] | SWITCHOVER | REWIND} |
|
||||||
|
* WITNESS { CREATE | REGISTER | UNREGISTER } |
|
||||||
|
* BDR { REGISTER | UNREGISTER } |
|
||||||
|
* CLUSTER { CROSSCHECK | MATRIX | SHOW | CLEANUP }
|
||||||
|
*
|
||||||
|
* [node] is an optional hostname, provided instead of the -h/--host optipn
|
||||||
|
*/
|
||||||
|
if (optind < argc)
|
||||||
|
{
|
||||||
|
repmgr_node_type = argv[optind++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind < argc)
|
||||||
|
{
|
||||||
|
repmgr_action = argv[optind++];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
repmgr_action = dummy_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repmgr_node_type != NULL)
|
||||||
|
{
|
||||||
|
if (strcasecmp(repmgr_node_type, "MASTER") == 0 || strcasecmp(repmgr_node_type, "PRIMARY") == 0 )
|
||||||
|
{
|
||||||
|
if (strcasecmp(repmgr_action, "REGISTER") == 0)
|
||||||
|
action = MASTER_REGISTER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid_repmgr_node_type_found = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == NO_ACTION)
|
||||||
|
{
|
||||||
|
PQExpBufferData command_error;
|
||||||
|
initPQExpBuffer(&command_error);
|
||||||
|
|
||||||
|
if (repmgr_node_type == NULL)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&command_error,
|
||||||
|
_("no repmgr command provided"));
|
||||||
|
}
|
||||||
|
else if (valid_repmgr_node_type_found == false && repmgr_action[0] == '\0')
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&command_error,
|
||||||
|
_("unknown repmgr node type '%s'"),
|
||||||
|
repmgr_node_type);
|
||||||
|
}
|
||||||
|
else if (repmgr_action[0] == '\0')
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&command_error,
|
||||||
|
_("no action provided for node type '%s'"),
|
||||||
|
repmgr_node_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&command_error,
|
||||||
|
_("unknown repmgr action '%s %s'"),
|
||||||
|
repmgr_node_type,
|
||||||
|
repmgr_action);
|
||||||
|
}
|
||||||
|
|
||||||
|
item_list_append(&cli_errors, command_error.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity checks for command line parameters completed by now;
|
||||||
|
* any further errors will be runtime ones
|
||||||
|
*/
|
||||||
|
if (cli_errors.head != NULL)
|
||||||
|
{
|
||||||
|
exit_with_errors();
|
||||||
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +187,7 @@ static void
|
|||||||
do_help(void)
|
do_help(void)
|
||||||
{
|
{
|
||||||
printf(_("%s: replication management tool for PostgreSQL\n"), progname());
|
printf(_("%s: replication management tool for PostgreSQL\n"), progname());
|
||||||
printf(_("\n"));
|
puts("");
|
||||||
|
|
||||||
/* add a big friendly warning if root is executing "repmgr --help" */
|
/* add a big friendly warning if root is executing "repmgr --help" */
|
||||||
if (geteuid() == 0)
|
if (geteuid() == 0)
|
||||||
@@ -93,6 +197,49 @@ do_help(void)
|
|||||||
printf(_(" **************************************************\n"));
|
printf(_(" **************************************************\n"));
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
printf(_("Usage:\n"));
|
|
||||||
|
|
||||||
|
printf(_("Usage:\n"));
|
||||||
|
printf(_(" %s [OPTIONS] master register\n"), progname());
|
||||||
|
puts("");
|
||||||
|
printf(_("General options:\n"));
|
||||||
|
printf(_(" -?, --help show this help, then exit\n"));
|
||||||
|
printf(_(" -V, --version output version information, then exit\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_("General configuration options:\n"));
|
||||||
|
printf(_(" -f, --config-file=PATH path to the configuration file\n"));
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
exit_with_errors(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, _("The following command line errors were encountered:\n"));
|
||||||
|
|
||||||
|
print_error_list(&cli_errors, LOG_ERR);
|
||||||
|
|
||||||
|
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname());
|
||||||
|
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_error_list(ItemList *error_list, int log_level)
|
||||||
|
{
|
||||||
|
ItemListCell *cell;
|
||||||
|
|
||||||
|
for (cell = error_list->head; cell; cell = cell->next)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
switch(log_level)
|
||||||
|
{
|
||||||
|
/* Currently we only need errors and warnings */
|
||||||
|
case LOG_ERROR:
|
||||||
|
log_error("%s", cell->string);
|
||||||
|
break;
|
||||||
|
case LOG_WARNING:
|
||||||
|
log_warning("%s", cell->string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,12 @@
|
|||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt_long.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifndef _REPMGR_CLIENT_H_
|
#ifndef _REPMGR_CLIENT_H_
|
||||||
#define _REPMGR_CLIENT_H_
|
#define _REPMGR_CLIENT_H_
|
||||||
|
|
||||||
|
#include <getopt_long.h>
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef RECOVERY_COMMAND_FILE
|
#ifndef RECOVERY_COMMAND_FILE
|
||||||
#define RECOVERY_COMMAND_FILE "recovery.conf"
|
#define RECOVERY_COMMAND_FILE "recovery.conf"
|
||||||
#endif
|
#endif
|
||||||
@@ -117,4 +116,7 @@ typedef struct
|
|||||||
|
|
||||||
static void do_help(void);
|
static void do_help(void);
|
||||||
|
|
||||||
|
static void exit_with_errors(void);
|
||||||
|
static void print_error_list(ItemList *error_list, int log_level);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
4
repmgr.h
4
repmgr.h
@@ -13,11 +13,11 @@
|
|||||||
#include <pqexpbuffer.h>
|
#include <pqexpbuffer.h>
|
||||||
|
|
||||||
#include "repmgr_version.h"
|
#include "repmgr_version.h"
|
||||||
|
#include "errcode.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#define MIN_SUPPORTED_VERSION "9.3"
|
#define MIN_SUPPORTED_VERSION "9.3"
|
||||||
#define MIN_SUPPORTED_VERSION_NUM 90300
|
#define MIN_SUPPORTED_VERSION_NUM 90300
|
||||||
|
|
||||||
// to errcodes.h
|
|
||||||
#define SUCCESS 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user