Merge pull request #115 from xocolatl/unregister

Add a STANDBY UNREGISTER command.
This commit is contained in:
Martín Marqués
2015-09-23 10:17:22 -03:00
2 changed files with 125 additions and 12 deletions

View File

@@ -350,6 +350,7 @@ Following event types currently exist:
master_register master_register
standby_register standby_register
standby_unregister
standby_clone standby_clone
standby_promote standby_promote
witness_create witness_create
@@ -458,6 +459,11 @@ its port if is different from the default one.
promote/follow operations and to allow `repmgrd` to work with the node. promote/follow operations and to allow `repmgrd` to work with the node.
An existing standby can be registered using this command. An existing standby can be registered using this command.
* `standby unregister`
Unregisters a standby with `repmgr`. This command does not affect the actual
replication.
* `standby clone [node to be cloned]` * `standby clone [node to be cloned]`
Clones a new standby node from the data directory of the master (or Clones a new standby node from the data directory of the master (or

125
repmgr.c
View File

@@ -10,6 +10,7 @@
* MASTER REGISTER * MASTER REGISTER
* *
* STANDBY REGISTER * STANDBY REGISTER
* STANDBY UNREGISTER
* STANDBY CLONE * STANDBY CLONE
* STANDBY FOLLOW * STANDBY FOLLOW
* STANDBY PROMOTE * STANDBY PROMOTE
@@ -56,12 +57,13 @@
#define NO_ACTION 0 /* Dummy default action */ #define NO_ACTION 0 /* Dummy default action */
#define MASTER_REGISTER 1 #define MASTER_REGISTER 1
#define STANDBY_REGISTER 2 #define STANDBY_REGISTER 2
#define STANDBY_CLONE 3 #define STANDBY_UNREGISTER 3
#define STANDBY_PROMOTE 4 #define STANDBY_CLONE 4
#define STANDBY_FOLLOW 5 #define STANDBY_PROMOTE 5
#define WITNESS_CREATE 6 #define STANDBY_FOLLOW 6
#define CLUSTER_SHOW 7 #define WITNESS_CREATE 7
#define CLUSTER_CLEANUP 8 #define CLUSTER_SHOW 8
#define CLUSTER_CLEANUP 9
@@ -83,6 +85,7 @@ static char *make_pg_path(char *file);
static void do_master_register(void); static void do_master_register(void);
static void do_standby_register(void); static void do_standby_register(void);
static void do_standby_unregister(void);
static void do_standby_clone(void); static void do_standby_clone(void);
static void do_standby_promote(void); static void do_standby_promote(void);
static void do_standby_follow(void); static void do_standby_follow(void);
@@ -293,8 +296,10 @@ main(int argc, char **argv)
/* /*
* Now we need to obtain the action, this comes in one of these forms: * Now we need to obtain the action, this comes in one of these forms:
* MASTER REGISTER | STANDBY {REGISTER | CLONE [node] | PROMOTE | FOLLOW * MASTER REGISTER |
* [node]} | WITNESS CREATE CLUSTER {SHOW | CLEANUP} * STANDBY {REGISTER | UNREGISTER | CLONE [node] | PROMOTE | FOLLOW [node]} |
* WITNESS CREATE |
* CLUSTER {SHOW | CLEANUP}
* *
* the node part is optional, if we receive it then we shouldn't have * the node part is optional, if we receive it then we shouldn't have
* received a -h option * received a -h option
@@ -327,6 +332,8 @@ main(int argc, char **argv)
{ {
if (strcasecmp(server_cmd, "REGISTER") == 0) if (strcasecmp(server_cmd, "REGISTER") == 0)
action = STANDBY_REGISTER; action = STANDBY_REGISTER;
if (strcasecmp(server_cmd, "UNREGISTER") == 0)
action = STANDBY_UNREGISTER;
else if (strcasecmp(server_cmd, "CLONE") == 0) else if (strcasecmp(server_cmd, "CLONE") == 0)
action = STANDBY_CLONE; action = STANDBY_CLONE;
else if (strcasecmp(server_cmd, "PROMOTE") == 0) else if (strcasecmp(server_cmd, "PROMOTE") == 0)
@@ -535,6 +542,9 @@ main(int argc, char **argv)
case STANDBY_REGISTER: case STANDBY_REGISTER:
do_standby_register(); do_standby_register();
break; break;
case STANDBY_UNREGISTER:
do_standby_unregister();
break;
case STANDBY_CLONE: case STANDBY_CLONE:
do_standby_clone(); do_standby_clone();
break; break;
@@ -901,6 +911,85 @@ do_standby_register(void)
} }
static void
do_standby_unregister(void)
{
PGconn *conn;
PGconn *master_conn;
int ret;
bool node_record_deleted;
log_info(_("connecting to standby database\n"));
conn = establish_db_connection(options.conninfo, true);
/* Check we are a standby */
ret = is_standby(conn);
if (ret == 0 || ret == -1)
{
log_err(_(ret == 0 ? "this node should be a standby (%s)\n" :
"connection to node (%s) lost\n"), options.conninfo);
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
/* Check if there is a schema for this cluster */
if (check_cluster_schema(conn) == false)
{
/* schema doesn't exist */
log_err(_("schema '%s' doesn't exist.\n"), get_repmgr_schema());
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
/* check if there is a master in this cluster */
log_info(_("connecting to master database\n"));
master_conn = get_master_connection(conn, options.cluster_name,
NULL, NULL);
if (!master_conn)
{
log_err(_("a master must be defined before configuring a slave\n"));
exit(ERR_BAD_CONFIG);
}
/*
* Verify that standby and master are supported and compatible server
* versions
*/
check_master_standby_version_match(conn, master_conn);
/* Now unregister the standby */
log_info(_("unregistering the standby\n"));
node_record_deleted = delete_node_record(master_conn,
options.node,
"standby unregister");
if (node_record_deleted == false)
{
PQfinish(master_conn);
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
/* Log the event */
create_event_record(master_conn,
&options,
options.node,
"standby_unregister",
true,
NULL);
PQfinish(master_conn);
PQfinish(conn);
log_info(_("standby unregistration complete\n"));
log_notice(_("standby node correctly unregistered for cluster %s with id %d (conninfo: %s)\n"),
options.cluster_name, options.node, options.conninfo);
return;
}
static void static void
do_standby_clone(void) do_standby_clone(void)
{ {
@@ -2224,7 +2313,7 @@ help(const char *progname)
printf(_("\n")); printf(_("\n"));
printf(_("Usage:\n")); printf(_("Usage:\n"));
printf(_(" %s [OPTIONS] master {register}\n"), progname); printf(_(" %s [OPTIONS] master {register}\n"), progname);
printf(_(" %s [OPTIONS] standby {register|clone|promote|follow}\n"), printf(_(" %s [OPTIONS] standby {register|unregister|clone|promote|follow}\n"),
progname); progname);
printf(_(" %s [OPTIONS] cluster {show|cleanup}\n"), progname); printf(_(" %s [OPTIONS] cluster {show|cleanup}\n"), progname);
printf(_("\n")); printf(_("\n"));
@@ -2264,6 +2353,7 @@ help(const char *progname)
printf(_(" master register - registers the master in a cluster\n")); printf(_(" master register - registers the master in a cluster\n"));
printf(_(" standby clone [node] - creates a new standby\n")); printf(_(" standby clone [node] - creates a new standby\n"));
printf(_(" standby register - registers a standby in a cluster\n")); printf(_(" standby register - registers a standby in a cluster\n"));
printf(_(" standby unregister - unregisters a standby in a cluster\n"));
printf(_(" standby promote - promotes a specific standby to master\n")); printf(_(" standby promote - promotes a specific standby to master\n"));
printf(_(" standby follow - makes standby follow a new master\n")); printf(_(" standby follow - makes standby follow a new master\n"));
printf(_(" cluster show - displays information about cluster nodes\n")); printf(_(" cluster show - displays information about cluster nodes\n"));
@@ -2597,6 +2687,23 @@ check_parameters_for_action(const int action)
error_list_append(_("destination directory not required when executing STANDBY REGISTER")); error_list_append(_("destination directory not required when executing STANDBY REGISTER"));
} }
break; break;
case STANDBY_UNREGISTER:
/*
* To unregister a standby we only need the repmgr.conf we don't
* need connection parameters to the master because we can detect
* the master in repl_nodes
*/
if (runtime_options.host[0] || runtime_options.masterport[0] ||
runtime_options.username[0] || runtime_options.dbname[0])
{
error_list_append(_("master connection parameters not required when executing STANDBY UNREGISTER"));
}
if (runtime_options.dest_dir[0])
{
error_list_append(_("destination directory not required when executing STANDBY UNREGISTER"));
}
break;
case STANDBY_PROMOTE: case STANDBY_PROMOTE:
/* /*