Commit 0fea7f15 authored by Daniel Salzman's avatar Daniel Salzman

python: extend control interface

parent c463afff
......@@ -4,33 +4,22 @@ Example:
ctl = KnotCtl()
ctl.connect("/var/run/knot/knot.sock")
query = KnotCtlData()
query[KnotCtlDataIdx.COMMAND] = "conf-read"
query[KnotCtlDataIdx.SECTION] = "zone"
ctl.send(KnotCtlType.DATA, query)
ctl.send(KnotCtlType.BLOCK)
while True:
reply = KnotCtlData()
reply_type = ctl.receive(reply)
if reply_type is KnotCtlType.DATA:
print("--- NEXT ---")
for i in KnotCtlDataIdx:
if reply[i]:
print("%s: %s" % (i.name, reply[i]))
elif reply_type is KnotCtlType.EXTRA:
if reply[KnotCtlDataIdx.TYPE]:
print(reply[KnotCtlDataIdx.TYPE] + ": " +
reply[KnotCtlDataIdx.DATA])
elif reply[KnotCtlDataIdx.DATA]:
print("DATA: " + reply[KnotCtlDataIdx.DATA])
else:
break
ctl.send(KnotCtlType.END)
ctl.close()
try:
ctl.send_block(cmd="conf-begin")
resp = ctl.receive_block()
ctl.send_block(cmd="conf-set", section="zone", item="domain", data="test")
resp = ctl.receive_block()
ctl.send_block(cmd="conf-commit")
resp = ctl.receive_block()
ctl.send_block(cmd="conf-read", section="zone", item="domain")
resp = ctl.receive_block()
print(json.dumps(resp, indent=4))
finally:
ctl.send(KnotCtlType.END)
ctl.close()
"""
from ctypes import cdll, c_void_p, c_int, c_char_p, c_uint, byref
......@@ -119,7 +108,7 @@ class KnotCtlData(object):
@type value: str
"""
self.data[index] = c_char_p(value.encode())
self.data[index] = c_char_p(value.encode()) if value else c_char_p()
class KnotCtl(object):
"""Libknot server control interface."""
......@@ -181,3 +170,87 @@ class KnotCtl(object):
err = CTL_ERROR(ret)
raise Exception(err if isinstance(err, str) else err.decode())
return KnotCtlType(data_type.value)
def send_block(self, cmd, section=None, identifier=None, item=None, zone=None, data=None):
"""Sends a control query block.
@type cmd: str
@type section: str
@type item: str
@type identifier: str
@type zone: str
@type data: str
"""
query = KnotCtlData()
query[KnotCtlDataIdx.COMMAND] = cmd
query[KnotCtlDataIdx.SECTION] = section
query[KnotCtlDataIdx.ITEM] = item
query[KnotCtlDataIdx.ID] = identifier
query[KnotCtlDataIdx.ZONE] = zone
query[KnotCtlDataIdx.DATA] = data
self.send(KnotCtlType.DATA, query)
self.send(KnotCtlType.BLOCK)
def receive_block(self):
"""Receives a control answer and returns it as a structured dictionary.
@rtype: dict
"""
out = dict()
while True:
reply = KnotCtlData()
reply_type = self.receive(reply)
# Stop if not data type.
if reply_type not in [KnotCtlType.DATA, KnotCtlType.EXTRA]:
break
# Check for an error.
if reply[KnotCtlDataIdx.ERROR]:
raise Exception(reply[KnotCtlDataIdx.ERROR])
# Check for config data.
if reply[KnotCtlDataIdx.SECTION]:
ident = reply[KnotCtlDataIdx.ID]
key = reply[KnotCtlDataIdx.ITEM]
# Check for zone data.
elif reply[KnotCtlDataIdx.ZONE]:
ident = reply[KnotCtlDataIdx.ZONE]
key = reply[KnotCtlDataIdx.TYPE]
else:
continue
section = reply[KnotCtlDataIdx.SECTION]
data = reply[KnotCtlDataIdx.DATA]
# Add the section if not exists.
if section:
if section not in out:
out[section] = dict()
level1 = out[section] if section else out
# Add the identifier if not exists.
if ident:
if ident not in level1:
level1[ident] = dict()
level2 = level1[ident] if ident else level1
# Add the key/value.
if key:
# Treat alone identifier item differently.
if reply[KnotCtlDataIdx.SECTION] and key in ["id", "domain", "target"]:
level1[data] = dict()
else:
if key not in level2:
level2[key] = list()
if data:
level2[key].append(data)
return out
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment