1# Copyright (C) 2002 Stanislav Sinyagin 2# 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 2 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program; if not, write to the Free Software 15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 16 17# Stanislav Sinyagin <ssinyagin@k-open.com> 18 19## %Torrus::Global::treeConfig manipulation 20 21package Torrus::SiteConfig; 22 23use strict; 24use warnings; 25 26use Torrus::Log; 27 28our %validDaemonNames = ('collector' => 1, 29 'monitor' => 1); 30 31our %mandatoryGraphStyles = 32 ( 33 'SingleGraph' => {'color' => 1, 'line' => 1}, 34 'HWBoundary' => {'color' => 1, 'line' => 1}, 35 'HWFailure' => {'color' => 1}, 36 'HruleMin' => {'color' => 1}, 37 'HruleNormal' => {'color' => 1}, 38 'HruleMax' => {'color' => 1}, 39 'BpsIn' => {'color' => 1, 'line' => 1}, 40 'BpsOut' => {'color' => 1, 'line' => 1} 41 ); 42 43%Torrus::SiteConfig::validLineStyles = 44 ( 45 'LINE1' => 1, 46 'LINE2' => 1, 47 'LINE3' => 1, 48 'AREA' => 1, 49 'STACK' => 1 50 ); 51 52## Verify the correctness of %Torrus::Global::treeConfig contents 53 54sub verify 55{ 56 my $ok = 1; 57 if( not (scalar( keys %Torrus::Global::treeConfig )) ) 58 { 59 Error('%Torrus::Global::treeConfig is not defined or empty'); 60 $ok = 0; 61 } 62 63 foreach my $tree ( keys %Torrus::Global::treeConfig ) 64 { 65 if( $tree !~ /^[a-zA-Z][a-zA-Z0-9_\-]*$/o ) 66 { 67 Error("Invalid tree name: " . $tree); 68 $ok = 0; 69 next; 70 } 71 72 if( not $Torrus::Global::treeConfig{$tree}{'description'} ) 73 { 74 Error("Missing description for the tree named \"" . $tree . "\""); 75 $ok = 0; 76 } 77 78 my $xmlfiles = $Torrus::Global::treeConfig{$tree}{'xmlfiles'}; 79 if( not ref( $xmlfiles ) or not scalar( @{$xmlfiles} ) ) 80 { 81 Error("'xmlfiles' array is not defined for the tree named \"" . 82 $tree . "\""); 83 $ok = 0; 84 } 85 else 86 { 87 foreach my $file ( @{$xmlfiles} ) 88 { 89 $ok = findXMLFile( $file, 90 "in the tree named \"" . $tree . "\"" ) ? 91 $ok:0; 92 } 93 94 if( ref( $Torrus::Global::treeConfig{$tree}{'run'} ) ) 95 { 96 foreach my $daemon 97 ( keys %{$Torrus::Global::treeConfig{$tree}{'run'}} ) 98 { 99 if( not $validDaemonNames{$daemon} ) 100 { 101 Error("\"" . $daemon . "\" is not a correct daemon " . 102 "name in the tree named \"" . $tree . "\""); 103 $ok = 0; 104 } 105 } 106 } 107 } 108 } 109 110 foreach my $file ( @Torrus::Global::xmlAlwaysIncludeFirst ) 111 { 112 $ok = findXMLFile( $file, 113 'in @Torrus::Global::xmlAlwaysIncludeFirst' ) ? 114 $ok:0; 115 } 116 foreach my $file ( @Torrus::Global::xmlAlwaysIncludeLast ) 117 { 118 $ok = findXMLFile( $file, 119 'in @Torrus::Global::xmlAlwaysIncludeLast' ) ? 120 $ok:0; 121 } 122 123 # Validate the styling profile 124 125 my $file = $Torrus::Global::stylingDir . '/' . 126 $Torrus::Renderer::stylingProfile . '.pl'; 127 if( -r $file ) 128 { 129 require $file; 130 131 #Color names are always there 132 require $Torrus::Global::stylingDir . '/colornames.pl'; 133 134 if( defined($Torrus::Renderer::stylingProfileOverlay) ) 135 { 136 my $overlay = $Torrus::Renderer::stylingProfileOverlay; 137 if( -r $overlay ) 138 { 139 require $overlay; 140 } 141 else 142 { 143 Error('Error reading styling profile overlay from ' . 144 $overlay . ': File is not readable'); 145 $ok = 0; 146 } 147 } 148 149 my $profile = \%Torrus::Renderer::graphStyles; 150 # Check if mandatory parameters present 151 foreach my $element ( keys %mandatoryGraphStyles ) 152 { 153 if( ref( $profile->{$element} ) ) 154 { 155 if( $mandatoryGraphStyles{$element}{'color'} 156 and not defined( $profile->{$element}{'color'} ) ) 157 { 158 Error('Mandatory color for ' . $element . 159 ' is not defined in ' . $file); 160 $ok = 0; 161 } 162 if( $mandatoryGraphStyles{$element}{'line'} 163 and not defined( $profile->{$element}{'line'} ) ) 164 { 165 Error('Mandatory line style for ' . $element . 166 ' is not defined in ' . $file); 167 $ok = 0; 168 } 169 } 170 else 171 { 172 Error('Mandatory styling for ' . $element . 173 ' is not defined in ' . $file); 174 $ok = 0; 175 } 176 } 177 # Check validity of all parameters 178 foreach my $element ( keys %{$profile} ) 179 { 180 if( defined( $profile->{$element}{'color'} ) ) 181 { 182 my $color = $profile->{$element}{'color'}; 183 my $recursionLimit = 100; 184 185 while( $color =~ /^\#\#(\S+)$/ ) 186 { 187 if( $recursionLimit-- <= 0 ) 188 { 189 Error('Color recursion is too deep'); 190 $ok = 0; 191 } 192 else 193 { 194 my $colorName = $1; 195 $color = $profile->{$colorName}{'color'}; 196 if( not defined( $color ) ) 197 { 198 Error('No color is defined for ' . $colorName); 199 $ok = 0; 200 } 201 } 202 } 203 204 if( $color !~ /^\#[0-9a-fA-F]{6}$/ ) 205 { 206 Error('Invalid color specification for ' . $element . 207 ' in ' . $file); 208 $ok = 0; 209 } 210 } 211 if( defined( $profile->{$element}{'line'} ) ) 212 { 213 if( not $Torrus::SiteConfig::validLineStyles{ 214 $profile->{$element}{'line'}} ) 215 { 216 Error('Invalid line specification for ' . $element . 217 ' in ' . $file); 218 $ok = 0; 219 } 220 } 221 } 222 } 223 else 224 { 225 Error('Error reading styling profile from ' . $file . 226 ': File is not readable'); 227 $ok = 0; 228 } 229 230 return $ok; 231} 232 233 234sub findXMLFile 235{ 236 my $file = shift; 237 my $msg = shift; 238 239 my $filename; 240 if( defined( $file ) ) 241 { 242 my $found = 0; 243 foreach my $dir ( @Torrus::Global::xmlDirs ) 244 { 245 $filename = $dir . '/' . $file; 246 if( -r $filename ) 247 { 248 $found = 1; 249 last; 250 } 251 } 252 253 if( not $found ) 254 { 255 Error("Cannot find file: " . $file); 256 $filename = undef; 257 } 258 } 259 else 260 { 261 Error("File name undefined " . $msg); 262 } 263 return $filename; 264} 265 266 267sub treeExists 268{ 269 my $tree = shift; 270 return defined( $Torrus::Global::treeConfig{$tree} ); 271} 272 273 274sub listTreeNames 275{ 276 return( sort keys %Torrus::Global::treeConfig ); 277} 278 279 280sub mayRunCollector 281{ 282 my $tree = shift; 283 my $run = $Torrus::Global::treeConfig{$tree}{'run'}{'collector'}; 284 return( defined($run) and $run > 0 ); 285} 286 287sub collectorInstances 288{ 289 my $tree = shift; 290 my $run = $Torrus::Global::treeConfig{$tree}{'run'}{'collector'}; 291 return( (defined($run) and $run > 1) ? int($run) : 1 ); 292} 293 294sub mayRunMonitor 295{ 296 my $tree = shift; 297 return $Torrus::Global::treeConfig{$tree}{'run'}{'monitor'}; 298} 299 300 301sub listXmlFiles 302{ 303 my $tree = shift; 304 return @{$Torrus::Global::treeConfig{$tree}{'xmlfiles'}}; 305} 306 307 308sub treeDescription 309{ 310 my $tree = shift; 311 return $Torrus::Global::treeConfig{$tree}{'description'}; 312} 313 314 315sub loadStyling 316{ 317 require $Torrus::Global::stylingDir . '/' . 318 $Torrus::Renderer::stylingProfile . '.pl'; 319 320 require $Torrus::Global::stylingDir . '/colornames.pl'; 321 322 if( defined($Torrus::Renderer::stylingProfileOverlay) ) 323 { 324 require $Torrus::Renderer::stylingProfileOverlay; 325 } 326 return; 327} 328 329 3301; 331 332 333# Local Variables: 334# mode: perl 335# indent-tabs-mode: nil 336# perl-indent-level: 4 337# End: 338