@@ -52,12 +52,146 @@ class NXClient(Client):
52
52
>>> capabilities = client.capabilities()
53
53
>>> print(capabilities)
54
54
"""
55
+ def delete_xpaths (self , xpaths , prefix = None ):
56
+ """A convenience wrapper for set() which constructs Paths from supplied xpaths
57
+ to be passed to set() as the delete parameter.
55
58
56
- def get (self , * args , ** kwargs ):
57
- raise NotImplementedError ("Get not yet supported on NX-OS!" )
59
+ Parameters
60
+ ----------
61
+ xpaths : iterable of str
62
+ XPaths to specify to be deleted.
63
+ If prefix is specified these strings are assumed to be the suffixes.
64
+ prefix : str
65
+ The XPath prefix to apply to all XPaths for deletion.
66
+
67
+ Returns
68
+ -------
69
+ set()
70
+ """
71
+ if isinstance (xpaths , string_types ):
72
+ xpaths = [xpaths ]
73
+ paths = []
74
+ # prefix is not supported on NX yet
75
+ prefix = None
76
+ for xpath in xpaths :
77
+ if prefix :
78
+ if prefix .endswith ("/" ) and xpath .startswith ("/" ):
79
+ xpath = "{prefix}{xpath}" .format (
80
+ prefix = prefix [:- 1 ], xpath = xpath [1 :]
81
+ )
82
+ elif prefix .endswith ("/" ) or xpath .startswith ("/" ):
83
+ xpath = "{prefix}{xpath}" .format (prefix = prefix , xpath = xpath )
84
+ else :
85
+ xpath = "{prefix}/{xpath}" .format (prefix = prefix , xpath = xpath )
86
+ paths .append (self .parse_xpath_to_gnmi_path (xpath ))
87
+ return self .set (deletes = paths )
88
+
89
+ def set_json (self , update_json_configs = None , replace_json_configs = None , ietf = False , prefix = None ):
90
+ """A convenience wrapper for set() which assumes JSON payloads and constructs desired messages.
91
+ All parameters are optional, but at least one must be present.
92
+
93
+ This method expects JSON in the same format as what you might send via the native gRPC interface
94
+ with a fully modeled configuration which is then parsed to meet the gNMI implementation.
95
+
96
+ Parameters
97
+ ----------
98
+ update_json_configs : iterable of JSON configurations, optional
99
+ JSON configs to apply as updates.
100
+ replace_json_configs : iterable of JSON configurations, optional
101
+ JSON configs to apply as replacements.
102
+ ietf : bool, optional
103
+ Use JSON_IETF vs JSON.
104
+
105
+ Returns
106
+ -------
107
+ set()
108
+ """
109
+ # JSON_IETF and prefix are not supported on NX yet
110
+ ietf = False
111
+ prefix = None
112
+
113
+ if not any ([update_json_configs , replace_json_configs ]):
114
+ raise Exception ("Must supply at least one set of configurations to method!" )
115
+
116
+ def check_configs (name , configs ):
117
+ if isinstance (configs , string_types ):
118
+ logger .debug ("Handling %s as JSON string." , name )
119
+ try :
120
+ configs = json .loads (configs )
121
+ except :
122
+ raise Exception ("{name} is invalid JSON!" .format (name = name ))
123
+ configs = [configs ]
124
+ elif isinstance (configs , dict ):
125
+ logger .debug ("Handling %s as already serialized JSON object." , name )
126
+ configs = [configs ]
127
+ elif not isinstance (configs , (list , set )):
128
+ raise Exception (
129
+ "{name} must be an iterable of configs!" .format (name = name )
130
+ )
131
+ return configs
58
132
59
- def set (self , * args , ** kwargs ):
60
- raise NotImplementedError ("Set not yet supported on NX-OS!" )
133
+ def create_updates (name , configs ):
134
+ if not configs :
135
+ return None
136
+ configs = check_configs (name , configs )
137
+ updates = []
138
+ for config in configs :
139
+ if not isinstance (config , dict ):
140
+ raise Exception ("config must be a JSON object!" )
141
+ if len (config .keys ()) > 1 :
142
+ raise Exception ("config should only target one YANG module!" )
143
+ top_element = next (iter (config .keys ()))
144
+ update = proto .gnmi_pb2 .Update ()
145
+ update .path .CopyFrom (self .parse_xpath_to_gnmi_path (top_element ))
146
+ config = config .pop (top_element )
147
+ if ietf :
148
+ update .val .json_ietf_val = json .dumps (config ).encode ("utf-8" )
149
+ else :
150
+ update .val .json_val = json .dumps (config ).encode ("utf-8" )
151
+ updates .append (update )
152
+ return updates
153
+
154
+ updates = create_updates ("update_json_configs" , update_json_configs )
155
+ replaces = create_updates ("replace_json_configs" , replace_json_configs )
156
+ return self .set (prefix = prefix , updates = updates , replaces = replaces )
157
+
158
+ def get_xpaths (self , xpaths , data_type = "ALL" , encoding = "JSON_IETF" ):
159
+ """A convenience wrapper for get() which forms proto.gnmi_pb2.Path from supplied xpaths.
160
+
161
+ Parameters
162
+ ----------
163
+ xpaths : iterable of str or str
164
+ An iterable of XPath strings to request data of
165
+ If simply a str, wraps as a list for convenience
166
+ data_type : proto.gnmi_pb2.GetRequest.DataType, optional
167
+ A direct value or key from the GetRequest.DataType enum
168
+ [ALL, CONFIG, STATE, OPERATIONAL]
169
+ encoding : proto.gnmi_pb2.GetRequest.Encoding, optional
170
+ A direct value or key from the Encoding enum
171
+ [JSON, JSON_IETF]
172
+
173
+ Returns
174
+ -------
175
+ get()
176
+ """
177
+ supported_encodings = ["JSON" , "JSON_IETF" ]
178
+ encoding = util .validate_proto_enum (
179
+ "encoding" ,
180
+ encoding ,
181
+ "Encoding" ,
182
+ proto .gnmi_pb2 .Encoding ,
183
+ supported_encodings ,
184
+ )
185
+ gnmi_path = None
186
+ if isinstance (xpaths , (list , set )):
187
+ gnmi_path = map (self .parse_xpath_to_gnmi_path , set (xpaths ))
188
+ elif isinstance (xpaths , string_types ):
189
+ gnmi_path = [self .parse_xpath_to_gnmi_path (xpaths )]
190
+ else :
191
+ raise Exception (
192
+ "xpaths must be a single xpath string or iterable of xpath strings!"
193
+ )
194
+ return self .get (gnmi_path , data_type = data_type , encoding = encoding )
61
195
62
196
def subscribe_xpaths (
63
197
self ,
0 commit comments