]>
git.proxmox.com Git - pve-manager.git/blob - PVE/AutoBalloon.pm
1 package PVE
::AutoBalloon
;
7 my ($vmstatus, $goal, $maxchange, $debug) = @_;
9 my $log = sub { print @_ if $debug; };
11 my $change_func = sub {
12 my ($res, $idlist, $bytes) = @_;
19 while ($rest && $repeat && $progress) {
26 foreach my $vmid (@$idlist) {
27 next if defined($done_hash->{$vmid});
28 my $d = $vmstatus->{$vmid};
29 my $balloon = defined($res->{$vmid}) ?
$res->{$vmid} : $d->{balloon
};
30 $alloc_old += $balloon - $d->{balloon_min
};
31 $shares_total += $d->{shares
} || 1000;
36 my $alloc_new = $alloc_old + $rest;
38 &$log("shares_total: $shares_total $alloc_new\n");
40 foreach my $vmid (@$idlist) {
41 next if defined($done_hash->{$vmid});
42 my $d = $vmstatus->{$vmid};
43 my $shares = $d->{shares
} || 1000;
44 my $desired = $d->{balloon_min
} + int(($alloc_new/$shares_total)*$shares);
46 if ($desired > $d->{maxmem
}) {
47 $desired = $d->{maxmem
};
49 } elsif ($desired < $d->{balloon_min
}) {
50 $desired = $d->{balloon_min
};
55 if (($bytes > 0) && ($desired - $d->{balloon
}) > 0) { # grow
56 $new = $d->{balloon
} + $maxchange;
57 $balloon = $new > $desired ?
$desired : $new;
58 } elsif (($desired - $d->{balloon
}) < 0) { # shrink
59 $new = $d->{balloon
} - $maxchange;
60 $balloon = $new > $desired ?
$new : $desired;
62 $done_hash->{$vmid} = 1;
66 my $diff = $balloon - $d->{balloon
};
68 my $oldballoon = defined($res->{$vmid}) ?
$res->{$vmid} : $d->{balloon
};
69 $res->{$vmid} = $balloon;
70 my $change = $balloon - $oldballoon;
73 my $absdiff = $diff > 0 ?
$diff : -$diff;
74 $progress += $absdiff;
77 &$log("change request for $vmid ($balloon, $diff, $desired, $new, $changes, $progress)\n");
88 my $idlist = []; # list of VMs with working balloon river
89 my $idlist1 = []; # list of VMs with memory pressure
90 my $idlist2 = []; # list of VMs with enough free memory
92 foreach my $vmid (keys %$vmstatus) {
93 my $d = $vmstatus->{$vmid};
94 next if !$d->{balloon
}; # skip if balloon driver not running
95 next if !$d->{balloon_min
}; # skip if balloon value not set in config
96 next if $d->{lock} && $d->{lock} eq 'migrate';
97 next if defined($d->{shares
}) &&
98 ($d->{shares
} == 0); # skip if shares set to zero
100 push @$idlist, $vmid;
103 ($d->{freemem
} > $d->{balloon_min
}*0.25) &&
104 ($d->{balloon
} >= $d->{balloon_min
})) {
105 push @$idlist2, $vmid;
106 &$log("idlist2 $vmid $d->{balloon}, $d->{balloon_min}, $d->{freemem}\n");
108 push @$idlist1, $vmid;
109 &$log("idlist1 $vmid $d->{balloon}, $d->{balloon_min}\n");
115 if ($goal > 10*1024*1024) {
116 &$log("grow request start $goal\n");
117 # priorize VMs with memory pressure
118 my $rest = &$change_func($res, $idlist1, $goal);
119 if ($rest >= $goal) { # no progress ==> consider all VMs
120 &$log("grow request loop $rest\n");
121 $rest = &$change_func($res, $idlist, $rest);
123 &$log("grow request end $rest\n");
125 } elsif ($goal < -10*1024*1024) {
126 &$log("shrink request $goal\n");
127 # priorize VMs with enough free memory
128 my $rest = &$change_func($res, $idlist2, $goal);
129 if ($rest <= $goal) { # no progress ==> consider all VMs
130 &$log("shrink request loop $rest\n");
131 $rest = &$change_func($res, $idlist, $rest);
133 &$log("shrink request end $rest\n");
135 &$log("do nothing\n");
136 # do nothing - requested change to small
139 foreach my $vmid (@$idlist) {
140 next if !$res->{$vmid};
141 my $d = $vmstatus->{$vmid};
142 my $diff = int($res->{$vmid} - $d->{balloon
});
143 my $absdiff = $diff < 0 ?
-$diff : $diff;
144 &$log("BALLOON $vmid to $res->{$vmid} ($diff)\n");