blob: 03d190f2ab728ed321178aed097424f2a0218e3b [file] [log] [blame]
Radek Krejcia1339602017-11-02 13:52:38 +01001"""
2NETCONF data helper functions
3File: data.py
4Author: Radek Krejci <rkrejci@cesnet.cz>
5"""
6
7import json
8import os
9
10import libyang as ly
11import netconf2 as nc
12
Radek Krejci4d3896c2018-01-08 17:10:43 +010013def infoBuiltInType(base):
14 return {
Radek Krejci6e772b22018-01-25 13:28:57 +010015 - 1 : 'error',
16 0 : 'derived',
17 1 : 'binary',
18 2 : 'bits',
19 3 : 'boolean',
20 4 : 'decimal64',
21 5 : 'empty',
22 6 : 'enumeration',
23 7 : 'identityref',
24 8 : 'instance-identifier',
25 9 : 'leafref',
Radek Krejci4d3896c2018-01-08 17:10:43 +010026 10: 'string',
27 11: 'union',
28 12: 'int8',
29 13: 'uint8',
30 14: 'int16',
31 15: 'uint16',
32 16: 'int32',
33 17: 'uint32',
34 18: 'int64',
35 19: 'uint64',
36 }[base]
37
Radek Krejci6e772b22018-01-25 13:28:57 +010038
39def schemaInfoType(schema, info):
40 info["datatype"] = schema.type().der().name()
41 info["datatypebase"] = infoBuiltInType(schema.type().base())
42
43
Radek Krejcid0ce4cf2018-02-09 14:44:34 +010044def typeValues(type, result):
45 while type.der():
46 if type.base() == 2:
47 # bits
48 if type.info().bits().count():
49 for bit in type.info().bits().bit():
50 result.append(bit.name())
51 elif type.base() == 6:
52 # enumeration
53 if type.info().enums().count():
54 for enm in type.info().enums().enm():
55 result.append(enm.name())
56 else:
57 return result
58 type = type.der().type()
59
60 return result
61
Radek Krejci6e772b22018-01-25 13:28:57 +010062def schemaInfoNode(schema):
63 info = {}
64
65 info["type"] = schema.nodetype()
66 info["module"] = schema.module().name()
67 info["name"] = schema.name()
68 info["dsc"] = schema.dsc()
69 info["config"] = True if schema.flags() & ly.LYS_CONFIG_W else False
70 if info["type"] == 1:
71 info["presence"] = schema.subtype().presence()
72 info["path"] = schema.path()
73
74 if info["type"] == ly.LYS_LEAF:
75 schemaInfoType(schema.subtype(), info)
76 info["key"] = False if schema.subtype().is_key() == -1 else True
77 dflt = schema.subtype().dflt()
78 if dflt:
79 info["default"] = dflt
80 else:
81 tpdf = schema.subtype().type().der()
82 while tpdf and not tpdf.dflt():
83 tpdf = tpdf.type().der()
84 if tpdf:
85 info["default"] = tpdf.dflt()
86 elif info["type"] == ly.LYS_LEAFLIST:
87 schemaInfoType(schema.subtype(), info)
88 elif info["type"] == ly.LYS_LIST:
89 info["keys"] = []
90 for key in schema.subtype().keys():
91 info["keys"].append(key.name())
92
93 return info
94
Radek Krejci4d3896c2018-01-08 17:10:43 +010095
Radek Krejci27134982017-11-10 15:42:00 +010096def dataInfoNode(node, parent=None, recursion=False):
Radek Krejcia1339602017-11-02 13:52:38 +010097 schema = node.schema()
98 casted = node.subtype()
99
100 if node.dflt():
101 return None
102
Radek Krejci27134982017-11-10 15:42:00 +0100103 if parent and schema.nodetype() == ly.LYS_LEAFLIST:
104 # find previous instance and just add value
105 for child in parent["children"]:
106 if child["info"]["name"] == schema.name():
107 child["value"].append(casted.value_str())
108 if not node.next():
109 child["last"] = True
110 return None
111
Radek Krejci6e772b22018-01-25 13:28:57 +0100112 info = schemaInfoNode(schema);
Radek Krejcia1339602017-11-02 13:52:38 +0100113
114 result = {}
Radek Krejci27134982017-11-10 15:42:00 +0100115 if info["type"] == ly.LYS_LEAF:
Radek Krejcia1339602017-11-02 13:52:38 +0100116 result["value"] = casted.value_str()
Radek Krejci27134982017-11-10 15:42:00 +0100117 elif info["type"] == ly.LYS_LEAFLIST:
118 result["value"] = [casted.value_str()]
Radek Krejcia1339602017-11-02 13:52:38 +0100119 elif recursion:
120 result["children"] = []
121 if node.child():
122 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100123 childNode = dataInfoNode(child, result, True)
Radek Krejcia1339602017-11-02 13:52:38 +0100124 if not childNode:
125 continue
126 if not child.next():
127 childNode["last"] = True
128 result["children"].append(childNode)
Radek Krejcid82dfe22018-01-05 13:20:31 +0100129
130 if info["type"] == ly.LYS_LIST:
131 result["keys"] = []
132 index = 0
133 for key in schema.subtype().keys():
134 if len(result["children"]) <= index:
135 break
136 if key.subtype().name() == result["children"][index]["info"]["name"]:
137 result["keys"].append(result["children"][index]["value"])
Radek Krejcid82dfe22018-01-05 13:20:31 +0100138 index = index + 1
Radek Krejcia1339602017-11-02 13:52:38 +0100139 result["info"] = info
140 result["path"] = node.path()
141
142 return result
143
144def dataInfoSubtree(data, path, recursion=False):
145 try:
146 node = data.find_path(path).data()[0]
147 except:
148 return(json.dumps({'success': False, 'error-msg': 'Invalid data path.'}))
149
150 result = dataInfoNode(node)
151 if not result:
152 return(json.dumps({'success': False, 'error-msg': 'Path refers to a default node.'}))
153
154 result["children"] = []
155 if node.child():
156 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100157 childNode = dataInfoNode(child, result, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100158 if not childNode:
159 continue
160 if not child.next():
161 childNode["last"] = True
162 result["children"].append(childNode)
163
164 return(json.dumps({'success': True, 'data': result}))
165
166
167def dataInfoRoots(data, recursion=False):
Radek Krejci27134982017-11-10 15:42:00 +0100168 top = {}
169 top["children"] = []
Radek Krejcia1339602017-11-02 13:52:38 +0100170 for root in data.tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100171 rootNode = dataInfoNode(root, top, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100172 if not rootNode:
173 continue
174 if not root.next():
175 rootNode["last"] = True
Radek Krejci27134982017-11-10 15:42:00 +0100176 top["children"].append(rootNode)
Radek Krejcia1339602017-11-02 13:52:38 +0100177
Radek Krejci4d3896c2018-01-08 17:10:43 +0100178 return(json.dumps({'success': True, 'data': top["children"]}))