Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / ceph / ceph-osd-info @ 8589c6df

Historique | Voir | Annoter | Télécharger (5,76 ko)

1
#!/usr/bin/python
2

    
3
"""
4
: << =cut
5

    
6
=head1 NAME
7

    
8
ceph osd stats by BTG
9

    
10
=head1 NOTES
11

    
12
I have no idea what I'm doing here
13

    
14
Usage:
15

    
16
$0 config
17
	show graphs that should be generated
18

    
19
$0
20
	show the data for the graphs
21

    
22
Place this in /etc/munin/plugins/ and munin should find it.
23

    
24
You may need to add "timeout 240" to /etc/munin/munin-node.conf and restart
25

    
26
=head1 AUTHOR
27

    
28
Jort Bloem
29

    
30
=head1 EXCUSES
31

    
32
This is one of the first programs I wrote in Python. I got carried away
33
by Python's powerful one-line commands. Just because you can, doesn't
34
mean you should. 
35

    
36
This program needs a rewrite, and if there were any problems with it,
37
I probably would.
38

    
39
=head1 LICENSE
40

    
41
Copyright (C) 2013 Business Technology Group (btg.co.nz)
42

    
43
Permission is granted to copy, distribute and/or modify this document
44
under the terms of the GNU Free Documentation License, Version 1.3
45
or any later version published by the Free Software Foundation;
46
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
47
A copy of the license is included in the section entitled "GNU
48
Free Documentation License".
49

    
50
If you wish to use this code on any other terms, please contact us
51
with your needs, we'll do what we can. This may not include payment.
52
We don't bite.
53

    
54
=head1 MAGIC MARKERS
55

    
56
 #%# capabilities=config
57

    
58
=cut
59
"""
60

    
61
import socket,os,json,sys,re,glob,itertools
62

    
63
# this overrides config values for specific graphs:
64
# "graphname.osd1":{"graph_title":"This is the graph for OSD 1!"}
65
# "graphname.osd*":{"graph_title":"This is one of the 'dig deeper' graphs!"}
66
# "graphname":{"graph_title":"This is my great graph!"}
67
#
68
# "graphname" overrides defaults, both for graphname and graphname.osd*
69
# "graphname.osd*" overrides graphname and defaults (for the sub-graphs), but cannot have the OSD number in it.
70
# "graphname.osd1" (or .osd2, or .osd3...) is the final setting for osd1 - may be needed if you want the number of the osd in it.
71
# if "graphname.osd*" and "graphname.osd1" are not used, all the settings will be the same as the parent graph,
72
#  except the title will have " - OSD 1" (or whichever osd it is) appended.
73
#
74
# Alternatively, "graph":None will hide a graph.
75

    
76
settings_graph={
77
#	"osd_opq":{"graph_title":"test"},
78
}
79

    
80

    
81
### BUG REPORT TODO README!
82
# If subgraph is true, then graphs for osd* are created individually.
83
# This causes the master (client) munin to take so long to update rrds that timeouts happen.
84
# Solutions:
85
# 1: set subgraph to false.
86
# 2: increase the timeout, wherever that is
87
# 3: return config, but no data, for individual graphs, so rrds aren't updated, then link individual rrds to their parent rrd.
88
# 4: change munin so which rrd file is used can be overridden
89
#
90
# option 1: add "timeout 240" to /etc/munin/munin-node.conf and restart
91

    
92
subgraphs=True
93

    
94
def read_osd(filename):
95
	for loop in range(10):
96
		try:
97
			s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
98
			s.connect(filename)
99
			s.send("{\"prefix\": \"perf dump\"}\0")
100
			result=s.recv(102400)
101
			result=result[4:]
102
			return json.loads(result)
103
		except:
104
			pass
105
		
106
	return None
107

    
108
def osd_list():
109
	result={}
110
	for osd in glob.glob("/var/run/ceph/ceph-osd.*.asok"):
111
		data=read_osd(osd)
112
		if data:
113
			result[osd.split(".")[1]]=data
114
	return result
115

    
116
def collapse_one(inputdict,newkeyformat="%s_%s"):
117
	"""map inputdict["a"]["b"]=val to outdict["a_b"]=val"""
118
	outdict={}
119
	for outer in inputdict.items():
120
		#print "outer => %s %s" % outer
121
		for inner in outer[1].items():
122
			outdict[newkeyformat % (outer[0],inner[0])]=inner[1]
123
	return outdict
124

    
125
def sortlist(listtosort):
126
	listtosort=list(listtosort)
127
	listtosort.sort()
128
	return listtosort
129

    
130
# get and tidy osd_list, get derived keys.
131
data=osd_list()
132
osds=[key for key in data.keys() if data[key]!=None]
133
osds.sort()
134
for key in osds:
135
	data[key]=collapse_one(data[key])
136

    
137
graphlist=[item[1].keys() for item in data.items()]+settings_graph.keys()
138
graphlist=list(set(itertools.chain(*graphlist)))
139

    
140
if (sys.argv.__len__()>1) and (sys.argv[1]=="config"):
141
	for graph in graphlist:
142
		if (graph not in settings_graph):
143
			graphsettings={}
144
		elif settings_graph[graph]==None:
145
			continue
146
		else:
147
			graphsettings=settings_graph[graph]
148
		gr_simple=graph.replace("-","_").replace(":","_")
149
		gr_pretty=graph.replace("_"," ").title()
150
		gr=graph.replace("-","_").replace(":","_")
151
		graphdefaults={"graph_title":gr_pretty,"graph_vlabel":gr_pretty,"graph_category":"osd"}
152
		graphsettings=dict(graphdefaults.items()+graphsettings.items())
153
		print "multigraph %s" % (gr_simple)
154
		print "\n".join(["%s %s" % setting for setting in graphsettings.items()])
155
		for osd in sortlist(data.keys()):
156
			print "osd%s_%s.label osd %s" % (osd,gr_simple,osd)
157
		if subgraphs:
158
			for osd in sortlist(data.keys()):
159
				print "multigraph %s.osd%s" % (gr_simple,osd)
160
				thisrecord=dict(graphsettings.items()+[("graph_title","%s - OSD %s" % (graphsettings["graph_title"],osd),)])
161
				#print thisrecord
162
				if ("%s.osd*" % (graph) in settings_graph):
163
					thisrecord=dict(thisrecord.items()+settings_graph["%s.osd%s" % (graph,osd)].items())
164
				if ("%s.osd%s" % (graph,osd) in settings_graph):
165
					thisrecord=dict(thisrecord.items()+settings_graph["%s.osd%s" % (graph,osd)].items())
166
				print "\n".join(["%s %s" % setting for setting in thisrecord.items()])
167
				print "osd%s_%s.label osd %s" % (osd,gr_simple,osd)
168
else:
169
	for graph in graphlist:
170
		gr=graph.replace("-","_").replace(":","_")
171
		print "multigraph %s" % gr
172
		for osd in osds:
173
			if type(data[osd][graph])==dict:
174
				if data[osd][graph]["avgcount"]==0:
175
					data[osd][graph]="NaN"
176
				else:
177
					data[osd][graph]=float(data[osd][graph]["sum"])/float(data[osd][graph]["avgcount"])
178
		for osd in osds:
179
			value=data[osd][graph]
180
			print "osd%s_%s.value %s" % (osd,gr,data[osd][graph])
181
		if subgraphs:
182
			for osd in osds:
183
				print "multigraph %s.osd%s" % (gr,osd)
184
				print "osd%s_%s.value %s" % (osd,gr,data[osd][graph])
185

    
186
# for Munin Plugin Gallery
187
# graph_category fs
188