[pve-devel] [RFC PATCH qemu-server 7/7] memory: 'current' value for dimms
Wolfgang Bumiller
w.bumiller at proxmox.com
Tue Dec 20 12:49:26 CET 2016
This allows switching from the old hotplguging method to the
new one more easily by fetching the config of a running VM
by setting dimms to "current".
---
PVE/QemuServer.pm | 9 ++++--
PVE/QemuServer/Memory.pm | 83 ++++++++++++++++++++++++++++++++++++++----------
2 files changed, 74 insertions(+), 18 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 66aad3a..6f7a9c7 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -235,10 +235,11 @@ my $confdesc = {
dimms => {
optional => 1,
type => 'string',
- pattern => '(?:\d+@\d+(?:x\d+)?(?:[ ;]\d+@\d+(?:x\d+)?)*)|none',
+ pattern => '(?:\d+@\d+(?:x\d+)?(?:[ ;]\d+@\d+(?:x\d+)?)*)|none|current',
description => 'When memory hotplug is available and dimms are explicitly specified,'
.' the "memory" option becomes the static memory and the defined DIMMs are used for hotplugging.'
- .' This can be "none" to enable later dimm hotplugging with no initial ones added at startup.',
+ .' This can be "none" to enable later dimm hotplugging with no initial ones added at startup.'
+ .' The special value "current" can be used on a running machine to switch from the old hotplugging method to dimm hotplugging.',
},
balloon => {
optional => 1,
@@ -4249,6 +4250,8 @@ sub vmconfig_apply_pending {
# cold plug
+ my $defaults = load_defaults();
+
my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
while (my ($opt, $force) = each %$pending_delete_hash) {
die "internal error" if $opt =~ m/^unused/;
@@ -4279,6 +4282,8 @@ sub vmconfig_apply_pending {
vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
if defined($conf->{$opt});
$conf->{$opt} = $conf->{pending}->{$opt};
+ } elsif ($opt eq 'dimms') {
+ $conf->{$opt} = PVE::QemuServer::Memory::qemu_dimm_hotplug($vmid, $conf, $defaults, $opt, $conf->{pending}->{$opt});
} else {
$conf->{$opt} = $conf->{pending}->{$opt};
}
diff --git a/PVE/QemuServer/Memory.pm b/PVE/QemuServer/Memory.pm
index 89f1aff..4a2007d 100644
--- a/PVE/QemuServer/Memory.pm
+++ b/PVE/QemuServer/Memory.pm
@@ -254,13 +254,58 @@ my $qemu_update_dimm_config = sub {
return $value;
};
+sub current_dimm_config {
+ my ($vmid, $conf, $defaults, $running, $cur_sizes_by_node) = @_;
+
+ my $old = $conf->{dimms};
+
+ if ($running) {
+ # use the above $cur_sizes_by_node info which was queried from qemu.
+ if (!$old) {
+ use integer;
+ # We used the old hotplug method before, so we first caclulcate the
+ # amount of RAM the machine is currently using:
+ my $memdevs = PVE::QemuServer::vm_mon_cmd_nocheck($vmid, "query-memdev");
+ my $memory = 0;
+ $memory += $_->{size} foreach @$memdevs;
+ $memory /= 1024*1024;
+
+ # Then subtract the dimm configuration
+ foreach my $node (keys %$cur_sizes_by_node) {
+ my $sizes = $cur_sizes_by_node->{$node};
+ foreach my $size (keys %$sizes) {
+ my $size_ids = $sizes->{$size};
+ $memory -= $size * scalar(@$size_ids);
+ }
+ }
+ # Then we have our static memory:
+ $conf->{memory} = $memory;
+ PVE::QemuConfig->write_config($vmid, $conf);
+ }
+ } elsif ($old && $old ne 'current') {
+ # Not running and we have a dimm config, no change.
+ return $old;
+ } else {
+ # Not running and old config model was used. Convert:
+ $cur_sizes_by_node = {};
+ my $memory = $conf->{memory} || $defaults->{memory};
+ my $sockets = $conf->{sockets} || 1;
+ foreach_dimm($conf, $vmid, $memory, $sockets, sub {
+ my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
+ push @{$cur_sizes_by_node->{$numanode}->{$dimm_size}}, $name;
+ });
+ }
+
+ return &$qemu_update_dimm_config($vmid, $conf, $cur_sizes_by_node, 0)
+}
+
sub qemu_dimm_hotplug {
my ($vmid, $conf, $defaults, $opt, $value) = @_;
- return $value if !PVE::QemuServer::check_running($vmid);
+ my $running = PVE::QemuServer::check_running($vmid);
- if (!defined($value)) {
- die "dimms need to be unplugged before deleting the dimms property\n"
+ if ($running && !defined($value)) {
+ die "dimms need to be unplugged before deleting the dimm property\n"
if $conf->{dimms} && $conf->{dimms} ne 'none';
return undef;
}
@@ -268,22 +313,28 @@ sub qemu_dimm_hotplug {
my %allnodes;
my %allids;
my %allsizes;
-
- my $qemudimms = qemu_dimm_list($vmid);
-
+ my $qemudimms;
my $cur_sizes_by_node = {};
- foreach my $id (keys %$qemudimms) {
- my $dimm = $qemudimms->{$id};
- my $node = $dimm->{node};
- my $size = $dimm->{size};
- my $megs = int($size/(1024*1024));
- next if ($megs*1024*1024) != $size; # sanity check
- $allids{$id} = 1;
- $allnodes{$node} = 1;
- $allsizes{$megs} = 1;
- push @{$cur_sizes_by_node->{$node}->{$megs}}, $id;
+ if ($running) {
+ $qemudimms = qemu_dimm_list($vmid);
+ foreach my $id (keys %$qemudimms) {
+ my $dimm = $qemudimms->{$id};
+ my $node = $dimm->{node};
+ my $size = $dimm->{size};
+ my $megs = int($size/(1024*1024));
+ next if ($megs*1024*1024) != $size; # sanity check
+ $allids{$id} = 1;
+ $allnodes{$node} = 1;
+ $allsizes{$megs} = 1;
+ push @{$cur_sizes_by_node->{$node}->{$megs}}, $id;
+ }
}
+ return current_dimm_config($vmid, $conf, $defaults, $running, $cur_sizes_by_node)
+ if $value eq 'current';
+
+ return $value if !$running;
+
my @new_dimms = parse_dimmlist($value);
foreach my $dimm (@new_dimms) {
my ($dimm_size, $numanode) = @$dimm;
--
2.1.4
More information about the pve-devel
mailing list