Skip to content
Snippets Groups Projects
Commit 41a32249 authored by Filip Siroky's avatar Filip Siroky Committed by Daniel Salzman
Browse files

tests-extra: add mod-stats

parent 051cd241
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env python3
''' Check 'stats' query module functionality. '''
import os
import random
from dnstest.libknot import libknot
from dnstest.module import ModStats
from dnstest.test import Test
from dnstest.utils import *
def check_item(server, section, item, value, idx=None, zone=None):
try:
ctl = libknot.control.KnotCtl()
ctl.connect(os.path.join(server.dir, "knot.sock"))
if zone:
ctl.send_block(cmd="zone-stats", section=section, item=item, zone=zone.name)
else:
ctl.send_block(cmd="stats", section=section, item=item)
stats = ctl.receive_stats()
finally:
ctl.send(libknot.control.KnotCtlType.END)
ctl.close()
if not stats and value == -1:
return
if zone:
stats = stats.get("zone").get(zone.name.lower())
if idx:
if value == -1:
isset(idx not in stats.get(section).get(item), idx)
return
else:
data = int(stats.get(section).get(item).get(idx))
else:
data = int(stats.get(section).get(item))
compare(data, value, "%s.%s" % (section, item))
ModStats.check()
proto = random.choice([4, 6])
t = Test(stress=False, tsig=False, address=proto)
knot = t.server("knot")
zones = t.zone_rnd(2)
t.link(zones, knot)
knot.add_module(None, ModStats())
knot.add_module(zones[0], ModStats())
knot.add_module(zones[1], ModStats())
t.start()
t.sleep(1)
check_item(knot, "server", "zone-count", 2)
resp = knot.dig(zones[0].name, "SOA", tries=1, udp=True)
query_size1 = resp.query_size()
reply_size1 = resp.response_size()
resp = knot.dig(zones[0].name, "NS", tries=1, udp=False)
query_size2 = resp.query_size()
reply_size2 = resp.response_size()
resp = knot.dig(zones[1].name, "TYPE11", tries=1, udp=True)
query_size3 = resp.query_size()
reply_size3 = resp.response_size()
# Sucessfull transfer.
resp = knot.dig(zones[0].name, "AXFR", tries=1)
resp.check_xfr(rcode="NOERROR")
xfr_query_size = resp.query_size()
# Cannot get xfr_reply_size :-/
# Successfull update.
up = knot.update(zones[1])
up.add(zones[1].name, "3600", "AAAA", "::1")
up.send("NOERROR")
ddns_query_size = up.query_size()
# Due to DDNS bulk processing, failed RCODE and response-bytes are not incremented!
# Check request protocol metrics.
check_item(knot, "mod-stats", "request-protocol", 2, "udp%s" % proto)
check_item(knot, "mod-stats", "request-protocol", 1, "udp%s" % proto, zone=zones[0])
check_item(knot, "mod-stats", "request-protocol", 1, "udp%s" % proto, zone=zones[1])
check_item(knot, "mod-stats", "request-protocol", 3, "tcp%s" % proto)
check_item(knot, "mod-stats", "request-protocol", 2, "tcp%s" % proto, zone=zones[0])
# Check request/response bytes metrics.
check_item(knot, "mod-stats", "request-bytes", query_size1 + query_size2 + query_size3,
"query")
check_item(knot, "mod-stats", "request-bytes", ddns_query_size, "update")
check_item(knot, "mod-stats", "request-bytes", xfr_query_size, "other")
check_item(knot, "mod-stats", "response-bytes", reply_size1 + reply_size2 + reply_size3,
"reply")
check_item(knot, "mod-stats", "request-bytes", query_size1 + query_size2, "query",
zone=zones[0])
check_item(knot, "mod-stats", "response-bytes", reply_size1 + reply_size2, "reply",
zone=zones[0])
check_item(knot, "mod-stats", "request-bytes", query_size3, "query", zone=zones[1])
check_item(knot, "mod-stats", "response-bytes", reply_size3, "reply", zone=zones[1])
# Check query size metrics (just for global module).
indices = dict()
for size in [query_size1, query_size2, query_size3]:
idx = "%i-%i" % (int(size / 16) * 16, int(size / 16) * 16 + 15)
if idx not in indices:
indices[idx] = 1
else:
indices[idx] += 1;
for size in indices:
check_item(knot, "mod-stats", "query-size", indices[size], idx=size)
# Check reply size metrics (just for global module).
indices = dict()
for size in [reply_size1, reply_size2, reply_size3]:
idx = "%i-%i" % (int(size / 16) * 16, int(size / 16) * 16 + 15)
if idx not in indices:
indices[idx] = 1
else:
indices[idx] += 1;
for size in indices:
check_item(knot, "mod-stats", "reply-size", indices[size], idx=size)
# Check query type metrics.
check_item(knot, "mod-stats", "query-type", 1, idx="SOA")
check_item(knot, "mod-stats", "query-type", 1, idx="NS")
check_item(knot, "mod-stats", "query-type", 1, idx="TYPE11")
check_item(knot, "mod-stats", "query-type", 1, idx="SOA", zone=zones[0])
check_item(knot, "mod-stats", "query-type", 1, idx="NS", zone=zones[0])
check_item(knot, "mod-stats", "query-type", -1, idx="TYPE11", zone=zones[0])
check_item(knot, "mod-stats", "query-type", -1, idx="SOA", zone=zones[1])
check_item(knot, "mod-stats", "query-type", -1, idx="NS", zone=zones[1])
check_item(knot, "mod-stats", "query-type", 1, idx="TYPE11", zone=zones[1])
# Check server operation metrics.
check_item(knot, "mod-stats", "server-operation", 3, idx="query")
check_item(knot, "mod-stats", "server-operation", 1, idx="axfr")
check_item(knot, "mod-stats", "server-operation", 1, idx="update")
# Check response code metrics.
check_item(knot, "mod-stats", "response-code", 4, idx="NOERROR")
check_item(knot, "mod-stats", "response-code", 3, idx="NOERROR", zone=zones[0])
check_item(knot, "mod-stats", "response-code", 1, idx="NOERROR", zone=zones[1])
# Check nodata metrics.
check_item(knot, "mod-stats", "reply-nodata", 1, idx="other")
check_item(knot, "mod-stats", "reply-nodata", -1, idx="other", zone=zones[0])
check_item(knot, "mod-stats", "reply-nodata", 1, idx="other", zone=zones[1])
t.end()
......@@ -181,3 +181,36 @@ class ModRosedb(KnotModule):
set_err("ROSEDB_TOOL")
detail_log("!Failed to add a record into rosedb '%s'" % self.dbdir)
detail_log(SEP)
class ModStats(KnotModule):
'''Stats module'''
src_name = "stats_load"
conf_name = "mod-stats"
def __init__(self):
super().__init__()
def _bool(self, conf, name, value=True):
conf.item_str(name, "on" if value else "off")
def get_conf(self, conf=None):
if not conf:
conf = dnstest.config.KnotConf()
conf.begin(self.conf_name)
conf.id_item("id", self.conf_id)
self._bool(conf, "request-protocol", True)
self._bool(conf, "server-operation", True)
self._bool(conf, "request-bytes", True)
self._bool(conf, "response-bytes", True)
self._bool(conf, "edns-presence", True)
self._bool(conf, "flag-presence", True)
self._bool(conf, "response-code", True)
self._bool(conf, "reply-nodata", True)
self._bool(conf, "query-type", True)
self._bool(conf, "query-size", True)
self._bool(conf, "reply-size", True)
conf.end()
return conf
......@@ -392,3 +392,13 @@ class Response(object):
for rr in nsec3_rrs:
detail_log(" %s" % rr)
detail_log(SEP)
def query_size(self):
'''Return query size.'''
return len(self.query.to_wire())
def response_size(self):
'''Return response size.'''
return len(self.resp.to_wire())
......@@ -42,3 +42,8 @@ class Update(object):
if self.upd.keyring and not resp.had_tsig:
set_err("INVALID RESPONSE")
check_log("ERROR: Expected TSIG signed response")
def query_size(self):
'''Return update query size.'''
return len(self.upd.to_wire())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment