diff --git a/doc/source/configuration_synopsis.rst b/doc/source/configuration_synopsis.rst index 4b4a11355e..ac6985a951 100644 --- a/doc/source/configuration_synopsis.rst +++ b/doc/source/configuration_synopsis.rst @@ -142,6 +142,7 @@ VRRP Instance Definitions Synopsis **priority** num **advert_int** num **smtp_alert** + **exec_before_vip** **authentication** { **auth_type** *PASS|AH* **auth_pass** string @@ -185,6 +186,7 @@ notify_master specify a shell script to be executed during transit notify_backup specify a shell script to be executed during transition to backup state path notify_fault specify a shell script to be executed during transition to fault state path vrrp_sync_group Identify the VRRP synchronization instances group string +exec_before_vip notify_master script executed before vip setted if this setted true ========================== ======================================================================= ========= Path type: A system path to a script eg: “/usr/local/bin/transit.sh ” diff --git a/keepalived/include/vrrp.h b/keepalived/include/vrrp.h index 275d9359b2..914ccead13 100644 --- a/keepalived/include/vrrp.h +++ b/keepalived/include/vrrp.h @@ -368,7 +368,8 @@ typedef struct _vrrp_t { notify_script_t *script_deleted; notify_script_t *script_master_rx_lower_pri; notify_script_t *script; - int notify_priority_changes; + int exec_before_vip; /* exec script_master first before set vip address */ + int notify_priority_changes; /* rfc2338.6.2 */ uint32_t ms_down_timer; diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c index 2ea8d5167c..13d9cbb860 100644 --- a/keepalived/vrrp/vrrp.c +++ b/keepalived/vrrp/vrrp.c @@ -1709,8 +1709,10 @@ vrrp_state_become_master(vrrp_t * vrrp) vrrp->vmac_garp_timer = timer_add_now(vrrp->vmac_garp_intvl); #endif - /* Check if notify is needed */ - send_instance_notifies(vrrp); + if (!vrrp->exec_before_vip) { + /* Check if notify is needed */ + send_instance_notifies(vrrp); + } #ifdef _WITH_LVS_ /* Check if sync daemon handling is needed */ @@ -2026,6 +2028,9 @@ vrrp_state_master_tx(vrrp_t * vrrp) if (!VRRP_VIP_ISSET(vrrp)) { log_message(LOG_INFO, "(%s) Entering MASTER STATE" , vrrp->iname); + if (vrrp->exec_before_vip) { + send_instance_notifies(vrrp); + } vrrp_state_become_master(vrrp); /* * If we catch the master transition diff --git a/keepalived/vrrp/vrrp_notify.c b/keepalived/vrrp/vrrp_notify.c index 6047ce7fd0..7b5f3638ce 100644 --- a/keepalived/vrrp/vrrp_notify.c +++ b/keepalived/vrrp/vrrp_notify.c @@ -271,6 +271,7 @@ send_instance_notifies(vrrp_t *vrrp) { notify_script_t *script = get_iscript(vrrp); notify_script_t *gscript = get_igscript(vrrp); + bool sync_exec = vrrp->state == VRRP_STATE_MAST && vrrp->exec_before_vip; if (vrrp->notifies_sent && vrrp->sync && vrrp->state == vrrp->sync->state) { /* We are already in the required state due to our sync group, @@ -290,7 +291,7 @@ send_instance_notifies(vrrp_t *vrrp) if (vrrp->state == VRRP_STATE_STOP) system_call_script(master, child_killed_thread, NULL, TIMER_HZ, script); else - notify_exec(script); + system_call_script_0(NULL, NULL, NULL, 0, script, sync_exec); } /* Launch the generic notify script */ diff --git a/keepalived/vrrp/vrrp_parser.c b/keepalived/vrrp/vrrp_parser.c index 8ea2b1e670..1e2779bbd0 100644 --- a/keepalived/vrrp/vrrp_parser.c +++ b/keepalived/vrrp/vrrp_parser.c @@ -1165,6 +1165,21 @@ vrrp_notify_handler(const vector_t *strvec) current_vrrp->notify_exec = true; } static void +vrrp_script_exec_handler(const vector_t *strvec) +{ + vrrp_t *vrrp = list_last_entry(&vrrp_data->vrrp, vrrp_t, e_list); + int res = true; + + if (vector_size(strvec) >= 2) { + res = check_true_false(strvec_slot(strvec, 1)); + if (res == -1) { + report_config_error(CONFIG_GENERAL_ERROR, "Invalid vrrp_group exec_before_vip parameter %s", strvec_slot(strvec, 1)); + return; + } + } + vrrp->exec_before_vip = res; +} +static void vrrp_notify_master_rx_lower_pri(const vector_t *strvec) { if (current_vrrp->script_master_rx_lower_pri) { @@ -2159,7 +2174,8 @@ init_vrrp_keywords(bool active) install_keyword("notify_stop", &vrrp_notify_stop_handler); install_keyword("notify_deleted", &vrrp_notify_deleted_handler); install_keyword("notify", &vrrp_notify_handler); - install_keyword("notify_master_rx_lower_pri", vrrp_notify_master_rx_lower_pri); + install_keyword("exec_before_vip", &vrrp_script_exec_handler); + install_keyword("notify_master_rx_lower_pri", vrrp_notify_master_rx_lower_pri); install_keyword("smtp_alert", &vrrp_smtp_handler); install_keyword("notify_priority_changes", &vrrp_notify_priority_changes_handler); #ifdef _WITH_LVS_ diff --git a/lib/notify.c b/lib/notify.c index eb785787f0..ca6376016c 100644 --- a/lib/notify.c +++ b/lib/notify.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "notify.h" #include "signals.h" @@ -151,6 +152,12 @@ cmd_str(const notify_script_t *script) int system_call_script(thread_master_t *m, thread_func_t func, void * arg, unsigned long timer, const notify_script_t* script) +{ + return system_call_script_0(m, func, arg, timer, script, false); +} + +int +system_call_script_0(thread_master_t *m, thread_func_t func, void * arg, unsigned long timer, const notify_script_t* script, bool sync_exec) { pid_t pid; const char *str; @@ -172,6 +179,15 @@ system_call_script(thread_master_t *m, thread_func_t func, void * arg, unsigned } if (pid) { + int wait_ret; + pid_t wait_pid; + if (sync_exec) { + wait_pid = waitpid(pid, &wait_ret, 0); + if (wait_pid != pid || !WIFEXITED(wait_ret)) { + log_message(LOG_INFO, "Failed wait script process completed"); + return -1; + } + } /* parent process */ if (func) { thread_add_child(m, func, arg, pid, timer); diff --git a/lib/notify.h b/lib/notify.h index b3761c879b..9bf149a5d9 100644 --- a/lib/notify.h +++ b/lib/notify.h @@ -94,6 +94,7 @@ extern const char *cmd_str(const notify_script_t *); extern void notify_fifo_open(notify_fifo_t*, notify_fifo_t*, thread_func_t, const char *); extern void notify_fifo_close(notify_fifo_t*, notify_fifo_t*); extern int system_call_script(thread_master_t *, thread_func_t, void *, unsigned long, const notify_script_t *); +extern int system_call_script_0(thread_master_t *, thread_func_t, void *, unsigned long, const notify_script_t *, bool); extern int notify_exec(const notify_script_t *); extern void child_killed_thread(thread_ref_t); extern void script_killall(thread_master_t *, int, bool);