pve-manager/test/vzdump_new_test.pl
Fiona Ebner ebfd6dd79b backup: implement backup for external providers
Call job_{init,cleanup}() and backup_{init,cleanup}() methods so that
backup providers can prepare and clean up for the whole backup job and
for individual guest backups.

It is necessary to adapt some log messages and special case some
things like is already done for PBS, e.g. log file handling.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Tested-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Link: https://lore.proxmox.com/20250404133204.239783-30-f.ebner@proxmox.com
2025-04-06 21:45:13 +02:00

676 lines
13 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use warnings;
use lib '..';
use Test::More;
use Test::MockModule;
use PVE::VZDump;
my $vzdump_config;
my $storage_config;
sub prepare_storage_config {
my ($param) = @_;
$storage_config = "dir: local\n";
$storage_config .= "\tcontent backup\n";
$storage_config .= "\tpath /var/lib/vz\n";
foreach my $key (keys %{$param}) {
my $value = $param->{$key};
$storage_config .= "\t${key} ${value}\n";
}
}
sub prepare_vzdump_config {
my ($param) = @_;
$vzdump_config = "";
foreach my $key (keys %{$param}) {
my $value = $param->{$key};
$vzdump_config .= "${key}: ${value}\n";
}
}
my $pve_vzdump_module = Test::MockModule->new('PVE::VZDump');
$pve_vzdump_module->mock(
mkpath => sub {
return;
},
check_bin => sub {
return;
},
);
my $pve_storage_module = Test::MockModule->new('PVE::Storage');
$pve_storage_module->mock(
activate_storage => sub {
return;
},
get_backup_provider => sub {
return;
},
);
my $pve_cluster_module = Test::MockModule->new('PVE::Cluster');
$pve_cluster_module->mock(
get_config => sub {
my ($filename) = @_;
die "unexpected filename '$filename'\n" if $filename ne 'storage.cfg';
return $storage_config;
},
# never update during the tests
cfs_update => sub {
return;
},
);
my $pve_tools_module = Test::MockModule->new('PVE::Tools');
$pve_tools_module->mock(
file_get_contents => sub {
my ($filename) = @_;
die "unexpected filename '$filename'\n" if $filename ne '/etc/vzdump.conf';
return $vzdump_config;
},
);
my $tested_options;
# each test consists of the following:
# name - unique name for the test
# cli_param - CLI parameters to be passed to new(); vmid and storage are hardcoded
# storage_param - parameters for the mocked storage configuration
# vzdump_param - parameters for the mocked /etc/vzdump.conf
# expected - expected options
#
# To begin testing for different options, use a fake test like the first one
my @tests = (
{
description => 'BEGIN RETENTION TESTS',
tested_options => ['prune-backups', 'remove'],
},
{
description => 'no params',
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
# TODO make parse error critical?
{
description => 'maxfiles vzdump 1',
vzdump_param => {
maxfiles => 0,
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'maxfiles vzdump 2',
vzdump_param => {
maxfiles => 7,
},
expected => {
'prune-backups' => {
'keep-last' => 7,
},
remove => 1,
},
},
{
description => 'maxfiles storage 1',
storage_param => {
maxfiles => 0,
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'maxfiles storage 2',
storage_param => {
maxfiles => 7,
},
expected => {
'prune-backups' => {
'keep-last' => 7,
},
remove => 1,
},
},
{
description => 'maxfiles CLI 1',
cli_param => {
maxfiles => 0,
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'maxfiles CLI 2',
cli_param => {
maxfiles => 7,
},
expected => {
'prune-backups' => {
'keep-last' => 7,
},
remove => 1,
},
},
{
description => 'prune-backups vzdump 1',
vzdump_param => {
'prune-backups' => 'keep-last=1,keep-hourly=2,keep-daily=3,' .
'keep-weekly=4,keep-monthly=5,keep-yearly=6',
},
expected => {
'prune-backups' => {
'keep-last' => 1,
'keep-hourly' => 2,
'keep-daily' => 3,
'keep-weekly' => 4,
'keep-monthly' => 5,
'keep-yearly' => 6,
},
remove => 1,
},
},
{
description => 'prune-backups vzdump 2',
vzdump_param => {
'prune-backups' => 'keep-all=1',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'prune-backups vzdump 3',
vzdump_param => {
'prune-backups' => 'keep-hourly=0,keep-monthly=0,keep-yearly=0',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'both vzdump 1',
vzdump_param => {
'prune-backups' => 'keep-all=1',
maxfiles => 7,
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'prune-backups storage 1',
storage_param => {
'prune-backups' => 'keep-last=1,keep-hourly=2,keep-daily=3,' .
'keep-weekly=4,keep-monthly=5,keep-yearly=6',
},
expected => {
'prune-backups' => {
'keep-last' => 1,
'keep-hourly' => 2,
'keep-daily' => 3,
'keep-weekly' => 4,
'keep-monthly' => 5,
'keep-yearly' => 6,
},
remove => 1,
},
},
{
description => 'prune-backups storage 2',
storage_param => {
'prune-backups' => 'keep-last=0,keep-hourly=0,keep-daily=0,' .
'keep-weekly=0,keep-monthly=0,keep-yearly=0',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'prune-backups storage 3',
storage_param => {
'prune-backups' => 'keep-hourly=0,keep-monthly=0,keep-yearly=0',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'both storage 1',
storage_param => {
'prune-backups' => 'keep-hourly=1,keep-monthly=2,keep-yearly=3',
maxfiles => 0,
},
expected => {
'prune-backups' => {
'keep-hourly' => 1,
'keep-monthly' => 2,
'keep-yearly' => 3,
},
remove => 1,
},
},
{
description => 'prune-backups CLI 1',
cli_param => {
'prune-backups' => 'keep-last=1,keep-hourly=2,keep-daily=3,' .
'keep-weekly=4,keep-monthly=5,keep-yearly=6',
},
expected => {
'prune-backups' => {
'keep-last' => 1,
'keep-hourly' => 2,
'keep-daily' => 3,
'keep-weekly' => 4,
'keep-monthly' => 5,
'keep-yearly' => 6,
},
remove => 1,
},
},
{
description => 'prune-backups CLI 2',
cli_param => {
'prune-backups' => 'keep-last=0,keep-hourly=0,keep-daily=0,' .
'keep-weekly=0,keep-monthly=0,keep-yearly=0',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'prune-backups CLI 3',
cli_param => {
'prune-backups' => 'foo=bar',
},
expected => "format error\n" .
"foo: property is not defined in schema and the schema does not allow additional properties\n",
},
{
description => 'both CLI 1',
cli_param => {
'prune-backups' => 'keep-hourly=1,keep-monthly=2,keep-yearly=3',
maxfiles => 4,
},
expected => "400 Parameter verification failed.\n" .
"prune-backups: option conflicts with option 'maxfiles'\n",
},
{
description => 'mixed 1',
vzdump_param => {
maxfiles => 7,
},
storage_param => {
'prune-backups' => 'keep-hourly=24',
},
expected => {
'prune-backups' => {
'keep-hourly' => 24,
},
remove => 1,
},
},
# TODO make parse error critical?
{
description => 'mixed 2',
vzdump_param => {
maxfiles => 7,
},
storage_param => {
'prune-backups' => 'keephourly=24',
},
expected => {
'prune-backups' => {
'keep-last' => 7,
},
remove => 1,
},
},
{
description => 'mixed 3',
vzdump_param => {
maxfiles => 7,
},
cli_param => {
'prune-backups' => 'keep-all=1',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'mixed 4',
vzdump_param => {
maxfiles => 7,
},
storage_param => {
'prune-backups' => 'keep-all=0,keep-last=10',
},
cli_param => {
'prune-backups' => 'keep-all=1',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'mixed 5',
vzdump_param => {
maxfiles => 7,
},
storage_param => {
'prune-backups' => 'keep-all=0,keep-last=10',
},
expected => {
'prune-backups' => {
'keep-last' => 10,
},
remove => 1,
},
},
{
description => 'mixed 6',
storage_param => {
'prune-backups' => 'keep-last=10',
},
cli_param => {
'prune-backups' => 'keep-all=1',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'mixed 7',
storage_param => {
'prune-backups' => 'keep-all=1',
},
cli_param => {
'prune-backups' => 'keep-last=10',
},
expected => {
'prune-backups' => {
'keep-last' => 10,
},
remove => 1,
},
},
{
description => 'mixed 8',
storage_param => {
'prune-backups' => 'keep-last=10',
},
vzdump_param => {
'prune-backups' => 'keep-all=1',
},
expected => {
'prune-backups' => {
'keep-last' => 10,
},
remove => 1,
},
},
{
description => 'mixed 9',
vzdump_param => {
'prune-backups' => 'keep-last=10',
},
cli_param => {
'prune-backups' => 'keep-all=1',
},
expected => {
'prune-backups' => {
'keep-all' => 1,
},
remove => 0,
},
},
{
description => 'BEGIN MAILTO TESTS',
tested_options => ['mailto'],
},
{
description => 'mailto vzdump 1',
vzdump_param => {
'mailto' => 'developer@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
],
},
},
{
description => 'mailto vzdump 2',
vzdump_param => {
'mailto' => 'developer@proxmox.com admin@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto vzdump 3',
vzdump_param => {
'mailto' => 'developer@proxmox.com,admin@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto vzdump 4',
vzdump_param => {
'mailto' => 'developer@proxmox.com, admin@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto vzdump 5',
vzdump_param => {
'mailto' => ' ,,; developer@proxmox.com, ; admin@proxmox.com ',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto vzdump 6',
vzdump_param => {
'mailto' => '',
},
expected => {
'mailto' => [],
},
},
{
description => 'mailto CLI 1',
cli_param => {
'mailto' => 'developer@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
],
},
},
{
description => 'mailto CLI 2',
cli_param => {
'mailto' => 'developer@proxmox.com admin@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto CLI 3',
cli_param => {
'mailto' => 'developer@proxmox.com,admin@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto CLI 4',
cli_param => {
'mailto' => 'developer@proxmox.com, admin@proxmox.com',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto CLI 5',
cli_param => {
'mailto' => ' ,,; developer@proxmox.com, ; admin@proxmox.com ',
},
expected => {
'mailto' => [
'developer@proxmox.com',
'admin@proxmox.com',
],
},
},
{
description => 'mailto both 1',
vzdump_param => {
'mailto' => 'developer@proxmox.com',
},
cli_param => {
'mailto' => 'admin@proxmox.com',
},
expected => {
'mailto' => [
'admin@proxmox.com',
],
},
},
{
description => 'mailto both 2',
vzdump_param => {
'mailto' => 'developer@proxmox.com',
},
cli_param => {
'mailto' => '',
},
expected => {
'mailto' => [],
},
},
);
plan tests => scalar @tests;
foreach my $test (@tests) {
if (defined($test->{tested_options})) {
$tested_options = $test->{tested_options};
ok(1, $test->{description});
next;
}
prepare_storage_config($test->{storage_param});
prepare_vzdump_config($test->{vzdump_param});
$test->{cli_param}->{vmid} = 100;
$test->{cli_param}->{storage} = 'local';
my $got = eval {
PVE::VZDump::verify_vzdump_parameters($test->{cli_param}, 1);
PVE::VZDump::parse_mailto_exclude_path($test->{cli_param});
my $vzdump = PVE::VZDump->new('fake cmdline', $test->{cli_param}, undef);
my $opts = $vzdump->{opts} or die "did not get options\n";
die "maxfiles is defined" if defined($opts->{maxfiles});
my $res = {};
foreach my $opt (@{$tested_options}) {
next if !defined($opts->{$opt});
$res->{$opt} = $opts->{$opt};
}
return $res;
};
$got = $@ if $@;
is_deeply($got, $test->{expected}, $test->{description}) || diag(explain($got));
}
done_testing();