Skip to content

Commit d9fd6ca

Browse files
committed
Added volume File (inode) and Space metrics to c-mode script
1 parent 5cb89c1 commit d9fd6ca

2 files changed

Lines changed: 183 additions & 28 deletions

File tree

netapp_api/conf.d/netapp_api_cmode.pyconf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,11 @@ collection_group {
1515
metric {
1616
name_match = "(.+)ops"
1717
}
18+
metric {
19+
name_match = "(.+)files_(.+)"
20+
}
21+
metric {
22+
name_match = "(.+)size_(.+)"
23+
}
24+
1825
}

netapp_api/python_modules/netapp_cmode_api.py

Lines changed: 176 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
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

89
import sys
910
import 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

184303
def 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

284431
def 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

Comments
 (0)