1
1
#!/usr/bin/python
2
- #Name: netapp_api_cmode .py
2
+ #Name: netapp_api .py
3
3
#Desc: Uses Netapp Data Ontap API to get per volume latency & iops metrics. Download the managemability SDK from now.netapp.com
4
4
#Author: Evan Fraser <evan.fraser@trademe.co.nz>
5
5
#Date: 13/08/2012
@@ -33,6 +33,8 @@ def __init__(self, MetricName, FilerName):
33
33
self .filer_metrics = None
34
34
self .MetricName = MetricName
35
35
self .FilerName = FilerName
36
+ self .instances = None
37
+ self .ClusterName = filerdict [self .FilerName ]['name' ]
36
38
super (GetMetricsThread , self ).__init__ ()
37
39
38
40
def run (self ):
@@ -92,12 +94,18 @@ def run(self):
92
94
if (out .results_status () == "failed" ):
93
95
print (out .results_reason () + "\n " )
94
96
sys .exit (2 )
97
+
98
+ #self.clusterName = filerdict[filer]['name']
95
99
96
- filername = filerdict [filer ]['name' ]
97
100
instances_list = out .child_get ("instances" )
98
101
instances = instances_list .children_get ()
102
+ self .instances = instances
99
103
100
- for inst in instances :
104
+ #Function within the class for updating the metrics
105
+ def update_metrics (self ):
106
+ clustername = self .ClusterName
107
+ print clustername
108
+ for inst in self .instances :
101
109
inst_name = unicodedata .normalize ('NFKD' ,inst .child_get_string ("name" )).encode ('ascii' ,'ignore' )
102
110
counters_list = inst .child_get ("counters" )
103
111
counters = counters_list .children_get ()
@@ -106,7 +114,71 @@ def run(self):
106
114
counter_name = unicodedata .normalize ('NFKD' ,counter .child_get_string ("name" )).encode ('ascii' ,'ignore' )
107
115
counter_value = counter .child_get_string ("value" )
108
116
counter_unit = counter .child_get_string ("unit" )
109
- self .filer_metrics [filername + '_vol_' + inst_name + '_' + counter_name ] = float (counter_value )
117
+ self .filer_metrics [clustername + '_vol_' + inst_name + '_' + counter_name ] = float (counter_value )
118
+
119
+ #Function within the class for defining the metrics for ganglia
120
+ def define_metrics (self ,Desc_Skel ,params ):
121
+
122
+ clustername = self .ClusterName
123
+ filer = self .FilerName
124
+ for inst in self .instances :
125
+ inst_name = unicodedata .normalize ('NFKD' ,inst .child_get_string ("name" )).encode ('ascii' ,'ignore' )
126
+ counters_list = inst .child_get ("counters" )
127
+ counters = counters_list .children_get ()
128
+
129
+ for counter in counters :
130
+ counter_name = unicodedata .normalize ('NFKD' ,counter .child_get_string ("name" )).encode ('ascii' ,'ignore' )
131
+ counter_value = counter .child_get_string ("value" )
132
+ counter_unit = counter .child_get_string ("unit" )
133
+ print counter_name
134
+ if 'total_ops' in counter_name :
135
+ descriptors .append (create_desc (Desc_Skel , {
136
+ "name" : clustername + '_vol_' + inst_name + '_' + counter_name ,
137
+ "units" : 'iops' ,
138
+ "description" : "volume iops" ,
139
+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
140
+ "groups" : "iops"
141
+ }))
142
+ elif 'avg_latency' in counter_name :
143
+ descriptors .append (create_desc (Desc_Skel , {
144
+ "name" : clustername + '_vol_' + inst_name + '_' + counter_name ,
145
+ "units" : 'ms' ,
146
+ "description" : "volume avg latency" ,
147
+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
148
+ "groups" : "latency"
149
+ }))
150
+ elif 'read_ops' in counter_name :
151
+ descriptors .append (create_desc (Desc_Skel , {
152
+ "name" : clustername + '_vol_' + inst_name + '_' + counter_name ,
153
+ "units" : 'iops' ,
154
+ "description" : "volume read iops" ,
155
+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
156
+ "groups" : "iops"
157
+ }))
158
+ elif 'read_latency' in counter_name :
159
+ descriptors .append (create_desc (Desc_Skel , {
160
+ "name" : clustername + '_vol_' + inst_name + '_' + counter_name ,
161
+ "units" : 'ms' ,
162
+ "description" : "volume read latency" ,
163
+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
164
+ "groups" : "latency"
165
+ }))
166
+ elif 'write_ops' in counter_name :
167
+ descriptors .append (create_desc (Desc_Skel , {
168
+ "name" : clustername + '_vol_' + inst_name + '_' + counter_name ,
169
+ "units" : 'iops' ,
170
+ "description" : "volume write iops" ,
171
+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
172
+ "groups" : "iops"
173
+ }))
174
+ elif 'write_latency' in counter_name :
175
+ descriptors .append (create_desc (Desc_Skel , {
176
+ "name" : clustername + '_vol_' + inst_name + '_' + counter_name ,
177
+ "units" : 'ms' ,
178
+ "description" : "volume write latency" ,
179
+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
180
+ "groups" : "latency"
181
+ }))
110
182
111
183
112
184
def get_metrics (name ):
@@ -125,6 +197,7 @@ def get_metrics(name):
125
197
#Wait for the threads to return here
126
198
for t in threads :
127
199
t .join ()
200
+ t .update_metrics ()
128
201
metrics .update (t .filer_metrics )
129
202
#end = time.time()
130
203
#print "elapsed time was: ",(end - start)
@@ -157,7 +230,7 @@ def get_metrics(name):
157
230
#Find the metric name of the base counter
158
231
total_ops_name = name .replace ('avg_latency' , 'total_ops' )
159
232
#Calculate latency in time (div 100 to change to ms)
160
- return float ((FASMETRICS ['data' ][name ] - LAST_FASMETRICS ['data' ][name ]) / (FASMETRICS ['data' ][total_ops_name ] - LAST_FASMETRICS ['data' ][total_ops_name ])) / 100
233
+ return float ((FASMETRICS ['data' ][name ] - LAST_FASMETRICS ['data' ][name ]) / (FASMETRICS ['data' ][total_ops_name ] - LAST_FASMETRICS ['data' ][total_ops_name ])) / 1000
161
234
except StandardError :
162
235
return 0
163
236
elif 'read_ops' in name :
@@ -174,7 +247,7 @@ def get_metrics(name):
174
247
elif 'read_latency' in name :
175
248
try :
176
249
read_ops_name = name .replace ('read_latency' , 'read_ops' )
177
- return float ((FASMETRICS ['data' ][name ] - LAST_FASMETRICS ['data' ][name ]) / (FASMETRICS ['data' ][read_ops_name ] - LAST_FASMETRICS ['data' ][read_ops_name ])) / 100
250
+ return float ((FASMETRICS ['data' ][name ] - LAST_FASMETRICS ['data' ][name ]) / (FASMETRICS ['data' ][read_ops_name ] - LAST_FASMETRICS ['data' ][read_ops_name ])) / 1000
178
251
except StandardError :
179
252
return 0
180
253
elif 'write_ops' in name :
@@ -190,7 +263,7 @@ def get_metrics(name):
190
263
elif 'write_latency' in name :
191
264
try :
192
265
write_ops_name = name .replace ('write_latency' , 'write_ops' )
193
- return float ((FASMETRICS ['data' ][name ] - LAST_FASMETRICS ['data' ][name ]) / (FASMETRICS ['data' ][write_ops_name ] - LAST_FASMETRICS ['data' ][write_ops_name ])) / 100
266
+ return float ((FASMETRICS ['data' ][name ] - LAST_FASMETRICS ['data' ][name ]) / (FASMETRICS ['data' ][write_ops_name ] - LAST_FASMETRICS ['data' ][write_ops_name ])) / 1000
194
267
except StandardError :
195
268
return 0
196
269
@@ -206,163 +279,40 @@ def create_desc(skel, prop):
206
279
return d
207
280
208
281
209
- def define_metrics_thread (Desc_Skel ,filer ,params ):
210
- global descriptors
211
- s = NaServer (params [filer ]['ipaddr' ], 1 , 3 )
212
- out = s .set_transport_type ('HTTPS' )
213
- if (out and out .results_errno () != 0 ) :
214
- r = out .results_reason ()
215
- print ("Connection to filer failed: " + r + "\n " )
216
- sys .exit (2 )
217
-
218
- out = s .set_style ('LOGIN' )
219
- if (out and out .results_errno () != 0 ) :
220
- r = out .results_reason ()
221
- print ("Connection to filer failed: " + r + "\n " )
222
- sys .exit (2 )
223
- out = s .set_admin_user (params [filer ]['user' ], params [filer ]['password' ])
224
-
225
- #In C-mode, perf-object-get-instances-iter-start doesn't exist
226
- # Also need to get list of instance names to provide to the perf-object-get-instances now.
227
- #Get list of volume instances
228
- obj_name = "volume"
229
- instance_in = NaElement ("perf-object-instance-list-info-iter" )
230
- instance_in .child_add_string ("objectname" , obj_name )
231
-
232
- #Invoke API
233
- out = s .invoke_elem (instance_in )
234
- if (out .results_status () == "failed" ):
235
- print ("Invoke failed: " + out .results_reason () + "\n " )
236
- sys .exit (2 )
237
-
238
- #create an object for all the instances which we will pass to the perf-object-get-instances below
239
- instance_obj = NaElement ("instances" )
240
- instance_list = out .child_get ("attributes-list" )
241
- instances = instance_list .children_get ()
242
- instance_names = []
243
- for i in instances :
244
- instance_obj .child_add_string ("instance" , i .child_get_string ("name" ))
245
-
246
-
247
- #Get perf objects for each instance
248
- perf_in = NaElement ("perf-object-get-instances" )
249
- perf_in .child_add_string ("objectname" , obj_name )
250
- perf_in .child_add (instance_obj )
251
- #perf_in.
252
-
253
- #Hard coded volume, only volume stats gathered at present
254
- #Create object of type counters
255
- counters = NaElement ("counters" )
256
- #Add counter names to the object
257
- counter_name_list = ["total_ops" ,"avg_latency" ,"read_ops" ,"read_latency" ,"write_ops" ,"write_latency" ]
258
- for c in counter_name_list :
259
- counters .child_add_string ("counter" , c )
260
- perf_in .child_add (counters )
261
-
262
-
263
- #Invoke API
264
- out = s .invoke_elem (perf_in )
265
- if (out .results_status () == "failed" ):
266
- print ("Invoke failed: " + out .results_reason () + "\n " )
267
- sys .exit (2 )
268
-
269
-
270
- #iter_tag = out.child_get_string("tag")
271
- #num_records = 1
272
- filername = params [filer ]['name' ]
273
-
274
- instances_list = out .child_get ("instances" )
275
- instances = instances_list .children_get ()
276
-
277
- for inst in instances :
278
- inst_name = unicodedata .normalize ('NFKD' ,inst .child_get_string ("name" )).encode ('ascii' ,'ignore' )
279
- counters_list = inst .child_get ("counters" )
280
- counters = counters_list .children_get ()
281
-
282
- for counter in counters :
283
- counter_name = unicodedata .normalize ('NFKD' ,counter .child_get_string ("name" )).encode ('ascii' ,'ignore' )
284
- counter_value = counter .child_get_string ("value" )
285
- counter_unit = counter .child_get_string ("unit" )
286
- if 'total_ops' in counter_name :
287
- descriptors .append (create_desc (Desc_Skel , {
288
- "name" : filername + '_vol_' + inst_name + '_' + counter_name ,
289
- "units" : 'iops' ,
290
- "description" : "volume iops" ,
291
- "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
292
- "groups" : "iops"
293
- }))
294
- elif 'avg_latency' in counter_name :
295
- descriptors .append (create_desc (Desc_Skel , {
296
- "name" : filername + '_vol_' + inst_name + '_' + counter_name ,
297
- "units" : 'ms' ,
298
- "description" : "volume avg latency" ,
299
- "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
300
- "groups" : "latency"
301
- }))
302
- elif 'read_ops' in counter_name :
303
- descriptors .append (create_desc (Desc_Skel , {
304
- "name" : filername + '_vol_' + inst_name + '_' + counter_name ,
305
- "units" : 'iops' ,
306
- "description" : "volume read iops" ,
307
- "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
308
- "groups" : "iops"
309
- }))
310
- elif 'read_latency' in counter_name :
311
- descriptors .append (create_desc (Desc_Skel , {
312
- "name" : filername + '_vol_' + inst_name + '_' + counter_name ,
313
- "units" : 'ms' ,
314
- "description" : "volume read latency" ,
315
- "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
316
- "groups" : "latency"
317
- }))
318
- elif 'write_ops' in counter_name :
319
- descriptors .append (create_desc (Desc_Skel , {
320
- "name" : filername + '_vol_' + inst_name + '_' + counter_name ,
321
- "units" : 'iops' ,
322
- "description" : "volume write iops" ,
323
- "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
324
- "groups" : "iops"
325
- }))
326
- elif 'write_latency' in counter_name :
327
- descriptors .append (create_desc (Desc_Skel , {
328
- "name" : filername + '_vol_' + inst_name + '_' + counter_name ,
329
- "units" : 'ms' ,
330
- "description" : "volume write latency" ,
331
- "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
332
- "groups" : "latency"
333
- }))
334
- #return descriptors
335
282
336
283
337
284
def define_metrics (Desc_Skel ,params ):
338
285
global descriptors
286
+ ObjectTypeList = ["lif:vserver" ]
339
287
max_records = 10
340
288
threads = []
341
289
for filer in params .keys ():
342
290
#call define_metrics_thread as separate threads for each filer
343
- thread = threading .Thread (target = define_metrics_thread , args = (Desc_Skel ,filer ,params ))
291
+ blankname = ""
292
+ thread = GetMetricsThread (blankname ,filer )
344
293
thread .start ()
345
294
threads .append (thread )
346
295
347
296
for t in threads :
348
297
t .join ()
349
-
298
+ t .define_metrics (Desc_Skel ,params )
299
+
350
300
return descriptors
351
301
352
302
def metric_init (params ):
353
303
global descriptors ,filerdict
354
304
print 'netapp_stats] Received the following parameters'
355
305
params = {
356
306
'filer1' : {
357
- 'name' : 'cluster1mgmt.local ' ,
307
+ 'name' : 'cluster1.localdomain ' ,
358
308
'ipaddr' : '192.168.1.100' ,
359
- 'user' : 'monitoruser ' ,
309
+ 'user' : 'username ' ,
360
310
'password' : 'password' ,
361
311
},
362
312
'filer2' : {
363
- 'name' : 'cluster2mgmt.local ' ,
364
- 'ipaddr' : '192.168.1.200 ' ,
365
- 'user' : 'monitoruser ' ,
313
+ 'name' : 'cluster2.localdomain ' ,
314
+ 'ipaddr' : '192.168.1.100 ' ,
315
+ 'user' : 'username ' ,
366
316
'password' : 'password' ,
367
317
},
368
318
}
0 commit comments