|
40 | 40 | import subprocess |
41 | 41 | import traceback |
42 | 42 | import logging |
| 43 | +import os |
| 44 | +import stat |
43 | 45 |
|
44 | 46 | descriptors = [] |
45 | 47 |
|
|
61 | 63 |
|
62 | 64 | PARTITIONS_FILE = '/proc/partitions' |
63 | 65 | DISKSTATS_FILE = '/proc/diskstats' |
| 66 | +DMDIR = '/dev/mapper' |
| 67 | +device_mapper = '' |
64 | 68 |
|
65 | 69 | PARTITIONS = [] |
| 70 | +dmnames = [] |
| 71 | +dm2pair = {} |
| 72 | +pair2dm = {} |
| 73 | +devnames = [] |
| 74 | +dev2pair = {} |
| 75 | +pair2dev = {} |
| 76 | + |
| 77 | +def build_dmblock_major_minor_tables(): |
| 78 | + """Returns |
| 79 | + 1) a table of filenames that are all device mapper block special files |
| 80 | + 2) a dict mapping each device mapper name to (major,minor) |
| 81 | + 3) a dict mapping each (major,minor) pair to a table of devce mapper names""" |
| 82 | + |
| 83 | + names = [] |
| 84 | + name2pair = {} |
| 85 | + pair2name = {} |
| 86 | + mapper_entries = [] |
| 87 | + |
| 88 | + mapper_entries = os.listdir(DMDIR) |
| 89 | + for n in mapper_entries: |
| 90 | + s = os.lstat(DMDIR + '/' + n) |
| 91 | + if stat.S_ISBLK(s[stat.ST_MODE]): |
| 92 | + names.append(n) |
| 93 | + maj = str(os.major(s.st_rdev)) |
| 94 | + min = str(os.minor(s.st_rdev)) |
| 95 | + name2pair[n] = (maj, min) |
| 96 | + pair2name[(maj, min)] = n |
| 97 | + |
| 98 | + logging.debug('grabbed dmsetup device info') |
| 99 | + logging.debug('dmsetup devices: ' + str(name2pair)) |
| 100 | + |
| 101 | + return (names, name2pair, pair2name) |
| 102 | + |
| 103 | +def build_block_major_minor_tables(): |
| 104 | + """Returns |
| 105 | + 1) a table of filenames that are all block special files |
| 106 | + 2) a dict mapping each dev name to (major,minor) |
| 107 | + 3) a dict mapping each (major,minor) pair to a table of dev names""" |
| 108 | + dnames = [] |
| 109 | + d2p = {} |
| 110 | + p2d = {} |
| 111 | + |
| 112 | + # Get values from diskstats file |
| 113 | + p = subprocess.Popen("awk '{print $1,$2, $3}' " + DISKSTATS_FILE, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 114 | + out, err = p.communicate() |
| 115 | + |
| 116 | + logging.debug('grabbed diskstat device info') |
| 117 | + logging.debug('diskstat devices: ' + str(out)) |
| 118 | + |
| 119 | + for n in out.split('\n'): |
| 120 | + if n: |
| 121 | + [maj, min, name] = n.split() |
| 122 | + dnames.append(name) |
| 123 | + d2p[name] = (maj, min) |
| 124 | + p2d[(maj, min)] = name |
| 125 | + |
| 126 | + return (dnames, d2p, p2d) |
| 127 | + |
| 128 | +def get_devname(dev): |
| 129 | + """Returns |
| 130 | + device mapper name converted to dev name""" |
| 131 | + |
| 132 | + (maj,min) = dm2pair[dev] |
| 133 | + name = pair2dev[(maj,min)] |
| 134 | + return name |
| 135 | + |
| 136 | +def list_dmnames(): |
| 137 | + """Returns |
| 138 | + string of device names associated with device mapper names""" |
| 139 | + |
| 140 | + global dmnames |
| 141 | + global dm2pair |
| 142 | + global pair2dm |
| 143 | + global devnames |
| 144 | + global dev2pair |
| 145 | + global pair2dev |
| 146 | + devlist = '' |
| 147 | + |
| 148 | + dmnames, dm2pair, pair2dm = build_dmblock_major_minor_tables() |
| 149 | + logging.debug('dmnames: ' + str(dmnames)) |
| 150 | + |
| 151 | + devnames, dev2pair, pair2dev = build_block_major_minor_tables() |
| 152 | + logging.debug('devnames: ' + str(dmnames)) |
| 153 | + |
| 154 | + for d in dmnames: |
| 155 | + devlist = devlist + ' ' + str(d) |
| 156 | + |
| 157 | + logging.debug('devlist: ' + str(devlist)) |
| 158 | + |
| 159 | + return devlist |
66 | 160 |
|
67 | 161 | def get_partitions(): |
68 | 162 | logging.debug('getting partitions') |
@@ -161,13 +255,22 @@ def update_stats(): |
161 | 255 | if not dev in last_val: |
162 | 256 | last_val[dev] = {} |
163 | 257 |
|
| 258 | + # Convert from dmname to devname for use by awk |
| 259 | + if device_mapper == 'true': |
| 260 | + olddev = dev |
| 261 | + dev = get_devname(dev) |
| 262 | + |
164 | 263 | # Get values from diskstats file |
165 | 264 | p = subprocess.Popen("awk -v dev=" + dev + " '$3 == dev' " + DISKSTATS_FILE, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
166 | 265 | out, err = p.communicate() |
167 | 266 |
|
168 | 267 | vals = out.split() |
169 | 268 | logging.debug(' vals: ' + str(vals)) |
170 | 269 |
|
| 270 | + # Reset back to orignal dev name |
| 271 | + if device_mapper == 'true': |
| 272 | + dev = olddev |
| 273 | + |
171 | 274 | get_diff(dev, 'reads', int(vals[3])) |
172 | 275 | get_diff(dev, 'writes', int(vals[7])) |
173 | 276 |
|
@@ -267,10 +370,18 @@ def get_stat(name): |
267 | 370 | return 0 |
268 | 371 |
|
269 | 372 | def metric_init(params): |
270 | | - global descriptors |
271 | | - global MIN_DISK_SIZE, DEVICES |
272 | | - |
273 | | - DEVICES = params.get('devices') |
| 373 | + global descriptors, device_mapper |
| 374 | + global MIN_DISK_SIZE, DEVICES, IGNORE_DEV |
| 375 | + |
| 376 | + # Use params.get here to assure function via gmond |
| 377 | + if params.get('device-mapper') == 'true': |
| 378 | + devices = list_dmnames() |
| 379 | + DEVICES = devices |
| 380 | + IGNORE_DEV = 'loop|drbd' |
| 381 | + device_mapper = 'true' |
| 382 | + logging.debug('dm block devices: ' + str(devices)) |
| 383 | + else: |
| 384 | + DEVICES = params.get('devices') |
274 | 385 |
|
275 | 386 | logging.debug('init: ' + str(params)) |
276 | 387 |
|
@@ -371,13 +482,19 @@ def metric_cleanup(): |
371 | 482 | parser.add_option('-b', '--gmetric-bin', dest='gmetric_bin', default='/usr/bin/gmetric', help='path to gmetric binary') |
372 | 483 | parser.add_option('-c', '--gmond-conf', dest='gmond_conf', default='/etc/ganglia/gmond.conf', help='path to gmond.conf') |
373 | 484 | parser.add_option('-g', '--gmetric', dest='gmetric', action='store_true', default=False, help='submit via gmetric') |
| 485 | + parser.add_option('-m', '--device-mapper', dest='device_mapper', action='store_true', default=False, help='utilize all device mapper devices if set') |
374 | 486 | parser.add_option('-q', '--quiet', dest='quiet', action='store_true', default=False) |
375 | 487 |
|
376 | 488 | (options, args) = parser.parse_args() |
377 | 489 |
|
378 | | - metric_init({ |
379 | | - 'devices': options.devices, |
380 | | - }) |
| 490 | + if options.device_mapper: |
| 491 | + metric_init({ |
| 492 | + 'device-mapper': 'true', |
| 493 | + }) |
| 494 | + else: |
| 495 | + metric_init({ |
| 496 | + 'devices': options.devices, |
| 497 | + }) |
381 | 498 |
|
382 | 499 | while True: |
383 | 500 | for d in descriptors: |
|
0 commit comments