Projet

Général

Profil

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

root / plugins / openvz / openvzcpu @ eaf6c2d7

Historique | Voir | Annoter | Télécharger (7,89 ko)

1
#!/usr/bin/perl -w
2
# -*- perl -*-
3
# vim: sts=8 sw=8 ts=8
4

    
5
#
6
# Run "perldoc thisfilename" to get a well-formated set of documentation
7
# for this munin plugin.
8
#
9
=head1 NAME
10

    
11
openvzcpu - Munin plugin to monitor the amount of CPU used by each OpenVZ
12
container running on this machine.
13

    
14
=head2 SYNOPSIS
15

    
16
Draws a stacked graph showing system/user/nice CPU usage for each container
17
running on a OpenVZ hardware node.  Must be run from outside of any container
18
in order to gain access to the values generated by the OpenVZ kernel code in
19
C</proc/vz/vestat>
20

    
21
=head1 CONFIGURATION
22

    
23
The following perl libraries are used:
24

    
25
Graphics::ColorNames
26
Graphics::ColorObject
27

    
28
... on Debian based systems (i.e. Ubuntu etc.) you may just:
29

    
30
    aptitude install libcolor-calc-perl libgraphics-colorobject-perl
31

    
32
Must be run as root in order to read C</proc/vz/vestat>
33

    
34
Place the following in a file such as C</etc/munin/plugin-conf.d/openvzcpu>
35
B<and then restart munin-node>.
36

    
37
  [openvzcpu]
38
    user root
39

    
40
=head2 OPTIONS
41

    
42
The following may be added to the file above, in order to enable the graphing
43
of idle and iowait times:
44

    
45
    env.drawidle 1
46

    
47
For kernels which have other than 100 jiffies per second (sic) n.b. this is
48
unlikely to be necessary - you may add the followin to the plugin-specific
49
configuration:
50

    
51
    env.HZ 1000
52

    
53

    
54
If you have a high number of containers running on the machine, you may be
55
able to gain extra clarity by asking munin to create a "taller" graph by
56
adding the following to /etc/munin.conf, or in a file under
57
C</etc/munin/munin-conf.d/> if you are using Munin v1.4 or above:
58

    
59
    openvzcpu.graph_height 700
60

    
61
=head1 SEE ALSO
62

    
63
http://wiki.openvz.org/Vestat
64

    
65
=head1 TODO
66

    
67
. Add Munin 1.4 multigraph support
68

    
69
. Sort graphing order so that the smallest container is rendered at the
70
    bottom of the graph.
71

    
72
. Make the colour list into a configuration item.
73

    
74
. Fix graphing of non-container CPU usage.
75

    
76
=head1 VERSION
77

    
78
  0.6 Initial Public Release
79

    
80
=head1 AUTHOR
81

    
82
Tim Small <tim@seoss.co.uk>
83

    
84
Copyright 2010 South East Open Source Solutions Ltd.
85

    
86
The creation of this plugin was funded by Latitude Hosting
87

    
88
http://www.latitudehosting.net/
89

    
90
Patches welcome.
91

    
92
=head1 LICENSE
93

    
94
GPLv2
95

    
96
=begin comment
97

    
98
This program is free software; you can redistribute it and/or modify
99
it under the terms of the GNU General Public License as published by
100
the Free Software Foundation; version 2 dated June, 1991.
101

    
102
This program is distributed in the hope that it will be useful, but
103
WITHOUT ANY WARRANTY; without even the implied warranty of
104
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
105
General Public License for more details.
106

    
107
You should have received a copy of the GNU General Public License
108
along with this program; if not, write to the Free Software
109
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
110
USA.
111

    
112
=end comment
113

    
114
=head1 MAGIC MARKERS
115

    
116
  #%# family=auto
117
  #%# capabilities=autoconf
118

    
119
=cut
120

    
121
use strict;
122
use Carp;
123
use Graphics::ColorNames 2.10;
124
use Graphics::ColorObject;
125

    
126
my $vestat = '/proc/vz/vestat';
127
my $stat = '/proc/stat';
128

    
129
my @vestatitems = ('user', 'system', 'nice');
130

    
131
my @colorlist = ('purple', 'green', 'red', 'pink2', 'green', 'brown', 'cyan', 'orange', 'blue', 'grey');
132

    
133
############
134
# autoconf #
135
############
136

    
137
if ( defined $ARGV[0] && $ARGV[0] eq 'autoconf' ) {
138
	if ( -r '/proc/stat' && -r '/proc/vz/vestat' ) {
139
		print "yes\n";
140
	} else {
141
		print "no\n";
142
	}
143
	exit 0;
144
}
145

    
146
my $hz = 100;
147

    
148

    
149
#use Data::Dumper; croak Dumper(\%ENV);
150

    
151

    
152
$hz = $ENV{'HZ'} if ( defined $ENV{'HZ'} );
153

    
154
my $drawidle = 0;
155

    
156
$drawidle = $ENV{'drawidle'} if ( defined $ENV{'drawidle'} );
157

    
158
open VESTAT, "<$vestat" or croak "Failed to open $vestat\n";
159

    
160
my %vejif;
161

    
162
while (<VESTAT>) {
163
	my ($veid, $user, $nice, $system);
164
	($veid, $user, $nice, $system) = m,^\W+(\d+)\W+(\d+)\W+(\d+)\W+(\d+)\W+(\d+),;
165
	if (defined $veid) {
166
		$vejif{$veid}->{'user'} = $user;
167
		$vejif{$veid}->{'nice'} = $nice;
168
		$vejif{$veid}->{'system'} = $system;
169
	}
170
}
171

    
172
close VESTAT or croak "Failed to close $vestat\n";
173

    
174
open STAT, "<$stat" or croak "Failed to open $stat\n";
175

    
176
my $line = 0;
177
my $cores = 0;
178

    
179
while (<STAT>) {
180
	my ($user, $nice, $system, $idle, $iowait, $irq, $softirq);
181
	($user, $nice, $system, $idle, $iowait, $irq, $softirq) = m,^cpu\W+(\d+)\W+(\d+)\W+(\d+)\W+(\d+)\W+(\d+)\W+(\d+)\W+(\d+)\W+(\d+),;
182
	if (defined $user) {
183
		$vejif{'global'}->{'user'} = $user;
184
		$vejif{'global'}->{'nice'} = $nice;
185
		$vejif{'global'}->{'system'} = $system;
186
		$vejif{'global'}->{'idle'} = $idle;
187
		$vejif{'global'}->{'iowait'} = $iowait;
188
		$vejif{'global'}->{'irq'} = $irq;
189
		$vejif{'global'}->{'softirq'} = $softirq;
190
	}
191
	# Count number of CPU cores on this system while we are here
192
	$cores++ if m,cpu\d,;
193
}
194

    
195
$cores = 1 if $cores == 0;
196

    
197
foreach my $thing (@vestatitems) {
198
##FIXME  this doesn't appear to work on 2.6.32.  OpenVZ bug?
199
##	#Subtract total container usage from overall usage to get non-openvz
200
##      # usage (AKA VEID 0)
201
##	$vejif{'0'}->{$thing} = $vejif{'global'}->{$thing};
202
##	foreach my $veid (keys %vejif) {
203
##		next if $veid eq 'global';
204
##		$vejif{'0'}->{$thing} = $vejif{'0'}->{$thing} - $vejif{$veid}->{$thing};
205
##	}
206
	delete $vejif{'global'}->{$thing};
207
}
208

    
209

    
210
##########
211
# config #
212
##########
213

    
214
if ( defined $ARGV[0] && $ARGV[0] eq 'config' ) {
215
	my $uplimit = $cores;
216
	my $first = 1;
217
	my $veprocessed = 0;
218
#print 'graph_args --base 1000 -r --lower-limit 0 --units-length 4 --y-grid 0.01:10';
219
print 'graph_args --base 1000 -r --lower-limit 0 -Y';
220
print " --upper-limit $uplimit" if $drawidle;
221
print <<STDCONFIG;
222

    
223
graph_title OpenVZ container CPU usage
224
graph_vlabel CPU cores used ($cores available)
225
graph_scale no
226
graph_info This graph shows how CPU time is spent.
227
graph_category virtualization
228
graph_period second
229
STDCONFIG
230
	if (0) {
231
		print "graph_printf %6.3lf\n";
232
	}
233
	foreach my $veid (keys %vejif) {
234
		next if $veid eq 'global';
235
		my $color = $colorlist[$veprocessed++ % @colorlist];
236
		my $vename = `vzlist -H -o name $veid`;
237
		($vename) = ($vename =~ m,(\w*),);
238

    
239
		my $cnameobj = new Graphics::ColorNames(qw( X ));
240

    
241
		# Use LCHab colour space in order to be able to change the
242
		# Apparent brightness of the color (by scaling the "L"
243
		# component).  Convert back to RGB for munin.
244
		my @lchab = @{
245
			(Graphics::ColorObject->new_RGBhex(
246
				$cnameobj->hex($color)
247
			))->as_LCHab()
248
		};
249

    
250
		foreach my $item ('system', 'user', 'nice') {
251
			my @itemc;
252
			@itemc = @lchab;
253
			$itemc[0] = 1.3 * $itemc[0] if ($item eq 'nice');
254
			$itemc[0] = 0.7 * $itemc[0] if ($item eq 'system');
255
			my $itemcolor = Graphics::ColorObject->new_LCHab(\@itemc);
256
			print "v${veid}${item}.label $vename $item\n";
257
			if($first) {
258
				print "v${veid}${item}.draw AREA\n";
259
				$first = 0;
260
			} else {
261
				print "v${veid}${item}.draw STACK\n";
262
			}
263
			print "v${veid}${item}.colour " . $itemcolor->as_RGBhex() . "\n";
264
			print "v${veid}${item}.min 0\n";
265
			print "v${veid}${item}.type DERIVE\n";
266
			print "v${veid}${item}.cdef v${veid}${item},100,/\n";
267
		}
268
	}
269
	print <<STDCONFIG;
270
vglobalirq.label irq
271
vglobalirq.draw STACK
272
vglobalirq.min 0
273
vglobalirq.colour EEEE00
274
vglobalirq.type DERIVE
275
vglobalirq.cdef vglobalirq,100,/
276
vglobalirq.info CPU time spent handling interrupts
277
vglobalsoftirq.label softirq
278
vglobalsoftirq.draw STACK
279
vglobalsoftirq.min 0
280
vglobalsoftirq.colour CCCC00
281
vglobalsoftirq.type DERIVE
282
vglobalsoftirq.cdef vglobalsoftirq,100,/
283
vglobalsoftirq.info CPU time spent handling "batched" interrupts
284
STDCONFIG
285
if ($drawidle) {
286
	print <<STDCONFIG
287
vglobalidle.label idle
288
vglobalidle.draw STACK
289
vglobalidle.colour EEEEEE
290
vglobalidle.min 0
291
vglobalidle.type DERIVE
292
vglobalidle.cdef vglobalidle,100,/
293
vglobalidle.info Idle CPU time
294
vglobaliowait.label iowait
295
vglobaliowait.draw STACK
296
vglobaliowait.colour DDDDDD
297
vglobaliowait.min 0
298
vglobaliowait.type DERIVE
299
vglobaliowait.cdef vglobaliowait,100,/
300
vglobaliowait.info CPU time spent waiting for I/O operations to finish when there is nothing else to do.
301
STDCONFIG
302
	}
303
	exit 0;
304
}
305

    
306

    
307
foreach my $veid (keys %vejif) {
308
	foreach my $datapoint (keys %{$vejif{$veid}}) {
309
		printf "v${veid}${datapoint}.value %.0f\n", $vejif{$veid}->{$datapoint} / $hz * 100;
310
	}
311
}