Reworked handling of state data, included support for KNOT RPCs and much more

parent c40670eb
......@@ -10,22 +10,22 @@ from yaml.parser import ParserError
from yangson.enumerations import ContentType, ValidationScope
from yangson.exceptions import YangsonException
from yangson.schema import SchemaError, SemanticError
from yangson.schemanode import SchemaError, SemanticError
from . import usr_op_handlers, usr_state_data_handlers
from . import usr_state_data_handlers
from .rest_server import RestServer
from .config import CONFIG_GLOBAL, load_config, print_config
from .config import CONFIG_GLOBAL, CONFIG_KNOT, load_config, print_config
from .data import JsonDatastore
from .helpers import DataHelpers, ErrorHelpers
from .handler_list import OP_HANDLERS, STATE_DATA_HANDLES, CONF_DATA_HANDLES
from .knot_api import knot_global_init, knot_connect, knot_disconnect
from .knot_api import KNOT, knot_connect, knot_disconnect
from .usr_op_handlers import OP_HANDLERS_IMPL
from .usr_conf_data_handlers import (
KnotConfServerListener,
KnotConfLogListener,
KnotConfZoneListener,
KnotConfControlListener,
KnotConfAclListener,
KnotZoneDataListener
KnotConfAclListener
)
......@@ -162,19 +162,22 @@ def main():
# Register configuration data node listeners
CONF_DATA_HANDLES.register_handler(KnotConfServerListener(datastore, "/dns-server:dns-server/server-options"))
CONF_DATA_HANDLES.register_handler(KnotConfLogListener(datastore, "/dns-server:dns-server/knot-dns:log"))
CONF_DATA_HANDLES.register_handler(KnotConfZoneListener(datastore, "/dns-server:dns-server/zones"))
CONF_DATA_HANDLES.register_handler(KnotConfZoneListener(datastore, "/dns-server:dns-server/zones/zone"))
CONF_DATA_HANDLES.register_handler(KnotConfControlListener(datastore, "/dns-server:dns-server/knot-dns:control-socket"))
CONF_DATA_HANDLES.register_handler(KnotConfAclListener(datastore, "/dns-server:dns-server/access-control-list"))
CONF_DATA_HANDLES.register_handler(KnotZoneDataListener(datastore, "/dns-zones:zone-data"))
# Register op handlers
OP_HANDLERS.register_handler("generate-key", usr_op_handlers.sign_op_handler)
OP_HANDLERS.register_handler("dns-zone-rpcs:begin-transaction", OP_HANDLERS_IMPL.zone_begin_transaction)
OP_HANDLERS.register_handler("dns-zone-rpcs:commit-transaction", OP_HANDLERS_IMPL.zone_commit_transaction)
OP_HANDLERS.register_handler("dns-zone-rpcs:abort-transaction", OP_HANDLERS_IMPL.zone_abort_transaction)
OP_HANDLERS.register_handler("dns-zone-rpcs:zone-set", OP_HANDLERS_IMPL.zone_set)
OP_HANDLERS.register_handler("dns-zone-rpcs:zone-unset", OP_HANDLERS_IMPL.zone_unset)
# Create and register state data node listeners
usr_state_data_handlers.create_zone_state_handlers(STATE_DATA_HANDLES, datamodel)
# Initialize Knot control interface
knot_global_init()
KNOT.set_socket(CONFIG_KNOT["SOCKET"])
datastore.commit_begin_callback = knot_connect
datastore.commit_end_callback = knot_disconnect
......
This diff is collapsed.
......@@ -5,7 +5,7 @@ from enum import Enum
from typing import List, Dict, Union, Any, Iterable
from datetime import datetime
from pytz import timezone
from yangson.instance import InstanceRoute, MemberName, EntryKeys, InstanceIdParser, ResourceIdParser
from yangson.instance import InstanceRoute, MemberName, EntryKeys
from yangson.datamodel import DataModel
from .config import CONFIG_GLOBAL, CONFIG_HTTP
......@@ -57,14 +57,14 @@ class DataHelpers:
return dm
# Parse Instance Identifier from string
@staticmethod
def parse_ii(path: str, path_format: PathFormat) -> InstanceRoute:
if path_format == PathFormat.URL:
ii = ResourceIdParser(path).parse()
else:
ii = InstanceIdParser(path).parse()
return ii
# @staticmethod
# def parse_ii(path: str, path_format: PathFormat) -> InstanceRoute:
# if path_format == PathFormat.URL:
# ii = ResourceIdParser(path).parse()
# else:
# ii = InstanceIdParser(path).parse()
#
# return ii
# Convert InstanceRoute or List[InstanceSelector] to string
@staticmethod
......
......@@ -8,8 +8,8 @@ from colorlog import error, warning as warn, info
from urllib.parse import parse_qs
from typing import Dict, List, Optional
from yangson.schema import NonexistentSchemaNode, ContainerNode, ListNode, GroupNode
from yangson.instance import NonexistentInstance, InstanceValueError
from yangson.schemanode import NonexistentSchemaNode, ContainerNode, ListNode, GroupNode, LeafListNode, LeafNode
from yangson.instance import NonexistentInstance, InstanceValueError, RootNode
from yangson.datatype import YangTypeError
from .config import CONFIG_GLOBAL, CONFIG_HTTP, NACM_ADMINS, API_ROOT_data, API_ROOT_STAGING_data, API_ROOT_ops
......@@ -123,7 +123,7 @@ def _get(ds: BaseDatastore, pth: str, username: str, yl_data: bool=False, stagin
except InstanceValueError as e:
warn(epretty(e))
http_resp = HttpResponse.empty(HttpStatus.BadRequest)
except ConfHandlerFailedError as e:
except (ConfHandlerFailedError, NoHandlerError) as e:
error(epretty(e))
http_resp = HttpResponse.empty(HttpStatus.InternalServerError)
finally:
......@@ -132,17 +132,16 @@ def _get(ds: BaseDatastore, pth: str, username: str, yl_data: bool=False, stagin
if n is not None:
n_value = n.raw_value()
try:
env_n = n.up()
env_sn = env_n.schema_node
print(n.schema_node)
print(env_sn)
if isinstance(env_sn, (ContainerNode, GroupNode)):
sn = n.schema_node
if isinstance(n, RootNode):
# Getting top-level node
restconf_env = "ietf-restconf:data"
restconf_n_value = {restconf_env: n_value}
else:
sn = n.schema_node
if isinstance(sn, (ContainerNode, GroupNode, LeafNode)):
restconf_env = "{}:{}".format(sn.qual_name[1], sn.qual_name[0])
restconf_n_value = {restconf_env: n_value}
elif isinstance(env_sn, ListNode):
sn = n.schema_node
elif isinstance(sn, ListNode):
restconf_env = "{}:{}".format(sn.qual_name[1], sn.qual_name[0])
if isinstance(n_value, list):
# List and list item points to the same schema node
......@@ -151,10 +150,6 @@ def _get(ds: BaseDatastore, pth: str, username: str, yl_data: bool=False, stagin
restconf_n_value = {restconf_env: [n_value]}
else:
raise HttpRequestError()
except NonexistentInstance:
# Getting root node (cannot go up)
restconf_env = "ietf-restconf:data"
restconf_n_value = {restconf_env: n_value}
response = json.dumps(restconf_n_value, indent=4)
......@@ -464,7 +459,7 @@ def create_api_op(ds: BaseDatastore):
rpc1 = RpcInfo()
rpc1.username = username
rpc1.path = api_pth
rpc1.op_name = op_name
rpc1.op_name = op_name_fq
rpc1.op_input_args = input_args
# Skip NACM check for privileged users
......
......@@ -6,7 +6,6 @@ from .libknot.control import KnotCtl, KnotCtlType
from .config import CONFIG
from .helpers import LogHelpers
KNOT = None # type: KnotConfig
JsonNodeT = Union[Dict[str, Any], List[Any], str, int]
debug_knot = LogHelpers.create_module_dbg_logger(__name__)
......@@ -106,13 +105,16 @@ class MXRecord(RRecordBase):
class KnotConfig(KnotCtl):
def __init__(self, sock_path: str):
def __init__(self):
super().__init__()
self.sock_path = sock_path
self.sock_path = ""
self.connected = False
self.socket_lock = Lock()
self.conf_state = KnotConfState.NONE
def set_socket(self, sock_path: str):
self.sock_path = sock_path
def knot_connect(self):
if self.connected:
raise KnotApiError("Knot socket already opened")
......@@ -134,14 +136,7 @@ class KnotConfig(KnotCtl):
self.socket_lock.release()
def flush_socket(self):
self.set_timeout(1)
while True:
try:
self.receive_block()
except Exception as e:
if str(e) == "connection timeout":
debug_knot("socket flushed")
break
pass
# Starts a new transaction for configuration data
def begin(self):
......@@ -322,6 +317,123 @@ class KnotConfig(KnotCtl):
raise KnotInternalError(str(e))
return resp
# Reads zone data and converts them to YANG model compliant data tree
def zone_read(self, domain_name: str) -> JsonNodeT:
if not self.connected:
raise KnotApiError("Knot socket is closed")
try:
self.send_block("zone-read", zone=domain_name)
resp = self.receive_block()
except Exception as e:
raise KnotInternalError(str(e))
resp = resp[domain_name]
zone_template = {
"dns-zones:zone-data": {
"zone": [
{
"name": domain_name,
"class": "IN",
"default-ttl": 3600,
"SOA": {},
"rrset": []
}
]
}
}
zone_out = zone_template["dns-zones:zone-data"]["zone"][0]
soa_out = zone_out["SOA"]
soa = resp[domain_name]["SOA"]
soa_data = soa["data"][0].split()
try:
soa_out["ttl"] = int(soa["ttl"])
soa_out["mname"] = soa_data[0]
soa_out["rname"] = soa_data[1]
soa_out["serial"] = int(soa_data[2])
soa_out["refresh"] = int(soa_data[3])
soa_out["retry"] = int(soa_data[4])
soa_out["expire"] = int(soa_data[5])
soa_out["minimum"] = int(soa_data[6])
except (IndexError, ValueError) as e:
print(str(e))
rrset_out = zone_out["rrset"]
for owner, rrs in resp.items():
# print("rrs={}".format(rrs))
for rr_type, rr in rrs.items():
# print("rr={}".format(rr))
if rr_type not in ("A", "AAAA", "NS", "MX", "TXT", "TLSA", "CNAME"):
continue
ttl = int(rr["ttl"])
rr_data_list = rr["data"]
new_rr_out_rdata_list = []
new_rr_out = {
"owner": owner,
"type": "iana-dns-parameters:" + rr_type,
"ttl": ttl,
"rdata": new_rr_out_rdata_list
}
id_int = 0
for rr_data in rr_data_list:
new_rr_out_rdata_values = {}
new_rr_out_rdata = {
"id": str(id_int),
rr_type: new_rr_out_rdata_values
}
if rr_type in ("A", "AAAA"):
new_rr_out_rdata_values["address"] = rr_data
elif rr_type == "NS":
new_rr_out_rdata_values["nsdname"] = rr_data
elif rr_type == "MX":
rr_data = rr_data.split()
new_rr_out_rdata_values["preference"] = rr_data[0]
new_rr_out_rdata_values["exchange"] = rr_data[1]
elif rr_type == "TXT":
new_rr_out_rdata_values["txt-data"] = rr_data.strip(" \"")
elif rr_type == "TLSA":
cert_usage_enum = {
"0": "PKIX-TA",
"1": "PKIX-EE",
"2": "DANE-TA",
"3": "DANE-EE",
"255": "PrivCert"
}
sel_enum = {
"0": "Cert",
"1": "SPKI",
"255": "PrivSel"
}
match_type_enum = {
"0": "Full",
"1": "SHA2-256",
"2": "SHA2-512",
"255": "PrivMatch"
}
rr_data = rr_data.split()
new_rr_out_rdata_values["certificate-usage"] = cert_usage_enum[rr_data[0]]
new_rr_out_rdata_values["selector"] = sel_enum[rr_data[1]]
new_rr_out_rdata_values["matching-type"] = match_type_enum[rr_data[2]]
new_rr_out_rdata_values["certificate-association-data"] = rr_data[3]
elif rr_type == "CNAME":
new_rr_out_rdata_values["cname"] = rr_data
new_rr_out_rdata_list.append(new_rr_out_rdata)
id_int += 1
rrset_out.append(new_rr_out)
return zone_template
# Connects to Knot control socket and begins a new transaction (config or zone)
def knot_connect(transaction_opts: Optional[JsonNodeT]) -> bool:
......@@ -357,9 +469,4 @@ def knot_disconnect(transaction_opts: Optional[JsonNodeT], failed: bool=False) -
return retval
def knot_global_init():
global KNOT
if KNOT is None:
KNOT = KnotConfig(CONFIG["KNOT"]["SOCKET"])
else:
raise ValueError("Knot API already instantiated")
KNOT = KnotConfig()
......@@ -5,13 +5,13 @@ from enum import Enum
from colorlog import error, info
from typing import List, Set, Optional
from yangson.datamodel import DataModel
from yangson.instance import (
InstanceNode,
NonexistentSchemaNode,
NonexistentInstance,
ArrayValue,
ObjectValue,
InstanceSelector,
InstanceRoute,
MemberName,
EntryIndex,
......@@ -76,7 +76,7 @@ class NacmRule:
class RuleTreeNode:
def __init__(self, isel: InstanceSelector=None, up: "RuleTreeNode"=None):
def __init__(self, isel: "InstanceSelector"=None, up: "RuleTreeNode"=None):
self.isel = isel
self.rule = None # type: NacmRule
self.up = up
......@@ -104,13 +104,13 @@ class NacmRuleList:
class DataRuleTree:
def __init__(self, rule_lists: List[NacmRuleList]):
def __init__(self, dm: DataModel, rule_lists: List[NacmRuleList]):
self.root = [] # type: List[RuleTreeNode]
for rl in rule_lists:
for rule in filter(lambda r: r.type == NacmRuleType.NACM_RULE_DATA, rl.rules):
try:
ii = DataHelpers.parse_ii(rule.type_data.path, PathFormat.XPATH)
ii = dm.parse_instance_id(rule.type_data.path)
except NonexistentSchemaNode as e:
error(epretty(e, __name__))
ii = []
......@@ -161,8 +161,9 @@ class DataRuleTree:
class NacmConfig:
def __init__(self, nacm_ds: "BaseDatastore"):
def __init__(self, nacm_ds: "BaseDatastore", dm: DataModel):
self.nacm_ds = nacm_ds
self.dm = dm
self.enabled = False
self.default_read = Action.PERMIT
self.default_write = Action.PERMIT
......@@ -273,7 +274,7 @@ class NacmConfig:
return
info("Creating personalized rule list for user \"{}\"".format(username))
self._user_nacm_rpc[username] = UserNacm(self, username)
self._user_nacm_rpc[username] = UserNacm(self.dm, self, username)
self.internal_data_lock.release()
......@@ -288,7 +289,7 @@ class NacmConfig:
# Rules for particular user
class UserNacm:
def __init__(self, config: NacmConfig, username: str):
def __init__(self, dm: DataModel, config: NacmConfig, username: str):
self.nacm_enabled = config.enabled
self.default_read = config.default_read
self.default_write = config.default_write
......@@ -299,7 +300,7 @@ class UserNacm:
user_groups_names = list(map(lambda x: x.name, user_groups))
self.rule_lists = list(filter(lambda x: (set(user_groups_names) & set(x.groups)), config.rule_lists))
self.rule_tree = DataRuleTree(self.rule_lists)
self.rule_tree = DataRuleTree(dm, self.rule_lists)
debug_nacm("Rule tree for user \"{}\":\n{}".format(username, self.rule_tree.print_rule_tree()))
def check_data_node_permission(self, root: InstanceNode, ii: InstanceRoute, access: Permission) -> Action:
......
This diff is collapsed.
from enum import Enum
from typing import Dict, List
from colorlog import error, warning as warn, info
from . import knot_api
from .helpers import JsonNodeT
from .knot_api import SOARecord, ARecord, AAAARecord, MXRecord
class KnotZoneCmd(Enum):
SET = 0
UNSET = 1
class KnotOp:
def __init__(self, cmd: KnotZoneCmd, op_input: JsonNodeT):
self.cmd = cmd
self.op_input = op_input
class OpHandlersContainer:
def __init__(self):
self.op_journal = {} # type: Dict[str, List[KnotOp]]
def zone_begin_transaction(self, input_args: JsonNodeT, username: str) -> JsonNodeT:
self.op_journal[username] = []
def zone_commit_transaction(self, input_args: JsonNodeT, username: str) -> JsonNodeT:
try:
usr_op_journal = self.op_journal[username]
except KeyError:
warn("zone_commit_transaction: Nothing to commit")
return
# Connect to Knot socket and start zone transaction
knot_api.KNOT.knot_connect()
knot_api.KNOT.begin_zone()
for knot_op in usr_op_journal:
input_args = knot_op.op_input
domain = input_args["dns-zone-rpcs:zone"]
if knot_op.cmd == KnotZoneCmd.SET:
rr_type = input_args["dns-zone-rpcs:type"][0]
if rr_type == "SOA":
rrdata = input_args["dns-zone-rpcs:SOA"]
rr = SOARecord()
rr.ttl = input_args["dns-zone-rpcs:ttl"]
rr.mname = rrdata["mname"]
rr.rname = rrdata["rname"]
rr.serial = rrdata["serial"]
rr.refresh = rrdata["refresh"]
rr.retry = rrdata["retry"]
rr.expire = rrdata["expire"]
rr.minimum = rrdata["minimum"]
knot_api.KNOT.zone_add_record(domain, rr)
elif rr_type == "A":
rrdata = input_args["dns-zone-rpcs:A"]
rr = ARecord(input_args["dns-zone-rpcs:owner"], input_args["dns-zone-rpcs:ttl"])
rr.address = rrdata["address"]
knot_api.KNOT.zone_add_record(domain, rr)
elif rr_type == "AAAA":
rrdata = input_args["dns-zone-rpcs:AAAA"]
rr = AAAARecord(input_args["dns-zone-rpcs:owner"], input_args["dns-zone-rpcs:ttl"])
rr.address = rrdata["address"]
knot_api.KNOT.zone_add_record(domain, rr)
elif rr_type == "MX":
rrdata = input_args["dns-zone-rpcs:MX"]
rr = MXRecord(input_args["dns-zone-rpcs:owner"], input_args["dns-zone-rpcs:ttl"])
rr.address = rrdata["address"]
knot_api.KNOT.zone_add_record(domain, rr)
elif knot_op.cmd == KnotZoneCmd.UNSET:
pass
knot_api.KNOT.commit()
knot_api.KNOT.knot_disconnect()
del self.op_journal[username]
def zone_abort_transaction(self, input_args: JsonNodeT, username: str) -> JsonNodeT:
try:
del self.op_journal[username]
except KeyError:
warn("zone_abort_transaction: Nothing to abort")
def zone_set(self, input_args: JsonNodeT, username: str) -> JsonNodeT:
try:
usr_op_journal = self.op_journal[username]
except KeyError:
warn("zone_set: Op transaction not started")
return
usr_op_journal.append(KnotOp(KnotZoneCmd.SET, input_args))
def zone_unset(self, input_args: JsonNodeT, username: str) -> JsonNodeT:
try:
usr_op_journal = self.op_journal[username]
except KeyError:
warn("zone_set: Op transaction not started")
return
usr_op_journal.append(KnotOp(KnotZoneCmd.UNSET, input_args))
def sign_op_handler(input_args: JsonNodeT) -> JsonNodeT:
print("input={}".format(input_args))
print("signing...")
ret = {"status": "OK"}
return ret
OP_HANDLERS_IMPL = OpHandlersContainer()
from colorlog import error
from typing import Dict, Any, List, Union
from yangson.datamodel import DataModel
from yangson.instance import InstanceRoute, InstanceNode, EntryKeys, NonexistentInstance
from yangson.instance import InstanceRoute, InstanceNode, EntryKeys, NonexistentInstance, RootNode
from jetconf.knot_api import KnotInternalError
from . import knot_api
from .knot_api import KNOT, KnotInternalError
from .helpers import DataHelpers, JsonNodeT
from .handler_list import StateDataHandlerList
......@@ -20,31 +18,32 @@ class StateNonexistentInstance(NonexistentInstance):
class StateNodeHandlerBase:
def __init__(self, data_model: DataModel):
def __init__(self, data_model: DataModel, schema_path: str):
self.data_model = data_model
self.sch_pth = None
self.schema_node = None
self.member_handlers = {} # type: Dict[str, StateNodeHandlerBase]
self.sch_pth = schema_path
self.schema_node = data_model.get_data_node(self.sch_pth)
class ContainerNodeHandlerBase(StateNodeHandlerBase):
def generate_node(self, node_ii: InstanceRoute, data_root: InstanceNode) -> InstanceNode:
pass
def add_member_handler(self, member: str, handler: "StateNodeHandlerBase"):
self.member_handlers[member] = handler
def update_node(self, node_ii: InstanceRoute, data_root: InstanceNode, with_container: bool) -> InstanceNode:
class ListNodeHandlerBase(StateNodeHandlerBase):
def generate_list(self, node_ii: InstanceRoute, data_root: InstanceNode) -> InstanceNode:
pass
def gen_container(self, ii: InstanceRoute, data: JsonNodeT) -> JsonNodeT:
return DataHelpers.node2doc(ii, data)
def generate_item(self, node_ii: InstanceRoute, data_root: InstanceNode) -> InstanceNode:
pass
class ZoneSigningStateHandler(StateNodeHandlerBase):
class ZoneSigningStateHandler(ContainerNodeHandlerBase):
def __init__(self, data_model: DataModel):
super().__init__(data_model)
self.sch_pth = "/dns-server:dns-server-state/zone/dnssec-signing:dnssec-signing"
self.schema_node = data_model.get_data_node(self.sch_pth)
super().__init__(data_model, "/dns-server:dns-server-state/zone/dnssec-signing:dnssec-signing")
def update_node(self, node_ii: InstanceRoute, data_root: InstanceNode, with_container: bool) -> InstanceNode:
def generate_node(self, node_ii: InstanceRoute, data_root: InstanceNode) -> InstanceNode:
print("zone_state_signing_handler, ii = {}".format(node_ii))
zone_name = node_ii[2].keys.get("domain")
domain_name = node_ii[2].keys.get(("domain", None)) + "."
zone_signing = {
"enabled": True,
......@@ -57,91 +56,71 @@ class ZoneSigningStateHandler(StateNodeHandlerBase):
"flags": "zone-key secure-entry-point",
"created": "2015-06-18T18:02:45+02:00",
"publish": "2015-06-18T19:00:00+02:00",
# "activate": str(datetime.now()),
"retire": "2015-07-18T18:02:45+02:00",
"remove": "2015-07-25T00:00:00+02:00"
}
]
}
if with_container:
retval = self.gen_container(node_ii[0:4], zone_signing)
else:
retval = zone_signing
retval = zone_signing
return retval
class ZoneStateHandler(StateNodeHandlerBase):
class ZoneStateHandler(ListNodeHandlerBase):
def __init__(self, data_model: DataModel):
super().__init__(data_model)
self.sch_pth = "/dns-server:dns-server-state/zone"
self.schema_node = data_model.get_data_node(self.sch_pth)
super().__init__(data_model, "/dns-server:dns-server-state/zone")
def update_node(self, node_ii: InstanceRoute, data_root: InstanceNode, with_container: bool) -> InstanceNode:
node_ii_str = sch_pth = "".join([str(seg) for seg in node_ii])
print("zone_state_handler, ii = {}".format(node_ii_str))
def generate_list(self, node_ii: InstanceRoute, data_root: InstanceNode) -> InstanceNode:
zones_list = []
# Request status of specific zone
if len(node_ii) > 2:
zone_name = node_ii[2].keys.get("domain") + "."
KNOT.knot_connect()
# Request status of all zones
resp = KNOT.zone_status()
KNOT.knot_disconnect()
for domain_name, status_data in resp.items():
try:
resp = knot_api.KNOT.zone_status(zone_name)
resp = resp.get(zone_name)
except KnotInternalError:
raise StateNonexistentInstance(node_ii, "No such zone")
zone_obj = {
"domain": domain_name.rstrip("."),
"class": "IN",
"serial": int(status_data.get("serial")),
"server-role": status_data.get("type")
}
zone_obj = {
"domain": zone_name,
"class": "IN",
"serial": int(resp.get("serial")),
"server-role": resp.get("type")
}
zones_list.append(zone_obj)
except ValueError:
error("Error parsing Knot zone status data")
if with_container:
retval = self.gen_container(node_ii[0:3], zone_obj)
else:
retval = zone_obj
return zones_list
for m, h in self.member_handlers.items():
zone_obj[m] = h.update_node(node_ii, data_root, False)
def generate_item(self, node_ii: InstanceRoute, data_root: InstanceNode) -> InstanceNode:
zone_obj = {}
# Request status of all zones
else:
resp = knot_api.KNOT.zone_status()
zones_list = []
for zone_name, zone_status in resp.items():
try:
zone_name = zone_name.rstrip(".")
zone_obj = {
"domain": zone_name,
"class": "IN",
"serial": int(zone_status.get("serial")),
"server-role": zone_status.get("type")
}
for m, h in self.member_handlers.items():
zone_obj[m] = h.update_node(node_ii + [EntryKeys({"domain": zone_name})], data_root, False)
zones_list.append(zone_obj)
except ValueError:
error("Error parsing Knot zone status data")
if with_container:
retval = self.gen_container(node_ii[0:2], zones_list)
else:
retval = zones_list
# Request status of specific zone
KNOT.knot_connect()
domain_desired = node_ii[2].keys.get(("domain", None))
resp = KNOT.zone_status(domain_desired)
KNOT.knot_disconnect()
return retval
domain_name, status_data = tuple(resp.items())[0]
try:
zone_obj = {
"domain": domain_name.rstrip("."),
"class": "IN",
"serial": int(status_data.get("serial")),
"server-role": status_data.get("type")
}
except ValueError:
error("Error parsing Knot zone status data")
return zone_obj
# Create handler hierarchy
# Instantiate state data handlers
def create_zone_state_handlers(handler_list: "StateDataHandlerList", dm: DataModel):
# zssh = ZoneSigningStateHandler(dm)
# handler_list.register_handler(zssh)
zsh = ZoneStateHandler(dm)
# zsh.add_member_handler("dnssec-signing:dnssec-signing", zssh)
handler_list.register_handler(zsh)
\ No newline at end of file
......@@ -3,8 +3,8 @@
CLIENT_CERT="/home/pspirek/sslclient/pavel_curl.pem"