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

Reply via email to