]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_Routing.py
dnsdist tests: make py3k compatible and pick py3k if available
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Routing.py
CommitLineData
903853f4
RG
1#!/usr/bin/env python
2import threading
3import time
4import dns
5from dnsdisttests import DNSDistTest
6
7class TestRoutingPoolRouting(DNSDistTest):
8
9 _config_template = """
10 newServer{address="127.0.0.1:%s", pool="real"}
903853f4 11 addAction(makeRule("poolaction.routing.tests.powerdns.com"), PoolAction("real"))
903853f4
RG
12 """
13
903853f4
RG
14 def testPolicyPoolAction(self):
15 """
16 Routing: Set pool by qname via PoolAction
17
18 Send an A query to "poolaction.routing.tests.powerdns.com.",
19 check that dnsdist routes the query to the "real" pool.
20 """
6bb38cd6 21 name = 'poolaction.routing.tests.powerdns.com.'
903853f4
RG
22 query = dns.message.make_query(name, 'A', 'IN')
23 response = dns.message.make_response(query)
24 rrset = dns.rrset.from_text(name,
25 60,
26 dns.rdataclass.IN,
27 dns.rdatatype.A,
28 '192.0.2.1')
29 response.answer.append(rrset)
30
31 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
32 receivedQuery.id = query.id
33 self.assertEquals(query, receivedQuery)
34 self.assertEquals(response, receivedResponse)
35
36 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
37 receivedQuery.id = query.id
38 self.assertEquals(query, receivedQuery)
39 self.assertEquals(response, receivedResponse)
40
41 def testDefaultPool(self):
42 """
43 Routing: Set pool by qname canary
44
45 Send an A query to "notpool.routing.tests.powerdns.com.",
46 check that dnsdist sends no response (no servers
47 in the default pool).
48 """
49 name = 'notpool.routing.tests.powerdns.com.'
50 query = dns.message.make_query(name, 'A', 'IN')
51
52 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
53 self.assertEquals(receivedResponse, None)
54
55 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
56 self.assertEquals(receivedResponse, None)
57
58class TestRoutingQPSPoolRouting(DNSDistTest):
59 _config_template = """
60 newServer{address="127.0.0.1:%s", pool="regular"}
903853f4
RG
61 addAction(makeRule("qpspoolaction.routing.tests.powerdns.com"), QPSPoolAction(10, "regular"))
62 """
63
903853f4
RG
64 def testQPSPoolAction(self):
65 """
66 Routing: Set pool by QPS via action
67
68 Send queries to "qpspoolaction.routing.tests.powerdns.com."
69 check that dnsdist does not route the query to the "regular" pool
70 when the max QPS has been reached.
71 """
72 maxQPS = 10
73 name = 'qpspoolaction.routing.tests.powerdns.com.'
74 query = dns.message.make_query(name, 'A', 'IN')
75 response = dns.message.make_response(query)
76 rrset = dns.rrset.from_text(name,
77 60,
78 dns.rdataclass.IN,
79 dns.rdatatype.A,
80 '192.0.2.1')
81 response.answer.append(rrset)
82
83 for _ in range(maxQPS):
84 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
85 receivedQuery.id = query.id
86 self.assertEquals(query, receivedQuery)
87 self.assertEquals(response, receivedResponse)
88
89 # we should now be sent to the "abuse" pool which is empty,
90 # so the queries should be dropped
91 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
92 self.assertEquals(receivedResponse, None)
93
94 time.sleep(1)
95
96 # again, over TCP this time
97 for _ in range(maxQPS):
98 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
99 receivedQuery.id = query.id
100 self.assertEquals(query, receivedQuery)
101 self.assertEquals(response, receivedResponse)
102
103
104 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
105 self.assertEquals(receivedResponse, None)
106
107
108class TestRoutingRoundRobinLB(DNSDistTest):
109
110 _testServer2Port = 5351
111 _config_params = ['_testServerPort', '_testServer2Port']
112 _config_template = """
113 setServerPolicy(roundrobin)
114 s1 = newServer{address="127.0.0.1:%s"}
115 s1:setUp()
116 s2 = newServer{address="127.0.0.1:%s"}
117 s2:setUp()
118 """
119
120 @classmethod
121 def startResponders(cls):
122 print("Launching responders..")
5df86a8a 123 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
903853f4
RG
124 cls._UDPResponder.setDaemon(True)
125 cls._UDPResponder.start()
5df86a8a 126 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
903853f4
RG
127 cls._UDPResponder2.setDaemon(True)
128 cls._UDPResponder2.start()
129
5df86a8a 130 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
903853f4
RG
131 cls._TCPResponder.setDaemon(True)
132 cls._TCPResponder.start()
133
5df86a8a 134 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
903853f4
RG
135 cls._TCPResponder2.setDaemon(True)
136 cls._TCPResponder2.start()
137
138 def testRR(self):
139 """
140 Routing: Round Robin
141
142 Send 100 A queries to "rr.routing.tests.powerdns.com.",
143 check that dnsdist routes half of it to each backend.
144 """
145 numberOfQueries = 10
146 name = 'rr.routing.tests.powerdns.com.'
147 query = dns.message.make_query(name, 'A', 'IN')
148 response = dns.message.make_response(query)
149 rrset = dns.rrset.from_text(name,
150 60,
151 dns.rdataclass.IN,
152 dns.rdatatype.A,
153 '192.0.2.1')
154 response.answer.append(rrset)
155
156 # the round robin counter is shared for UDP and TCP,
157 # so we need to do UDP then TCP to have a clean count
158 for _ in range(numberOfQueries):
159 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
160 receivedQuery.id = query.id
161 self.assertEquals(query, receivedQuery)
162 self.assertEquals(response, receivedResponse)
163
164 for _ in range(numberOfQueries):
165 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
166 receivedQuery.id = query.id
167 self.assertEquals(query, receivedQuery)
168 self.assertEquals(response, receivedResponse)
169
02bbf9eb
RG
170 for key in self._responsesCounter:
171 value = self._responsesCounter[key]
903853f4
RG
172 self.assertEquals(value, numberOfQueries / 2)
173
174class TestRoutingRoundRobinLBOneDown(DNSDistTest):
175
176 _testServer2Port = 5351
177 _config_params = ['_testServerPort', '_testServer2Port']
178 _config_template = """
179 setServerPolicy(roundrobin)
180 s1 = newServer{address="127.0.0.1:%s"}
181 s1:setUp()
182 s2 = newServer{address="127.0.0.1:%s"}
183 s2:setDown()
184 """
185
186 def testRRWithOneDown(self):
187 """
188 Routing: Round Robin with one server down
189
190 Send 100 A queries to "rr.routing.tests.powerdns.com.",
191 check that dnsdist routes all of it to the only backend up.
192 """
193 numberOfQueries = 10
194 name = 'rr.routing.tests.powerdns.com.'
195 query = dns.message.make_query(name, 'A', 'IN')
196 response = dns.message.make_response(query)
197 rrset = dns.rrset.from_text(name,
198 60,
199 dns.rdataclass.IN,
200 dns.rdatatype.A,
201 '192.0.2.1')
202 response.answer.append(rrset)
203
204 # the round robin counter is shared for UDP and TCP,
205 # so we need to do UDP then TCP to have a clean count
206 for _ in range(numberOfQueries):
207 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
208 receivedQuery.id = query.id
209 self.assertEquals(query, receivedQuery)
210 self.assertEquals(response, receivedResponse)
211
212 for _ in range(numberOfQueries):
213 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
214 receivedQuery.id = query.id
215 self.assertEquals(query, receivedQuery)
216 self.assertEquals(response, receivedResponse)
217
218 total = 0
02bbf9eb
RG
219 for key in self._responsesCounter:
220 value = self._responsesCounter[key]
903853f4
RG
221 self.assertTrue(value == numberOfQueries or value == 0)
222 total += value
223
224 self.assertEquals(total, numberOfQueries * 2)
d12cd8e9
RG
225
226class TestRoutingOrder(DNSDistTest):
227
228 _testServer2Port = 5351
229 _config_params = ['_testServerPort', '_testServer2Port']
230 _config_template = """
231 setServerPolicy(firstAvailable)
232 s1 = newServer{address="127.0.0.1:%s", order=2}
233 s1:setUp()
234 s2 = newServer{address="127.0.0.1:%s", order=1}
235 s2:setUp()
236 """
237
238 @classmethod
239 def startResponders(cls):
240 print("Launching responders..")
5df86a8a 241 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
d12cd8e9
RG
242 cls._UDPResponder.setDaemon(True)
243 cls._UDPResponder.start()
5df86a8a 244 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
d12cd8e9
RG
245 cls._UDPResponder2.setDaemon(True)
246 cls._UDPResponder2.start()
247
5df86a8a 248 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
d12cd8e9
RG
249 cls._TCPResponder.setDaemon(True)
250 cls._TCPResponder.start()
251
5df86a8a 252 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
d12cd8e9
RG
253 cls._TCPResponder2.setDaemon(True)
254 cls._TCPResponder2.start()
255
256 def testOrder(self):
257 """
258 Routing: firstAvailable policy based on 'order'
259
260 Send 50 A queries to "order.routing.tests.powerdns.com.",
261 check that dnsdist routes all of it to the second backend
262 because it has the lower order value.
263 """
264 numberOfQueries = 50
265 name = 'order.routing.tests.powerdns.com.'
266 query = dns.message.make_query(name, 'A', 'IN')
267 response = dns.message.make_response(query)
268 rrset = dns.rrset.from_text(name,
269 60,
270 dns.rdataclass.IN,
271 dns.rdatatype.A,
272 '192.0.2.1')
273 response.answer.append(rrset)
274
275 for _ in range(numberOfQueries):
276 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
277 receivedQuery.id = query.id
278 self.assertEquals(query, receivedQuery)
279 self.assertEquals(response, receivedResponse)
280 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
281 receivedQuery.id = query.id
282 self.assertEquals(query, receivedQuery)
283 self.assertEquals(response, receivedResponse)
284
285 total = 0
26a3cdb7
RG
286 if 'UDP Responder' in self._responsesCounter:
287 self.assertEquals(self._responsesCounter['UDP Responder'], 0)
d12cd8e9 288 self.assertEquals(self._responsesCounter['UDP Responder 2'], numberOfQueries)
26a3cdb7
RG
289 if 'TCP Responder' in self._responsesCounter:
290 self.assertEquals(self._responsesCounter['TCP Responder'], 0)
d12cd8e9 291 self.assertEquals(self._responsesCounter['TCP Responder 2'], numberOfQueries)
26a3cdb7
RG
292
293class TestRoutingNoServer(DNSDistTest):
294
295 _config_template = """
296 newServer{address="127.0.0.1:%s", pool="real"}
297 setServFailWhenNoServer(true)
298 """
299
300 def testPolicyPoolNoServer(self):
301 """
302 Routing: No server should return ServFail
303 """
304 name = 'noserver.routing.tests.powerdns.com.'
305 query = dns.message.make_query(name, 'A', 'IN')
306 expectedResponse = dns.message.make_response(query)
307 expectedResponse.set_rcode(dns.rcode.SERVFAIL)
308
309 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
310 self.assertEquals(receivedResponse, expectedResponse)
311
312 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
313 self.assertEquals(receivedResponse, expectedResponse)