Code cleanup and other improvements

parent d4f9de63
......@@ -57,36 +57,30 @@ class BaseDatastore:
def get_data_root(self) -> Instance:
return self._data
# Parse Instance Identifier from string
def parse_ii(self, path: str, path_format: PathFormat) -> InstanceIdentifier:
if path_format == PathFormat.URL:
ii = self._dm.parse_resource_id(path)
else:
ii = self._dm.parse_instance_id(path)
return ii
# Just get the node, do not evaluate NACM (for testing purposes)
def get_node(self, ii: InstanceIdentifier) -> Instance:
# self.lock_data("get_node")
n = self._data.goto(ii)
# self.unlock_data()
return n
# Just get the node, do not evaluate NACM (for testing purposes)
def get_node_path(self, path: str, path_format: PathFormat) -> Instance:
n = None
if path_format == PathFormat.URL:
ii = self._dm.parse_resource_id(path)
else:
ii = self._dm.parse_instance_id(path)
# self.lock_data("get_node_path")
ii = self.parse_ii(path, path_format)
n = self._data.goto(ii)
# self.unlock_data()
return n
# Get data node, evaluate NACM if possible
def get_node_rpc(self, rpc: Rpc) -> Instance:
n = None
if rpc.path_format == PathFormat.URL:
ii = self._dm.parse_resource_id(rpc.path)
else:
ii = self._dm.parse_instance_id(rpc.path)
# self.lock_data(rpc.username)
ii = self.parse_ii(rpc.path, rpc.path_format)
n = self._data.goto(ii)
# self.unlock_data()
if self.nacm:
nrpc = NacmRpc(self.nacm, self, rpc.username)
......@@ -98,9 +92,24 @@ class BaseDatastore:
return n
def put_node_rpc(self, rpc: Rpc, value: Any):
ii = self.parse_ii(rpc.path, rpc.path_format)
n = self._data.goto(ii)
# if self.nacm:
# nrpc = NacmRpc(self.nacm, self, rpc.username)
# if nrpc.check_data_node_path(ii, Permission.NACM_ACCESS_READ) == Action.DENY:
# raise NacmForbiddenError()
# else:
# # Prun subtree data
# n = nrpc.check_data_read_path(ii)
new_n = n.update(value)
self._data = new_n.top()
# Locks datastore data
def lock_data(self, username: str = None):
ret = self._data_lock.acquire(blocking=False)
def lock_data(self, username: str = None, blocking: bool=True):
ret = self._data_lock.acquire(blocking=blocking, timeout=1)
if ret:
self._lock_username = username or "(unknown)"
info("Acquired lock in datastore \"{}\" for user \"{}\"".format(self.name, username))
......@@ -142,16 +151,6 @@ class JsonDatastore(BaseDatastore):
def test():
"""
with open("./data/yang-library-data.json") as ylfile:
yl = ylfile.read()
_dm = DataModel.from_yang_library(yl, "./data")
with open("jetconf/example-data.json", "rt") as fp:
_root = _dm.from_raw(json.load(fp))
print(hash(_root.member("dns-server:dns-server").value))
"""
# exit()
data = JsonDatastore("./data", "./data/yang-library-data.json")
data.load("jetconf/example-data.json")
......@@ -160,9 +159,13 @@ def test():
rpc.path = "/dns-server:dns-server/zones/zone[domain='example.com']/query-module"
rpc.path_format = PathFormat.XPATH
info("Reading: " + rpc.path)
n = data.get_node_rpc(rpc)
info("Result =")
print(n.value)
print(hash(data.get_data_root().member("dns-server:dns-server").value))
if json.loads(json.dumps(n.value)) == [{'name': 'test1', 'type': 'knot-dns:synth-record'}, {'name': 'test2', 'type': 'knot-dns:synth-record'}]:
info("OK")
else:
warn("FAILED")
from .nacm import NacmConfig, NacmRpc, Permission, Action
This diff is collapsed.
......@@ -30,6 +30,7 @@ CONFIG = {
# NACM_ADMINS = []
class CertHelpers:
@staticmethod
def get_field(cert: Dict[str, Any], key: str) -> str:
......@@ -135,9 +136,14 @@ class H2Protocol(asyncio.Protocol):
rpc1.path = pth
try:
ex_datastore.nacm.nacm_ds.lock_data(username)
n = ex_datastore.nacm.nacm_ds.get_node_rpc(rpc1)
response = json.dumps(n.value, indent=4) + "\n"
response = json.dumps(n.value, indent=4)
http_status = "200"
except DataLockError as e:
warn(e.msg)
response = "Internal Server Error"
http_status = "500"
except NonexistentSchemaNode:
warn("NonexistentSchemaNode: " + pth)
response = "NonexistentSchemaNode"
......@@ -146,7 +152,10 @@ class H2Protocol(asyncio.Protocol):
warn("NonexistentInstance: " + pth)
response = "NonexistentInstance"
http_status = "404"
finally:
ex_datastore.nacm.nacm_ds.unlock_data()
response += "\n"
response_headers = (
(':status', http_status),
('content-type', 'application/yang.api+json'),
......@@ -172,7 +181,7 @@ class H2Protocol(asyncio.Protocol):
try:
ex_datastore.lock_data(username)
n = ex_datastore.get_node_rpc(rpc1)
response = json.dumps(n.value, indent=4) + "\n"
response = json.dumps(n.value, indent=4)
http_status = "200"
except DataLockError as e:
warn(e.msg)
......@@ -193,6 +202,7 @@ class H2Protocol(asyncio.Protocol):
finally:
ex_datastore.unlock_data()
response += "\n"
response_headers = (
(':status', http_status),
('content-type', 'application/yang.api+json'),
......@@ -251,28 +261,60 @@ class H2Protocol(asyncio.Protocol):
print("put")
def handle_post(self, headers: OrderedDict, data: bytes, stream_id: int):
print("post")
return
parsed_url = yang_json_path.URLPath(headers[":path"])
print(json.dumps({"query": parsed_url.query_table, "path": parsed_url.path_list}, indent=4))
print("prijato: " + data.decode("utf-8"))
print(json.dumps({"headers": headers}, indent=4))
response = "Jmenujes se {} a tvuj e-mail je {}\n".format(
CertHelpers.get_field(self.client_cert, "organizationName"),
CertHelpers.get_field(self.client_cert, "emailAddress")
).encode()
response_headers = (
(':status', '200'),
('content-type', 'application/yang.api+json'),
('content-length', len(response)),
('server', CONFIG["SERVER_NAME"]),
)
self.conn.send_headers(stream_id, response_headers)
self.conn.send_data(stream_id, response, end_stream=True)
data_str = data.decode("utf-8")
info("prijato: " + data_str)
if headers[":path"].startswith(os.path.join(CONFIG["RESTCONF_NACM_API_ROOT"], "data")):
info(("nacm_api_post: " + headers[":path"]))
username = CertHelpers.get_field(self.client_cert, "emailAddress")
pth = headers[":path"][len(os.path.join(CONFIG["RESTCONF_NACM_API_ROOT"], "data")):]
rpc1 = Rpc()
rpc1.username = username
rpc1.path = pth
try:
ex_datastore.nacm.nacm_ds.lock_data(username)
ex_datastore.nacm.nacm_ds.put_node_rpc(rpc1, json.loads(data_str))
response = "Done\n"
http_status = "200"
except DataLockError as e:
warn(e.msg)
response = "Internal Server Error"
http_status = "500"
except NacmForbiddenError as e:
warn(e.msg)
response = "Forbidden"
http_status = "403"
except NonexistentSchemaNode:
warn("NonexistentSchemaNode: " + pth)
response = "NonexistentSchemaNode"
http_status = "404"
except NonexistentInstance:
warn("NonexistentInstance: " + pth)
response = "NonexistentInstance"
http_status = "404"
finally:
ex_datastore.nacm.nacm_ds.unlock_data()
ex_datastore.nacm.update(ex_datastore.nacm.nacm_ds.get_data_root().member("ietf-netconf-acm:nacm"))
response += "\n"
response = response.encode()
response_headers = (
(':status', http_status),
('content-type', 'application/yang.api+json'),
('content-length', len(response)),
('server', CONFIG["SERVER_NAME"]),
)
self.conn.send_headers(stream_id, response_headers)
self.conn.send_data(stream_id, response, end_stream=True)
else:
# Unknown POST URL
pass
def run():
......
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