@@ -55,6 +55,76 @@ class NXClient(Client):
55
55
>>> print(capabilities)
56
56
"""
57
57
58
+ def xpath_to_path_elem (self , request ):
59
+ paths = []
60
+ message = {
61
+ 'update' : [],
62
+ 'replace' : [],
63
+ 'delete' : [],
64
+ 'get' : [],
65
+ }
66
+ if 'nodes' not in request :
67
+ # TODO: raw rpc?
68
+ return paths
69
+ else :
70
+ namespace_modules = {}
71
+ for prefix , nspace in request .get ('namespace' , {}).items ():
72
+ module = ''
73
+ if '/Cisco-IOS-' in nspace :
74
+ module = nspace [nspace .rfind ('/' ) + 1 :]
75
+ elif '/cisco-nx' in nspace : # NXOS lowercases namespace
76
+ module = 'Cisco-NX-OS-device'
77
+ elif '/openconfig.net' in nspace :
78
+ module = 'openconfig-'
79
+ module += nspace [nspace .rfind ('/' ) + 1 :]
80
+ elif 'urn:ietf:params:xml:ns:yang:' in nspace :
81
+ module = nspace .replace (
82
+ 'urn:ietf:params:xml:ns:yang:' , '' )
83
+ if module :
84
+ namespace_modules [prefix ] = module
85
+ for node in request .get ('nodes' , []):
86
+ if 'xpath' not in node :
87
+ log .error ('Xpath is not in message' )
88
+ else :
89
+ xpath = node ['xpath' ]
90
+ value = node .get ('value' , '' )
91
+ edit_op = node .get ('edit-op' , '' )
92
+
93
+ for pfx , ns in namespace_modules .items ():
94
+ xpath = xpath .replace (pfx + ':' , '' )
95
+ value = value .replace (pfx + ':' , '' )
96
+ if edit_op :
97
+ if edit_op in ['create' , 'merge' , 'replace' ]:
98
+ xpath_lst = xpath .split ('/' )
99
+ name = xpath_lst .pop ()
100
+ xpath = '/' .join (xpath_lst )
101
+ if edit_op == 'replace' :
102
+ if not message ['replace' ]:
103
+ message ['replace' ] = [{
104
+ xpath : {name : value }
105
+ }]
106
+ else :
107
+ message ['replace' ].append (
108
+ {xpath : {name : value }}
109
+ )
110
+ else :
111
+ if not message ['update' ]:
112
+ message ['update' ] = [{
113
+ xpath : {name : value }
114
+ }]
115
+ else :
116
+ message ['update' ].append (
117
+ {xpath : {name : value }}
118
+ )
119
+ elif edit_op in ['delete' , 'remove' ]:
120
+ if message ['delete' ]:
121
+ message ['delete' ].add (xpath )
122
+ else :
123
+ message ['delete' ] = set (xpath )
124
+ else :
125
+ message ['get' ].append (xpath )
126
+ return namespace_modules , message
127
+
58
128
def delete_xpaths (self , xpaths , prefix = None ):
59
129
"""A convenience wrapper for set() which constructs Paths from supplied xpaths
60
130
to be passed to set() as the delete parameter.
@@ -87,6 +157,31 @@ def delete_xpaths(self, xpaths, prefix=None):
87
157
paths .append (self .parse_xpath_to_gnmi_path (xpath ))
88
158
return self .set (deletes = paths )
89
159
160
+ def segment_configs (self , request , configs = []):
161
+ seg_config = []
162
+ for config in configs :
163
+ top_element = next (iter (config .keys ()))
164
+ name , val = (next (iter (config [top_element ].items ())))
165
+ value = {'name' : name , 'value' : val }
166
+ seg_config .append (
167
+ (
168
+ top_element ,
169
+ [seg for seg in self .xpath_iterator (top_element )],
170
+ value
171
+ )
172
+ )
173
+ import pdb ; pdb .set_trace ()
174
+ # seg_config = self.resolve_segments(seg_config)
175
+ # Build the Path
176
+ path = proto .gnmi_pb2 .Path ()
177
+ for config in seg_config :
178
+ xpath , segments , value = config
179
+ for seg in segments :
180
+ path_elem = proto .gnmi_pb2 .PathElem ()
181
+ path_elem .name = seg ['elem' ]['name' ]
182
+
183
+ return seg_config
184
+
90
185
def set_json (self , update_json_configs = None , replace_json_configs = None , ietf = True ):
91
186
"""A convenience wrapper for set() which assumes JSON payloads and constructs desired messages.
92
187
All parameters are optional, but at least one must be present.
@@ -127,36 +222,12 @@ def check_configs(configs):
127
222
)
128
223
return configs
129
224
130
- def segment_configs (configs = []):
131
- seg_config = []
132
- for config in configs :
133
- top_element = next (iter (config .keys ()))
134
- name , val = (next (iter (config [top_element ].items ())))
135
- value = {'name' : name , 'value' : val }
136
- seg_config .append (
137
- (
138
- top_element ,
139
- [seg for seg in self .xpath_iterator (top_element )],
140
- value
141
- )
142
- )
143
- import pdb ; pdb .set_trace ()
144
- seg_config = self .resolve_segments (seg_config )
145
- # Build the Path
146
- path = proto .gnmi_pb2 .Path ()
147
- for config in seg_config :
148
- xpath , segments , value = config
149
- for seg in segments :
150
- path_elem = proto .gnmi_pb2 .PathElem ()
151
- path_elem .name = seg ['elem' ]['name' ]
152
- return seg_config
153
-
154
225
def create_updates (configs ):
155
226
if not configs :
156
227
return None
157
228
configs = check_configs (configs )
158
229
import pdb ; pdb .set_trace ()
159
- #segment_configs(configs)
230
+ #self. segment_configs(configs)
160
231
updates = []
161
232
for config in configs :
162
233
if not isinstance (config , dict ):
@@ -252,106 +323,6 @@ def get_xpaths(self, xpaths, data_type="ALL", encoding="JSON"):
252
323
)
253
324
return self .get (gnmi_path , data_type = data_type , encoding = encoding )
254
325
255
- def subscribe_xpaths (
256
- self ,
257
- xpath_subscriptions ,
258
- encoding = "JSON_IETF" ,
259
- sample_interval = Client ._NS_IN_S * 10 ,
260
- heartbeat_interval = None ,
261
- ):
262
- """A convenience wrapper of subscribe() which aids in building of SubscriptionRequest
263
- with request as subscribe SubscriptionList. This method accepts an iterable of simply xpath strings,
264
- dictionaries with Subscription attributes for more granularity, or already built Subscription
265
- objects and builds the SubscriptionList. Fields not supplied will be defaulted with the default arguments
266
- to the method.
267
-
268
- Generates a single SubscribeRequest.
269
-
270
- Parameters
271
- ----------
272
- xpath_subscriptions : str or iterable of str, dict, Subscription
273
- An iterable which is parsed to form the Subscriptions in the SubscriptionList to be passed
274
- to SubscriptionRequest. Strings are parsed as XPaths and defaulted with the default arguments,
275
- dictionaries are treated as dicts of args to pass to the Subscribe init, and Subscription is
276
- treated as simply a pre-made Subscription.
277
- encoding : proto.gnmi_pb2.Encoding, optional
278
- A member of the proto.gnmi_pb2.Encoding enum specifying desired encoding of returned data
279
- [JSON, JSON_IETF]
280
- sample_interval : int, optional
281
- Default nanoseconds for sample to occur.
282
- Defaults to 10 seconds.
283
- heartbeat_interval : int, optional
284
- Specifies the maximum allowable silent period in nanoseconds when
285
- suppress_redundant is in use. The target should send a value at least once
286
- in the period specified.
287
-
288
- Returns
289
- -------
290
- subscribe()
291
- """
292
- supported_request_modes = ["STREAM" ]
293
- request_mode = "STREAM"
294
- supported_sub_modes = ["SAMPLE" ]
295
- sub_mode = "SAMPLE"
296
- supported_encodings = ["JSON" , "JSON_IETF" ]
297
- subscription_list = proto .gnmi_pb2 .SubscriptionList ()
298
- subscription_list .mode = util .validate_proto_enum (
299
- "mode" ,
300
- request_mode ,
301
- "SubscriptionList.Mode" ,
302
- proto .gnmi_pb2 .SubscriptionList .Mode ,
303
- supported_request_modes ,
304
- )
305
- subscription_list .encoding = util .validate_proto_enum (
306
- "encoding" ,
307
- encoding ,
308
- "Encoding" ,
309
- proto .gnmi_pb2 .Encoding ,
310
- supported_encodings ,
311
- )
312
- if isinstance (xpath_subscriptions , string_types ):
313
- xpath_subscriptions = [xpath_subscriptions ]
314
- subscriptions = []
315
- for xpath_subscription in xpath_subscriptions :
316
- subscription = None
317
- if isinstance (xpath_subscription , string_types ):
318
- subscription = proto .gnmi_pb2 .Subscription ()
319
- subscription .path .CopyFrom (
320
- self .parse_xpath_to_gnmi_path (xpath_subscription )
321
- )
322
- subscription .mode = util .validate_proto_enum (
323
- "sub_mode" ,
324
- sub_mode ,
325
- "SubscriptionMode" ,
326
- proto .gnmi_pb2 .SubscriptionMode ,
327
- supported_sub_modes ,
328
- )
329
- subscription .sample_interval = sample_interval
330
- elif isinstance (xpath_subscription , dict ):
331
- path = self .parse_xpath_to_gnmi_path (xpath_subscription ["path" ])
332
- arg_dict = {
333
- "path" : path ,
334
- "mode" : sub_mode ,
335
- "sample_interval" : sample_interval ,
336
- }
337
- arg_dict .update (xpath_subscription )
338
- if "mode" in arg_dict :
339
- arg_dict ["mode" ] = util .validate_proto_enum (
340
- "sub_mode" ,
341
- arg_dict ["mode" ],
342
- "SubscriptionMode" ,
343
- proto .gnmi_pb2 .SubscriptionMode ,
344
- supported_sub_modes ,
345
- )
346
- subscription = proto .gnmi_pb2 .Subscription (** arg_dict )
347
- elif isinstance (xpath_subscription , proto .gnmi_pb2 .Subscription ):
348
- subscription = xpath_subscription
349
- else :
350
- raise Exception ("xpath in list must be xpath or dict/Path!" )
351
- subscriptions .append (subscription )
352
- subscription_list .subscription .extend (subscriptions )
353
- return self .subscribe ([subscription_list ])
354
-
355
326
def subscribe_xpaths (
356
327
self ,
357
328
xpath_subscriptions ,
0 commit comments