Skip to content

Commit f130c67

Browse files
committed
Added qtree quota metrics to the c-mode script
1 parent 1407362 commit f130c67

3 files changed

Lines changed: 71 additions & 8 deletions

File tree

netapp_api/README.mkdn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The API allows counter access to many more metrics than available through SNMP.
1010
This module currently gathers per volume Read/Write/Average IOPs and Latency and handles multiple filers/clusters
1111

1212
## Changelog
13+
* 03/04/2014 c-mode script now retrieves qtree quota metrics
1314
* 02/04/2014 c-mode script now gathers volume file and space metrics
1415
* 26/03/2014 c-mode script now does cluster api calls as separate threads
1516

netapp_api/conf.d/netapp_api_cmode.pyconf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@ collection_group {
2121
metric {
2222
name_match = "(.+)size_(.+)"
2323
}
24+
metric {
25+
name_match = "(.+)quota_used"
26+
}
2427

2528
}

netapp_api/python_modules/netapp_cmode_api.py

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
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
7+
#Updated 02/04/2014: Now retrieves per volume space and file(inode) metrics
8+
#Updated 03/04/2014: Now retrieves qtree quota usage metrics
89

910
import sys
1011
import time
@@ -37,8 +38,10 @@ def __init__(self, MetricName, FilerName):
3738
self.instances = None
3839
self.ClusterName = filerdict[self.FilerName]['name']
3940
self.volume_capacity_obj = None
41+
self.quota_obj = None
4042
super(GetMetricsThread, self).__init__()
4143

44+
4245
def volume_perf_metrics(self, s):
4346
# In class function to get volume perf metrics
4447

@@ -88,6 +91,29 @@ def volume_perf_metrics(self, s):
8891
instances = instances_list.children_get()
8992
self.instances = instances
9093

94+
def quota_metrics(self, s):
95+
na_server_obj = s
96+
97+
api = NaElement("quota-report-iter")
98+
api.child_add_string("max-records", "999")
99+
100+
out = na_server_obj.invoke_elem(api)
101+
if(out.results_status() == "failed"):
102+
print("Invoke failed: " + out.results_reason() + "\n")
103+
sys.exit(2)
104+
#pprint(out)
105+
num_records = out.child_get_string("num-records")
106+
107+
quota_list = out.child_get("attributes-list")
108+
109+
#Check if quota_list returned is empty, if so, skip quota metrics for this cluster
110+
if quota_list is None:
111+
return
112+
quotas = quota_list.children_get()
113+
self.quota_obj = quotas
114+
115+
return
116+
91117
def volume_capacity_metrics(self, s):
92118
# Function to perform API queries to get volume capacity metrics.
93119
na_server_obj = s
@@ -145,6 +171,7 @@ def run(self):
145171
#Get the volume performance metrics
146172
self.volume_perf_metrics(s)
147173
self.volume_capacity_metrics(s)
174+
self.quota_metrics(s)
148175

149176
#Function within the class for updating the metrics
150177
def update_metrics(self):
@@ -184,6 +211,17 @@ def update_metrics(self):
184211
self.filer_metrics[clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_total'] = float(vol_size_total)
185212
self.filer_metrics[clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_used_percent'] = vol_size_used_percent
186213

214+
215+
#Only do quota metrics if cluster actually has quotas enabled
216+
if self.quota_obj is not None:
217+
218+
for q in self.quota_obj:
219+
q_qtree_name = unicodedata.normalize('NFKD',unicode(q.child_get_string("tree"))).encode('ascii','ignore').replace(" ", "_")
220+
q_quota_used = unicodedata.normalize('NFKD',q.child_get_string("disk-used")).encode('ascii','ignore')
221+
q_vserver_name = unicodedata.normalize('NFKD',q.child_get_string("vserver")).encode('ascii','ignore')
222+
q_volume_name = unicodedata.normalize('NFKD',q.child_get_string("volume")).encode('ascii','ignore')
223+
self.filer_metrics[clustername + '_vol_' + q_vserver_name + '_' + q_volume_name + '_' + q_qtree_name + '_' + 'quota_used'] = float(q_quota_used)
224+
187225

188226
#Function within the class for defining the metrics for ganglia
189227
def define_metrics(self,Desc_Skel,params):
@@ -299,7 +337,22 @@ def define_metrics(self,Desc_Skel,params):
299337
"groups" : "capacity"
300338
}))
301339

302-
340+
if self.quota_obj is not None:
341+
for q in self.quota_obj:
342+
q_qtree_name = unicodedata.normalize('NFKD',unicode(q.child_get_string("tree"))).encode('ascii','ignore').replace(" ", "_")
343+
#q_quota_used = float(q.child_get_string("disk-used"))
344+
q_vserver_name = unicodedata.normalize('NFKD',q.child_get_string("vserver")).encode('ascii','ignore')
345+
q_volume_name = unicodedata.normalize('NFKD',q.child_get_string("volume")).encode('ascii','ignore')
346+
descriptors.append(create_desc(Desc_Skel, {
347+
"name" : clustername + '_vol_' + q_vserver_name + '_' + q_volume_name + '_' + q_qtree_name + '_' + 'quota_used',
348+
"units" : 'Bytes',
349+
"description" : "quota space used",
350+
"spoof_host" : params[filer]['ipaddr'] + ':' + params[filer]['name'],
351+
"groups" : "quotas"
352+
}))
353+
354+
#print q_qtree_name + " ",q_quota_used, " ", q_vserver_name, " ", q_volume_name
355+
303356
def get_metrics(name):
304357
global FASMETRICS, LAST_FASMETRICS, FASMETRICS_CACHE_MAX, params
305358
max_records = 10
@@ -414,6 +467,12 @@ def get_metrics(name):
414467
except StandardError:
415468
result = 0
416469
return result
470+
elif 'quota_used' in name:
471+
try:
472+
result = float(FASMETRICS['data'][name]) * 1024
473+
except StandardError:
474+
result = 0
475+
return result
417476

418477
return 0
419478

@@ -457,12 +516,12 @@ def metric_init(params):
457516
'user' : 'username',
458517
'password' : 'password',
459518
},
460-
'filer2' : {
461-
'name' : 'cluster2.localdomain',
462-
'ipaddr' : '192.168.2.100',
463-
'user' : 'username',
464-
'password' : 'password',
465-
},
519+
'filer2' : {
520+
'name' : 'cluster2.localdomain',
521+
'ipaddr' : '192.168.1.200',
522+
'user' : 'username',
523+
'password' : 'password',
524+
},
466525
}
467526

468527
filerdict = dict(params)

0 commit comments

Comments
 (0)