blob: 05237e33aa2b8df9b8c827a164eab9c094815e5b [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
Radek Krejci0f793fe2018-02-14 08:33:45 +010010import yang
Radek Krejcia1339602017-11-02 13:52:38 +010011import 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()
Radek Krejciad45e572018-02-21 10:54:54 +010066 if schema.module().rev_size():
67 info["module"] = schema.module().name() + '@' + schema.module().rev().date()
68 else:
69 info["module"] = schema.module().name()
Radek Krejci6e772b22018-01-25 13:28:57 +010070 info["name"] = schema.name()
71 info["dsc"] = schema.dsc()
Radek Krejci0f793fe2018-02-14 08:33:45 +010072 info["config"] = True if schema.flags() & yang.LYS_CONFIG_W else False
Radek Krejci6e772b22018-01-25 13:28:57 +010073 if info["type"] == 1:
74 info["presence"] = schema.subtype().presence()
75 info["path"] = schema.path()
76
Radek Krejci0f793fe2018-02-14 08:33:45 +010077 if info["type"] == yang.LYS_LEAF:
Radek Krejci6e772b22018-01-25 13:28:57 +010078 schemaInfoType(schema.subtype(), info)
79 info["key"] = False if schema.subtype().is_key() == -1 else True
80 dflt = schema.subtype().dflt()
81 if dflt:
82 info["default"] = dflt
83 else:
84 tpdf = schema.subtype().type().der()
85 while tpdf and not tpdf.dflt():
86 tpdf = tpdf.type().der()
87 if tpdf:
88 info["default"] = tpdf.dflt()
Radek Krejci0f793fe2018-02-14 08:33:45 +010089 elif info["type"] == yang.LYS_LEAFLIST:
Radek Krejci6e772b22018-01-25 13:28:57 +010090 schemaInfoType(schema.subtype(), info)
Radek Krejci010475d2018-03-08 13:14:19 +010091 if schema.flags() & yang.LYS_USERORDERED:
92 info["ordered"] = True;
Radek Krejci0f793fe2018-02-14 08:33:45 +010093 elif info["type"] == yang.LYS_LIST:
Radek Krejci010475d2018-03-08 13:14:19 +010094 if schema.flags() & yang.LYS_USERORDERED:
95 info["ordered"] = True;
Radek Krejci6e772b22018-01-25 13:28:57 +010096 info["keys"] = []
97 for key in schema.subtype().keys():
98 info["keys"].append(key.name())
99
100 return info
101
Radek Krejci4d3896c2018-01-08 17:10:43 +0100102
Radek Krejci30ce1592018-03-01 14:44:14 +0100103def _sortChildren(node):
104 sorted = []
105 for index, item in enumerate(node["children"]):
106 sorted.append(item)
107 if item["info"]["type"] == yang.LYS_LIST:
108 removed = 0
Radek Krejci010475d2018-03-08 13:14:19 +0100109 if "ordered" in item["info"]:
110 item["order"] = removed
Radek Krejci30ce1592018-03-01 14:44:14 +0100111 for i, instance in enumerate(node["children"][index + 1:]):
112 if item["info"]["name"] == instance["info"]["name"] and item["info"]["module"] == instance["info"]["module"]:
113 sorted.append(node["children"].pop(index + 1 + i - removed))
114 removed += 1;
Radek Krejci010475d2018-03-08 13:14:19 +0100115 if "ordered" in item["info"]:
116 instance["order"] = removed
Radek Krejci30ce1592018-03-01 14:44:14 +0100117 if item["info"]["type"] == yang.LYS_LEAFLIST:
118 lastLeafList = len(sorted) - 1
119 item["first"] = True
120 removed = 0
Radek Krejci010475d2018-03-08 13:14:19 +0100121 if "ordered" in item["info"]:
122 item["order"] = removed
Radek Krejci30ce1592018-03-01 14:44:14 +0100123 for i, instance in enumerate(node["children"][index + 1:]):
124 if item["info"]["name"] == instance["info"]["name"] and item["info"]["module"] == instance["info"]["module"]:
125 instance["first"] = False
126 sorted.append(node["children"].pop(index + 1 + i - removed))
127 removed += 1;
Radek Krejci010475d2018-03-08 13:14:19 +0100128 if "ordered" in item["info"]:
129 instance["order"] = removed
Radek Krejci30ce1592018-03-01 14:44:14 +0100130 node["children"] = sorted
131 last = node["children"][len(node["children"]) - 1]
132 if last["info"]["type"] == yang.LYS_LEAFLIST:
133 node["children"][lastLeafList]["last"] = True
134 for item in node["children"][lastLeafList + 1:]:
135 item["lastLeafList"] = True;
136 else:
137 last["last"] = True
138
139
Radek Krejci27134982017-11-10 15:42:00 +0100140def dataInfoNode(node, parent=None, recursion=False):
Radek Krejcia1339602017-11-02 13:52:38 +0100141 schema = node.schema()
142 casted = node.subtype()
143
144 if node.dflt():
145 return None
146
Radek Krejci6e772b22018-01-25 13:28:57 +0100147 info = schemaInfoNode(schema);
Radek Krejcia1339602017-11-02 13:52:38 +0100148
149 result = {}
Radek Krejci30ce1592018-03-01 14:44:14 +0100150 if info["type"] == yang.LYS_LEAF or info["type"] == yang.LYS_LEAFLIST:
Radek Krejcia1339602017-11-02 13:52:38 +0100151 result["value"] = casted.value_str()
152 elif recursion:
153 result["children"] = []
154 if node.child():
155 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100156 childNode = dataInfoNode(child, result, True)
Radek Krejcia1339602017-11-02 13:52:38 +0100157 if not childNode:
158 continue
Radek Krejcia1339602017-11-02 13:52:38 +0100159 result["children"].append(childNode)
Radek Krejci30ce1592018-03-01 14:44:14 +0100160 # sort list instances
161 _sortChildren(result)
Radek Krejci0f793fe2018-02-14 08:33:45 +0100162 if info["type"] == yang.LYS_LIST:
Radek Krejcid82dfe22018-01-05 13:20:31 +0100163 result["keys"] = []
164 index = 0
165 for key in schema.subtype().keys():
166 if len(result["children"]) <= index:
167 break
168 if key.subtype().name() == result["children"][index]["info"]["name"]:
169 result["keys"].append(result["children"][index]["value"])
Radek Krejcid82dfe22018-01-05 13:20:31 +0100170 index = index + 1
Radek Krejcia1339602017-11-02 13:52:38 +0100171 result["info"] = info
172 result["path"] = node.path()
173
174 return result
175
176def dataInfoSubtree(data, path, recursion=False):
177 try:
178 node = data.find_path(path).data()[0]
179 except:
180 return(json.dumps({'success': False, 'error-msg': 'Invalid data path.'}))
181
182 result = dataInfoNode(node)
183 if not result:
184 return(json.dumps({'success': False, 'error-msg': 'Path refers to a default node.'}))
185
186 result["children"] = []
187 if node.child():
188 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100189 childNode = dataInfoNode(child, result, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100190 if not childNode:
191 continue
Radek Krejcia1339602017-11-02 13:52:38 +0100192 result["children"].append(childNode)
Radek Krejci30ce1592018-03-01 14:44:14 +0100193 _sortChildren(result)
Radek Krejcia1339602017-11-02 13:52:38 +0100194
195 return(json.dumps({'success': True, 'data': result}))
196
197
198def dataInfoRoots(data, recursion=False):
Radek Krejci27134982017-11-10 15:42:00 +0100199 top = {}
200 top["children"] = []
Radek Krejcia1339602017-11-02 13:52:38 +0100201 for root in data.tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100202 rootNode = dataInfoNode(root, top, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100203 if not rootNode:
204 continue
Radek Krejcid0fac3b2018-03-13 16:55:47 +0100205 if not recursion:
206 rootNode['subtreeRoot'] = True
Radek Krejci27134982017-11-10 15:42:00 +0100207 top["children"].append(rootNode)
Radek Krejci30ce1592018-03-01 14:44:14 +0100208 _sortChildren(top)
Radek Krejci4d3896c2018-01-08 17:10:43 +0100209 return(json.dumps({'success': True, 'data': top["children"]}))