From e06949db872f0debd27790449e2c0b916459c38e Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Sat, 3 Jan 2015 11:13:09 +0900 Subject: [PATCH] Add option --check-master-config Consolidate the configuration checks carried out when cloning a standby, and enable them to be run separately to check the required configuration without running STANDBY CLONE multiple times. --- repmgr.c | 197 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 140 insertions(+), 57 deletions(-) diff --git a/repmgr.c b/repmgr.c index 8779b04c..a6f88d22 100644 --- a/repmgr.c +++ b/repmgr.c @@ -63,6 +63,7 @@ static bool create_schema(PGconn *conn); static bool copy_configuration(PGconn *masterconn, PGconn *witnessconn); static void write_primary_conninfo(char *line); static int check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string); +static bool check_master_config(PGconn *conn, bool exit_on_error); static void do_master_register(void); static void do_standby_register(void); @@ -72,6 +73,7 @@ static void do_standby_follow(void); static void do_witness_create(void); static void do_cluster_show(void); static void do_cluster_cleanup(void); +static void do_check_master_config(void); static void usage(void); static void help(const char *progname); @@ -115,12 +117,14 @@ main(int argc, char **argv) {"min-recovery-apply-delay", required_argument, NULL, 'r'}, {"verbose", no_argument, NULL, 'v'}, {"initdb-no-pwprompt", no_argument, NULL, 1}, + {"check-master-config", no_argument, NULL, 2}, {NULL, 0, NULL, 0} }; int optindex; int c, targ; int action = NO_ACTION; + bool check_master_config = false; char *ptr = NULL; progname = get_progname(argv[0]); @@ -218,12 +222,21 @@ main(int argc, char **argv) case 1: runtime_options.initdb_no_pwprompt = true; break; + case 2: + check_master_config = true; + break; default: usage(); exit(ERR_BAD_CONFIG); } } + if(check_master_config == true) + { + do_check_master_config(); + exit(SUCCESS); + } + /* * Now we need to obtain the action, this comes in one of these forms: * MASTER REGISTER | STANDBY {REGISTER | CLONE [node] | PROMOTE | FOLLOW @@ -825,8 +838,7 @@ do_standby_clone(void) int r = 0, retval = SUCCESS; - int i, - is_standby_retval; + int i; bool flag_success = false; bool test_mode = false; @@ -875,61 +887,7 @@ do_standby_clone(void) log_info(_("%s connected to master, checking its state\n"), progname); master_version_num = check_server_version(conn, "master", true, NULL); - /* ZZZ check user is qualified to perform base backup */ - /* Check we are cloning a primary node */ - is_standby_retval = is_standby(conn); - if (is_standby_retval) - { - log_err(_(is_standby_retval == 1 ? "The command should clone a primary node\n" : - "Connection to node lost!\n")); - - PQfinish(conn); - exit(ERR_BAD_CONFIG); - } - - /* And check if it is well configured */ - i = guc_set(conn, "wal_level", "=", "hot_standby"); - if (i == 0 || i == -1) - { - PQfinish(conn); - if (i == 0) - log_err(_("%s needs parameter 'wal_level' to be set to 'hot_standby'\n"), - progname); - exit(ERR_BAD_CONFIG); - } - - - /* ZZZ change this */ - i = guc_set_typed(conn, "wal_keep_segments", ">=", - runtime_options.wal_keep_segments, "integer"); - if (i == 0 || i == -1) - { - PQfinish(conn); - if (i == 0) - log_err(_("%s needs parameter 'wal_keep_segments' to be set to %s or greater (see the '-w' option or edit the postgresql.conf of the PostgreSQL master.)\n"), - progname, runtime_options.wal_keep_segments); - exit(ERR_BAD_CONFIG); - } - - i = guc_set(conn, "archive_mode", "=", "on"); - if (i == 0 || i == -1) - { - PQfinish(conn); - if (i == 0) - log_err(_("%s needs parameter 'archive_mode' to be set to 'on'\n"), - progname); - exit(ERR_BAD_CONFIG); - } - - i = guc_set(conn, "hot_standby", "=", "on"); - if (i == 0 || i == -1) - { - PQfinish(conn); - if (i == 0) - log_err(_("%s needs parameter 'hot_standby' to be set to 'on'\n"), - progname); - exit(ERR_BAD_CONFIG); - } + check_master_config(conn, true); /* * Check if the tablespace locations exists and that we can write to them. @@ -1653,6 +1611,7 @@ help(const char *progname) printf(_(" -W, --wait wait for a master to appear\n")); printf(_(" -r, --min-recovery-apply-delay=VALUE enable recovery time delay, value has to be a valid time atom (e.g. 5min)\n")); printf(_(" --initdb-no-pwprompt don't require superuser password when running initdb\n")); + printf(_(" --check-master-config report problems with master configuration\n")); printf(_("\n%s performs some tasks like clone a node, promote it or making follow\n"), progname); printf(_("another node and then exits.\n\n")); printf(_("COMMANDS:\n")); @@ -2312,3 +2271,127 @@ check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char * return server_version_num; } + + +/* + * check_master_config() + * + * Perform sanity check on master configuration + */ +static bool +check_master_config(PGconn *conn, bool exit_on_error) +{ + int i, + is_standby_retval; + bool config_ok = true; + + /* ZZZ check user is qualified to perform base backup */ + /* Check we are cloning a primary node */ + is_standby_retval = is_standby(conn); + if (is_standby_retval) + { + log_err(_(is_standby_retval == 1 ? "The command should clone a primary node\n" : + "Connection to node lost!\n")); + + if(exit_on_error == true) + { + PQfinish(conn); + exit(ERR_BAD_CONFIG); + } + + config_ok = false; + } + + /* And check if it is well configured */ + i = guc_set(conn, "wal_level", "=", "hot_standby"); + if (i == 0 || i == -1) + { + if (i == 0) + log_err(_("%s needs parameter 'wal_level' to be set to 'hot_standby'\n"), + progname); + if(exit_on_error == true) + { + PQfinish(conn); + exit(ERR_BAD_CONFIG); + } + + config_ok = false; + } + + /* ZZZ change this */ + i = guc_set_typed(conn, "wal_keep_segments", ">=", + runtime_options.wal_keep_segments, "integer"); + if (i == 0 || i == -1) + { + if (i == 0) + log_err(_("%s needs parameter 'wal_keep_segments' to be set to %s or greater (see the '-w' option or edit the postgresql.conf of the PostgreSQL master.)\n"), + progname, runtime_options.wal_keep_segments); + + if(exit_on_error == true) + { + PQfinish(conn); + exit(ERR_BAD_CONFIG); + } + + config_ok = false; + } + + i = guc_set(conn, "archive_mode", "=", "on"); + if (i == 0 || i == -1) + { + if (i == 0) + log_err(_("%s needs parameter 'archive_mode' to be set to 'on'\n"), + progname); + if(exit_on_error == true) + { + PQfinish(conn); + exit(ERR_BAD_CONFIG); + } + + config_ok = false; + } + + i = guc_set(conn, "hot_standby", "=", "on"); + if (i == 0 || i == -1) + { + if (i == 0) + log_err(_("%s needs parameter 'hot_standby' to be set to 'on'\n"), + progname); + + if(exit_on_error == true) + { + PQfinish(conn); + exit(ERR_BAD_CONFIG); + } + + config_ok = false; + } + + return config_ok; +} + +static void +do_check_master_config(void) +{ + PGconn *conn; + + /* Connection parameters for master only */ + keywords[0] = "host"; + values[0] = runtime_options.host; + keywords[1] = "port"; + values[1] = runtime_options.masterport; + keywords[2] = "dbname"; + values[2] = runtime_options.dbname; + printf("%s %s\n", values[0], values[1]); + /* We need to connect to check configuration and start a backup */ + log_info(_("%s connecting to master database\n"), progname); + conn = establish_db_connection_by_params(keywords, values, true); + + /* Verify that master is a supported server version */ + log_info(_("%s connected to master, checking its state\n"), progname); + check_server_version(conn, "master", false, NULL); + + check_master_config(conn, false); + + PQfinish(conn); +}