|
4 | 4 | #Author: Evan Fraser <[email protected]> |
5 | 5 | #Date: 13/08/2012 |
6 | 6 | #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 |
8 | 9 |
|
9 | 10 | import sys |
10 | 11 | import time |
@@ -37,8 +38,10 @@ def __init__(self, MetricName, FilerName): |
37 | 38 | self.instances = None |
38 | 39 | self.ClusterName = filerdict[self.FilerName]['name'] |
39 | 40 | self.volume_capacity_obj = None |
| 41 | + self.quota_obj = None |
40 | 42 | super(GetMetricsThread, self).__init__() |
41 | 43 |
|
| 44 | + |
42 | 45 | def volume_perf_metrics(self, s): |
43 | 46 | # In class function to get volume perf metrics |
44 | 47 |
|
@@ -88,6 +91,29 @@ def volume_perf_metrics(self, s): |
88 | 91 | instances = instances_list.children_get() |
89 | 92 | self.instances = instances |
90 | 93 |
|
| 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 | + |
91 | 117 | def volume_capacity_metrics(self, s): |
92 | 118 | # Function to perform API queries to get volume capacity metrics. |
93 | 119 | na_server_obj = s |
@@ -145,6 +171,7 @@ def run(self): |
145 | 171 | #Get the volume performance metrics |
146 | 172 | self.volume_perf_metrics(s) |
147 | 173 | self.volume_capacity_metrics(s) |
| 174 | + self.quota_metrics(s) |
148 | 175 |
|
149 | 176 | #Function within the class for updating the metrics |
150 | 177 | def update_metrics(self): |
@@ -184,6 +211,17 @@ def update_metrics(self): |
184 | 211 | self.filer_metrics[clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_total'] = float(vol_size_total) |
185 | 212 | self.filer_metrics[clustername + '_vol_' + vserver_name + '_' + vol_name + '_' + 'size_used_percent'] = vol_size_used_percent |
186 | 213 |
|
| 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 | + |
187 | 225 |
|
188 | 226 | #Function within the class for defining the metrics for ganglia |
189 | 227 | def define_metrics(self,Desc_Skel,params): |
@@ -299,7 +337,22 @@ def define_metrics(self,Desc_Skel,params): |
299 | 337 | "groups" : "capacity" |
300 | 338 | })) |
301 | 339 |
|
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 | + |
303 | 356 | def get_metrics(name): |
304 | 357 | global FASMETRICS, LAST_FASMETRICS, FASMETRICS_CACHE_MAX, params |
305 | 358 | max_records = 10 |
@@ -414,6 +467,12 @@ def get_metrics(name): |
414 | 467 | except StandardError: |
415 | 468 | result = 0 |
416 | 469 | 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 |
417 | 476 |
|
418 | 477 | return 0 |
419 | 478 |
|
@@ -457,12 +516,12 @@ def metric_init(params): |
457 | 516 | 'user' : 'username', |
458 | 517 | 'password' : 'password', |
459 | 518 | }, |
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 | + }, |
466 | 525 | } |
467 | 526 |
|
468 | 527 | filerdict = dict(params) |
|
0 commit comments