blob: 935d974e30016cb1ad0b33a73d44c411aca1aa4f [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 Krejci0f793fe2018-02-14 08:33:45 +010091 elif info["type"] == yang.LYS_LIST:
Radek Krejci6e772b22018-01-25 13:28:57 +010092 info["keys"] = []
93 for key in schema.subtype().keys():
94 info["keys"].append(key.name())
95
96 return info
97
Radek Krejci4d3896c2018-01-08 17:10:43 +010098
Radek Krejci27134982017-11-10 15:42:00 +010099def dataInfoNode(node, parent=None, recursion=False):
Radek Krejcia1339602017-11-02 13:52:38 +0100100 schema = node.schema()
101 casted = node.subtype()
102
103 if node.dflt():
104 return None
105
Radek Krejci0f793fe2018-02-14 08:33:45 +0100106 if parent and schema.nodetype() == yang.LYS_LEAFLIST:
Radek Krejci27134982017-11-10 15:42:00 +0100107 # find previous instance and just add value
108 for child in parent["children"]:
109 if child["info"]["name"] == schema.name():
110 child["value"].append(casted.value_str())
111 if not node.next():
112 child["last"] = True
113 return None
114
Radek Krejci6e772b22018-01-25 13:28:57 +0100115 info = schemaInfoNode(schema);
Radek Krejcia1339602017-11-02 13:52:38 +0100116
117 result = {}
Radek Krejci0f793fe2018-02-14 08:33:45 +0100118 if info["type"] == yang.LYS_LEAF:
Radek Krejcia1339602017-11-02 13:52:38 +0100119 result["value"] = casted.value_str()
Radek Krejci0f793fe2018-02-14 08:33:45 +0100120 elif info["type"] == yang.LYS_LEAFLIST:
Radek Krejci27134982017-11-10 15:42:00 +0100121 result["value"] = [casted.value_str()]
Radek Krejcia1339602017-11-02 13:52:38 +0100122 elif recursion:
123 result["children"] = []
124 if node.child():
125 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100126 childNode = dataInfoNode(child, result, True)
Radek Krejcia1339602017-11-02 13:52:38 +0100127 if not childNode:
128 continue
129 if not child.next():
130 childNode["last"] = True
131 result["children"].append(childNode)
Radek Krejcid82dfe22018-01-05 13:20:31 +0100132
Radek Krejci0f793fe2018-02-14 08:33:45 +0100133 if info["type"] == yang.LYS_LIST:
Radek Krejcid82dfe22018-01-05 13:20:31 +0100134 result["keys"] = []
135 index = 0
136 for key in schema.subtype().keys():
137 if len(result["children"]) <= index:
138 break
139 if key.subtype().name() == result["children"][index]["info"]["name"]:
140 result["keys"].append(result["children"][index]["value"])
Radek Krejcid82dfe22018-01-05 13:20:31 +0100141 index = index + 1
Radek Krejcia1339602017-11-02 13:52:38 +0100142 result["info"] = info
143 result["path"] = node.path()
144
145 return result
146
147def dataInfoSubtree(data, path, recursion=False):
148 try:
149 node = data.find_path(path).data()[0]
150 except:
151 return(json.dumps({'success': False, 'error-msg': 'Invalid data path.'}))
152
153 result = dataInfoNode(node)
154 if not result:
155 return(json.dumps({'success': False, 'error-msg': 'Path refers to a default node.'}))
156
157 result["children"] = []
158 if node.child():
159 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100160 childNode = dataInfoNode(child, result, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100161 if not childNode:
162 continue
163 if not child.next():
164 childNode["last"] = True
165 result["children"].append(childNode)
166
167 return(json.dumps({'success': True, 'data': result}))
168
169
170def dataInfoRoots(data, recursion=False):
Radek Krejci27134982017-11-10 15:42:00 +0100171 top = {}
172 top["children"] = []
Radek Krejcia1339602017-11-02 13:52:38 +0100173 for root in data.tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100174 rootNode = dataInfoNode(root, top, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100175 if not rootNode:
176 continue
177 if not root.next():
178 rootNode["last"] = True
Radek Krejci27134982017-11-10 15:42:00 +0100179 top["children"].append(rootNode)
Radek Krejcia1339602017-11-02 13:52:38 +0100180
Radek Krejci4d3896c2018-01-08 17:10:43 +0100181 return(json.dumps({'success': True, 'data': top["children"]}))