]> git.proxmox.com Git - qemu-server.git/commitdiff
rework cloudinit_record_changed logic
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Thu, 17 Nov 2022 13:35:27 +0000 (14:35 +0100)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Thu, 17 Nov 2022 13:35:27 +0000 (14:35 +0100)
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
PVE/QemuServer.pm

index dd3d3512a89609d17fd31737b50e3be6baac16f7..835759e5e69b4176d1adf49dfae15a9fd414e3b8 100644 (file)
@@ -4913,44 +4913,61 @@ sub vmconfig_hotplug_pending {
        my $ci = ($conf->{cloudinit} //= {});
 
        my $recorded = $ci->{$opt};
-
-       my $remove_added = sub {
-           my @added = grep { $_ ne $opt } PVE::Tools::split_list(delete($ci->{added}) // '');
-           my $added = join(',', @added);
-           $ci->{added} = $added if length($added);
-       };
-
-       my $record_added = sub {
-           my %added = map { $_ => 1 } PVE::Tools::split_list(delete($ci->{added}) // '');
-           $added{$opt} = 1;
-           $ci->{added} = join(',', keys %added);
-       };
-
-       if (defined($recorded)) {
-           # cloud-init already had a version of this key
-           if (!defined($new)) {
-               # the option existed temporarily and was now removed:
-               $remove_added->();
-           } elsif ($new eq $recorded) {
-               # it was reverted to the state in cloud-init
-               delete $ci->{$opt};
+       my %added = map { $_ => 1 } PVE::Tools::split_list(delete($ci->{added}) // '');
+
+       if (defined($new)) {
+           if (defined($old)) {
+               # an existing value is being modified
+               if (defined($recorded)) {
+                   # the value was already not in sync
+                   if ($new eq $recorded) {
+                       # a value is being reverted to the cloud-init state:
+                       delete $ci->{$opt};
+                       delete $added{$opt};
+                   } else {
+                       # the value was changed multiple times, do nothing
+                   }
+               } elsif ($added{$opt}) {
+                   # the value had been marked as added and is being changed, do nothing
+               } else {
+                   # the value is new, record it:
+                   $ci->{$opt} = $old;
+               }
            } else {
-               # $old was newer than $recorded, do nothing
+               # a new value is being added
+               if (defined($recorded)) {
+                   # it was already not in sync
+                   if ($new eq $recorded) {
+                       # a value is being reverted to the cloud-init state:
+                       delete $ci->{$opt};
+                       delete $added{$opt};
+                   } else {
+                       # the value had temporarily been removed, do nothing
+                   }
+               } elsif ($added{$opt}) {
+                   # the value had been marked as added already, do nothing
+               } else {
+                   # the value is new, add it
+                   $added{$opt} = 1;
+               }
            }
+       } elsif (!defined($old)) {
+           # a non-existent value is being removed? ignore...
        } else {
-           # the key was not present the last time we generated the cloud-init image:
-           if (!defined($new)) {
-               # it is being deleted, which means we're back to the cloud-init sate:
-               delete $ci->{$opt};
-               $remove_added->();
-           } elsif (defined($old)) {
-               # the key was modified
-               $ci->{$opt} = $old;
+           # a value is being deleted
+           if (defined($recorded)) {
+               # a value was already recorded, just keep it
+           } elsif ($added{$opt}) {
+               # the value was marked as added, remove it
+               delete $added{$opt};
            } else {
-               # the key was added, no old value exists
-               $record_added->();
+               # a previously unrecorded value is being removed, record the old value:
+               $ci->{$opt} = $old;
            }
        }
+
+       my $added = join(',', sort keys %added);
+       $ci->{added} = $added if length($added);
     };
 
     my $changes = 0;