blob: 89f84befc1f26c8c2f3e0862cd2f5d958fc2e555 [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
44def schemaInfoNode(schema):
45 info = {}
46
47 info["type"] = schema.nodetype()
48 info["module"] = schema.module().name()
49 info["name"] = schema.name()
50 info["dsc"] = schema.dsc()
51 info["config"] = True if schema.flags() & ly.LYS_CONFIG_W else False
52 if info["type"] == 1:
53 info["presence"] = schema.subtype().presence()
54 info["path"] = schema.path()
55
56 if info["type"] == ly.LYS_LEAF:
57 schemaInfoType(schema.subtype(), info)
58 info["key"] = False if schema.subtype().is_key() == -1 else True
59 dflt = schema.subtype().dflt()
60 if dflt:
61 info["default"] = dflt
62 else:
63 tpdf = schema.subtype().type().der()
64 while tpdf and not tpdf.dflt():
65 tpdf = tpdf.type().der()
66 if tpdf:
67 info["default"] = tpdf.dflt()
68 elif info["type"] == ly.LYS_LEAFLIST:
69 schemaInfoType(schema.subtype(), info)
70 elif info["type"] == ly.LYS_LIST:
71 info["keys"] = []
72 for key in schema.subtype().keys():
73 info["keys"].append(key.name())
74
75 return info
76
Radek Krejci4d3896c2018-01-08 17:10:43 +010077
Radek Krejci27134982017-11-10 15:42:00 +010078def dataInfoNode(node, parent=None, recursion=False):
Radek Krejcia1339602017-11-02 13:52:38 +010079 schema = node.schema()
80 casted = node.subtype()
81
82 if node.dflt():
83 return None
84
Radek Krejci27134982017-11-10 15:42:00 +010085 if parent and schema.nodetype() == ly.LYS_LEAFLIST:
86 # find previous instance and just add value
87 for child in parent["children"]:
88 if child["info"]["name"] == schema.name():
89 child["value"].append(casted.value_str())
90 if not node.next():
91 child["last"] = True
92 return None
93
Radek Krejci6e772b22018-01-25 13:28:57 +010094 info = schemaInfoNode(schema);
Radek Krejcia1339602017-11-02 13:52:38 +010095
96 result = {}
Radek Krejci27134982017-11-10 15:42:00 +010097 if info["type"] == ly.LYS_LEAF:
Radek Krejcia1339602017-11-02 13:52:38 +010098 result["value"] = casted.value_str()
Radek Krejci27134982017-11-10 15:42:00 +010099 elif info["type"] == ly.LYS_LEAFLIST:
100 result["value"] = [casted.value_str()]
Radek Krejcia1339602017-11-02 13:52:38 +0100101 elif recursion:
102 result["children"] = []
103 if node.child():
104 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100105 childNode = dataInfoNode(child, result, True)
Radek Krejcia1339602017-11-02 13:52:38 +0100106 if not childNode:
107 continue
108 if not child.next():
109 childNode["last"] = True
110 result["children"].append(childNode)
Radek Krejcid82dfe22018-01-05 13:20:31 +0100111
112 if info["type"] == ly.LYS_LIST:
113 result["keys"] = []
114 index = 0
115 for key in schema.subtype().keys():
116 if len(result["children"]) <= index:
117 break
118 if key.subtype().name() == result["children"][index]["info"]["name"]:
119 result["keys"].append(result["children"][index]["value"])
Radek Krejcid82dfe22018-01-05 13:20:31 +0100120 index = index + 1
Radek Krejcia1339602017-11-02 13:52:38 +0100121 result["info"] = info
122 result["path"] = node.path()
123
124 return result
125
126def dataInfoSubtree(data, path, recursion=False):
127 try:
128 node = data.find_path(path).data()[0]
129 except:
130 return(json.dumps({'success': False, 'error-msg': 'Invalid data path.'}))
131
132 result = dataInfoNode(node)
133 if not result:
134 return(json.dumps({'success': False, 'error-msg': 'Path refers to a default node.'}))
135
136 result["children"] = []
137 if node.child():
138 for child in node.child().tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100139 childNode = dataInfoNode(child, result, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100140 if not childNode:
141 continue
142 if not child.next():
143 childNode["last"] = True
144 result["children"].append(childNode)
145
146 return(json.dumps({'success': True, 'data': result}))
147
148
149def dataInfoRoots(data, recursion=False):
Radek Krejci27134982017-11-10 15:42:00 +0100150 top = {}
151 top["children"] = []
Radek Krejcia1339602017-11-02 13:52:38 +0100152 for root in data.tree_for():
Radek Krejci27134982017-11-10 15:42:00 +0100153 rootNode = dataInfoNode(root, top, recursion)
Radek Krejcia1339602017-11-02 13:52:38 +0100154 if not rootNode:
155 continue
156 if not root.next():
157 rootNode["last"] = True
Radek Krejci27134982017-11-10 15:42:00 +0100158 top["children"].append(rootNode)
Radek Krejcia1339602017-11-02 13:52:38 +0100159
Radek Krejci4d3896c2018-01-08 17:10:43 +0100160 return(json.dumps({'success': True, 'data': top["children"]}))