| 1 | #/******************************************************************************* |
|---|
| 2 | #* Portions Copyright (C) 2007 Novell, Inc. All rights reserved. |
|---|
| 3 | #* |
|---|
| 4 | #* Redistribution and use in source and binary forms, with or without |
|---|
| 5 | #* modification, are permitted provided that the following conditions are met: |
|---|
| 6 | #* |
|---|
| 7 | #* - Redistributions of source code must retain the above copyright notice, |
|---|
| 8 | #* this list of conditions and the following disclaimer. |
|---|
| 9 | #* |
|---|
| 10 | #* - Redistributions in binary form must reproduce the above copyright notice, |
|---|
| 11 | #* this list of conditions and the following disclaimer in the documentation |
|---|
| 12 | #* and/or other materials provided with the distribution. |
|---|
| 13 | #* |
|---|
| 14 | #* - Neither the name of Novell, Inc. nor the names of its |
|---|
| 15 | #* contributors may be used to endorse or promote products derived from this |
|---|
| 16 | #* software without specific prior written permission. |
|---|
| 17 | #* |
|---|
| 18 | #* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' |
|---|
| 19 | #* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|---|
| 20 | #* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|---|
| 21 | #* ARE DISCLAIMED. IN NO EVENT SHALL Novell, Inc. OR THE CONTRIBUTORS |
|---|
| 22 | #* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|---|
| 23 | #* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|---|
| 24 | #* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|---|
| 25 | #* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|---|
| 26 | #* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|---|
| 27 | #* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|---|
| 28 | #* POSSIBILITY OF SUCH DAMAGE. |
|---|
| 29 | #* |
|---|
| 30 | #* Author: Brad Nicholes (bnicholes novell.com) |
|---|
| 31 | #******************************************************************************/ |
|---|
| 32 | |
|---|
| 33 | import statvfs |
|---|
| 34 | import os |
|---|
| 35 | import ganglia |
|---|
| 36 | |
|---|
| 37 | descriptors = list() |
|---|
| 38 | |
|---|
| 39 | def Find_Metric (name): |
|---|
| 40 | '''Find the metric definition data given the metric name. |
|---|
| 41 | The metric name should always be unique.''' |
|---|
| 42 | for d in descriptors: |
|---|
| 43 | if d['name'] == name: |
|---|
| 44 | return d |
|---|
| 45 | pass |
|---|
| 46 | |
|---|
| 47 | def Remote_Mount(device, type): |
|---|
| 48 | '''Determine if the device specifed is a local or remote device.''' |
|---|
| 49 | return ((device.rfind(':') != -1) |
|---|
| 50 | or ((type == "smbfs") and device.startswith('//')) |
|---|
| 51 | or type.startswith('nfs') or (type == 'autofs') |
|---|
| 52 | or (type == 'gfs') or (type == 'none')) |
|---|
| 53 | |
|---|
| 54 | def DiskTotal_Handler(name): |
|---|
| 55 | '''Calculate the total disk space for the device that is associated |
|---|
| 56 | with the metric name.''' |
|---|
| 57 | d = Find_Metric(name) |
|---|
| 58 | if not d: |
|---|
| 59 | return 0 |
|---|
| 60 | |
|---|
| 61 | st = os.statvfs(d['mount']) |
|---|
| 62 | size = st[statvfs.F_BLOCKS] |
|---|
| 63 | blocksize = st[statvfs.F_BSIZE] |
|---|
| 64 | vv = (size * blocksize) / 1e9 |
|---|
| 65 | return vv |
|---|
| 66 | |
|---|
| 67 | def DiskUsed_Handler(name): |
|---|
| 68 | '''Calculate the used disk space for the device that is associated |
|---|
| 69 | with the metric name.''' |
|---|
| 70 | d = Find_Metric(name) |
|---|
| 71 | if not d: |
|---|
| 72 | return float(0) |
|---|
| 73 | |
|---|
| 74 | st = os.statvfs(d['mount']) |
|---|
| 75 | free = st[statvfs.F_BAVAIL] |
|---|
| 76 | size = st[statvfs.F_BLOCKS] |
|---|
| 77 | |
|---|
| 78 | if size: |
|---|
| 79 | return ((size - free) / float(size)) * 100 |
|---|
| 80 | else: |
|---|
| 81 | return float(0) |
|---|
| 82 | |
|---|
| 83 | def Init_Metric (line, name, tmax, type, units, slope, fmt, desc, handler): |
|---|
| 84 | '''Create a metric definition dictionary object for a device.''' |
|---|
| 85 | metric_name = line[0] + '-' + name |
|---|
| 86 | |
|---|
| 87 | d = {'name': metric_name.replace('/', '-').lstrip('-'), |
|---|
| 88 | 'call_back': handler, |
|---|
| 89 | 'time_max': tmax, |
|---|
| 90 | 'value_type': type, |
|---|
| 91 | 'units': units, |
|---|
| 92 | 'slope': slope, |
|---|
| 93 | 'format': fmt, |
|---|
| 94 | 'description': desc, |
|---|
| 95 | 'groups': 'disk', |
|---|
| 96 | 'mount': line[1]} |
|---|
| 97 | return d |
|---|
| 98 | |
|---|
| 99 | |
|---|
| 100 | def metric_init(params): |
|---|
| 101 | '''Discover all of the local disk devices on the system and create |
|---|
| 102 | a metric definition dictionary object for each.''' |
|---|
| 103 | global descriptors |
|---|
| 104 | f = open('/proc/mounts', 'r') |
|---|
| 105 | |
|---|
| 106 | for l in f: |
|---|
| 107 | line = l.split() |
|---|
| 108 | if line[3].startswith('ro'): continue |
|---|
| 109 | elif Remote_Mount(line[0], line[2]): continue |
|---|
| 110 | elif (not line[0].startswith('/dev/')) and (not line[0].startswith('/dev2/')): continue; |
|---|
| 111 | |
|---|
| 112 | if ganglia.get_debug_msg_level() > 1: |
|---|
| 113 | print 'Discovered device %s' % line[1] |
|---|
| 114 | |
|---|
| 115 | descriptors.append(Init_Metric(line, 'disk_total', int(1200), |
|---|
| 116 | 'double', 'GB', 'both', '%.3f', |
|---|
| 117 | 'Available disk space', DiskTotal_Handler)) |
|---|
| 118 | descriptors.append(Init_Metric(line, 'disk_used', int(180), |
|---|
| 119 | 'float', '%', 'both', '%.1f', |
|---|
| 120 | 'Percent used disk space', DiskUsed_Handler)) |
|---|
| 121 | |
|---|
| 122 | f.close() |
|---|
| 123 | return descriptors |
|---|
| 124 | |
|---|
| 125 | def metric_cleanup(): |
|---|
| 126 | '''Clean up the metric module.''' |
|---|
| 127 | pass |
|---|
| 128 | |
|---|
| 129 | #This code is for debugging and unit testing |
|---|
| 130 | if __name__ == '__main__': |
|---|
| 131 | metric_init(None) |
|---|
| 132 | for d in descriptors: |
|---|
| 133 | v = d['call_back'](d['name']) |
|---|
| 134 | print 'value for %s is %f' % (d['name'], v) |
|---|