auto-format code using perltidy with Proxmox style guide

using the new top-level `make tidy` target, which calls perltidy via
our wrapper to enforce the desired style as closely as possible.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht
2025-06-11 10:03:21 +02:00
parent 5d23073cb6
commit 5a66c27cc6
54 changed files with 14137 additions and 12461 deletions

View File

@ -22,119 +22,119 @@ my $NOTES_EXT = PVE::Storage::Plugin::NOTES_EXT;
my $tests = [
# backup archives
{
description => 'Backup archive, lxc, tgz, future millenium',
archive => "backup/vzdump-lxc-$vmid-3070_01_01-00_00_00.tgz",
expected => {
'filename' => "vzdump-lxc-$vmid-3070_01_01-00_00_00.tgz",
'logfilename' => "vzdump-lxc-$vmid-3070_01_01-00_00_00".$LOG_EXT,
'notesfilename'=> "vzdump-lxc-$vmid-3070_01_01-00_00_00.tgz".$NOTES_EXT,
'type' => 'lxc',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 60*60*24 * (365*1100 + 267),
'is_std_name' => 1,
},
description => 'Backup archive, lxc, tgz, future millenium',
archive => "backup/vzdump-lxc-$vmid-3070_01_01-00_00_00.tgz",
expected => {
'filename' => "vzdump-lxc-$vmid-3070_01_01-00_00_00.tgz",
'logfilename' => "vzdump-lxc-$vmid-3070_01_01-00_00_00" . $LOG_EXT,
'notesfilename' => "vzdump-lxc-$vmid-3070_01_01-00_00_00.tgz" . $NOTES_EXT,
'type' => 'lxc',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 60 * 60 * 24 * (365 * 1100 + 267),
'is_std_name' => 1,
},
},
{
description => 'Backup archive, lxc, tgz, very old',
archive => "backup/vzdump-lxc-$vmid-1970_01_01-02_00_30.tgz",
expected => {
'filename' => "vzdump-lxc-$vmid-1970_01_01-02_00_30.tgz",
'logfilename' => "vzdump-lxc-$vmid-1970_01_01-02_00_30".$LOG_EXT,
'notesfilename'=> "vzdump-lxc-$vmid-1970_01_01-02_00_30.tgz".$NOTES_EXT,
'type' => 'lxc',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 60*60*2 + 30,
'is_std_name' => 1,
},
description => 'Backup archive, lxc, tgz, very old',
archive => "backup/vzdump-lxc-$vmid-1970_01_01-02_00_30.tgz",
expected => {
'filename' => "vzdump-lxc-$vmid-1970_01_01-02_00_30.tgz",
'logfilename' => "vzdump-lxc-$vmid-1970_01_01-02_00_30" . $LOG_EXT,
'notesfilename' => "vzdump-lxc-$vmid-1970_01_01-02_00_30.tgz" . $NOTES_EXT,
'type' => 'lxc',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 60 * 60 * 2 + 30,
'is_std_name' => 1,
},
},
{
description => 'Backup archive, lxc, tgz',
archive => "backup/vzdump-lxc-$vmid-2020_03_30-21_39_30.tgz",
expected => {
'filename' => "vzdump-lxc-$vmid-2020_03_30-21_39_30.tgz",
'logfilename' => "vzdump-lxc-$vmid-2020_03_30-21_39_30".$LOG_EXT,
'notesfilename'=> "vzdump-lxc-$vmid-2020_03_30-21_39_30.tgz".$NOTES_EXT,
'type' => 'lxc',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 1585604370,
'is_std_name' => 1,
},
description => 'Backup archive, lxc, tgz',
archive => "backup/vzdump-lxc-$vmid-2020_03_30-21_39_30.tgz",
expected => {
'filename' => "vzdump-lxc-$vmid-2020_03_30-21_39_30.tgz",
'logfilename' => "vzdump-lxc-$vmid-2020_03_30-21_39_30" . $LOG_EXT,
'notesfilename' => "vzdump-lxc-$vmid-2020_03_30-21_39_30.tgz" . $NOTES_EXT,
'type' => 'lxc',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 1585604370,
'is_std_name' => 1,
},
},
{
description => 'Backup archive, openvz, tgz',
archive => "backup/vzdump-openvz-$vmid-2020_03_30-21_39_30.tgz",
expected => {
'filename' => "vzdump-openvz-$vmid-2020_03_30-21_39_30.tgz",
'logfilename' => "vzdump-openvz-$vmid-2020_03_30-21_39_30".$LOG_EXT,
'notesfilename'=> "vzdump-openvz-$vmid-2020_03_30-21_39_30.tgz".$NOTES_EXT,
'type' => 'openvz',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 1585604370,
'is_std_name' => 1,
},
description => 'Backup archive, openvz, tgz',
archive => "backup/vzdump-openvz-$vmid-2020_03_30-21_39_30.tgz",
expected => {
'filename' => "vzdump-openvz-$vmid-2020_03_30-21_39_30.tgz",
'logfilename' => "vzdump-openvz-$vmid-2020_03_30-21_39_30" . $LOG_EXT,
'notesfilename' => "vzdump-openvz-$vmid-2020_03_30-21_39_30.tgz" . $NOTES_EXT,
'type' => 'openvz',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 1585604370,
'is_std_name' => 1,
},
},
{
description => 'Backup archive, custom dump directory, qemu, tgz',
archive => "/here/be/Back-ups/vzdump-qemu-$vmid-2020_03_30-21_39_30.tgz",
expected => {
'filename' => "vzdump-qemu-$vmid-2020_03_30-21_39_30.tgz",
'logfilename' => "vzdump-qemu-$vmid-2020_03_30-21_39_30".$LOG_EXT,
'notesfilename'=> "vzdump-qemu-$vmid-2020_03_30-21_39_30.tgz".$NOTES_EXT,
'type' => 'qemu',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 1585604370,
'is_std_name' => 1,
},
description => 'Backup archive, custom dump directory, qemu, tgz',
archive => "/here/be/Back-ups/vzdump-qemu-$vmid-2020_03_30-21_39_30.tgz",
expected => {
'filename' => "vzdump-qemu-$vmid-2020_03_30-21_39_30.tgz",
'logfilename' => "vzdump-qemu-$vmid-2020_03_30-21_39_30" . $LOG_EXT,
'notesfilename' => "vzdump-qemu-$vmid-2020_03_30-21_39_30.tgz" . $NOTES_EXT,
'type' => 'qemu',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'vmid' => $vmid,
'ctime' => 1585604370,
'is_std_name' => 1,
},
},
{
description => 'Backup archive, none, tgz',
archive => "backup/vzdump-qemu-$vmid-whatever-the-name_is_here.tgz",
expected => {
'filename' => "vzdump-qemu-$vmid-whatever-the-name_is_here.tgz",
'type' => 'qemu',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'is_std_name' => 0,
},
description => 'Backup archive, none, tgz',
archive => "backup/vzdump-qemu-$vmid-whatever-the-name_is_here.tgz",
expected => {
'filename' => "vzdump-qemu-$vmid-whatever-the-name_is_here.tgz",
'type' => 'qemu',
'format' => 'tar',
'decompressor' => ['tar', '-z'],
'compression' => 'gz',
'is_std_name' => 0,
},
},
];
# add new compression fromats to test
my $decompressor = {
tar => {
gz => ['tar', '-z'],
lzo => ['tar', '--lzop'],
zst => ['tar', '--zstd'],
bz2 => ['tar', '--bzip2'],
gz => ['tar', '-z'],
lzo => ['tar', '--lzop'],
zst => ['tar', '--zstd'],
bz2 => ['tar', '--bzip2'],
},
vma => {
gz => ['zcat'],
lzo => ['lzop', '-d', '-c'],
zst => ['zstd', '-q', '-d', '-c'],
bz2 => ['bzcat', '-q'],
gz => ['zcat'],
lzo => ['lzop', '-d', '-c'],
zst => ['zstd', '-q', '-d', '-c'],
bz2 => ['bzcat', '-q'],
},
};
my $bkp_suffix = {
qemu => [ 'vma', $decompressor->{vma}, ],
lxc => [ 'tar', $decompressor->{tar}, ],
openvz => [ 'tar', $decompressor->{tar}, ],
qemu => ['vma', $decompressor->{vma}],
lxc => ['tar', $decompressor->{tar}],
openvz => ['tar', $decompressor->{tar}],
};
# create more test cases for backup files matches
@ -143,48 +143,48 @@ for my $virt (sort keys %$bkp_suffix) {
my $archive_name = "vzdump-$virt-$vmid-2020_03_30-21_12_40";
for my $suffix (sort keys %$decomp) {
push @$tests, {
description => "Backup archive, $virt, $format.$suffix",
archive => "backup/$archive_name.$format.$suffix",
expected => {
'filename' => "$archive_name.$format.$suffix",
'logfilename' => $archive_name.$LOG_EXT,
'notesfilename'=> "$archive_name.$format.$suffix".$NOTES_EXT,
'type' => "$virt",
'format' => "$format",
'decompressor' => $decomp->{$suffix},
'compression' => "$suffix",
'vmid' => $vmid,
'ctime' => 1585602760,
'is_std_name' => 1,
},
};
push @$tests,
{
description => "Backup archive, $virt, $format.$suffix",
archive => "backup/$archive_name.$format.$suffix",
expected => {
'filename' => "$archive_name.$format.$suffix",
'logfilename' => $archive_name . $LOG_EXT,
'notesfilename' => "$archive_name.$format.$suffix" . $NOTES_EXT,
'type' => "$virt",
'format' => "$format",
'decompressor' => $decomp->{$suffix},
'compression' => "$suffix",
'vmid' => $vmid,
'ctime' => 1585602760,
'is_std_name' => 1,
},
};
}
}
# add compression formats to test failed matches
my $non_bkp_suffix = {
'openvz' => [ 'zip', 'tgz.lzo', 'zip.gz', '', ],
'lxc' => [ 'zip', 'tgz.lzo', 'zip.gz', '', ],
'qemu' => [ 'vma.xz', 'vms.gz', 'vmx.zst', '', ],
'none' => [ 'tar.gz', ],
'openvz' => ['zip', 'tgz.lzo', 'zip.gz', ''],
'lxc' => ['zip', 'tgz.lzo', 'zip.gz', ''],
'qemu' => ['vma.xz', 'vms.gz', 'vmx.zst', ''],
'none' => ['tar.gz'],
};
# create tests for failed matches
for my $virt (sort keys %$non_bkp_suffix) {
my $suffix = $non_bkp_suffix->{$virt};
for my $s (@$suffix) {
my $archive = "backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s";
push @$tests, {
description => "Failed match: Backup archive, $virt, $s",
archive => $archive,
expected => "ERROR: couldn't determine archive info from '$archive'\n",
};
my $archive = "backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s";
push @$tests,
{
description => "Failed match: Backup archive, $virt, $s",
archive => $archive,
expected => "ERROR: couldn't determine archive info from '$archive'\n",
};
}
}
plan tests => scalar @$tests;
for my $tt (@$tests) {

View File

@ -23,57 +23,57 @@ sub mocked_run_command {
my $outputlines = [];
if (my $ref = ref($cmd)) {
if ($cmd->[0] =~ m/udevadm/i) {
# simulate udevadm output
my $dev = $cmd->[3];
$dev =~ s|/sys/block/||;
@$outputlines = split(/\n/, read_test_file("${dev}_udevadm"));
if ($cmd->[0] =~ m/udevadm/i) {
# simulate udevadm output
my $dev = $cmd->[3];
$dev =~ s|/sys/block/||;
@$outputlines = split(/\n/, read_test_file("${dev}_udevadm"));
} elsif ($cmd->[0] =~ m/smartctl/i) {
# simulate smartctl output
my $dev;
my $type;
if (@$cmd > 3) {
$dev = $cmd->[5];
$type = 'smart';
} else {
$dev = $cmd->[2];
$type = 'health';
}
$dev =~ s|/dev/||;
@$outputlines = split(/\n/, read_test_file("${dev}_${type}"));
} elsif ($cmd->[0] =~ m/sgdisk/i) {
# simulate sgdisk
die "implement me: @$cmd\n";
} elsif ($cmd->[0] =~ m/zpool/i) {
# simulate zpool output
@$outputlines = split(/\n/, read_test_file('zpool'));
} elsif ($cmd->[0] =~ m/smartctl/i) {
# simulate smartctl output
my $dev;
my $type;
if (@$cmd > 3) {
$dev = $cmd->[5];
$type = 'smart';
} else {
$dev = $cmd->[2];
$type = 'health';
}
$dev =~ s|/dev/||;
@$outputlines = split(/\n/, read_test_file("${dev}_${type}"));
} elsif ($cmd->[0] =~ m/sgdisk/i) {
# simulate sgdisk
die "implement me: @$cmd\n";
} elsif ($cmd->[0] =~ m/zpool/i) {
# simulate zpool output
@$outputlines = split(/\n/, read_test_file('zpool'));
} elsif ($cmd->[0] =~ m/pvs/i) {
# simulate lvs output
@$outputlines = split(/\n/, read_test_file('pvs'));
} elsif ($cmd->[0] =~ m/lvs/i) {
@$outputlines = split(/\n/, read_test_file('lvs'));
} elsif ($cmd->[0] =~ m/lsblk/i) {
my $content = read_test_file('lsblk');
if ($content eq '') {
$content = '{}';
}
@$outputlines = split(/\n/, $content);
} else {
die "unexpected run_command call: '@$cmd', aborting\n";
}
} elsif ($cmd->[0] =~ m/pvs/i) {
# simulate lvs output
@$outputlines = split(/\n/, read_test_file('pvs'));
} elsif ($cmd->[0] =~ m/lvs/i) {
@$outputlines = split(/\n/, read_test_file('lvs'));
} elsif ($cmd->[0] =~ m/lsblk/i) {
my $content = read_test_file('lsblk');
if ($content eq '') {
$content = '{}';
}
@$outputlines = split(/\n/, $content);
} else {
die "unexpected run_command call: '@$cmd', aborting\n";
}
} else {
print "unexpected run_command call: '@$cmd', aborting\n";
die;
print "unexpected run_command call: '@$cmd', aborting\n";
die;
}
my $outfunc;
if ($param{outfunc}) {
$outfunc = $param{outfunc};
map { &$outfunc(($_)) } @$outputlines;
$outfunc = $param{outfunc};
map { &$outfunc(($_)) } @$outputlines;
return 0;
return 0;
}
}
@ -107,16 +107,16 @@ sub mocked_dir_glob_foreach {
my $lines = [];
# read lines in from file
if ($dir =~ m{^/sys/block$} ) {
@$lines = split(/\n/, read_test_file('disklist'));
if ($dir =~ m{^/sys/block$}) {
@$lines = split(/\n/, read_test_file('disklist'));
} elsif ($dir =~ m{^/sys/block/([^/]+)}) {
@$lines = split(/\n/, read_test_file('partlist'));
@$lines = split(/\n/, read_test_file('partlist'));
}
foreach my $line (@$lines) {
if ($line =~ m/$regex/) {
&$sub($line);
}
if ($line =~ m/$regex/) {
&$sub($line);
}
}
}
@ -125,8 +125,8 @@ sub mocked_parse_proc_mounts {
my $mounts = [];
foreach my $line(split(/\n/, $text)) {
push @$mounts, [split(/\s+/, $line)];
foreach my $line (split(/\n/, $text)) {
push @$mounts, [split(/\s+/, $line)];
}
return $mounts;
@ -135,83 +135,85 @@ sub mocked_parse_proc_mounts {
sub read_test_file {
my ($filename) = @_;
if (!-f "disk_tests/$testcasedir/$filename") {
print "file '$testcasedir/$filename' not found\n";
return '';
if (!-f "disk_tests/$testcasedir/$filename") {
print "file '$testcasedir/$filename' not found\n";
return '';
}
open (my $fh, '<', "disk_tests/$testcasedir/$filename")
or die "Cannot open disk_tests/$testcasedir/$filename: $!";
open(my $fh, '<', "disk_tests/$testcasedir/$filename")
or die "Cannot open disk_tests/$testcasedir/$filename: $!";
my $output = <$fh> // '';
chomp $output if $output;
while (my $line = <$fh>) {
chomp $line;
$output .= "\n$line";
chomp $line;
$output .= "\n$line";
}
return $output;
}
sub test_disk_list {
my ($testdir) = @_;
subtest "Test '$testdir'" => sub {
my $testcount = 0;
$testcasedir = $testdir;
my $testcount = 0;
$testcasedir = $testdir;
my $disks;
my $expected_disk_list;
eval {
$disks = PVE::Diskmanage::get_disks();
};
warn $@ if $@;
$expected_disk_list = decode_json(read_test_file('disklist_expected.json'));
my $disks;
my $expected_disk_list;
eval { $disks = PVE::Diskmanage::get_disks(); };
warn $@ if $@;
$expected_disk_list = decode_json(read_test_file('disklist_expected.json'));
print Dumper($disks) if $print;
$testcount++;
is_deeply($disks, $expected_disk_list, 'disk list should be the same');
print Dumper($disks) if $print;
$testcount++;
is_deeply($disks, $expected_disk_list, 'disk list should be the same');
foreach my $disk (sort keys %$disks) {
my $smart;
my $expected_smart;
eval {
$smart = PVE::Diskmanage::get_smart_data("/dev/$disk");
print Dumper($smart) if $print;
$expected_smart = decode_json(read_test_file("${disk}_smart_expected.json"));
};
foreach my $disk (sort keys %$disks) {
my $smart;
my $expected_smart;
eval {
$smart = PVE::Diskmanage::get_smart_data("/dev/$disk");
print Dumper($smart) if $print;
$expected_smart = decode_json(read_test_file("${disk}_smart_expected.json"));
};
if ($smart && $expected_smart) {
$testcount++;
is_deeply($smart, $expected_smart, "smart data for '$disk' should be the same");
} elsif ($smart && -f "disk_tests/$testcasedir/${disk}_smart_expected.json") {
$testcount++;
ok(0, "could not parse expected smart for '$disk'\n");
}
my $disk_tmp = {};
if ($smart && $expected_smart) {
$testcount++;
is_deeply($smart, $expected_smart, "smart data for '$disk' should be the same");
} elsif ($smart && -f "disk_tests/$testcasedir/${disk}_smart_expected.json") {
$testcount++;
ok(0, "could not parse expected smart for '$disk'\n");
}
my $disk_tmp = {};
# test single disk parameter
$disk_tmp = PVE::Diskmanage::get_disks($disk);
warn $@ if $@;
$testcount++;
print Dumper $disk_tmp if $print;
is_deeply($disk_tmp->{$disk}, $expected_disk_list->{$disk}, "disk $disk should be the same");
# test single disk parameter
$disk_tmp = PVE::Diskmanage::get_disks($disk);
warn $@ if $@;
$testcount++;
print Dumper $disk_tmp if $print;
is_deeply(
$disk_tmp->{$disk},
$expected_disk_list->{$disk},
"disk $disk should be the same",
);
# test wrong parameter
eval { PVE::Diskmanage::get_disks({ test => 1 }); };
my $err = $@;
$testcount++;
is_deeply(
$err,
"disks is not a string or array reference\n",
"error message should be the same",
);
# test wrong parameter
eval {
PVE::Diskmanage::get_disks( { test => 1 } );
};
my $err = $@;
$testcount++;
is_deeply($err, "disks is not a string or array reference\n", "error message should be the same");
}
# test multi disk parameter
$disks = PVE::Diskmanage::get_disks([keys %$disks]);
$testcount++;
is_deeply($disks, $expected_disk_list, 'disk list should be the same');
}
# test multi disk parameter
$disks = PVE::Diskmanage::get_disks( [ keys %$disks ] );
$testcount++;
is_deeply($disks, $expected_disk_list, 'disk list should be the same');
done_testing($testcount);
done_testing($testcount);
};
}
@ -235,24 +237,26 @@ $diskmanage_module->mock('is_iscsi' => \&mocked_is_iscsi);
print("\tMocked is_iscsi\n");
$diskmanage_module->mock('assert_blockdev' => sub { return 1; });
print("\tMocked assert_blockdev\n");
$diskmanage_module->mock('dir_is_empty' => sub {
# all partitions have a holder dir
my $val = shift;
if ($val =~ m|^/sys/block/.+/.+/|) {
return 0;
}
return 1;
});
$diskmanage_module->mock(
'dir_is_empty' => sub {
# all partitions have a holder dir
my $val = shift;
if ($val =~ m|^/sys/block/.+/.+/|) {
return 0;
}
return 1;
},
);
print("\tMocked dir_is_empty\n");
$diskmanage_module->mock('check_bin' => sub { return 1; });
print("\tMocked check_bin\n");
my $tools_module= Test::MockModule->new('PVE::ProcFSTools', no_auto => 1);
my $tools_module = Test::MockModule->new('PVE::ProcFSTools', no_auto => 1);
$tools_module->mock('parse_proc_mounts' => \&mocked_parse_proc_mounts);
print("\tMocked parse_proc_mounts\n");
print("Done Setting up Mocking\n\n");
print("Beginning Tests:\n\n");
opendir (my $dh, 'disk_tests')
opendir(my $dh, 'disk_tests')
or die "Cannot open disk_tests: $!";
while (readdir $dh) {

View File

@ -16,54 +16,44 @@ my $path = '/some/path';
# 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 => 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.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 => 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 => '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 => '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'
],
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',
],
},
];
@ -76,13 +66,11 @@ foreach my $tt (@$tests) {
my $scfg = { path => $path };
my $got;
eval {
$got = [ PVE::Storage::Plugin->filesystem_path($scfg, $volname, $snapname) ];
};
eval { $got = [PVE::Storage::Plugin->filesystem_path($scfg, $volname, $snapname)]; };
$got = $@ if $@;
is_deeply($got, $expected, "wantarray: filesystem_path for $volname")
|| diag(explain($got));
|| diag(explain($got));
}

View File

@ -17,21 +17,26 @@ my $vtype_subdirs = PVE::Storage::Plugin::get_vtype_subdirs();
# [2] => expected return from get_subdir
my $tests = [
# failed matches
[ $scfg_with_path, 'none', "unknown vtype 'none'\n" ],
[ {}, 'iso', "storage definition has no path\n" ],
[$scfg_with_path, 'none', "unknown vtype 'none'\n"],
[{}, 'iso', "storage definition 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 ];
push @$tests, [$scfg_with_path, $type, $path];
}
# creates additional tests for overrides
foreach my $type (keys %$vtype_subdirs) {
my $override = "${type}_override";
my $scfg_with_override = { path => '/some/path', 'content-dirs' => { $type => $override } };
push @$tests, [ $scfg_with_override, $type, "$scfg_with_override->{path}/$scfg_with_override->{'content-dirs'}->{$type}" ];
push @$tests,
[
$scfg_with_override,
$type,
"$scfg_with_override->{path}/$scfg_with_override->{'content-dirs'}->{$type}",
];
}
plan tests => scalar @$tests;
@ -43,7 +48,7 @@ foreach my $tt (@$tests) {
eval { $got = PVE::Storage::Plugin->get_subdir($scfg, $type) };
$got = $@ if $@;
is ($got, $expected, "get_subdir for $type") || diag(explain($got));
is($got, $expected, "get_subdir for $type") || diag(explain($got));
}
done_testing();

View File

@ -27,52 +27,52 @@ use constant DEFAULT_CTIME => 1234567890;
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,
}
}
'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',
'type' => 'dir',
'maxfiles' => 0,
'path' => $storage_dir,
'shared' => 0,
'content' => {
'iso' => 1,
'rootdir' => 1,
'vztmpl' => 1,
'images' => 1,
'snippets' => 1,
'backup' => 1,
'path' => $storage_dir,
'shared' => 0,
'content' => {
'iso' => 1,
'rootdir' => 1,
'vztmpl' => 1,
'images' => 1,
'snippets' => 1,
'backup' => 1,
},
};
@ -84,389 +84,387 @@ my $scfg = {
# (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/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst",
"$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' => 1585602700,
'format' => 'vma.gz',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz',
},
{
'content' => 'backup',
'ctime' => 1585602765,
'format' => 'vma.lzo',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo',
},
{
'content' => 'backup',
'ctime' => 1585602835,
'format' => 'vma',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma',
},
{
'content' => 'backup',
'ctime' => 1585602835,
'format' => 'vma.zst',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst',
},
{
'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: 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/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst",
"$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' => 1585602700,
'format' => 'vma.gz',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz',
},
{
'content' => 'backup',
'ctime' => 1585602765,
'format' => 'vma.lzo',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo',
},
{
'content' => 'backup',
'ctime' => 1585602835,
'format' => 'vma',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma',
},
{
'content' => 'backup',
'ctime' => 1585602835,
'format' => 'vma.zst',
'size' => DEFAULT_SIZE,
'subtype' => 'qemu',
'vmid' => '16110',
'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst',
},
{
'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: 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: 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: 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: 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, 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, 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, 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
},
);
# provide static vmlist for tests
my $mock_cluster = Test::MockModule->new('PVE::Cluster', no_auto => 1);
$mock_cluster->redefine(get_vmlist => sub { return $mocked_vmlist; });
@ -474,26 +472,31 @@ $mock_cluster->redefine(get_vmlist => sub { return $mocked_vmlist; });
# populate is File::stat's method to fill all information from CORE::stat into
# an blessed array.
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;
$mock_stat->redefine(
populate => sub {
my (@st) = @_;
$st[7] = DEFAULT_SIZE;
$st[10] = DEFAULT_CTIME;
my $result = $mock_stat->original('populate')->(@st);
my $result = $mock_stat->original('populate')->(@st);
return $result;
});
return $result;
},
);
# override info provided by qemu-img in file_size_info
my $mock_fsi = Test::MockModule->new('PVE::Storage::Plugin', no_auto => 1);
$mock_fsi->redefine(file_size_info => sub {
my ($size, $format, $used, $parent, $ctime) = $mock_fsi->original('file_size_info')->(@_);
$mock_fsi->redefine(
file_size_info => sub {
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;
});
return wantarray ? ($size, $format, $used, $parent, $ctime) : $size;
},
);
my $plan = scalar @tests;
plan tests => $plan + 1;
@ -507,54 +510,56 @@ plan tests => $plan + 1;
PVE::Storage::Plugin->list_volumes('sid', $scfg_with_type, undef, ['images']);
is_deeply ($tested_vmlist, $original_vmlist,
'PVE::Cluster::vmlist remains unmodified')
|| diag ("Expected vmlist to remain\n", explain($original_vmlist),
"but it turned to\n", explain($tested_vmlist));
is_deeply($tested_vmlist, $original_vmlist, 'PVE::Cluster::vmlist remains unmodified')
|| diag(
"Expected vmlist to remain\n",
explain($original_vmlist),
"but it turned to\n",
explain($tested_vmlist),
);
}
{
my $sid = 'local';
my $types = [ 'rootdir', 'images', 'vztmpl', 'iso', 'backup', 'snippets' ];
my @suffixes = ( 'qcow2', 'raw', 'vmdk', 'vhdx' );
my $types = ['rootdir', 'images', 'vztmpl', 'iso', 'backup', 'snippets'];
my @suffixes = ('qcow2', 'raw', 'vmdk', 'vhdx');
# run through test cases
foreach my $tt (@tests) {
my $vmid = $tt->{vmid};
my $files = $tt->{files};
my $expected = $tt->{expected};
my $description = $tt->{description};
my $parent = $tt->{parent};
my $vmid = $tt->{vmid};
my $files = $tt->{files};
my $expected = $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, @suffixes);
# prepare environment
my $num = 0; #parent disks
for my $file (@$files) {
my ($name, $dir, $suffix) = fileparse($file, @suffixes);
make_path($dir, { verbose => 1, mode => 0755 });
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++;
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]);
}
}
run_command([@cmd]);
}
}
my $got;
eval { $got = PVE::Storage::Plugin->list_volumes($sid, $scfg, $vmid, $types) };
$got = $@ if $@;
my $got;
eval { $got = PVE::Storage::Plugin->list_volumes($sid, $scfg, $vmid, $types) };
$got = $@ if $@;
is_deeply($got, $expected, $description) || diag(explain($got));
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 });
# clean up after each test case, otherwise
# we get wrong results from leftover files
remove_tree($storage_dir, { verbose => 1 });
}
}

View File

@ -19,251 +19,285 @@ 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', ],
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', undef, undef, undef, undef, 'raw'],
description => 'ISO image, iso',
volname => 'iso/some-installation-disk.iso',
expected => ['iso', 'some-installation-disk.iso', undef, undef, undef, undef, 'raw'],
},
{
description => 'ISO image, img',
volname => 'iso/some-other-installation-disk.img',
expected => ['iso', 'some-other-installation-disk.img', undef, undef, undef, undef, 'raw'],
description => 'ISO image, img',
volname => 'iso/some-other-installation-disk.img',
expected =>
['iso', 'some-other-installation-disk.img', undef, undef, undef, undef, 'raw'],
},
#
# 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', undef, undef, undef, undef, 'raw'],
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',
undef,
undef,
undef,
undef,
'raw',
],
},
{
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', undef, undef, undef, undef, 'raw'],
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',
undef,
undef,
undef,
undef,
'raw',
],
},
{
description => 'Container template tar.bz2',
volname => 'vztmpl/debian-10.0-standard_10.0-1_amd64.tar.bz2',
expected => ['vztmpl', 'debian-10.0-standard_10.0-1_amd64.tar.bz2', undef, undef, undef, undef, 'raw'],
description => 'Container template tar.bz2',
volname => 'vztmpl/debian-10.0-standard_10.0-1_amd64.tar.bz2',
expected => [
'vztmpl',
'debian-10.0-standard_10.0-1_amd64.tar.bz2',
undef,
undef,
undef,
undef,
'raw',
],
},
#
# container rootdir
#
{
description => 'Container rootdir, sub directory',
volname => "rootdir/$vmid",
expected => ['rootdir', "$vmid", "$vmid"],
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 => '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", undef, undef, undef, undef, 'raw'],
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",
undef,
undef,
undef,
undef,
'raw',
],
},
#
# Snippets
#
{
description => 'Snippets, yaml',
volname => 'snippets/userconfig.yaml',
expected => ['snippets', 'userconfig.yaml', undef, undef, undef, undef, 'raw'],
description => 'Snippets, yaml',
volname => 'snippets/userconfig.yaml',
expected => ['snippets', 'userconfig.yaml', undef, undef, undef, undef, 'raw'],
},
{
description => 'Snippets, perl',
volname => 'snippets/hookscript.pl',
expected => ['snippets', 'hookscript.pl', undef, undef, undef, undef, 'raw'],
description => 'Snippets, perl',
volname => 'snippets/hookscript.pl',
expected => ['snippets', 'hookscript.pl', undef, undef, undef, undef, 'raw'],
},
#
# Import
#
{
description => "Import, ova",
volname => 'import/import.ova',
expected => ['import', 'import.ova', undef, undef, undef ,undef, 'ova'],
description => "Import, ova",
volname => 'import/import.ova',
expected => ['import', 'import.ova', undef, undef, undef, undef, 'ova'],
},
{
description => "Import, ovf",
volname => 'import/import.ovf',
expected => ['import', 'import.ovf', undef, undef, undef ,undef, 'ovf'],
description => "Import, ovf",
volname => 'import/import.ovf',
expected => ['import', 'import.ovf', undef, undef, undef, undef, 'ovf'],
},
{
description => "Import, innner file of ova",
volname => 'import/import.ova/disk.qcow2',
expected => ['import', 'import.ova/disk.qcow2', undef, undef, undef, undef, 'ova+qcow2'],
description => "Import, innner file of ova",
volname => 'import/import.ova/disk.qcow2',
expected =>
['import', 'import.ova/disk.qcow2', undef, undef, undef, undef, 'ova+qcow2'],
},
{
description => "Import, innner file of ova",
volname => 'import/import.ova/disk.vmdk',
expected => ['import', 'import.ova/disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'],
description => "Import, innner file of ova",
volname => 'import/import.ova/disk.vmdk',
expected => ['import', 'import.ova/disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'],
},
{
description => "Import, innner file of ova with whitespace in name",
volname => 'import/import.ova/OS disk.vmdk',
expected => ['import', 'import.ova/OS disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'],
description => "Import, innner file of ova with whitespace in name",
volname => 'import/import.ova/OS disk.vmdk',
expected =>
['import', 'import.ova/OS disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'],
},
{
description => "Import, innner file of ova",
volname => 'import/import.ova/disk.raw',
expected => ['import', 'import.ova/disk.raw', undef, undef, undef, undef, 'ova+raw'],
description => "Import, innner file of ova",
volname => 'import/import.ova/disk.raw',
expected => ['import', 'import.ova/disk.raw', undef, undef, undef, undef, 'ova+raw'],
},
#
# failed matches
#
{
description => "Failed match: VM disk image, base, raw",
volname => "ssss/base-$vmid-disk-0.raw",
expected => "unable to parse directory volume name 'ssss/base-$vmid-disk-0.raw'\n",
description => "Failed match: VM disk image, base, raw",
volname => "ssss/base-$vmid-disk-0.raw",
expected => "unable to parse directory volume name 'ssss/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: 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, 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 rootdir, subvol',
volname => "rootdir/subvol-$vmid-disk-0",
expected => "unable to parse directory volume name 'rootdir/subvol-$vmid-disk-0'\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 parse volume filename 'base-$vmid-disk-0.vhdx'\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 parse volume filename 'base-$vmid-disk-0.vhdx'\n",
},
{
description => 'Failed match: VM disk image, linked, qcow2, first vmid',
volname => "ssss/base-$vmid-disk-0.qcow2/$vmid/vm-$vmid-disk-0.qcow2",
expected => "unable to parse directory volume name 'ssss/base-$vmid-disk-0.qcow2/$vmid/vm-$vmid-disk-0.qcow2'\n",
description => 'Failed match: VM disk image, linked, qcow2, first vmid',
volname => "ssss/base-$vmid-disk-0.qcow2/$vmid/vm-$vmid-disk-0.qcow2",
expected =>
"unable to parse directory volume name 'ssss/base-$vmid-disk-0.qcow2/$vmid/vm-$vmid-disk-0.qcow2'\n",
},
{
description => 'Failed match: VM disk image, linked, qcow2, second vmid',
volname => "$vmid/base-$vmid-disk-0.qcow2/ssss/vm-$vmid-disk-0.qcow2",
expected => "unable to parse volume filename 'base-$vmid-disk-0.qcow2/ssss/vm-$vmid-disk-0.qcow2'\n",
description => 'Failed match: VM disk image, linked, qcow2, second vmid',
volname => "$vmid/base-$vmid-disk-0.qcow2/ssss/vm-$vmid-disk-0.qcow2",
expected =>
"unable to parse volume filename 'base-$vmid-disk-0.qcow2/ssss/vm-$vmid-disk-0.qcow2'\n",
},
{
description => "Failed match: import dir but no ova/ovf/disk image",
volname => "import/test.foo",
expected => "unable to parse directory volume name 'import/test.foo'\n",
description => "Failed match: import dir but no ova/ovf/disk image",
volname => "import/test.foo",
expected => "unable to parse directory volume name 'import/test.foo'\n",
},
];
# create more test cases for VM disk images matches
my $disk_suffix = [ 'raw', 'qcow2', 'vmdk' ];
my $disk_suffix = ['raw', 'qcow2', 'vmdk'];
foreach my $s (@$disk_suffix) {
my @arr = (
{
description => "VM disk image, $s",
volname => "$vmid/vm-$vmid-disk-1.$s",
expected => [
'images',
"vm-$vmid-disk-1.$s",
"$vmid",
undef,
undef,
undef,
"$s",
],
},
{
description => "VM disk image, linked, $s",
volname => "$vmid/base-$vmid-disk-0.$s/$vmid/vm-$vmid-disk-0.$s",
expected => [
'images',
"vm-$vmid-disk-0.$s",
"$vmid",
"base-$vmid-disk-0.$s",
"$vmid",
undef,
"$s",
],
},
{
description => "VM disk image, base, $s",
volname => "$vmid/base-$vmid-disk-0.$s",
expected => [
'images',
"base-$vmid-disk-0.$s",
"$vmid",
undef,
undef,
'base-',
"$s"
],
},
{
description => "VM disk image, $s",
volname => "$vmid/vm-$vmid-disk-1.$s",
expected => [
'images', "vm-$vmid-disk-1.$s", "$vmid", undef, undef, undef, "$s",
],
},
{
description => "VM disk image, linked, $s",
volname => "$vmid/base-$vmid-disk-0.$s/$vmid/vm-$vmid-disk-0.$s",
expected => [
'images',
"vm-$vmid-disk-0.$s",
"$vmid",
"base-$vmid-disk-0.$s",
"$vmid",
undef,
"$s",
],
},
{
description => "VM disk image, base, $s",
volname => "$vmid/base-$vmid-disk-0.$s",
expected => [
'images', "base-$vmid-disk-0.$s", "$vmid", undef, undef, 'base-', "$s",
],
},
);
push @$tests, @arr;
}
# create more test cases for backup files matches
my $bkp_suffix = {
qemu => [ 'vma', 'vma.gz', 'vma.lzo', 'vma.zst' ],
lxc => [ 'tar', 'tgz', 'tar.gz', 'tar.lzo', 'tar.zst', 'tar.bz2' ],
openvz => [ 'tar', 'tgz', 'tar.gz', 'tar.lzo', 'tar.zst' ],
qemu => ['vma', 'vma.gz', 'vma.lzo', 'vma.zst'],
lxc => ['tar', 'tgz', 'tar.gz', 'tar.lzo', 'tar.zst', 'tar.bz2'],
openvz => ['tar', 'tgz', 'tar.gz', 'tar.lzo', 'tar.zst'],
};
foreach my $virt (keys %$bkp_suffix) {
my $suffix = $bkp_suffix->{$virt};
foreach my $s (@$suffix) {
my @arr = (
{
description => "Backup archive, $virt, $s",
volname => "backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s",
expected => [
'backup',
"vzdump-$virt-$vmid-2020_03_30-21_12_40.$s",
"$vmid",
undef,
undef,
undef,
'raw'
],
},
);
my @arr = (
{
description => "Backup archive, $virt, $s",
volname => "backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s",
expected => [
'backup',
"vzdump-$virt-$vmid-2020_03_30-21_12_40.$s",
"$vmid",
undef,
undef,
undef,
'raw',
],
},
);
push @$tests, @arr;
push @$tests, @arr;
}
}
# create more test cases for failed backup files matches
my $non_bkp_suffix = {
qemu => [ 'vms.gz', 'vma.xz' ],
lxc => [ 'zip.gz', 'tgz.lzo' ],
qemu => ['vms.gz', 'vma.xz'],
lxc => ['zip.gz', 'tgz.lzo'],
};
foreach my $virt (keys %$non_bkp_suffix) {
my $suffix = $non_bkp_suffix->{$virt};
foreach my $s (@$suffix) {
my @arr = (
{
description => "Failed match: Backup archive, $virt, $s",
volname => "backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s",
expected => "unable to parse directory volume name 'backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s'\n",
},
);
my @arr = (
{
description => "Failed match: Backup archive, $virt, $s",
volname => "backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s",
expected =>
"unable to parse directory volume name 'backup/vzdump-$virt-$vmid-2020_03_30-21_12_40.$s'\n",
},
);
push @$tests, @arr;
push @$tests, @arr;
}
}
#
# run through test case array
#
@ -278,12 +312,12 @@ foreach my $t (@$tests) {
my $expected = $t->{expected};
my $got;
eval { $got = [ PVE::Storage::Plugin->parse_volname($volname) ] };
eval { $got = [PVE::Storage::Plugin->parse_volname($volname)] };
$got = $@ if $@;
is_deeply($got, $expected, $description);
$seen_vtype->{@$expected[0]} = 1 if ref $expected eq 'ARRAY';
$seen_vtype->{ @$expected[0] } = 1 if ref $expected eq 'ARRAY';
}
# to check if all $vtype_subdirs are defined in path_to_volume_id

View File

@ -17,24 +17,24 @@ 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,
},
},
'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,
'local' => 1,
},
};
@ -44,219 +44,199 @@ my $scfg = {
# 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, 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, 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 => '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 => [
'backup',
'local:backup/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz',
],
description => 'Backup, vma.gz',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz",
expected => [
'backup', '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 => [
'backup',
'local:backup/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo',
],
description => 'Backup, vma.lzo',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo",
expected => [
'backup', '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 => [
'backup',
'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma',
],
description => 'Backup, vma',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma",
expected => [
'backup', '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 => [
'backup',
'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo',
],
description => 'Backup, tar.lzo',
volname => "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo",
expected => [
'backup', 'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo',
],
},
{
description => 'Backup, vma.zst',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst",
expected => [
'backup',
'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst'
],
description => 'Backup, vma.zst',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst",
expected => [
'backup', 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma.zst',
],
},
{
description => 'Backup, tar.zst',
volname => "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.zst",
expected => [
'backup',
'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.zst'
],
description => 'Backup, tar.zst',
volname => "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.zst",
expected => [
'backup', 'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.zst',
],
},
{
description => 'Backup, tar.bz2',
volname => "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2",
expected => [
'backup',
'local:backup/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2',
],
description => 'Backup, tar.bz2',
volname => "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2",
expected => [
'backup', 'local:backup/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2',
],
},
{
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 => '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 => '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 => 'CT template, wrong ending, tar bz2',
volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.bz2",
expected => [
'vztmpl',
'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.bz2',
],
description => 'CT template, wrong ending, tar bz2',
volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.bz2",
expected => [
'vztmpl', 'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.bz2',
],
},
{
description => 'Rootdir',
volname => "$storage_dir/private/1234/", # fileparse needs / at the end
expected => [
'rootdir',
'local:rootdir/1234',
],
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'
],
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',
],
},
{
description => 'Snippets, yaml',
volname => "$storage_dir/snippets/userconfig.yaml",
expected => [
'snippets',
'local:snippets/userconfig.yaml',
],
description => 'Snippets, yaml',
volname => "$storage_dir/snippets/userconfig.yaml",
expected => [
'snippets', 'local:snippets/userconfig.yaml',
],
},
{
description => 'Snippets, hookscript',
volname => "$storage_dir/snippets/hookscript.pl",
expected => [
'snippets',
'local:snippets/hookscript.pl',
],
description => 'Snippets, hookscript',
volname => "$storage_dir/snippets/hookscript.pl",
expected => [
'snippets', 'local:snippets/hookscript.pl',
],
},
{
description => 'CT template, tar.xz',
volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.xz",
expected => [
'vztmpl',
'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.xz',
],
description => 'CT template, tar.xz',
volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.xz",
expected => [
'vztmpl', 'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.xz',
],
},
{
description => 'Import, ova',
volname => "$storage_dir/import/import.ova",
expected => [
'import',
'local:import/import.ova',
],
description => 'Import, ova',
volname => "$storage_dir/import/import.ova",
expected => [
'import', 'local:import/import.ova',
],
},
{
description => 'Import, ovf',
volname => "$storage_dir/import/import.ovf",
expected => [
'import',
'local:import/import.ovf',
],
description => 'Import, ovf',
volname => "$storage_dir/import/import.ovf",
expected => [
'import', 'local:import/import.ovf',
],
},
# no matches, path or files with failures
{
description => 'Base template, string as vmid in folder name',
volname => "$storage_dir/images/ssss/base-4321-disk-0.raw",
expected => [''],
description => 'Base template, string as vmid in folder name',
volname => "$storage_dir/images/ssss/base-4321-disk-0.raw",
expected => [''],
},
{
description => 'ISO file, wrong ending',
volname => "$storage_dir/template/iso/yet-again-a-installation-disk.dvd",
expected => [''],
description => 'ISO file, wrong ending',
volname => "$storage_dir/template/iso/yet-again-a-installation-disk.dvd",
expected => [''],
},
{
description => 'CT template, wrong ending, zip.gz',
volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.zip.gz",
expected => [''],
description => 'CT template, wrong ending, zip.gz',
volname => "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.zip.gz",
expected => [''],
},
{
description => 'Rootdir as subvol, wrong path',
volname => "$storage_dir/private/subvol-19254-disk-0/",
expected => [''],
description => 'Rootdir as subvol, wrong path',
volname => "$storage_dir/private/subvol-19254-disk-0/",
expected => [''],
},
{
description => 'Backup, wrong format, openvz, zip.gz',
volname => "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.zip.gz",
expected => [''],
description => 'Backup, wrong format, openvz, zip.gz',
volname => "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.zip.gz",
expected => [''],
},
{
description => 'Backup, wrong format, openvz, tgz.lzo',
volname => "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tgz.lzo",
expected => [''],
description => 'Backup, wrong format, openvz, tgz.lzo',
volname => "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tgz.lzo",
expected => [''],
},
{
description => 'Backup, wrong ending, qemu, vma.xz',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vma.xz",
expected => [''],
description => 'Backup, wrong ending, qemu, vma.xz',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vma.xz",
expected => [''],
},
{
description => 'Backup, wrong format, qemu, vms.gz',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vms.gz",
expected => [''],
description => 'Backup, wrong format, qemu, vms.gz',
volname => "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vms.gz",
expected => [''],
},
{
description => 'Image, string as vmid in folder name',
volname => "$storage_dir/images/ssss/vm-1234-disk-0.qcow2",
expected => [''],
description => 'Image, string as vmid in folder name',
volname => "$storage_dir/images/ssss/vm-1234-disk-0.qcow2",
expected => [''],
},
{
description => 'Import, non ova/ovf/disk image in import dir',
volname => "$storage_dir/import/test.foo",
expected => [''],
description => 'Import, non ova/ovf/disk image in import dir',
volname => "$storage_dir/import/test.foo",
expected => [''],
},
);
@ -275,19 +255,19 @@ foreach my $tt (@tests) {
make_path($dir, { verbose => 1, mode => 0755 });
if ($name) {
open(my $fh, ">>", "$file") || die "Error open file: $!";
close($fh);
open(my $fh, ">>", "$file") || die "Error open file: $!";
close($fh);
}
# run tests
my $got;
eval { $got = [ PVE::Storage::path_to_volume_id($scfg, $file) ] };
eval { $got = [PVE::Storage::path_to_volume_id($scfg, $file)] };
$got = $@ if $@;
is_deeply($got, $expected, $description) || diag(explain($got));
$seen_vtype->{@$expected[0]} = 1
if ( @$expected[0] ne '' && scalar @$expected > 1);
$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

View File

@ -18,183 +18,193 @@ my $mocked_backups_lists = {};
my $basetime = 1577881101; # 2020_01_01-12_18_21 UTC
foreach my $vmid (@vmids) {
push @{$mocked_backups_lists->{default}}, (
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2018_05_26-11_18_21.tar.zst",
'ctime' => $basetime - 585*24*60*60 - 60*60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_21.tar.zst",
'ctime' => $basetime - 24*60*60 - 60*60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_51.tar.zst",
'ctime' => $basetime - 24*60*60 - 60*60 + 30,
'vmid' => $vmid,
'protected' => 1,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_19_21.tar.zst",
'ctime' => $basetime - 24*60*60 - 60*60 + 60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-11_18_21.tar.zst",
'ctime' => $basetime - 60*60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-lxc-$vmid-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-$vmid-renamed.tar.zst",
'ctime' => 1234,
'vmid' => $vmid,
},
);
push @{ $mocked_backups_lists->{default} },
(
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2018_05_26-11_18_21.tar.zst",
'ctime' => $basetime - 585 * 24 * 60 * 60 - 60 * 60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_21.tar.zst",
'ctime' => $basetime - 24 * 60 * 60 - 60 * 60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_51.tar.zst",
'ctime' => $basetime - 24 * 60 * 60 - 60 * 60 + 30,
'vmid' => $vmid,
'protected' => 1,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_19_21.tar.zst",
'ctime' => $basetime - 24 * 60 * 60 - 60 * 60 + 60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-11_18_21.tar.zst",
'ctime' => $basetime - 60 * 60,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-lxc-$vmid-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-$vmid-renamed.tar.zst",
'ctime' => 1234,
'vmid' => $vmid,
},
);
}
push @{$mocked_backups_lists->{year1970}}, (
{
'volid' => "$storeid:backup/vzdump-lxc-321-1970_01_01-00_01_23.tar.zst",
'ctime' => 83,
'vmid' => 321,
},
{
'volid' => "$storeid:backup/vzdump-lxc-321-2070_01_01-00_01_00.tar.zst",
'ctime' => 60*60*24 * (365*100 + 25) + 60,
'vmid' => 321,
},
);
push @{$mocked_backups_lists->{novmid}}, (
{
'volid' => "$storeid:backup/vzdump-lxc-novmid.tar.gz",
'ctime' => 1234,
},
);
push @{$mocked_backups_lists->{threeway}}, (
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_25-12_18_21.tar.zst",
'ctime' => $basetime - 7*24*60*60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_31-12_18_21.tar.zst",
'ctime' => $basetime - 24*60*60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'vmid' => 7654,
},
);
push @{$mocked_backups_lists->{weekboundary}}, (
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_03-12_18_21.tar.zst",
'ctime' => $basetime + (366-31+2)*24*60*60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_04-12_18_21.tar.zst",
'ctime' => $basetime + (366-31+3)*24*60*60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_07-12_18_21.tar.zst",
'ctime' => $basetime + (366-31+6)*24*60*60,
'vmid' => 7654,
},
);
push @{ $mocked_backups_lists->{year1970} },
(
{
'volid' => "$storeid:backup/vzdump-lxc-321-1970_01_01-00_01_23.tar.zst",
'ctime' => 83,
'vmid' => 321,
},
{
'volid' => "$storeid:backup/vzdump-lxc-321-2070_01_01-00_01_00.tar.zst",
'ctime' => 60 * 60 * 24 * (365 * 100 + 25) + 60,
'vmid' => 321,
},
);
push @{ $mocked_backups_lists->{novmid} },
(
{
'volid' => "$storeid:backup/vzdump-lxc-novmid.tar.gz",
'ctime' => 1234,
},
);
push @{ $mocked_backups_lists->{threeway} },
(
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_25-12_18_21.tar.zst",
'ctime' => $basetime - 7 * 24 * 60 * 60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_31-12_18_21.tar.zst",
'ctime' => $basetime - 24 * 60 * 60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'vmid' => 7654,
},
);
push @{ $mocked_backups_lists->{weekboundary} },
(
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_03-12_18_21.tar.zst",
'ctime' => $basetime + (366 - 31 + 2) * 24 * 60 * 60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_04-12_18_21.tar.zst",
'ctime' => $basetime + (366 - 31 + 3) * 24 * 60 * 60,
'vmid' => 7654,
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_07-12_18_21.tar.zst",
'ctime' => $basetime + (366 - 31 + 6) * 24 * 60 * 60,
'vmid' => 7654,
},
);
my $current_list;
my $mock_plugin = Test::MockModule->new('PVE::Storage::Plugin');
$mock_plugin->redefine(list_volumes => sub {
my ($class, $storeid, $scfg, $vmid, $content_types) = @_;
$mock_plugin->redefine(
list_volumes => sub {
my ($class, $storeid, $scfg, $vmid, $content_types) = @_;
my $list = $mocked_backups_lists->{$current_list};
my $list = $mocked_backups_lists->{$current_list};
return $list if !defined($vmid);
return $list if !defined($vmid);
return [ grep { $_->{vmid} eq $vmid } @{$list} ];
});
return [grep { $_->{vmid} eq $vmid } @{$list}];
},
);
sub generate_expected {
my ($vmids, $type, $marks) = @_;
my @expected;
foreach my $vmid (@{$vmids}) {
push @expected, (
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2018_05_26-11_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 585*24*60*60 - 60*60,
'mark' => $marks->[0],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 24*60*60 - 60*60,
'mark' => $marks->[1],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_51.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 24*60*60 - 60*60 + 30,
'mark' => 'protected',
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_19_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 24*60*60 - 60*60 + 60,
'mark' => $marks->[2],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-11_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 60*60,
'mark' => $marks->[3],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-12_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime,
'mark' => $marks->[4],
'vmid' => $vmid,
},
) if !defined($type) || $type eq 'qemu';
push @expected, (
{
'volid' => "$storeid:backup/vzdump-lxc-$vmid-2020_01_01-12_18_21.tar.zst",
'type' => 'lxc',
'ctime' => $basetime,
'mark' => $marks->[5],
'vmid' => $vmid,
},
) if !defined($type) || $type eq 'lxc';
push @expected, (
{
'volid' => "$storeid:backup/vzdump-$vmid-renamed.tar.zst",
'type' => 'unknown',
'ctime' => 1234,
'mark' => 'renamed',
'vmid' => $vmid,
},
) if !defined($type);
push @expected,
(
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2018_05_26-11_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 585 * 24 * 60 * 60 - 60 * 60,
'mark' => $marks->[0],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 24 * 60 * 60 - 60 * 60,
'mark' => $marks->[1],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_51.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 24 * 60 * 60 - 60 * 60 + 30,
'mark' => 'protected',
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_19_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 24 * 60 * 60 - 60 * 60 + 60,
'mark' => $marks->[2],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-11_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime - 60 * 60,
'mark' => $marks->[3],
'vmid' => $vmid,
},
{
'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-12_18_21.tar.zst",
'type' => 'qemu',
'ctime' => $basetime,
'mark' => $marks->[4],
'vmid' => $vmid,
},
) if !defined($type) || $type eq 'qemu';
push @expected,
(
{
'volid' => "$storeid:backup/vzdump-lxc-$vmid-2020_01_01-12_18_21.tar.zst",
'type' => 'lxc',
'ctime' => $basetime,
'mark' => $marks->[5],
'vmid' => $vmid,
},
) if !defined($type) || $type eq 'lxc';
push @expected,
(
{
'volid' => "$storeid:backup/vzdump-$vmid-renamed.tar.zst",
'type' => 'unknown',
'ctime' => 1234,
'mark' => 'renamed',
'vmid' => $vmid,
},
) if !defined($type);
}
return [ sort { $a->{volid} cmp $b->{volid} } @expected ];
return [sort { $a->{volid} cmp $b->{volid} } @expected];
}
# an array of test cases, each test is comprised of the following keys:
@ -208,268 +218,312 @@ sub generate_expected {
# most of them are created further below
my $tests = [
{
description => 'last=3, multiple IDs',
keep => {
'keep-last' => 3,
},
expected => generate_expected(\@vmids, undef, ['remove', 'remove', 'keep', 'keep', 'keep', 'keep']),
description => 'last=3, multiple IDs',
keep => {
'keep-last' => 3,
},
expected =>
generate_expected(\@vmids, undef, ['remove', 'remove', 'keep', 'keep', 'keep', 'keep']),
},
{
description => 'weekly=2, one ID',
vmid => $vmids[0],
keep => {
'keep-weekly' => 2,
},
expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'remove', 'remove', 'keep', 'keep']),
description => 'weekly=2, one ID',
vmid => $vmids[0],
keep => {
'keep-weekly' => 2,
},
expected => generate_expected(
[$vmids[0]],
undef,
['keep', 'remove', 'remove', 'remove', 'keep', 'keep'],
),
},
{
description => 'daily=weekly=monthly=1, multiple IDs',
keep => {
'keep-hourly' => 0,
'keep-daily' => 1,
'keep-weekly' => 1,
'keep-monthly' => 1,
},
expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
description => 'daily=weekly=monthly=1, multiple IDs',
keep => {
'keep-hourly' => 0,
'keep-daily' => 1,
'keep-weekly' => 1,
'keep-monthly' => 1,
},
expected =>
generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
},
{
description => 'hourly=4, one ID',
vmid => $vmids[0],
keep => {
'keep-hourly' => 4,
'keep-daily' => 0,
},
expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'keep', 'keep', 'keep', 'keep']),
description => 'hourly=4, one ID',
vmid => $vmids[0],
keep => {
'keep-hourly' => 4,
'keep-daily' => 0,
},
expected => generate_expected(
[$vmids[0]],
undef,
['keep', 'remove', 'keep', 'keep', 'keep', 'keep'],
),
},
{
description => 'yearly=2, multiple IDs',
keep => {
'keep-hourly' => 0,
'keep-daily' => 0,
'keep-weekly' => 0,
'keep-monthly' => 0,
'keep-yearly' => 2,
},
expected => generate_expected(\@vmids, undef, ['remove', 'remove', 'keep', 'remove', 'keep', 'keep']),
description => 'yearly=2, multiple IDs',
keep => {
'keep-hourly' => 0,
'keep-daily' => 0,
'keep-weekly' => 0,
'keep-monthly' => 0,
'keep-yearly' => 2,
},
expected => generate_expected(
\@vmids,
undef,
['remove', 'remove', 'keep', 'remove', 'keep', 'keep'],
),
},
{
description => 'last=2,hourly=2 one ID',
vmid => $vmids[0],
keep => {
'keep-last' => 2,
'keep-hourly' => 2,
},
expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'keep', 'keep', 'keep', 'keep']),
description => 'last=2,hourly=2 one ID',
vmid => $vmids[0],
keep => {
'keep-last' => 2,
'keep-hourly' => 2,
},
expected => generate_expected(
[$vmids[0]],
undef,
['keep', 'remove', 'keep', 'keep', 'keep', 'keep'],
),
},
{
description => 'last=1,monthly=2, multiple IDs',
keep => {
'keep-last' => 1,
'keep-monthly' => 2,
},
expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
description => 'last=1,monthly=2, multiple IDs',
keep => {
'keep-last' => 1,
'keep-monthly' => 2,
},
expected =>
generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
},
{
description => 'monthly=3, one ID',
vmid => $vmids[0],
keep => {
'keep-monthly' => 3,
},
expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
description => 'monthly=3, one ID',
vmid => $vmids[0],
keep => {
'keep-monthly' => 3,
},
expected => generate_expected(
[$vmids[0]],
undef,
['keep', 'remove', 'keep', 'remove', 'keep', 'keep'],
),
},
{
description => 'last=daily=weekly=1, multiple IDs',
keep => {
'keep-last' => 1,
'keep-daily' => 1,
'keep-weekly' => 1,
},
expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
description => 'last=daily=weekly=1, multiple IDs',
keep => {
'keep-last' => 1,
'keep-daily' => 1,
'keep-weekly' => 1,
},
expected =>
generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
},
{
description => 'last=daily=weekly=1, others zero, multiple IDs',
keep => {
'keep-hourly' => 0,
'keep-last' => 1,
'keep-daily' => 1,
'keep-weekly' => 1,
'keep-monthly' => 0,
'keep-yearly' => 0,
},
expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
description => 'last=daily=weekly=1, others zero, multiple IDs',
keep => {
'keep-hourly' => 0,
'keep-last' => 1,
'keep-daily' => 1,
'keep-weekly' => 1,
'keep-monthly' => 0,
'keep-yearly' => 0,
},
expected =>
generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
},
{
description => 'daily=2, one ID',
vmid => $vmids[0],
keep => {
'keep-daily' => 2,
},
expected => generate_expected([$vmids[0]], undef, ['remove', 'remove', 'keep', 'remove', 'keep', 'keep']),
description => 'daily=2, one ID',
vmid => $vmids[0],
keep => {
'keep-daily' => 2,
},
expected => generate_expected(
[$vmids[0]],
undef,
['remove', 'remove', 'keep', 'remove', 'keep', 'keep'],
),
},
{
description => 'weekly=monthly=1, multiple IDs',
keep => {
'keep-weekly' => 1,
'keep-monthly' => 1,
},
expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'remove', 'remove', 'keep', 'keep']),
description => 'weekly=monthly=1, multiple IDs',
keep => {
'keep-weekly' => 1,
'keep-monthly' => 1,
},
expected => generate_expected(
\@vmids,
undef,
['keep', 'remove', 'remove', 'remove', 'keep', 'keep'],
),
},
{
description => 'weekly=yearly=1, one ID',
vmid => $vmids[0],
keep => {
'keep-weekly' => 1,
'keep-yearly' => 1,
},
expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'remove', 'remove', 'keep', 'keep']),
description => 'weekly=yearly=1, one ID',
vmid => $vmids[0],
keep => {
'keep-weekly' => 1,
'keep-yearly' => 1,
},
expected => generate_expected(
[$vmids[0]],
undef,
['keep', 'remove', 'remove', 'remove', 'keep', 'keep'],
),
},
{
description => 'weekly=yearly=1, one ID, type qemu',
vmid => $vmids[0],
type => 'qemu',
keep => {
'keep-weekly' => 1,
'keep-yearly' => 1,
},
expected => generate_expected([$vmids[0]], 'qemu', ['keep', 'remove', 'remove', 'remove', 'keep', '']),
description => 'weekly=yearly=1, one ID, type qemu',
vmid => $vmids[0],
type => 'qemu',
keep => {
'keep-weekly' => 1,
'keep-yearly' => 1,
},
expected => generate_expected(
[$vmids[0]],
'qemu',
['keep', 'remove', 'remove', 'remove', 'keep', ''],
),
},
{
description => 'week=yearly=1, one ID, type lxc',
vmid => $vmids[0],
type => 'lxc',
keep => {
'keep-last' => 1,
},
expected => generate_expected([$vmids[0]], 'lxc', ['', '', '', '', '', 'keep']),
description => 'week=yearly=1, one ID, type lxc',
vmid => $vmids[0],
type => 'lxc',
keep => {
'keep-last' => 1,
},
expected => generate_expected([$vmids[0]], 'lxc', ['', '', '', '', '', 'keep']),
},
{
description => 'yearly=1, year before 2000',
keep => {
'keep-yearly' => 1,
},
list => 'year1970',
expected => [
{
'volid' => "$storeid:backup/vzdump-lxc-321-1970_01_01-00_01_23.tar.zst",
'ctime' => 83,
'mark' => 'remove',
'type' => 'lxc',
'vmid' => 321,
},
{
'volid' => "$storeid:backup/vzdump-lxc-321-2070_01_01-00_01_00.tar.zst",
'ctime' => 60*60*24 * (365*100 + 25) + 60,
'mark' => 'keep',
'type' => 'lxc',
'vmid' => 321,
},
],
description => 'yearly=1, year before 2000',
keep => {
'keep-yearly' => 1,
},
list => 'year1970',
expected => [
{
'volid' => "$storeid:backup/vzdump-lxc-321-1970_01_01-00_01_23.tar.zst",
'ctime' => 83,
'mark' => 'remove',
'type' => 'lxc',
'vmid' => 321,
},
{
'volid' => "$storeid:backup/vzdump-lxc-321-2070_01_01-00_01_00.tar.zst",
'ctime' => 60 * 60 * 24 * (365 * 100 + 25) + 60,
'mark' => 'keep',
'type' => 'lxc',
'vmid' => 321,
},
],
},
{
description => 'last=1, ne ID, year before 2000',
keep => {
'keep-last' => 1,
},
list => 'novmid',
expected => [
{
'volid' => "$storeid:backup/vzdump-lxc-novmid.tar.gz",
'ctime' => 1234,
'mark' => 'renamed',
'type' => 'lxc',
},
],
description => 'last=1, ne ID, year before 2000',
keep => {
'keep-last' => 1,
},
list => 'novmid',
expected => [
{
'volid' => "$storeid:backup/vzdump-lxc-novmid.tar.gz",
'ctime' => 1234,
'mark' => 'renamed',
'type' => 'lxc',
},
],
},
{
description => 'all missing, multiple IDs',
keep => {},
expected => generate_expected(\@vmids, undef, ['keep', 'keep', 'keep', 'keep', 'keep', 'keep']),
description => 'all missing, multiple IDs',
keep => {},
expected =>
generate_expected(\@vmids, undef, ['keep', 'keep', 'keep', 'keep', 'keep', 'keep']),
},
{
description => 'all zero, multiple IDs',
keep => {
'keep-last' => 0,
'keep-hourly' => 0,
'keep-daily' => 0,
'keep-weekly' => 0,
'keep-monthyl' => 0,
'keep-yearly' => 0,
},
expected => generate_expected(\@vmids, undef, ['keep', 'keep', 'keep', 'keep', 'keep', 'keep']),
description => 'all zero, multiple IDs',
keep => {
'keep-last' => 0,
'keep-hourly' => 0,
'keep-daily' => 0,
'keep-weekly' => 0,
'keep-monthyl' => 0,
'keep-yearly' => 0,
},
expected =>
generate_expected(\@vmids, undef, ['keep', 'keep', 'keep', 'keep', 'keep', 'keep']),
},
{
description => 'some zero, some missing, multiple IDs',
keep => {
'keep-last' => 0,
'keep-hourly' => 0,
'keep-daily' => 0,
'keep-monthyl' => 0,
'keep-yearly' => 0,
},
expected => generate_expected(\@vmids, undef, ['keep', 'keep', 'keep', 'keep', 'keep', 'keep']),
description => 'some zero, some missing, multiple IDs',
keep => {
'keep-last' => 0,
'keep-hourly' => 0,
'keep-daily' => 0,
'keep-monthyl' => 0,
'keep-yearly' => 0,
},
expected =>
generate_expected(\@vmids, undef, ['keep', 'keep', 'keep', 'keep', 'keep', 'keep']),
},
{
description => 'daily=weekly=monthly=1',
keep => {
'keep-daily' => 1,
'keep-weekly' => 1,
'keep-monthly' => 1,
},
list => 'threeway',
expected => [
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_25-12_18_21.tar.zst",
'ctime' => $basetime - 7*24*60*60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_31-12_18_21.tar.zst",
'ctime' => $basetime - 24*60*60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'remove', # month is already covered by the backup kept by keep-weekly!
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
],
description => 'daily=weekly=monthly=1',
keep => {
'keep-daily' => 1,
'keep-weekly' => 1,
'keep-monthly' => 1,
},
list => 'threeway',
expected => [
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_25-12_18_21.tar.zst",
'ctime' => $basetime - 7 * 24 * 60 * 60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2019_12_31-12_18_21.tar.zst",
'ctime' => $basetime - 24 * 60 * 60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'remove', # month is already covered by the backup kept by keep-weekly!
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_01_01-12_18_21.tar.zst",
'ctime' => $basetime,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
],
},
{
description => 'daily=weekly=1,weekboundary',
keep => {
'keep-daily' => 1,
'keep-weekly' => 1,
},
list => 'weekboundary',
expected => [
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_03-12_18_21.tar.zst",
'ctime' => $basetime + (366-31+2)*24*60*60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'remove',
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_04-12_18_21.tar.zst",
'ctime' => $basetime + (366-31+3)*24*60*60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_07-12_18_21.tar.zst",
'ctime' => $basetime + (366-31+6)*24*60*60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
],
description => 'daily=weekly=1,weekboundary',
keep => {
'keep-daily' => 1,
'keep-weekly' => 1,
},
list => 'weekboundary',
expected => [
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_03-12_18_21.tar.zst",
'ctime' => $basetime + (366 - 31 + 2) * 24 * 60 * 60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'remove',
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_04-12_18_21.tar.zst",
'ctime' => $basetime + (366 - 31 + 3) * 24 * 60 * 60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
{
'volid' => "$storeid:backup/vzdump-qemu-7654-2020_12_07-12_18_21.tar.zst",
'ctime' => $basetime + (366 - 31 + 6) * 24 * 60 * 60,
'type' => 'qemu',
'vmid' => 7654,
'mark' => 'keep',
},
],
},
];
@ -478,9 +532,11 @@ plan tests => scalar @$tests;
for my $tt (@$tests) {
my $got = eval {
$current_list = $tt->{list} // 'default';
my $res = PVE::Storage::Plugin->prune_backups($tt->{scfg}, $storeid, $tt->{keep}, $tt->{vmid}, $tt->{type}, 1);
return [ sort { $a->{volid} cmp $b->{volid} } @{$res} ];
$current_list = $tt->{list} // 'default';
my $res = PVE::Storage::Plugin->prune_backups(
$tt->{scfg}, $storeid, $tt->{keep}, $tt->{vmid}, $tt->{type}, 1,
);
return [sort { $a->{volid} cmp $b->{volid} } @{$res}];
};
$got = $@ if $@;

View File

@ -26,7 +26,7 @@ use JSON;
use PVE::Tools qw(run_command);
my $pool = "testpool";
my $use_existing= undef;
my $use_existing = undef;
my $namespace = "testspace";
my $showhelp = '';
my $vmid = 999999;
@ -46,7 +46,7 @@ Known options are:
-h, --help Print this help message
";
GetOptions (
GetOptions(
"pool=s" => \$pool,
"use-existing" => \$use_existing,
"namespace=s" => \$namespace,
@ -54,7 +54,7 @@ GetOptions (
"h|help" => \$showhelp,
"cleanup" => \$cleanup,
"d|debug" => \$DEBUG,
) or die ($helpstring);
) or die($helpstring);
if ($showhelp) {
warn $helpstring;
@ -69,6 +69,7 @@ my $vmid_linked_clone = int($vmid) - 2;
sub jp {
print to_json($_[0], { utf8 => 8, pretty => 1, canonical => 1 }) . "\n";
}
sub dbgvar {
jp(@_) if $DEBUG;
}
@ -77,26 +78,24 @@ sub run_cmd {
my ($cmd, $json, $ignore_errors) = @_;
my $raw = '';
my $parser = sub {$raw .= shift;};
my $parser = sub { $raw .= shift; };
eval {
run_command($cmd, outfunc => $parser);
};
eval { run_command($cmd, outfunc => $parser); };
if (my $err = $@) {
die $err if !$ignore_errors;
die $err if !$ignore_errors;
}
if ($json) {
my $result;
if ($raw eq '') {
$result = [];
} elsif ($raw =~ m/^(\[.*\])$/s) { # untaint
$result = JSON::decode_json($1);
} else {
die "got unexpected data from command: '$cmd' -> '$raw'\n";
}
return $result;
}
my $result;
if ($raw eq '') {
$result = [];
} elsif ($raw =~ m/^(\[.*\])$/s) { # untaint
$result = JSON::decode_json($1);
} else {
die "got unexpected data from command: '$cmd' -> '$raw'\n";
}
return $result;
}
return $raw;
}
@ -105,17 +104,15 @@ sub run_test_cmd {
my $raw = '';
my $out = sub {
my $line = shift;
$raw .= "${line}\n";
my $line = shift;
$raw .= "${line}\n";
};
eval {
run_command($cmd, outfunc => $out);
};
eval { run_command($cmd, outfunc => $out); };
if (my $err = $@) {
print $raw;
print $err;
return 0;
print $raw;
print $err;
return 0;
}
print $raw;
return 1;
@ -126,23 +123,23 @@ sub prepare {
my $pools = run_cmd("ceph osd pool ls --format json", 1);
my %poolnames = map {$_ => 1} @$pools;
my %poolnames = map { $_ => 1 } @$pools;
die "Pool '$pool' does not exist!\n"
if !exists($poolnames{$pool}) && $use_existing;
if !exists($poolnames{$pool}) && $use_existing;
run_cmd(['pveceph', 'pool', 'create', ${pool}, '--add_storages', 1])
if !$use_existing;
if !$use_existing;
my $namespaces = run_cmd(['rbd', '-p', ${pool}, 'namespace', 'ls', '--format', 'json'], 1);
dbgvar($namespace);
my $ns_found = 0;
for my $i (@$namespaces) {
$ns_found = 1 if $i->{name} eq $namespace;
$ns_found = 1 if $i->{name} eq $namespace;
}
if (!$ns_found) {
print "Create namespace '${namespace}' in pool '${pool}'\n";
run_cmd(['rbd', 'namespace', 'create', "${pool}/${namespace}"]);
print "Create namespace '${namespace}' in pool '${pool}'\n";
run_cmd(['rbd', 'namespace', 'create', "${pool}/${namespace}"]);
}
my $storages = run_cmd(['pvesh', 'get', 'storage', '--output-format', 'json'], 1);
@ -152,41 +149,67 @@ sub prepare {
print "Create storage definition\n";
for my $stor (@$storages) {
$pool_found = 1 if $stor->{storage} eq $pool;
$rbd_found = 1 if $stor->{storage} eq $storage_name;
$pool_found = 1 if $stor->{storage} eq $pool;
$rbd_found = 1 if $stor->{storage} eq $storage_name;
if ($rbd_found) {
run_cmd(['pvesm', 'set', ${storage_name}, '--krbd', '0']);
die "Enable the storage '$stor->{storage}'!" if $stor->{disable};
}
if ($rbd_found) {
run_cmd(['pvesm', 'set', ${storage_name}, '--krbd', '0']);
die "Enable the storage '$stor->{storage}'!" if $stor->{disable};
}
}
if (!$pool_found) {
die "No storage for pool '${pool}' found! Must have same name as pool!\n"
if $use_existing;
die "No storage for pool '${pool}' found! Must have same name as pool!\n"
if $use_existing;
run_cmd(['pvesm', 'add', 'rbd', $pool, '--pool', $pool, '--content', 'images,rootdir']);
run_cmd(['pvesm', 'add', 'rbd', $pool, '--pool', $pool, '--content', 'images,rootdir']);
}
# create PVE storages (librbd / krbd)
run_cmd(['pvesm', 'add', 'rbd', ${storage_name}, '--krbd', '0', '--pool', ${pool}, '--namespace', ${namespace}, '--content', 'images,rootdir'])
if !$rbd_found;
run_cmd(
[
'pvesm',
'add',
'rbd',
${storage_name},
'--krbd',
'0',
'--pool',
${pool},
'--namespace',
${namespace},
'--content',
'images,rootdir',
],
) if !$rbd_found;
# create test VM
print "Create test VM ${vmid}\n";
my $vms = run_cmd(['pvesh', 'get', 'cluster/resources', '--type', 'vm', '--output-format', 'json'], 1);
my $vms =
run_cmd(['pvesh', 'get', 'cluster/resources', '--type', 'vm', '--output-format', 'json'],
1);
for my $vm (@$vms) {
# TODO: introduce a force flag to make this behaviour configurable
# TODO: introduce a force flag to make this behaviour configurable
if ($vm->{vmid} eq $vmid) {
print "Test VM '${vmid}' already exists. It will be removed and recreated!\n";
run_cmd(['qm', 'stop', ${vmid}], 0, 1);
run_cmd(['qm', 'destroy', ${vmid}]);
}
if ($vm->{vmid} eq $vmid) {
print "Test VM '${vmid}' already exists. It will be removed and recreated!\n";
run_cmd(['qm', 'stop', ${vmid}], 0, 1);
run_cmd(['qm', 'destroy', ${vmid}]);
}
}
run_cmd(['qm', 'create', ${vmid}, '--bios', 'ovmf', '--efidisk0', "${storage_name}:1", '--scsi0', "${storage_name}:2"]);
run_cmd(
[
'qm',
'create',
${vmid},
'--bios',
'ovmf',
'--efidisk0',
"${storage_name}:1",
'--scsi0',
"${storage_name}:2",
],
);
}
sub cleanup {
print "Cleaning up test environment!\n";
print "Removing VMs\n";
@ -195,7 +218,21 @@ sub cleanup {
run_cmd(['qm', 'stop', ${vmid_clone}], 0, 1);
run_cmd(['qm', 'destroy', ${vmid_linked_clone}], 0, 1);
run_cmd(['qm', 'destroy', ${vmid_clone}], 0, 1);
run_cmd(['for', 'i', 'in', "/dev/rbd/${pool}/${namespace}/*;", 'do', '/usr/bin/rbd', 'unmap', '\$i;', 'done'], 0, 1);
run_cmd(
[
'for',
'i',
'in',
"/dev/rbd/${pool}/${namespace}/*;",
'do',
'/usr/bin/rbd',
'unmap',
'\$i;',
'done',
],
0,
1,
);
run_cmd(['qm', 'unlock', ${vmid}], 0, 1);
run_cmd(['qm', 'destroy', ${vmid}], 0, 1);
@ -206,10 +243,10 @@ sub cleanup {
run_cmd(['rbd', 'namespace', 'remove', "${pool}/${namespace}"], 0, 1);
if (!$use_existing) {
print "Removing Storage definition for ${pool}\n";
run_cmd(['pvesm', 'remove', ${pool}], 0, 1);
print "Removing test pool\n";
run_cmd(['pveceph', 'pool', 'destroy', $pool]);
print "Removing Storage definition for ${pool}\n";
run_cmd(['pvesm', 'remove', ${pool}], 0, 1);
print "Removing test pool\n";
run_cmd(['pveceph', 'pool', 'destroy', $pool]);
}
}
@ -229,102 +266,96 @@ my $tests = [
# ],
# },
{
name => 'first VM start',
steps => [
['qm', 'start', $vmid],
],
name => 'first VM start',
steps => [
['qm', 'start', $vmid],
],
},
{
name => 'snapshot/rollback',
steps => [
['qm', 'snapshot', $vmid, 'test'],
['qm', 'rollback', $vmid, 'test'],
],
cleanup => [
['qm', 'unlock', $vmid],
],
name => 'snapshot/rollback',
steps => [
['qm', 'snapshot', $vmid, 'test'], ['qm', 'rollback', $vmid, 'test'],
],
cleanup => [
['qm', 'unlock', $vmid],
],
},
{
name => 'remove snapshot',
steps => [
['qm', 'delsnapshot', $vmid, 'test'],
],
name => 'remove snapshot',
steps => [
['qm', 'delsnapshot', $vmid, 'test'],
],
},
{
name => 'moving disk between namespaces',
steps => [
['qm', 'move_disk', $vmid, 'scsi0', $pool, '--delete', 1],
['qm', 'move_disk', $vmid, 'scsi0', $storage_name, '--delete', 1],
],
name => 'moving disk between namespaces',
steps => [
['qm', 'move_disk', $vmid, 'scsi0', $pool, '--delete', 1],
['qm', 'move_disk', $vmid, 'scsi0', $storage_name, '--delete', 1],
],
},
{
name => 'switch to krbd',
preparations => [
['qm', 'stop', $vmid],
['pvesm', 'set', $storage_name, '--krbd', 1]
],
name => 'switch to krbd',
preparations => [
['qm', 'stop', $vmid], ['pvesm', 'set', $storage_name, '--krbd', 1],
],
},
{
name => 'start VM with krbd',
steps => [
['qm', 'start', $vmid],
],
name => 'start VM with krbd',
steps => [
['qm', 'start', $vmid],
],
},
{
name => 'snapshot/rollback with krbd',
steps => [
['qm', 'snapshot', $vmid, 'test'],
['qm', 'rollback', $vmid, 'test'],
],
cleanup => [
['qm', 'unlock', $vmid],
],
name => 'snapshot/rollback with krbd',
steps => [
['qm', 'snapshot', $vmid, 'test'], ['qm', 'rollback', $vmid, 'test'],
],
cleanup => [
['qm', 'unlock', $vmid],
],
},
{
name => 'remove snapshot with krbd',
steps => [
['qm', 'delsnapshot', $vmid, 'test'],
],
name => 'remove snapshot with krbd',
steps => [
['qm', 'delsnapshot', $vmid, 'test'],
],
},
{
name => 'moving disk between namespaces with krbd',
steps => [
['qm', 'move_disk', $vmid, 'scsi0', $pool, '--delete', 1],
['qm', 'move_disk', $vmid, 'scsi0', $storage_name, '--delete', 1],
],
name => 'moving disk between namespaces with krbd',
steps => [
['qm', 'move_disk', $vmid, 'scsi0', $pool, '--delete', 1],
['qm', 'move_disk', $vmid, 'scsi0', $storage_name, '--delete', 1],
],
},
{
name => 'clone VM with krbd',
steps => [
['qm', 'clone', $vmid, $vmid_clone],
],
name => 'clone VM with krbd',
steps => [
['qm', 'clone', $vmid, $vmid_clone],
],
},
{
name => 'switch to non krbd',
preparations => [
['qm', 'stop', $vmid],
['qm', 'stop', $vmid_clone],
['pvesm', 'set', $storage_name, '--krbd', 0]
],
name => 'switch to non krbd',
preparations => [
['qm', 'stop', $vmid],
['qm', 'stop', $vmid_clone],
['pvesm', 'set', $storage_name, '--krbd', 0],
],
},
{
name => 'templates and linked clone',
steps => [
['qm', 'template', $vmid],
['qm', 'clone', $vmid, $vmid_linked_clone],
['qm', 'start', $vmid_linked_clone],
['qm', 'stop', $vmid_linked_clone],
],
name => 'templates and linked clone',
steps => [
['qm', 'template', $vmid],
['qm', 'clone', $vmid, $vmid_linked_clone],
['qm', 'start', $vmid_linked_clone],
['qm', 'stop', $vmid_linked_clone],
],
},
{
name => 'start linked clone with krbd',
preparations => [
['pvesm', 'set', $storage_name, '--krbd', 1]
],
steps => [
['qm', 'start', $vmid_linked_clone],
['qm', 'stop', $vmid_linked_clone],
],
name => 'start linked clone with krbd',
preparations => [['pvesm', 'set', $storage_name, '--krbd', 1]],
steps => [
['qm', 'start', $vmid_linked_clone], ['qm', 'stop', $vmid_linked_clone],
],
},
];
@ -332,8 +363,8 @@ sub run_prep_cleanup {
my ($cmds) = @_;
for (@$cmds) {
print join(' ', @$_). "\n";
run_cmd($_);
print join(' ', @$_) . "\n";
run_cmd($_);
}
}
@ -341,7 +372,7 @@ sub run_steps {
my ($steps) = @_;
for (@$steps) {
ok(run_test_cmd($_), join(' ', @$_));
ok(run_test_cmd($_), join(' ', @$_));
}
}
@ -350,23 +381,23 @@ sub run_tests {
my $num_tests = 0;
for (@$tests) {
$num_tests += scalar(@{$_->{steps}}) if defined $_->{steps};
$num_tests += scalar(@{ $_->{steps} }) if defined $_->{steps};
}
print("Tests: $num_tests\n");
plan tests => $num_tests;
for my $test (@$tests) {
print "Section: $test->{name}\n";
run_prep_cleanup($test->{preparations}) if defined $test->{preparations};
run_steps($test->{steps}) if defined $test->{steps};
run_prep_cleanup($test->{cleanup}) if defined $test->{cleanup};
print "Section: $test->{name}\n";
run_prep_cleanup($test->{preparations}) if defined $test->{preparations};
run_steps($test->{steps}) if defined $test->{steps};
run_prep_cleanup($test->{cleanup}) if defined $test->{cleanup};
}
done_testing();
if (Test::More->builder->is_passing()) {
cleanup();
cleanup();
}
}

View File

@ -51,23 +51,23 @@ EOF
my $permissions = {
'user1@test' => {},
'user2@test' => { '/' => ['Sys.Modify'], },
'user3@test' => { '/storage' => ['Datastore.Allocate'], },
'user4@test' => { '/storage/d20m40r30' => ['Datastore.Allocate'], },
'user2@test' => { '/' => ['Sys.Modify'] },
'user3@test' => { '/storage' => ['Datastore.Allocate'] },
'user4@test' => { '/storage/d20m40r30' => ['Datastore.Allocate'] },
};
my $pve_cluster_module;
$pve_cluster_module = Test::MockModule->new('PVE::Cluster');
$pve_cluster_module->mock(
cfs_update => sub {},
cfs_update => sub { },
get_config => sub {
my ($file) = @_;
if ($file eq 'datacenter.cfg') {
return $datacenter_cfg;
} elsif ($file eq 'storage.cfg') {
return $storage_cfg;
}
die "TODO: mock get_config($file)\n";
my ($file) = @_;
if ($file eq 'datacenter.cfg') {
return $datacenter_cfg;
} elsif ($file eq 'storage.cfg') {
return $storage_cfg;
}
die "TODO: mock get_config($file)\n";
},
);
@ -75,136 +75,360 @@ my $rpcenv_module;
$rpcenv_module = Test::MockModule->new('PVE::RPCEnvironment');
$rpcenv_module->mock(
check => sub {
my ($env, $user, $path, $perms, $noerr) = @_;
return 1 if $user eq 'root@pam';
my $userperms = $permissions->{$user}
or die "no permissions defined for user $user\n";
if (defined(my $pathperms = $userperms->{$path})) {
foreach my $pp (@$pathperms) {
foreach my $reqp (@$perms) {
return 1 if $pp eq $reqp;
}
}
}
die "permission denied\n" if !$noerr;
return 0;
my ($env, $user, $path, $perms, $noerr) = @_;
return 1 if $user eq 'root@pam';
my $userperms = $permissions->{$user}
or die "no permissions defined for user $user\n";
if (defined(my $pathperms = $userperms->{$path})) {
foreach my $pp (@$pathperms) {
foreach my $reqp (@$perms) {
return 1 if $pp eq $reqp;
}
}
}
die "permission denied\n" if !$noerr;
return 0;
},
);
my $rpcenv = PVE::RPCEnvironment->init('pub');
my @tests = (
[ user => 'root@pam' ],
[ ['unknown', ['nolimit'], undef], 100, 'root / generic default limit, requesting default' ],
[ ['move', ['nolimit'], undef], 80, 'root / specific default limit, requesting default (move)' ],
[ ['restore', ['nolimit'], undef], 60, 'root / specific default limit, requesting default (restore)' ],
[ ['unknown', ['d50m40r30'], undef], 50, 'root / storage default limit' ],
[ ['move', ['d50m40r30'], undef], 40, 'root / specific storage limit (move)' ],
[ ['restore', ['d50m40r30'], undef], 30, 'root / specific storage limit (restore)' ],
[ ['unknown', ['nolimit'], 0], 0, 'root / generic default limit' ],
[ ['move', ['nolimit'], 0], 0, 'root / specific default limit (move)' ],
[ ['restore', ['nolimit'], 0], 0, 'root / specific default limit (restore)' ],
[ ['unknown', ['d50m40r30'], 0], 0, 'root / storage default limit' ],
[ ['move', ['d50m40r30'], 0], 0, 'root / specific storage limit (move)' ],
[ ['restore', ['d50m40r30'], 0], 0, 'root / specific storage limit (restore)' ],
[ ['migrate', undef, 100], 100, 'root / undef storage (migrate)' ],
[ ['migrate', [], 100], 100, 'root / no storage (migrate)' ],
[ ['migrate', [undef], undef], 100, 'root / [undef] storage no override (migrate)' ],
[ ['migrate', [undef, undef], 200], 200, 'root / list of undef storages with override (migrate)' ],
[user => 'root@pam'],
[['unknown', ['nolimit'], undef], 100, 'root / generic default limit, requesting default'],
[
['move', ['nolimit'], undef],
80,
'root / specific default limit, requesting default (move)',
],
[
['restore', ['nolimit'], undef],
60,
'root / specific default limit, requesting default (restore)',
],
[['unknown', ['d50m40r30'], undef], 50, 'root / storage default limit'],
[['move', ['d50m40r30'], undef], 40, 'root / specific storage limit (move)'],
[['restore', ['d50m40r30'], undef], 30, 'root / specific storage limit (restore)'],
[['unknown', ['nolimit'], 0], 0, 'root / generic default limit'],
[['move', ['nolimit'], 0], 0, 'root / specific default limit (move)'],
[['restore', ['nolimit'], 0], 0, 'root / specific default limit (restore)'],
[['unknown', ['d50m40r30'], 0], 0, 'root / storage default limit'],
[['move', ['d50m40r30'], 0], 0, 'root / specific storage limit (move)'],
[['restore', ['d50m40r30'], 0], 0, 'root / specific storage limit (restore)'],
[['migrate', undef, 100], 100, 'root / undef storage (migrate)'],
[['migrate', [], 100], 100, 'root / no storage (migrate)'],
[['migrate', [undef], undef], 100, 'root / [undef] storage no override (migrate)'],
[
['migrate', [undef, undef], 200],
200,
'root / list of undef storages with override (migrate)',
],
[ user => 'user1@test' ],
[ ['unknown', ['nolimit'], undef], 100, 'generic default limit' ],
[ ['move', ['nolimit'], undef], 80, 'specific default limit (move)' ],
[ ['restore', ['nolimit'], undef], 60, 'specific default limit (restore)' ],
[ ['unknown', ['d50m40r30'], undef], 50, 'storage default limit' ],
[ ['move', ['d50m40r30'], undef], 40, 'specific storage limit (move)' ],
[ ['restore', ['d50m40r30'], undef], 30, 'specific storage limit (restore)' ],
[ ['unknown', ['d200m400r300'], undef], 200, 'storage default limit above datacenter limits' ],
[ ['move', ['d200m400r300'], undef], 400, 'specific storage limit above datacenter limits (move)' ],
[ ['restore', ['d200m400r300'], undef], 300, 'specific storage limit above datacenter limits (restore)' ],
[ ['unknown', ['d50'], undef], 50, 'storage default limit' ],
[ ['move', ['d50'], undef], 50, 'storage default limit (move)' ],
[ ['restore', ['d50'], undef], 50, 'storage default limit (restore)' ],
[user => 'user1@test'],
[['unknown', ['nolimit'], undef], 100, 'generic default limit'],
[['move', ['nolimit'], undef], 80, 'specific default limit (move)'],
[['restore', ['nolimit'], undef], 60, 'specific default limit (restore)'],
[['unknown', ['d50m40r30'], undef], 50, 'storage default limit'],
[['move', ['d50m40r30'], undef], 40, 'specific storage limit (move)'],
[['restore', ['d50m40r30'], undef], 30, 'specific storage limit (restore)'],
[
['unknown', ['d200m400r300'], undef],
200,
'storage default limit above datacenter limits',
],
[
['move', ['d200m400r300'], undef],
400,
'specific storage limit above datacenter limits (move)',
],
[
['restore', ['d200m400r300'], undef],
300,
'specific storage limit above datacenter limits (restore)',
],
[['unknown', ['d50'], undef], 50, 'storage default limit'],
[['move', ['d50'], undef], 50, 'storage default limit (move)'],
[['restore', ['d50'], undef], 50, 'storage default limit (restore)'],
[ user => 'user2@test' ],
[ ['unknown', ['nolimit'], 0], 0, 'generic default limit with Sys.Modify, passing unlimited' ],
[ ['unknown', ['nolimit'], undef], 100, 'generic default limit with Sys.Modify' ],
[ ['move', ['nolimit'], undef], 80, 'specific default limit with Sys.Modify (move)' ],
[ ['restore', ['nolimit'], undef], 60, 'specific default limit with Sys.Modify (restore)' ],
[ ['restore', ['nolimit'], 0], 0, 'specific default limit with Sys.Modify, passing unlimited (restore)' ],
[ ['move', ['nolimit'], 0], 0, 'specific default limit with Sys.Modify, passing unlimited (move)' ],
[ ['unknown', ['d50m40r30'], undef], 50, 'storage default limit with Sys.Modify' ],
[ ['restore', ['d50m40r30'], undef], 30, 'specific storage limit with Sys.Modify (restore)' ],
[ ['move', ['d50m40r30'], undef], 40, 'specific storage limit with Sys.Modify (move)' ],
[user => 'user2@test'],
[
['unknown', ['nolimit'], 0],
0,
'generic default limit with Sys.Modify, passing unlimited',
],
[['unknown', ['nolimit'], undef], 100, 'generic default limit with Sys.Modify'],
[['move', ['nolimit'], undef], 80, 'specific default limit with Sys.Modify (move)'],
[['restore', ['nolimit'], undef], 60, 'specific default limit with Sys.Modify (restore)'],
[
['restore', ['nolimit'], 0],
0,
'specific default limit with Sys.Modify, passing unlimited (restore)',
],
[
['move', ['nolimit'], 0],
0,
'specific default limit with Sys.Modify, passing unlimited (move)',
],
[['unknown', ['d50m40r30'], undef], 50, 'storage default limit with Sys.Modify'],
[['restore', ['d50m40r30'], undef], 30, 'specific storage limit with Sys.Modify (restore)'],
[['move', ['d50m40r30'], undef], 40, 'specific storage limit with Sys.Modify (move)'],
[ user => 'user3@test' ],
[ ['unknown', ['nolimit'], undef], 100, 'generic default limit with privileges on /' ],
[ ['unknown', ['nolimit'], 80], 80, 'generic default limit with privileges on /, passing an override value' ],
[ ['unknown', ['nolimit'], 0], 0, 'generic default limit with privileges on /, passing unlimited' ],
[ ['move', ['nolimit'], undef], 80, 'specific default limit with privileges on / (move)' ],
[ ['move', ['nolimit'], 0], 0, 'specific default limit with privileges on /, passing unlimited (move)' ],
[ ['restore', ['nolimit'], undef], 60, 'specific default limit with privileges on / (restore)' ],
[ ['restore', ['nolimit'], 0], 0, 'specific default limit with privileges on /, passing unlimited (restore)' ],
[ ['unknown', ['d50m40r30'], 0], 0, 'storage default limit with privileges on /, passing unlimited' ],
[ ['unknown', ['d50m40r30'], undef], 50, 'storage default limit with privileges on /' ],
[ ['unknown', ['d50m40r30'], 0], 0, 'storage default limit with privileges on, passing unlimited /' ],
[ ['move', ['d50m40r30'], undef], 40, 'specific storage limit with privileges on / (move)' ],
[ ['move', ['d50m40r30'], 0], 0, 'specific storage limit with privileges on, passing unlimited / (move)' ],
[ ['restore', ['d50m40r30'], undef], 30, 'specific storage limit with privileges on / (restore)' ],
[ ['restore', ['d50m40r30'], 0], 0, 'specific storage limit with privileges on /, passing unlimited (restore)' ],
[user => 'user3@test'],
[['unknown', ['nolimit'], undef], 100, 'generic default limit with privileges on /'],
[
['unknown', ['nolimit'], 80],
80,
'generic default limit with privileges on /, passing an override value',
],
[
['unknown', ['nolimit'], 0],
0,
'generic default limit with privileges on /, passing unlimited',
],
[['move', ['nolimit'], undef], 80, 'specific default limit with privileges on / (move)'],
[
['move', ['nolimit'], 0],
0,
'specific default limit with privileges on /, passing unlimited (move)',
],
[
['restore', ['nolimit'], undef],
60,
'specific default limit with privileges on / (restore)',
],
[
['restore', ['nolimit'], 0],
0,
'specific default limit with privileges on /, passing unlimited (restore)',
],
[
['unknown', ['d50m40r30'], 0],
0,
'storage default limit with privileges on /, passing unlimited',
],
[['unknown', ['d50m40r30'], undef], 50, 'storage default limit with privileges on /'],
[
['unknown', ['d50m40r30'], 0],
0,
'storage default limit with privileges on, passing unlimited /',
],
[['move', ['d50m40r30'], undef], 40, 'specific storage limit with privileges on / (move)'],
[
['move', ['d50m40r30'], 0],
0,
'specific storage limit with privileges on, passing unlimited / (move)',
],
[
['restore', ['d50m40r30'], undef],
30,
'specific storage limit with privileges on / (restore)',
],
[
['restore', ['d50m40r30'], 0],
0,
'specific storage limit with privileges on /, passing unlimited (restore)',
],
[ user => 'user4@test' ],
[ ['unknown', ['nolimit'], 10], 10, 'generic default limit with privileges on a different storage, passing lower override' ],
[ ['unknown', ['nolimit'], undef], 100, 'generic default limit with privileges on a different storage' ],
[ ['unknown', ['nolimit'], 0], 100, 'generic default limit with privileges on a different storage, passing unlimited' ],
[ ['move', ['nolimit'], undef], 80, 'specific default limit with privileges on a different storage (move)' ],
[ ['restore', ['nolimit'], undef], 60, 'specific default limit with privileges on a different storage (restore)' ],
[ ['unknown', ['d50m40r30'], undef], 50, 'storage default limit with privileges on a different storage' ],
[ ['move', ['d50m40r30'], undef], 40, 'specific storage limit with privileges on a different storage (move)' ],
[ ['restore', ['d50m40r30'], undef], 30, 'specific storage limit with privileges on a different storage (restore)' ],
[ ['unknown', ['d20m40r30'], undef], 20, 'storage default limit with privileges on that storage' ],
[ ['unknown', ['d20m40r30'], 0], 0, 'storage default limit with privileges on that storage, passing unlimited' ],
[ ['move', ['d20m40r30'], undef], 40, 'specific storage limit with privileges on that storage (move)' ],
[ ['move', ['d20m40r30'], 0], 0, 'specific storage limit with privileges on that storage, passing unlimited (move)' ],
[ ['move', ['d20m40r30'], 10], 10, 'specific storage limit with privileges on that storage, passing low override (move)' ],
[ ['move', ['d20m40r30'], 300], 300, 'specific storage limit with privileges on that storage, passing high override (move)' ],
[ ['restore', ['d20m40r30'], undef], 30, 'specific storage limit with privileges on that storage (restore)' ],
[ ['restore', ['d20m40r30'], 0], 0, 'specific storage limit with privileges on that storage, passing unlimited (restore)' ],
[ ['unknown', ['d50m40r30', 'd20m40r30'], 0], 50, 'multiple storages default limit with privileges on one of them, passing unlimited' ],
[ ['move', ['d50m40r30', 'd20m40r30'], 0], 40, 'multiple storages specific limit with privileges on one of them, passing unlimited (move)' ],
[ ['restore', ['d50m40r30', 'd20m40r30'], 0], 30, 'multiple storages specific limit with privileges on one of them, passing unlimited (restore)' ],
[ ['unknown', ['d50m40r30', 'd20m40r30'], undef], 20, 'multiple storages default limit with privileges on one of them' ],
[ ['unknown', ['d10', 'd20m40r30'], undef], 10, 'multiple storages default limit with privileges on one of them (storage limited)' ],
[ ['move', ['d10', 'd20m40r30'], undef], 10, 'multiple storages specific limit with privileges on one of them (storage limited) (move)' ],
[ ['restore', ['d10', 'd20m40r30'], undef], 10, 'multiple storages specific limit with privileges on one of them (storage limited) (restore)' ],
[ ['restore', ['d10', 'd20m40r30'], 5], 5, 'multiple storages specific limit (storage limited) (restore), passing lower override' ],
[ ['restore', ['d200', 'd200m400r300'], 65], 65, 'multiple storages specific limit (storage limited) (restore), passing lower override' ],
[ ['restore', ['d200', 'd200m400r300'], 400], 200, 'multiple storages specific limit (storage limited) (restore), passing higher override' ],
[ ['restore', ['d200', 'd200m400r300'], 0], 200, 'multiple storages specific limit (storage limited) (restore), passing unlimited' ],
[ ['restore', ['d200', 'd200m400r300'], 1], 1, 'multiple storages specific limit (storage limited) (restore), passing 1' ],
[ ['restore', ['d10', 'd20m40r30'], 500], 10, 'multiple storages specific limit with privileges on one of them (storage limited) (restore), passing higher override' ],
[ ['unknown', ['nolimit', 'd20m40r30'], 0], 100, 'multiple storages default limit with privileges on one of them, passing unlimited (default limited)' ],
[ ['move', ['nolimit', 'd20m40r30'], 0], 80, 'multiple storages specific limit with privileges on one of them, passing unlimited (default limited) (move)' ],
[ ['restore', ['nolimit', 'd20m40r30'], 0], 60, 'multiple storages specific limit with privileges on one of them, passing unlimited (default limited) (restore)' ],
[ ['unknown', ['nolimit', 'd20m40r30'], undef], 20, 'multiple storages default limit with privileges on one of them (default limited)' ],
[ ['move', ['nolimit', 'd20m40r30'], undef], 40, 'multiple storages specific limit with privileges on one of them (default limited) (move)' ],
[ ['restore', ['nolimit', 'd20m40r30'], undef], 30, 'multiple storages specific limit with privileges on one of them (default limited) (restore)' ],
[ ['restore', ['d20m40r30', 'm50'], 200], 60, 'multiple storages specific limit with privileges on one of them (global default limited) (restore)' ],
[ ['move', ['nolimit', undef ], 40] , 40, 'multiple storages one undefined, passing 40 (move)' ],
[ ['move', undef, 100] , 80, 'undef storage, passing 100 (move)' ],
[ ['move', [undef], 100] , 80, '[undef] storage, passing 100 (move)' ],
[ ['move', [undef], undef] , 80, '[undef] storage, no override (move)' ],
[user => 'user4@test'],
[
['unknown', ['nolimit'], 10],
10,
'generic default limit with privileges on a different storage, passing lower override',
],
[
['unknown', ['nolimit'], undef],
100,
'generic default limit with privileges on a different storage',
],
[
['unknown', ['nolimit'], 0],
100,
'generic default limit with privileges on a different storage, passing unlimited',
],
[
['move', ['nolimit'], undef],
80,
'specific default limit with privileges on a different storage (move)',
],
[
['restore', ['nolimit'], undef],
60,
'specific default limit with privileges on a different storage (restore)',
],
[
['unknown', ['d50m40r30'], undef],
50,
'storage default limit with privileges on a different storage',
],
[
['move', ['d50m40r30'], undef],
40,
'specific storage limit with privileges on a different storage (move)',
],
[
['restore', ['d50m40r30'], undef],
30,
'specific storage limit with privileges on a different storage (restore)',
],
[
['unknown', ['d20m40r30'], undef],
20,
'storage default limit with privileges on that storage',
],
[
['unknown', ['d20m40r30'], 0],
0,
'storage default limit with privileges on that storage, passing unlimited',
],
[
['move', ['d20m40r30'], undef],
40,
'specific storage limit with privileges on that storage (move)',
],
[
['move', ['d20m40r30'], 0],
0,
'specific storage limit with privileges on that storage, passing unlimited (move)',
],
[
['move', ['d20m40r30'], 10],
10,
'specific storage limit with privileges on that storage, passing low override (move)',
],
[
['move', ['d20m40r30'], 300],
300,
'specific storage limit with privileges on that storage, passing high override (move)',
],
[
['restore', ['d20m40r30'], undef],
30,
'specific storage limit with privileges on that storage (restore)',
],
[
['restore', ['d20m40r30'], 0],
0,
'specific storage limit with privileges on that storage, passing unlimited (restore)',
],
[
['unknown', ['d50m40r30', 'd20m40r30'], 0],
50,
'multiple storages default limit with privileges on one of them, passing unlimited',
],
[
['move', ['d50m40r30', 'd20m40r30'], 0],
40,
'multiple storages specific limit with privileges on one of them, passing unlimited (move)',
],
[
['restore', ['d50m40r30', 'd20m40r30'], 0],
30,
'multiple storages specific limit with privileges on one of them, passing unlimited (restore)',
],
[
['unknown', ['d50m40r30', 'd20m40r30'], undef],
20,
'multiple storages default limit with privileges on one of them',
],
[
['unknown', ['d10', 'd20m40r30'], undef],
10,
'multiple storages default limit with privileges on one of them (storage limited)',
],
[
['move', ['d10', 'd20m40r30'], undef],
10,
'multiple storages specific limit with privileges on one of them (storage limited) (move)',
],
[
['restore', ['d10', 'd20m40r30'], undef],
10,
'multiple storages specific limit with privileges on one of them (storage limited) (restore)',
],
[
['restore', ['d10', 'd20m40r30'], 5],
5,
'multiple storages specific limit (storage limited) (restore), passing lower override',
],
[
['restore', ['d200', 'd200m400r300'], 65],
65,
'multiple storages specific limit (storage limited) (restore), passing lower override',
],
[
['restore', ['d200', 'd200m400r300'], 400],
200,
'multiple storages specific limit (storage limited) (restore), passing higher override',
],
[
['restore', ['d200', 'd200m400r300'], 0],
200,
'multiple storages specific limit (storage limited) (restore), passing unlimited',
],
[
['restore', ['d200', 'd200m400r300'], 1],
1,
'multiple storages specific limit (storage limited) (restore), passing 1',
],
[
['restore', ['d10', 'd20m40r30'], 500],
10,
'multiple storages specific limit with privileges on one of them (storage limited) (restore), passing higher override',
],
[
['unknown', ['nolimit', 'd20m40r30'], 0],
100,
'multiple storages default limit with privileges on one of them, passing unlimited (default limited)',
],
[
['move', ['nolimit', 'd20m40r30'], 0],
80,
'multiple storages specific limit with privileges on one of them, passing unlimited (default limited) (move)',
],
[
['restore', ['nolimit', 'd20m40r30'], 0],
60,
'multiple storages specific limit with privileges on one of them, passing unlimited (default limited) (restore)',
],
[
['unknown', ['nolimit', 'd20m40r30'], undef],
20,
'multiple storages default limit with privileges on one of them (default limited)',
],
[
['move', ['nolimit', 'd20m40r30'], undef],
40,
'multiple storages specific limit with privileges on one of them (default limited) (move)',
],
[
['restore', ['nolimit', 'd20m40r30'], undef],
30,
'multiple storages specific limit with privileges on one of them (default limited) (restore)',
],
[
['restore', ['d20m40r30', 'm50'], 200],
60,
'multiple storages specific limit with privileges on one of them (global default limited) (restore)',
],
[
['move', ['nolimit', undef], 40],
40,
'multiple storages one undefined, passing 40 (move)',
],
[['move', undef, 100], 80, 'undef storage, passing 100 (move)'],
[['move', [undef], 100], 80, '[undef] storage, passing 100 (move)'],
[['move', [undef], undef], 80, '[undef] storage, no override (move)'],
);
foreach my $t (@tests) {
my ($args, $expected, $description) = @$t;
if (!ref($args)) {
if ($args eq 'user') {
$rpcenv->set_user($expected);
} else {
die "not a test specification\n";
}
next;
if ($args eq 'user') {
$rpcenv->set_user($expected);
} else {
die "not a test specification\n";
}
next;
}
is(PVE::Storage::get_bandwidth_limit(@$args), $expected, $description);
}

View File

@ -5,8 +5,8 @@ use warnings;
use TAP::Harness;
my $harness = TAP::Harness->new( { verbosity => -2 });
my $res = $harness->runtests( "disklist_test.pm" );
my $harness = TAP::Harness->new({ verbosity => -2 });
my $res = $harness->runtests("disklist_test.pm");
exit -1 if !$res || $res->{failed} || $res->{parse_errors};

View File

@ -10,11 +10,12 @@ use Test::More;
use Data::Dumper;
my $test_manifests = join ('/', $Bin, 'ovf_manifests');
my $test_manifests = join('/', $Bin, 'ovf_manifests');
print "parsing ovfs\n";
my $win2008 = eval { PVE::GuestImport::OVF::parse_ovf("$test_manifests/Win_2008_R2_two-disks.ovf") };
my $win2008 =
eval { PVE::GuestImport::OVF::parse_ovf("$test_manifests/Win_2008_R2_two-disks.ovf") };
if (my $err = $@) {
fail('parse win2008');
warn("error: $err\n");
@ -28,7 +29,8 @@ if (my $err = $@) {
} else {
ok('parse win10');
}
my $win10noNs = eval { PVE::GuestImport::OVF::parse_ovf("$test_manifests/Win10-Liz_no_default_ns.ovf") };
my $win10noNs =
eval { PVE::GuestImport::OVF::parse_ovf("$test_manifests/Win10-Liz_no_default_ns.ovf") };
if (my $err = $@) {
fail("parse win10 no default rasd NS");
warn("error: $err\n");
@ -38,26 +40,59 @@ if (my $err = $@) {
print "testing disks\n";
is($win2008->{disks}->[0]->{disk_address}, 'scsi0', 'multidisk vm has the correct first disk controller');
is($win2008->{disks}->[0]->{backing_file}, "$test_manifests/disk1.vmdk", 'multidisk vm has the correct first disk backing device');
is(
$win2008->{disks}->[0]->{disk_address},
'scsi0',
'multidisk vm has the correct first disk controller',
);
is(
$win2008->{disks}->[0]->{backing_file},
"$test_manifests/disk1.vmdk",
'multidisk vm has the correct first disk backing device',
);
is($win2008->{disks}->[0]->{virtual_size}, 2048, 'multidisk vm has the correct first disk size');
is($win2008->{disks}->[1]->{disk_address}, 'scsi1', 'multidisk vm has the correct second disk controller');
is($win2008->{disks}->[1]->{backing_file}, "$test_manifests/disk2.vmdk", 'multidisk vm has the correct second disk backing device');
is(
$win2008->{disks}->[1]->{disk_address},
'scsi1',
'multidisk vm has the correct second disk controller',
);
is(
$win2008->{disks}->[1]->{backing_file},
"$test_manifests/disk2.vmdk",
'multidisk vm has the correct second disk backing device',
);
is($win2008->{disks}->[1]->{virtual_size}, 2048, 'multidisk vm has the correct second disk size');
is($win10->{disks}->[0]->{disk_address}, 'scsi0', 'single disk vm has the correct disk controller');
is($win10->{disks}->[0]->{backing_file}, "$test_manifests/Win10-Liz-disk1.vmdk", 'single disk vm has the correct disk backing device');
is(
$win10->{disks}->[0]->{backing_file},
"$test_manifests/Win10-Liz-disk1.vmdk",
'single disk vm has the correct disk backing device',
);
is($win10->{disks}->[0]->{virtual_size}, 2048, 'single disk vm has the correct size');
is($win10noNs->{disks}->[0]->{disk_address}, 'scsi0', 'single disk vm (no default rasd NS) has the correct disk controller');
is($win10noNs->{disks}->[0]->{backing_file}, "$test_manifests/Win10-Liz-disk1.vmdk", 'single disk vm (no default rasd NS) has the correct disk backing device');
is($win10noNs->{disks}->[0]->{virtual_size}, 2048, 'single disk vm (no default rasd NS) has the correct size');
is(
$win10noNs->{disks}->[0]->{disk_address},
'scsi0',
'single disk vm (no default rasd NS) has the correct disk controller',
);
is(
$win10noNs->{disks}->[0]->{backing_file},
"$test_manifests/Win10-Liz-disk1.vmdk",
'single disk vm (no default rasd NS) has the correct disk backing device',
);
is(
$win10noNs->{disks}->[0]->{virtual_size},
2048,
'single disk vm (no default rasd NS) has the correct size',
);
print "testing nics\n";
is($win2008->{net}->{net0}->{model}, 'e1000', 'win2008 has correct nic model');
is($win10->{net}->{net0}->{model}, 'e1000e', 'win10 has correct nic model');
is($win10noNs->{net}->{net0}->{model}, 'e1000e', 'win10 (no default rasd NS) has correct nic model');
is($win10noNs->{net}->{net0}->{model}, 'e1000e',
'win10 (no default rasd NS) has correct nic model');
print "\ntesting vm.conf extraction\n";

View File

@ -8,7 +8,7 @@ $ENV{TZ} = 'UTC';
use TAP::Harness;
my $harness = TAP::Harness->new( { verbosity => -1 });
my $harness = TAP::Harness->new({ verbosity => -1 });
my $res = $harness->runtests(
"archive_info_test.pm",
"parse_volname_test.pm",

File diff suppressed because it is too large Load Diff