#!/usr/bin/perl -w # Smeadmin - panel cgi perl affichant les infos dans le server-manager # Copyright (C) 2006 # This file is distributed under the GPL license. # Landry Breuil , 2006. # heading : Administration # description : Smeadmin # navigation : 4000 4020 #---------------------------------------------------------------- #inclusion des modules use strict; no strict 'refs'; use CGI':all'; use CGI::Carp qw(fatalsToBrowser); use DBD::mysql; use RRDs; use esmith::cgi; use esmith::ConfigDB; use esmith::I18N; use POSIX; use Locale::gettext; ##raid status use Getopt::Long; #---------------------------------------------------------------- #declaration de variables globales my ($DomainName,$SystemName,$SystemMode,$ExternalInterface,$InternalInterface,$ExternalIP,$InternalIP); my $progname="smeadmin"; #handle de la db sme my $smedb=esmith::ConfigDB->open; my $smeadmindb = $smedb->get('smeadmind') || die "Error opening smeadmind db\n"; #handle de la bd mysql my $bd; my $rrddir="/var/lib/smeadmin"; my $imgdir="/etc/e-smith/web/panels/manager/html/smeadmin"; #my $maxping=0.1; my $maxping=0.5; my $SshPort; #---------------------------------------------------------------- #declaration des fonctions #webpages-funcs sub showConf; sub showAlertConf; sub readConf; sub changeOk; sub accueil; sub svcControl; sub showAdvancedTest; #details de services sub showHttpd; sub showSquid; sub showSamba; sub showAfp; sub showFtp; sub showPppoe; sub showVpn; sub showSsh; sub showDhcpd; sub showQpsmtpd; sub showQmail; #graph-pages-funcs sub showHardGraph; sub showNetGraph; sub showSystmGraph; #misc-funcs sub ipnum2ipdot; sub connectDB; sub deconnectDB; sub printPopupMenu; sub showService; sub showSvcGraph; sub showDbData; #---------------------------------------------------------------- #---------------------------------------------------------------- #debut pre-main BEGIN { # Clear PATH and related environment variables so that calls to # external programs do not cause results to be tainted. See # "perlsec" manual page for details. $ENV {'PATH'} = '/bin:/usr/bin:/sbin'; $ENV {'SHELL'} = '/bin/bash'; delete $ENV {'ENV'}; } my $i18n = new esmith::I18N; my $http_lang = $i18n->preferredLanguage( $ENV{HTTP_ACCEPT_LANGUAGE} ); if ($http_lang =~ /^([a-z]{2})$/) { $http_lang .= "_" .uc($1) } $http_lang =~ s/([a-z]{2})-([a-z]{2})/"$1_".uc($2)/e; $ENV{LC_MESSAGES} = "$http_lang"; unless(setlocale(LC_MESSAGES, "")){ $http_lang = 'en_US'; $ENV{LC_MESSAGES} = "$http_lang"; setlocale(LC_MESSAGES, ""); } bindtextdomain("smeadmin","/usr/share/locale"); textdomain("smeadmin"); bind_textdomain_codeset "smeadmin", 'utf-8'; #la locale est reglee => on peut balancer les gettext #rapide hash de labels utilise dans les 3 pages de graphes my %labels=("-1h"=>gettext("Graphs on one hour, average on 5mn."), "-6h"=>gettext("Graphs on six hours, average on 5mn."), "-1d"=>gettext("Graphs on one day, average on 5mn."), "-3d"=>gettext("Graphs on three days, average on 30mn."), "-7d"=>gettext("Graphs on one week, average on 30mn."), "-1m"=>gettext("Graphs on one month, average on 2h"), "-6months"=>gettext("Graphs on six months, average on 1d."), "-1y"=>gettext("Graphs on one year, average on 1d")); #chaines de caracteres pour le tableau de bounds my %strings=( 'MaxMailIn'=>gettext("Maximum number of incoming e-mails "), 'MaxMailOut'=>gettext("Maximum number of outgoing e-mails "), 'MaxDiskSpace'=>gettext("Maximum % of hard disk usage "), 'MaxCpu'=>gettext("Maximum % of cpu usage "), 'MaxHwTemp'=>gettext("Maximum temperature for cpu and motherboard "), 'MaxHdTemp'=>gettext("Maximum hard disk temperature "), 'MaxSamba'=>gettext("Maximum number of samba sessions "), 'MaxSsh'=>gettext("Maximum number of ssh sessions "), 'MaxFtp'=>gettext("Maximum number of ftp sessions "), 'MaxVpn'=>gettext("Maximum number of vpn sessions ")); #hash faisant correspondre la cle (nom du param) a sa valeur [ICI, CE SONT LES VALEURS PAR DEFAUT !!] #idem dans le daemon /usr/bin/smeadmind my %params=( 'DbName'=>"smeadmin", 'DbPassword'=>"pass", 'DbUser'=>"smeadmin", # 'if_internal'=>"eth0", # 'if_external'=>"eth1", 'ImgFormat'=>"PNG", 'ImgWidth'=>"500", 'ImgHeight'=>"300", # /sbin/e-smith/db domains keys pour voir les autres domaines du serveur 'OtherMailDomains'=>"", 'PingTarget'=>"www.google.fr", 'hd1'=>"hda", 'hd2'=>"", 'hd3'=>"", 'hd4'=>"", 'hd5'=>"", 'hd6'=>"", 'UseDu'=>"on", 'SensorsTag1'=>"temp1", 'SensorsTag2'=>"temp2", 'SensorsTagFan'=>"fan1", 'SensorsTagFan2'=>"", 'LimitPppoeDisconnect'=>"1", 'LimitPppoeDuration'=>"4", 'LimitVpnDuration'=>"2", 'AlertMailRecipient'=>'admin', 'StatusMailRecipient'=>'admin', 'StatusInterval'=>"3", 'MaxMailIn'=>"1", 'MaxMailOut'=>"1", 'MaxDiskSpace'=>"60", 'MaxCpu'=>"50", 'MaxHwTemp'=>"40", 'MaxHdTemp'=>"40", 'MaxSamba'=>"1", 'MaxSsh'=>"1", 'MaxFtp'=>"1", 'MaxVpn'=>"1"); #---------------------------------------------------------------- #---------------------------------------------------------------- #debut MAIN #on envoie le cgi esmith::util::setRealToEffective (); my $q = new CGI; $q->charset('utf-8'); #on lit les parametres dans la db readConf(); #on genere l'entete de la page $q->default_dtd('-//W3C//DTD XHTML 1.0 Transitional//EN'); print $q->header ('text/html'); print $q->start_html ( -TITLE => "$progname - $DomainName", -AUTHOR => 'landry@firewall-services.com', -CLASS => "main", -STYLE => { -verbatim => '@import url("/server-common/css/sme_main.css");', -src => '/server-common/css/sme_core.css'}); print $q->h1 ("$progname : $DomainName"); #examine le param 'state' pour savoir quelle page on demande #METTRE UN SWITCH ??? => NON, le switch PERL est LEEEEEEEENT *4 # a voir : un hash de fonctions if (! grep (/^state$/, $q->param)) {accueil();} elsif ($q->param('state') eq 'conf') {showConf();} elsif ($q->param('state') eq 'conf_alert') {showAlertConf();} elsif ($q->param('state') eq 'validate') {changeOk();} elsif ($q->param('state') eq 'service_control') {svcControl();} elsif ($q->param('state') eq 'advanced') {showAdvancedTest();} elsif ($q->param('state') eq 'service_detail') {showService();} elsif ($q->param('state') eq 'hard') {showHardGraph();} elsif ($q->param('state') eq 'net') {showNetGraph();} elsif ($q->param('state') eq 'systm') {showSystmGraph();} else { print $q->p("PrOTcH !! No page !!");} esmith::cgi::genFooter ($q); exit (0); #fin MAIN #---------------------------------------------------------------- #---------------------------------------------------------------- # definition des fonctions #---------------------------------------------------------------- sub accueil { #affichage des liens vers les autres pages print $q->p(gettext("View graphs on :"),$q->ul( $q->li($q->a ({href => "$progname?state=hard"},gettext("server's hardware (sensors)\n"))), $q->li($q->a ({href => "$progname?state=net"},gettext("network use (connections,sessions,load)\n"))), $q->li($q->a ({href => "$progname?state=systm"},gettext("system performance (cpu, memory, hard disk)\n"))))), $q->p($q->a ({href => "$progname?state=advanced"},gettext("Advanced connection tests on services\n"))), $q->p($q->a ({href => "$progname?state=conf"},gettext("Configuration of smeadmin\n"))), $q->hr({width=>'80%'}); #hack pour la mise en forme : a) debut 1er case a gauche print $q->start_table,$q->start_Tr,$q->start_td; #affichage du tableau des connexions reseau actives print $q->p(gettext("Active tcp connections tcp with external(blue)/local(green) connections highlighted :\n")),$q->br; print $q->start_table({-border => '1'}), $q->Tr($q->th(gettext("Local IP:port")),$q->th(gettext("Remote IP:port")),$q->th(gettext("State")),$q->th(gettext("PID/Process"))); foreach (`/bin/netstat --tcp --numeric-host --program `) { my($proto,undef,undef,$loc,$dist,$stat,$prog)=split(/\s+/,$_); #mise en couleur de l'ip en fct ext/loc if ($proto eq 'tcp') { print $q->Tr($q->td({bgcolor=>(($loc =~ /($InternalIP|127.0.0.1):/o)?"#32CD32":(($loc =~ /$ExternalIP:/o)?"#1E90FF":"#FFFFFF"))},$loc),$q->td($dist),$q->td($stat),$q->td($prog)); } } print $q->end_table,$q->br; #hack pour la mise en forme : b) fin 1er case a gauche et debut 2e case print $q->end_td,$q->td({-width=>'20'}),$q->start_td({-valign=>'top'}); #affichage du resultat de 'uptime' my $uptime=`/usr/bin/uptime`; print $q->p(gettext("Stats :\n")),$q->p($uptime); ##Start to check linux raid status and display the content my $Raidcheck = `/bin/cat /proc/mdstat`; if ( $Raidcheck =~ "raid") { print $q->br; print $q->p(gettext("Status of Linux software RAID :")); my $file = "/proc/mdstat"; my $device = "all"; # Get command line options. GetOptions ('file=s' => \$file, 'device=s' => \$device, 'help' => sub { &usage() } ); ## Strip leading "/dev/" from --device in case it has been given $device =~ s/^\/dev\///; ## This is a global return value - set to the worst result we get overall my $retval = 0; my (%active_devs, %failed_devs, %spare_devs); open FILE, "< $file" or die "Can't open $file : $!"; while () { next if ! /^(md\d+)+\s*:/; next if $device ne "all" and $device ne $1; my $dev = $1; my @array = split(/ /); for $_ (@array) { next if ! /(\w+)\[\d+\](\(.\))*/; if (defined $2 && $2 eq "(F)") { $failed_devs{$dev} .= "$1,"; } elsif (defined $2 && $2 eq "(S)") { $spare_devs{$dev} .= "$1,"; } else { $active_devs{$dev} .= "$1,"; } } if (! defined($active_devs{$dev})) { $active_devs{$dev} = "none"; } else { $active_devs{$dev} =~ s/,$//; } if (! defined($spare_devs{$dev})) { $spare_devs{$dev} = "none"; } else { $spare_devs{$dev} =~ s/,$//; } if (! defined($failed_devs{$dev})) { $failed_devs{$dev} = "none"; } else { $failed_devs{$dev} =~ s/,$//; } $_ = ; /\[(\d+)\/(\d+)\]\s+\[(.*)\]$/; my $devs_total = $1; my $devs_up = $2; my $stat = $3; my $result = "OK"; if ($devs_total > $devs_up or $failed_devs{$dev} ne "none") { $result = "CRITICAL"; } my @raidstatus = "$result - $dev [$stat] has $devs_up of $devs_total devices active (active=$active_devs{$dev} failed=$failed_devs{$dev} spare=$spare_devs{$dev})\n"; foreach my $raid (@raidstatus) { #if the raid is degraded (but not failed) on one drive then we get the orange colour, else green if ( $raid =~ ("CRITICAL" && "failed=none") ){ print $q->table( $q->td($q->td({bgcolor=>(($raid =~ "CRITICAL")?"orange":"#32CD32")},$raid)));} #if the raid is degraded and failed on drive(s) then we get the red colour, else green elsif ( $raid =~ ("CRITICAL" && "_") ){ print $q->table ($q->td($q->td({bgcolor=>(($raid =~ "CRITICAL")?"red":"#32CD32")},$raid)));} } } } #s'il ya des users connectes on affiche le resultat de la commande 'w' if (!($uptime =~ /0 user /)) { print $q->br; print $q->p(gettext("Connected users :")),$q->start_table({-border => '1'}), $q->Tr($q->th(gettext("Login")),$q->th(gettext("TTY")),$q->th(gettext("From")),$q->th(gettext("Since")),$q->th(gettext("Idle")),$q->th(gettext("Command"))); #root pts/3 pc-00010:S.0 17:09 58.00s 1.13s 1.05s vim smeadmin #root pts/2 pc-00010.plop.gr 17:07 0.00s 0.19s 0.05s w -h foreach(`/usr/bin/w -h`) { my($user,$tty,$src,$since,$idle,undef,undef,@cmd)=split(/\s+/,$_); print $q->Tr($q->td({bgcolor=>(($user eq "root")?"red":"white")},$user), $q->td({bgcolor=>(($tty =~ /tty/)?"orange":"white")},$tty),$q->td($src),$q->td($since),$q->td($idle),$q->td(@cmd)); } print $q->end_table; } print $q->end_td,$q->end_Tr,$q->end_table; print $q->hr({width=>'80%'}); #liste des services et classification my @services = ("#".gettext("Web services"),"httpd-e-smith","httpd-admin","httpd-bkpc","httpd-fpbx","httpd-pki","httpd-isoqlog","squid","php-fpm", "php55-php-fpm", "php56-php-fpm", "php70-php-fpm", "php71-php-fpm", "php72-php-fpm", "php73-php-fpm", "php74-php-fpm", "php80-php-fpm", "php81-php-fpm", "php82-php-fpm", "php83-php-fpm", "#".gettext("Administrative services"), "sshd", "smeadmind", "#".gettext("Network services"),"wan","dhcpd","pptpd","ippp","bridge","openvpn-s2s","openvpn-routed","openvpn-bridge","wireguard","ipsec","vpnserver", "#".gettext("File-sharing services"),"smb","smbd","nmbd","ftp","nfs","madsonic", "#".gettext("E-mail services"),"dovecot","pop3","pop3s","imaps","imap","qmail","altqmail","qpsmtpd","sqpsmtpd","clamd","freshclam","spamassassin","mailman",#mail "#".gettext("DNS services"),"tinydns","dnscache", "dnscache.forwarder", "DynDNS", #dns "#".gettext("Authentication services"),"oidentd","ldap","smtp-auth-proxy","radiusd","cvm-unix", #auth "#".gettext("Misc. services"),"mariadb","ntpd","lpd", "backuppc", "bandwidthd","unifi", #misc "#".gettext("System services"),"crond","rsyslog","ulogd","acpid","raidmonitor","local", "yum"); #sys et materiel #hack pour la mise en forme : a) debut 1er case a gauche print $q->start_table,$q->start_Tr,$q->start_td; #affichage du tableau des services print $q->p(gettext("System services (Click on a service name for details) :\n")),$q->br, $q->start_table({-border => '1'}); $q->Tr($q->th(gettext("Service")),$q->th(gettext("State")),$q->th(gettext("Nb process")),$q->th(gettext("Action"))); print $q->startform(-method => 'GET', -action => $q->url (-absolute => 1)); foreach my $svc (@services) { # si le service pppoe est disabled on n'affiche pas la ligne correspondante next if ($svc eq 'pppoe' && $smedb->get('pppoe')->prop('status') eq 'disabled'); my $cmd; my $details=0; #si c'est un 'header' if ($svc=~/^#(.*)/) { print $q->Tr(),$q->Tr($q->th($1),$q->th(gettext("State")),$q->th(gettext("Action")),$q->th("DB Status"),$q->th("DB Action")); } else { #si c'est un service pour lequel on a des infos complementaires... if($svc=~/^(httpd-e-smith|httpd-admin|smb|smbd|nmbd|squid|pptpd|dhcpd|sshd|ftp|pppoe|pppd|wan|altqmail|qmail|qpsmtpd|sqpsmtpd)$/) {$details=1;} if ($svc=~/^(imaps|imap|pop3|pop3s)$/) { $cmd = "/usr/bin/systemctl is-active dovecot"; } else {$cmd = "/usr/bin/systemctl is-active $svc";} my @res=`$cmd`; foreach (@res) { my $dbsv=$smedb->get("$svc") ||next; # workaround to see db config status my $dbstatus="not defined"; if ( length(`/sbin/e-smith/db configuration show $svc`) > 1 ) {$dbstatus=$smedb->get("$svc")->prop('status')||"disabled";} # trouver un moyen de verifier que le nom du service est bien trouvé dans liste else {$dbstatus="";} if ($svc=~/^(imaps|imap|pop3|pop3s)$/) { print $q->Tr( (($details==1)? $q->td($q->a({href=>"$progname?state=service_detail&service=$svc"},"$svc")) : $q->td("$svc")), $q->td(""),$q->td( "dovecot" ) , $q->td("$dbstatus"), $q->td( ( ("$dbstatus" ne "") ? (("$dbstatus" eq "enabled" )? $q->submit(-name=>"disabled_$svc",-value=>'disable'): $q->submit(-name=>"enabled_$svc",-value=>'enable')) : " ") ) ); } #si le service est arrete^:il ya down ou il n'y a pas de () pour le pid et ca ne fini pas par ... elsif(/^down:/ || /^([a-zA-Z0-9]*) [^(^)]*([^.]{3})$/ || /^failed/ || /^unknown/|| /^inactive/) { #on fait une conditionnelle pour savoir si on met le nom du service en lien ou pas print $q->Tr((($details==1)? $q->td($q->a({href=>"$progname?state=service_detail&service=$svc"},"$svc")) : $q->td("$svc")), $q->td(gettext("Stopped")),$q->td( (("$dbstatus" eq "enabled" || "$dbstatus" eq "" )? $q->submit(-name=>"start_$svc",-value=>'start'): "disabled") ) ,$q->td("$dbstatus"), $q->td( ( ("$dbstatus" ne "") ? (("$dbstatus" eq "enabled" )? $q->submit(-name=>"disabled_$svc",-value=>'disable'): $q->submit(-name=>"enabled_$svc",-value=>'enable')) : " ") ) ); } elsif (/^run:(.*)\(pid ([\d\s]+)\)/ || /^([a-zA-Z0-9]*) \(pid ([\d\s]+)\).*\.\.\.$/ || /^active/ ) { #$2=liste pids my @pids; @pids=split(/ /,$2) if defined $2; print $q->Tr( (($details==1)? $q->td($q->a({href=>"$progname?state=service_detail&service=$svc"},"$svc")) : $q->td("$svc")), $q->td(gettext("Started")), $q->td($q->submit(-name=>"stop_$svc",-value=>'stop')) ,$q->td("$dbstatus"), $q->td( ( ("$dbstatus" ne "") ? (("$dbstatus" eq "enabled" )? $q->submit(-name=>"disabled_$svc",-value=>'disable'): $q->submit(-name=>"enabled_$svc",-value=>'enable')) : " ") ) ); } } } } #service_control est le parametre qui prend le nom du service a arreter/demarrer print $q->hidden(-name=>'state',-default=>'service_control',-override=>1), $q->end_table, $q->endform; #hack pour la mise en forme : b) fin 1er case a gauche et debut 2e case print $q->end_td,$q->td({-width=>'100'}),$q->start_td({-valign=>'top'}); #affichage du tableau des connexions reseau en ecoute print $q->p(gettext("Listening tcp sockets, and corresponding process :\n")),$q->br; print $q->start_table({-border => '1'}), $q->Tr($q->th(gettext("Local IP:port")),$q->th(gettext("PID/Process"))); foreach (`/bin/netstat --tcp --numeric-host --program --listen`) { my($proto,undef,undef,$loc,undef,undef,$prog)=split(/\s+/,$_); #mise en couleur de l'ip en fct ext/loc if ($proto eq 'tcp') { print $q->Tr($q->td($loc),$q->td($prog)); } } print $q->end_table; print $q->end_td,$q->end_Tr,$q->end_table; print $q->br,$q->hr({width=>'80%'}); if (-e "/usr/sbin/clamd") { #affichage des infos sur l'antivirus my $sigs=0; foreach (`/usr/bin/tail -n 6 /var/log/freshclam/current`) { #ClamAV update process started at Thu Jul 29 18:36:00 2004 if (/ClamAV update process started at (\w{3} \w{3}\s{1,2}\d{1,3} [0-9:]{8} \d{4})/) {print $q->p(sprintf(gettext("Last update of ClamAV antivirus : %s.\n"),$1));} #LOL !! le guide du routard galactique if (/DON'T PANIC/) {print $q->p(gettext("Warning ! Your antivirus may not be up-to-date.\n"));} # main.cvd is up to date (version: 24, sigs: 21793, f-level: 2, builder: tomek) # daily.cvd is up to date (version: 428, sigs: 1177, f-level: 2, builder: acab) # Database updated (23150 signatures) from database # 2005-12-01 21:46:29.777100500 ClamAV update process started at Thu Dec 1 21:46:29 2005 # 2005-12-01 21:46:29.981397500 WARNING: Your ClamAV installation is OUTDATED! # 2005-12-01 21:46:29.981407500 WARNING: Local version: 0.87 Recommended version: 0.87.1 # 2005-12-01 21:46:29.981414500 DON'T PANIC! Read http://www.clamav.net/faq.html # 2005-12-01 21:46:29.981420500 main.cvd is up to date (version: 34, sigs: 39625, f-level: 5, builder: tkojm) # 2005-12-01 21:46:29.981428500 daily.cvd is up to date (version: 1200, sigs: 1669, f-level: 6, builder: tomek) if (/sigs: (\d+)/) {$sigs+=$1;} } print $q->p(sprintf(gettext("The database contains %s virus signatures.\n"),$sigs)); } #un peu de bug report ? # rem jpp waiting for full dormmagick translation. Landry do not support anymore this contrib, will have a direct link to bugzilla here # print $q->p(gettext("Some feature request, comment or bug report ? send an e-mail to "),$q->b($q->i(gettext("landry at firewall-services dot com\n")))); } #---------------------------------------------------------------- # lecture de la conf dans la smedb et dans le fichier de conf sub readConf { #lecture des parametres contenus dans la db de sme my $smedb=esmith::ConfigDB->open; $DomainName = $smedb->get('DomainName')->value; $SystemName = $smedb->get('SystemName')->value; $SystemMode = $smedb->get("SystemMode")->value; #on n'a une external ip que si on est en server-passerelle if ($SystemMode =~ /servergateway/) { $ExternalIP = $smedb->get("ExternalIP")->value; $ExternalInterface = $smedb->get("ExternalInterface")->prop('Name'); } else{ $ExternalIP = ''; $ExternalInterface =''; } $InternalIP = $smedb->get("LocalIP")->value; foreach my $key (keys(%params)){ $params{$key} = $smeadmindb->prop($key); } $SshPort = $smedb->get('sshd')->prop('TCPPort'); } #---------------------------------------------------------------- #affiche le formulaire permettant de parametrer smeadmin sub showConf { print $q->startform (-method => 'GET', -action => $q->url (-absolute => 1 )), $q->i($q->p(gettext("Configuration of status e-mails.\n"))), $q->p(gettext("If you set the frequency to 0, status e-mails are disabled. You can put only the username if the recipient is a local user.\n")), $q->start_table, esmith::cgi::genNameValueRow($q,gettext("Status e-mails recipient"),"StatusMailRecipient",$params{"StatusMailRecipient"}), esmith::cgi::genNameValueRow($q,gettext("Frequency of status e-mails (* 5min)"),"StatusInterval",$params{"StatusInterval"}), $q->end_table, $q->hr({width=>'50%'}); #partie MySQL du formulaire print $q->i($q->p(gettext("Configuration of MySQL connection.\n"))), $q->p(gettext("You shall only modify these settings if you change the default values with phpMyAdmin or mysqladmin. These settings don't directly affect the configuration of MySQL.")),$q->br, $q->start_table, esmith::cgi::genNameValueRow($q,gettext("Database"),'DbName',$params{'DbName'}), esmith::cgi::genNameValueRow($q,gettext("MySQL user"),'DbUser',$params{'DbUser'}), esmith::cgi::genNameValueRow($q,gettext("Password"),'DbPassword',$params{'DbPassword'}), $q->end_table,$q->hr({width=>'50%'}); #partie reseau du formulaire print $q->i($q->p(gettext("Configuration of network settings.\n"))), $q->p(gettext('You can specify the names of the network interfaces to monitor, the e-mail domains and adresses to count in the e-mail graph (list of domains or adresses separated by semicolons. "me@domain.fr ; other-domain.com ; virtual.domain.fr" - the primary domain name and virtual domains are already counted). You can already choose a target for the ping latency graph (www.google.fr, default gateway,...)')),$q->br, $q->start_table; print esmith::cgi::genNameValueRow($q,gettext("Other e-mail domains"),'OtherMailDomains',$params{'OtherMailDomains'}), esmith::cgi::genNameValueRow($q,gettext("Ping target"),'PingTarget',$params{'PingTarget'}), $q->end_table,$q->hr({width=>'50%'}); #partie graphique/interface print $q->i($q->p(gettext("Web panel configuration.\n"))), $q->p(gettext("You can set the format and size of graphs, and the bounds upon which pppoe and vpn connections need to be highlighted.\n")),$q->br, $q->start_table, #vieux hack pour récuperer la css du NameValueRow # esmith::cgi::genNameValueRow($q,gettext("Format d'image (PNG/GIF)"),'img_format',$params{'img_format'}), $q->Tr ($q->td ({-class => "sme-noborders-label"},gettext("Image Format:")),"\n", $q->td($q->popup_menu(-name=>'ImgFormat', -values=>['PNG','GIF'], -default=>$params{'ImgFormat'}))), esmith::cgi::genNameValueRow($q,gettext("Graphs width"),'ImgWidth',$params{'ImgWidth'}), esmith::cgi::genNameValueRow($q,gettext("Graphs height"),'ImgHeight',$params{'ImgHeight'}), esmith::cgi::genNameValueRow($q,gettext("Pppoe disconnection lasting more than (in minutes)"),'LimitPppoeDisconnect',$params{'LimitPppoeDisconnect'}), esmith::cgi::genNameValueRow($q,gettext("Pppoe connection lasting less than (in hours)"),'LimitPppoeDuration',$params{'LimitPppoeDuration'}), esmith::cgi::genNameValueRow($q,gettext("Vpn connection lasting more than (in hours)"),'LimitVpnDuration',$params{'LimitVpnDuration'}), $q->end_table,$q->hr({width=>'50%'}); #partie senseurs materiels print $q->i($q->p(gettext("Configuration of hardware sensors.\n"))), $q->p(gettext("For the hard disks, generally you have 'hda' or 'hdb' with IDE and 'sda' or 'sdb' with SATA/SCSI. If you have only on disk, let the second field blank. You can choose to activate the computing of the main directories' size of SME. (maybe long and resource-consuming on large disks). To find available sensors, execute 'sensors' in a shell, and look for the keywords corresponding to the working sensors ('temp1','CPU Temp','MB Temp','fan3',....). Let the fields blank if you have no sensors available.\n")),$q->br, $q->start_table, $q->Tr ($q->td ({-class => "sme-noborders-label"},gettext("Activate du -s:")),"\n", $q->td($q->popup_menu(-name=>'UseDu', -values=>['on','off'], -default=>$params{'UseDu'}))), esmith::cgi::genNameValueRow($q,gettext("First hard disk"),'hd1',$params{'hd1'}), esmith::cgi::genNameValueRow($q,gettext("Second hard disk"),'hd2',$params{'hd2'}), esmith::cgi::genNameValueRow($q,gettext("Third hard disk"),'hd3',$params{'hd3'}), esmith::cgi::genNameValueRow($q,gettext("Fourth hard disk"),'hd4',$params{'hd4'}), esmith::cgi::genNameValueRow($q,gettext("Fifth hard disk"),'hd5',$params{'hd5'}), esmith::cgi::genNameValueRow($q,gettext("Sixth hard disk"),'hd6',$params{'hd6'}), esmith::cgi::genNameValueRow($q,gettext("First sensor (cpu)"),'SensorsTag1',$params{'SensorsTag1'}), esmith::cgi::genNameValueRow($q,gettext("Second sensor (motherboard)"),'SensorsTag2',$params{'SensorsTag2'}), esmith::cgi::genNameValueRow($q,gettext("Third sensor (fan)"),'SensorsTagFan',$params{'SensorsTagFan'}), esmith::cgi::genNameValueRow($q,gettext("Fourth sensor (fan)"),'SensorsTagFan2',$params{'SensorsTagFan2'}), $q->end_table,$q->hr({width=>'50%'}); #partie alertes print $q->i($q->p(gettext("Configuration of alerts.\n"))), $q->p(gettext("You should notice that these values are not limits FOR the system, but just values beyond which an alert e-mail is sent. If you set the limit to 0, the alert is disabled. You can put only the username if the recipient is a local user.\n")),$q->br; print $q->start_table, esmith::cgi::genNameValueRow($q,gettext("Alert e-mails recipient "),"AlertMailRecipient",$params{"AlertMailRecipient"}); #affichage du tableau des strings/limites parametree foreach my $key (keys(%strings)) { print esmith::cgi::genNameValueRow($q,$strings{$key},$key,$params{$key}); } print $q->end_table, $q->hr({width=>'50%'}), esmith::cgi::genButtonRow($q,$q->submit(-name=>'action',-value=>gettext("Save"))), $q->hidden(-name=>'state',-default=>'validate',-override=>1), $q->endform; } #---------------------------------------------------------------- #little patch : on montre juste la limite pour UNE alerte (cible du lien contenu dans le mail d'alerte) # cette fonction affiche juste un petit formulaire pour modifier la limite sub showAlertConf { my $key=$q->param('alert'); print $q->startform (-method => 'GET', -action => $q->url (-absolute => 1 )), $q->i($q->p(gettext("Alert configuration.\n"))),$q->p(gettext("Put 0 to desactivate it.\n")),$q->br, $q->start_table, esmith::cgi::genNameValueRow($q,$strings{$key},$key,$params{$key}), $q->end_table,$q->br, esmith::cgi::genButtonRow($q,$q->submit(-name=>'action',-value=>gettext("Save"))), $q->hidden(-name=>'state',-default=>'validate',-override=>1), $q->hidden(-name=>'alert',-default=>"$key",-override=>1), $q->endform; } #---------------------------------------------------------------- #verifie et sauve les nouveaux parametres sub changeOk { # faire juste une verification des valeurs, et afficher le formulaire vert changements appliques (meme si rien n'est modifie) # eventuellement un message si les mails de status viennent d'etre desactives # sinon, ne rien appliquer, donner la raison de l'erreur et afficher le formulaire rouge #Verification des parametres my $modified=0; my $verifok=1; my $str; #il y a deux cas : # - on verifie TOUTE la conf (on vient de changer plusieurs params) # - on verifie UN parametre (on vient de changer une limite numerique) # cas 1 :) if (!defined $q->param ('alert')) { # on regarde si un parametre a ete modifie foreach my $key (keys(%params)) { #print $key.": ".$q->param("$key")."
"; $modified=1 if ($params{$key} ne $q->param("$key")); } # ces 2 verifs ont ete "assouplies" pour permettre de ne mettre qu'un username local au serveur sans mettre tout l'adresse mail complete #verification validite e-mail alertes if (! ($q->param('AlertMailRecipient') =~ /^[\w.-]+(@[\dA-Za-z-.]+)?$/) ) { $verifok=0; $str=sprintf(gettext("\"%s\" is not a valid e-mail address.\n"),$q->param("AlertMailRecipient")); print esmith::cgi::genTextRow($q,$q->p($str)); } #verification validite e-mail status if (! ($q->param('StatusMailRecipient') =~ /^[\w.-]+(@[\dA-Za-z-.]+)?$/) ) { $verifok=0; $str=sprintf(gettext("\"%s\" is not a valid e-mail address.\n"),$q->param("StatusMailRecipient")); print esmith::cgi::genTextRow($q,$q->p($str)); } #verification valeurs numeriques foreach my $key ( 'ImgWidth', 'ImgHeight', 'LimitPppoeDisconnect', 'LimitPppoeDuration', 'LimitVpnDuration', 'StatusInterval', 'MaxMailIn', 'MaxMailOut', 'MaxDiskSpace', 'MaxCpu', 'MaxHdTemp', 'MaxHwTemp', 'MaxSamba', 'MaxSsh', 'MaxFtp', 'MaxVpn') { if (!($q->param("$key")=~/\d+/)) { $verifok=0; $str=sprintf(gettext("\"%s\" is not an integer numeric value for the setting '%s'.\n"),$q->param("$key"),$key); print esmith::cgi::genTextRow($q,$q->p($str)); } } # si on vient de desactiver les mails de status, on affiche un message if ($params{'StatusInterval'} != 0 && $q->param('StatusInterval') == 0) { print esmith::cgi::genTextRow($q,$q->p(gettext("Status e-mails have been disabled.\n"))); } if ($modified){ foreach my $key (keys(%params)) { $smeadmindb->set_prop($key,$q->param($key)); } } } else #cas 2 :) { my $key=$q->param('alert'); $modified=1 if ($params{$key} ne $q->param("$key")); if (!($q->param("$key")=~/\d+/)) { $verifok=0; $str=sprintf(gettext("\"%s\" is not an integer numeric value for the setting '%s'.\n"),$q->param("$key"),$key); print esmith::cgi::genTextRow($q,$q->p($str)); } else { #on applique la nouvelle valeur $params{$q->param('alert')}=$q->param("$key"); } $smeadmindb->set_prop($key,$q->param($key)) if ($modified); } if ($verifok) { if ($modified) { #si un param a ete change, on notifie le demon avec un -SIGHUP # `pkill -SIGHUP smeadmind`; #notify the deamon is not enough we want to restart it when parameters are changed system ('service smeadmind restart 2>&1 1>/dev/null') == 0 or die 'ERROR: the service smeadmind can not be restarted'; print $q->table({-class =>"sme-borders"}, $q->Tr( $q->td( 'SUCCESS'), $q->td( $q->div( {-class=>"success"}, gettext("New settings have been saved."))))) ; } else { print esmith::cgi::genTextRow($q,$q->p(gettext("The settings are the same, nothing has been modified.\n"))); } } else { print $q->table({-class =>"sme-borders"}, $q->Tr( $q->td( 'ERROR'), $q->td( $q->div( {-class=>"error"}, gettext("An error occured. Check the settings you provided."))))) ; } print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } #---------------------------------------------------------------- #arret/demarrage du service (bourrin, oui, j'utilise pas serviceControl) sub svcControl { #pour tous les champs du formulaire qu'on a recu (normalement , juste 'state', et un 'start_$service' ou 'stop_$service' foreach ($q->param()) { #si le nom du parametre est (start|stop)_$svc if(/^(stop|start)_([\w-]+)$/) { #$_ est le nom du champ #$1 est l'action #$2 est le nom du service==doit etre egal a la valeur #si la valeur correspond a l'action if ($q->param("$_") eq "$1") { my $cmd=''; $cmd=`/usr/bin/systemctl $1 $2`; my @res=$cmd; foreach (@res) { print $q->p("$_\n");} } else #on a affaire a un petit malin qui bricole les parametres { print $q->p("Parametre incorrect1\n"); } } #si le nom du parametre est (enable|disable)_$svc if(/^(enabled|disabled)_([\w-]+)$/) { #$_ est le nom du champ #$1 est l'action #$2 est le nom du service==doit etre egal a la valeur #si la valeur correspond a l'action if ($q->param("$_")."d" eq "$1") { my @res=`/sbin/e-smith/db configuration setprop $2 status $1`; push(@res,`/sbin/e-smith/db configuration printprop $2 status`); # we should restart the service here because it should be stop if disabled !!! my $ordre=""; if ( $1 eq "enabled") {$ordre="start";} if ( $1 eq "disabled") {$ordre="stop";} my $cmd=''; if ($2=~/^(ulogd|smbd|nmbd|rsyslog)$/)#(-d "/service/$2") {$cmd = `/usr/bin/sv $ordre $2`;} else {$cmd=`/sbin/e-smith/service $2 $ordre`;} push(@res,$cmd); foreach (@res) { print $q->p("$_\n");} } else #on a affaire a un petit malin qui bricole les parametres { print $q->p("Parametre incorrect2\n"); } } } print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } #---------------------------------------------------------------- #Tests de connexion aux services de SME sub showAdvancedTest { #affichage de la liste des tests si le param 'service' n'est pas défini. if (!defined($q->param('service'))) { print $q->p(gettext("These differents tests may produce false positives, do not take care of them.")), $q->p(gettext("Execute them only if you know what they do, and how to analyse their results.")),$q->br, $q->start_table, $q->Tr($q->td(gettext("Test http service")), $q->td($q->a ({href => "$progname?state=advanced&service=http"},"http@\n"))), $q->Tr($q->td(gettext("Test samba service")), $q->td($q->a ({href => "$progname?state=advanced&service=samba"},"smbcontrol\n"))), $q->Tr($q->td(gettext("Test network latency")), $q->td($q->a ({href => "$progname?state=advanced&service=ping"},"ping\n"))), $q->Tr($q->td(gettext("Test ftp service")), $q->td($q->a ({href => "$progname?state=advanced&service=ftp"},"telnet 21\n"))), $q->Tr($q->td(gettext("Test ssh service")), $q->td($q->a ({href => "$progname?state=advanced&service=ssh"},"telnet ${SshPort}\n"))), $q->Tr($q->td(gettext("Test pop service")), $q->td($q->a ({href => "$progname?state=advanced&service=pop"},"telnet 110\n"))), $q->Tr($q->td(gettext("Test smtp service")), $q->td($q->a ({href => "$progname?state=advanced&service=smtp"},"telnet 25\n"))), $q->end_table; print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } #on fait le test avance else { #hack this to handle the server-only case my $record; $record = $smedb->get("SystemMode"); #on n'a une external ip que si on est en server-passerelle if ($record->value =~ /servergateway/) { $record = $smedb->get("ExternalIP"); } else { $record = $smedb->get("LocalIP"); } my $ip =$record->value; #test du service http => http@ if ($q->param('service') eq 'http') { print $q->p($q->b(gettext("Execution of 'http\@' (should return html source code of server's homepage):"))),$q->br; foreach (`/usr/local/bin/http@ 2>&1`) { print escapeHTML($_),$q->br; } } #test du service samba => smbcontrol smbd ping elsif ($q->param('service') eq 'samba') { print $q->p($q->b(gettext("Execution of 'smbcontrol smbd ping' (samba server answers giving its PID):"))),$q->br; foreach (`/usr/bin/smbcontrol smbd ping 2>&1`) { print $q->p($_); } } #test du service http => http@ elsif ($q->param('service') eq 'ping') { print $q->p($q->b(gettext("Execution of 'ping google.fr -c 1' (latency):"))),$q->br; foreach (`/bin/ping google.fr -c 1 2>&1`) { print $q->p($_); } } elsif ($q->param('service') eq 'ftp') { print $q->p($q->b(sprintf(gettext("Execution of 'echo \"SYST\" | nc %s 21' (ftp opened to the external network):"),$ip))),$q->br; foreach (`/bin/echo "SYST" | /usr/bin/nc $ip 21 2>&1`) { print $q->p($_); } } elsif ($q->param('service') eq 'ssh') { print $q->p($q->b(sprintf(gettext("Execution of 'echo \"hello\" | nc %s %s' (ssh opened to the external network):"),$ip,$SshPort))),$q->br; foreach (`/bin/echo "hello" | /usr/bin/nc $ip $SshPort 2>&1`) { print $q->p($_); } } elsif ($q->param('service') eq 'pop') { print $q->p($q->b(sprintf(gettext("Execution of 'echo \"quit\" | nc %s 110' (pop server running):"),$ip))),$q->br; foreach (`/bin/echo "quit" | /usr/bin/nc $ip 110 2>&1`) { print $q->p($_); } } elsif ($q->param('service') eq 'smtp') { print $q->p($q->b(sprintf(gettext("Execution of 'echo \"quit\" | nc -i 2 %s 25' (smtp server running):"),$ip))),$q->br; foreach (`/bin/echo "quit" | /usr/bin/nc -i 2 $ip 25 2>&1`) { print $q->p($_); } } print $q->p($q->a ({href => "$progname?state=advanced"},gettext("Another test\n"))); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } } #---------------------------------------------------------------- #DBI:mysql, connecte MOI sub connectBD { $bd=DBI->connect ("DBI:mysql:$params{'DbName'}","$params{'DbUser'}","$params{'DbPassword'}"); if (!defined ($bd)) { print $q->p("MySQL error : $DBI::errstr"); die (gettext("Check MySQL connection settings.\n")); } } #---------------------------------------------------------------- #DBI:mysql, deconnecte MOI sub deconnectBD { $bd->disconnect; if (!defined ($bd)) { print $q->p("MySQL error : $DBI::errstr"); die (gettext("Check MySQL connection settings.\n")); } } #---------------------------------------------------------------- # fonction prenant une ip numerique et renvoyant une ip format a.b.c.d # rapide hack peut-etre efficace... # (en fait j'ai trouve mieux dans esmith::util::IPaddrToQuad, je repompe le # code pour pas avoir a loader tout esmith::util) sub ipnum2ipdot { my ($addrBits) = @_; return sprintf( "%d.%d.%d.%d", ( $addrBits >> 24 ) & 0xff, ( $addrBits >> 16 ) & 0xff, ( $addrBits >> 8 ) & 0xff, $addrBits & 0xff ); } #---------------------------------------------------------------- # affiche un menu deroulant pour le choix de la duree des graphes sub printPopupMenu { my ($msg)=(@_); my %labels=("-1h"=>gettext("one hour"), "-6h"=>gettext("six hours"), "-1d"=>gettext("the day"), "-3d"=>gettext("three days"), "-7d"=>gettext("one week"), "-1m"=>gettext("one month"), "-6months"=>gettext("six months"), "-1y"=>gettext("one year")); print $q->start_form, $msg, $q->popup_menu(-name=>'duree', -values=>['-1h','-6h','-1d','-3d','-7d','-1m','-6months','-1y'], -default=>'-1d', -labels=>\%labels), $q->submit('action',"Go !"), $q->hidden(-name=>'state',-default=>$q->param('state'),-override=>1), $q->hidden(-name=>'service',-default=>$q->param('service'),-override=>1), $q->end_form,"\n"; } #---------------------------------------------------------------- #cette fonction cree et affiche le graphe supervisant $svc # $svc = {httpd, squid, samba, afp} sub showSvcGraph { my ($svc,$msg)=(@_); my $start='-1d'; printPopupMenu($msg); $start=$q->param('duree') if defined($q->param('duree')); #creation du graphe createShowGraph("","$svc$start", "--title=Service $svc", "--start=$start", "DEF:cpu=$rrddir/$svc.rrd:cpu:AVERAGE","DEF:maxcpu=$rrddir/$svc.rrd:cpu:MAX", "DEF:mem=$rrddir/$svc.rrd:mem:AVERAGE","DEF:maxmem=$rrddir/$svc.rrd:mem:MAX", "DEF:nbproc=$rrddir/$svc.rrd:nbproc:AVERAGE","DEF:maxnbproc=$rrddir/$svc.rrd:nbproc:MAX", "COMMENT: ", "AREA:mem#1144BB:\%Mem", "LINE2:cpu#FFDD00:\%Cpu", "LINE2:nbproc#CC1100:Nb Proc", "COMMENT:\\n", "COMMENT:Max\\:", "GPRINT:maxmem:MAX:%2.2lf %%", "GPRINT:maxcpu:MAX:%2.2lf %%", "GPRINT:maxnbproc:MAX:%2lg" ); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } #---------------------------------------------------------------- #cette fonction est juste un "aiguillage" vers la fonction qui affiche le service demande # on passe par ici en cliquant sur les liens correspondant aux noms des services sub showService { #les 4 premiers sont les services qui ont des rrds #les 7 derniers sont ceux qui ont des donnees dans mysql if ($q->param('service') eq 'httpd-e-smith' || $q->param('service') eq 'httpd-admin') {showHttpd();} elsif ($q->param('service') eq 'squid') {showSquid();} elsif ($q->param('service') eq 'smbd' || $q->param('service') eq 'smb' || $q->param('service') eq 'nmbd') {showSamba();} elsif ($q->param('service') eq 'atalkd') {showAfp();} elsif ($q->param('service') eq 'pptpd') {showVpn();} elsif ($q->param('service') eq 'dhcpd') {showDhcpd();} elsif ($q->param('service') eq 'sshd') {showSsh();} elsif ($q->param('service') eq 'proftpd') {showFtp();} elsif ($q->param('service') eq 'ftp') {showFtp();} elsif ($q->param('service') eq 'pppoe' || $q->param('service') eq 'wan' || $q->param('service') eq 'pppd' ) {showPppoe();} elsif ($q->param('service') eq 'qpsmtpd' || $q->param('service') eq 'sqpsmtpd' ) {showQpsmtpd();} elsif ($q->param('service') eq 'qmail') {showQmail();} elsif ($q->param('service') eq 'altqmail') {showQmail();} } #---------------------------------------------------------------- #details du service httpd sub showHttpd { showSvcGraph("httpd",gettext("System load for the apache web server (httpd-e-smith & httpd-admin processes) on ")); } #---------------------------------------------------------------- #details du service qmail sub showQmail { my $start='-1d'; printPopupMenu(gettext("View graphs on ")); $start=$q->param('duree') if defined($q->param('duree')); print $q->p($q->b($labels{"$start"})); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); #qmail local and remote email createGraphQmail($start); createGraphAltQmail($start); } #---------------------------------------------------------------- #details du service s?qpsmtpd sub showQpsmtpd { my $start='-1d'; printPopupMenu(gettext("View graphs on ")); $start=$q->param('duree') if defined($q->param('duree')); print $q->p($q->b($labels{"$start"})); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); #qpsmtpd incoming emails from outside the server( local network and internet) createGraphQpsmtpd($start); } #---------------------------------------------------------------- #details du service squid sub showSquid { showSvcGraph("squid",gettext("System load for the transparent http/ftp proxy squid on ")); } #---------------------------------------------------------------- #details du service samba sub showSamba { #voir plus bas pour explication des params showDbData( [ [gettext("IP Address"),sub { return ipnum2ipdot(@_); } ], [gettext("Login"),], [gettext("Hostname"),], [gettext("Start"),], [gettext("End"),] ], \"SELECT ip,login,machine,debut,derniere_vue FROM samba ORDER BY debut DESC", \gettext("Detailed list of the last times a host has connected to a samba share.\n")); #affichage du graphe showSvcGraph("samba",gettext("System load for the samba server (smbd & nmbd processes) on ")); } #---------------------------------------------------------------- #details du service appletalk sub showAfp { #voir plus bas pour explication des params showDbData( [ [gettext("Start"),], [gettext("End"),], [gettext("IP Address"),sub { return ipnum2ipdot(@_); } ], [gettext("Login"),], [gettext("Written data (Ko)"),], [gettext("Read data (Ko)"),] ], \"SELECT debut,fin,ip,login,volume_read,volume_write FROM afp WHERE debut > CURDATE() - INTERVAL 7 DAY ORDER BY debut DESC", \gettext("Detailed list of the last connections (on the last 7 days) to the afp service (Apple File Protocol).\n")); #affichage du graphe showSvcGraph("afp",gettext("System load for the appletalk server (atalkd, papd, afpd and cnid_metad processes).")); } #---------------------------------------------------------------- #details du service pptpd vpn sub showVpn { showDbData( [ [gettext("Start"),], [gettext("End"),], [gettext("Duration"),], [gettext("Client IP address"),sub { return ipnum2ipdot(@_); } ], [gettext("Client local IP address"),sub { return ipnum2ipdot(@_); } ], [gettext("Incoming data (Ko)"),sub {return sprintf('%.2f',$_[0]/1024);}], [gettext("Outgoing data (ko)"),sub {return sprintf('%.2f',$_[0]/1024);}], [gettext("Login"),] ], \"SELECT debut,fin,duree,ip,vpn_clt,volume_in,volume_out,login FROM vpn ORDER BY debut DESC", \gettext("Detailed list of vpn connections (Virtual Private Network).\n")); } #---------------------------------------------------------------- #details du service dhcpd sub showDhcpd { showDbData( [ [gettext("IP Address"),sub { return ipnum2ipdot(@_); } ], [gettext("MAC Address"),], [gettext("Hostname"),], [gettext("Date of renewal"),] ], \"SELECT ip,mac,hostname,debut FROM dhcpd ORDER BY debut DESC", \gettext("List of the last dhcp leases renewal (Dynamic Host Control Protocol).\n")); } #---------------------------------------------------------------- #details du service pppoe sub showPppoe { # get first db entry my $requete="SELECT substr(debut,1,4), substr(debut,6,2) FROM pppoe WHERE debut >= CURDATE() - INTERVAL 24 MONTH ORDER BY debut ASC LIMIT 1"; #connexion a la base de donnees mySQL connectBD(); #recuperation des donnees my $rq=$bd->prepare($requete) or print $q->p(sprintf(gettext("MySQL error : Impossible to prepare SQL query \"%s\" : %s\n"),$requete,$bd->errstr)); $rq->execute or print $q->p(sprintf(gettext("MySQL error : Can't execute query : %s\n"),$rq->errstr)); my @debut = $rq->fetchrow_array(); # get first db entry my $requete_DESC="SELECT substr(fin,1,4), substr(fin,6,2) FROM pppoe WHERE debut >= CURDATE() - INTERVAL 24 MONTH ORDER BY debut DESC LIMIT 1"; #connexion a la base de donnees mySQL connectBD(); #recuperation des donnees my $rq_DESC=$bd->prepare($requete_DESC) or print $q->p(sprintf(gettext("MySQL error : Impossible to prepare SQL query \"%s\" : %s\n"),$requete_DESC,$bd->errstr)); $rq_DESC->execute or print $q->p(sprintf(gettext("MySQL error : Can't execute query : %s\n"),$rq_DESC->errstr)); my @fin = $rq_DESC->fetchrow_array(); #$debut[1] -- if ($debut[1] == $fin[1]); my $end_yymm = $debut[0].$debut[1]; my $yymm = $fin[0].$fin[1]; my $startMonth = $debut[1]; my $startYear = $debut[0]; my $endMonth; my $endYear; my $preMonth; my $preYear; my $i=0; print $q->p(gettext("Traffic by Month")); print $q->start_table({-border=>'1'}), $q->start_Tr; print $q->th(gettext("year-month")); print $q->th(gettext("IN (GB)")); print $q->th(gettext("OUT (GB)")); print $q->th(gettext("TOTAL (GB)")); $q->end_Tr; my $nblines = 0; while ($end_yymm < $yymm || $nblines < 1) { $nblines =1; if ($startMonth eq '12') { $endMonth = 1; $endYear = $startYear + 1; } else { $endMonth = $startMonth + 1; $endYear = $startYear; } ## Now that you have the end year and month incremented setup the end_yymm variable again to be picked up in the while statement: $end_yymm = $startYear . ${\(length($startMonth) == 1 ? '0' : '')} . $startMonth; if ($startMonth eq '1') { $preMonth=12; $preYear=$startYear-1; } else { $preMonth=$startMonth-1; $preYear= $startYear; } # ...... carry on with the rest of your code # print "**$end_yymm
\n"; $requete="SELECT substring(`fin`,1,7) as 'month', round(SUM(`volume_in`)/1000/1000/1000,3) as 'In (Go)' , round(SUM(`volume_out`) /1000/1000/1000,3) as 'Out (Go)' , round(SUM(`volume_in` + `volume_out`)/1000/1000/1000,3) as 'Total (Go)' , SUM(TIME_TO_SEC(`duree`))/3600/24 as 'duree' FROM `pppoe` WHERE # mois (`debut`> '$startYear-$startMonth-01 00:00:00' and `fin`< '$endYear-$endMonth-01 00:00:00') # bordure or ( `debut`> '$preYear-$preMonth-01 00:00:00' and `debut`< '$startYear-$startMonth-01 00:00:00' and `fin`> '$startYear-$startMonth-01 00:00:00') or ( `debut`< '$endYear-$endMonth-01 00:00:00' and `fin`> '$endYear-$endMonth-01 00:00:00' and `fin`< '$endYear-$endMonth-28 00:00:00')"; my $rq=$bd->prepare($requete) or print $q->p(sprintf(gettext("MySQL error : Impossible to prepare SQL query \"%s\" : %s\n"),$requete,$bd->errstr)); $rq->execute or print $q->p(sprintf(gettext("MySQL error : Can't execute query : %s\n"),$rq->errstr)); my @ligne = $rq->fetchrow_array(); print $q->start_Tr; print $q->td("$startYear-". ${\(length($startMonth) == 1 ? '0' : '')} ."$startMonth"); print $q->td($ligne[1]); print $q->td($ligne[2]); print $q->td($ligne[3]); print $q->end_Tr; # get ready for next loop if ($startMonth eq '12') { $startMonth = 1; $startYear++; } else { $startMonth++ } } # end the while loop print $q->end_table; deconnectBD(); showDbData( [ [gettext("Start"),], [gettext("End"),], [gettext("Duration"),], [gettext("IP Address"),sub { return ipnum2ipdot(@_); } ], [gettext("Connection peer"),sub { return ipnum2ipdot(@_); } ], [gettext("Incoming data (MB)"),sub {return sprintf('%.2f',$_[0]/1000/1000);}], [gettext("Outgoing data (MB)"),sub {return sprintf('%.2f',$_[0]/1000/1000);}] ], \"SELECT debut,fin,duree,ip,peer,volume_in,volume_out,fin-debut as 'encours' FROM pppoe WHERE debut >= CURDATE() - INTERVAL 24 MONTH ORDER BY debut DESC", \gettext("Detailed list of ADSL/PPPoE connections.\n")); } #---------------------------------------------------------------- #details du service ssh sub showSsh { showDbData( [ [gettext("Start"),], [gettext("IP Address"),sub {return ipnum2ipdot(@_);}], [gettext("Login"),], [gettext("Connected ?"),sub {return (($_[0])?gettext('Yes'):gettext('No'));}] ], #pour cause de sprintf, la requete est dans le showDbData \"", \gettext("Detailed list of ssh connections (Secure SHell).\n")); } #---------------------------------------------------------------- #details du service ftp sub showFtp { #WARN ! Highly complicated !! # @tab est un tableau a 2 dimensions, chaque "ligne" du tableau contient 2 champs : # - le label/entete de la colonne a afficher # - une fonction inline de modification de l'affichage de la valeur allant dans la colonne # ( pour ce champ, il peut etre nul (d'ou le ["Start",]). my @tab=([gettext("Start"),], [gettext("End"),], [gettext("Duration"),], [gettext("IP Address"),sub {return ipnum2ipdot(@_);}], [gettext("Login"),], [gettext("Connected ?"),sub {return (($_[0])?gettext('Yes'):gettext('No'));}], [gettext("Written data (Ko)"),sub {return sprintf('%.2f',$_[0]/1024);}], [gettext("Read data (Ko)"),sub {return sprintf('%.2f',$_[0]/1024);}]); #appel de la fonction qui va interroger la bdd et afficher le tableau #passage des params par REFERENCE (tab, requete et titre a afficher) showDbData(\@tab, \"SELECT debut,fin,duree,ip,login,connecte,volume_in,volume_out FROM ftp WHERE debut > CURDATE() - INTERVAL 7 DAY ORDER BY debut DESC", \gettext("Detailed list of the last connections (on the last 7 days) to the ftp service (File Transfer Protocol).\n")); } #---------------------------------------------------------------- #DOCUMENT IT OR YOU'LL BE MAD - Magnifique HACK qui est trop elegant #Fonction qui fait la requete vers la BDD, et affiche le resultat en fonction #du @tab passe en param qui contient les entetes de colonne et les fonctions de #modif d'affichage. sub showDbData { #recuperation des params et DEREFERENCEMENT my ($ref_tab,$ref_requete,$ref_title)=(@_); my @tab=@$ref_tab; my $requete=$$ref_requete; my $title=$$ref_title; my $i=0; #utilise uniquement si service=pppoe my $start_next_cnx; #utilise uniquement si service=sshd my $interval; if ($q->param('service') eq 'sshd') { #gruika hack pour avoir le tableau sur plusieurs periodes printPopupMenu(gettext("See the records on ")); $interval=$q->param('duree'); #somebody please put a SWITCH CASE !! if ((!defined($interval)) || $interval eq '-7d') {$interval="7 DAY";} elsif ($interval eq '-1h') {$interval="1 HOUR";} elsif ($interval eq '-6h') {$interval="6 HOUR";} elsif ($interval eq '-1d') {$interval="1 DAY";} elsif ($interval eq '-3d') {$interval="3 DAY";} elsif ($interval eq '-1m') {$interval="1 MONTH";} elsif ($interval eq '-6months') {$interval="6 MONTH";} elsif ($interval eq '-1y') {$interval="1 YEAR";} $requete="SELECT debut,ip,login,ok FROM ssh WHERE debut > NOW() - INTERVAL $interval ORDER BY debut DESC"; } #connexion a la base de donnees mySQL connectBD(); #recuperation des donnees my $rq=$bd->prepare($requete) or print $q->p(sprintf(gettext("MySQL error : Impossible to prepare SQL query \"%s\" : %s\n"),$requete,$bd->errstr)); $rq->execute or print $q->p(sprintf(gettext("MySQL error : Can't execute query : %s\n"),$rq->errstr)); #affichage du debut de page print $q->p(gettext($title)); #affichage des eventuelles mises en evidence if ($q->param('service') eq 'pptpd') { print $q->table($q->Tr($q->td(gettext("Connections which lasted ")), $q->td({bgcolor=>"#FF4444"},sprintf(gettext("more than %s hours are highlighted.\n"),$params{'LimitVpnDuration'})))); } elsif ($q->param('service') eq 'wan'|| $q->param('service') eq 'pppoe' ) { print $q->table($q->Tr($q->td(gettext("Connections which lasted ")), $q->td({bgcolor=>"#FF4444"},sprintf(gettext("less than %s hours are highlighted.\n"),$params{'LimitPppoeDuration'})))), $q->table($q->Tr($q->td(gettext("Disconnections which lasted ")), $q->td({bgcolor=>"#9999FF"},sprintf(gettext("more than %s minutes are highlighted.\n"),$params{'LimitPppoeDisconnect'})))); } elsif ($q->param('service') eq 'sshd') { print $q->table($q->Tr($q->td(gettext("Successful ")),$q->td({bgcolor=>"#33CC00"},gettext(" root connections are highlighted.\n")))); } print $q->br, $q->start_table({-border=>'1'}), $q->start_Tr; #affichage des entetes du tableau foreach (@tab) { #j'aimerai bien comprendre le pourquoi du comment du 1er [0] #le $i est pour recup la "ligne" du tab passe en param #le 2e [0] est pour recup le label, 1ere valeur de la ligne print $q->th(gettext($_[0][$i][0])); $i++; } print $q->end_Tr; #boucle sur les lignes / resultats de la requete SQL while(my @ligne = $rq->fetchrow_array()) { $i=0; #affichage des lignes speciales (pour pptpd,ssh et pppoe only) if ($q->param('service') eq 'pptpd') { $ligne[2]=~/(\d{2}):\d{2}:\d{2}/; #si le nb d'heure > limite, surbrillance print $q->start_Tr({bgcolor=>(($1 >= $params{'LimitVpnDuration'})?"#FF4444":"#FFFFFF")}); } elsif ($q->param('service') eq 'wan' || $q->param('service') eq 'pppoe') { #on interroge la bd pour voir si il y a eu une longue deconnexion #(beaucoup plus simple que de parser les 2 dates et faire une difference, la on utilise la possibilite de calcul de diff de dates de MySQL) $requete="select '$start_next_cnx' > '$ligne[1]' + interval $params{'LimitPppoeDisconnect'} minute"; my $rq2=$bd->prepare($requete) or print $q->p(sprintf(gettext("MySQL error : Impossible to prepare SQL query \"%s\" : %s\n"),$requete,$bd->errstr)); $rq2->execute or print $q->p(sprintf(gettext("MySQL error : Can't execute query : %s\n"),$rq->errstr)); #on sauve le debut de la cnx pour faire la comparaison au debut de boucle $start_next_cnx=$ligne[0]; #si on a trouve que la connexion suivante avait commence apres la fin de connexion precedente + interval defini #alors afficher une ligne de separation print $q->Tr($q->td({bgcolor=>"#9999FF",colspan=>"7"},sprintf(gettext("Disconnection lasted more than %s minutes"),$params{'LimitPppoeDisconnect'}))) if (($rq2->fetchrow_array)[0] eq '1'); #on match le nb d'heure de la duree cnx my $curdur; if ($ligne[2]) { # ended connection $ligne[2]=~/(\d{2}):\d{2}:\d{2}/; $curdur=$1; }else{ # ongoing connection $curdur=$ligne[7]/3600; } #si le nb d'heure < limite et different de null, surbrillance print $q->start_Tr({bgcolor=>((($curdur < $params{'LimitPppoeDuration'}) && ($1 ne ''))?"#FF4444":"#FFFFFF")}); } elsif ($q->param('service') eq 'sshd') { #si login root && connecte, surbrillance print $q->start_Tr({bgcolor=>(($ligne[2] eq 'root')&& $ligne[3])?"#33CC00":"#FFFFFF"}); } else { print $q->start_Tr; } #boucle sur les champs de la ligne foreach (@tab) { #on recupere la fonction de mise en forme de la valeur my $func=$_[0][$i][1]; #si elle existe if (defined ($func)) #on l'applique a la valeur (contenue dans $ligne[$i]) { print $q->td(&$func($ligne[$i]));} else #sinon, on affiche directement la valeur { print $q->td($ligne[$i]);} $i++; } print $q->end_Tr; } print $q->end_table, $q->p($q->a ({href => "$progname"},gettext("Back\n"))); deconnectBD(); } #---------------------------------------------------------------- #fonction faisant les appels a RRDs::graph #creation de l'image, affichage d'un titre, affichage de l'image sub createShowGraph { my($title,$imgFilename,@rrdparams)=(@_); # print "
" . join("|", @rrdparams) . "
"; my (undef,$xsize,$ysize)=RRDs::graph ("$imgdir/$imgFilename.$params{'ImgFormat'}", "--imgformat=$params{'ImgFormat'}", "--width=$params{'ImgWidth'}", "--height=$params{'ImgHeight'}", @rrdparams); my $error=RRDs::error; print $q->p(sprintf(gettext("Error at RRDs::graph(%s) : %s\n"),"$imgFilename.$params{'ImgFormat'}",$error)) if $error; print $q->p($title),$q->br, $q->img({src=>"../smeadmin/$imgFilename.$params{'ImgFormat'}",alt=>"../smeadmin/$imgFilename.$params{'ImgFormat'}",width=>$xsize,height=>$ysize}); } #---------------------------------------------------------------- #affiche les graphes avec les sensors materiels # - temp process, mb & hdd1/2 # - vitesse rotation ventilateur #---------------------------------------------------------------- sub showHardGraph { my $start='-1d'; printPopupMenu(gettext("View graphs on ")); $start=$q->param('duree') if defined($q->param('duree')); print $q->p($q->b($labels{"$start"})); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); my @tab=("--title=".gettext("Temperatures"), "--vertical-label=T°C", "--start=$start", "DEF:t1=$rrddir/sensors.rrd:t1:AVERAGE", "DEF:maxt1=$rrddir/sensors.rrd:t1:MAX", "DEF:mint1=$rrddir/sensors.rrd:t1:MIN", "DEF:t2=$rrddir/sensors.rrd:t2:AVERAGE", "DEF:maxt2=$rrddir/sensors.rrd:t2:MAX", "DEF:mint2=$rrddir/sensors.rrd:t2:MIN", "COMMENT: ", "LINE2:t1#1000FF:Temp 1 ", "LINE2:t2#00EEBB:Temp 2 ", "COMMENT:\\n", "COMMENT:Max\\: ", "GPRINT:maxt1:MAX:%5.2lf °C", "GPRINT:maxt2:MAX:%5.2lf °C ", "COMMENT:\\n", "COMMENT:Min\\: ", "GPRINT:mint1:MIN:%5.2lf °C", "GPRINT:mint2:MIN:%5.2lf °C ", "COMMENT:\\n", "COMMENT:Avg\\: ", "GPRINT:t1:AVERAGE:%5.2lf °C", "GPRINT:t2:AVERAGE:%5.2lf °C ", "COMMENT:\\n", "COMMENT:Last\\:", "GPRINT:t1:LAST:%5.2lf °C", "GPRINT:t2:LAST:%5.2lf °C ", "COMMENT:\\n"); #creation du graphe des temperatures createShowGraph(gettext("Hardware temperatures (Processor, motherboard)."),"temperature",@tab); #start to retrieve data for the hard disks sensors my $has_second_hd=1; $has_second_hd=0 if ($params{'hd2'} eq ''); my $has_third_hd=1; $has_third_hd=0 if ($params{'hd3'} eq ''); my $has_fourth_hd=1; $has_fourth_hd=0 if ($params{'hd4'} eq ''); my $has_fifth_hd=1; $has_fifth_hd=0 if ($params{'hd5'} eq ''); my $has_sixth_hd=1; $has_sixth_hd=0 if ($params{'hd6'} eq ''); my @HDtab=("--title=".gettext("Hard-disks Temperatures"), "--vertical-label=T°C", "--start=$start", "DEF:thd1=$rrddir/sensors.rrd:thd1:AVERAGE", "DEF:maxthd1=$rrddir/sensors.rrd:thd1:MAX", "DEF:minthd1=$rrddir/sensors.rrd:thd1:MIN"); push @HDtab, "DEF:thd2=$rrddir/sensors.rrd:thd2:AVERAGE", "DEF:maxthd2=$rrddir/sensors.rrd:thd2:MAX", "DEF:minthd2=$rrddir/sensors.rrd:thd2:MIN" if ($has_second_hd); push @HDtab, "DEF:thd3=$rrddir/sensors.rrd:thd3:AVERAGE", "DEF:maxthd3=$rrddir/sensors.rrd:thd3:MAX", "DEF:minthd3=$rrddir/sensors.rrd:thd3:MIN" if ($has_third_hd); push @HDtab, "DEF:thd4=$rrddir/sensors.rrd:thd4:AVERAGE", "DEF:maxthd4=$rrddir/sensors.rrd:thd4:MAX", "DEF:minthd4=$rrddir/sensors.rrd:thd4:MIN" if ($has_fourth_hd); push @HDtab, "DEF:thd5=$rrddir/sensors.rrd:thd5:AVERAGE", "DEF:maxthd5=$rrddir/sensors.rrd:thd5:MAX", "DEF:minthd5=$rrddir/sensors.rrd:thd5:MIN" if ($has_fifth_hd); push @HDtab, "DEF:thd6=$rrddir/sensors.rrd:thd6:AVERAGE", "DEF:maxthd6=$rrddir/sensors.rrd:thd6:MAX", "DEF:minthd6=$rrddir/sensors.rrd:thd6:MIN" if ($has_sixth_hd); push @HDtab, "COMMENT: ", "LINE2:thd1#CC5500:Temp hd 1"; push @HDtab, "LINE2:thd2#550000:Temp hd 2" if ($has_second_hd); push @HDtab, "LINE2:thd3#1000FF:Temp hd 3" if ($has_third_hd); push @HDtab, "LINE2:thd4#00EEBB:Temp hd 4" if ($has_fourth_hd); push @HDtab, "LINE2:thd5#FF2222:Temp hd 5" if ($has_fifth_hd); push @HDtab, "LINE2:thd6#FFD700:Temp hd 6" if ($has_sixth_hd); push @HDtab, "COMMENT:\\n", "COMMENT:Max\\:", "GPRINT:maxthd1:MAX:%5.2lf °C "; push @HDtab, "GPRINT:maxthd2:MAX:%5.2lf °C " if ($has_second_hd); push @HDtab, "GPRINT:maxthd3:MAX:%5.2lf °C " if ($has_third_hd); push @HDtab, "GPRINT:maxthd4:MAX:%5.2lf °C " if ($has_fourth_hd); push @HDtab, "GPRINT:maxthd5:MAX:%5.2lf °C " if ($has_fifth_hd); push @HDtab, "GPRINT:maxthd6:MAX:%5.2lf °C" if ($has_sixth_hd); push @HDtab, "COMMENT:\\n", "COMMENT:Min\\: ", "GPRINT:minthd1:MIN:%5.2lf °C "; push @HDtab, "GPRINT:minthd2:MIN:%5.2lf °C " if ($has_second_hd); push @HDtab, "GPRINT:minthd3:MIN:%5.2lf °C " if ($has_third_hd); push @HDtab, "GPRINT:minthd4:MIN:%5.2lf °C " if ($has_fourth_hd); push @HDtab, "GPRINT:minthd5:MIN:%5.2lf °C " if ($has_fifth_hd); push @HDtab, "GPRINT:minthd6:MIN:%5.2lf °C" if ($has_sixth_hd); push @HDtab, "COMMENT:\\n", "COMMENT:Avg\\: ", "GPRINT:thd1:AVERAGE:%5.2lf °C "; push @HDtab, "GPRINT:thd2:AVERAGE:%5.2lf °C " if ($has_second_hd); push @HDtab, "GPRINT:thd3:AVERAGE:%5.2lf °C " if ($has_third_hd); push @HDtab, "GPRINT:thd4:AVERAGE:%5.2lf °C " if ($has_fourth_hd); push @HDtab, "GPRINT:thd5:AVERAGE:%5.2lf °C " if ($has_fifth_hd); push @HDtab, "GPRINT:thd6:AVERAGE:%5.2lf °C" if ($has_sixth_hd); push @HDtab, "COMMENT:\\n", "COMMENT:Last\\:", "GPRINT:thd1:LAST:%5.2lf °C "; push @HDtab, "GPRINT:thd2:LAST:%5.2lf °C " if ($has_second_hd); push @HDtab, "GPRINT:thd3:LAST:%5.2lf °C " if ($has_third_hd); push @HDtab, "GPRINT:thd4:LAST:%5.2lf °C " if ($has_fourth_hd); push @HDtab, "GPRINT:thd5:LAST:%5.2lf °C " if ($has_fifth_hd); push @HDtab, "GPRINT:thd6:LAST:%5.2lf °C" if ($has_sixth_hd); push @HDtab, "COMMENT:\\n"; #creation du graphe des temperatures createShowGraph(gettext("Hard disks temperatures."),"HD temperature",@HDtab); #start to retrieve data for the Fan speed my $has_second_fan=1; $has_second_fan=0 if ($params{'SensorsTagFan2'} eq ''); my @tabfan=("--title=".gettext("Fan speed"), "--vertical-label=".gettext("Rpm"), "--start=$start", "DEF:fspd=$rrddir/sensors.rrd:fspd:AVERAGE","DEF:maxfspd=$rrddir/sensors.rrd:fspd:MAX","DEF:minfspd=$rrddir/sensors.rrd:fspd:MIN"); push @tabfan, "DEF:fspd2=$rrddir/sensors.rrd:fspd2:AVERAGE", "DEF:maxfspd2=$rrddir/sensors.rrd:fspd2:MAX", "DEF:minfspd2=$rrddir/sensors.rrd:fspd2:MIN" if ($has_second_fan); push @tabfan, "COMMENT: ", "LINE2:fspd#1000FF:".gettext("Fan speed") . " "; push @tabfan, "LINE2:fspd2#550000:".gettext("Fan speed"), "COMMENT:\\n" if ($has_second_fan); push @tabfan, "COMMENT:\\n", "COMMENT:Max\\: ", "GPRINT:maxfspd:MAX:%5.0lf ".gettext("Rpm"). " "; push @tabfan, "GPRINT:maxfspd2:MAX:%5.0lf ".gettext("Rpm") if ($has_second_fan); push @tabfan, "COMMENT:\\n", "COMMENT:Min\\: ", "GPRINT:minfspd:MIN:%5.0lf ".gettext("Rpm"). " "; push @tabfan, "GPRINT:minfspd2:MIN:%5.0lf ".gettext("Rpm") if ($has_second_fan); push @tabfan, "COMMENT:\\n", "COMMENT:Avg\\: ", "GPRINT:fspd:AVERAGE:%5.0lf ".gettext("Rpm"). " "; push @tabfan, "GPRINT:fspd2:AVERAGE:%5.0lf ".gettext("Rpm") if ($has_second_fan); push @tabfan, "COMMENT:\\n", "COMMENT:Last\\: ", "GPRINT:fspd:LAST:%5.0lf ".gettext("Rpm"). " "; push @tabfan, "GPRINT:fspd2:LAST:%5.0lf ".gettext("Rpm") if ($has_second_fan); push @tabfan, "COMMENT:\\n"; #creation of the fan speed sensors createShowGraph(gettext("Processor fan speed."),"fanspeed",@tabfan); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } #---------------------------------------------------------------- #affiche les graphes reseau # - sessions # - volume brut transfert / reseau local / externe / route # - baux dhcp # - volume mail/spam/virus # - latency #---------------------------------------------------------------- sub showNetGraph { my $start='-1d'; printPopupMenu(gettext("View graphs on ")); $start=$q->param('duree') if defined($q->param('duree')); print $q->p($q->b($labels{$start})); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); #sessions par netstat createShowGraph(gettext("Number of opened tcp connections for ssh, ftp, vpn, afp and netbios protocols."),"sessions", "--title=".gettext("Opened connections"), "--start=$start", "DEF:ssh=$rrddir/sessions.rrd:ssh:AVERAGE", "DEF:maxssh=$rrddir/sessions.rrd:ssh:MAX", "DEF:minssh=$rrddir/sessions.rrd:ssh:MIN", "DEF:vpn=$rrddir/sessions.rrd:vpn:AVERAGE", "DEF:maxvpn=$rrddir/sessions.rrd:vpn:MAX", "DEF:minvpn=$rrddir/sessions.rrd:vpn:MIN", "DEF:ftp=$rrddir/sessions.rrd:ftp:AVERAGE", "DEF:maxftp=$rrddir/sessions.rrd:ftp:MAX", "DEF:minftp=$rrddir/sessions.rrd:ftp:MIN", "DEF:netbios=$rrddir/sessions.rrd:netbios:AVERAGE", "DEF:maxnetbios=$rrddir/sessions.rrd:netbios:MAX", "DEF:minnetbios=$rrddir/sessions.rrd:netbios:MIN", "DEF:afp=$rrddir/sessions.rrd:afp:AVERAGE", "DEF:maxafp=$rrddir/sessions.rrd:afp:MAX", "DEF:minafp=$rrddir/sessions.rrd:afp:MIN", "COMMENT: ","LINE2:ssh#0000FF:ssh ($SshPort)","LINE2:ftp#FF2222:ftp (21)","LINE2:vpn#AA3300:vpn (1723)", "LINE2:netbios#33B010:netbios (139)","LINE2:afp#FFD700:afp (548)","COMMENT:\\n", "COMMENT:Max\\: ","GPRINT:maxssh:MAX:%4.0lf ","GPRINT:maxftp:MAX:%4.0lf ","GPRINT:maxvpn:MAX:%4.0lf ", "GPRINT:maxnetbios:MAX:%4.0lf ","GPRINT:maxafp:MAX:%4.0lf ","COMMENT:\\n", "COMMENT:Min\\: ","GPRINT:minssh:MIN:%4.0lf ","GPRINT:minftp:MIN:%4.0lf ","GPRINT:minvpn:MIN:%4.0lf ", "GPRINT:minnetbios:MIN:%4.0lf ","GPRINT:minafp:MIN:%4.0lf ","COMMENT:\\n", "COMMENT:Last\\:","GPRINT:ssh:LAST:%4.0lf ","GPRINT:ftp:LAST:%4.0lf ","GPRINT:vpn:LAST:%4.0lf ", "GPRINT:netbios:LAST:%4.0lf ","GPRINT:afp:LAST:%4.0lf ","COMMENT:\\n"); #baux dhcp, smbstatus:S createShowGraph(gettext("Number of dhcp leases renewals and opened samba shares."),"dhcpsmb", "--title=".gettext("Dhcp & Smbstatus"), "--start=$start", "DEF:samba=$rrddir/net.rrd:samba:AVERAGE", "DEF:maxsamba=$rrddir/net.rrd:samba:MAX", "DEF:minsamba=$rrddir/net.rrd:samba:MIN", "DEF:dhcp=$rrddir/net.rrd:dhcp:AVERAGE", "DEF:maxdhcp=$rrddir/net.rrd:dhcp:MAX", "DEF:mindhcp=$rrddir/net.rrd:dhcp:MIN", "COMMENT: ","LINE2:dhcp#8B4513:Dhcp","LINE2:samba#DAA520:Samba","COMMENT:\\n", "COMMENT:Max\\: ","GPRINT:maxdhcp:MAX:%4.0lf ","GPRINT:maxsamba:MAX:%4.0lf","COMMENT:\\n", "COMMENT:Min\\: ","GPRINT:mindhcp:MIN:%4.0lf ","GPRINT:minsamba:MIN:%4.0lf","COMMENT:\\n", "COMMENT:Last\\:","GPRINT:dhcp:LAST:%4.0lf ","GPRINT:samba:LAST:%4.0lf","COMMENT:\\n"); #qmail local and remote email createGraphQmail($start); #qpsmtpd incoming emails from outside the server( local network and internet) createGraphQpsmtpd($start); #ping latency createShowGraph(gettext("Average and maximal ping with the selected target."),"latency", "--title=".gettext("Target ping latency"), "--vertical-label=s/%", "--start=$start", "DEF:avglatency=$rrddir/net.rrd:avglatency:AVERAGE","DEF:maxavglatency=$rrddir/net.rrd:avglatency:MAX","DEF:minavglatency=$rrddir/net.rrd:avglatency:MIN", "DEF:maxlatency=$rrddir/net.rrd:maxlatency:AVERAGE","DEF:maxmaxlatency=$rrddir/net.rrd:maxlatency:MAX","DEF:minmaxlatency=$rrddir/net.rrd:maxlatency:MIN", "DEF:minlatency=$rrddir/net.rrd:minlatency:AVERAGE","DEF:maxminlatency=$rrddir/net.rrd:minlatency:MAX", "DEF:minminlatency=$rrddir/net.rrd:minlatency:MIN", "DEF:loss=$rrddir/net.rrd:loss:AVERAGE","DEF:maxloss=$rrddir/net.rrd:loss:MAX","DEF:minloss=$rrddir/net.rrd:loss:MIN", "CDEF:adjavglatency=avglatency,$maxping,MIN","CDEF:adjmaxlatency=maxlatency,$maxping,MIN","CDEF:adjloss=loss,1000,/", "COMMENT: ","AREA:adjmaxlatency#00008B:".gettext("Max ping"),"AREA:adjavglatency#00EE22:".gettext("Avg ping"), "LINE1:adjloss#FF4444:".gettext("Pkt loss"),"COMMENT:\\n", "COMMENT:Max\\: ",'GPRINT:maxmaxlatency:MAX:%6.2lf %ss ','GPRINT:maxavglatency:MAX:%6.2lf %ss ','GPRINT:maxloss:MAX:%6.2lf %%',"COMMENT:\\n", "COMMENT:Min\\: ",'GPRINT:minmaxlatency:MIN:%6.2lf %ss ','GPRINT:minavglatency:MIN:%6.2lf %ss ','GPRINT:minloss:MAX:%6.2lf %%',"COMMENT:\\n", "COMMENT:Last\\:",'GPRINT:maxlatency:LAST:%6.2lf %ss ','GPRINT:avglatency:LAST:%6.2lf %ss ','GPRINT:loss:LAST:%6.2lf %%',"COMMENT:\\n"); #trafic sur l'interface cote reseau local createShowGraph(gettext("Load on the local network interface."),"if_loc", "--title=".gettext("Local network load"), "--vertical-label=KB/s", "--start=$start","--base=1000","--lower-limit=0", "DEF:bin=$rrddir/if_loc.rrd:bin:AVERAGE","DEF:maxbin=$rrddir/if_loc.rrd:bin:MAX","DEF:bout=$rrddir/if_loc.rrd:bout:AVERAGE","DEF:maxbout=$rrddir/if_loc.rrd:bout:MAX","DEF:minbin=$rrddir/if_loc.rrd:bin:MIN","DEF:minbout=$rrddir/if_loc.rrd:bout:MIN", "CDEF:adj_bout=0,bout,-", "COMMENT: ","AREA:bin#0066FF:".gettext("Incoming Kilobytes"),"AREA:adj_bout#FF6633:".gettext("Outgoing Kilobytes"),"COMMENT:\\n", "COMMENT:Max\\: ",'GPRINT:maxbin:MAX:%8.2lf %sKB/s','GPRINT:maxbout:MAX:%8.2lf %sKB/s',"COMMENT:\\n", "COMMENT:Min\\: ",'GPRINT:minbin:MIN:%8.2lf %sKB/s','GPRINT:minbout:MIN:%8.2lf %sKB/s',"COMMENT:\\n", "COMMENT:Last\\:",'GPRINT:bin:LAST:%8.2lf %sKB/s','GPRINT:bout:LAST:%8.2lf %sKB/s',"COMMENT:\\n"); #si on a une 2e interface reseay if ($ExternalInterface ne "") { #trafic sur l'interface cote reseau externe createShowGraph(gettext("Load on the external network interface (to internet)."),"if_ext", "--title=".gettext("External network load"), "--vertical-label=KB/s", "--start=$start","--base=1000","--lower-limit=0", "DEF:bin=$rrddir/if_ext.rrd:bin:AVERAGE","DEF:maxbin=$rrddir/if_ext.rrd:bin:MAX","DEF:bout=$rrddir/if_ext.rrd:bout:AVERAGE","DEF:maxbout=$rrddir/if_ext.rrd:bout:MAX","DEF:minbin=$rrddir/if_ext.rrd:bin:MIN","DEF:minbout=$rrddir/if_ext.rrd:bout:MIN", "CDEF:adj_bout=0,bout,-", "COMMENT: ","AREA:bin#FF6633:".gettext("Incoming Kilobytes"),"AREA:adj_bout#0066FF:".gettext("Outgoing Kilobytes"),"COMMENT:\\n", "COMMENT:Max\\: ",'GPRINT:maxbin:MAX:%8.2lf %sKB/s','GPRINT:maxbout:MAX:%8.2lf %sKB/s',"COMMENT:\\n", "COMMENT:Min\\: ",'GPRINT:minbin:MIN:%8.2lf %sKB/s','GPRINT:minbout:MIN:%8.2lf %sKB/s',"COMMENT:\\n", "COMMENT:Last\\:",'GPRINT:bin:LAST:%8.2lf %sKB/s','GPRINT:bout:LAST:%8.2lf %sKB/s',"COMMENT:\\n"); print $q->p(gettext("Network load on the server except routing.")), $q->ul( $q->li(gettext("If the blue curve is :")), $q->ul( $q->li(gettext("positive => download from the internet")), $q->li(gettext("negative => upload from the local network")), ), $q->li(gettext("If the red curve is :")), $q->ul( $q->li(gettext("positive => upload from the internet")), $q->li(gettext("negative => download from the local network")) )),$q->br; createShowGraph("","if_delta", "--title=".gettext("Network load on the server"), "--vertical-label=KB/s", "--start=$start","--base=1000","--lower-limit=0", "DEF:extbin=$rrddir/if_ext.rrd:bin:AVERAGE","DEF:maxextbin=$rrddir/if_ext.rrd:bin:MAX","DEF:extbout=$rrddir/if_ext.rrd:bout:AVERAGE","DEF:maxextbout=$rrddir/if_ext.rrd:bout:MAX", "DEF:locbin=$rrddir/if_loc.rrd:bin:AVERAGE","DEF:maxlocbin=$rrddir/if_loc.rrd:bin:MAX","DEF:locbout=$rrddir/if_loc.rrd:bout:AVERAGE","DEF:maxlocbout=$rrddir/if_loc.rrd:bout:MAX", "CDEF:loc_srv=extbout,locbin,-","CDEF:srv_net=extbin,locbout,-", "COMMENT: ","LINE2:loc_srv#3300FF:Server=>Net - Local=>Server","LINE2:srv_net#FF0033:Net=>Server - Server=>Local","COMMENT:\\n"); } print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } #---------------------------------------------------------------- #---------------------------------------------------------------- #affiche les graphes systeme # - cpu:user/system/nice # - cpu:load1/load5/load15/total # - cpu:runq/plist # - cpu:uptime # - mem:used/cached/buffer/free # - mem:swap used/free # - hd:du # - hd:blkread/blkwrite sub showSystmGraph { my $start='-1d'; printPopupMenu(gettext("View graphs on ")); $start=$q->param('duree') if defined($q->param('duree')); print $q->p($q->b($labels{$start})); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); #repartition user/nice/system createShowGraph(gettext("Distribution of cpu usage for system, user and niced processes."),"cpu_usage", "--title=".gettext("Cpu usage"), "--vertical-label=%", "--start=$start","--base=1000","--lower-limit=0", "DEF:user=$rrddir/cpu.rrd:user:AVERAGE","DEF:maxuser=$rrddir/cpu.rrd:user:MAX","DEF:minuser=$rrddir/cpu.rrd:user:MIN", "DEF:system=$rrddir/cpu.rrd:system:AVERAGE","DEF:maxsystem=$rrddir/cpu.rrd:system:MAX","DEF:minsystem=$rrddir/cpu.rrd:system:MIN", "DEF:nice=$rrddir/cpu.rrd:nice:AVERAGE","DEF:maxnice=$rrddir/cpu.rrd:nice:MAX","DEF:minnice=$rrddir/cpu.rrd:nice:MIN", "COMMENT: ", "AREA:system#0066FF: System ", "STACK:nice#330066: Nice ", "STACK:user#00FF33: User", "COMMENT:\\n", "COMMENT:Max\\: ", 'GPRINT:maxsystem:MAX:%7.2lf %%', 'GPRINT:maxnice:MAX: %7.2lf %%', 'GPRINT:maxuser:MAX: %7.2lf %%', "COMMENT:\\n", "COMMENT:Min\\: ", 'GPRINT:minsystem:MIN:%7.2lf %%', 'GPRINT:minnice:MIN: %7.2lf %%', 'GPRINT:minuser:MIN: %7.2lf %%', "COMMENT:\\n", "COMMENT:Avg\\: ", 'GPRINT:system:AVERAGE:%7.2lf %%', 'GPRINT:nice:AVERAGE: %7.2lf %%', 'GPRINT:user:AVERAGE: %7.2lf %%', "COMMENT:\\n", "COMMENT:Last\\:", 'GPRINT:system:LAST:%7.2lf %%', 'GPRINT:nice:LAST: %7.2lf %%', 'GPRINT:user:LAST: %7.2lf %%',"COMMENT:\\n"); #load average sur 1/5 & 15mn // total cpu createShowGraph(gettext("System load average on 1mn,5mn,15mn compared to cpu usage."),"cpu_load", "--title=".gettext("System load / Cpu %"), "--vertical-label={Load*10} / %", "--start=$start","--base=1000","--lower-limit=0", "DEF:load1=$rrddir/cpu.rrd:load1:AVERAGE", "DEF:maxload1=$rrddir/cpu.rrd:load1:MAX", "DEF:minload1=$rrddir/cpu.rrd:load1:MIN", "DEF:load5=$rrddir/cpu.rrd:load5:AVERAGE", "DEF:maxload5=$rrddir/cpu.rrd:load5:MAX", "DEF:minload5=$rrddir/cpu.rrd:load5:MIN", "DEF:load15=$rrddir/cpu.rrd:load15:AVERAGE","DEF:maxload15=$rrddir/cpu.rrd:load15:MAX", "DEF:minload15=$rrddir/cpu.rrd:load15:MIN", "DEF:total=$rrddir/cpu.rrd:total:AVERAGE", "DEF:maxtotal=$rrddir/cpu.rrd:total:MAX", "DEF:mintotal=$rrddir/cpu.rrd:total:MIN", "CDEF:adjload1=load1,10,*", "CDEF:adjload5=load5,10,*", "CDEF:adjload15=load15,10,*", "COMMENT: ", "AREA:total#22BB00: Cpu ","LINE1:adjload1#0000DD: Load1 ", "LINE1:adjload5#EE2200: Load5 ","LINE1:adjload15#EEFF00: Load15 ", "COMMENT:\\n", "COMMENT:Max\\: ",'GPRINT:maxtotal:MAX:%7.2lf %%','GPRINT:maxload1:MAX:%7.3lf ', 'GPRINT:maxload5:MAX: %7.3lf ', 'GPRINT:maxload15:MAX: %7.3lf ', "COMMENT:\\n", "COMMENT:Min\\: ",'GPRINT:mintotal:MIN:%7.2lf %%','GPRINT:minload1:MIN:%7.3lf ', 'GPRINT:minload5:MIN: %7.3lf ', 'GPRINT:minload15:MIN: %7.3lf ', "COMMENT:\\n", "COMMENT:Avg\\: ",'GPRINT:total:AVERAGE:%7.2lf %%','GPRINT:load1:AVERAGE:%7.3lf ', 'GPRINT:load5:AVERAGE: %7.3lf ','GPRINT:load15:AVERAGE: %7.3lf ',"COMMENT:\\n", "COMMENT:Last\\:",'GPRINT:total:LAST:%7.2lf %%','GPRINT:load1:LAST:%7.3lf ', 'GPRINT:load5:LAST: %7.3lf ','GPRINT:load15:LAST: %7.3lf ',"COMMENT:\\n"); #process list/run queue createShowGraph(gettext("Number of running processes on the server, and kernel run queue size."),"cpu_process", "--title=".gettext("Number of processes / run queue size"), "--vertical-label=Nb proc / {Rq*10}", "--start=$start","--base=1000","--lower-limit=0", "DEF:plist=$rrddir/cpu.rrd:plist:AVERAGE","DEF:maxplist=$rrddir/cpu.rrd:plist:MAX","DEF:minplist=$rrddir/cpu.rrd:plist:MIN", "DEF:runq=$rrddir/cpu.rrd:runq:AVERAGE","DEF:maxrunq=$rrddir/cpu.rrd:runq:MAX","DEF:minrunq=$rrddir/cpu.rrd:runq:MIN", "CDEF:adjrunq=runq,10,*", "COMMENT: ", "AREA:plist#FFDD00: ".gettext("Processes"),"LINE1:adjrunq#EE3300: ".gettext("Run queue"), "COMMENT:\\n", "COMMENT:Max\\: ", 'GPRINT:maxplist:MAX:%4.0lf ','GPRINT:maxrunq:MAX: %7.3lf ', "COMMENT:\\n", "COMMENT:Min\\: ", 'GPRINT:minplist:MIN:%4.0lf ','GPRINT:minrunq:MIN: %7.3lf ', "COMMENT:\\n", "COMMENT:Avg\\: ", 'GPRINT:plist:AVERAGE:%4.0lf ', 'GPRINT:runq:AVERAGE: %7.3lf ',"COMMENT:\\n", "COMMENT:Last\\:", 'GPRINT:plist:LAST:%4.0lf ', 'GPRINT:runq:LAST: %7.3lf',"COMMENT:\\n"); #uptime createShowGraph(gettext("Server uptime."),"cpu_uptime", "--title=".gettext("Uptime"), "--vertical-label=".gettext("Days"), "--start=$start","--base=1000","--lower-limit=0", "DEF:uptime=$rrddir/cpu.rrd:uptime:AVERAGE","DEF:maxuptime=$rrddir/cpu.rrd:uptime:MAX","DEF:minuptime=$rrddir/cpu.rrd:uptime:MIN", "CDEF:adjuptime=uptime,86400,/", "CDEF:adjmaxuptime=maxuptime,86400,/", "CDEF:adjminuptime=minuptime,86400,/", "COMMENT: ", "AREA:adjuptime#FF1100: ".gettext("Uptime"),"COMMENT:\\n", "COMMENT:Max\\: ", 'GPRINT:adjmaxuptime:MAX: %4.1lf', "COMMENT:\\n", "COMMENT:Min\\: ", 'GPRINT:adjminuptime:MIN: %4.1lf', "COMMENT:\\n", "COMMENT:Last\\: ", 'GPRINT:adjuptime:LAST:%4.1lf',"COMMENT:\\n"); #memoire : used/cached/buffers/free createShowGraph(gettext("Detailed usage of the server memory."),"mem", "--title=".gettext("Memory usage"), "--vertical-label=".gettext("Bytes"), "--start=$start","--base=1024","--lower-limit=0", "DEF:used=$rrddir/mem.rrd:memused:AVERAGE","DEF:maxused=$rrddir/mem.rrd:memused:MAX","DEF:minused=$rrddir/mem.rrd:memused:MIN", "DEF:cached=$rrddir/mem.rrd:memcached:AVERAGE","DEF:maxcached=$rrddir/mem.rrd:memcached:MAX","DEF:mincached=$rrddir/mem.rrd:memcached:MIN", "DEF:buffers=$rrddir/mem.rrd:membuffers:AVERAGE","DEF:maxbuffers=$rrddir/mem.rrd:membuffers:MAX","DEF:minbuffers=$rrddir/mem.rrd:membuffers:MIN", "DEF:actualfree=$rrddir/mem.rrd:memactualfree:AVERAGE","DEF:maxactualfree=$rrddir/mem.rrd:memactualfree:MAX","DEF:minactualfree=$rrddir/mem.rrd:memactualfree:MIN", "DEF:total=$rrddir/mem.rrd:memtotal:AVERAGE", "COMMENT: ", "AREA:used#000066: ".gettext("Used"),"STACK:buffers#6633CC: ".gettext("Buffers"),"STACK:cached#339933: ".gettext("Cached"), "STACK:actualfree#00FF99: ".gettext("Free"),"LINE1:total#FF0000: ".gettext("Total"),"COMMENT:\\n", "COMMENT:Max\\: ",'GPRINT:maxused:MAX:%6.2lf%sb','GPRINT:maxbuffers:MAX:%6.2lf%sb','GPRINT:maxcached:MAX:%6.2lf%sb', 'GPRINT:maxactualfree:MAX:%6.2lf%sb',"COMMENT:\\n", "COMMENT:Min\\: ",'GPRINT:minused:MIN:%6.2lf%sb','GPRINT:minbuffers:MIN:%6.2lf%sb','GPRINT:mincached:MIN:%6.2lf%sb', 'GPRINT:minactualfree:MIN:%6.2lf%sb',"COMMENT:\\n", "COMMENT:Avg\\: ",'GPRINT:used:AVERAGE:%6.2lf%sb','GPRINT:buffers:AVERAGE:%6.2lf%sb','GPRINT:cached:AVERAGE:%6.2lf%sb', 'GPRINT:actualfree:AVERAGE:%6.2lf%sb',"COMMENT:\\n", "COMMENT:Last\\:",'GPRINT:used:LAST:%6.2lf%sb','GPRINT:buffers:LAST:%6.2lf%sb','GPRINT:cached:LAST:%6.2lf%sb', 'GPRINT:actualfree:LAST:%6.2lf%sb','GPRINT:total:LAST:%6.2lf%sb',"COMMENT:\\n"); #memoire : swap used/free/total createShowGraph(gettext("Swap usage (virtual memory) on the server's hard disk."),"swap", "--title=".gettext("Swap usage"), "--vertical-label=".gettext("Bytes"), "--start=$start","--base=1024","--lower-limit=0", "DEF:used=$rrddir/mem.rrd:swapused:AVERAGE","DEF:maxused=$rrddir/mem.rrd:swapused:MAX","DEF:minused=$rrddir/mem.rrd:swapused:MIN", "DEF:free=$rrddir/mem.rrd:swapfree:AVERAGE","DEF:maxfree=$rrddir/mem.rrd:swapfree:MAX","DEF:minfree=$rrddir/mem.rrd:swapfree:MIN", "DEF:total=$rrddir/mem.rrd:swaptotal:AVERAGE","DEF:maxtotal=$rrddir/mem.rrd:swaptotal:MAX","DEF:mintotal=$rrddir/mem.rrd:swaptotal:MIN", "COMMENT: ", "AREA:used#FF0033: ".gettext("Used"),"STACK:free#FF9966: ".gettext("Free"),"LINE1:total#006600: ".gettext("Total"), "COMMENT:\\n", "COMMENT:Max\\: ", 'GPRINT:maxused:MAX:%6.2lf%sb','GPRINT:maxfree:MAX:%6.2lf%sb','GPRINT:maxtotal:MAX:%6.2lf%sb',"COMMENT:\\n", "COMMENT:Min\\: ",'GPRINT:minused:MIN:%6.2lf%sb','GPRINT:minfree:MIN:%6.2lf%sb','GPRINT:mintotal:MIN:%6.2lf%sb',"COMMENT:\\n", "COMMENT:Avg\\: ",'GPRINT:used:AVERAGE:%6.2lf%sb','GPRINT:free:AVERAGE:%6.2lf%sb','GPRINT:total:AVERAGE:%6.2lf%sb',"COMMENT:\\n", "COMMENT:Last\\:",'GPRINT:used:LAST:%6.2lf%sb','GPRINT:free:LAST:%6.2lf%sb','GPRINT:total:LAST:%6.2lf%sb',"COMMENT:\\n"); #taux d'ecriture/lecture sur le disque dur createShowGraph(gettext("Amount of raw data read/written on the hard disk."),"hd_hard", "--title=".gettext("Data written/read"), "--vertical-label=".gettext("Blocks/s"), "--start=$start","--base=1024", "DEF:read=$rrddir/hd.rrd:blckread:AVERAGE","DEF:maxread=$rrddir/hd.rrd:blckread:MAX","DEF:minread=$rrddir/hd.rrd:blckread:MIN", "DEF:write=$rrddir/hd.rrd:blckwrite:AVERAGE","DEF:maxwrite=$rrddir/hd.rrd:blckwrite:MAX","DEF:minwrite=$rrddir/hd.rrd:blckwrite:MIN", "CDEF:adjread=0,read,-", "COMMENT: ", "LINE1:adjread#FF0033: ".gettext("Read"),"LINE1:write#3300FF: ".gettext("Written"),"COMMENT:\\n", "COMMENT:Max\\: ",'GPRINT:maxread:MAX:%6.2lf %sblk/s','GPRINT:maxwrite:MAX:%6.2lf %sblk/s',"COMMENT:\\n", "COMMENT:Min\\: ",'GPRINT:minread:MIN:%6.2lf %sblk/s','GPRINT:minwrite:MIN:%6.2lf %sblk/s',"COMMENT:\\n", "COMMENT:Avg\\: ",'GPRINT:read:AVERAGE:%6.2lf %sblk/s','GPRINT:write:AVERAGE:%6.2lf %sblk/s',"COMMENT:\\n", "COMMENT:Last\\:",'GPRINT:read:LAST:%6.2lf %sblk/s','GPRINT:write:LAST:%6.2lf %sblk/s',"COMMENT:\\n"); #ici, hack en fonction du param du_enabled : on met toutes les infos ou juste used/free/total #taux de remplissage du hd, place prise par log/squidcache/mysql/smefiles my $du_enabled=$params{'UseDu'}; my @tab=( "--title=".gettext("Hard disk usage"), "--vertical-label=".gettext("Bytes"), "--start=$start","--base=1024","--lower-limit=0", "DEF:used=$rrddir/hd.rrd:used:AVERAGE","DEF:maxused=$rrddir/hd.rrd:used:MAX","DEF:minused=$rrddir/hd.rrd:used:MIN", "DEF:free=$rrddir/hd.rrd:free:AVERAGE","DEF:maxfree=$rrddir/hd.rrd:free:MAX","DEF:minfree=$rrddir/hd.rrd:free:MIN", "DEF:total=$rrddir/hd.rrd:total:AVERAGE"); push @tab, "DEF:log=$rrddir/hd.rrd:log:AVERAGE","DEF:maxlog=$rrddir/hd.rrd:log:MAX","DEF:minlog=$rrddir/hd.rrd:log:MIN", "DEF:squid=$rrddir/hd.rrd:squid:AVERAGE","DEF:maxsquid=$rrddir/hd.rrd:squid:MAX","DEF:minsquid=$rrddir/hd.rrd:squid:MIN", "DEF:files=$rrddir/hd.rrd:files:AVERAGE","DEF:maxfiles=$rrddir/hd.rrd:files:MAX","DEF:minfiles=$rrddir/hd.rrd:files:MIN", "DEF:mysql=$rrddir/hd.rrd:mysql:AVERAGE","DEF:maxmysql=$rrddir/hd.rrd:mysql:MAX","DEF:minmysql=$rrddir/hd.rrd:mysql:MIN" if ($du_enabled eq "on"); push @tab,"COMMENT: ", "AREA:used#FF0033:".gettext("Used"),"STACK:free#44CCFF:".gettext("Free"); push @tab,"AREA:files#23EF41:Files","STACK:squid#AA1A00:Squid", "STACK:log#11AA00:Log", "STACK:mysql#FFFF00:Mysql" if ($du_enabled eq "on"); push @tab,"LINE1:total#0000FF:Total", "COMMENT:\\n", "COMMENT:Max\\: ",'GPRINT:maxused:MAX:%5.1lf%sb ','GPRINT:maxfree:MAX:%5.1lf%sb '; push @tab,'GPRINT:maxfiles:MAX:%5.1lf%sb','GPRINT:maxsquid:MAX:%5.1lf%sb','GPRINT:maxlog:MAX:%5.1lf%sb','GPRINT:maxmysql:MAX:%5.1lf%sb' if ($du_enabled eq "on"); push @tab,"COMMENT:\\n","COMMENT:Min\\: ",'GPRINT:minused:MIN:%5.1lf%sb ','GPRINT:minfree:MIN:%5.1lf%sb '; push @tab,'GPRINT:minfiles:MIN:%5.1lf%sb','GPRINT:minsquid:MIN:%5.1lf%sb','GPRINT:minlog:MIN:%5.1lf%sb','GPRINT:minmysql:MIN:%5.1lf%sb' if ($du_enabled eq "on"); push @tab,"COMMENT:\\n","COMMENT:Avg\\: ",'GPRINT:used:AVERAGE:%5.1lf%sb ','GPRINT:free:AVERAGE:%5.1lf%sb '; push @tab,'GPRINT:files:AVERAGE:%5.1lf%sb','GPRINT:squid:AVERAGE:%5.1lf%sb','GPRINT:log:AVERAGE:%5.1lf%sb','GPRINT:mysql:AVERAGE:%5.1lf%sb' if ($du_enabled eq "on"); push @tab,"COMMENT:\\n","COMMENT:Last\\:",'GPRINT:used:LAST:%5.1lf%sb ','GPRINT:free:LAST:%5.1lf%sb '; push @tab,'GPRINT:files:LAST:%5.1lf%sb','GPRINT:squid:LAST:%5.1lf%sb','GPRINT:log:LAST:%5.1lf%sb','GPRINT:mysql:LAST:%5.1lf%sb' if ($du_enabled eq "on"); push @tab,'GPRINT:total:LAST:%5.1lf%sb',"COMMENT:\\n"; my $title=gettext("Detailed usage of disk space (squid cache, mysql databases, log files, user files..)."); $title=gettext("Disk space usage.") if ($du_enabled eq "off"); createShowGraph($title,"hd_usage",@tab); print $q->p($q->a ({href => "$progname"},gettext("Back\n"))); } sub createGraphQmail { my($start)=(@_); #qmail entrant/sortant createShowGraph(gettext("Number of local/remote e-mails handled by the internal mail service (including other service generated e-mails)."),"qmail", "--title=".gettext("Local/Remote e-mails"), "--start=$start", "DEF:local_failure=$rrddir/qmail.rrd:local_failure:AVERAGE","DEF:maxlocal_failure=$rrddir/qmail.rrd:local_failure:MAX","DEF:minlocal_failure=$rrddir/qmail.rrd:local_failure:MIN", "DEF:local_deferral=$rrddir/qmail.rrd:local_deferral:AVERAGE","DEF:maxlocal_deferral=$rrddir/qmail.rrd:local_deferral:MAX","DEF:minlocal_deferral=$rrddir/qmail.rrd:local_deferral:MIN", "DEF:local_success=$rrddir/qmail.rrd:local_success:AVERAGE","DEF:maxlocal_success=$rrddir/qmail.rrd:local_success:MAX","DEF:minlocal_success=$rrddir/qmail.rrd:local_success:MIN", "DEF:local_total=$rrddir/qmail.rrd:local_total:AVERAGE","DEF:maxlocal_total=$rrddir/qmail.rrd:local_total:MAX","DEF:minlocal_total=$rrddir/qmail.rrd:local_total:MIN", "DEF:remote_failure=$rrddir/qmail.rrd:remote_failure:AVERAGE","DEF:maxremote_failure=$rrddir/qmail.rrd:remote_failure:MAX","DEF:minremote_failure=$rrddir/qmail.rrd:remote_failure:MIN", "DEF:remote_deferral=$rrddir/qmail.rrd:remote_deferral:AVERAGE","DEF:maxremote_deferral=$rrddir/qmail.rrd:remote_deferral:MAX","DEF:minremote_deferral=$rrddir/qmail.rrd:remote_deferral:MIN", "DEF:remote_success=$rrddir/qmail.rrd:remote_success:AVERAGE","DEF:maxremote_success=$rrddir/qmail.rrd:remote_success:MAX","DEF:minremote_success=$rrddir/qmail.rrd:remote_success:MIN", "DEF:remote_total=$rrddir/qmail.rrd:remote_total:AVERAGE","DEF:maxremote_total=$rrddir/qmail.rrd:remote_total:MAX","DEF:minremote_total=$rrddir/qmail.rrd:remote_total:MIN", "DEF:local_queue=$rrddir/qmail.rrd:local_queue:AVERAGE","DEF:maxlocal_queue=$rrddir/qmail.rrd:local_queue:MAX","DEF:minlocal_queue=$rrddir/qmail.rrd:local_queue:MIN", "DEF:remote_queue=$rrddir/qmail.rrd:remote_queue:AVERAGE","DEF:maxremote_queue=$rrddir/qmail.rrd:remote_queue:MAX","DEF:minremote_queue=$rrddir/qmail.rrd:remote_queue:MIN", "CDEF:adj_remote_total=0,remote_total,-", "CDEF:adj_remote_queue=0,remote_queue,-", "CDEF:adj_remote_failure=0,remote_failure,-", "CDEF:adj_remote_deferral=0,remote_deferral,-","CDEF:adj_remote_success=0,remote_success,-", "COMMENT:Last\\t Min\\t Avg\\t Max\\r", "COMMENT:\\n","AREA:local_total#1ED408:".gettext("Total local e-mails"),"COMMENT:\\u","GPRINT:local_total:LAST:%4.0lf ","GPRINT:minlocal_total:MIN:%4.0lf ","GPRINT:local_total:AVERAGE:%4.0lf ","GPRINT:maxlocal_total:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ".gettext("Total remote e-mails"), "COMMENT:\\u","GPRINT:remote_total:LAST:%4.0lf ","GPRINT:minremote_total:MIN:%4.0lf ","GPRINT:remote_total:AVERAGE:%4.0lf ","GPRINT:maxremote_total:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ","AREA:adj_remote_success#0000ff:".gettext("Remote e-mail success"), "COMMENT:\\u","GPRINT:remote_success:LAST:%4.0lf ","GPRINT:minremote_success:MIN:%4.0lf ","GPRINT:remote_success:AVERAGE:%4.0lf ","GPRINT:maxremote_success:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ","AREA:adj_remote_deferral#ffff00:".gettext("Remote e-mail deferral").":STACK", "COMMENT:\\u","GPRINT:remote_deferral:LAST:%4.0lf ","GPRINT:minremote_deferral:MIN:%4.0lf ","GPRINT:remote_deferral:AVERAGE:%4.0lf ","GPRINT:maxremote_deferral:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ","AREA:adj_remote_failure#ff0000:".gettext("Remote e-mail failure").":STACK", "COMMENT:\\u","GPRINT:remote_failure:LAST:%4.0lf ","GPRINT:minremote_failure:MIN:%4.0lf ","GPRINT:remote_failure:AVERAGE:%4.0lf ","GPRINT:maxremote_failure:MAX:%4.0lf \\r", "COMMENT:\\n","LINE2:local_queue#666666:".gettext("Local queue"),"COMMENT:\\u", "GPRINT:local_queue:LAST:%4.0lf ","GPRINT:minlocal_queue:MIN:%4.0lf ","GPRINT:local_queue:AVERAGE:%4.0lf ","GPRINT:maxlocal_queue:MAX:%4.0lf \\r", "COMMENT:\\n","LINE2:adj_remote_queue#000000:".gettext("Remote queue"),"COMMENT:\\u", "GPRINT:remote_queue:LAST:%4.0lf ","GPRINT:minremote_queue:MIN:%4.0lf ","GPRINT:remote_queue:AVERAGE:%4.0lf ","GPRINT:maxremote_queue:MAX:%4.0lf \\r", "COMMENT:\\n"); } sub createGraphAltQmail { my($start)=(@_); #qmail entrant/sortant createShowGraph(gettext("Number of remote e-mails handled by the alternative mail service (altqmail)."),"altqmail", "--title=".gettext("Remote e-mails (altqmail)"), "--start=$start", "DEF:local_failure=$rrddir/altqmail.rrd:local_failure:AVERAGE","DEF:maxlocal_failure=$rrddir/altqmail.rrd:local_failure:MAX","DEF:minlocal_failure=$rrddir/altqmail.rrd:local_failure:MIN", "DEF:local_deferral=$rrddir/altqmail.rrd:local_deferral:AVERAGE","DEF:maxlocal_deferral=$rrddir/altqmail.rrd:local_deferral:MAX","DEF:minlocal_deferral=$rrddir/altqmail.rrd:local_deferral:MIN", "DEF:local_success=$rrddir/altqmail.rrd:local_success:AVERAGE","DEF:maxlocal_success=$rrddir/altqmail.rrd:local_success:MAX","DEF:minlocal_success=$rrddir/altqmail.rrd:local_success:MIN", "DEF:local_total=$rrddir/altqmail.rrd:local_total:AVERAGE","DEF:maxlocal_total=$rrddir/altqmail.rrd:local_total:MAX","DEF:minlocal_total=$rrddir/altqmail.rrd:local_total:MIN", "DEF:remote_failure=$rrddir/altqmail.rrd:remote_failure:AVERAGE","DEF:maxremote_failure=$rrddir/altqmail.rrd:remote_failure:MAX","DEF:minremote_failure=$rrddir/altqmail.rrd:remote_failure:MIN", "DEF:remote_deferral=$rrddir/altqmail.rrd:remote_deferral:AVERAGE","DEF:maxremote_deferral=$rrddir/altqmail.rrd:remote_deferral:MAX","DEF:minremote_deferral=$rrddir/altqmail.rrd:remote_deferral:MIN", "DEF:remote_success=$rrddir/altqmail.rrd:remote_success:AVERAGE","DEF:maxremote_success=$rrddir/altqmail.rrd:remote_success:MAX","DEF:minremote_success=$rrddir/altqmail.rrd:remote_success:MIN", "DEF:remote_total=$rrddir/altqmail.rrd:remote_total:AVERAGE","DEF:maxremote_total=$rrddir/altqmail.rrd:remote_total:MAX","DEF:minremote_total=$rrddir/altqmail.rrd:remote_total:MIN", "DEF:local_queue=$rrddir/altqmail.rrd:local_queue:AVERAGE","DEF:maxlocal_queue=$rrddir/altqmail.rrd:local_queue:MAX","DEF:minlocal_queue=$rrddir/altqmail.rrd:local_queue:MIN", "DEF:remote_queue=$rrddir/altqmail.rrd:remote_queue:AVERAGE","DEF:maxremote_queue=$rrddir/altqmail.rrd:remote_queue:MAX","DEF:minremote_queue=$rrddir/altqmail.rrd:remote_queue:MIN", "CDEF:adj_remote_total=0,remote_total,-", "CDEF:adj_remote_queue=0,remote_queue,-", "CDEF:adj_remote_failure=0,remote_failure,-", "CDEF:adj_remote_deferral=0,remote_deferral,-","CDEF:adj_remote_success=0,remote_success,-", "COMMENT:Last\\t Min\\t Avg\\t Max\\r", "COMMENT:\\n","AREA:local_total#1ED408:".gettext("Total local e-mails"),"COMMENT:\\u","GPRINT:local_total:LAST:%4.0lf ","GPRINT:minlocal_total:MIN:%4.0lf ","GPRINT:local_total:AVERAGE:%4.0lf ","GPRINT:maxlocal_total:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ".gettext("Total remote e-mails"), "COMMENT:\\u","GPRINT:remote_total:LAST:%4.0lf ","GPRINT:minremote_total:MIN:%4.0lf ","GPRINT:remote_total:AVERAGE:%4.0lf ","GPRINT:maxremote_total:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ","AREA:adj_remote_success#0000ff:".gettext("Remote e-mail success"), "COMMENT:\\u","GPRINT:remote_success:LAST:%4.0lf ","GPRINT:minremote_success:MIN:%4.0lf ","GPRINT:remote_success:AVERAGE:%4.0lf ","GPRINT:maxremote_success:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ","AREA:adj_remote_deferral#ffff00:".gettext("Remote e-mail deferral").":STACK", "COMMENT:\\u","GPRINT:remote_deferral:LAST:%4.0lf ","GPRINT:minremote_deferral:MIN:%4.0lf ","GPRINT:remote_deferral:AVERAGE:%4.0lf ","GPRINT:maxremote_deferral:MAX:%4.0lf \\r", "COMMENT:\\n","COMMENT: ","AREA:adj_remote_failure#ff0000:".gettext("Remote e-mail failure").":STACK", "COMMENT:\\u","GPRINT:remote_failure:LAST:%4.0lf ","GPRINT:minremote_failure:MIN:%4.0lf ","GPRINT:remote_failure:AVERAGE:%4.0lf ","GPRINT:maxremote_failure:MAX:%4.0lf \\r", "COMMENT:\\n","LINE2:local_queue#666666:".gettext("Local queue"),"COMMENT:\\u", "GPRINT:local_queue:LAST:%4.0lf ","GPRINT:minlocal_queue:MIN:%4.0lf ","GPRINT:local_queue:AVERAGE:%4.0lf ","GPRINT:maxlocal_queue:MAX:%4.0lf \\r", "COMMENT:\\n","LINE2:adj_remote_queue#000000:".gettext("Remote queue"),"COMMENT:\\u", "GPRINT:remote_queue:LAST:%4.0lf ","GPRINT:minremote_queue:MIN:%4.0lf ","GPRINT:remote_queue:AVERAGE:%4.0lf ","GPRINT:maxremote_queue:MAX:%4.0lf \\r", "COMMENT:\\n"); } sub createGraphQpsmtpd { my($start)=(@_); #qpsmtpd #check_basicheaders:check_goodrcptto:clamav:karma:tls_failed:rhsbl:check_earlytalker:resolvable_fromhost:dnsbl:fcrdns:spf:check_spamhelo:uribl:dmarc:total_denied:spam_denied:other_denied:spam_queued:queued:total createShowGraph(gettext("Number of incoming e-mail connections to qpsmtpd services (outside of server incoming e-mails) and amount of spam/viruses filtered."),"qpsmtpd", "--title=".gettext("Incoming qpsmtpd connections spam/virus/e-mails"), "--start=$start", "DEF:check_basicheaders=$rrddir/qpsmtpd.rrd:check_basicheaders:AVERAGE","DEF:maxcheck_basicheaders=$rrddir/qpsmtpd.rrd:check_basicheaders:MAX","DEF:mincheck_basicheaders=$rrddir/qpsmtpd.rrd:check_basicheaders:MIN", "DEF:check_goodrcptto=$rrddir/qpsmtpd.rrd:check_goodrcptto:AVERAGE","DEF:maxcheck_goodrcptto=$rrddir/qpsmtpd.rrd:check_goodrcptto:MAX","DEF:mincheck_goodrcptto=$rrddir/qpsmtpd.rrd:check_goodrcptto:MIN", "DEF:clamav=$rrddir/qpsmtpd.rrd:clamav:AVERAGE","DEF:maxclamav=$rrddir/qpsmtpd.rrd:clamav:MAX","DEF:minclamav=$rrddir/qpsmtpd.rrd:clamav:MIN", "DEF:karma=$rrddir/qpsmtpd.rrd:karma:AVERAGE","DEF:maxkarma=$rrddir/qpsmtpd.rrd:karma:MAX","DEF:minkarma=$rrddir/qpsmtpd.rrd:karma:MIN", "DEF:tls_failed=$rrddir/qpsmtpd.rrd:tls_failed:AVERAGE","DEF:maxtls_failed=$rrddir/qpsmtpd.rrd:tls_failed:MAX","DEF:mintls_failed=$rrddir/qpsmtpd.rrd:tls_failed:MIN", "DEF:auth_failed=$rrddir/qpsmtpd.rrd:auth_failed:AVERAGE","DEF:maxauth_failed=$rrddir/qpsmtpd.rrd:auth_failed:MAX","DEF:minauth_failed=$rrddir/qpsmtpd.rrd:auth_failed:MIN", "DEF:rhsbl=$rrddir/qpsmtpd.rrd:rhsbl:AVERAGE","DEF:maxrhsbl=$rrddir/qpsmtpd.rrd:rhsbl:MAX","DEF:minrhsbl=$rrddir/qpsmtpd.rrd:rhsbl:MIN", "DEF:check_earlytalker=$rrddir/qpsmtpd.rrd:check_earlytalker:AVERAGE","DEF:maxcheck_earlytalker=$rrddir/qpsmtpd.rrd:check_earlytalker:MAX","DEF:mincheck_earlytalker=$rrddir/qpsmtpd.rrd:check_earlytalker:MIN", "DEF:resolvable_fromhost=$rrddir/qpsmtpd.rrd:resolvable_fromhost:AVERAGE","DEF:maxresolvable_fromhost=$rrddir/qpsmtpd.rrd:resolvable_fromhost:MAX","DEF:minresolvable_fromhost=$rrddir/qpsmtpd.rrd:resolvable_fromhost:MIN", "DEF:dnsbl=$rrddir/qpsmtpd.rrd:dnsbl:AVERAGE","DEF:maxdnsbl=$rrddir/qpsmtpd.rrd:dnsbl:MAX","DEF:mindnsbl=$rrddir/qpsmtpd.rrd:dnsbl:MIN", "DEF:fcrdns=$rrddir/qpsmtpd.rrd:fcrdns:AVERAGE","DEF:maxfcrdns=$rrddir/qpsmtpd.rrd:fcrdns:MAX","DEF:minfcrdns=$rrddir/qpsmtpd.rrd:fcrdns:MIN", "DEF:spf=$rrddir/qpsmtpd.rrd:spf:AVERAGE","DEF:maxspf=$rrddir/qpsmtpd.rrd:spf:MAX","DEF:minspf=$rrddir/qpsmtpd.rrd:spf:MIN", "DEF:check_spamhelo=$rrddir/qpsmtpd.rrd:check_spamhelo:AVERAGE","DEF:maxcheck_spamhelo=$rrddir/qpsmtpd.rrd:check_spamhelo:MAX","DEF:mincheck_spamhelo=$rrddir/qpsmtpd.rrd:check_spamhelo:MIN", "DEF:uribl=$rrddir/qpsmtpd.rrd:uribl:AVERAGE","DEF:maxuribl=$rrddir/qpsmtpd.rrd:uribl:MAX","DEF:minuribl=$rrddir/qpsmtpd.rrd:uribl:MIN", "DEF:dmarc=$rrddir/qpsmtpd.rrd:dmarc:AVERAGE","DEF:maxdmarc=$rrddir/qpsmtpd.rrd:dmarc:MAX","DEF:mindmarc=$rrddir/qpsmtpd.rrd:dmarc:MIN", "DEF:total_denied=$rrddir/qpsmtpd.rrd:total_denied:AVERAGE","DEF:maxtotal_denied=$rrddir/qpsmtpd.rrd:total_denied:MAX","DEF:mintotal_denied=$rrddir/qpsmtpd.rrd:total_denied:MIN", "DEF:spam_denied=$rrddir/qpsmtpd.rrd:spam_denied:AVERAGE","DEF:maxspam_denied=$rrddir/qpsmtpd.rrd:spam_denied:MAX","DEF:minspam_denied=$rrddir/qpsmtpd.rrd:spam_denied:MIN", "DEF:other_denied=$rrddir/qpsmtpd.rrd:other_denied:AVERAGE","DEF:maxother_denied=$rrddir/qpsmtpd.rrd:other_denied:MAX","DEF:minother_denied=$rrddir/qpsmtpd.rrd:other_denied:MIN", "DEF:spam_queued=$rrddir/qpsmtpd.rrd:spam_queued:AVERAGE","DEF:maxspam_queued=$rrddir/qpsmtpd.rrd:spam_queued:MAX","DEF:minspam_queued=$rrddir/qpsmtpd.rrd:spam_queued:MIN", "DEF:queued=$rrddir/qpsmtpd.rrd:queued:AVERAGE","DEF:maxqueued=$rrddir/qpsmtpd.rrd:queued:MAX","DEF:minqueued=$rrddir/qpsmtpd.rrd:queued:MIN", "DEF:total=$rrddir/qpsmtpd.rrd:total:AVERAGE","DEF:maxtotal=$rrddir/qpsmtpd.rrd:total:MAX","DEF:mintotal=$rrddir/qpsmtpd.rrd:total:MIN", "CDEF:total_accepted=queued,spam_queued,+", "COMMENT:Last\\t Min\\t Avg\\t Max\\r", "COMMENT:\\n","COMMENT:".gettext("Total"),"COMMENT:\\u","GPRINT:total:LAST:%4.0lf ","GPRINT:mintotal:MIN:%4.0lf ","GPRINT:total:AVERAGE:%4.0lf ","GPRINT:maxtotal:MAX:%4.0lf \\r", "COMMENT:".gettext("Total accepted e-mails"),"COMMENT:\\u","GPRINT:total_accepted:LAST:%4.0lf ","GPRINT:total_accepted:MIN:%4.0lf ","GPRINT:total_accepted:AVERAGE:%4.0lf ","GPRINT:total_accepted:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:spam_queued#8fd487:".gettext("Accepted e-mails")."\\: ".gettext("spam queued"),"COMMENT:\\u","GPRINT:spam_queued:LAST:%4.0lf ","GPRINT:minspam_queued:MIN:%4.0lf ","GPRINT:spam_queued:AVERAGE:%4.0lf ","GPRINT:maxspam_queued:MAX:%4.0lf \\r", "COMMENT:\\n","AREA:queued#1ED408:".gettext("Accepted e-mails")."\\: ".gettext("queued").":STACK","COMMENT:\\u","GPRINT:queued:LAST:%4.0lf ","GPRINT:minqueued:MIN:%4.0lf ","GPRINT:queued:AVERAGE:%4.0lf ","GPRINT:maxqueued:MAX:%4.0lf \\r", "COMMENT:\\n", "COMMENT:".gettext("Total denied e-mails"),"COMMENT:\\u","GPRINT:total_denied:LAST:%4.0lf ","GPRINT:mintotal_denied:MIN:%4.0lf ","GPRINT:total_denied:AVERAGE:%4.0lf ","GPRINT:maxtotal_denied:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:check_spamhelo#007a7a:".gettext("Denied e-mails")."\\: ".gettext("check_spamhelo").":STACK","COMMENT:\\u","GPRINT:check_spamhelo:LAST:%4.0lf ","GPRINT:mincheck_spamhelo:MIN:%4.0lf ","GPRINT:check_spamhelo:AVERAGE:%4.0lf ","GPRINT:maxcheck_spamhelo:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:other_denied#666666:".gettext("Denied e-mails")."\\: ".gettext("other reasons").":STACK","COMMENT:\\u","GPRINT:other_denied:LAST:%4.0lf ","GPRINT:minother_denied:MIN:%4.0lf ","GPRINT:other_denied:AVERAGE:%4.0lf ","GPRINT:maxother_denied:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:tls_failed#990099:".gettext("Denied e-mails")."\\: ".gettext("tls failed").":STACK","COMMENT:\\u","GPRINT:tls_failed:LAST:%4.0lf ","GPRINT:mintls_failed:MIN:%4.0lf ","GPRINT:tls_failed:AVERAGE:%4.0lf ","GPRINT:maxtls_failed:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:auth_failed#FFA500:".gettext("Denied e-mails")."\\: ".gettext("auth failed").":STACK","COMMENT:\\u","GPRINT:auth_failed:LAST:%4.0lf ","GPRINT:minauth_failed:MIN:%4.0lf ","GPRINT:auth_failed:AVERAGE:%4.0lf ","GPRINT:maxauth_failed:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:spf#00004f:".gettext("Denied e-mails")."\\: ".gettext("spf").":STACK","COMMENT:\\u","GPRINT:spf:LAST:%4.0lf ","GPRINT:minspf:MIN:%4.0lf ","GPRINT:spf:AVERAGE:%4.0lf ","GPRINT:maxspf:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:resolvable_fromhost#ff99ff:".gettext("Denied e-mails")."\\: ".gettext("resolvable_fromhost").":STACK","COMMENT:\\u","GPRINT:resolvable_fromhost:LAST:%4.0lf ","GPRINT:minresolvable_fromhost:MIN:%4.0lf ","GPRINT:resolvable_fromhost:AVERAGE:%4.0lf ","GPRINT:maxresolvable_fromhost:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:karma#ffff00:".gettext("Denied e-mails")."\\: ".gettext("karma").":STACK","COMMENT:\\u","GPRINT:karma:LAST:%4.0lf ","GPRINT:minkarma:MIN:%4.0lf ","GPRINT:karma:AVERAGE:%4.0lf ","GPRINT:maxkarma:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:check_basicheaders#ff00ff:".gettext("Denied e-mails")."\\: ".gettext("check_basicheaders").":STACK","COMMENT:\\u","GPRINT:check_basicheaders:LAST:%4.0lf ","GPRINT:mincheck_basicheaders:MIN:%4.0lf ","GPRINT:check_basicheaders:AVERAGE:%4.0lf ","GPRINT:maxcheck_basicheaders:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:check_goodrcptto#00ffff:".gettext("Denied e-mails")."\\: ".gettext("check_goodrcptto").":STACK","COMMENT:\\u","GPRINT:check_goodrcptto:LAST:%4.0lf ","GPRINT:mincheck_goodrcptto:MIN:%4.0lf ","GPRINT:check_goodrcptto:AVERAGE:%4.0lf ","GPRINT:maxcheck_goodrcptto:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:uribl#4c004c:".gettext("Denied e-mails")."\\: ".gettext("uribl").":STACK","COMMENT:\\u","GPRINT:uribl:LAST:%4.0lf ","GPRINT:minuribl:MIN:%4.0lf ","GPRINT:uribl:AVERAGE:%4.0lf ","GPRINT:maxuribl:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:rhsbl#7f7f7f:".gettext("Denied e-mails")."\\: ".gettext("rhsbl").":STACK","COMMENT:\\u","GPRINT:rhsbl:LAST:%4.0lf ","GPRINT:minrhsbl:MIN:%4.0lf ","GPRINT:rhsbl:AVERAGE:%4.0lf ","GPRINT:maxrhsbl:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:dnsbl#0000ff:".gettext("Denied e-mails")."\\: ".gettext("dnsbl").":STACK","COMMENT:\\u","GPRINT:dnsbl:LAST:%4.0lf ","GPRINT:mindnsbl:MIN:%4.0lf ","GPRINT:dnsbl:AVERAGE:%4.0lf ","GPRINT:maxdnsbl:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:check_earlytalker#7c7cff:".gettext("Denied e-mails")."\\: ".gettext("check_earlytalker").":STACK","COMMENT:\\u","GPRINT:check_earlytalker:LAST:%4.0lf ","GPRINT:mincheck_earlytalker:MIN:%4.0lf ","GPRINT:check_earlytalker:AVERAGE:%4.0lf ","GPRINT:maxcheck_earlytalker:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:fcrdns#827f00:".gettext("Denied e-mails")."\\: ".gettext("fcrdns").":STACK","COMMENT:\\u","GPRINT:fcrdns:LAST:%4.0lf ","GPRINT:minfcrdns:MIN:%4.0lf ","GPRINT:fcrdns:AVERAGE:%4.0lf ","GPRINT:maxfcrdns:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:dmarc#7f0000:".gettext("Denied e-mails")."\\: ".gettext("dmarc").":STACK","COMMENT:\\u","GPRINT:dmarc:LAST:%4.0lf ","GPRINT:mindmarc:MIN:%4.0lf ","GPRINT:dmarc:AVERAGE:%4.0lf ","GPRINT:maxdmarc:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:spam_denied#DAA520:".gettext("Denied e-mails")."\\: ".gettext("spam denied").":STACK","COMMENT:\\u","GPRINT:spam_denied:LAST:%4.0lf ","GPRINT:minspam_denied:MIN:%4.0lf ","GPRINT:spam_denied:AVERAGE:%4.0lf ","GPRINT:maxspam_denied:MAX:%4.0lf \\r", "COMMENT:\\n", "AREA:clamav#ff0000:".gettext("Denied e-mails")."\\: ".gettext("virus").":STACK","COMMENT:\\u","GPRINT:clamav:LAST:%4.0lf ","GPRINT:minclamav:MIN:%4.0lf ","GPRINT:clamav:AVERAGE:%4.0lf ","GPRINT:maxclamav:MAX:%4.0lf \\r", "COMMENT:\\n"); }