From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 2B8D01FF0C0 for ; Wed, 04 Nov 2026 20:07:26 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 13764218B2; Wed, 04 Nov 2026 20:05:26 +0100 (CET) From: =?UTF-8?q?Michael=20K=C3=B6ppl?= To: pve-devel@lists.proxmox.com Subject: [PATCH e2e-tests 31/38] tests: pbs: verify container backup and restore Date: Wed, 4 Nov 2026 20:03:38 +0100 Message-ID: <20261104190345.2573464-32-m.koeppl@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261104190345.2573464-1-m.koeppl@proxmox.com> References: <20261104190345.2573464-1-m.koeppl@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1793819036336 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.218 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: JOM5LULFREGE3Z6ZBQ4P5PUMJ2IK3RSJ X-Message-ID-Hash: JOM5LULFREGE3Z6ZBQ4P5PUMJ2IK3RSJ X-MailFrom: m.koeppl@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Back up a running container in snapshot mode to a local datastore on PBS, restore it as a new container and check its config and data. Signed-off-by: Michael Köppl --- tests/pbs/test_pbs_ct_backup_restore.pl | 150 ++++++++++++++++++++++++ tests/testcases.ron | 10 ++ 2 files changed, 160 insertions(+) create mode 100755 tests/pbs/test_pbs_ct_backup_restore.pl diff --git a/tests/pbs/test_pbs_ct_backup_restore.pl b/tests/pbs/test_pbs_ct_backup_restore.pl new file mode 100755 index 0000000..43fb66f --- /dev/null +++ b/tests/pbs/test_pbs_ct_backup_restore.pl @@ -0,0 +1,150 @@ +#!/usr/bin/perl + +=head1 NAME + +C - Back up a running container to PBS and restore it. + +=head1 DESCRIPTION + +This testcase creates a local datastore on PBS and adds it to PVE as a storage. +It then creates an unprivileged container, starts it, and writes a marker file. +It backs up the running container the PBS datastore in snapshot mode, restores +the backup as a new container, and verifies that the restored container keeps +its configuration and data. + +=cut + +use strict; +use warnings; + +use Test::More; + +use lib '.'; +use Proxmox::Test::Helper qw(CONTAINER_TEMPLATE get_pbs_instance get_pve_instance); +use Proxmox::Test::Testcase; + +my $pve = get_pve_instance('pve1'); +my $pbs = get_pbs_instance('pbs1'); + +my $datastore = 'e2e-ct'; +my $storage_id = 'e2e-pbs-ct'; + +my $node = $pve->get_nodename(); +my $client = $pve->client(); + +my $test_container = { + vmid => $client->get('/cluster/nextid'), + node => $node, + ostemplate => CONTAINER_TEMPLATE, + rootfs => 'local-lvm:2', + storage => 'local-lvm', + memory => 256, + unprivileged => 1, + features => 'nesting=1', + hostname => 'e2e-ct-pbs-backup', +}; + +my $vmid = $test_container->{vmid}; +my $marker = "e2e-backup-$vmid"; +my $backup_volid; +my $restore_vmid; + +Proxmox::Test::Testcase->new('pbs_ct_backup_restore')->with([{}])->step( + 'create datastore on PBS', + sub { + $pbs->create_datastore($datastore); + }, + sub { + $pbs->remove_datastore($datastore); + }, +)->step( + 'add PBS as storage on PVE', + sub { + $pve->add_pbs_storage($storage_id, $pbs, $datastore); + }, + sub { + $client->delete("/storage/$storage_id"); + }, +)->step( + 'create container', + sub { + my $upid = $client->post("/nodes/$node/lxc", $test_container); + $pve->task_ok($upid, "created container $vmid") + or die "creating container $vmid failed\n"; + }, + sub { + $pve->destroy_guest('lxc', $vmid); + }, +)->step( + 'start container and write marker', + sub { + $pve->start_guest('lxc', $vmid); + $pve->ct_exec($vmid, "sh -c 'echo $marker > /root/marker'"); + }, +)->step( + 'back up running container to PBS', + sub { + my $upid = $client->post( + "/nodes/$node/vzdump", + { + vmid => $vmid, + storage => $storage_id, + mode => 'snapshot', + }, + ); + $pve->task_ok($upid, 'backed up container to PBS') or die "backup failed\n"; + + my $content = + $client->get("/nodes/$node/storage/$storage_id/content", { content => 'backup' }); + my ($backup) = grep { $_->{vmid} == $vmid } $content->@*; + $backup_volid = $backup->{volid}; + ok($backup_volid, 'found container backup on PBS storage') or die "backup not found\n"; + is($backup->{format}, 'pbs-ct', 'backup has the PBS container format'); + + is( + $client->get("/nodes/$node/lxc/$vmid/status/current", {})->{status}, + 'running', + 'container keeps running during a snapshot mode backup', + ); + }, +)->step( + 'restore backup as new container', + sub { + $restore_vmid = $client->get('/cluster/nextid'); + my $upid = $client->post( + "/nodes/$node/lxc", + { + vmid => $restore_vmid, + ostemplate => $backup_volid, + restore => 1, + storage => 'local-lvm', + }, + ); + $pve->task_ok($upid, "restored container $restore_vmid from PBS") + or die "restoring the backup failed\n"; + }, + sub { + $pve->destroy_guest('lxc', $restore_vmid) if defined($restore_vmid); + }, +)->step( + 'verify restored container', + sub { + my $conf = $client->get("/nodes/$node/lxc/$restore_vmid/config", {}); + is($conf->{hostname}, $test_container->{hostname}, 'restored config has the hostname'); + is($conf->{unprivileged}, 1, 'restored container is still unprivileged'); + like( + $conf->{rootfs} // '', + qr/^local-lvm:vm-$restore_vmid-disk-\d+\b/, + 'restored rootfs is allocated for the new container', + ); + + $pve->start_guest('lxc', $restore_vmid); + is( + $pve->ct_exec($restore_vmid, 'cat /root/marker'), + "$marker\n", + 'restored data is intact', + ); + }, +)->run(); + +done_testing(); diff --git a/tests/testcases.ron b/tests/testcases.ron index 340ac81..ace5792 100644 --- a/tests/testcases.ron +++ b/tests/testcases.ron @@ -273,6 +273,16 @@ TestcaseConfig( ], tag: "pbs", ), + Testcase( + name: "pbs_ct_backup_restore", + run: "./tests/pbs/test_pbs_ct_backup_restore.pl", + timeout: 600, + instances: [ + "pve1", + "pbs1", + ], + tag: "pbs", + ), Testcase( name: "sdn_create_vlan_zone", run: "./tests/sdn/test_vlan_zone.pl", -- 2.47.3