Commit 79986b91 authored by Pavel Spirek's avatar Pavel Spirek

Basic read functionality working

parent 9b68a4af
import colorlog
import getopt
import logging
import sys
from importlib import import_module
from . import rest_server
def main():
opts, args = (None, None)
colorlog.basicConfig(
format="%(asctime)s %(log_color)s%(levelname)-8s%(reset)s %(message)s",
level=logging.INFO,
stream=sys.stdout
)
test_module = None
try:
opts, args = getopt.getopt(sys.argv[1:], "t:")
except getopt.GetoptError:
print("Invalid argument detected. Possibles are: -t (test module)")
exit()
for opt, arg in opts:
if opt == '-t':
test_module = arg
if test_module is not None:
try:
tm = import_module("." + test_module, "jetconf")
tm.test()
except ImportError as e:
print(e.msg)
except AttributeError:
print("Module \"{}\" has no test() function".format(test_module))
else:
rest_server.run()
if __name__ == "__main__":
main()
-----BEGIN CERTIFICATE-----
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
dAjt3iWQ9yND28ASZ+yRXwZn6ZMmbg==
-----END CERTIFICATE-----
......@@ -16,8 +16,8 @@ from yangson.datamodel import InstanceIdentifier
class Rpc:
def __init__(self):
self.username = None
self.path = None # type: str
self.username = None # type: str
self.path = None # type: str
class BaseDatastore:
......@@ -65,6 +65,23 @@ class BaseDatastore:
return n
def get_node_rpc2(self, rpc: Rpc) -> Instance:
n = None
ii = self.dm.parse_resource_id(rpc.path)
self.lock_data(rpc.username)
n = self.data.goto(ii)
self.unlock_data()
if self.nacm:
nrpc = NacmRpc(self.nacm, self, None, rpc.username)
if nrpc.check_data_node(n, Permission.NACM_ACCESS_READ) == Action.DENY:
return None
else:
# Prun subtree data
n = nrpc.check_data_read(n)
return n
def lock_data(self, username: str = None):
ret = self._data_lock.acquire(blocking=False)
if ret:
......@@ -91,9 +108,6 @@ class JsonDatastore(BaseDatastore):
def test():
colorlog.basicConfig(format="%(asctime)s %(log_color)s%(levelname)-8s%(reset)s %(message)s", level=logging.INFO,
stream=sys.stdout)
data = JsonDatastore("./data", "./data/yang-library-data.json")
data.load_json("jetconf/example-data.json")
......
-----BEGIN CERTIFICATE-----
MIICeDCCAWACAQowDQYJKoZIhvcNAQEFBQAwajELMAkGA1UEBhMCQ1oxCzAJBgNV
BAcMAkNCMRgwFgYDVQQKDA9BdXRvcml0YSBzLnIuby4xFTATBgNVBAMMDGF1dG9y
aXRhLmNvbTEdMBsGCSqGSIb3DQEJARYOYUBhdXRvcml0YS5jb20wHhcNMTYwMTI5
MTAyNTMwWhcNMTYwMjI4MTAyNTMwWjAeMRwwGgYJKoZIhvcNAQkBFg1sb2p6YUBt
YWlsLmN6MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsaIBTzwjoHMGGiiK
uxoGwUJCBsAIMX5BUEBCIoX7A3Yuit3TKWSVuTZrikPEEOXGCfJw3odQAKlK7QU7
u732iP0+VIRMxhMh8BGS7p76QgDOGe+gBYRvuJBPgYdHqWu7kCuL/FrKUeu/Ui4Z
/7QP6AbWwT2aSswlJwZWRYhsvwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQCLaMhp
4pbMpYUahrFupPecEgmrFiSDZOtXA113wiLk+8u1u2Yo0mvpyDMRa1PWaSEh4kAL
WJ8uKr6FLrmLQc+TJz7kpKxw1fOmB68t7as+gCjJKrQmT1Cw8D9bWZIzr7TLqquw
B8dBrDBW25xbfE8IJOpJ3kNATpiIpjt3Oa5xiD6uJyC3adL/VrBKSmkyAZXi9sll
5vm329/BKOgasmNdTdpqA3OAfnf5CrV0rrp57ygEf5vYW+e5p+6Ee+mMWpZYAhXN
Pxe5i8QPtpD+mHLBJnE8+SWGFYn+j9Jyq/8qUrKPejoVDPUp1FrsKj7IiQ+pKYL7
3st+hPwePhZPuEhn
MIICZjCCAU4CAQ0wDQYJKoZIhvcNAQEFBQAwSzELMAkGA1UEBhMCQ1oxEzARBgNV
BAoMCkV4YW1wbGUgQ0ExEDAOBgNVBAsMB2V4Y2EuY3oxFTATBgNVBAMMDG1haWxA
ZXhjYS5jejAeFw0xNjAzMDgxNTIzMTNaFw0xNjA0MDcxNTIzMTNaMCsxCzAJBgNV
BAYTAkNaMRwwGgYJKoZIhvcNAQkBFg1sb2p6YUBtYWlsLmN6MIGfMA0GCSqGSIb3
DQEBAQUAA4GNADCBiQKBgQDZsaIBTzwjoHMGGiiKuxoGwUJCBsAIMX5BUEBCIoX7
A3Yuit3TKWSVuTZrikPEEOXGCfJw3odQAKlK7QU7u732iP0+VIRMxhMh8BGS7p76
QgDOGe+gBYRvuJBPgYdHqWu7kCuL/FrKUeu/Ui4Z/7QP6AbWwT2aSswlJwZWRYhs
vwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBq7cnlwqSNza5kL4O2rLevwnF3BVfi
B4UlDJePne+c8ymGLtMHa1xevHpLVdCJOkF18zaBwxaVzQGlILu8yqtBZjbXnOV5
fNsajzo6FyifKnd6OB/ckt2wCi4+QYdttJc7YNn9Dx4PHoRLwCzshIjOY5p5xIzI
9pCVUgc1bNO5QwgmJpoeumjN4ml2v+JDiYu0cNXTJP9tyX22YAxXkYRDkfnGQQb/
wo0Jt4KpPtRg8NSHYswumWlWDJuHKqauck6RjKDSGV+ifv6COoUbT83eiC+46PTy
iJBhiz0zScDzMyOjDhv/cyxnfO/3+Z7BOrmWz9faGRlLnc4OdJ+7TupX
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDZsaIBTzwjoHMGGiiKuxoGwUJCBsAIMX5BUEBCIoX7A3Yuit3T
......
......@@ -276,9 +276,6 @@ class NacmRpc:
def test():
colorlog.basicConfig(format="%(asctime)s %(log_color)s%(levelname)-8s%(reset)s %(message)s", level=logging.INFO,
stream=sys.stdout)
nacm_data = JsonDatastore("./data", "./data/yang-library-data.json")
nacm_data.load_json("jetconf/example-data-nacm.json")
......
......@@ -12,7 +12,8 @@ from typing import List, Tuple, Dict, Any
import yaml
import copy
from .nacm import NacmConfig
from .data import JsonDatastore
from .data import JsonDatastore, Rpc
from yangson.schema import NonexistentSchemaNode
from h2.connection import H2Connection
from h2.events import DataReceived, RequestReceived, RemoteSettingsChanged
......@@ -84,8 +85,9 @@ class H2Protocol(asyncio.Protocol):
def handle_get(self, headers: OrderedDict, stream_id: int):
response = None
parsed_url = yang_json_path.URLPath(headers[":path"])
if parsed_url.path_equals(CONFIG["RESTCONF_NACM_API_ROOT"]):
print(headers[":path"])
if headers[":path"] == CONFIG["RESTCONF_NACM_API_ROOT"]:
# Top level api resource (appendix D.1.1)
response = ("{\n"
" \"ietf-restconf:restconf\": {\n"
......@@ -102,29 +104,26 @@ class H2Protocol(asyncio.Protocol):
self.conn.send_headers(stream_id, response_headers)
self.conn.send_data(stream_id, response.encode(), end_stream=True)
elif parsed_url.path_contains(os.path.join(CONFIG["RESTCONF_NACM_API_ROOT"], "data")):
elif headers[":path"].startswith(os.path.join(CONFIG["RESTCONF_NACM_API_ROOT"], "data")):
# NACM api request
info(("nacm_api_get: " + headers[":path"]))
username = CertHelpers.get_field(self.client_cert, "emailAddress")
parsed_url.path_segments = parsed_url.path_segments[2:] # TODO: Hack
print(parsed_url.path_segments)
pth = headers[":path"][len(os.path.join(CONFIG["RESTCONF_NACM_API_ROOT"], "data")):]
nacm_config.lock_data(username)
_node = copy.deepcopy(nacm_config.json.select_data_node(parsed_url))
nacm_config.unlock_data()
rpc1 = Rpc()
rpc1.username = username
rpc1.path = pth
if not _node:
warn("Node not found")
try:
n = ex_datastore.nacm.nacm_ds.get_node_rpc2(rpc1)
response = json.dumps(n.value, indent=4) + "\n"
http_status = "200"
except NonexistentSchemaNode:
warn("Node not found: " + pth)
response = "Not found"
http_status = "404"
else:
_doc = nacm.JsonDoc(_node[-1], parsed_url)
_rpc = nacm.NacmRpc(nacm_config, None, username)
_rpc.check_data_read(_node[-1], _doc)
response = json.dumps(_doc.root)
http_status = "200"
response_headers = (
(':status', http_status),
......@@ -132,16 +131,61 @@ class H2Protocol(asyncio.Protocol):
('content-length', len(response)),
('server', CONFIG["SERVER_NAME"]),
)
self.conn.send_headers(stream_id, response_headers)
self.conn.send_data(stream_id, response.encode(), end_stream=True)
elif headers[":path"] == CONFIG["RESTCONF_API_ROOT"]:
# Top level api resource (appendix D.1.1)
response = ("{\n"
" \"ietf-restconf:restconf\": {\n"
" \"data\" : [ null ],\n"
" \"operations\" : [ null ]\n"
" }\n"
"}")
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.encode(), end_stream=True)
elif parsed_url.path_contains(CONFIG["RESTCONF_API_ROOT"]):
elif headers[":path"].startswith(os.path.join(CONFIG["RESTCONF_API_ROOT"], "data")):
# api request
pass
info(("api_get: " + headers[":path"]))
username = CertHelpers.get_field(self.client_cert, "emailAddress")
pth = headers[":path"][len(os.path.join(CONFIG["RESTCONF_API_ROOT"], "data")):]
rpc1 = Rpc()
rpc1.username = username
rpc1.path = pth
try:
n = ex_datastore.get_node_rpc2(rpc1)
response = json.dumps(n.value, indent=4) + "\n"
http_status = "200"
except NonexistentSchemaNode:
warn("Node not found: " + pth)
response = "Not found"
http_status = "404"
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.encode(), end_stream=True)
else:
# Ordinary file on filesystem
file_path = CONFIG["DOC_ROOT"] + "/" + parsed_url.path_str.replace("..", "").replace("&", "")
file_path = os.path.join(CONFIG["DOC_ROOT"], headers[":path"][1:].replace("..", "").replace("&", ""))
if os.path.isdir(file_path):
file_path = os.path.join(file_path, CONFIG["DOC_DEFAULT_NAME"])
......@@ -211,9 +255,6 @@ class H2Protocol(asyncio.Protocol):
def run():
colorlog.basicConfig(format="%(asctime)s %(log_color)s%(levelname)-8s%(reset)s %(message)s", level=logging.INFO,
stream=sys.stdout)
try:
with open("jetconf/config.yaml") as conf_fd:
conf_yaml = yaml.load(conf_fd)
......
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