Project

General

Profile

Download (6.7 KB) Statistics
| Branch: | Revision:

root / indexmrtg.cgi @ master

1
#!/usr/bin/perl
2
#
3
# Generate a machine readable index from mrtg.cfg inputs
4
#
5

    
6
our $VERSION=0.6;
7

    
8
use strict;
9
use warnings;
10

    
11
use FileHandle;
12

    
13
use JSON;
14

    
15
use Data::Dumper;
16
$Data::Dumper::Indent = 1;
17
$Data::Dumper::Sortkeys = 1;
18

    
19
use CGI ':all';
20
use CGI::Carp qw(fatalsToBrowser);
21
use Sys::Hostname;
22

    
23
use HTML::Entities();
24

    
25
# List of config files to search for
26
my @config_files = (
27
	'/etc/mrtg.cfg',
28
	'/usr/share/WWW/mrtg/mrtg.cfg',
29
);
30

    
31
# FIXME - globals
32
my $warnings;
33
my $db = {};	# storage for all tests found
34

    
35
$db->{global}{graph}{mtime} = 0; # Scan for newest graph and save info for later
36
$db->{hide}{mrtg}{global}{postfix}{xsize} = 500;
37
$db->{hide}{mrtg}{global}{postfix}{ysize} = 135;
38

    
39
sub config_save_val($$$$) {
40
	my ($filename,$name,$var,$val) = @_;
41

    
42
	my $this_ysize;
43
	my $this_xsize;
44
	my $this_title;
45

    
46
	# HACK!
47
	if ( $var eq 'ysize' ) {
48
		$val += 35;
49
	} elsif ( $var eq 'xsize' ) {
50
		$val += 100;
51
	}
52

    
53
	# Save any default initializers
54
	if ($name eq '_') {
55
		$db->{hide}{mrtg}{global}{postfix}{$var} = $val;
56
		return;
57
	}
58
	if ($name eq '^') {
59
		$db->{hide}{mrtg}{global}{prefix}{$var} = $val;
60
		return;
61
	}
62

    
63
	# Check for name name collision, and uniqueify
64
	my $unique_name = $name;
65
	my $unique_id = 1;
66
	while (defined $db->{graph}->{$unique_name}
67
		 && $db->{graph}->{$unique_name}->{definedby} ne $filename) {
68
		$unique_name = $name . '_' . $unique_id;
69
		$unique_id++;
70
	}
71

    
72
	if (!defined $db->{graph}->{$unique_name}) {
73
		# initialize a new name
74

    
75
		#TODO - instantiate new tests from all of the "_"/"^" defaults
76

    
77
		push @{$db->{hide}{sequence}}, $unique_name;
78

    
79
		$db->{graph}->{$unique_name}->{name} = $name;
80
		$db->{graph}->{$unique_name}->{definedby} = $filename;
81
		$db->{graph}->{$unique_name}->{sequence} = @{$db->{hide}{sequence}};
82

    
83
		$db->{graph}{$unique_name}{img}{xsize} = $db->{hide}{mrtg}{global}{postfix}{xsize};
84
		$db->{graph}{$unique_name}{img}{ysize} = $db->{hide}{mrtg}{global}{postfix}{ysize};
85

    
86
	}
87
	$db->{hide}{mrtg}{target}{$unique_name}{$var} = $val;
88
}
89

    
90
# Load one or more files
91
#
92
sub config_load_file(@) {
93
	while (@_) {
94
		my $filename = shift;
95

    
96
		my $fh = new FileHandle $filename,"r";
97
		if (!defined $fh) {
98
			# FIXME globals
99
			$warnings .= "Warning: Could not open $filename $!\n";
100
			return;
101
		}
102

    
103
		#TODO - multi-line values
104
		#TODO - reset the {hide}{mrtg}{global} vars
105

    
106
		while(<$fh>){
107

    
108
			# Is this a standard MRTG setting?
109
			if ( $_ =~ /^([^#[][^[]+)\[(.*)\]:\s*(.+)$/ ) {
110
				my $var=lc $1;
111
				my $name=lc $2;
112
				my $val=$3;
113

    
114
				config_save_val($filename,$name,$var,$val);
115

    
116
			} elsif ( $_ =~ /^([^#[][^[]+):\s*(.+)$/ ) {
117
				# its a global statement
118
				my $var=lc $1;
119
				my $val=$2;
120

    
121
				$db->{hide}{mrtg}{global}{$var}=$val;
122
			}
123

    
124
			# TODO - Handle extra statements:
125
			#	Include
126
			# 	WorkDir - see config_read_filesystem
127
			#	LogDir
128
			#	##HC Magic for baseurl
129
		}
130
	}
131
}
132

    
133
# Itterate through the loaded name and read their mtime and
134
# any other filesystem details for them.
135
#
136
sub config_read_filesystem() {
137

    
138
	# TODO - also check the other directory statements
139
	if ($db->{hide}{mrtg}{global}{workdir}) {
140
		chdir $db->{hide}{mrtg}{global}{workdir};
141
	}
142

    
143
	# check and update details for all known tests;
144
	for my $i (keys %{$db->{graph}}) {
145
		my $graph = $db->{graph}->{$i};
146
		my $graphname = $graph->{name};
147
		my $mrtg = $db->{hide}{mrtg}{target}{$i};
148

    
149
		# Default is GIF, unless a PNG file exists
150
		$mrtg->{_imagetype} = 'gif';
151
		if ( -e "$graphname-day.png" ) {
152
			$mrtg->{_imagetype} = "png";
153
		}
154

    
155
		# TODO - determine correct URL prefix
156
		# TODO - change the filename based on the displayed period
157
		my $filename = $graphname . "-day." . $mrtg->{_imagetype};
158
		$graph->{img}{URL}{day} = $filename;
159

    
160
		$graph->{img}{URL}{week}  = $graphname."-week.".$mrtg->{_imagetype};
161
		$graph->{img}{URL}{month} = $graphname."-month.".$mrtg->{_imagetype};
162
		$graph->{img}{URL}{year}  = $graphname."-year.".$mrtg->{_imagetype};
163
		
164
		my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
165
			$atime,$mtime,$ctime,$blksize,$blocks)
166
			= stat($filename);
167
		if (!defined $mtime) {
168
			# if we cannot stat the file, skip it
169
			next;
170
		}
171

    
172
		# TODO - move these to a better function
173
		$graph->{URL} = $graphname . '.html';
174
		$graph->{title} = $mrtg->{title};
175

    
176
		$graph->{img}{mtime} = $mtime;
177

    
178
		# find the newest file
179
		if ($mtime > $db->{global}{graph}{mtime}) {
180
			$db->{global}{graph}{mtime} = $mtime;
181
		}
182
	}
183
}
184

    
185
sub extract_grouphosttest($) {
186
	my ($name) = @_;
187

    
188
	# Do not classify a test with no separators in it
189
	if ($name !~ /,/) {
190
		return undef;
191
	}
192

    
193
	my ($group,$host,$test) = split ',', $name;
194
	# TODO cope with missing group/host/test parts.
195
	if (!defined $group || !defined $host || !defined $test) {
196
		return undef;
197
	}
198
	return ($group,$host,$test);
199
}
200

    
201
# Read through the list of name and find common hostname prefixes,
202
# so that we can group these hosts together
203
# (a hosttype entry)
204
#
205
sub maketree_find_hosttypes() {
206

    
207
	for my $name (keys %{$db->{graph}}) {
208
		my ($group,$host,$test) = extract_grouphosttest($name);
209
		if (!defined($group)) {
210
			next;
211
		}
212
		
213
		my $hosttype;
214
		# TODO - this needs to have a better way...
215
		# hosttype is the non digit hostname prefix - thus
216
		# "proxy-1" and "proxy-2" would both end up in the
217
		# "proxy-" hosttype
218
		if ($host =~ m/^(.*[^0-9])(\d+)$/) {
219
			$hosttype = $1.'*';
220
		} else {
221
			next;
222
		}
223

    
224
		$db->{graph}{$name}{tag}{hosttype} = $hosttype;
225
		$db->{hide}{hosttype}->{$hosttype}->{$host}++;
226
	}
227

    
228
	for my $hosttype (keys %{$db->{hide}{hosttype}}) {
229
		if ((keys %{$db->{hide}{hosttype}->{$hosttype}})<2) {
230
			delete $db->{hide}{hosttype}->{$hosttype};
231
		}
232
	}
233
}
234

    
235
sub maketags() {
236
	maketree_find_hosttypes();
237

    
238
	for my $name (keys %{$db->{graph}}) {
239
		my $graph = $db->{graph}->{$name};
240
		my ($group,$host,$test) = extract_grouphosttest($name);
241

    
242
		$graph->{tag}{group}=$group if $group;
243
		$graph->{tag}{host}=$host if $host;
244
		$graph->{tag}{test}=$test if $test;
245
	}
246
}
247

    
248
my $this_host = hostname;
249

    
250
print "Content-Type: text/json; charset=ISO-8859-1\n";
251

    
252
config_load_file(@config_files);
253
config_read_filesystem();
254
maketags();
255

    
256
# Time the next update to occur a little while after the next interval completes
257
my $interval = 300; # 5 min update interval
258
my $guardband = 15; # updates occur this many seconds after predicted gif completion
259
my $refresh = $interval + $guardband + $db->{global}{graph}{mtime} - time; # predict how long until next update
260
$refresh = $interval if $refresh <= $guardband;
261
my $expires = gmtime (time + $interval * 2 + $guardband);
262

    
263
$db->{global}{creator}{name} = "indexmrtg";
264
$db->{global}{creator}{version} = "$VERSION";
265

    
266
$db->{global}{graph}{expires} = "$expires GMT";
267
$db->{global}{graph}{refresh} = $refresh;
268
$db->{global}{sequence} = @{$db->{hide}{sequence}};
269

    
270
if (param('debug')) {
271
	print "\n",Dumper(\$db),"\n";
272
}
273

    
274
# Remove objects that are not intended to be public
275
delete $db->{hide};
276

    
277
print "\n",JSON->new->utf8(1)->pretty(1)->canonical(1)->encode($db),"\n";
278

    
279

    
(5-5/7)