]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: dns: runtime resolution can change server admin state
authorBaptiste Assmann <bedis9@gmail.com>
Wed, 2 Nov 2016 21:58:18 +0000 (22:58 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 9 Nov 2016 14:30:47 +0000 (15:30 +0100)
WARNING: this is a MAJOR (and disruptive) change with previous HAProxy's
behavior: before, HAProxy never ever used to change a server administrative
status when the DNS resolution failed at run time.

This patch gives HAProxy the ability to change the administrative status
of a server to MAINT (RMAINT actually) when an error is encountered for
a period longer than its own allowed by the corresponding 'hold'
parameter.

IE if the configuration sets "hold nx 10s" and a server's hostname
points to a NX for more than 10s, then the server will be set to RMAINT,
hence in MAINTENANCE mode.

src/server.c

index cf5891838408da488eac9a768b04cff192f91003..f2e419daec99c271f1a81bce942556129e62e990 100644 (file)
@@ -2845,6 +2845,9 @@ out:
 int snr_update_srv_status(struct server *s)
 {
        struct dns_resolution *resolution = s->resolution;
+       struct dns_resolvers *resolvers;
+
+       resolvers = resolution->resolvers;
 
        switch (resolution->status) {
                case RSLV_STATUS_NONE:
@@ -2852,7 +2855,59 @@ int snr_update_srv_status(struct server *s)
                        trigger_resolution(s);
                        break;
 
+               case RSLV_STATUS_VALID:
+                       /*
+                        * resume health checks
+                        * server will be turned back on if health check is safe
+                        */
+                       if (!(s->admin & SRV_ADMF_RMAINT))
+                               return 1;
+                       srv_clr_admin_flag(s, SRV_ADMF_RMAINT);
+                       chunk_printf(&trash, "Server %s/%s administratively READY thanks to valid DNS answer",
+                                    s->proxy->id, s->id);
+
+                       Warning("%s.\n", trash.str);
+                       send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+                       return 0;
+
+               case RSLV_STATUS_NX:
+                       /* stop server if resolution is NX for a long enough period */
+                       if (tick_is_expired(tick_add(resolution->last_status_change, resolvers->hold.nx), now_ms)) {
+                               if (s->admin & SRV_ADMF_RMAINT)
+                                       return 1;
+                               srv_set_admin_flag(s, SRV_ADMF_RMAINT, "DNS NX status");
+                               return 0;
+                       }
+                       break;
+
+               case RSLV_STATUS_TIMEOUT:
+                       /* stop server if resolution is TIMEOUT for a long enough period */
+                       if (tick_is_expired(tick_add(resolution->last_status_change, resolvers->hold.timeout), now_ms)) {
+                               if (s->admin & SRV_ADMF_RMAINT)
+                                       return 1;
+                               srv_set_admin_flag(s, SRV_ADMF_RMAINT, "DNS timeout status");
+                               return 0;
+                       }
+                       break;
+
+               case RSLV_STATUS_REFUSED:
+                       /* stop server if resolution is REFUSED for a long enough period */
+                       if (tick_is_expired(tick_add(resolution->last_status_change, resolvers->hold.refused), now_ms)) {
+                               if (s->admin & SRV_ADMF_RMAINT)
+                                       return 1;
+                               srv_set_admin_flag(s, SRV_ADMF_RMAINT, "DNS refused status");
+                               return 0;
+                       }
+                       break;
+
                default:
+                       /* stop server if resolution is in unmatched error for a long enough period */
+                       if (tick_is_expired(tick_add(resolution->last_status_change, resolvers->hold.other), now_ms)) {
+                               if (s->admin & SRV_ADMF_RMAINT)
+                                       return 1;
+                               srv_set_admin_flag(s, SRV_ADMF_RMAINT, "unspecified DNS error");
+                               return 0;
+                       }
                        break;
        }