44#Author: Evan Fraser <[email protected] > 55#Date: 13/08/2012
66#Updated 26/03/2014: Now polls each filer as a separate thread and now only supports Clustered ONTAP 8.2+
7+ #Updated 02/04/2014: Now has volume space and inode metrics
78
89import sys
910import time
@@ -35,25 +36,11 @@ def __init__(self, MetricName, FilerName):
3536 self .FilerName = FilerName
3637 self .instances = None
3738 self .ClusterName = filerdict [self .FilerName ]['name' ]
39+ self .volume_capacity_obj = None
3840 super (GetMetricsThread , self ).__init__ ()
39-
40- def run (self ):
41- self .filer_metrics = {}
42- metric = self .MetricName
43- filer = self .FilerName
44- s = NaServer (filerdict [filer ]['ipaddr' ], 1 , 3 )
45- out = s .set_transport_type ('HTTPS' )
46- if (out and out .results_errno () != 0 ) :
47- r = out .results_reason ()
48- print ("Connection to filer failed: " + r + "\n " )
49- sys .exit (2 )
50-
51- out = s .set_style ('LOGIN' )
52- if (out and out .results_errno () != 0 ) :
53- r = out .results_reason ()
54- print ("Connection to filer failed: " + r + "\n " )
55- sys .exit (2 )
56- out = s .set_admin_user (filerdict [filer ]['user' ], filerdict [filer ]['password' ])
41+
42+ def volume_perf_metrics (self , s ):
43+ # In class function to get volume perf metrics
5744
5845 #In C-mode, perf-object-get-instances-iter-start doesn't exist
5946 # Also need to get list of instance names to provide to the perf-object-get-instances now.
@@ -101,10 +88,68 @@ def run(self):
10188 instances = instances_list .children_get ()
10289 self .instances = instances
10390
91+ def volume_capacity_metrics (self , s ):
92+ # Function to perform API queries to get volume capacity metrics.
93+ na_server_obj = s
94+ #Limit the volume attributes we retrieve to the inode and space metrics
95+ api = NaElement ("volume-get-iter" )
96+
97+ xi = NaElement ("desired-attributes" )
98+ api .child_add (xi )
99+ api .child_add_string ("max-records" , "999" )
100+
101+
102+ xi1 = NaElement ("volume-attributes" )
103+ xi .child_add (xi1 )
104+
105+
106+ xi2 = NaElement ("volume-id-attributes" )
107+ xi1 .child_add (xi2 )
108+
109+ xi3 = NaElement ("volume-space-attributes" )
110+ xi1 .child_add (xi3 )
111+
112+ xi4 = NaElement ("volume-inode-attributes" )
113+ xi1 .child_add (xi4 )
114+
115+ out = na_server_obj .invoke_elem (api )
116+ if (out .results_status () == "failed" ):
117+ print ("Invoke failed: " + out .results_reason () + "\n " )
118+ sys .exit (2 )
119+
120+ vol_list = out .child_get ("attributes-list" )
121+ volumes = vol_list .children_get ()
122+
123+ self .volume_capacity_obj = volumes
124+
125+ return
126+
127+ def run (self ):
128+ self .filer_metrics = {}
129+ metric = self .MetricName
130+ filer = self .FilerName
131+ s = NaServer (filerdict [filer ]['ipaddr' ], 1 , 3 )
132+ out = s .set_transport_type ('HTTPS' )
133+ if (out and out .results_errno () != 0 ) :
134+ r = out .results_reason ()
135+ print ("Connection to filer failed: " + r + "\n " )
136+ sys .exit (2 )
137+
138+ out = s .set_style ('LOGIN' )
139+ if (out and out .results_errno () != 0 ) :
140+ r = out .results_reason ()
141+ print ("Connection to filer failed: " + r + "\n " )
142+ sys .exit (2 )
143+ out = s .set_admin_user (filerdict [filer ]['user' ], filerdict [filer ]['password' ])
144+
145+ #Get the volume performance metrics
146+ self .volume_perf_metrics (s )
147+ self .volume_capacity_metrics (s )
148+
104149 #Function within the class for updating the metrics
105150 def update_metrics (self ):
106151 clustername = self .ClusterName
107- print clustername
152+
108153 for inst in self .instances :
109154 inst_name = unicodedata .normalize ('NFKD' ,inst .child_get_string ("name" )).encode ('ascii' ,'ignore' )
110155 counters_list = inst .child_get ("counters" )
@@ -116,6 +161,30 @@ def update_metrics(self):
116161 counter_unit = counter .child_get_string ("unit" )
117162 self .filer_metrics [clustername + '_vol_' + inst_name + '_' + counter_name ] = float (counter_value )
118163
164+ for vol in self .volume_capacity_obj :
165+
166+ vol_id = vol .child_get ("volume-id-attributes" )
167+ vol_name = unicodedata .normalize ('NFKD' ,vol_id .child_get_string ("name" )).encode ('ascii' ,'ignore' )
168+ vserver_name = unicodedata .normalize ('NFKD' ,vol_id .child_get_string ("owning-vserver-name" )).encode ('ascii' ,'ignore' )
169+
170+ vol_inode = vol .child_get ("volume-inode-attributes" )
171+ vol_files_used = unicodedata .normalize ('NFKD' ,vol_inode .child_get_string ("files-used" )).encode ('ascii' ,'ignore' )
172+ vol_files_total = unicodedata .normalize ('NFKD' ,vol_inode .child_get_string ("files-total" )).encode ('ascii' ,'ignore' )
173+ vol_files_used_percent = float (vol_files_used ) / float (vol_files_total ) * 100
174+
175+ vol_space = vol .child_get ("volume-space-attributes" )
176+ vol_size_used = unicodedata .normalize ('NFKD' ,vol_space .child_get_string ("size-used" )).encode ('ascii' ,'ignore' )
177+ vol_size_total = unicodedata .normalize ('NFKD' ,vol_space .child_get_string ("size-total" )).encode ('ascii' ,'ignore' )
178+ vol_size_used_percent = float (vol_size_used ) / float (vol_size_total ) * 100
179+
180+ self .filer_metrics [clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'files_used' ] = float (vol_files_used )
181+ self .filer_metrics [clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'files_total' ] = float (vol_files_total )
182+ self .filer_metrics [clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'files_used_percent' ] = vol_files_used_percent
183+ self .filer_metrics [clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_used' ] = float (vol_size_used )
184+ self .filer_metrics [clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_total' ] = float (vol_size_total )
185+ self .filer_metrics [clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_used_percent' ] = vol_size_used_percent
186+
187+
119188 #Function within the class for defining the metrics for ganglia
120189 def define_metrics (self ,Desc_Skel ,params ):
121190
@@ -130,7 +199,7 @@ def define_metrics(self,Desc_Skel,params):
130199 counter_name = unicodedata .normalize ('NFKD' ,counter .child_get_string ("name" )).encode ('ascii' ,'ignore' )
131200 counter_value = counter .child_get_string ("value" )
132201 counter_unit = counter .child_get_string ("unit" )
133- print counter_name
202+
134203 if 'total_ops' in counter_name :
135204 descriptors .append (create_desc (Desc_Skel , {
136205 "name" : clustername + '_vol_' + inst_name + '_' + counter_name ,
@@ -180,6 +249,56 @@ def define_metrics(self,Desc_Skel,params):
180249 "groups" : "latency"
181250 }))
182251
252+
253+ for vol in self .volume_capacity_obj :
254+
255+ vol_id = vol .child_get ("volume-id-attributes" )
256+ vol_name = unicodedata .normalize ('NFKD' ,vol_id .child_get_string ("name" )).encode ('ascii' ,'ignore' )
257+ vserver_name = unicodedata .normalize ('NFKD' ,vol_id .child_get_string ("owning-vserver-name" )).encode ('ascii' ,'ignore' )
258+
259+ descriptors .append (create_desc (Desc_Skel , {
260+ "name" : clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'files_used' ,
261+ "units" : 'inodes' ,
262+ "description" : "volume files used" ,
263+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
264+ "groups" : "inodes"
265+ }))
266+ descriptors .append (create_desc (Desc_Skel , {
267+ "name" : clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'files_total' ,
268+ "units" : 'inodes' ,
269+ "description" : "volume files total" ,
270+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
271+ "groups" : "inodes"
272+ }))
273+ descriptors .append (create_desc (Desc_Skel , {
274+ "name" : clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'files_used_percent' ,
275+ "units" : 'percent' ,
276+ "description" : "volume inodes percent used" ,
277+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
278+ "groups" : "inodes"
279+ }))
280+ descriptors .append (create_desc (Desc_Skel , {
281+ "name" : clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_used' ,
282+ "units" : 'Bytes' ,
283+ "description" : "volume bytes used" ,
284+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
285+ "groups" : "capacity"
286+ }))
287+ descriptors .append (create_desc (Desc_Skel , {
288+ "name" : clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_total' ,
289+ "units" : 'Bytes' ,
290+ "description" : "volume size in bytes" ,
291+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
292+ "groups" : "capacity"
293+ }))
294+ descriptors .append (create_desc (Desc_Skel , {
295+ "name" : clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_used_percent' ,
296+ "units" : 'percent' ,
297+ "description" : "volume capacity percent used" ,
298+ "spoof_host" : params [filer ]['ipaddr' ] + ':' + params [filer ]['name' ],
299+ "groups" : "capacity"
300+ }))
301+
183302
184303def get_metrics (name ):
185304 global FASMETRICS , LAST_FASMETRICS , FASMETRICS_CACHE_MAX , params
@@ -266,7 +385,35 @@ def get_metrics(name):
266385 return float ((FASMETRICS ['data' ][name ] - LAST_FASMETRICS ['data' ][name ]) / (FASMETRICS ['data' ][write_ops_name ] - LAST_FASMETRICS ['data' ][write_ops_name ])) / 1000
267386 except StandardError :
268387 return 0
388+
389+ elif 'files_used' in name :
390+ try :
391+ result = float (FASMETRICS ['data' ][name ])
392+ except StandardError :
393+ result = 0
269394
395+ return result
396+ elif 'files_total' in name :
397+ try :
398+ result = float (FASMETRICS ['data' ][name ])
399+ except StandardError :
400+ result = 0
401+
402+ return result
403+
404+ elif 'size_used' in name :
405+ try :
406+ result = float (FASMETRICS ['data' ][name ])
407+ except StandardError :
408+ result = 0
409+ return result
410+
411+ elif 'size_total' in name :
412+ try :
413+ result = float (FASMETRICS ['data' ][name ])
414+ except StandardError :
415+ result = 0
416+ return result
270417
271418 return 0
272419
@@ -283,8 +430,9 @@ def create_desc(skel, prop):
283430
284431def define_metrics (Desc_Skel ,params ):
285432 global descriptors
286- ObjectTypeList = ["lif:vserver" ]
287- max_records = 10
433+ #ObjectTypeList = ["lif:vserver"]
434+ ObjectTypeList = ["volume" ]
435+
288436 threads = []
289437 for filer in params .keys ():
290438 #call define_metrics_thread as separate threads for each filer
@@ -309,12 +457,12 @@ def metric_init(params):
309457 'user' : 'username' ,
310458 'password' : 'password' ,
311459 },
312- 'filer2' : {
313- 'name' : 'cluster2.localdomain' ,
314- 'ipaddr' : '192.168.1 .100' ,
315- 'user' : 'username' ,
316- 'password' : 'password' ,
317- },
460+ 'filer2' : {
461+ 'name' : 'cluster2.localdomain' ,
462+ 'ipaddr' : '192.168.2 .100' ,
463+ 'user' : 'username' ,
464+ 'password' : 'password' ,
465+ },
318466 }
319467
320468 filerdict = dict (params )
0 commit comments