11#!/usr/bin/python
2- #Name: netapp_api_cmode .py
2+ #Name: netapp_api .py
33#Desc: Uses Netapp Data Ontap API to get per volume latency & iops metrics. Download the managemability SDK from now.netapp.com
44#Author: Evan Fraser <[email protected] > 55#Date: 13/08/2012
@@ -33,6 +33,8 @@ def __init__(self, MetricName, FilerName):
3333 self .filer_metrics = None
3434 self .MetricName = MetricName
3535 self .FilerName = FilerName
36+ self .instances = None
37+ self .ClusterName = filerdict [self .FilerName ]['name' ]
3638 super (GetMetricsThread , self ).__init__ ()
3739
3840 def run (self ):
@@ -92,12 +94,18 @@ def run(self):
9294 if (out .results_status () == "failed" ):
9395 print (out .results_reason () + "\n " )
9496 sys .exit (2 )
97+
98+ #self.clusterName = filerdict[filer]['name']
9599
96- filername = filerdict [filer ]['name' ]
97100 instances_list = out .child_get ("instances" )
98101 instances = instances_list .children_get ()
102+ self .instances = instances
99103
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 :
101109 inst_name = unicodedata .normalize ('NFKD' ,inst .child_get_string ("name" )).encode ('ascii' ,'ignore' )
102110 counters_list = inst .child_get ("counters" )
103111 counters = counters_list .children_get ()
@@ -106,7 +114,71 @@ def run(self):
106114 counter_name = unicodedata .normalize ('NFKD' ,counter .child_get_string ("name" )).encode ('ascii' ,'ignore' )
107115 counter_value = counter .child_get_string ("value" )
108116 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+ }))
110182
111183
112184def get_metrics (name ):
@@ -125,6 +197,7 @@ def get_metrics(name):
125197 #Wait for the threads to return here
126198 for t in threads :
127199 t .join ()
200+ t .update_metrics ()
128201 metrics .update (t .filer_metrics )
129202 #end = time.time()
130203 #print "elapsed time was: ",(end - start)
@@ -157,7 +230,7 @@ def get_metrics(name):
157230 #Find the metric name of the base counter
158231 total_ops_name = name .replace ('avg_latency' , 'total_ops' )
159232 #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
161234 except StandardError :
162235 return 0
163236 elif 'read_ops' in name :
@@ -174,7 +247,7 @@ def get_metrics(name):
174247 elif 'read_latency' in name :
175248 try :
176249 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
178251 except StandardError :
179252 return 0
180253 elif 'write_ops' in name :
@@ -190,7 +263,7 @@ def get_metrics(name):
190263 elif 'write_latency' in name :
191264 try :
192265 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
194267 except StandardError :
195268 return 0
196269
@@ -206,163 +279,40 @@ def create_desc(skel, prop):
206279 return d
207280
208281
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
335282
336283
337284def define_metrics (Desc_Skel ,params ):
338285 global descriptors
286+ ObjectTypeList = ["lif:vserver" ]
339287 max_records = 10
340288 threads = []
341289 for filer in params .keys ():
342290 #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 )
344293 thread .start ()
345294 threads .append (thread )
346295
347296 for t in threads :
348297 t .join ()
349-
298+ t .define_metrics (Desc_Skel ,params )
299+
350300 return descriptors
351301
352302def metric_init (params ):
353303 global descriptors ,filerdict
354304 print 'netapp_stats] Received the following parameters'
355305 params = {
356306 'filer1' : {
357- 'name' : 'cluster1mgmt.local ' ,
307+ 'name' : 'cluster1.localdomain ' ,
358308 'ipaddr' : '192.168.1.100' ,
359- 'user' : 'monitoruser ' ,
309+ 'user' : 'username ' ,
360310 'password' : 'password' ,
361311 },
362312 '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 ' ,
366316 'password' : 'password' ,
367317 },
368318 }
0 commit comments