for test!
require ballooning stats patchs on top qemu-kvm
Signed-off-by: Alexandre Derumier aderum...@odiso.com
---
PVE/QemuServer.pm | 141 -
1 file changed, 140 insertions(+), 1 deletion(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 81cc682..3df3f57 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -31,6 +31,25 @@ use Time::HiRes qw(gettimeofday);
my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
+# then we will consider the host to be under memory pressure
+my $pressure_threshold = 0.20;
+
+# If pressure threshold drops below this level, then the pressure
+# is critical and more aggressive ballooning will be employed.
+my $pressure_critical = 0.05;
+
+# This is the minimum percentage of free memory that an unconstrained
+# guest would like to maintain
+my $min_guest_free_percent = 0.20;
+
+# Don't change a guest's memory by more than this percent of total memory
+my $max_balloon_change_percent = 0.5;
+
+# Only ballooning operations that change the balloon by this percentage
+# of current guest memory should be undertaken to avoid overhead
+my $min_balloon_change_percent = 0.0025;
+
+
# Note about locking: we use flock on the config file protect
# against concurent actions.
# Aditionaly, we have a 'lock' setting in the config file. This
@@ -1966,6 +1985,9 @@ sub vmstatus {
$d-{diskread} = 0;
$d-{diskwrite} = 0;
+ $d-{freemem} = undef;
+ $d-{balloon} = $conf-{balloon} ?($conf-{balloon} * 1024 *1024) :
undef;
+
$res-{$vmid} = $d;
}
@@ -2042,10 +2064,28 @@ sub vmstatus {
$res-{$vmid}-{diskwrite} = $totalwrbytes;
};
+my $freememcb = sub {
+ my ($vmid, $resp) = @_;
+ my $value = $resp-{'return'} || 0;
+ $res-{$vmid}-{freemem} = $value;
+};
+
+my $totalmemcb = sub {
+ my ($vmid, $resp) = @_;
+ my $value = $resp-{'return'} || 0;
+ $res-{$vmid}-{mem} = $value;
+};
+
my $statuscb = sub {
my ($vmid, $resp) = @_;
$qmpclient-queue_cmd($vmid, $blockstatscb, 'query-blockstats');
+ if( $res-{$vmid}-{balloon}){
+ $qmpclient-queue_cmd($vmid, undef, 'qom-set',path=
machine/peripheral/balloon0, property = stats-polling-interval, value =
10);
+ $qmpclient-queue_cmd($vmid, $freememcb, 'qom-get',path=
machine/peripheral/balloon0, property = stat-free-memory);
+ $qmpclient-queue_cmd($vmid, $totalmemcb, 'qom-get',path=
machine/peripheral/balloon0, property = stat-total-memory);
+ }
+
my $status = 'unknown';
if (!defined($status = $resp-{'return'}-{status})) {
warn unable to get VM status\n;
@@ -2068,9 +2108,109 @@ sub vmstatus {
$res-{$vmid}-{qmpstatus} = $res-{$vmid}-{status} if
!$res-{$vmid}-{qmpstatus};
}
+#auto-balloning
+my $hostmeminfo = PVE::ProcFSTools::read_meminfo();
+my $hostfreemem = $hostmeminfo-{memtotal} - $hostmeminfo-{memused};
+my $host_free_percent = ($hostfreemem / $hostmeminfo-{memtotal});
+
+warn host free:.$hostfreemem. total:.$hostmeminfo-{memtotal}.\n;
+
+foreach my $vmid (keys %$list) {
+ if($res-{$vmid}-{pid} $res-{$vmid}-{balloon}
$res-{$vmid}-{freemem}){
+ warn vm $vmid: mem:.$res-{$vmid}-{mem}.
maxmem:.$res-{$vmid}-{maxmem} . freemem:.$res-{$vmid}-{freemem}.
min_mem: .$res-{$vmid}-{balloon}.\n;
+if ($host_free_percent $pressure_threshold){
+balloon_shrink_guest($vmid, $host_free_percent,
$res-{$vmid}-{mem}, $res-{$vmid}-{maxmem}, $res-{$vmid}-{freemem},
$res-{$vmid}-{balloon});
+}else{
+balloon_grow_guest($vmid, $host_free_percent,
$res-{$vmid}-{mem}, $res-{$vmid}-{maxmem}, $res-{$vmid}-{freemem},
$res-{$vmid}-{balloon});
+}
+}
+
+}
+
return $res;
}
+sub balloon_shrink_guest {
+my ($vmid, $host_free_percent, $balloon_cur, $balloon_max, $freemem,
$min_mem) = @_;
+
+my $guest_free_percent = undef;
+ # Determine the degree of host memory pressure
+if ($host_free_percent = $pressure_critical){
+# Pressure is critical:
+# Force guest to swap by making free memory negative
+$guest_free_percent = (-0.05 + $host_free_percent);
+}else{
+# Normal pressure situation
+# Scale the guest free memory back according to host pressure
+$guest_free_percent = ($min_guest_free_percent * ($host_free_percent /
$pressure_threshold));
+}
+
+# Given current conditions, determine the ideal guest memory size
+# $guest_used_mem = $guest.StatAvg balloon_cur) - (guest.StatAvg
mem_unused);
+
+my $guest_used_mem = $balloon_cur - $freemem; # do we need average ?
+
+my $balloon_min = $guest_used_mem + ($guest_free_percent * $balloon_cur);
+
+$balloon_min = $min_mem if $balloon_min $min_mem;
+
+# But do not change it too fast
+my $balloon_size = $balloon_cur * (1 -