From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 67DE81FF13B for ; Wed, 22 Apr 2026 13:19:48 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id EDE921A22E; Wed, 22 Apr 2026 13:15:15 +0200 (CEST) From: "Max R. Carrara" To: pve-devel@lists.proxmox.com Subject: [PATCH pve-storage v1 37/54] test: list volumes: remove legacy code and migrate cases to new format Date: Wed, 22 Apr 2026 13:13:03 +0200 Message-ID: <20260422111322.257380-38-m.carrara@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260422111322.257380-1-m.carrara@proxmox.com> References: <20260422111322.257380-1-m.carrara@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1776856355303 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.083 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: ZGNZQBGSIZXG2FVYOMEI5M7DOPNNUBU7 X-Message-ID-Hash: ZGNZQBGSIZXG2FVYOMEI5M7DOPNNUBU7 X-MailFrom: m.carrara@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Remove all that remains of the old testing code, including the constants defined with the `use constant` pragma and other old variables. Migrate all remaining test cases over to the new format. Signed-off-by: Max R. Carrara --- src/test/list_volumes_test.pm | 1185 ++++++++++++++++++--------------- 1 file changed, 654 insertions(+), 531 deletions(-) diff --git a/src/test/list_volumes_test.pm b/src/test/list_volumes_test.pm index c83b782e..ca3bbac7 100644 --- a/src/test/list_volumes_test.pm +++ b/src/test/list_volumes_test.pm @@ -19,10 +19,6 @@ 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; - my $DEFAULT_SIZE = 128 * 1024; # 128 kiB my $DEFAULT_USED = 256 * 1024; # 256 kiB my $DEFAULT_CTIME = 1234567890; @@ -64,22 +60,6 @@ my $mocked_vmlist = { }, }; -my $storage_dir = File::Temp->newdir(); -my $scfg = { - 'type' => 'dir', - 'path' => $storage_dir, - 'shared' => 0, - 'content' => { - 'iso' => 1, - 'rootdir' => 1, - 'vztmpl' => 1, - 'images' => 1, - 'snippets' => 1, - 'backup' => 1, - 'import' => 1, - }, -}; - my $DEFAULT_STOREID = 'local'; my $DEFAULT_STORAGE_PATH = File::Temp->newdir(); my $DEFAULT_SCFG = { @@ -99,463 +79,6 @@ my $DEFAULT_SCFG = { my @BACKING_FILE_SUFFIXES = ('qcow2', 'raw', 'vmdk', 'vhdx'); -# 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: 16112, lxc, raw, backup', - vmid => '16112', - files => [ - "$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", - "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2", - ], - expected => [ - { - 'content' => 'rootdir', - 'ctime' => DEFAULT_CTIME, - 'format' => 'raw', - 'parent' => undef, - 'size' => DEFAULT_SIZE, - 'used' => DEFAULT_USED, - 'vmid' => '16112', - 'volid' => 'local:16112/vm-16112-disk-0.raw', - }, - { - 'content' => 'backup', - 'ctime' => 1585604370, - 'format' => 'tar.lzo', - 'size' => DEFAULT_SIZE, - 'subtype' => 'lxc', - 'vmid' => '16112', - 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo', - }, - { - 'content' => 'backup', - 'ctime' => 1585604970, - 'format' => 'tar.gz', - 'size' => DEFAULT_SIZE, - 'subtype' => 'lxc', - 'vmid' => '16112', - 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_49_30.tar.gz', - }, - { - 'content' => 'backup', - 'ctime' => 1585604970, - 'format' => 'tar.zst', - 'size' => DEFAULT_SIZE, - 'subtype' => 'lxc', - 'vmid' => '16112', - 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_49_30.tar.zst', - }, - { - 'content' => 'backup', - 'ctime' => 1585605570, - 'format' => 'tgz', - 'size' => DEFAULT_SIZE, - 'subtype' => 'lxc', - 'vmid' => '16112', - 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_59_30.tgz', - }, - { - 'content' => 'backup', - 'ctime' => 1585604370, - 'format' => 'tar.bz2', - 'size' => DEFAULT_SIZE, - 'subtype' => 'openvz', - 'vmid' => '16112', - 'volid' => 'local:backup/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2', - }, - ], - }, - { - description => 'VMID: 16114, VM, qcow2, linked clone', - vmid => '16114', - files => [ - "$storage_dir/images/16114/vm-16114-disk-0.qcow2", - "$storage_dir/images/16114/vm-16114-disk-1.qcow2", - ], - parent => [ - "../9004/base-9004-disk-0.qcow2", "../9004/base-9004-disk-1.qcow2", - ], - expected => [ - { - 'content' => 'images', - 'ctime' => DEFAULT_CTIME, - 'format' => 'qcow2', - 'parent' => '../9004/base-9004-disk-0.qcow2', - 'size' => DEFAULT_SIZE, - 'used' => DEFAULT_USED, - 'vmid' => '16114', - 'volid' => 'local:9004/base-9004-disk-0.qcow2/16114/vm-16114-disk-0.qcow2', - }, - { - 'content' => 'images', - 'ctime' => DEFAULT_CTIME, - 'format' => 'qcow2', - 'parent' => '../9004/base-9004-disk-1.qcow2', - 'size' => DEFAULT_SIZE, - 'used' => DEFAULT_USED, - 'vmid' => '16114', - 'volid' => 'local:9004/base-9004-disk-1.qcow2/16114/vm-16114-disk-1.qcow2', - }, - ], - }, - { - description => 'VMID: 9004, VM, template, qcow2', - vmid => '9004', - files => [ - "$storage_dir/images/9004/base-9004-disk-0.qcow2", - "$storage_dir/images/9004/base-9004-disk-1.qcow2", - ], - expected => [ - { - 'content' => 'images', - 'ctime' => DEFAULT_CTIME, - 'format' => 'qcow2', - 'parent' => undef, - 'size' => DEFAULT_SIZE, - 'used' => DEFAULT_USED, - 'vmid' => '9004', - 'volid' => 'local:9004/base-9004-disk-0.qcow2', - }, - { - 'content' => 'images', - 'ctime' => DEFAULT_CTIME, - 'format' => 'qcow2', - 'parent' => undef, - 'size' => DEFAULT_SIZE, - 'used' => DEFAULT_USED, - 'vmid' => '9004', - 'volid' => 'local:9004/base-9004-disk-1.qcow2', - }, - ], - }, - { - description => 'VMID: none, templates, snippets, backup', - vmid => undef, - files => [ - "$storage_dir/dump/vzdump-lxc-19253-2020_02_03-19_57_43.tar.gz", - "$storage_dir/dump/vzdump-lxc-19254-2019_01_21-19_29_19.tar", - "$storage_dir/template/iso/archlinux-2020.02.01-x86_64.iso", - "$storage_dir/template/iso/debian-8.11.1-amd64-DVD-1.iso", - "$storage_dir/template/iso/debian-9.12.0-amd64-netinst.iso", - "$storage_dir/template/iso/proxmox-ve_6.1-1.iso", - "$storage_dir/template/cache/archlinux-base_20190924-1_amd64.tar.gz", - "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.gz", - "$storage_dir/template/cache/debian-11.0-standard_11.0-1_amd64.tar.bz2", - "$storage_dir/template/cache/alpine-3.10-default_20190626_amd64.tar.xz", - "$storage_dir/snippets/userconfig.yaml", - "$storage_dir/snippets/hookscript.pl", - "$storage_dir/private/1234/", # fileparse needs / at the end - "$storage_dir/private/1234/subvol-1234-disk-0.subvol/", # fileparse needs / at the end - ], - expected => [ - { - 'content' => 'vztmpl', - 'ctime' => DEFAULT_CTIME, - 'format' => 'txz', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:vztmpl/alpine-3.10-default_20190626_amd64.tar.xz', - }, - { - 'content' => 'vztmpl', - 'ctime' => DEFAULT_CTIME, - 'format' => 'tgz', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:vztmpl/archlinux-base_20190924-1_amd64.tar.gz', - }, - { - 'content' => 'vztmpl', - 'ctime' => DEFAULT_CTIME, - 'format' => 'tgz', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz', - }, - { - 'content' => 'vztmpl', - 'ctime' => DEFAULT_CTIME, - 'format' => 'tbz2', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:vztmpl/debian-11.0-standard_11.0-1_amd64.tar.bz2', - }, - { - 'content' => 'iso', - 'ctime' => DEFAULT_CTIME, - 'format' => 'iso', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:iso/archlinux-2020.02.01-x86_64.iso', - }, - { - 'content' => 'iso', - 'ctime' => DEFAULT_CTIME, - 'format' => 'iso', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:iso/debian-8.11.1-amd64-DVD-1.iso', - }, - { - 'content' => 'iso', - 'ctime' => DEFAULT_CTIME, - 'format' => 'iso', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:iso/debian-9.12.0-amd64-netinst.iso', - }, - { - 'content' => 'iso', - 'ctime' => DEFAULT_CTIME, - 'format' => 'iso', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:iso/proxmox-ve_6.1-1.iso', - }, - { - 'content' => 'backup', - 'ctime' => 1580759863, - 'format' => 'tar.gz', - 'size' => DEFAULT_SIZE, - 'subtype' => 'lxc', - 'vmid' => '19253', - 'volid' => 'local:backup/vzdump-lxc-19253-2020_02_03-19_57_43.tar.gz', - }, - { - 'content' => 'backup', - 'ctime' => 1548098959, - 'format' => 'tar', - 'size' => DEFAULT_SIZE, - 'subtype' => 'lxc', - 'vmid' => '19254', - 'volid' => 'local:backup/vzdump-lxc-19254-2019_01_21-19_29_19.tar', - }, - { - 'content' => 'snippets', - 'ctime' => DEFAULT_CTIME, - 'format' => 'snippet', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:snippets/hookscript.pl', - }, - { - 'content' => 'snippets', - 'ctime' => DEFAULT_CTIME, - 'format' => 'snippet', - 'size' => DEFAULT_SIZE, - 'volid' => 'local:snippets/userconfig.yaml', - }, - ], - }, - { - description => 'VMID: none, parent, non-matching', - # string instead of vmid in folder - #"$storage_dir/images/ssss/base-4321-disk-0.qcow2/1234/vm-1234-disk-0.qcow2", - vmid => undef, - files => [ - "$storage_dir/images/1234/vm-1234-disk-0.qcow2", - ], - parent => [ - "../ssss/base-4321-disk-0.qcow2", - ], - expected => [ - { - 'content' => 'images', - 'ctime' => DEFAULT_CTIME, - 'format' => 'qcow2', - 'parent' => '../ssss/base-4321-disk-0.qcow2', - 'size' => DEFAULT_SIZE, - 'used' => DEFAULT_USED, - 'vmid' => '1234', - 'volid' => 'local:1234/vm-1234-disk-0.qcow2', - }, - ], - }, - { - description => 'VMID: none, non-matching', - # failed matches - vmid => undef, - files => [ - "$storage_dir/images/ssss/base-4321-disk-0.raw", - "$storage_dir/images/ssss/vm-1234-disk-0.qcow2", - "$storage_dir/template/iso/yet-again-a-installation-disk.dvd", - "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.zip.gz", - "$storage_dir/private/subvol-19254-disk-0/19254", - "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.zip.gz", - "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tgz.lzo", - "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vma.xz", - "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vms.gz", - ], - expected => [], # returns empty list - }, - { - description => 'VMID: none, valid file names for import', - vmid => undef, - files => [ - "$storage_dir/import/import.ova", - "$storage_dir/import/import.ovf", - "$storage_dir/import/some-disk.qcow2", - "$storage_dir/import/some-disk.vmdk", - "$storage_dir/import/some-raw-disk.raw", - ], - expected => [ - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ova', - size => DEFAULT_SIZE, - volid => "local:import/import.ova", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ovf', - size => DEFAULT_SIZE, - volid => "local:import/import.ovf", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'qcow2', - size => DEFAULT_SIZE, - volid => "local:import/some-disk.qcow2", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'vmdk', - size => DEFAULT_SIZE, - volid => "local:import/some-disk.vmdk", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'raw', - size => DEFAULT_SIZE, - volid => "local:import/some-raw-disk.raw", - }, - ], - }, - { - description => 'VMID: none, non-matching file paths for import', - vmid => undef, - files => [ - # Malformed file names - "$storage_dir/import/import.ovff", - "$storage_dir/import/importova", - "$storage_dir/import/import.ov", - "$storage_dir/import/diskraw", - "$storage_dir/import/diskvmdk", - "$storage_dir/import/disk.invalid", - "$storage_dir/import/.ova", - "$storage_dir/import/.raw", - # Trailing whitespace must not be trimmed - "$storage_dir/import/import.ova\t", - "$storage_dir/import/disk.raw ", - # Whitespace in file name - "$storage_dir/import/something I want to import.ova", - "$storage_dir/import/ .raw", - "$storage_dir/import/ disk .vmdk", - "$storage_dir/import/disk .qcow2", - "$storage_dir/import/ import.ova", - # Unsafe characters in file name - "$storage_dir/import/linux🐧-vm.ova", - "$storage_dir/import/🐪perl-playground🐪.ova", - "$storage_dir/import/fish_<><_<><_<><.ova", - $storage_dir . '/import/C:\\\\Windows\\Path.ova', - # Content inside .ova files may only be specified as part - # of volume names, and may never appear when looked up as - # a file path - "$storage_dir/import/import.ova/disk.qcow2", - "$storage_dir/import/import.ova/disk.raw", - "$storage_dir/import/import.ova/disk.vmdk", - "$storage_dir/import/import.ova/disk.invalid", - ], - expected => [], # returns empty list - }, - { - description => 'VMID: none, weird but valid file names for import', - vmid => undef, - files => [ - "$storage_dir/import/import.ova.ova", - "$storage_dir/import/import.ova.ova.ova", - "$storage_dir/import/import.ova.ova.ova.ova", - "$storage_dir/import/ova.ova", - "$storage_dir/import/ova.ovf", - "$storage_dir/import/ova.vmdk", - "$storage_dir/import/raw.raw.qcow2", - "$storage_dir/import/raw.raw.qcow2.import.qcow2", - "$storage_dir/import/raw.raw.raw.your-boat.ova", - ], - expected => [ - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ova', - size => DEFAULT_SIZE, - volid => "local:import/import.ova.ova", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ova', - size => DEFAULT_SIZE, - volid => "local:import/import.ova.ova.ova", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ova', - size => DEFAULT_SIZE, - volid => "local:import/import.ova.ova.ova.ova", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ova', - size => DEFAULT_SIZE, - volid => "local:import/ova.ova", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ovf', - size => DEFAULT_SIZE, - volid => "local:import/ova.ovf", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'vmdk', - size => DEFAULT_SIZE, - volid => "local:import/ova.vmdk", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'qcow2', - size => DEFAULT_SIZE, - volid => "local:import/raw.raw.qcow2", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'qcow2', - size => DEFAULT_SIZE, - volid => "local:import/raw.raw.qcow2.import.qcow2", - }, - { - content => 'import', - ctime => DEFAULT_CTIME, - format => 'ova', - size => DEFAULT_SIZE, - volid => "local:import/raw.raw.raw.your-boat.ova", - }, - ], - }, -); - =head2 TEST CASE FORMAT The parameters for individual test cases are hashes with the following @@ -737,6 +260,655 @@ my $test_param_list = [ }, ], }, + { + description => 'VMID: 16112, lxc, raw, backup', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => 16112, + vtypes => ['rootdir', 'backup'], + cases => [ + { + file => "$DEFAULT_STORAGE_PATH/images/16112/vm-16112-disk-0.raw", + expected => { + content => 'rootdir', + ctime => $DEFAULT_CTIME, + format => 'raw', + parent => undef, + size => $DEFAULT_SIZE, + used => $DEFAULT_USED, + vmid => '16112', + volid => 'local:16112/vm-16112-disk-0.raw', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo", + expected => { + content => 'backup', + ctime => 1585604370, + format => 'tar.lzo', + size => $DEFAULT_SIZE, + subtype => 'lxc', + vmid => '16112', + volid => 'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-lxc-16112-2020_03_30-21_49_30.tar.gz", + expected => { + content => 'backup', + ctime => 1585604970, + format => 'tar.gz', + size => $DEFAULT_SIZE, + subtype => 'lxc', + vmid => '16112', + volid => 'local:backup/vzdump-lxc-16112-2020_03_30-21_49_30.tar.gz', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-lxc-16112-2020_03_30-21_49_30.tar.zst", + expected => { + content => 'backup', + ctime => 1585604970, + format => 'tar.zst', + size => $DEFAULT_SIZE, + subtype => 'lxc', + vmid => '16112', + volid => 'local:backup/vzdump-lxc-16112-2020_03_30-21_49_30.tar.zst', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/dump/vzdump-lxc-16112-2020_03_30-21_59_30.tgz", + expected => { + content => 'backup', + ctime => 1585605570, + format => 'tgz', + size => $DEFAULT_SIZE, + subtype => 'lxc', + vmid => '16112', + volid => 'local:backup/vzdump-lxc-16112-2020_03_30-21_59_30.tgz', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2", + expected => { + content => 'backup', + ctime => 1585604370, + format => 'tar.bz2', + size => $DEFAULT_SIZE, + subtype => 'openvz', + vmid => '16112', + volid => 'local:backup/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2', + }, + }, + ], + }, + { + description => 'VMID: 16114, VM, qcow2, linked clone', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => 16114, + vtypes => ['images'], + cases => [ + { + file => "$DEFAULT_STORAGE_PATH/images/16114/vm-16114-disk-0.qcow2", + parent => '../9004/base-9004-disk-0.qcow2', + expected => { + content => 'images', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + parent => '../9004/base-9004-disk-0.qcow2', + size => $DEFAULT_SIZE, + used => $DEFAULT_USED, + vmid => '16114', + volid => 'local:9004/base-9004-disk-0.qcow2/16114/vm-16114-disk-0.qcow2', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/images/16114/vm-16114-disk-1.qcow2", + parent => '../9004/base-9004-disk-1.qcow2', + expected => { + content => 'images', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + parent => '../9004/base-9004-disk-1.qcow2', + size => $DEFAULT_SIZE, + used => $DEFAULT_USED, + vmid => '16114', + volid => 'local:9004/base-9004-disk-1.qcow2/16114/vm-16114-disk-1.qcow2', + }, + }, + ], + }, + { + description => 'VMID: 9004, VM, template, qcow2', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => 9004, + vtypes => ['images'], + cases => [ + { + file => "$DEFAULT_STORAGE_PATH/images/9004/base-9004-disk-0.qcow2", + expected => { + content => 'images', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + parent => undef, + size => $DEFAULT_SIZE, + used => $DEFAULT_USED, + vmid => '9004', + volid => 'local:9004/base-9004-disk-0.qcow2', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/images/9004/base-9004-disk-1.qcow2", + expected => { + content => 'images', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + parent => undef, + size => $DEFAULT_SIZE, + used => $DEFAULT_USED, + vmid => '9004', + volid => 'local:9004/base-9004-disk-1.qcow2', + }, + }, + ], + }, + { + description => 'VMID: none, templates, snippets, backup', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => undef, + vtypes => ['vztmpl', 'iso', 'backup', 'snippets'], + cases => [ + { + file => + "$DEFAULT_STORAGE_PATH/template/cache/alpine-3.10-default_20190626_amd64.tar.xz", + expected => { + content => 'vztmpl', + ctime => $DEFAULT_CTIME, + format => 'txz', + size => $DEFAULT_SIZE, + volid => 'local:vztmpl/alpine-3.10-default_20190626_amd64.tar.xz', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/template/cache/archlinux-base_20190924-1_amd64.tar.gz", + expected => { + content => 'vztmpl', + ctime => $DEFAULT_CTIME, + format => 'tgz', + size => $DEFAULT_SIZE, + volid => 'local:vztmpl/archlinux-base_20190924-1_amd64.tar.gz', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/template/cache/debian-10.0-standard_10.0-1_amd64.tar.gz", + expected => { + content => 'vztmpl', + ctime => $DEFAULT_CTIME, + format => 'tgz', + size => $DEFAULT_SIZE, + volid => 'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/template/cache/debian-11.0-standard_11.0-1_amd64.tar.bz2", + expected => { + content => 'vztmpl', + ctime => $DEFAULT_CTIME, + format => 'tbz2', + size => $DEFAULT_SIZE, + volid => 'local:vztmpl/debian-11.0-standard_11.0-1_amd64.tar.bz2', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/template/iso/archlinux-2020.02.01-x86_64.iso", + expected => { + content => 'iso', + ctime => $DEFAULT_CTIME, + format => 'iso', + size => $DEFAULT_SIZE, + volid => 'local:iso/archlinux-2020.02.01-x86_64.iso', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/template/iso/debian-8.11.1-amd64-DVD-1.iso", + expected => { + content => 'iso', + ctime => $DEFAULT_CTIME, + format => 'iso', + size => $DEFAULT_SIZE, + volid => 'local:iso/debian-8.11.1-amd64-DVD-1.iso', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/template/iso/debian-9.12.0-amd64-netinst.iso", + expected => { + content => 'iso', + ctime => $DEFAULT_CTIME, + format => 'iso', + size => $DEFAULT_SIZE, + volid => 'local:iso/debian-9.12.0-amd64-netinst.iso', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/template/iso/proxmox-ve_6.1-1.iso", + expected => { + content => 'iso', + ctime => $DEFAULT_CTIME, + format => 'iso', + size => $DEFAULT_SIZE, + volid => 'local:iso/proxmox-ve_6.1-1.iso', + }, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-lxc-19253-2020_02_03-19_57_43.tar.gz", + expected => { + content => 'backup', + ctime => 1580759863, + format => 'tar.gz', + size => $DEFAULT_SIZE, + subtype => 'lxc', + vmid => '19253', + volid => 'local:backup/vzdump-lxc-19253-2020_02_03-19_57_43.tar.gz', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/dump/vzdump-lxc-19254-2019_01_21-19_29_19.tar", + expected => { + content => 'backup', + ctime => 1548098959, + format => 'tar', + size => $DEFAULT_SIZE, + subtype => 'lxc', + vmid => '19254', + volid => 'local:backup/vzdump-lxc-19254-2019_01_21-19_29_19.tar', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/snippets/hookscript.pl", + expected => { + content => 'snippets', + ctime => $DEFAULT_CTIME, + format => 'snippet', + size => $DEFAULT_SIZE, + volid => 'local:snippets/hookscript.pl', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/snippets/userconfig.yaml", + expected => { + content => 'snippets', + ctime => $DEFAULT_CTIME, + format => 'snippet', + size => $DEFAULT_SIZE, + volid => 'local:snippets/userconfig.yaml', + }, + }, + { + # fileparse needs / at the end + file => "$DEFAULT_STORAGE_PATH/private/1234/", + expected => undef, + }, + { + # fileparse needs / at the end + file => "$DEFAULT_STORAGE_PATH/private/1234/subvol-1234-disk-0.subvol/", + expected => undef, + }, + ], + }, + { + description => 'VMID: none, parent, non-matching', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => undef, + vtypes => ['images'], + cases => [ + { + file => "$DEFAULT_STORAGE_PATH/images/1234/vm-1234-disk-0.qcow2", + parent => '../ssss/base-4321-disk-0.qcow2', + expected => { + content => 'images', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + parent => '../ssss/base-4321-disk-0.qcow2', + size => $DEFAULT_SIZE, + used => $DEFAULT_USED, + vmid => '1234', + volid => 'local:1234/vm-1234-disk-0.qcow2', + }, + }, + ], + }, + { + description => 'VMID: none, non-matching', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => undef, + vtypes => [sort keys $DEFAULT_SCFG->{content}->%*], + cases => [ + { + file => "$DEFAULT_STORAGE_PATH/images/ssss/base-4321-disk-0.raw", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/images/ssss/vm-1234-disk-0.qcow2", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/template/iso/yet-again-a-installation-disk.dvd", + expected => undef, + }, + { + file => + "$DEFAULT_STORAGE_PATH/template/cache/debian-10.0-standard_10.0-1_amd64.zip.gz", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/private/subvol-19254-disk-0/19254", + expected => undef, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-openvz-16112-2020_03_30-21_39_30.zip.gz", + expected => undef, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tgz.lzo", + expected => undef, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vma.xz", + expected => undef, + }, + { + file => + "$DEFAULT_STORAGE_PATH/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vms.gz", + expected => undef, + }, + ], + }, + { + description => 'VMID: none, valid file names for import', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => undef, + vtypes => ['import'], + cases => [ + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ova', + size => $DEFAULT_SIZE, + volid => 'local:import/import.ova', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/import.ovf", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ovf', + size => $DEFAULT_SIZE, + volid => 'local:import/import.ovf', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/some-disk.qcow2", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + size => $DEFAULT_SIZE, + volid => 'local:import/some-disk.qcow2', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/some-disk.vmdk", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'vmdk', + size => $DEFAULT_SIZE, + volid => 'local:import/some-disk.vmdk', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/some-raw-disk.raw", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'raw', + size => $DEFAULT_SIZE, + volid => 'local:import/some-raw-disk.raw', + }, + }, + ], + }, + { + description => 'VMID: none, non-matching file paths for import', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => undef, + vtypes => ['import'], + cases => [ + # Malformed file names + { + file => "$DEFAULT_STORAGE_PATH/import/import.ovff", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/importova", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/import.ov", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/diskraw", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/diskvmdk", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/disk.invalid", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/.ova", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/.raw", + expected => undef, + }, + + # Trailing whitespace must not be trimmed + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova\t", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/disk.raw ", + expected => undef, + }, + + # Whitespace in file name + { + file => "$DEFAULT_STORAGE_PATH/import/something I want to import.ova", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/ .raw", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/ disk .vmdk", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/disk .qcow2", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/ import.ova", + expected => undef, + }, + + # Unsafe characters in file name + { + file => "$DEFAULT_STORAGE_PATH/import/linux🐧-vm.ova", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/🐪perl-playground🐪.ova", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/fish_<><_<><_<><.ova", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/C:\\\\Windows\\Path.ova", + expected => undef, + }, + + # Content inside .ova files may only be specified as part + # of volume names, and may never appear when looked up as + # a file path + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova/disk.qcow2", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova/disk.raw", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova/disk.vmdk", + expected => undef, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova/disk.invalid", + expected => undef, + }, + ], + }, + { + description => 'VMID: none, weird but valid file names for import', + storeid => $DEFAULT_STOREID, + scfg => $DEFAULT_SCFG, + vmid => undef, + vtypes => ['import'], + cases => [ + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova.ova", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ova', + size => $DEFAULT_SIZE, + volid => 'local:import/import.ova.ova', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova.ova.ova", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ova', + size => $DEFAULT_SIZE, + volid => 'local:import/import.ova.ova.ova', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/import.ova.ova.ova.ova", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ova', + size => $DEFAULT_SIZE, + volid => 'local:import/import.ova.ova.ova.ova', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/ova.ova", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ova', + size => $DEFAULT_SIZE, + volid => 'local:import/ova.ova', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/ova.ovf", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ovf', + size => $DEFAULT_SIZE, + volid => 'local:import/ova.ovf', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/ova.vmdk", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'vmdk', + size => $DEFAULT_SIZE, + volid => 'local:import/ova.vmdk', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/raw.raw.qcow2", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + size => $DEFAULT_SIZE, + volid => 'local:import/raw.raw.qcow2', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/raw.raw.qcow2.import.qcow2", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'qcow2', + size => $DEFAULT_SIZE, + volid => 'local:import/raw.raw.qcow2.import.qcow2', + }, + }, + { + file => "$DEFAULT_STORAGE_PATH/import/raw.raw.raw.your-boat.ova", + expected => { + content => 'import', + ctime => $DEFAULT_CTIME, + format => 'ova', + size => $DEFAULT_SIZE, + volid => 'local:import/raw.raw.raw.your-boat.ova', + }, + }, + ], + }, ]; # provide static vmlist for tests @@ -749,8 +921,8 @@ my $mock_stat = Test::MockModule->new('File::stat', no_auto => 1); $mock_stat->redefine( populate => sub { my (@st) = @_; - $st[7] = DEFAULT_SIZE; - $st[10] = DEFAULT_CTIME; + $st[7] = $DEFAULT_SIZE; + $st[10] = $DEFAULT_CTIME; my $result = $mock_stat->original('populate')->(@st); @@ -765,8 +937,8 @@ $mock_fsi->redefine( my ($size, $format, $used, $parent, $ctime) = $mock_fsi->original('file_size_info')->(@_); - $size = DEFAULT_SIZE; - $used = DEFAULT_USED; + $size = $DEFAULT_SIZE; + $used = $DEFAULT_USED; return wantarray ? ($size, $format, $used, $parent, $ctime) : $size; }, @@ -776,53 +948,6 @@ my sub cmp_volinfo_by_volid { return $a->{volid} cmp $b->{volid}; } -my sub run_legacy_tests() { - my $sid = 'local'; - my $types = [grep { $scfg->{content}->{$_} } keys $scfg->{content}->%*]; - - # run through test cases - foreach my $tt (@tests) { - my $vmid = $tt->{vmid}; - my $files = $tt->{files}; - my $expected = [sort cmp_volinfo_by_volid $tt->{expected}->@*]; - my $description = $tt->{description}; - my $parent = $tt->{parent}; - - # prepare environment - my $num = 0; #parent disks - for my $file (@$files) { - my ($name, $dir, $suffix) = fileparse($file, @BACKING_FILE_SUFFIXES); - - make_path($dir, { verbose => 1, mode => 0755 }); - - if ($name) { - # using qemu-img to also be able to represent the backing device - my @cmd = ('/usr/bin/qemu-img', 'create', "$file", DEFAULT_SIZE); - push @cmd, ('-f', $suffix) if $suffix; - push @cmd, ('-u', '-b', @$parent[$num]) if $parent; - push @cmd, ('-F', $suffix) if $parent && $suffix; - $num++; - - run_command([@cmd]); - } - } - - my $got = eval { - my $volume_list = PVE::Storage::Plugin->list_volumes($sid, $scfg, $vmid, $types); - return [sort cmp_volinfo_by_volid $volume_list->@*]; - }; - $got = $@ if $@; - - is_deeply($got, $expected, $description) || diag(explain($got)); - - # clean up after each test case, otherwise - # we get wrong results from leftover files - remove_tree($storage_dir, { verbose => 1 }); - } - - return; -} - my sub setup_test_env($test_params) { my ($storeid, $scfg) = $test_params->@{qw(storeid scfg)}; @@ -913,7 +1038,7 @@ my sub assert_test_params_keys_exist($test_params) { } sub main() { - plan tests => scalar(@tests) + scalar($test_param_list->@*) + 1; + plan tests => scalar($test_param_list->@*) + 1; # Keep the original vmlist around in order to check whether it was modified # after running all the tests. See: @@ -925,8 +1050,6 @@ sub main() { run_test_for_params($test_params); } - run_legacy_tests(); - my $vmlist = PVE::Cluster::get_vmlist(); is_deeply( -- 2.47.3