use Fcntl ':flock';
use Getopt::Long;
use Time::HiRes qw (gettimeofday);
-use PVE::Tools;
+use PVE::Tools qw(dir_glob_foreach file_read_firstline);
use PVE::ProcFSTools;
use Filesys::Df;
use PVE::INotify;
use PVE::QemuServer;
use PVE::OpenVZ;
use PVE::RPCEnvironment;
+use PVE::API2::Subscription;
+use PVE::AutoBalloon;
$SIG{'__WARN__'} = sub {
my $err = $@;
my $maxcpu = $cpuinfo->{cpus};
+ my $subinfo = PVE::INotify::read_file('subscription');
+ my $sublevel = $subinfo->{level} || '';
+
# traffic from/to physical interface cards
my $netin = 0;
my $netout = 0;
# everything not free is considered to be used
my $dused = $dinfo->{blocks} - $dinfo->{bfree};
- my $data = "$uptime:$ctime:$avg1:$maxcpu:$stat->{cpu}:$stat->{wait}:" .
+ my $data = "$uptime:$sublevel:$ctime:$avg1:$maxcpu:$stat->{cpu}:$stat->{wait}:" .
"$meminfo->{memtotal}:$meminfo->{memused}:" .
"$meminfo->{swaptotal}:$meminfo->{swapused}:" .
"$dinfo->{blocks}:$dused:$netin:$netout";
PVE::Cluster::broadcast_rrd("pve2-node/$nodename", $data);
}
+sub auto_balloning {
+ my ($vmstatus) = @_;
+
+ my $log = sub {
+ return if !$opt_debug;
+ print @_;
+ };
+
+ my $hostmeminfo = PVE::ProcFSTools::read_meminfo();
+
+ # to debug, run 'pvestatd -d' and set memtotal here
+ #$hostmeminfo->{memtotal} = int(2*1024*1024*1024/0.8); # you can set this to test
+
+ my $hostfreemem = $hostmeminfo->{memtotal} - $hostmeminfo->{memused};
+
+ # we try to use about 80% host memory
+ # goal: we want to change memory usage by this amount (positive or negative)
+ my $goal = int($hostmeminfo->{memtotal}*0.8 - $hostmeminfo->{memused});
+
+ my $maxchange = 100*1024*1024;
+ my $res = PVE::AutoBalloon::compute_alg1($vmstatus, $goal, $maxchange);
+
+ &$log("host goal: $goal free: $hostfreemem total: $hostmeminfo->{memtotal}\n");
+
+ foreach my $vmid (keys %$vmstatus) {
+ next if !$res->{$vmid};
+ my $d = $vmstatus->{$vmid};
+ my $diff = int($res->{$vmid} - $d->{balloon});
+ my $absdiff = $diff < 0 ? -$diff : $diff;
+ if ($absdiff > 0) {
+ &$log("BALLOON $vmid to $res->{$vmid} ($diff)\n");
+ eval {
+ PVE::QemuServer::vm_mon_cmd($vmid, "balloon",
+ value => int($res->{$vmid}));
+ };
+ warn $@ if $@;
+ }
+ }
+}
+
sub update_qemu_status {
my $ctime = time();
- my $vmstatus = PVE::QemuServer::vmstatus();
+ my $vmstatus = PVE::QemuServer::vmstatus(undef, 1);
+
+ eval { auto_balloning($vmstatus); };
+ syslog('err', "auto ballooning error: $@") if $@;
foreach my $vmid (keys %$vmstatus) {
my $d = $vmstatus->{$vmid};
}
}
+sub find_vzctl_console_pids {
+
+ my $res = {};
+
+ dir_glob_foreach('/proc', '\d+', sub {
+ my ($pid) = @_;
+
+ my $cmdline = file_read_firstline("/proc/$pid/cmdline");
+ return if !$cmdline;
+
+ my @args = split(/\0/, $cmdline);
+
+ # serach for vzctl console <vmid>
+ return if scalar(@args) != 3;
+ return if $args[1] ne 'console';
+ return if $args[2] !~ m/^\d+$/;
+ return if $args[0] !~ m|^(/usr/sbin/)?vzctl$|;
+
+ my $vmid = $args[2];
+
+ push @{$res->{$vmid}}, $pid;
+ });
+
+ return $res;
+}
+sub remove_stale_openvz_consoles {
+
+ my $vmstatus = PVE::OpenVZ::vmstatus();
+ my $pidhash = find_vzctl_console_pids();
+
+ foreach my $vmid (keys %$pidhash) {
+ next if defined($vmstatus->{$vmid});
+ syslog('info', "remove stale vzctl console for CT $vmid");
+ foreach my $pid (@{$pidhash->{$vmid}}) {
+ kill(9, $pid);
+ }
+ }
+}
+
sub update_openvz_status {
my $ctime = time();
};
$err = $@;
syslog('err', "storage status update error: $err") if $err;
+
+ eval {
+ remove_stale_openvz_consoles();
+ };
+ $err = $@;
+ syslog('err', "openvz console cleanup error: $err") if $err;
}
my $next_update = 0;
exit (-1); # never reached?
}
+my $initial_memory_usage;
+
for (;;) { # forever
eval {
my ($ccsec, $cusec) = gettimeofday ();
eval {
$reload_config = 0;
- syslog('info', "start status update");
+ # syslog('info', "start status update");
PVE::Cluster::cfs_update();
update_status();
};
my ($ccsec_end, $cusec_end) = gettimeofday ();
my $cptime = ($ccsec_end-$ccsec) + ($cusec_end - $cusec)/1000000;
- syslog('info', sprintf("status update finished (%.3f seconds)", $cptime));
+ syslog('info', sprintf("status update time (%.3f seconds)", $cptime))
+ if ($cptime > 5);
}
$cycle++;
my $mem = PVE::ProcFSTools::read_memory_usage();
- if ($mem->{resident} > (35*1024*1024)) {
- syslog ('info', "restarting server after $cycle cycles to " .
- "reduce memory usage (free $mem->{resident} bytes)");
- restart_server ();
+ if (!defined($initial_memory_usage) || ($cycle < 10)) {
+ $initial_memory_usage = $mem->{resident};
+ } else {
+ my $diff = $mem->{resident} - $initial_memory_usage;
+ if ($diff > 5*1024*1024) {
+ syslog ('info', "restarting server after $cycle cycles to " .
+ "reduce memory usage (free $mem->{resident} ($diff) bytes)");
+ restart_server ();
+ }
}
my $wcount = 0;