diff --git a/IDEAS b/IDEAS index fec60c087..99930859d 100644 --- a/IDEAS +++ b/IDEAS @@ -41,10 +41,9 @@ - mailbox_list_mails should use select function for virtual folders! - - theme fixes - - caching on right frame - - 5-minute cron job - - can we trust status module? + - theme caching + - mobile and thejax themes too + - need to release new Virtualmin first - templates for new mailing list configs - http://www.virtualmin.com/bug-tracker/bug?bug%5fnumber=739 diff --git a/collect-lib.pl b/collect-lib.pl new file mode 100644 index 000000000..571549f5f --- /dev/null +++ b/collect-lib.pl @@ -0,0 +1,185 @@ +# Functions for collecting general system info + +# collect_system_info() +# Returns a hash reference containing system information +sub collect_system_info +{ +local $info = { }; + +# System information +if (&foreign_check("proc")) { + &foreign_require("proc", "proc-lib.pl"); + if (defined(&proc::get_cpu_info)) { + local @c = &proc::get_cpu_info(); + $info->{'load'} = \@c; + } + local @procs = &proc::list_processes(); + $info->{'procs'} = scalar(@procs); + if (defined(&proc::get_memory_info)) { + local @m = &proc::get_memory_info(); + $info->{'mem'} = \@m; + } + if (&foreign_check("mount")) { + &foreign_require("mount", "mount-lib.pl"); + local @mounted = &mount::list_mounted(); + local $total = 0; + local $free = 0; + foreach my $m (@mounted) { + if ($m->[2] eq "ext2" || $m->[2] eq "ext3" || + $m->[2] eq "reiserfs" || $m->[2] eq "ufs" || + $m->[1] =~ /^\/dev\//) { + local ($t, $f) = + &mount::disk_space($m->[2], $m->[0]); + $total += $t*1024; + $free += $f*1024; + } + } + $info->{'disk_total'} = $total; + $info->{'disk_free'} = $free; + } + } + +# Available package updates +if (&foreign_available("security-updates")) { + &foreign_require("security-updates", "security-updates-lib.pl"); + local @poss = &security_updates::list_possible_updates(1); + $info->{'poss'} = \@poss; + } + +# System status +$info->{'startstop'} = [ &get_startstop_links() ]; + +# Counts for domains +local @doms = &virtual_server::list_domains(); +local %fcount = map { $_, 0 } @virtual_server::features; +$fcount{'doms'} = 0; +foreach my $d (@doms) { + $fcount{'doms'}++; + foreach my $f (@virtual_server::features) { + $fcount{$f}++ if ($d->{$f}); + } + my @dbs = &virtual_server::domain_databases($d); + $fcount{'dbs'} += scalar(@dbs); + my @users = &virtual_server::list_domain_users($d, 0, 1, 1, 1); + $fcount{'users'} += scalar(@users); + my @aliases = &virtual_server::list_domain_aliases($d, 1); + $fcount{'aliases'} += scalar(@aliases); + } +$info->{'fcount'} = \%fcount; +$info->{'ftypes'} = [ "doms", "dns", "web", "ssl", "mail", "dbs", + "users", "aliases" ]; +local (%fmax, %fextra, %fhide); +foreach my $f (@{$info->{'ftypes'}}) { + local ($extra, $reason, $max, $hide) = + &virtual_server::count_feature($f); + $fmax{$f} = $max; + $fextra{$f} = $extra; + $fhide{$f} = $hide; + } +$info->{'fmax'} = \%fmax; +$info->{'fextra'} = \%fextra; +$info->{'fhide'} = \%fhide; + +# Quota use for domains +if (&virtual_server::has_home_quotas()) { + local @quota; + local $homesize = &virtual_server::quota_bsize("home"); + local $mailsize = &virtual_server::quota_bsize("mail"); + local $maxquota = 0; + + # Work out quotas + foreach my $d (@doms) { + # If this is a parent domain, sum up quotas + if (!$d->{'parent'} && &virtual_server::has_home_quotas()) { + local ($home, $mail, $dbusage) = + &virtual_server::get_domain_quota($d, 1); + local $usage = $home*$homesize + + $mail*$mailsize; + $maxquota = $usage+$dbusage if ($usage+$dbusage > $maxquota); + local $limit = $d->{'quota'}*$homesize; + $maxquota = $limit if ($limit > $maxquota); + push(@quota, [ $d, $usage, $limit, $dbusage ]); + } + } + $info->{'quota'} = \@quota; + $info->{'maxquota'} = $maxquota; + } + +# IP addresses used +local (%ipcount, %ipdom); +foreach my $d (@doms) { + next if ($d->{'alias'}); + $ipcount{$d->{'ip'}}++; + $ipdom{$d->{'ip'}} ||= $d; + } +if (keys %ipdom > 1) { + local $defip = &virtual_server::get_default_ip(); + if (defined(&virtual_server::list_resellers)) { + foreach my $r (&virtual_server::list_resellers()) { + if ($r->{'acl'}->{'defip'}) { + $reselip{ + $r->{'acl'}->{'defip'}} = $r; + } + } + } + if (defined(&virtual_server::list_shared_ips)) { + foreach my $ip (&virtual_server::list_shared_ips()) { + $sharedip{$ip}++; + } + } + local @ips; + foreach my $ip ($defip, + (sort { $a cmp $b } keys %reselip), + (sort { $a cmp $b } keys %ipcount)) { + next if ($doneip{$ip}++); + push(@ips, [ $ip, $ip eq $defip ? ('def', undef) : + $reselip{$ip} ? ('reseller', + $reselip{$ip}->{'name'}) : + $sharedip{$ip} ? ('shared', undef) : + ('virt', undef), + $ipcount{$ip}, $ipdom{$ip}->{'dom'} ]); + } + $info->{'ips'} = \@ips; + } + +# Program information +local @progs; +foreach my $f ("virtualmin", @virtual_server::features) { + if ($virtual_server::config{$f} || $f eq "virtualmin") { + local $ifunc = "sysinfo_$f"; + if (defined(&$ifunc)) { + push(@progs, &$ifunc()); + } + } + } +$info->{'progs'} = \@progs; + +return $info; +} + +# get_collected_info() +# Returns the most recently collected system information, or the current info +sub get_collected_info +{ +local $infostr = &read_file_contents($collected_info_file); +if ($infostr) { + local $info = &unserialise_variable($infostr); + if (ref($info) eq 'HASH' && keys(%$info) > 0) { + return $info; + } + } +return &collect_system_info(); +} + +# save_collected_info(&info) +# Save information collected on schedule +sub save_collected_info +{ +local ($info) = @_; +&open_tempfile(INFO, ">$collected_info_file"); +&print_tempfile(INFO, &serialise_variable($info)); +&close_tempfile(INFO); +} + +1; + diff --git a/collectinfo.pl b/collectinfo.pl new file mode 100644 index 000000000..250f54892 --- /dev/null +++ b/collectinfo.pl @@ -0,0 +1,13 @@ +#!/usr/local/bin/perl +# Collect various pieces of general system information, for display by themes +# on their status pages. Run every 5 mins from Cron. + +package virtual_server; +$main::no_acl_check++; +require './virtual-server-lib.pl'; + +$info = &collect_system_info(); +if ($info) { + &save_collected_info($info); + } + diff --git a/postinstall.pl b/postinstall.pl index 4d8b56236..1c740aeb1 100755 --- a/postinstall.pl +++ b/postinstall.pl @@ -202,5 +202,25 @@ sub module_install &execute_command($ratings_cron_cmd); } } + +# Create the cron job for collecting system info +&foreign_require("cron", "cron-lib.pl"); +local ($job) = grep { $_->{'user'} eq 'root' && + $_->{'command'} eq $collect_cron_cmd } + &cron::list_cron_jobs(); +if (!$job) { + # Create, and run for the first time + $job = { 'mins' => '0,5,10,15,20,25,30,35,40,45,50,55', + 'hours' => '*', + 'days' => '*', + 'months' => '*', + 'weekdays' => '*', + 'user' => 'root', + 'active' => 1, + 'command' => $collect_cron_cmd }; + &cron::create_cron_job($job); + &cron::create_wrapper($collect_cron_cmd, $module_name, + "collectinfo.pl"); + } } diff --git a/virtual-server-lib-funcs.pl b/virtual-server-lib-funcs.pl index e55771630..dd1c04d6f 100644 --- a/virtual-server-lib-funcs.pl +++ b/virtual-server-lib-funcs.pl @@ -13,7 +13,7 @@ $virtual_server_root = "$1/virtual-server"; } foreach my $lib ("scripts", "resellers", "admins", "simple", "s3", "styles", - "php", "ruby", "vui", "dynip") { + "php", "ruby", "vui", "dynip", "collect") { do "$virtual_server_root/$lib-lib.pl"; if ($@ && -r "$virtual_server_root/$lib-lib.pl") { print STDERR "failed to load $lib-lib.pl : $@\n"; @@ -8609,26 +8609,27 @@ sub get_template_pages return (\@tlinks, \@ttitles, \@ticons); } -# get_startstop_links() +# get_startstop_links([live]) # Returns a list of status objects for relevant features and plugins sub get_startstop_links { +local ($live) = @_; local @rv; local %typestatus; -if (&foreign_check("status")) { - # Get scheduled monitoring status - &foreign_require("status", "status-lib.pl"); - local %oldstatus; - if ($status::config{'sched_mode'} && - &read_file($status::oldstatus_file, \%oldstatus)) { - # Can use scheduled status - foreach my $s (&status::list_services()) { - local $stat = &status::expand_oldstatus( - $oldstatus{$s->{'id'}}); - $typestatus{$s->{'type'}} = $stat->{'*'}; - } - } - } +#if (&foreign_check("status")) { +# # Get scheduled monitoring status (Disabled due to inaccuracy) +# &foreign_require("status", "status-lib.pl"); +# local %oldstatus; +# if ($status::config{'sched_mode'} && +# &read_file($status::oldstatus_file, \%oldstatus)) { +# # Can use scheduled status +# foreach my $s (&status::list_services()) { +# local $stat = &status::expand_oldstatus( +# $oldstatus{$s->{'id'}}); +# $typestatus{$s->{'type'}} = $stat->{'*'}; +# } +# } +# } foreach my $f (@startstop_features) { if ($config{$f}) { local $sfunc = "startstop_".$f; @@ -8649,15 +8650,10 @@ sub get_startstop_links } # refresh_startstop_status() -# Tell the status module to perform an un-scheduled status refresh +# Refresh regularly collected info on status of services sub refresh_startstop_status { -if (&foreign_check("status")) { - &foreign_require("status", "status-lib.pl"); - if ($status::config{'sched_mode'} && -r $status::cron_cmd) { - &system_logged("$status::cron_cmd >/dev/null 2>&1