all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Fiona Ebner <f.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com, aderumier@odiso.com
Subject: Re: [pve-devel] [PATCH qemu-server 02/10] add memory parser
Date: Fri, 16 Dec 2022 14:38:46 +0100	[thread overview]
Message-ID: <af2a9609-6839-f0b6-018f-81383537b83c@proxmox.com> (raw)
In-Reply-To: <20221209192726.1499142-3-aderumier@odiso.com>

Am 09.12.22 um 20:27 schrieb Alexandre Derumier:
> Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
> ---
>  PVE/API2/Qemu.pm          | 12 ++++++++-
>  PVE/QemuConfig.pm         |  4 +--
>  PVE/QemuMigrate.pm        |  6 +++--
>  PVE/QemuServer.pm         | 56 ++++++++++++++++++++++++++++++---------
>  PVE/QemuServer/Helpers.pm |  3 +--
>  PVE/QemuServer/Memory.pm  | 35 +++++++++++++++++-------
>  6 files changed, 88 insertions(+), 28 deletions(-)
> 

From a modularity standpoint, it would be nice to move the format
description, parsing+printing to PVE/QemuServer/Memory.pm, similar to
how it is done in PVE/QemuServer/PCI.pm

Since $confdesc->{memory}->{default} is now gone, load_defaults() will
not return a default for 'memory' anymore. And $conf->{memory} needs to
be parsed everywhere. These two things will break getting static usage
in HA manager, which uses load_defaults() and relies on $conf->{memory}
to be a single value right now. We can switch there to use
get_current_memory() too of course, but it'd require a versioned
Breaks+Depends.

Alternatively, we could add a function in qemu-server for calculating
the static stats and call that from HA. Requires a versioned
Breaks+Depends too, but then we'd be safe in the future and also catch
such changes more easily. OTOH, it'd make the coupling go in the other
direction: if HA manager wants to change what it uses for static
consideration, then qemu-server would need to adapt. So not sure.

> diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
> index badfc37..ba893d2 100644
> --- a/PVE/API2/Qemu.pm
> +++ b/PVE/API2/Qemu.pm
> @@ -32,6 +32,7 @@ use PVE::QemuServer::Drive;
>  use PVE::QemuServer::ImportDisk;
>  use PVE::QemuServer::Monitor qw(mon_cmd);
>  use PVE::QemuServer::Machine;
> +use PVE::QemuServer::Memory qw(get_current_memory);
>  use PVE::QemuMigrate;
>  use PVE::RPCEnvironment;
>  use PVE::AccessControl;
> @@ -1608,7 +1609,16 @@ my $update_vm_api  = sub {
>  	}
>  
>  	if ($param->{memory} || defined($param->{balloon})) {
> -	    my $maxmem = $param->{memory} || $conf->{pending}->{memory} || $conf->{memory} || $defaults->{memory};
> +
> +	    my $maxmem = undef;
> +	    if($param->{memory}) {

Style nit: missing space after if

> +	        $maxmem = get_current_memory($param);
> +	    } elsif ($conf->{pending}->{memory}) {
> +	        $maxmem = get_current_memory($conf->{pending});
> +	    } elsif ($conf->{memory}) {

Should be 'else'. Otherwise, you don't get the default when no branch is
taken.

> +	        $maxmem = get_current_memory($conf);
> +	    }> +
>  	    my $balloon = defined($param->{balloon}) ? $param->{balloon} : $conf->{pending}->{balloon} || $conf->{balloon};
>  
>  	    die "balloon value too large (must be smaller than assigned memory)\n"
> diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
> index 051382c..6fc4170 100644
> --- a/PVE/QemuConfig.pm
> +++ b/PVE/QemuConfig.pm
> @@ -12,6 +12,7 @@ use PVE::QemuServer::Helpers;
>  use PVE::QemuServer::Monitor qw(mon_cmd);
>  use PVE::QemuServer;
>  use PVE::QemuServer::Machine;
> +use PVE::QemuServer::Memory qw(get_current_memory);
>  use PVE::Storage;
>  use PVE::Tools;
>  use PVE::Format qw(render_bytes render_duration);
> @@ -208,8 +209,7 @@ sub __snapshot_save_vmstate {
>  	$target = PVE::QemuServer::find_vmstate_storage($conf, $storecfg);
>      }
>  
> -    my $defaults = PVE::QemuServer::load_defaults();
> -    my $mem_size = $conf->{memory} // $defaults->{memory};
> +    my $mem_size = get_current_memory($conf);
>      my $driver_state_size = 500; # assume 500MB is enough to safe all driver state;
>      # our savevm-start does live-save of the memory until the space left in the
>      # volume is just enough for the remaining memory content + internal state
> diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
> index 5e466d9..121b7e2 100644
> --- a/PVE/QemuMigrate.pm
> +++ b/PVE/QemuMigrate.pm
> @@ -26,6 +26,7 @@ use PVE::QemuServer::Drive;
>  use PVE::QemuServer::Helpers qw(min_version);
>  use PVE::QemuServer::Machine;
>  use PVE::QemuServer::Monitor qw(mon_cmd);
> +use PVE::QemuServer::Memory qw(get_current_memory);
>  use PVE::QemuServer;
>  
>  use PVE::AbstractMigrate;
> @@ -1024,7 +1025,8 @@ sub phase2_start_remote_cluster {
>      my $remote_vmid = $self->{opts}->{remote}->{vmid};
>  
>      # like regular start but with some overhead accounted for
> -    my $timeout = PVE::QemuServer::Helpers::config_aware_timeout($self->{vmconf}) + 10;
> +    my $memory = get_current_memory($self->{vmconf}); 

Style nit: trailing space

> +    my $timeout = PVE::QemuServer::Helpers::config_aware_timeout($self->{vmconf}, $memory) + 10;
>  
>      my $res = PVE::Tunnel::write_tunnel($self->{tunnel}, $timeout, "start", $params);
>  
> @@ -1179,7 +1181,7 @@ sub phase2 {
>      $qemu_migrate_params->{'downtime-limit'} = int($migrate_downtime);
>  
>      # set cachesize to 10% of the total memory
> -    my $memory =  $conf->{memory} || $defaults->{memory};
> +    my $memory = get_current_memory($conf);
>      my $cachesize = int($memory * 1048576 / 10);
>      $cachesize = round_powerof2($cachesize);
>  
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index a52a883..ad69b76 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -52,7 +52,7 @@ use PVE::QemuServer::CGroup;
>  use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options);
>  use PVE::QemuServer::Drive qw(is_valid_drivename drive_is_cloudinit drive_is_cdrom drive_is_read_only parse_drive print_drive);
>  use PVE::QemuServer::Machine;
> -use PVE::QemuServer::Memory;
> +use PVE::QemuServer::Memory qw(get_current_memory);
>  use PVE::QemuServer::Monitor qw(mon_cmd);
>  use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port parse_hostpci);
>  use PVE::QemuServer::USB qw(parse_usb_device);
> @@ -267,6 +267,18 @@ my $rng_fmt = {
>      },
>  };
>  
> +my $memory_fmt = {
> +    current => {
> +        description => "Current amount of online RAM for the VM in MB. This is the maximum available memory when"
> +            ." you use the balloon device.",
> +        type => 'integer',
> +	default_key => 1,
> +        optional => 1,
> +        minimum => 16,
> +        default => 512,
> +    }

Style nit: whitespace errors

> +};
> +
>  my $meta_info_fmt = {
>      'ctime' => {
>  	type => 'integer',
> @@ -340,11 +352,8 @@ my $confdesc = {
>      },
>      memory => {
>  	optional => 1,
> -	type => 'integer',
> -	description => "Amount of RAM for the VM in MB. This is the maximum available memory when"
> -	    ." you use the balloon device.",
> -	minimum => 16,
> -	default => 512,
> +	type => 'string',
> +	format => $memory_fmt,
>      },
>      balloon => {
>  	optional => 1,
> @@ -2168,6 +2177,24 @@ sub parse_rng {
>      return $res;
>  }
>  
> +sub print_memory {
> +    my $memory = shift;
> +
> +    return PVE::JSONSchema::print_property_string($memory, $memory_fmt);
> +}
> +
> +sub parse_memory {
> +    my ($value) = @_;
> +
> +    my $current_default = $memory_fmt->{current}->{default};
> +    my $res = { current => $current_default };
> +    return $res if !defined($value);
> +
> +    $res = eval { parse_property_string($memory_fmt, $value) };
> +    warn $@ if $@;

Why not die? The configuration is wrong after all.

> +    return $res;
> +}
> +
>  sub parse_meta_info {
>      my ($value) = @_;
>  

(...)

> diff --git a/PVE/QemuServer/Helpers.pm b/PVE/QemuServer/Helpers.pm
> index e91f906..9115d50 100644
> --- a/PVE/QemuServer/Helpers.pm
> +++ b/PVE/QemuServer/Helpers.pm
> @@ -143,8 +143,7 @@ sub version_cmp {
>  }
>  
>  sub config_aware_timeout {
> -    my ($config, $is_suspended) = @_;
> -    my $memory = $config->{memory};
> +    my ($config, $memory, $is_suspended) = @_;

Why do you add this? Also, when you adapt the callers, you only pass in
$config->{memory} which is already part of $config.

>      my $timeout = 30;
>  
>      # Based on user reported startup time for vm with 512GiB @ 4-5 minutes
> diff --git a/PVE/QemuServer/Memory.pm b/PVE/QemuServer/Memory.pm
> index f8fc534..668508b 100644
> --- a/PVE/QemuServer/Memory.pm
> +++ b/PVE/QemuServer/Memory.pm
> @@ -8,6 +8,11 @@ use PVE::Exception qw(raise raise_param_exc);
>  
>  use PVE::QemuServer;
>  use PVE::QemuServer::Monitor qw(mon_cmd);
> +use base qw(Exporter);
> +
> +our @EXPORT_OK = qw(
> +get_current_memory
> +);
>  
>  my $MAX_NUMA = 8;
>  my $STATICMEM = 1024;
> @@ -63,6 +68,13 @@ my sub get_max_mem {
>      return $bits_to_max_mem > 4*1024*1024 ? 4*1024*1024 : $bits_to_max_mem;
>  }
>  
> +sub get_current_memory{

Style nit: missing space

> +    my ($conf) = @_;

Could take the memory property string as a parameter rather than a whole
config.

> +
> +    my $memory = PVE::QemuServer::parse_memory($conf->{memory});
> +    return $memory->{current};
> +}
> +
>  sub get_numa_node_list {
>      my ($conf) = @_;
>      my @numa_map;
> @@ -162,8 +174,7 @@ sub qemu_memory_hotplug {
>      my $sockets = 1;
>      $sockets = $conf->{sockets} if $conf->{sockets};
>  
> -    my $memory = $conf->{memory} || $defaults->{memory};
> -    $value = $defaults->{memory} if !$value;

Now there is no fallback for $value anymore.

> +    my $memory = get_current_memory($conf);
>      return $value if $value == $memory;
>  
>      my $static_memory = $STATICMEM;
> @@ -171,7 +182,7 @@ sub qemu_memory_hotplug {
>  
>      die "memory can't be lower than $static_memory MB" if $value < $static_memory;
>      my $MAX_MEM = get_max_mem($conf);
> -    die "you cannot add more memory than max mem $MAX_MEM MB!\n" if $memory > $MAX_MEM;
> +    die "you cannot add more memory than max mem $MAX_MEM MB!\n" if $value > $MAX_MEM;

So this check was wrong previously? This should be its own patch.

>  
>      if ($value > $memory) {
>  
> @@ -180,7 +191,7 @@ sub qemu_memory_hotplug {
>  	foreach_dimm($conf, $vmid, $value, $sockets, sub {
>  	    my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
>  
> -		return if $current_size <= $conf->{memory};
> +		return if $current_size <= get_current_memory($conf);
>  
>  		if ($conf->{hugepages}) {
>  		    $numa_hostmap = get_numa_guest_to_host_map($conf) if !$numa_hostmap;
> @@ -219,7 +230,9 @@ sub qemu_memory_hotplug {
>  		    die $err;
>  		}
>  		#update conf after each succesful module hotplug
> -		$conf->{memory} = $current_size;
> +		my $mem = {};
> +		$mem->{current} = $current_size;
> +		$conf->{memory} = PVE::QemuServer::print_memory($mem);

Future properties other than current are dropped here. You do fix it in
10/10, but ideally it would be good from the start.

>  		PVE::QemuConfig->write_config($vmid, $conf);
>  	});
>  
> @@ -228,7 +241,8 @@ sub qemu_memory_hotplug {
>  	foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
>  	    my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
>  
> -		return if $current_size >= $conf->{memory};
> +		return if $current_size >= get_current_memory($conf);
> +
>  		print "try to unplug memory dimm $name\n";
>  
>  		my $retry = 0;
> @@ -242,7 +256,9 @@ sub qemu_memory_hotplug {
>  		}
>  
>  		#update conf after each succesful module unplug
> -		$conf->{memory} = $current_size;
> +		my $mem = {};
> +		$mem->{current} = $current_size;
> +		$conf->{memory} = PVE::QemuServer::print_memory($mem);

Same here.




  reply	other threads:[~2022-12-16 13:39 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-09 19:27 [pve-devel] [PATCH qemu-server 00/10] rework memory hotplug + virtiomem Alexandre Derumier
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 01/10] test: add memory tests Alexandre Derumier
2022-12-16 13:38   ` Fiona Ebner
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 02/10] add memory parser Alexandre Derumier
2022-12-16 13:38   ` Fiona Ebner [this message]
2023-01-02 10:50     ` DERUMIER, Alexandre
2023-01-05 12:47       ` Fiona Ebner
2023-01-02 11:23     ` DERUMIER, Alexandre
2023-01-05 12:48       ` Fiona Ebner
     [not found]         ` <4ba723fb986517054761eb65f38812fac86a895b.camel@groupe-cyllene.com>
2023-01-09 14:35           ` Fiona Ebner
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 03/10] config: memory: add 'max' option Alexandre Derumier
2022-12-16 13:38   ` Fiona Ebner
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 04/10] memory: add get_static_mem Alexandre Derumier
2022-12-16 13:38   ` Fiona Ebner
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 05/10] memory: get_max_mem: use config memory max Alexandre Derumier
2022-12-16 13:39   ` Fiona Ebner
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 06/10] memory: use 64 slots && static dimm size with max is defined Alexandre Derumier
2022-12-16 13:39   ` Fiona Ebner
2022-12-19 12:05     ` DERUMIER, Alexandre
2022-12-19 12:28       ` Fiona Ebner
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 07/10] test: add memory-max tests Alexandre Derumier
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 08/10] memory: add virtio-mem support Alexandre Derumier
2022-12-16 13:42   ` Fiona Ebner
     [not found]     ` <7b9306c429440304fb37601ece5ffdbad0b90e5f.camel@groupe-cyllene.com>
2022-12-20 10:26       ` Fiona Ebner
2022-12-20 12:16         ` [PVE-User] " DERUMIER, Alexandre
2022-12-20 12:31           ` DERUMIER, Alexandre
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 09/10] tests: add virtio-mem tests Alexandre Derumier
2022-12-16 13:42   ` Fiona Ebner
2022-12-19 14:48     ` Thomas Lamprecht
2022-12-09 19:27 ` [pve-devel] [PATCH qemu-server 10/10] memory: fix hotplug with virtiomem && maxmem Alexandre Derumier
2022-12-16 13:42   ` Fiona Ebner
2022-12-16 13:38 ` [pve-devel] [PATCH qemu-server 00/10] rework memory hotplug + virtiomem Fiona Ebner
2022-12-19 11:31   ` DERUMIER, Alexandre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=af2a9609-6839-f0b6-018f-81383537b83c@proxmox.com \
    --to=f.ebner@proxmox.com \
    --cc=aderumier@odiso.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal