[pve-devel] [PATCH manager] vzdump: test: add first tests to the guest include logic
Signed-off-by: Aaron Lauterer --- I forgot the makefile, please ignore the other patch and use this one. test/Makefile | 5 +- test/vzdump_guest_included_test.pl | 190 + 2 files changed, 194 insertions(+), 1 deletion(-) create mode 100755 test/vzdump_guest_included_test.pl diff --git a/test/Makefile b/test/Makefile index c26e16b1..44f3b0d7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,7 +5,7 @@ all: export PERLLIB=.. .PHONY: check -check: replication_test balloon_test mail_test +check: replication_test balloon_test mail_test vzdump_test balloon_test: ./balloontest.pl @@ -21,6 +21,9 @@ replication_test: mail_test: ./mail_test.pl +vzdump_test: + ./vzdump_guest_included_test.pl + .PHONY: install install: diff --git a/test/vzdump_guest_included_test.pl b/test/vzdump_guest_included_test.pl new file mode 100755 index ..31c520fa --- /dev/null +++ b/test/vzdump_guest_included_test.pl @@ -0,0 +1,190 @@ +#!/usr/bin/perl + +# Some of the tests can only be applied once the whole include logic is moved +# into one single method. Right now parts of it, (all, exclude) are in the +# PVE::VZDump->exec_backup() method. + +use strict; +use warnings; + +use lib '..'; + +use Test::More tests => 7; +use Test::MockModule; + +use PVE::VZDump; + +use Data::Dumper; + +my $vmlist = { +'ids' => { + 100 => { + 'type' => 'qemu', + 'node' => 'node1', + }, + 101 => { + 'type' => 'qemu', + 'node' => 'node1', + }, + 112 => { + 'type' => 'lxc', + 'node' => 'node1', + }, + 113 => { + 'type' => 'lxc', + 'node' => 'node1', + }, + 200 => { + 'type' => 'qemu', + 'node' => 'node2', + }, + 201 => { + 'type' => 'qemu', + 'node' => 'node2', + }, + 212 => { + 'type' => 'lxc', + 'node' => 'node2', + }, + 213 => { + 'type' => 'lxc', + 'node' => 'node2', + }, +} +}; + +my $pve_cluster_module = Test::MockModule->new('PVE::Cluster'); +$pve_cluster_module->mock( +get_vmlist => sub { + return $vmlist; +} +); + +my $pve_inotify = Test::MockModule->new('PVE::INotify'); +$pve_inotify->mock( +nodename => sub { + return 'node1'; +} +); + +my $pve_api2tools = Test::MockModule->new('PVE::API2Tools'); +$pve_api2tools->mock( +get_resource_pool_guest_members => sub { + return [100, 101, 200, 201]; +} +); + + + +my $tests = {}; + +# is handled in the PVE::VZDump->exec_backup() method for now +# $tests->{'Test all guests'} = { +# expected_vmids => [ 100, 101, 112, 113, 200, 201, 212, 213 ], +# expected_skiplist => [ ], +# param => { +# all => 1, +# } +# }; + +# is handled in the PVE::VZDump->exec_backup() method for now +# $tests->{'Test all guests with cluster node limit'} = { +# expected_vmids => [ 100, 101, 112, 113, 200, 201, 212, 213 ], +# expected_skiplist => [], +# param => { +# all => 1, +# node => 'node2', +# } +# }; + +# is handled in the PVE::VZDump->exec_backup() method for now +# $tests->{'Test all guests with local node limit'} = { +# expected_vmids => [ 100, 101, 112, 113 ], +# expected_skiplist => [ 200, 201, 212, 213 ], +# param => { +# all => 1, +# node => 'node1', +# } +# }; +# +# TODO: all test variants with exclude + +$tests->{'Test pool members'} = { +expected_vmids => [ 100, 101 ], +expected_skiplist => [ 200, 201 ], +param => { + pool => 'testpool', +} +}; + +$tests->{'Test pool members with cluster node limit'} = { +expected_vmids => [ 100, 101, 200, 201 ], +expected_skiplist => [], +param => { + pool => 'testpool', + node => 'node2', +} +}; + +$tests->{'Test pool members with local node limit'} = { +expected_vmids => [ 100, 101 ], +expected_skiplist => [ 200, 201 ], +param => { + pool => 'testpool', + node => 'node1', +} +}; + +$tests->{'Test selected VMIDs'} = { +expected_vmids => [ 100 ], +expected_skiplist => [ 201, 212 ], +param => { + vmid => '100, 201, 212', +} +}; + + +$tests->{'Test selected VMIDs with cluster node limit'} = { +expected_vmids => [ 100, 201, 212 ], +expected_skiplist => [], +param => { + vmid => '100, 201, 212', + node => 'node2', +} +}; + +$tests->{'Test selected VMIDs with local node limit'} = { +expected_vmids => [ 100 ], +expected_skiplist => [ 201, 212 ], +param => { + vmid => '100, 201, 212', + node => 'node1', +} +}; + +$tests->{'Test selected VMIDs on other nodes'} = { +expected_vmids => [], +expected_skiplist => [ 201, 212 ], +param => { + vmid => '201, 212', + node => 'node1', +} +}; + + + +foreach my $testname (sort keys %{$tests}) { +my $test
[pve-devel] [PATCH v2 common] print_text_table: handle undefined values in comparision
by introducing a safe_compare helper. Fixes warnings, e.g. pvesh get /nodes//network would print "use of uninitialized"-warnings if there are inactive network interfaces, because for those, 'active' is undef. Signed-off-by: Fabian Ebner --- Changes from v1: * don't change sort_key depending on data * instead handle undefined values directly in comparision src/PVE/CLIFormatter.pm | 11 +++ src/PVE/Tools.pm| 9 + 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/PVE/CLIFormatter.pm b/src/PVE/CLIFormatter.pm index 0e9cbe6..4f18fa9 100644 --- a/src/PVE/CLIFormatter.pm +++ b/src/PVE/CLIFormatter.pm @@ -150,8 +150,7 @@ sub data_to_text { # $props_to_print - ordered list of properties to print # $options # - sort_key: can be used to sort after a specific column, if it isn't set we sort -# after the leftmost column (with no undef value in $data) this can be -# turned off by passing 0 as sort_key +# after the leftmost column. This can be turned off by passing 0 as sort_key # - noborder: print without asciiart border # - noheader: print without table header # - columns: limit output width (if > 0) @@ -174,11 +173,15 @@ sub print_text_table { if (defined($sort_key) && $sort_key ne 0) { my $type = $returnprops->{$sort_key}->{type} // 'string'; + my $cmpfn; if ($type eq 'integer' || $type eq 'number') { - @$data = sort { $a->{$sort_key} <=> $b->{$sort_key} } @$data; + $cmpfn = sub { $_[0] <=> $_[1] }; } else { - @$data = sort { $a->{$sort_key} cmp $b->{$sort_key} } @$data; + $cmpfn = sub { $_[0] cmp $_[1] }; } + @$data = sort { + PVE::Tools::safe_compare($a->{$sort_key}, $b->{$sort_key}, $cmpfn) + } @$data; } my $colopts = {}; diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm index f02c0ae..f6b18f1 100644 --- a/src/PVE/Tools.pm +++ b/src/PVE/Tools.pm @@ -1766,4 +1766,13 @@ sub mount($) { ); } +sub safe_compare { +my ($left, $right, $cmp) = @_; + +return 0 if !defined($left) && !defined($right); +return -1 if !defined($left); +return 1 if !defined($right); +return $cmp->($left, $right); +} + 1; -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
Re: [pve-devel] [PATCH v2 common] print_text_table: handle undefined values in comparision
Tested-by: Oguz Bektas > Fabian Ebner hat am 28. April 2020 10:18 geschrieben: > > > by introducing a safe_compare helper. Fixes warnings, e.g. > pvesh get /nodes//network > would print "use of uninitialized"-warnings if there are inactive > network interfaces, because for those, 'active' is undef. > > Signed-off-by: Fabian Ebner > --- > > Changes from v1: > * don't change sort_key depending on data > * instead handle undefined values directly > in comparision > > src/PVE/CLIFormatter.pm | 11 +++ > src/PVE/Tools.pm| 9 + > 2 files changed, 16 insertions(+), 4 deletions(-) > > diff --git a/src/PVE/CLIFormatter.pm b/src/PVE/CLIFormatter.pm > index 0e9cbe6..4f18fa9 100644 > --- a/src/PVE/CLIFormatter.pm > +++ b/src/PVE/CLIFormatter.pm > @@ -150,8 +150,7 @@ sub data_to_text { > # $props_to_print - ordered list of properties to print > # $options > # - sort_key: can be used to sort after a specific column, if it isn't set > we sort > -# after the leftmost column (with no undef value in $data) this can be > -# turned off by passing 0 as sort_key > +# after the leftmost column. This can be turned off by passing 0 as > sort_key > # - noborder: print without asciiart border > # - noheader: print without table header > # - columns: limit output width (if > 0) > @@ -174,11 +173,15 @@ sub print_text_table { > > if (defined($sort_key) && $sort_key ne 0) { > my $type = $returnprops->{$sort_key}->{type} // 'string'; > + my $cmpfn; > if ($type eq 'integer' || $type eq 'number') { > - @$data = sort { $a->{$sort_key} <=> $b->{$sort_key} } @$data; > + $cmpfn = sub { $_[0] <=> $_[1] }; > } else { > - @$data = sort { $a->{$sort_key} cmp $b->{$sort_key} } @$data; > + $cmpfn = sub { $_[0] cmp $_[1] }; > } > + @$data = sort { > + PVE::Tools::safe_compare($a->{$sort_key}, $b->{$sort_key}, $cmpfn) > + } @$data; > } > > my $colopts = {}; > diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm > index f02c0ae..f6b18f1 100644 > --- a/src/PVE/Tools.pm > +++ b/src/PVE/Tools.pm > @@ -1766,4 +1766,13 @@ sub mount($) { > ); > } > > +sub safe_compare { > +my ($left, $right, $cmp) = @_; > + > +return 0 if !defined($left) && !defined($right); > +return -1 if !defined($left); > +return 1 if !defined($right); > +return $cmp->($left, $right); > +} > + > 1; > -- > 2.20.1 > > > ___ > pve-devel mailing list > pve-devel@pve.proxmox.com > https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
Re: [pve-devel] [PATCH guest-common 2/2] fix 2682: make sure configuration file is up-to-date for lock_config-variants
This patch breaks container creation for some reason. It'll fail with: unable to create CT : config file already exists I'll investigate why this happens. On 23.04.20 13:51, Fabian Ebner wrote: See [0] for the details. The call tree for the variants is lock_config -> lock_config_full -> lock_config_mode so it is sufficient to adapt lock_config_mode. [0]: https://bugzilla.proxmox.com/show_bug.cgi?id=2682 Suggested-by: Fabian Grünbichler Signed-off-by: Fabian Ebner --- PVE/AbstractConfig.pm | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/PVE/AbstractConfig.pm b/PVE/AbstractConfig.pm index f1b395c..15368de 100644 --- a/PVE/AbstractConfig.pm +++ b/PVE/AbstractConfig.pm @@ -292,7 +292,13 @@ sub lock_config_mode { my $filename = $class->config_file_lock($vmid); -my $res = lock_file_full($filename, $timeout, $shared, $code, @param); +# make sure configuration file is up-to-date +my $realcode = sub { + PVE::Cluster::cfs_update(); + $code->(@param); +}; + +my $res = lock_file_full($filename, $timeout, $shared, $realcode, @param); die $@ if $@; ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
Re: [pve-devel] [PATCH guest-common 2/2] fix 2682: make sure configuration file is up-to-date for lock_config-variants
On 28.04.20 13:00, Fabian Ebner wrote: This patch breaks container creation for some reason. It'll fail with: unable to create CT : config file already exist the real error message is: unable to create CT : CT already exists on node '' I pasted the wrong one in a hurry I'll investigate why this happens. The reason is that in create_vm for containers, update_pct_config is called before create_and_lock_config and the former leads to a write_config call (via vmconfig_apply_pending). On 23.04.20 13:51, Fabian Ebner wrote: See [0] for the details. The call tree for the variants is lock_config -> lock_config_full -> lock_config_mode so it is sufficient to adapt lock_config_mode. [0]: https://bugzilla.proxmox.com/show_bug.cgi?id=2682 Suggested-by: Fabian Grünbichler Signed-off-by: Fabian Ebner --- PVE/AbstractConfig.pm | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/PVE/AbstractConfig.pm b/PVE/AbstractConfig.pm index f1b395c..15368de 100644 --- a/PVE/AbstractConfig.pm +++ b/PVE/AbstractConfig.pm @@ -292,7 +292,13 @@ sub lock_config_mode { my $filename = $class->config_file_lock($vmid); - my $res = lock_file_full($filename, $timeout, $shared, $code, @param); + # make sure configuration file is up-to-date + my $realcode = sub { + PVE::Cluster::cfs_update(); + $code->(@param); + }; + + my $res = lock_file_full($filename, $timeout, $shared, $realcode, @param); die $@ if $@; ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
Re: [pve-devel] [PATCH container 1/2] LXC: drop unused imported locking functions
Played around for a bit with your patches applied on top of mine and found no obvious issue, except for LXC creation [0] which is exposed by my second patch. So for Fabian G.'s patches: Tested-By: Fabian Ebner [0]: https://pve.proxmox.com/pipermail/pve-devel/2020-April/043210.html On 27.04.20 10:24, Fabian Grünbichler wrote: Signed-off-by: Fabian Grünbichler --- src/PVE/LXC.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm index fbe736e..651ec08 100644 --- a/src/PVE/LXC.pm +++ b/src/PVE/LXC.pm @@ -20,8 +20,8 @@ use PVE::SafeSyslog; use PVE::INotify; use PVE::JSONSchema qw(get_standard_option); use PVE::Tools qw( -dir_glob_foreach file_get_contents file_set_contents lock_file -lock_file_full AT_FDCWD O_PATH $IPV4RE $IPV6RE +dir_glob_foreach file_get_contents file_set_contents +AT_FDCWD O_PATH $IPV4RE $IPV6RE ); use PVE::CpuSet; use PVE::Network; ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH qemu-server] restore: use correct storage for format check for cloudinit drives
when a backup includes a cloudinit disk on a non-existent storage, the restore fails with 'storage' does not exist this happens because we want to get the format of the disk, by checking the source storage we fix this by using the target storage first and only the source as fallback this will still fail if neither storage exists (which is ok, since we cannot restore then anyway) Signed-off-by: Dominik Csapak --- PVE/QemuServer.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 37c7320..e355810 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -5739,7 +5739,7 @@ my $parse_backup_hints = sub { my $drive = parse_drive($virtdev, $2); if (drive_is_cloudinit($drive)) { my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}); - my $scfg = PVE::Storage::storage_config($storecfg, $storeid); + my $scfg = PVE::Storage::storage_config($storecfg, $options->{storage} // $storeid); my $format = qemu_img_format($scfg, $volname); # has 'raw' fallback $virtdev_hash->{$virtdev} = { -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 00/17] Fix: #2124 zstd
Zstandard (zstd) [0] is a data compression algorithm, in addition to gzip, lzo for our backup/restore. It can utilize multiple core CPUs. But by default it has one compression and one writer thread. Here some quick tests I made on my workstation. The files where placed on a ram disk. And with dd filled from /dev/urandom and /dev/zero. __Compression__ file size: 1073741824 bytes = urandom = = zero = 995ms 1073766414328ms 98192zstd -k 732ms 1073766414295ms 98192zstd -k -T4 906ms 1073791036562ms 4894779 lzop -k 31992ms 1073915558 5594ms 1042087 gzip -k 30832ms 1074069541 5776ms 1171491 pigz -k -p 1 7814ms 1074069541 1567ms 1171491 pigz -k -p 4 __Decompression__ file size: 1073741824 bytes = urandom = = zero = 712ms 869ms zstd -d 685ms 872ms zstd -k -d -T4 841ms 2462ms lzop -d 5417ms 4754ms gzip -k -d 1248ms 3118ms pigz -k -d -p 1 1236ms 2379ms pigz -k -d -p 4 And I used the same ramdisk to move a VM onto it and run a quick backup/restore. __vzdump backup__ INFO: transferred 34359 MB in 69 seconds (497 MB/s) zstd -T1 INFO: transferred 34359 MB in 37 seconds (928 MB/s) zstd -T4 INFO: transferred 34359 MB in 51 seconds (673 MB/s) lzo INFO: transferred 34359 MB in 1083 seconds (31 MB/s) gzip INFO: transferred 34359 MB in 241 seconds (142 MB/s) pigz -n 4 __qmrestore__ progress 100% (read 34359738368 bytes, duration 36 sec) total bytes read 34359738368, sparse bytes 8005484544 (23.3%) zstd -d -T4 progress 100% (read 34359738368 bytes, duration 38 sec) total bytes read 34359738368, sparse bytes 8005484544 (23.3%) lzo progress 100% (read 34359738368 bytes, duration 175 sec) total bytes read 34359738368, sparse bytes 8005484544 (23.3%) pigz -n 4 v4 -> v5: * fixup, use File::stat directly without overwriting CORE::stat, thanks Dietmar for pointing this out https://pve.proxmox.com/pipermail/pve-devel/2020-April/043134.html * rebase to current master v3 -> v4: * fixed styling issues discovered by f.ebner (thanks) * incorporated tests of d.jaeger into patches * added fixes discovered by tests (f.ebner thanks) v2 -> v3: * split archive_info into decompressor_info and archive_info * "compact" regex pattern is now a constant and used in multiple modules * added tests for regex matching * bug fix for ctime of backup files v1 -> v2: * factored out the decompressor info first, as Thomas suggested * made the regex pattern of backup files more compact, easier to read (hopefully) * less code changes for container restores Thanks for any comment or suggestion in advance. [0] https://facebook.github.io/zstd/ Alwin Antreich (17): __pve-storage__ storage: test: split archive format/compressor storage: replace build-in stat with File::stat test: parse_volname test: list_volumes Fix: backup: ctime was from stat not file name test: path_to_volume_id Fix: path_to_volume_id returned wrong content Fix: add missing snippets subdir backup: compact regex for backup file filter Fix: #2124 storage: add zstd support test: get_subdir test: filesystem_path test/Makefile | 5 +- PVE/Diskmanage.pm | 9 +- PVE/Storage.pm | 91 -- PVE/Storage/Plugin.pm | 47 ++- test/archive_info_test.pm | 127 test/filesystem_path_test.pm | 91 ++ test/get_subdir_test.pm| 44 +++ test/list_volumes_test.pm | 537 + test/parse_volname_test.pm | 253 test/path_to_volume_id_test.pm | 274 + test/run_plugin_tests.pl | 18 ++ 11 files changed, 1440 insertions(+), 56 deletions(-) create mode 100644 test/archive_info_test.pm create mode 100644 test/filesystem_path_test.pm create mode 100644 test/get_subdir_test.pm create mode 100644 test/list_volumes_test.pm create mode 100644 test/parse_volname_test.pm create mode 100644 test/path_to_volume_id_test.pm create mode 100755 test/run_plugin_tests.pl __guest_common__ Fix: #2124 add zstd support PVE/VZDump/Common.pm | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) __qemu-server__ restore: replace archive format/compression Fix #2124: Add support for zstd PVE/QemuServer.pm | 38 +++--- 1 file changed, 7 insertions(+), 31 deletions(-) __pve-container__ Fix: #2124 add zstd src/PVE/LXC/Create.pm | 1 + 1 file changed, 1 insertion(+) __pve-manager__ Fix #2124: Add support for zstd PVE/VZDump.pm| 11 +-- debian/control | 1 + www/manager6/form/CompressionSelector.js | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH guest-common v5] Fix: #2124 add zstd support
Signed-off-by: Alwin Antreich --- PVE/VZDump/Common.pm | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/PVE/VZDump/Common.pm b/PVE/VZDump/Common.pm index 4789a50..909e3af 100644 --- a/PVE/VZDump/Common.pm +++ b/PVE/VZDump/Common.pm @@ -88,7 +88,7 @@ my $confdesc = { type => 'string', description => "Compress dump file.", optional => 1, - enum => ['0', '1', 'gzip', 'lzo'], + enum => ['0', '1', 'gzip', 'lzo', 'zstd'], default => '0', }, pigz=> { @@ -98,6 +98,13 @@ my $confdesc = { optional => 1, default => 0, }, +zstd => { + type => "integer", + description => "Zstd threads. N=0 uses half of the available cores,". + " N>0 uses N as thread count.", + optional => 1, + default => 1, +}, quiet => { type => 'boolean', description => "Be quiet.", -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH manager v5] Fix #2124: Add support for zstd
This patch adds the zstd to the compression selection for backup on the GUI and add .zst to the backup file filter. Including zstd as package install dependency. Signed-off-by: Alwin Antreich --- PVE/VZDump.pm| 11 +-- debian/control | 1 + www/manager6/form/CompressionSelector.js | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/PVE/VZDump.pm b/PVE/VZDump.pm index f3274196..80f4734c 100644 --- a/PVE/VZDump.pm +++ b/PVE/VZDump.pm @@ -609,6 +609,13 @@ sub compressor_info { } else { return ('gzip --rsyncable', 'gz'); } +} elsif ($opt_compress eq 'zstd') { + my $zstd_threads = $opts->{zstd} // 1; + if ($zstd_threads == 0) { + my $cpuinfo = PVE::ProcFSTools::read_cpuinfo(); + $zstd_threads = int(($cpuinfo->{cpus} + 1)/2); + } + return ("zstd --threads=${zstd_threads}", 'zst'); } else { die "internal error - unknown compression option '$opt_compress'"; } @@ -620,7 +627,7 @@ sub get_backup_file_list { my $bklist = []; foreach my $fn (<$dir/${bkname}-*>) { next if $exclude_fn && $fn eq $exclude_fn; - if ($fn =~ m!/(${bkname}-(\d{4})_(\d{2})_(\d{2})-(\d{2})_(\d{2})_(\d{2})\.(tgz|((tar|vma)(\.(gz|lzo))?)))$!) { + if ($fn =~ m!/(${bkname}-(\d{4})_(\d{2})_(\d{2})-(\d{2})_(\d{2})_(\d{2})\.(tgz|((tar|vma)(\.(${\PVE::Storage::Plugin::COMPRESSOR_RE}))?)))$!) { $fn = "$dir/$1"; # untaint my $t = timelocal ($7, $6, $5, $4, $3 - 1, $2); push @$bklist, [$fn, $t]; @@ -928,7 +935,7 @@ sub exec_backup_task { debugmsg ('info', "delete old backup '$d->[0]'", $logfd); unlink $d->[0]; my $logfn = $d->[0]; - $logfn =~ s/\.(tgz|((tar|vma)(\.(gz|lzo))?))$/\.log/; + $logfn =~ s/\.(tgz|((tar|vma)(\.(${\PVE::Storage::Plugin::COMPRESSOR_RE}))?))$/\.log/; unlink $logfn; } } diff --git a/debian/control b/debian/control index edb2833d..318b4f0e 100644 --- a/debian/control +++ b/debian/control @@ -60,6 +60,7 @@ Depends: apt-transport-https | apt (>= 1.5~), logrotate, lsb-base, lzop, + zstd, novnc-pve, pciutils, perl (>= 5.10.0-19), diff --git a/www/manager6/form/CompressionSelector.js b/www/manager6/form/CompressionSelector.js index 8938fc0e..842b7710 100644 --- a/www/manager6/form/CompressionSelector.js +++ b/www/manager6/form/CompressionSelector.js @@ -4,6 +4,7 @@ Ext.define('PVE.form.CompressionSelector', { comboItems: [ ['0', Proxmox.Utils.noneText], ['lzo', 'LZO (' + gettext('fast') + ')'], -['gzip', 'GZIP (' + gettext('good') + ')'] +['gzip', 'GZIP (' + gettext('good') + ')'], +['zstd', 'ZSTD (' + gettext('better') + ')'], ] }); -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 03/12] test: parse_volname
Test to reduce the potential for accidental breakage on regex changes. And to make sure that all vtype_subdirs are parsed. Signed-off-by: Alwin Antreich --- PVE/Storage/Plugin.pm | 4 + test/parse_volname_test.pm | 253 + test/run_plugin_tests.pl | 2 +- 3 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 test/parse_volname_test.pm diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index dba6eb9..0925910 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -457,6 +457,10 @@ my $vtype_subdirs = { snippets => 'snippets', }; +sub get_vtype_subdirs { +return $vtype_subdirs; +} + sub get_subdir { my ($class, $scfg, $vtype) = @_; diff --git a/test/parse_volname_test.pm b/test/parse_volname_test.pm new file mode 100644 index 000..87c758c --- /dev/null +++ b/test/parse_volname_test.pm @@ -0,0 +1,253 @@ +package PVE::Storage::TestParseVolname; + +use strict; +use warnings; + +use lib qw(..); + +use PVE::Storage; +use Test::More; + +my $vmid = 1234; + +# an array of test cases, each test is comprised of the following keys: +# description => to identify a single test +# volname => the input for parse_volname +# expected=> the array that parse_volname returns +my $tests = [ +# +# VM images +# +{ + description => 'VM disk image, linked, qcow2, vm- as base-', + volname => "$vmid/vm-$vmid-disk-0.qcow2/$vmid/vm-$vmid-disk-0.qcow2", + expected=> [ 'images', "vm-$vmid-disk-0.qcow2", "$vmid", "vm-$vmid-disk-0.qcow2", "$vmid", undef, 'qcow2', ], +}, +# +# iso +# +{ + description => 'ISO image, iso', + volname => 'iso/some-installation-disk.iso', + expected=> ['iso', 'some-installation-disk.iso'], +}, +{ + description => 'ISO image, img', + volname => 'iso/some-other-installation-disk.img', + expected=> ['iso', 'some-other-installation-disk.img'], +}, +# +# container templates +# +{ + description => 'Container template tar.gz', + volname => 'vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz', + expected=> ['vztmpl', 'debian-10.0-standard_10.0-1_amd64.tar.gz'], +}, +{ + description => 'Container template tar.xz', + volname => 'vztmpl/debian-10.0-standard_10.0-1_amd64.tar.xz', + expected=> ['vztmpl', 'debian-10.0-standard_10.0-1_amd64.tar.xz'], +}, +# +# container rootdir +# +{ + description => 'Container rootdir, sub directory', + volname => "rootdir/$vmid", + expected=> ['rootdir', "$vmid", "$vmid"], +}, +{ + description => 'Container rootdir, subvol', + volname => "$vmid/subvol-$vmid-disk-0.subvol", + expected=> [ 'images', "subvol-$vmid-disk-0.subvol", "$vmid", undef, undef, undef, 'subvol' ], +}, +{ + description => 'Backup archive, no virtualization type', + volname => "backup/vzdump-none-$vmid-2020_03_30-21_39_30.tar", + expected=> ['backup', "vzdump-none-$vmid-2020_03_30-21_39_30.tar"], +}, +# +# Snippets +# +{ + description => 'Snippets, yaml', + volname => 'snippets/userconfig.yaml', + expected=> ['snippets', 'userconfig.yaml'], +}, +{ + description => 'Snippets, perl', + volname => 'snippets/hookscript.pl', + expected=> ['snippets', 'hookscript.pl'], +}, +# +# failed matches +# +{ + description => "Failed match: VM disk image, base, raw", + volname => "/base-$vmid-disk-0.raw", + expected=> "unable to parse directory volume name '/base-$vmid-disk-0.raw'\n", +}, +{ + description => 'Failed match: ISO image, dvd', + volname => 'iso/yet-again-a-installation-disk.dvd', + expected=> "unable to parse directory volume name 'iso/yet-again-a-installation-disk.dvd'\n", +}, +{ + description => 'Failed match: Container template, zip.gz', + volname => 'vztmpl/debian-10.0-standard_10.0-1_amd64.zip.gz', + expected=> "unable to parse directory volume name 'vztmpl/debian-10.0-standard_10.0-1_amd64.zip.gz'\n", +}, +{ + description => 'Failed match: Container template, tar.bz2', + volname => 'vztmpl/debian-10.0-standard_10.0-1_amd64.tar.bz2', + expected=> "unable to parse directory volume name 'vztmpl/debian-10.0-standard_10.0-1_amd64.tar.bz2'\n", +}, +{ + description => 'Failed match: Container rootdir, subvol', + volname => "rootdir/subvol-$vmid-disk-0", + expected=> "unable to parse directory volume name 'rootdir/subvol-$vmid-disk-0'\n", +}, +{ + description => 'Failed match: VM disk image, linked, vhdx', + volname => "$vmid/base-$vmid-disk-0.vhdx/$vmid/vm-$vmid-disk-0.vhdx", + expected=> "unable to
[pve-devel] [PATCH storage v5 05/12] Fix: backup: ctime was from stat not file name
The vzdump file was passed with the full path to the regex. That regex captures the time from the file name, to calculate the epoch. As the regex didn't match, the ctime from stat was taken instead. This resulted in the ctime shown when the file was changed, not when the backup was made. Signed-off-by: Alwin Antreich --- PVE/Storage/Plugin.pm | 3 ++- test/list_volumes_test.pm | 16 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index 0925910..a6071eb 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -942,7 +942,8 @@ my $get_subdir_files = sub { next if $fn !~ m!/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!; my $format = $2; - $info = { volid => "$sid:backup/$1", format => $format }; + $fn = $1; + $info = { volid => "$sid:backup/$fn", format => $format }; if ($fn =~ m!^vzdump\-(?:lxc|qemu)\-(?:[1-9][0-9]{2,8})\-(\d{4})_(\d{2})_(\d{2})\-(\d{2})_(\d{2})_(\d{2})\.${format}$!) { my $epoch = timelocal($6, $5, $4, $3, $2-1, $1 - 1900); diff --git a/test/list_volumes_test.pm b/test/list_volumes_test.pm index a215617..941b903 100644 --- a/test/list_volumes_test.pm +++ b/test/list_volumes_test.pm @@ -129,7 +129,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1585595500, 'format' => 'vma.gz', 'size'=> DEFAULT_SIZE, 'vmid'=> '16110', @@ -137,7 +137,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1585595565, 'format' => 'vma.lzo', 'size'=> DEFAULT_SIZE, 'vmid'=> '16110', @@ -145,7 +145,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1585595635, 'format' => 'vma', 'size'=> DEFAULT_SIZE, 'vmid'=> '16110', @@ -189,7 +189,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1585597170, 'format' => 'tar.lzo', 'size'=> DEFAULT_SIZE, 'vmid'=> '16112', @@ -197,7 +197,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1585597770, 'format' => 'tar.gz', 'size'=> DEFAULT_SIZE, 'vmid'=> '16112', @@ -205,7 +205,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1585598370, 'format' => 'tgz', 'size'=> DEFAULT_SIZE, 'vmid'=> '16112', @@ -347,7 +347,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1580756263, 'format' => 'tar.gz', 'size'=> DEFAULT_SIZE, 'vmid'=> '19253', @@ -355,7 +355,7 @@ my @tests = ( }, { 'content' => 'backup', - 'ctime' => DEFAULT_CTIME, + 'ctime' => 1548095359, 'format' => 'tar', 'size'=> DEFAULT_SIZE, 'vmid'=> '19254', -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 11/12] test: get_subdir
Co-Authored-by: Dominic Jaeger Signed-off-by: Alwin Antreich --- test/get_subdir_test.pm | 44 test/run_plugin_tests.pl | 1 + 2 files changed, 45 insertions(+) create mode 100644 test/get_subdir_test.pm diff --git a/test/get_subdir_test.pm b/test/get_subdir_test.pm new file mode 100644 index 000..576c475 --- /dev/null +++ b/test/get_subdir_test.pm @@ -0,0 +1,44 @@ +package PVE::Storage::TestGetSubdir; + +use strict; +use warnings; + +use lib qw(..); + +use PVE::Storage::Plugin; +use Test::More; + +my $scfg_with_path = { path => '/some/path' }; +my $vtype_subdirs = PVE::Storage::Plugin::get_vtype_subdirs(); + +# each test is comprised of the following array keys: +# [0] => storage config; positive with path key +# [1] => storage type; see $vtype_subdirs +# [2] => expected return from get_subdir +my $tests = [ +# failed matches +[ $scfg_with_path, 'none', "unknown vtype 'none'\n" ], +[ {}, 'iso', "storage definintion has no path\n" ], +]; + +# creates additional positive tests +foreach my $type (keys %$vtype_subdirs) { +my $path = "$scfg_with_path->{path}/$vtype_subdirs->{$type}"; +push @$tests, [ $scfg_with_path, $type, $path ]; +} + +plan tests => scalar @$tests; + +foreach my $tt (@$tests) { +my ($scfg, $type, $expected) = @$tt; + +my $got; +eval { $got = PVE::Storage::Plugin->get_subdir($scfg, $type) }; +$got = $@ if $@; + +is ($got, $expected, "get_subdir for $type") || diag(explain($got)); +} + +done_testing(); + +1; diff --git a/test/run_plugin_tests.pl b/test/run_plugin_tests.pl index 770b407..9e427eb 100755 --- a/test/run_plugin_tests.pl +++ b/test/run_plugin_tests.pl @@ -11,6 +11,7 @@ my $res = $harness->runtests( "parse_volname_test.pm", "list_volumes_test.pm", "path_to_volume_id_test.pm", +"get_subdir_test.pm", ); exit -1 if !$res || $res->{failed} || $res->{parse_errors}; -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 02/12] storage: replace build-in stat occurrences
with File::stat::stat to minimize variable declarations. And allow to mock this method in tests instead of the perl build-in stat. Signed-off-by: Alwin Antreich --- PVE/Diskmanage.pm | 9 + PVE/Storage/Plugin.pm | 34 ++ 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/PVE/Diskmanage.pm b/PVE/Diskmanage.pm index 13e7cd8..cac944d 100644 --- a/PVE/Diskmanage.pm +++ b/PVE/Diskmanage.pm @@ -6,6 +6,7 @@ use PVE::ProcFSTools; use Data::Dumper; use Cwd qw(abs_path); use Fcntl ':mode'; +use File::stat; use JSON; use PVE::Tools qw(extract_param run_command file_get_contents file_read_firstline dir_glob_regex dir_glob_foreach trim); @@ -673,11 +674,11 @@ sub get_disks { sub get_partnum { my ($part_path) = @_; -my ($mode, $rdev) = (stat($part_path))[2,6]; +my $st = stat($part_path); -next if !$mode || !S_ISBLK($mode) || !$rdev; -my $major = PVE::Tools::dev_t_major($rdev); -my $minor = PVE::Tools::dev_t_minor($rdev); +next if !$st->mode || !S_ISBLK($st->mode) || !$st->rdev; +my $major = PVE::Tools::dev_t_major($st->rdev); +my $minor = PVE::Tools::dev_t_minor($st->rdev); my $partnum_path = "/sys/dev/block/$major:$minor/"; my $partnum; diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index 4489a77..dba6eb9 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -7,6 +7,7 @@ use Fcntl ':mode'; use File::chdir; use File::Path; use File::Basename; +use File::stat qw(); use Time::Local qw(timelocal); use PVE::Tools qw(run_command); @@ -718,12 +719,10 @@ sub free_image { sub file_size_info { my ($filename, $timeout) = @_; -my @fs = stat($filename); -my $mode = $fs[2]; -my $ctime = $fs[10]; +my $st = File::stat::stat($filename); -if (S_ISDIR($mode)) { - return wantarray ? (0, 'subvol', 0, undef, $ctime) : 1; +if (S_ISDIR($st->mode)) { + return wantarray ? (0, 'subvol', 0, undef, $st->ctime) : 1; } my $json = ''; @@ -741,7 +740,7 @@ sub file_size_info { my ($size, $format, $used, $parent) = $info->@{qw(virtual-size format actual-size backing-filename)}; -return wantarray ? ($size, $format, $used, $parent, $ctime) : $size; +return wantarray ? ($size, $format, $used, $parent, $st->ctime) : $size; } sub volume_size_info { @@ -918,22 +917,9 @@ my $get_subdir_files = sub { foreach my $fn (<$path/*>) { - my ($dev, - $ino, - $mode, - $nlink, - $uid, - $gid, - $rdev, - $size, - $atime, - $mtime, - $ctime, - $blksize, - $blocks - ) = stat($fn); - - next if S_ISDIR($mode); + my $st = File::stat::stat($fn); + + next if S_ISDIR($st->mode); my $info; @@ -972,8 +958,8 @@ my $get_subdir_files = sub { }; } - $info->{size} = $size; - $info->{ctime} //= $ctime; + $info->{size} = $st->size; + $info->{ctime} //= $st->ctime; push @$res, $info; } -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH qemu-server v5 1/2] restore: replace archive format/compression
regex to reduce the code duplication, as archive_info and decompressor_info provides the same information as well. Signed-off-by: Alwin Antreich --- PVE/QemuServer.pm | 36 ++-- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 37c7320..265d4f8 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -5627,28 +5627,9 @@ sub tar_restore_cleanup { sub restore_file_archive { my ($archive, $vmid, $user, $opts) = @_; -my $format = $opts->{format}; -my $comp; - -if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) { - $format = 'tar' if !$format; - $comp = 'gzip'; -} elsif ($archive =~ m/\.tar$/) { - $format = 'tar' if !$format; -} elsif ($archive =~ m/.tar.lzo$/) { - $format = 'tar' if !$format; - $comp = 'lzop'; -} elsif ($archive =~ m/\.vma$/) { - $format = 'vma' if !$format; -} elsif ($archive =~ m/\.vma\.gz$/) { - $format = 'vma' if !$format; - $comp = 'gzip'; -} elsif ($archive =~ m/\.vma\.lzo$/) { - $format = 'vma' if !$format; - $comp = 'lzop'; -} else { - $format = 'vma' if !$format; # default -} +my $info = PVE::Storage::archive_info($archive); +my $format = $opts->{format} // $info->{format}; +my $comp = $info->{compression}; # try to detect archive format if ($format eq 'tar') { @@ -6235,14 +6216,9 @@ sub restore_vma_archive { } if ($comp) { - my $cmd; - if ($comp eq 'gzip') { - $cmd = ['zcat', $readfrom]; - } elsif ($comp eq 'lzop') { - $cmd = ['lzop', '-d', '-c', $readfrom]; - } else { - die "unknown compression method '$comp'\n"; - } + my $info = PVE::Storage::decompressor_info('vma', $comp); + my $cmd = $info->{decompressor}; + push @$cmd, $readfrom; $add_pipe->($cmd); } -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 07/12] Fix: path_to_volume_id returned wrong content
type for backup files. Patch includes changes of the test as well. Signed-off-by: Alwin Antreich --- PVE/Storage.pm | 2 +- test/path_to_volume_id_test.pm | 8 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PVE/Storage.pm b/PVE/Storage.pm index bdd6ebc..1ef5ed2 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -536,7 +536,7 @@ sub path_to_volume_id { return ('rootdir', "$sid:rootdir/$vmid"); } elsif ($path =~ m!^$backupdir/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!) { my $name = $1; - return ('iso', "$sid:backup/$name"); + return ('backup', "$sid:backup/$name"); } } diff --git a/test/path_to_volume_id_test.pm b/test/path_to_volume_id_test.pm index 744c3ee..7d69869 100644 --- a/test/path_to_volume_id_test.pm +++ b/test/path_to_volume_id_test.pm @@ -72,7 +72,7 @@ my @tests = ( description => 'Backup, vma.gz', volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz", expected=> [ - 'iso', + 'backup', 'local:backup/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz', ], }, @@ -80,7 +80,7 @@ my @tests = ( description => 'Backup, vma.lzo', volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo", expected=> [ - 'iso', + 'backup', 'local:backup/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo', ], }, @@ -88,7 +88,7 @@ my @tests = ( description => 'Backup, vma', volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma", expected=> [ - 'iso', + 'backup', 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma', ], }, @@ -96,7 +96,7 @@ my @tests = ( description => 'Backup, tar.lzo', volname => "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo", expected=> [ - 'iso', + 'backup', 'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo', ], }, -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 09/12] backup: compact regex for backup file filter
the more compact form of the regex should allow easier addition of new file extensions. Signed-off-by: Alwin Antreich --- PVE/Storage.pm| 4 ++-- PVE/Storage/Plugin.pm | 6 -- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 5df074d..0b2745e 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -535,7 +535,7 @@ sub path_to_volume_id { } elsif ($path =~ m!^$privatedir/(\d+)$!) { my $vmid = $1; return ('rootdir', "$sid:rootdir/$vmid"); - } elsif ($path =~ m!^$backupdir/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!) { + } elsif ($path =~ m!^$backupdir/([^/]+\.(?:tgz|(?:(?:tar|vma)(?:\.(?:${\PVE::Storage::Plugin::COMPRESSOR_RE}))?)))$!) { my $name = $1; return ('backup', "$sid:backup/$name"); } elsif ($path =~ m!^$snippetsdir/([^/]+)$!) { @@ -1392,7 +1392,7 @@ sub archive_info { my $info; my $volid = basename($archive); -if ($volid =~ /vzdump-(lxc|openvz|qemu)-\d+-(?:\d{4})_(?:\d{2})_(?:\d{2})-(?:\d{2})_(?:\d{2})_(?:\d{2})\.(tgz$|tar|vma)(?:\.(gz|lzo))?$/) { +if ($volid =~ /vzdump-(lxc|openvz|qemu)-\d+-(?:\d{4})_(?:\d{2})_(?:\d{2})-(?:\d{2})_(?:\d{2})_(?:\d{2})\.(tgz$|tar|vma)(?:\.(${\PVE::Storage::Plugin::COMPRESSOR_RE}))?$/) { $info = decompressor_info($2, $3); $info->{type} = $1; } else { diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index a6071eb..5f3e4c1 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -18,6 +18,8 @@ use JSON; use base qw(PVE::SectionConfig); +use constant COMPRESSOR_RE => 'gz|lzo'; + our @COMMON_TAR_FLAGS = qw( --one-file-system -p --sparse --numeric-owner --acls @@ -435,7 +437,7 @@ sub parse_volname { return ('vztmpl', $1); } elsif ($volname =~ m!^rootdir/(\d+)$!) { return ('rootdir', $1, $1); -} elsif ($volname =~ m!^backup/([^/]+(\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo)))$!) { +} elsif ($volname =~ m!^backup/([^/]+(?:\.(?:tgz|(?:(?:tar|vma)(?:\.(?:${\COMPRESSOR_RE}))?$!) { my $fn = $1; if ($fn =~ m/^vzdump-(openvz|lxc|qemu)-(\d+)-.+/) { return ('backup', $fn, $2); @@ -939,7 +941,7 @@ my $get_subdir_files = sub { } elsif ($tt eq 'backup') { next if defined($vmid) && $fn !~ m/\S+-$vmid-\S+/; - next if $fn !~ m!/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!; + next if $fn !~ m!/([^/]+\.(tgz|(?:(?:tar|vma)(?:\.(${\COMPRESSOR_RE}))?)))$!; my $format = $2; $fn = $1; -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH qemu-server v5 2/2] Fix #2124: Add support for zstd
Signed-off-by: Alwin Antreich --- PVE/QemuServer.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 265d4f8..fda1acb 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -7165,7 +7165,7 @@ sub complete_backup_archives { my $res = []; foreach my $id (keys %$data) { foreach my $item (@{$data->{$id}}) { - next if $item->{format} !~ m/^vma\.(gz|lzo)$/; + next if $item->{format} !~ m/^vma\.(${\PVE::Storage::Plugin::COMPRESSOR_RE})$/; push @$res, $item->{volid} if defined($item->{volid}); } } -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH container v5] Fix: #2124 add zstd
Signed-off-by: Alwin Antreich --- src/PVE/LXC/Create.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm index 52b0b48..39902a2 100644 --- a/src/PVE/LXC/Create.pm +++ b/src/PVE/LXC/Create.pm @@ -123,6 +123,7 @@ sub restore_tar_archive { '.bz2' => '-j', '.xz' => '-J', '.lzo' => '--lzop', + '.zst' => '--zstd', ); if ($archive =~ /\.tar(\.[^.]+)?$/) { if (defined($1)) { -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 08/12] Fix: add missing snippets subdir
since it is a valid content type and adapt the path_to_volume_id_test. Also adds an extra check if all vtype_subdirs are returned. Signed-off-by: Alwin Antreich --- PVE/Storage.pm | 4 test/path_to_volume_id_test.pm | 26 +- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 1ef5ed2..5df074d 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -512,6 +512,7 @@ sub path_to_volume_id { my $tmpldir = $plugin->get_subdir($scfg, 'vztmpl'); my $backupdir = $plugin->get_subdir($scfg, 'backup'); my $privatedir = $plugin->get_subdir($scfg, 'rootdir'); + my $snippetsdir = $plugin->get_subdir($scfg, 'snippets'); if ($path =~ m!^$imagedir/(\d+)/([^/\s]+)$!) { my $vmid = $1; @@ -537,6 +538,9 @@ sub path_to_volume_id { } elsif ($path =~ m!^$backupdir/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!) { my $name = $1; return ('backup', "$sid:backup/$name"); + } elsif ($path =~ m!^$snippetsdir/([^/]+)$!) { + my $name = $1; + return ('snippets', "$sid:snippets/$name"); } } diff --git a/test/path_to_volume_id_test.pm b/test/path_to_volume_id_test.pm index 7d69869..e5e24c1 100644 --- a/test/path_to_volume_id_test.pm +++ b/test/path_to_volume_id_test.pm @@ -134,18 +134,24 @@ my @tests = ( 'local:1234/subvol-1234-disk-0.subvol' ], }, - -# no matches { description => 'Snippets, yaml', volname => "$storage_dir/snippets/userconfig.yaml", - expected => [''], + expected => [ + 'snippets', + 'local:snippets/userconfig.yaml', + ], }, { description => 'Snippets, hookscript', volname => "$storage_dir/snippets/hookscript.pl", - expected=> [''], + expected=> [ + 'snippets', + 'local:snippets/hookscript.pl', + ], }, + +# no matches { description => 'CT template, tar.xz', volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.xz", @@ -210,7 +216,10 @@ my @tests = ( }, ); -plan tests => scalar @tests; +plan tests => scalar @tests + 1; + +my $seen_vtype; +my $vtype_subdirs = { map { $_ => 1 } keys %{ PVE::Storage::Plugin::get_vtype_subdirs() } }; foreach my $tt (@tests) { my $file = $tt->{volname}; @@ -232,8 +241,15 @@ foreach my $tt (@tests) { $got = $@ if $@; is_deeply($got, $expected, $description) || diag(explain($got)); + +$seen_vtype->{@$expected[0]} = 1 + if ( @$expected[0] ne '' && scalar @$expected > 1); } +# to check if all $vtype_subdirs are defined in path_to_volume_id +# or have a test +is_deeply($seen_vtype, $vtype_subdirs, "vtype_subdir check"); + #cleanup # File::Temp unlinks tempdir on exit -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 01/12] storage: test: split archive format/compressor
detection into separate functions so they are reusable and easier modifiable. This patch also adds the test for archive_info. Signed-off-by: Alwin Antreich --- test/Makefile | 5 +- PVE/Storage.pm| 79 +--- test/archive_info_test.pm | 125 ++ test/run_plugin_tests.pl | 12 4 files changed, 199 insertions(+), 22 deletions(-) create mode 100644 test/archive_info_test.pm create mode 100755 test/run_plugin_tests.pl diff --git a/test/Makefile b/test/Makefile index 833a597..c54b10f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,6 @@ all: test -test: test_zfspoolplugin test_disklist test_bwlimit +test: test_zfspoolplugin test_disklist test_bwlimit test_plugin test_zfspoolplugin: run_test_zfspoolplugin.pl ./run_test_zfspoolplugin.pl @@ -10,3 +10,6 @@ test_disklist: run_disk_tests.pl test_bwlimit: run_bwlimit_tests.pl ./run_bwlimit_tests.pl + +test_plugin: run_plugin_tests.pl + ./run_plugin_tests.pl diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 0848176..bdd6ebc 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -1351,6 +1351,53 @@ sub foreach_volid { } } +sub decompressor_info { +my ($format, $comp) = @_; + +if ($format eq 'tgz' && !defined($comp)) { + ($format, $comp) = ('tar', 'gz'); +} + +my $decompressor = { + tar => { + gz => ['tar', '-z'], + lzo => ['tar', '--lzop'], + }, + vma => { + gz => ['zcat'], + lzo => ['lzop', '-d', '-c'], + }, +}; + +die "ERROR: archive format not defined\n" + if !defined($decompressor->{$format}); + +my $decomp = $decompressor->{$format}->{$comp} if $comp; + +my $info = { + format => $format, + compression => $comp, + decompressor => $decomp, +}; + +return $info; +} + +sub archive_info { +my ($archive) = shift; +my $info; + +my $volid = basename($archive); +if ($volid =~ /vzdump-(lxc|openvz|qemu)-\d+-(?:\d{4})_(?:\d{2})_(?:\d{2})-(?:\d{2})_(?:\d{2})_(?:\d{2})\.(tgz$|tar|vma)(?:\.(gz|lzo))?$/) { + $info = decompressor_info($2, $3); + $info->{type} = $1; +} else { + die "ERROR: couldn't determine format and compression type\n"; +} + +return $info; +} + sub extract_vzdump_config_tar { my ($archive, $conf_re) = @_; @@ -1396,16 +1443,12 @@ sub extract_vzdump_config_vma { }; +my $info = archive_info($archive); +$comp //= $info->{compression}; +my $decompressor = $info->{decompressor}; + if ($comp) { - my $uncomp; - if ($comp eq 'gz') { - $uncomp = ["zcat", $archive]; - } elsif ($comp eq 'lzo') { - $uncomp = ["lzop", "-d", "-c", $archive]; - } else { - die "unknown compression method '$comp'\n"; - } - $cmd = [$uncomp, ["vma", "config", "-"]]; + $cmd = [ [@$decompressor, $archive], ["vma", "config", "-"] ]; # in some cases, lzop/zcat exits with 1 when its stdout pipe is # closed early by vma, detect this and ignore the exit code later @@ -1455,20 +1498,14 @@ sub extract_vzdump_config { } my $archive = abs_filesystem_path($cfg, $volid); +my $info = archive_info($archive); +my $format = $info->{format}; +my $comp = $info->{compression}; +my $type = $info->{type}; -if ($volid =~ /vzdump-(lxc|openvz)-\d+-(\d{4})_(\d{2})_(\d{2})-(\d{2})_(\d{2})_(\d{2})\.(tgz|(tar(\.(gz|lzo))?))$/) { +if ($type eq 'lxc' || $type eq 'openvz') { return extract_vzdump_config_tar($archive, qr!^(\./etc/vzdump/(pct|vps)\.conf)$!); -} elsif ($volid =~ /vzdump-qemu-\d+-(\d{4})_(\d{2})_(\d{2})-(\d{2})_(\d{2})_(\d{2})\.(tgz|((tar|vma)(\.(gz|lzo))?))$/) { - my $format; - my $comp; - if ($7 eq 'tgz') { - $format = 'tar'; - $comp = 'gz'; - } else { - $format = $9; - $comp = $11 if defined($11); - } - +} elsif ($type eq 'qemu') { if ($format eq 'tar') { return extract_vzdump_config_tar($archive, qr!\(\./qemu-server\.conf\)!); } else { diff --git a/test/archive_info_test.pm b/test/archive_info_test.pm new file mode 100644 index 000..c9bb1b7 --- /dev/null +++ b/test/archive_info_test.pm @@ -0,0 +1,125 @@ +package PVE::Storage::TestArchiveInfo; + +use strict; +use warnings; + +use lib qw(..); + +use PVE::Storage; +use Test::More; + +my $vmid = 16110; + +# an array of test cases, each test is comprised of the following keys: +# description => to identify a single test +# archive => the input filename for archive_info +# expected=> the hash that archive_info returns +# +# most of them are created further below +my $tests = [ +# backup archives +{ + description => 'Backup archive, lxc, tgz', + archive => "backup/vzdump-lxc-$vmid-2020_03_30-21_39_30.tgz", + expected=> { + 't
[pve-devel] [PATCH storage v5 06/12] test: path_to_volume_id
Test to reduce the potential for accidental breakage on regex changes. Signed-off-by: Alwin Antreich --- test/path_to_volume_id_test.pm | 242 + test/run_plugin_tests.pl | 2 +- 2 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 test/path_to_volume_id_test.pm diff --git a/test/path_to_volume_id_test.pm b/test/path_to_volume_id_test.pm new file mode 100644 index 000..744c3ee --- /dev/null +++ b/test/path_to_volume_id_test.pm @@ -0,0 +1,242 @@ +package PVE::Storage::TestPathToVolumeId; + +use strict; +use warnings; + +use lib qw(..); + +use PVE::Storage; + +use Test::More; + +use Cwd; +use File::Basename; +use File::Path qw(make_path remove_tree); +use File::Temp; + +my $storage_dir = File::Temp->newdir(); +my $scfg = { +'digest' => 'd29306346b8b25b90a4a96165f1e8f52d1af1eda', +'ids'=> { + 'local' => { + 'shared' => 0, + 'path' => "$storage_dir", + 'type' => 'dir', + 'maxfiles' => 0, + 'content' => { + 'snippets' => 1, + 'rootdir' => 1, + 'images' => 1, + 'iso' => 1, + 'backup' => 1, + 'vztmpl' => 1, + }, + }, +}, +'order' => { + 'local' => 1, +}, +}; + +# the tests array consists of hashes with the following keys: +# description => to identify the test case +# volname => to create the test file +# expected=> the result that path_to_volume_id should return +my @tests = ( +{ + description => 'Image, qcow2', + volname => "$storage_dir/images/16110/vm-16110-disk-0.qcow2", + expected=> [ + 'images', + 'local:16110/vm-16110-disk-0.qcow2', + ], +}, +{ + description => 'Image, raw', + volname => "$storage_dir/images/16112/vm-16112-disk-0.raw", + expected=> [ + 'images', + 'local:16112/vm-16112-disk-0.raw', + ], +}, +{ + description => 'Image template, qcow2', + volname => "$storage_dir/images/9004/base-9004-disk-0.qcow2", + expected=> [ + 'images', + 'local:9004/base-9004-disk-0.qcow2', + ], +}, + +{ + description => 'Backup, vma.gz', + volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz", + expected=> [ + 'iso', + 'local:backup/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz', + ], +}, +{ + description => 'Backup, vma.lzo', + volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo", + expected=> [ + 'iso', + 'local:backup/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo', + ], +}, +{ + description => 'Backup, vma', + volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma", + expected=> [ + 'iso', + 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma', + ], +}, +{ + description => 'Backup, tar.lzo', + volname => "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo", + expected=> [ + 'iso', + 'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo', + ], +}, + +{ + description => 'ISO file', + volname => "$storage_dir/template/iso/yet-again-a-installation-disk.iso", + expected=> [ + 'iso', + 'local:iso/yet-again-a-installation-disk.iso', + ], +}, +{ + description => 'CT template, tar.gz', + volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.gz", + expected=> [ + 'vztmpl', + 'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz', + ], +}, + +{ + description => 'Rootdir', + volname => "$storage_dir/private/1234/", # fileparse needs / at the end + expected=> [ + 'rootdir', + 'local:rootdir/1234', + ], +}, +{ + description => 'Rootdir, folder subvol', + volname => "$storage_dir/images/1234/subvol-1234-disk-0.subvol/", # fileparse needs / at the end + expected=> [ + 'images', + 'local:1234/subvol-1234-disk-0.subvol' + ], +}, + +# no matches +{ + description => 'Snippets, yaml', + volname => "$storage_dir/snippets/userconfig.yaml", + expected => [''], +}, +{ + description => 'Snippets, hookscript', + volname => "$storage_dir/snippets/hookscript.pl", + expected=> [''], +}, +{ + description => 'CT template, tar.xz', + volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.xz", + expected=> [''], +}, + +# no matches, path or files with failures +{ + description
[pve-devel] [PATCH storage v5 10/12] Fix: #2124 storage: add zstd support
Signed-off-by: Alwin Antreich --- PVE/Storage.pm | 4 +++- PVE/Storage/Plugin.pm | 2 +- test/archive_info_test.pm | 4 +++- test/list_volumes_test.pm | 18 ++ test/parse_volname_test.pm | 6 +++--- test/path_to_volume_id_test.pm | 16 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 0b2745e..87550b1 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -1366,10 +1366,12 @@ sub decompressor_info { tar => { gz => ['tar', '-z'], lzo => ['tar', '--lzop'], + zst => ['tar', '--zstd'], }, vma => { gz => ['zcat'], lzo => ['lzop', '-d', '-c'], + zst => ['zstd', '-q', '-d', '-c'], }, }; @@ -1460,7 +1462,7 @@ sub extract_vzdump_config_vma { my $errstring; my $err = sub { my $output = shift; - if ($output =~ m/lzop: Broken pipe: / || $output =~ m/gzip: stdout: Broken pipe/) { + if ($output =~ m/lzop: Broken pipe: / || $output =~ m/gzip: stdout: Broken pipe/ || $output =~ m/zstd: error 70 : Write error : Broken pipe/) { $broken_pipe = 1; } elsif (!defined ($errstring) && $output !~ m/^\s*$/) { $errstring = "Failed to extract config from VMA archive: $output\n"; diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index 5f3e4c1..e9da403 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -18,7 +18,7 @@ use JSON; use base qw(PVE::SectionConfig); -use constant COMPRESSOR_RE => 'gz|lzo'; +use constant COMPRESSOR_RE => 'gz|lzo|zst'; our @COMMON_TAR_FLAGS = qw( --one-file-system diff --git a/test/archive_info_test.pm b/test/archive_info_test.pm index c9bb1b7..283fe47 100644 --- a/test/archive_info_test.pm +++ b/test/archive_info_test.pm @@ -45,10 +45,12 @@ my $decompressor = { tar => { gz => ['tar', '-z'], lzo => ['tar', '--lzop'], + zst => ['tar', '--zstd'], }, vma => { gz => ['zcat'], lzo => ['lzop', '-d', '-c'], + zst => ['zstd', '-q', '-d', '-c'], }, }; @@ -85,7 +87,7 @@ foreach my $virt (keys %$bkp_suffix) { my $non_bkp_suffix = { 'openvz' => [ 'zip', 'tgz.lzo', 'tar.bz2', 'zip.gz', '', ], 'lxc'=> [ 'zip', 'tgz.lzo', 'tar.bz2', 'zip.gz', '', ], -'qemu' => [ 'vma.xz', 'vms.gz', '', ], +'qemu' => [ 'vma.xz', 'vms.gz', 'vmx.zst', '', ], 'none' => [ 'tar.gz', ], }; diff --git a/test/list_volumes_test.pm b/test/list_volumes_test.pm index 941b903..efcb547 100644 --- a/test/list_volumes_test.pm +++ b/test/list_volumes_test.pm @@ -93,6 +93,7 @@ my @tests = ( "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz", "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo", "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst", "$storage_dir/snippets/userconfig.yaml", "$storage_dir/snippets/hookscript.pl", ], @@ -151,6 +152,14 @@ my @tests = ( 'vmid'=> '16110', 'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma', }, + { + 'content' => 'backup', + 'ctime' => 1585595635, + 'format' => 'vma.zst', + 'size'=> DEFAULT_SIZE, + 'vmid'=> '16110', + 'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst', + }, { 'content' => 'snippets', 'ctime' => DEFAULT_CTIME, @@ -174,6 +183,7 @@ my @tests = ( "$storage_dir/images/16112/vm-16112-disk-0.raw", "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo", "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_49_30.tar.gz", + "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_49_30.tar.zst", "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_59_30.tgz", ], expected => [ @@ -203,6 +213,14 @@ my @tests = ( 'vmid'=> '16112', 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_49_30.tar.gz', }, + { + 'content' => 'backup', + 'ctime' => 1585597770, + 'format' => 'tar.zst', + 'size'=> DEFAULT_SIZE, + 'vmid'=> '16112', + 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_49_30.tar.zst', + }, { 'content' => 'backup', 'ctime' => 1585598370, diff --git a/test/parse_volname_test.pm b/test/parse_volname_test.pm index 87c758c..d6ac885 100644 --- a/test/parse_volname_test.pm +++ b/test/parse_volname_test.pm @@ -176,9 +176,9 @@ foreach my $s
[pve-devel] [PATCH storage v5 12/12] test: filesystem_path
Signed-off-by: Alwin Antreich --- test/filesystem_path_test.pm | 91 test/run_plugin_tests.pl | 1 + 2 files changed, 92 insertions(+) create mode 100644 test/filesystem_path_test.pm diff --git a/test/filesystem_path_test.pm b/test/filesystem_path_test.pm new file mode 100644 index 000..c1b6d90 --- /dev/null +++ b/test/filesystem_path_test.pm @@ -0,0 +1,91 @@ +package PVE::Storage::TestFilesystemPath; + +use strict; +use warnings; + +use lib qw(..); + +use PVE::Storage; +use Test::More; + +my $path = '/some/path'; + +# each array entry is a test that consists of the following keys: +# volname => image name that is passed to parse_volname +# snapname => to test the die condition +# expected => the array of return values; or the die message +my $tests = [ +{ + volname => '1234/vm-1234-disk-0.raw', + snapname => undef, + expected => [ + "$path/images/1234/vm-1234-disk-0.raw", + '1234', + 'images' + ], +}, +{ + volname => '1234/vm-1234-disk-0.raw', + snapname => 'my_snap', + expected => "can't snapshot this image format\n" +}, +{ + volname => '1234/vm-1234-disk-0.qcow2', + snapname => undef, + expected => [ + "$path/images/1234/vm-1234-disk-0.qcow2", + '1234', + 'images' + ], +}, +{ + volname => '1234/vm-1234-disk-0.qcow2', + snapname => 'my_snap', + expected => [ + "$path/images/1234/vm-1234-disk-0.qcow2", + '1234', + 'images' + ], +}, +{ + volname => 'iso/my-awesome-proxmox.iso', + snapname => undef, + expected => [ + "$path/template/iso/my-awesome-proxmox.iso", + undef, + 'iso' + ], +}, +{ + volname => "backup/vzdump-qemu-1234-2020_03_30-21_12_40.vma", + snapname => undef, + expected => [ + "$path/dump/vzdump-qemu-1234-2020_03_30-21_12_40.vma", + 1234, + 'backup' + ], +}, +]; + +plan tests => scalar @$tests; + +foreach my $tt (@$tests) { +my $volname = $tt->{volname}; +my $snapname = $tt->{snapname}; +my $expected = $tt->{expected}; +my $scfg = { path => $path }; +my $got; + +eval { + $got = [ PVE::Storage::Plugin->filesystem_path($scfg, $volname, $snapname) ]; +}; +$got = $@ if $@; + +is_deeply($got, $expected, "wantarray: filesystem_path for $volname") +|| diag(explain($got)); + +} + +done_testing(); + +1; diff --git a/test/run_plugin_tests.pl b/test/run_plugin_tests.pl index 9e427eb..e29fc88 100755 --- a/test/run_plugin_tests.pl +++ b/test/run_plugin_tests.pl @@ -12,6 +12,7 @@ my $res = $harness->runtests( "list_volumes_test.pm", "path_to_volume_id_test.pm", "get_subdir_test.pm", +"filesystem_path_test.pm", ); exit -1 if !$res || $res->{failed} || $res->{parse_errors}; -- 2.20.1 ___ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
[pve-devel] [PATCH storage v5 04/12] test: list_volumes
Test to reduce the potential for accidental breakage on regex changes. Co-Authored-by: Dominic Jaeger Signed-off-by: Alwin Antreich --- test/list_volumes_test.pm | 519 ++ test/run_plugin_tests.pl | 6 +- 2 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 test/list_volumes_test.pm diff --git a/test/list_volumes_test.pm b/test/list_volumes_test.pm new file mode 100644 index 000..a215617 --- /dev/null +++ b/test/list_volumes_test.pm @@ -0,0 +1,519 @@ +package PVE::Storage::TestListVolumes; + +use strict; +use warnings; + +use lib qw(..); + +use PVE::Storage; +use PVE::Cluster; +use PVE::Tools qw(run_command); + +use Test::More; +use Test::MockModule; + +use Cwd; +use File::Basename; +use File::Path qw(make_path remove_tree); +use File::stat qw(); +use File::Temp; +use Storable qw(dclone); + +use constant DEFAULT_SIZE => 131072; # 128 kiB +use constant DEFAULT_USED => 262144; # 256 kiB +use constant DEFAULT_CTIME => 1234567890; + +# get_vmlist() return values +my $mocked_vmlist = { +'version' => 1, +'ids' => { + '16110' => { + 'node'=> 'x42', + 'type'=> 'qemu', + 'version' => 4, + }, + '16112' => { + 'node'=> 'x42', + 'type'=> 'lxc', + 'version' => 7, + }, + '16114' => { + 'node'=> 'x42', + 'type'=> 'qemu', + 'version' => 2, + }, + '16113' => { + 'node'=> 'x42', + 'type'=> 'qemu', + 'version' => 5, + }, + '16115' => { + 'node'=> 'x42', + 'type'=> 'qemu', + 'version' => 1, + }, + '9004' => { + 'node'=> 'x42', + 'type'=> 'qemu', + 'version' => 6, + } +} +}; + +my $storage_dir = File::Temp->newdir(); +my $scfg = { +'type' => 'dir', +'maxfiles' => 0, +'path' => $storage_dir, +'shared' => 0, +'content' => { + 'iso' => 1, + 'rootdir' => 1, + 'vztmpl' => 1, + 'images' => 1, + 'snippets' => 1, + 'backup' => 1, +}, +}; + +# The test cases are comprised of an arry of hashes with the following keys: +# description => displayed on error by Test::More +# vmid=> used for image matches by list_volume +# files => array of files for qemu-img to create +# expected=> returned result hash +#(content, ctime, format, parent, size, used, vimd, volid) +my @tests = ( +{ + description => 'VMID: 16110, VM, qcow2, backup, snippets', + vmid => '16110', + files => [ + "$storage_dir/images/16110/vm-16110-disk-0.qcow2", + "$storage_dir/images/16110/vm-16110-disk-1.raw", + "$storage_dir/images/16110/vm-16110-disk-2.vmdk", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma", + "$storage_dir/snippets/userconfig.yaml", + "$storage_dir/snippets/hookscript.pl", + ], + expected => [ + { + 'content' => 'images', + 'ctime' => DEFAULT_CTIME, + 'format' => 'qcow2', + 'parent' => undef, + 'size'=> DEFAULT_SIZE, + 'used'=> DEFAULT_USED, + 'vmid'=> '16110', + 'volid' => 'local:16110/vm-16110-disk-0.qcow2', + }, + { + 'content' => 'images', + 'ctime' => DEFAULT_CTIME, + 'format' => 'raw', + 'parent' => undef, + 'size'=> DEFAULT_SIZE, + 'used'=> DEFAULT_USED, + 'vmid'=> '16110', + 'volid' => 'local:16110/vm-16110-disk-1.raw', + }, + { + 'content' => 'images', + 'ctime' => DEFAULT_CTIME, + 'format' => 'vmdk', + 'parent' => undef, + 'size'=> DEFAULT_SIZE, + 'used'=> DEFAULT_USED, + 'vmid'=> '16110', + 'volid' => 'local:16110/vm-16110-disk-2.vmdk', + }, + { + 'content' => 'backup', + 'ctime' => DEFAULT_CTIME, + 'format' => 'vma.gz', + 'size'=> DEFAULT_SIZE, + 'vmid'=> '16110', + 'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz', + }, + { + 'content' => 'backup', + 'ctime' => DEFAULT_CTIME, + 'format' => 'vma.lzo', + 'size'=> DEFAULT_SIZE, + 'vmid'=> '16110', + 'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo',