From 7e1e159a9105d9e47c7e87c1d7a102df58c1dba5 Mon Sep 17 00:00:00 2001 From: weiyanhua Date: Wed, 12 Feb 2020 19:01:30 +0800 Subject: [PATCH] =?UTF-8?q?different=20virutal-service=20may=20refer=20to?= =?UTF-8?q?=20the=20same=20address=EF=BC=8Cwhen=20the=20address=20is=20ope?= =?UTF-8?q?rated=20by=20the=20script=20specified=20by=20quorum=5Fown=20var?= =?UTF-8?q?,=20Add=20judgment=20of=20other=20virtual-service's=20quorum=5F?= =?UTF-8?q?state=20that=20refer=20the=20same=20address.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/keepalived/keepalived/check/ipwrapper.c | 176 +++++++++++++++++- 1 file changed, 175 insertions(+), 1 deletion(-) diff --git a/tools/keepalived/keepalived/check/ipwrapper.c b/tools/keepalived/keepalived/check/ipwrapper.c index a83ec7450..1c3ba049b 100755 --- a/tools/keepalived/keepalived/check/ipwrapper.c +++ b/tools/keepalived/keepalived/check/ipwrapper.c @@ -160,6 +160,178 @@ notify_fifo_rs(virtual_server_t* vs, real_server_t* rs) FREE(line); } +static int vs_addr_cmp(struct sockaddr_storage *addr_a, struct sockaddr_storage *addr_b) +{ + int ret = 0; + + if (addr_a->ss_family != addr_b->ss_family) + return 0; + + if (addr_a->ss_family == AF_INET6) { + ret = inaddr_equal(AF_INET6, &((struct sockaddr_in6 *)addr_a)->sin6_addr, + &((struct sockaddr_in6 *)addr_b)->sin6_addr); + } else { + ret = inaddr_equal(AF_INET, &((struct sockaddr_in *)addr_a)->sin_addr, + &((struct sockaddr_in *)addr_b)->sin_addr); + } + + return ret; +} + +static int __vs_group_rang_addr_cmp(struct sockaddr_storage *addr, + virtual_server_group_entry_t *vsg_entry) +{ + uint32_t addr_ip, ip; + struct sockaddr_storage vip_addr; + int ret = 0; + + vip_addr = vsg_entry->addr; + if (vsg_entry->addr.ss_family == AF_INET6) { + //inet_sockaddrip6(&vsg_entry->addr, &addr.in6); + ip = ((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3]; + } else { + ip = ((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr; + } + + /* Parse the whole range */ + for (addr_ip = ip; + ((addr_ip >> 24) & 0xFF) <= vsg_entry->range; + addr_ip += 0x01000000) { + if (vsg_entry->addr.ss_family == AF_INET6) { + ((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3] = addr_ip; + } else { + ((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr = addr_ip; + } + + ret |= vs_addr_cmp(addr, &vip_addr); + } + return ret; + +} + +static int __vs_group_addr_cmp(struct sockaddr_storage *addr, virtual_server_group_t *vsg) +{ + virtual_server_group_entry_t *vsg_entry = NULL; + list l; + element e; + int ret = 0; + + /* visit range list */ + l = vsg->addr_range; + for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { + vsg_entry = ELEMENT_DATA(e); + ret |= __vs_group_rang_addr_cmp(addr, vsg_entry); + } + + return ret; +} + +static int __vs_group_rang_cmp(virtual_server_group_entry_t *vsg_entry, + virtual_server_group_t *vsg) +{ + uint32_t addr_ip, ip; + struct sockaddr_storage vip_addr; + int ret = 0; + + vip_addr = vsg_entry->addr; + if (vsg_entry->addr.ss_family == AF_INET6) { + //inet_sockaddrip6(&vsg_entry->addr, &addr.in6); + ip = ((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3]; + } else { + ip = ((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr; + } + + /* Parse the whole range */ + for (addr_ip = ip; + ((addr_ip >> 24) & 0xFF) <= vsg_entry->range; + addr_ip += 0x01000000) { + if (vsg_entry->addr.ss_family == AF_INET6) { + ((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3] = addr_ip; + } else { + ((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr = addr_ip; + } + ret |= __vs_group_addr_cmp(&vip_addr, vsg); + } + return ret; +} + +static int vs_group_addr_cmp(virtual_server_t *vs_a, virtual_server_t *vs_b) +{ + virtual_server_group_t *vsg_a = ipvs_get_group_by_name(vs_a->vsgname, check_data->vs_group); + virtual_server_group_t *vsg_b = ipvs_get_group_by_name(vs_b->vsgname, check_data->vs_group); + virtual_server_group_entry_t *vsg_entry; + list l; + element e; + int ret = 0; + + if (vsg_a == NULL || vsg_b == NULL) + return 0; + + if (vsg_a == vsg_b) + return 1; + + /* visit addr_ip list */ + l = vsg_a->addr_ip; + for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { + vsg_entry = ELEMENT_DATA(e); + ret |= __vs_group_addr_cmp(&vsg_entry->addr, vsg_b); + } + + /* visit range list */ + l = vsg_a->addr_range; + for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { + vsg_entry = ELEMENT_DATA(e); + ret |= __vs_group_rang_cmp(vsg_entry, vsg_b); + } + + return ret; +} + +static int all_vs_quorum_down(virtual_server_t *var_vs) +{ + element e; + virtual_server_t *tmp_vs = NULL; + virtual_server_group_t *vsg = NULL; + list l; + int ret = 0; + + if (NULL == check_data) { + return 1; + } + + l = check_data->vs; + + if (LIST_ISEMPTY(l)) { + return 1; + } + + for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { + tmp_vs = ELEMENT_DATA(e); + if (false == tmp_vs->quorum_state_up) + continue; + + if (var_vs->vsgname && tmp_vs->vsgname) { + ret = vs_group_addr_cmp(var_vs, tmp_vs); + } else if (var_vs->vsgname && NULL == tmp_vs->vsgname) { + vsg = ipvs_get_group_by_name(var_vs->vsgname, check_data->vs_group); + ret = __vs_group_addr_cmp(&tmp_vs->addr, vsg); + } else if (NULL == var_vs->vsgname && tmp_vs->vsgname) { + vsg = ipvs_get_group_by_name(tmp_vs->vsgname, check_data->vs_group); + ret = __vs_group_addr_cmp(&var_vs->addr, vsg); + } else { + ret = vs_addr_cmp(&var_vs->addr, &tmp_vs->addr); + } + + if (ret) { + log_message(LOG_INFO, "VS [%s] have the same vip with VS [%s], and the quorum_state is UP", + (tmp_vs->vsgname) ? tmp_vs->vsgname : FMT_VS(tmp_vs) + ,(var_vs->vsgname) ? var_vs->vsgname : FMT_VS(var_vs)); + return 0; + } + } + return 1; +} + static void do_vs_notifies(virtual_server_t* vs, bool init, long threshold, long weight_sum, bool stopping) { @@ -177,8 +349,10 @@ do_vs_notifies(virtual_server_t* vs, bool init, long threshold, long weight_sum, if (notify_script) { if (stopping) system_call_script(master, child_killed_thread, NULL, TIMER_HZ, notify_script); - else + else if (vs->quorum_state_up || ((!vs->quorum_state_up) && all_vs_quorum_down(vs))) { + log_message(LOG_INFO, "Execute script: %s.", cmd_str(notify_script)); notify_exec(notify_script); + } } notify_fifo_vs(vs);