From b8ae251afe10eac2f195fd71cb5f3efa358e213c Mon Sep 17 00:00:00 2001 From: Michal Fox Date: Fri, 2 Oct 2026 16:11:58 +0200 Subject: [PATCH] fix #7173: write config: drop empty tag list When the last tag of a VM gets removed, for example in the web UI, the API gets an empty 'tags' value, which then ends up as an empty 'tags:' line in the config and in the output of 'qm config'. As the config parser reads that line back as a single space, it also gets written out again on every following config change. Skip a tag list without any tag when writing the config, which also cleans up existing configs with such a line on their next change. The pending section still needs to keep it, otherwise the removal of all tags would get lost between writing the pending change and applying it. Signed-off-by: Michal Fox --- src/PVE/QemuServer.pm | 2 ++ src/test/parse-config-expected/empty-tags.conf | 8 ++++++++ src/test/parse-config-input/empty-tags.conf | 9 +++++++++ src/test/run_parse_config_tests.pl | 2 +- 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/test/parse-config-expected/empty-tags.conf create mode 100644 src/test/parse-config-input/empty-tags.conf diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm index f199371..3b9a86a 100644 --- a/src/PVE/QemuServer.pm +++ b/src/PVE/QemuServer.pm @@ -2167,6 +2167,8 @@ sub write_vm_config { foreach my $key (sort keys %$conf) { next if $key =~ /^(digest|description|pending|snapshots|special-sections)$/; + # an empty tag list is only needed as pending change for removing all tags + next if $key eq 'tags' && !$pending && $conf->{$key} =~ m/^\s*$/; $raw .= "$key: $conf->{$key}\n"; } return $raw; diff --git a/src/test/parse-config-expected/empty-tags.conf b/src/test/parse-config-expected/empty-tags.conf new file mode 100644 index 0000000..13e82c4 --- /dev/null +++ b/src/test/parse-config-expected/empty-tags.conf @@ -0,0 +1,8 @@ +# empty tag list +boot: order=scsi0 +cores: 1 +memory: 512 +name: notags +ostype: l26 +scsi0: local-lvm:vm-100-disk-0,size=4G +scsihw: virtio-scsi-single diff --git a/src/test/parse-config-input/empty-tags.conf b/src/test/parse-config-input/empty-tags.conf new file mode 100644 index 0000000..e3e09d6 --- /dev/null +++ b/src/test/parse-config-input/empty-tags.conf @@ -0,0 +1,9 @@ +# empty tag list +boot: order=scsi0 +cores: 1 +memory: 512 +name: notags +ostype: l26 +scsi0: local-lvm:vm-100-disk-0,size=4G +scsihw: virtio-scsi-single +tags: diff --git a/src/test/run_parse_config_tests.pl b/src/test/run_parse_config_tests.pl index 62e36ee..84602e4 100644 --- a/src/test/run_parse_config_tests.pl +++ b/src/test/run_parse_config_tests.pl @@ -26,7 +26,7 @@ my $OUTPUT_DIR = './parse-config-output'; my $EXPECTED_DIR = './parse-config-expected'; # NOTE update when you add/remove tests -plan tests => 2 * 10; +plan tests => 2 * 11; sub run_tests { my ($strict) = @_;