]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add 'setRoundRobinFailOnNoServer()'
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 9 Apr 2019 14:39:57 +0000 (16:39 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 9 Apr 2019 14:39:57 +0000 (16:39 +0200)
pdns/dnsdist-lua.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsdistdist/docs/guides/serverselection.rst
regression-tests.dnsdist/test_Routing.py

index 69e5c571f67178cb8e6242c0d19a180e517382b9..f8a9d749c1b974306be6c9d86ce45786341c0542 100644 (file)
@@ -1458,6 +1458,11 @@ void setupLuaConfig(bool client)
       g_servFailOnNoPolicy = servfail;
     });
 
+  g_lua.writeFunction("setRoundRobinFailOnNoServer", [](bool fail) {
+      setLuaSideEffect();
+      g_roundrobinFailOnNoServer = fail;
+    });
+
   g_lua.writeFunction("setRingBuffersSize", [](size_t capacity, boost::optional<size_t> numberOfShards) {
       setLuaSideEffect();
       if (g_configurationDone) {
index 461c5f389649257d2ca3a08b69294b1b3bfcfd58..a6575eebae91dd9cb5e34e2ab022c21c0758b99c 100644 (file)
@@ -142,6 +142,7 @@ bool g_servFailOnNoPolicy{false};
 bool g_truncateTC{false};
 bool g_fixupCase{false};
 bool g_preserveTrailingData{false};
+bool g_roundrobinFailOnNoServer{false};
 
 static void truncateTC(char* packet, uint16_t* len, size_t responseSize, unsigned int consumed)
 try
@@ -884,7 +885,7 @@ shared_ptr<DownstreamState> roundrobin(const NumberedServerVector& servers, cons
   }
 
   const auto *res=&poss;
-  if(poss.empty())
+  if(poss.empty() && !g_roundrobinFailOnNoServer)
     res = &servers;
 
   if(res->empty())
index 663e18061bdb115b3deaef847b91d12ef1fa5d5e..8325ad512dcb4949ad3e0fe95306de9fdb9739ff 100644 (file)
@@ -1034,6 +1034,7 @@ extern uint16_t g_downstreamTCPCleanupInterval;
 extern size_t g_udpVectorSize;
 extern bool g_preserveTrailingData;
 extern bool g_allowEmptyResponse;
+extern bool g_roundrobinFailOnNoServer;
 
 #ifdef HAVE_EBPF
 extern shared_ptr<BPFFilter> g_defaultBPFFilter;
index 191b934d6983d066c3e509230477086b3fd6ac6c..7e7a4495d27b374cd6127beb847c4d90769059ba 100644 (file)
@@ -54,6 +54,7 @@ You can also set the hash perturbation value, see :func:`setWHashedPertubation`.
 ~~~~~~~~~~~~~~
 
 The last available policy is ``roundrobin``, which indiscriminately sends each query to the next server that is up.
+If all servers are down, the policy will still select one server by default. Setting :func:`setRoundRobinFailOnNoServer` to ``true`` will change this behavior.
 
 Lua server policies
 -------------------
@@ -131,7 +132,7 @@ Functions
 
   If set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query.
 
-  :param bool value:
+  :param bool value: whether to return a servfail instead of dropping the query
 
 .. function:: setPoolServerPolicy(policy, pool)
 
@@ -148,6 +149,14 @@ Functions
   :param string function: name of the function
   :param string pool: Name of the pool
 
+.. function:: setRoundRobinFailOnNoServer(value)
+
+  .. versionadded:: 1.4.0
+
+  By default the roundrobin load-balancing policy will still try to select a backend even if all backends are currently down. Setting this to true will make the policy fail and return that no server is available instead.
+
+  :param bool value: whether to fail when all servers are down
+
 .. function:: showPoolServerPolicy(pool)
 
   Print server selection policy for ``pool``.
index e0bda09aebc4893b116377a8956efd4ab997bef3..386fba655f91ce2d8235e620cae1ac5283233e40 100644 (file)
@@ -220,6 +220,39 @@ class TestRoutingRoundRobinLBOneDown(DNSDistTest):
 
         self.assertEquals(total, numberOfQueries * 2)
 
+class TestRoutingRoundRobinLBAllDown(DNSDistTest):
+
+    _testServer2Port = 5351
+    _config_params = ['_testServerPort', '_testServer2Port']
+    _config_template = """
+    setServerPolicy(roundrobin)
+    setRoundRobinFailOnNoServer(true)
+    s1 = newServer{address="127.0.0.1:%s"}
+    s1:setDown()
+    s2 = newServer{address="127.0.0.1:%s"}
+    s2:setDown()
+    """
+
+    def testRRWithAllDown(self):
+        """
+        Routing: Round Robin with all servers down
+        """
+        numberOfQueries = 10
+        name = 'alldown.rr.routing.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '192.0.2.1')
+        response.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.assertEquals(receivedResponse, None)
+
 class TestRoutingOrder(DNSDistTest):
 
     _testServer2Port = 5351