]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_Routing.py
Merge pull request #6019 from mind04/schema
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Routing.py
1 #!/usr/bin/env python
2 import threading
3 import time
4 import dns
5 from dnsdisttests import DNSDistTest
6
7 class TestRoutingPoolRouting(DNSDistTest):
8
9 _config_template = """
10 newServer{address="127.0.0.1:%s", pool="real"}
11 addAction(makeRule("poolaction.routing.tests.powerdns.com"), PoolAction("real"))
12 """
13
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 """
21 name = 'poolaction.routing.tests.powerdns.com.'
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
58 class TestRoutingQPSPoolRouting(DNSDistTest):
59 _config_template = """
60 newServer{address="127.0.0.1:%s", pool="regular"}
61 addAction(makeRule("qpspoolaction.routing.tests.powerdns.com"), QPSPoolAction(10, "regular"))
62 """
63
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
108 class 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..")
123 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
124 cls._UDPResponder.setDaemon(True)
125 cls._UDPResponder.start()
126 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
127 cls._UDPResponder2.setDaemon(True)
128 cls._UDPResponder2.start()
129
130 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
131 cls._TCPResponder.setDaemon(True)
132 cls._TCPResponder.start()
133
134 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
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
170 for key in self._responsesCounter:
171 value = self._responsesCounter[key]
172 self.assertEquals(value, numberOfQueries / 2)
173
174 class 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
219 for key in self._responsesCounter:
220 value = self._responsesCounter[key]
221 self.assertTrue(value == numberOfQueries or value == 0)
222 total += value
223
224 self.assertEquals(total, numberOfQueries * 2)
225
226 class 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..")
241 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
242 cls._UDPResponder.setDaemon(True)
243 cls._UDPResponder.start()
244 cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
245 cls._UDPResponder2.setDaemon(True)
246 cls._UDPResponder2.start()
247
248 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
249 cls._TCPResponder.setDaemon(True)
250 cls._TCPResponder.start()
251
252 cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue])
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
286 if 'UDP Responder' in self._responsesCounter:
287 self.assertEquals(self._responsesCounter['UDP Responder'], 0)
288 self.assertEquals(self._responsesCounter['UDP Responder 2'], numberOfQueries)
289 if 'TCP Responder' in self._responsesCounter:
290 self.assertEquals(self._responsesCounter['TCP Responder'], 0)
291 self.assertEquals(self._responsesCounter['TCP Responder 2'], numberOfQueries)
292
293 class 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)