Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 1 | """ |
| 2 | NETCONF data helper functions |
| 3 | File: data.py |
| 4 | Author: Radek Krejci <rkrejci@cesnet.cz> |
| 5 | """ |
| 6 | |
| 7 | import json |
| 8 | import os |
| 9 | |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 10 | import yang |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 11 | import netconf2 as nc |
| 12 | |
Radek Krejci | 4d3896c | 2018-01-08 17:10:43 +0100 | [diff] [blame] | 13 | def infoBuiltInType(base): |
| 14 | return { |
Radek Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 15 | - 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 Krejci | 4d3896c | 2018-01-08 17:10:43 +0100 | [diff] [blame] | 26 | 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 Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 38 | |
| 39 | def schemaInfoType(schema, info): |
| 40 | info["datatype"] = schema.type().der().name() |
| 41 | info["datatypebase"] = infoBuiltInType(schema.type().base()) |
| 42 | |
| 43 | |
Radek Krejci | d0ce4cf | 2018-02-09 14:44:34 +0100 | [diff] [blame] | 44 | def 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 Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 62 | def schemaInfoNode(schema): |
| 63 | info = {} |
| 64 | |
| 65 | info["type"] = schema.nodetype() |
Radek Krejci | ad45e57 | 2018-02-21 10:54:54 +0100 | [diff] [blame^] | 66 | if schema.module().rev_size(): |
| 67 | info["module"] = schema.module().name() + '@' + schema.module().rev().date() |
| 68 | else: |
| 69 | info["module"] = schema.module().name() |
Radek Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 70 | info["name"] = schema.name() |
| 71 | info["dsc"] = schema.dsc() |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 72 | info["config"] = True if schema.flags() & yang.LYS_CONFIG_W else False |
Radek Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 73 | if info["type"] == 1: |
| 74 | info["presence"] = schema.subtype().presence() |
| 75 | info["path"] = schema.path() |
| 76 | |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 77 | if info["type"] == yang.LYS_LEAF: |
Radek Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 78 | 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 Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 89 | elif info["type"] == yang.LYS_LEAFLIST: |
Radek Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 90 | schemaInfoType(schema.subtype(), info) |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 91 | elif info["type"] == yang.LYS_LIST: |
Radek Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 92 | info["keys"] = [] |
| 93 | for key in schema.subtype().keys(): |
| 94 | info["keys"].append(key.name()) |
| 95 | |
| 96 | return info |
| 97 | |
Radek Krejci | 4d3896c | 2018-01-08 17:10:43 +0100 | [diff] [blame] | 98 | |
Radek Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 99 | def dataInfoNode(node, parent=None, recursion=False): |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 100 | schema = node.schema() |
| 101 | casted = node.subtype() |
| 102 | |
| 103 | if node.dflt(): |
| 104 | return None |
| 105 | |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 106 | if parent and schema.nodetype() == yang.LYS_LEAFLIST: |
Radek Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 107 | # 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 Krejci | 6e772b2 | 2018-01-25 13:28:57 +0100 | [diff] [blame] | 115 | info = schemaInfoNode(schema); |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 116 | |
| 117 | result = {} |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 118 | if info["type"] == yang.LYS_LEAF: |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 119 | result["value"] = casted.value_str() |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 120 | elif info["type"] == yang.LYS_LEAFLIST: |
Radek Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 121 | result["value"] = [casted.value_str()] |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 122 | elif recursion: |
| 123 | result["children"] = [] |
| 124 | if node.child(): |
| 125 | for child in node.child().tree_for(): |
Radek Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 126 | childNode = dataInfoNode(child, result, True) |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 127 | if not childNode: |
| 128 | continue |
| 129 | if not child.next(): |
| 130 | childNode["last"] = True |
| 131 | result["children"].append(childNode) |
Radek Krejci | d82dfe2 | 2018-01-05 13:20:31 +0100 | [diff] [blame] | 132 | |
Radek Krejci | 0f793fe | 2018-02-14 08:33:45 +0100 | [diff] [blame] | 133 | if info["type"] == yang.LYS_LIST: |
Radek Krejci | d82dfe2 | 2018-01-05 13:20:31 +0100 | [diff] [blame] | 134 | 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 Krejci | d82dfe2 | 2018-01-05 13:20:31 +0100 | [diff] [blame] | 141 | index = index + 1 |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 142 | result["info"] = info |
| 143 | result["path"] = node.path() |
| 144 | |
| 145 | return result |
| 146 | |
| 147 | def 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 Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 160 | childNode = dataInfoNode(child, result, recursion) |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 161 | 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 | |
| 170 | def dataInfoRoots(data, recursion=False): |
Radek Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 171 | top = {} |
| 172 | top["children"] = [] |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 173 | for root in data.tree_for(): |
Radek Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 174 | rootNode = dataInfoNode(root, top, recursion) |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 175 | if not rootNode: |
| 176 | continue |
| 177 | if not root.next(): |
| 178 | rootNode["last"] = True |
Radek Krejci | 2713498 | 2017-11-10 15:42:00 +0100 | [diff] [blame] | 179 | top["children"].append(rootNode) |
Radek Krejci | a133960 | 2017-11-02 13:52:38 +0100 | [diff] [blame] | 180 | |
Radek Krejci | 4d3896c | 2018-01-08 17:10:43 +0100 | [diff] [blame] | 181 | return(json.dumps({'success': True, 'data': top["children"]})) |