root / plugins / virtualization / xen-multi @ e3899a30
Historique | Voir | Annoter | Télécharger (9,02 ko)
| 1 | 20afb679 | Rapha?l HALIMI | #! /usr/bin/perl |
|---|---|---|---|
| 2 | |||
| 3 | # -*- perl -*- |
||
| 4 | |||
| 5 | =head1 NAME |
||
| 6 | |||
| 7 | xen_multi - Munin multigraph plugin to monitor Xen domains activity |
||
| 8 | |||
| 9 | =head1 APPLICABLE SYSTEMS |
||
| 10 | |||
| 11 | This plugin should work on any system running a Xen hypervisor and where xentop |
||
| 12 | is installed. It also needs Munin 1.4.0 or higher, since it uses AREASTACK |
||
| 13 | (available from 1.3.3) and multigraph (available from 1.4.0). |
||
| 14 | |||
| 15 | =head1 CONFIGURATION |
||
| 16 | |||
| 17 | xentop requires superuser privileges, so you need to include in your |
||
| 18 | configuration: |
||
| 19 | |||
| 20 | 4a525a31 | Niall Donegan | [xen-multi] |
| 21 | 20afb679 | Rapha?l HALIMI | user root |
| 22 | 332c74d7 | ivan | env.xenskip "<space separated module list>" |
| 23 | |||
| 24 | Modules: cput, cpup, mem, disk, net |
||
| 25 | 20afb679 | Rapha?l HALIMI | |
| 26 | Then restart munin-node and you're done. |
||
| 27 | |||
| 28 | =head1 INTERPRETATION |
||
| 29 | |||
| 30 | This plugin produces four different graphs: CPU usage, memory usage, disk IOs |
||
| 31 | and network traffic. |
||
| 32 | |||
| 33 | In each graph, all Xen domains (including dom0) have their data stacked, giving |
||
| 34 | an overall amount of ressources used. |
||
| 35 | |||
| 36 | NOTE: xentop always reports 0 for dom0's disk IOs and network traffic, but |
||
| 37 | both graphs show its entry all the same, so each domain can keep its own color |
||
| 38 | along the different graphs. |
||
| 39 | |||
| 40 | 332c74d7 | ivan | =head2 CPU time |
| 41 | 20afb679 | Rapha?l HALIMI | |
| 42 | This graph shows a percentage of the CPU time used by each domain. |
||
| 43 | |||
| 44 | 332c74d7 | ivan | =head2 CPU usage |
| 45 | |||
| 46 | This graph shows a percentage of the CPU percentage used by each domain. |
||
| 47 | |||
| 48 | 20afb679 | Rapha?l HALIMI | =head2 Memory usage |
| 49 | |||
| 50 | This graph shows the amount of memory (in bytes) used by each domain. |
||
| 51 | |||
| 52 | =head2 Disk IOs |
||
| 53 | |||
| 54 | This graph shows the number of disk read and write operations for each domain. |
||
| 55 | |||
| 56 | =head2 Network traffic |
||
| 57 | |||
| 58 | This graph shows the amount of bits received and transmitted for each domain. |
||
| 59 | |||
| 60 | =head1 ACKNOWLEDGEMENTS |
||
| 61 | |||
| 62 | Michael Renner for the C<diskstats> plugin which I borrowed some code from. |
||
| 63 | |||
| 64 | =head1 VERSION |
||
| 65 | |||
| 66 | 0.90 |
||
| 67 | |||
| 68 | =head1 MAGIC MARKERS |
||
| 69 | |||
| 70 | #%# family=auto |
||
| 71 | #%# capabilities=autoconf |
||
| 72 | |||
| 73 | =head1 AUTHOR |
||
| 74 | |||
| 75 | Raphael HALIMI <raphael.halimi@gmail.com> |
||
| 76 | 332c74d7 | ivan | Modified by Krisztian IVANCSO <github-ivan@ivancso.net> |
| 77 | 20afb679 | Rapha?l HALIMI | |
| 78 | =head1 LICENSE |
||
| 79 | |||
| 80 | GPLv2 |
||
| 81 | |||
| 82 | =cut |
||
| 83 | |||
| 84 | use strict; |
||
| 85 | 1e301c2d | Alex Tomlins | use Munin::Plugin; |
| 86 | 20afb679 | Rapha?l HALIMI | |
| 87 | 332c74d7 | ivan | my $XEN_SKIP = $ENV{xenskip} || "";
|
| 88 | |||
| 89 | 20afb679 | Rapha?l HALIMI | # autoconf - quite simple |
| 90 | if ($ARGV[0] eq "autoconf") {
|
||
| 91 | if (`which xentop`) {
|
||
| 92 | print "yes\n"; |
||
| 93 | } else {
|
||
| 94 | print "no (xentop not found)\n"; |
||
| 95 | } |
||
| 96 | exit 0; |
||
| 97 | } |
||
| 98 | |||
| 99 | |||
| 100 | # |
||
| 101 | # Common steps for both "config" and a normal run |
||
| 102 | # |
||
| 103 | |||
| 104 | # |
||
| 105 | # trim_label |
||
| 106 | # |
||
| 107 | # Trims a given label to it's non-wrapping size |
||
| 108 | # $type = 'pos' for normal graphs and 'neg' for mirror graphs |
||
| 109 | # pos: nnn.nnU_ times 4 |
||
| 110 | # neg: nnn.nnU/nnn.nnU_ times 4 |
||
| 111 | |||
| 112 | sub trim_label {
|
||
| 113 | my ($type, $label) = @_; my $data_characters; |
||
| 114 | 332c74d7 | ivan | my ($graph_width, $graph_border_width, $padding_characters, $pixels_per_character) = (497,3,5,6); |
| 115 | 20afb679 | Rapha?l HALIMI | if ($type eq 'pos') {$data_characters = 32;} elsif ($type eq 'neg') {$data_characters = 64;} else {return $label;}
|
| 116 | |||
| 117 | my $available_characters = abs(($graph_width+$graph_border_width)/$pixels_per_character)-$padding_characters-$data_characters; |
||
| 118 | |||
| 119 | # If the label is longer than the available space, we write as many |
||
| 120 | # characters as we can on both left and right, and two dots in the middle |
||
| 121 | if ( $available_characters < length $label ) {
|
||
| 122 | my $center = ($available_characters-2)/2; |
||
| 123 | $label = substr($label,0,($center)) . '..' . substr($label,-$center); |
||
| 124 | } |
||
| 125 | |||
| 126 | return $label; |
||
| 127 | } |
||
| 128 | |||
| 129 | # Global variables |
||
| 130 | 332c74d7 | ivan | my (%domains,$domain,@domainlist,$munindomain,$cpusecs,$cpupercent,$memk,$nettxk,$netrxk,$vbdrd,$vbdwr); |
| 131 | 20afb679 | Rapha?l HALIMI | |
| 132 | 332c74d7 | ivan | open (XENTOP,"xentop -b -f -i2 |") or die "Could not execute xentop, $!"; |
| 133 | 20afb679 | Rapha?l HALIMI | |
| 134 | # Now we build a hash of hashes to store information |
||
| 135 | 1e301c2d | Alex Tomlins | while (<XENTOP>) {
|
| 136 | 20afb679 | Rapha?l HALIMI | # Some cleaning first |
| 137 | s/^\s+//; chomp; |
||
| 138 | 1e301c2d | Alex Tomlins | # Skip the headers |
| 139 | next if /^NAME/; |
||
| 140 | |||
| 141 | # We define only what we need |
||
| 142 | 332c74d7 | ivan | ($domain,undef,$cpusecs,$cpupercent,$memk,undef,undef,undef,undef,undef,$nettxk,$netrxk,undef,undef,$vbdrd,$vbdwr,undef,undef,undef) = split(/\s+/); |
| 143 | 1e301c2d | Alex Tomlins | |
| 144 | # We have to store the sanitised domain name in a separate variable |
||
| 145 | $domains{$domain}{'munindomain'} = clean_fieldname($domain);
|
||
| 146 | |||
| 147 | # We need the remaining data only for a normal run |
||
| 148 | if ($ARGV[0] eq "") {
|
||
| 149 | $domains{$domain}{'cpusecs'} = $cpusecs;
|
||
| 150 | 332c74d7 | ivan | $domains{$domain}{'cpupercent'} = $cpupercent;
|
| 151 | 1e301c2d | Alex Tomlins | $domains{$domain}{'mem'} = $memk;
|
| 152 | $domains{$domain}{'nettx'} = $nettxk;
|
||
| 153 | $domains{$domain}{'netrx'} = $netrxk;
|
||
| 154 | $domains{$domain}{'vbdrd'} = $vbdrd;
|
||
| 155 | $domains{$domain}{'vbdwr'} = $vbdwr;
|
||
| 156 | 20afb679 | Rapha?l HALIMI | } |
| 157 | } |
||
| 158 | |||
| 159 | 332c74d7 | ivan | @domainlist = sort(keys(%domains)); |
| 160 | 20afb679 | Rapha?l HALIMI | |
| 161 | # |
||
| 162 | # config - quite simple, too |
||
| 163 | # |
||
| 164 | |||
| 165 | if ($ARGV[0] eq "config") {
|
||
| 166 | 332c74d7 | ivan | if ($XEN_SKIP !~ /cput/) {
|
| 167 | print "multigraph xen_cpu_time\n"; |
||
| 168 | print "graph_title Xen domains CPU time\n"; |
||
| 169 | print "graph_args --base 1000 -l 0\n"; |
||
| 170 | print "graph_vlabel cpu seconds\n"; |
||
| 171 | print "graph_scale no\n"; |
||
| 172 | e3899a30 | Gabriele Pohl | print "graph_category Virtualization\n"; |
| 173 | 332c74d7 | ivan | print "graph_info This graph shows CPU time for each Xen domain.\n"; |
| 174 | for $domain (@domainlist) {
|
||
| 175 | print "$domains{$domain}{'munindomain'}_cpu_time.label ".trim_label('pos',$domain)."\n";
|
||
| 176 | print "$domains{$domain}{'munindomain'}_cpu_time.type DERIVE\n";
|
||
| 177 | print "$domains{$domain}{'munindomain'}_cpu_time.cdef $domains{$domain}{'munindomain'}_cpu_time,100,*\n";
|
||
| 178 | print "$domains{$domain}{'munindomain'}_cpu_time.min 0\n";
|
||
| 179 | print "$domains{$domain}{'munindomain'}_cpu_time.draw AREASTACK\n";
|
||
| 180 | } |
||
| 181 | 20afb679 | Rapha?l HALIMI | } |
| 182 | |||
| 183 | 332c74d7 | ivan | if ($XEN_SKIP !~ /cpup/) {
|
| 184 | print "\nmultigraph xen_cpu\n"; |
||
| 185 | print "graph_title Xen domains CPU utilization\n"; |
||
| 186 | print "graph_args --base 1000 -l 0 --upper-limit 100\n"; |
||
| 187 | print "graph_vlabel %\n"; |
||
| 188 | print "graph_scale no\n"; |
||
| 189 | e3899a30 | Gabriele Pohl | print "graph_category Virtualization\n"; |
| 190 | 332c74d7 | ivan | print "graph_info This graph shows CPU utilization for each Xen domain.\n"; |
| 191 | for $domain (@domainlist) {
|
||
| 192 | print "$domains{$domain}{'munindomain'}_cpu.label ".trim_label('pos',$domain)."\n";
|
||
| 193 | print "$domains{$domain}{'munindomain'}_cpu.draw AREASTACK\n"
|
||
| 194 | } |
||
| 195 | 20afb679 | Rapha?l HALIMI | } |
| 196 | |||
| 197 | 332c74d7 | ivan | if ($XEN_SKIP !~ /mem/) {
|
| 198 | print "\nmultigraph xen_mem\n"; |
||
| 199 | print "graph_title Xen domains memory usage\n"; |
||
| 200 | print "graph_args --base 1024 -l 0\n"; |
||
| 201 | print "graph_vlabel bytes\n"; |
||
| 202 | e3899a30 | Gabriele Pohl | print "graph_category Virtualization\n"; |
| 203 | 332c74d7 | ivan | print "graph_info This graph shows memory usage for each Xen domain.\n"; |
| 204 | for $domain (@domainlist) {
|
||
| 205 | print "$domains{$domain}{'munindomain'}_mem.label ".trim_label('pos',$domain)."\n";
|
||
| 206 | print "$domains{$domain}{'munindomain'}_mem.cdef $domains{$domain}{'munindomain'}_mem,1024,*\n";
|
||
| 207 | print "$domains{$domain}{'munindomain'}_mem.draw AREASTACK\n";
|
||
| 208 | } |
||
| 209 | 20afb679 | Rapha?l HALIMI | } |
| 210 | |||
| 211 | 332c74d7 | ivan | if ($XEN_SKIP !~ /net/) {
|
| 212 | print "\nmultigraph xen_net\n"; |
||
| 213 | print "graph_title Xen domains network traffic\n"; |
||
| 214 | print "graph_args --base 1000\n"; |
||
| 215 | print "graph_vlabel bits per \${graph_period} in (-) / out (+)\n";
|
||
| 216 | e3899a30 | Gabriele Pohl | print "graph_category Virtualization\n"; |
| 217 | 332c74d7 | ivan | print "graph_info This graph shows network traffic for each Xen domain.\n"; |
| 218 | for $domain (@domainlist) {
|
||
| 219 | print "$domains{$domain}{'munindomain'}_netrx.label none\n";
|
||
| 220 | print "$domains{$domain}{'munindomain'}_netrx.cdef $domains{$domain}{'munindomain'}_netrx,8192,*\n";
|
||
| 221 | print "$domains{$domain}{'munindomain'}_netrx.type COUNTER\n";
|
||
| 222 | print "$domains{$domain}{'munindomain'}_netrx.graph no\n";
|
||
| 223 | print "$domains{$domain}{'munindomain'}_nettx.label ".trim_label('neg',$domain)."\n";
|
||
| 224 | print "$domains{$domain}{'munindomain'}_nettx.cdef $domains{$domain}{'munindomain'}_nettx,8192,*\n";
|
||
| 225 | print "$domains{$domain}{'munindomain'}_nettx.type COUNTER\n";
|
||
| 226 | print "$domains{$domain}{'munindomain'}_nettx.draw AREASTACK\n";
|
||
| 227 | print "$domains{$domain}{'munindomain'}_nettx.negative $domains{$domain}{'munindomain'}_netrx\n";
|
||
| 228 | } |
||
| 229 | } |
||
| 230 | |||
| 231 | if ($XEN_SKIP !~ /disk/) {
|
||
| 232 | print "\nmultigraph xen_disk\n"; |
||
| 233 | print "graph_title Xen domains disk IOs\n"; |
||
| 234 | print "graph_args --base 1000\n"; |
||
| 235 | print "graph_vlabel IOs per \${graph_period} read (-) / write (+)\n";
|
||
| 236 | e3899a30 | Gabriele Pohl | print "graph_category Virtualization\n"; |
| 237 | 332c74d7 | ivan | print "graph_info This graph shows disk IOs for each Xen domain.\n"; |
| 238 | for $domain (@domainlist) {
|
||
| 239 | print "$domains{$domain}{'munindomain'}_vbdrd.label none\n";
|
||
| 240 | print "$domains{$domain}{'munindomain'}_vbdrd.type COUNTER\n";
|
||
| 241 | print "$domains{$domain}{'munindomain'}_vbdrd.graph no\n";
|
||
| 242 | print "$domains{$domain}{'munindomain'}_vbdwr.label ".trim_label('neg',$domain)."\n";
|
||
| 243 | print "$domains{$domain}{'munindomain'}_vbdwr.type COUNTER\n";
|
||
| 244 | print "$domains{$domain}{'munindomain'}_vbdwr.draw AREASTACK\n";
|
||
| 245 | print "$domains{$domain}{'munindomain'}_vbdwr.negative $domains{$domain}{'munindomain'}_vbdrd\n";
|
||
| 246 | } |
||
| 247 | 20afb679 | Rapha?l HALIMI | } |
| 248 | |||
| 249 | exit 0; |
||
| 250 | } |
||
| 251 | |||
| 252 | |||
| 253 | # |
||
| 254 | # Normal run |
||
| 255 | # |
||
| 256 | |||
| 257 | 332c74d7 | ivan | if ($XEN_SKIP !~ /cput/) {
|
| 258 | print "multigraph xen_cpu_time\n"; |
||
| 259 | for $domain (@domainlist) {
|
||
| 260 | print "$domains{$domain}{'munindomain'}_cpu_time.value $domains{$domain}{'cpusecs'}\n";
|
||
| 261 | } |
||
| 262 | 20afb679 | Rapha?l HALIMI | } |
| 263 | |||
| 264 | 332c74d7 | ivan | if ($XEN_SKIP !~ /cpup/) {
|
| 265 | print "\nmultigraph xen_cpu\n"; |
||
| 266 | for $domain (@domainlist) {
|
||
| 267 | print "$domains{$domain}{'munindomain'}_cpu.value $domains{$domain}{'cpupercent'}\n";
|
||
| 268 | } |
||
| 269 | 20afb679 | Rapha?l HALIMI | } |
| 270 | |||
| 271 | 332c74d7 | ivan | if ($XEN_SKIP !~ /mem/) {
|
| 272 | print "\nmultigraph xen_mem\n"; |
||
| 273 | for $domain (@domainlist) {
|
||
| 274 | print "$domains{$domain}{'munindomain'}_mem.value $domains{$domain}{'mem'}\n";
|
||
| 275 | } |
||
| 276 | 20afb679 | Rapha?l HALIMI | } |
| 277 | |||
| 278 | 332c74d7 | ivan | if ($XEN_SKIP !~ /net/) {
|
| 279 | print "\nmultigraph xen_net\n"; |
||
| 280 | for $domain (@domainlist) {
|
||
| 281 | print "$domains{$domain}{'munindomain'}_nettx.value $domains{$domain}{'nettx'}\n";
|
||
| 282 | print "$domains{$domain}{'munindomain'}_netrx.value $domains{$domain}{'netrx'}\n";
|
||
| 283 | } |
||
| 284 | 20afb679 | Rapha?l HALIMI | } |
| 285 | 332c74d7 | ivan | |
| 286 | if ($XEN_SKIP !~ /disk/) {
|
||
| 287 | print "\nmultigraph xen_disk\n"; |
||
| 288 | for $domain (@domainlist) {
|
||
| 289 | print "$domains{$domain}{'munindomain'}_vbdrd.value $domains{$domain}{'vbdrd'}\n";
|
||
| 290 | print "$domains{$domain}{'munindomain'}_vbdwr.value $domains{$domain}{'vbdwr'}\n";
|
||
| 291 | } |
||
| 292 | } |
