this patch adds the partial_fast_plug function, which allows to partially fastplug an option with a property string.
this is done by having a map $partial_fast_plug_option, the format is commented. other helper functions: * safe_boolean_ne (!$a != !$b) * typesafe_ne (combines safe_string_ne, safe_num_ne and safe_boolean_ne by taking $type as an argument) the qemu-guest-agent is our first use case for this (although i am sure there are more, this is more of a proof of concept. it should be trivial to add other things via the map), specifically the fstrim_cloned_disks option. Co-Authored-by: Stefan Reiter <s.rei...@proxmox.com> Signed-off-by: Oguz Bektas <o.bek...@proxmox.com> --- i added stefan as a co-author for this, to thank for his help debugging and testing it with me also please note that i'm sending this as RFC for review only, and it shouldn't be applied yet since i'm working on generalizing it a bit more for code reuse via pve-guest-common PVE/QemuServer.pm | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index bcdadca..74cbba0 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -5031,6 +5031,10 @@ sub vmconfig_hotplug_pending { } vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk}, $vmid, $opt, $value, 1, $arch, $machine_type); + } elsif ($opt eq 'agent') { + # partially fastpluggable + # skip if all options were fastpluggable + die "skip\n" if partial_fast_plug($conf, $opt); } elsif ($opt =~ m/^memory$/) { #dimms die "skip\n" if !$hotplug_features->{memory}; $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value); @@ -5165,6 +5169,80 @@ my $safe_string_ne = sub { return $a ne $b; }; +my $safe_boolean_ne = sub { + my ($a, $b) = @_; + + # we don't check if value is defined, since undefined + # is false (so it's a valid boolean) + + # negate both values to normalize and compare + return !$a != !$b; +}; + +my $typesafe_ne = sub { + my ($a, $b, $type) = @_; + + return 0 if !defined($a) && !defined($b); + return 1 if !defined($a); + return 1 if !defined($b); + + if ($type eq 'string') { + $safe_string_ne->($a, $b); + } elsif ($type eq 'number') { + $safe_num_ne->($a, $b); + } elsif ($type eq 'boolean') { + $safe_boolean_ne->($a, $b); + } +}; + +my $partial_fast_plug_option = +# name +# -> fmt -> format variable +# -> properties -> fastpluggable options hash +{ + agent => { + fmt => $agent_fmt, + properties => { + fstrim_cloned_disks => 1 + }, + }, +}; + +sub partial_fast_plug { + my ($conf, $opt) = @_; + + my $format = $partial_fast_plug_option->{$opt}->{fmt}; + my $properties = $partial_fast_plug_option->{$opt}->{properties}; + + my $old = PVE::JSONSchema::parse_property_string($format, $conf->{$opt}); + my $new = PVE::JSONSchema::parse_property_string($format, $conf->{pending}->{$opt}); + + my $changes_left = 0; + + # merge old and new opts to iterate + my $all_opts = dclone($old); + foreach my $opt1 (keys %$new) { + $all_opts->{$opt1} = $new->{$opt1} if !defined($all_opts->{$opt1}); + } + + foreach my $opt2 (keys %$all_opts) { + my $is_fastpluggable = $properties->{$opt2}; + my $type = $format->{$opt2}->{type}; + if ($typesafe_ne->($old->{$opt2}, $new->{$opt2}, $type)) { + if (defined($is_fastpluggable)) { + $old->{$opt2} = $new->{$opt2}; + } else { + $changes_left = 1; + } + } + } + + $conf->{$opt} = PVE::JSONSchema::print_property_string($old, $format); + + return $changes_left; +} + + sub vmconfig_update_net { my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $arch, $machine_type) = @_; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel