]> git.proxmox.com Git - pve-cluster.git/blob - data/PVE/RRD.pm
fix #4234: vzdump: add cluster-wide configuration
[pve-cluster.git] / data / PVE / RRD.pm
1 package PVE::RRD;
2
3 use strict; use warnings;
4
5 use RRDs;
6
7 use PVE::Tools;
8
9 sub create_rrd_data {
10 my ($rrdname, $timeframe, $cf) = @_;
11
12 my $rrddir = "/var/lib/rrdcached/db";
13
14 my $rrd = "$rrddir/$rrdname";
15
16 my $setup = {
17 hour => [ 60, 70 ],
18 day => [ 60*30, 70 ],
19 week => [ 60*180, 70 ],
20 month => [ 60*720, 70 ],
21 year => [ 60*10080, 70 ],
22 };
23
24 my ($reso, $count) = @{$setup->{$timeframe}};
25 my $ctime = $reso*int(time()/$reso);
26 my $req_start = $ctime - $reso*$count;
27
28 $cf = "AVERAGE" if !$cf;
29
30 my @args = (
31 "-s" => $req_start,
32 "-e" => $ctime - 1,
33 "-r" => $reso,
34 );
35
36 my $socket = "/var/run/rrdcached.sock";
37 push @args, "--daemon" => "unix:$socket" if -S $socket;
38
39 my ($start, $step, $names, $data) = RRDs::fetch($rrd, $cf, @args);
40
41 my $err = RRDs::error;
42 die "RRD error: $err\n" if $err;
43
44 die "got wrong time resolution ($step != $reso)\n"
45 if $step != $reso;
46
47 my $res = [];
48 my $fields = scalar(@$names);
49 for my $line (@$data) {
50 my $entry = { 'time' => $start };
51 $start += $step;
52 for (my $i = 0; $i < $fields; $i++) {
53 my $name = $names->[$i];
54 if (defined(my $val = $line->[$i])) {
55 $entry->{$name} = $val;
56 } else {
57 # leave empty fields undefined
58 # maybe make this configurable?
59 }
60 }
61 push @$res, $entry;
62 }
63
64 return $res;
65 }
66
67 sub create_rrd_graph {
68 my ($rrdname, $timeframe, $ds, $cf) = @_;
69
70 # Using RRD graph is clumsy - maybe it
71 # is better to simply fetch the data, and do all display
72 # related things with javascript (new extjs html5 graph library).
73
74 my $rrddir = "/var/lib/rrdcached/db";
75
76 my $rrd = "$rrddir/$rrdname";
77
78 my @ids = PVE::Tools::split_list($ds);
79
80 my $ds_txt = join('_', @ids);
81
82 my $filename = "${rrd}_${ds_txt}.png";
83
84 my $setup = {
85 hour => [ 60, 60 ],
86 day => [ 60*30, 70 ],
87 week => [ 60*180, 70 ],
88 month => [ 60*720, 70 ],
89 year => [ 60*10080, 70 ],
90 };
91
92 my ($reso, $count) = @{$setup->{$timeframe}};
93
94 my @args = (
95 "--imgformat" => "PNG",
96 "--border" => 0,
97 "--height" => 200,
98 "--width" => 800,
99 "--start" => - $reso*$count,
100 "--end" => 'now' ,
101 "--lower-limit" => 0,
102 );
103
104 my $socket = "/var/run/rrdcached.sock";
105 push @args, "--daemon" => "unix:$socket" if -S $socket;
106
107 my @coldef = ('#00ddff', '#ff0000');
108
109 $cf = "AVERAGE" if !$cf;
110
111 my $i = 0;
112 foreach my $id (@ids) {
113 my $col = $coldef[$i++] || die "fixme: no color definition";
114 push @args, "DEF:${id}=$rrd:${id}:$cf";
115 my $dataid = $id;
116 if ($id eq 'cpu' || $id eq 'iowait') {
117 push @args, "CDEF:${id}_per=${id},100,*";
118 $dataid = "${id}_per";
119 }
120 push @args, "LINE2:${dataid}${col}:${id}";
121 }
122
123 push @args, '--full-size-mode';
124
125 # we do not really store data into the file
126 my $res = RRDs::graphv('-', @args);
127
128 my $err = RRDs::error;
129 die "RRD error: $err\n" if $err;
130
131 return { filename => $filename, image => $res->{image} };
132 }
133
134 1;