knot-dns/tests-extra/tests/ctl/concurrent/test.py
Libor Peltan 6be870f0bf implemented multi-socket CTL...
...with each socket handled by a thread
2025-04-14 18:07:52 +02:00

178 lines
5.5 KiB
Python

#!/usr/bin/env python3
'''Test concurrent access to control socket.'''
from dnstest.utils import *
from dnstest.test import Test
import random
import threading
import time
zone_backup_running = dict()
def check_shutdown(server):
if not server.log_search("shutting down"):
set_err("server %s not shut down" % server.name)
def random_sleep():
time.sleep(random.choice([0, 0, 0, 0, 0, 0.1, 0.2, 1, 2, 3 ]))
def random_ctl(server, zone_name):
cmd = random.choice(["status", "reload", "stats", "zone-check", "zone-status", "zone-reload",
"zone-refresh", "zone-retransfer", "zone-notify", "zone-flush",
"zone-sign", "zone-keys-load", "zone-ksk-submitted", "zone-freeze",
"zone-thaw", "zone-xfr-freeze", "zone-xfr-thaw", "zone-read", "zone-get",
"zone-stats", "conf-init", "conf-list", "conf-read", "conf-diff",
"conf-get"])
if cmd[0:5] == "zone-" and random.choice([False, True, True]):
cmd += " " + zone_name
if random.choice([False, True]):
cmd = "-b " + cmd
try:
server.ctl(cmd, availability=False)
except:
pass
def random_ctls(server, zone_name):
for i in range(random.choice([1, 1, 2, 3])):
random_ctl(server, zone_name)
random_sleep()
def ctl_txn_generic(server, txn_start, txn_modify, txn_commit, txn_abort, abort_failed_start):
txnsock = server.ctl_sock_rnd()
try:
server.ctl("zone-status", availability=False, custom_parm=txnsock)
except:
pass
try:
server.ctl(txn_start, availability=False, custom_parm=txnsock)
except:
try:
if abort_failed_start:
server.ctl(txn_abort, availability=False, custom_parm=txnsock)
except:
pass
return
random_sleep()
try:
server.ctl(txn_modify, availability=False, custom_parm=txnsock)
random_sleep()
server.ctl(txn_commit, availability=False, custom_parm=txnsock)
except:
attempts = 9
while attempts > 0:
time.sleep(2)
attempts -= 1
try:
server.ctl(txn_abort, availability=False, custom_parm=txnsock)
attempts = 0
except:
pass
def bck_purge_rest(server, zone_name):
global zone_backup_running
if random.choice([False, True]) and not True in zone_backup_running.values():
zone_name = " "
if zone_name in zone_backup_running and zone_backup_running[zone_name]:
return
if " " in zone_backup_running and zone_backup_running[" "]:
return
zone_backup_running[zone_name] = True
bckdir = "%s/backup" % server.dir
bckdir += str(int(time.time()))
bckdir = " +backupdir " + bckdir
cmd_bck = "-t 14 -b zone-backup " + zone_name + bckdir
cmd_pur = "-b -f zone-purge " + ("--" if zone_name == " " else zone_name)
cmd_res = "-b zone-restore " + zone_name + bckdir
ctl_txn_generic(server, cmd_bck, cmd_pur, cmd_res, cmd_res, False)
try:
server.ctl("zone-refresh " + zone_name, availability=False)
except:
pass
try:
server.ctl("zone-reload " + zone_name, availability=False)
except:
pass
for i in range(10):
try:
resp = server.dig(zone_name, "SOA")
if resp.count("SOA") > 0:
break
except:
pass
time.sleep(1)
zone_backup_running[zone_name] = False
def ctl_update(server, zone_name):
ctl_txn_generic(server, "-b zone-begin " + zone_name,
"zone-set " + zone_name + " abc 3600 A 1.2.3." + str(random.randint(1, 254)),
"zone-commit " + zone_name, "zone-abort " + zone_name, True)
def conf_update(server, zone_name):
ctl_txn_generic(server, "conf-begin",
"conf-set zone[" + zone_name + "].zonemd-generate " + random.choice(["none", "zonemd-sha384", "zonemd-sha512", "remove"]),
"conf-commit", "conf-abort", True)
def random_thing(server, zone_name):
scn = random.choice([random_ctls, random_ctls, random_ctls, random_ctls, bck_purge_rest, ctl_update, conf_update])
scn(server, zone_name)
def run_thr(fun, server, zone_name):
threading.Thread(target=fun, args=[server, zone_name]).start()
t = Test()
master = t.server("knot")
slave = t.server("knot")
zones = t.zone_rnd(2, dnssec=False, records=40)
t.link(zones, master, slave)
for z in zones:
master.dnssec(z).enable = True
master.dnssec(z).nsec3 = True
for s in [ master, slave ]:
s.bg_workers = 3
s.udp_workers = 1
s.tcp_workers = 1
t.start()
slave.zones_wait(zones)
for i in range(60):
s = random.choice([master, slave])
z = random.choice(zones)
run_thr(random_thing, s, z.name)
random_sleep()
for s in [ master, slave ]:
for z in zones:
try:
s.ctl("zone-xfr-thaw " + z.name, availability=False)
s.ctl("zone-thaw " + z.name, availability=False)
s.ctl("zone-notify " + z.name, availability=False)
except:
pass
for s in [ master, slave ]:
try:
s.ctl("conf-abort", availability=False)
except:
pass
for z in zones:
try:
s.ctl("zone-abort " + z.name, availability=False)
except:
pass
t.sleep(10)
master.zones_wait(zones) # check that server is still operable
slave.zones_wait(zones) # check that server is still operable
t.end()
time.sleep(4)
for s in [ master, slave ]:
check_shutdown(s)