Skip to content

Commit acb4108

Browse files
committed
Added support for storing and displaying device names using the persistent (across reboots) and user friendly device mapper alias names
1 parent 6008baa commit acb4108

1 file changed

Lines changed: 124 additions & 7 deletions

File tree

diskstat/python_modules/diskstat.py

Lines changed: 124 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
import subprocess
4141
import traceback
4242
import logging
43+
import os
44+
import stat
4345

4446
descriptors = []
4547

@@ -61,8 +63,100 @@
6163

6264
PARTITIONS_FILE = '/proc/partitions'
6365
DISKSTATS_FILE = '/proc/diskstats'
66+
DMDIR = '/dev/mapper'
67+
device_mapper = ''
6468

6569
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
66160

67161
def get_partitions():
68162
logging.debug('getting partitions')
@@ -161,13 +255,22 @@ def update_stats():
161255
if not dev in last_val:
162256
last_val[dev] = {}
163257

258+
# Convert from dmname to devname for use by awk
259+
if device_mapper == 'true':
260+
olddev = dev
261+
dev = get_devname(dev)
262+
164263
# Get values from diskstats file
165264
p = subprocess.Popen("awk -v dev=" + dev + " '$3 == dev' " + DISKSTATS_FILE, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
166265
out, err = p.communicate()
167266

168267
vals = out.split()
169268
logging.debug(' vals: ' + str(vals))
170269

270+
# Reset back to orignal dev name
271+
if device_mapper == 'true':
272+
dev = olddev
273+
171274
get_diff(dev, 'reads', int(vals[3]))
172275
get_diff(dev, 'writes', int(vals[7]))
173276

@@ -267,10 +370,18 @@ def get_stat(name):
267370
return 0
268371

269372
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')
274385

275386
logging.debug('init: ' + str(params))
276387

@@ -371,13 +482,19 @@ def metric_cleanup():
371482
parser.add_option('-b', '--gmetric-bin', dest='gmetric_bin', default='/usr/bin/gmetric', help='path to gmetric binary')
372483
parser.add_option('-c', '--gmond-conf', dest='gmond_conf', default='/etc/ganglia/gmond.conf', help='path to gmond.conf')
373484
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')
374486
parser.add_option('-q', '--quiet', dest='quiet', action='store_true', default=False)
375487

376488
(options, args) = parser.parse_args()
377489

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+
})
381498

382499
while True:
383500
for d in descriptors:

0 commit comments

Comments
 (0)