From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 43FE01FF168 for ; Tue, 12 Nov 2024 17:27:38 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id C834C2F502; Tue, 12 Nov 2024 17:27:36 +0100 (CET) Date: Tue, 12 Nov 2024 17:27:29 +0100 From: Fabian =?iso-8859-1?q?Gr=FCnbichler?= To: Proxmox VE development discussion References: <20241107165146.125935-1-f.ebner@proxmox.com> <20241107165146.125935-29-f.ebner@proxmox.com> In-Reply-To: <20241107165146.125935-29-f.ebner@proxmox.com> MIME-Version: 1.0 User-Agent: astroid/0.16.0 (https://github.com/astroidmail/astroid) Message-Id: <1731428381.as58eaw8ld.astroid@yuna.none> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.046 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: Re: [pve-devel] [RFC container v3 28/34] backup: implement restore for external providers X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" On November 7, 2024 5:51 pm, Fiona Ebner wrote: > First, the provider is asked about what restore mechanism to use. > Currently, 'directory' and 'tar' are possible, for restoring either > from a directory containing the full filesystem structure (for which > rsync is used) or a potentially compressed tar file containing the > same. nit: this is outdated, directory uses tar as transport/restore mechanism as well now :) > > The new functions are copied and adapted from the existing ones for > PBS or tar and it might be worth to factor out the common parts. > > Restore of containers as privileged are prohibited, because the > archives from an external provider are considered less trusted than > from Proxmox VE storages. If ever allowing that in the future, at > least it would be worth extracting the tar archive in a restricted > context (e.g. user namespace with ID mapped mount or seccomp). > > Signed-off-by: Fiona Ebner > --- > > Changes in v3: > * Use user namespace when restoring directory (and use tar instead of > rsync, because it is easier to split in privileged and unprivileged > half) > > src/PVE/LXC/Create.pm | 141 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 141 insertions(+) > > diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm > index 8c8cb9a..8657ac1 100644 > --- a/src/PVE/LXC/Create.pm > +++ b/src/PVE/LXC/Create.pm > @@ -7,6 +7,7 @@ use File::Path; > use Fcntl; > > use PVE::RPCEnvironment; > +use PVE::RESTEnvironment qw(log_warn); > use PVE::Storage::PBSPlugin; > use PVE::Storage::Plugin; > use PVE::Storage; > @@ -26,6 +27,24 @@ sub restore_archive { > if ($scfg->{type} eq 'pbs') { > return restore_proxmox_backup_archive($storage_cfg, $archive, $rootdir, $conf, $no_unpack_error, $bwlimit); > } > + if (PVE::Storage::storage_has_feature($storage_cfg, $storeid, 'backup-provider')) { > + my $log_function = sub { > + my ($log_level, $message) = @_; > + my $prefix = $log_level eq 'err' ? 'ERROR' : uc($log_level); > + print "$prefix: $message\n"; > + }; > + my $backup_provider = > + PVE::Storage::new_backup_provider($storage_cfg, $storeid, $log_function); > + return restore_external_archive( > + $backup_provider, > + $storeid, > + $volname, > + $rootdir, > + $conf, > + $no_unpack_error, > + $bwlimit, > + ); > + } > } > > $archive = PVE::Storage::abs_filesystem_path($storage_cfg, $archive) if $archive ne '-'; > @@ -127,6 +146,54 @@ sub restore_tar_archive { > die $err if $err && !$no_unpack_error; > } > > +sub restore_external_archive { > + my ($backup_provider, $storeid, $volname, $rootdir, $conf, $no_unpack_error, $bwlimit) = @_; > + > + die "refusing to restore privileged container backup from external source\n" > + if !$conf->{unprivileged}; > + > + my ($mechanism, $vmtype) = $backup_provider->restore_get_mechanism($volname, $storeid); > + die "cannot restore non-LXC guest of type '$vmtype'\n" if $vmtype ne 'lxc'; > + > + my $info = $backup_provider->restore_container_init($volname, $storeid, {}); > + eval { > + if ($mechanism eq 'tar') { > + my $tar_path = $info->{'tar-path'} > + or die "did not get path to tar file from backup provider\n"; > + die "not a regular file '$tar_path'" if !-f $tar_path; > + restore_tar_archive($tar_path, $rootdir, $conf, $no_unpack_error, $bwlimit); > + } elsif ($mechanism eq 'directory') { > + my $directory = $info->{'archive-directory'} > + or die "did not get path to archive directory from backup provider\n"; > + die "not a directory '$directory'" if !-d $directory; > + > + my $create_cmd = [ > + 'tar', > + 'cpf', > + '-', > + @PVE::Storage::Plugin::COMMON_TAR_FLAGS, > + "--directory=$directory", > + '.', > + ]; > + > + my $extract_cmd = restore_tar_archive_command($conf, undef, $rootdir, $bwlimit); > + > + eval { PVE::Tools::run_command([$create_cmd, $extract_cmd]); }; > + die $@ if $@ && !$no_unpack_error; > + } else { > + die "mechanism '$mechanism' requested by backup provider is not supported for LXCs\n"; > + } > + }; > + my $err = $@; > + eval { $backup_provider->restore_container_cleanup($volname, $storeid, {}); }; > + if (my $cleanup_err = $@) { > + die $cleanup_err if !$err; > + warn $cleanup_err; > + } > + die $err if $err; > + > +} > + > sub recover_config { > my ($storage_cfg, $volid, $vmid) = @_; > > @@ -135,6 +202,8 @@ sub recover_config { > my $scfg = PVE::Storage::storage_check_enabled($storage_cfg, $storeid); > if ($scfg->{type} eq 'pbs') { > return recover_config_from_proxmox_backup($storage_cfg, $volid, $vmid); > + } elsif (PVE::Storage::storage_has_feature($storage_cfg, $storeid, 'backup-provider')) { > + return recover_config_from_external_backup($storage_cfg, $volid, $vmid); > } > } > > @@ -209,6 +278,26 @@ sub recover_config_from_tar { > return wantarray ? ($conf, $mp_param) : $conf; > } > > +sub recover_config_from_external_backup { > + my ($storage_cfg, $volid, $vmid) = @_; > + > + $vmid //= 0; > + > + my $raw = PVE::Storage::extract_vzdump_config($storage_cfg, $volid); > + > + my $conf = PVE::LXC::Config::parse_pct_config("/lxc/${vmid}.conf" , $raw); > + > + delete $conf->{snapshots}; > + > + my $mp_param = {}; > + PVE::LXC::Config->foreach_volume($conf, sub { > + my ($ms, $mountpoint) = @_; > + $mp_param->{$ms} = $conf->{$ms}; > + }); > + > + return wantarray ? ($conf, $mp_param) : $conf; > +} > + > sub restore_configuration { > my ($vmid, $storage_cfg, $archive, $rootdir, $conf, $restricted, $unique, $skip_fw) = @_; > > @@ -218,6 +307,26 @@ sub restore_configuration { > if ($scfg->{type} eq 'pbs') { > return restore_configuration_from_proxmox_backup($vmid, $storage_cfg, $archive, $rootdir, $conf, $restricted, $unique, $skip_fw); > } > + if (PVE::Storage::storage_has_feature($storage_cfg, $storeid, 'backup-provider')) { > + my $log_function = sub { > + my ($log_level, $message) = @_; > + my $prefix = $log_level eq 'err' ? 'ERROR' : uc($log_level); > + print "$prefix: $message\n"; > + }; > + my $backup_provider = > + PVE::Storage::new_backup_provider($storage_cfg, $storeid, $log_function); > + return restore_configuration_from_external_backup( > + $backup_provider, > + $vmid, > + $storage_cfg, > + $archive, > + $rootdir, > + $conf, > + $restricted, > + $unique, > + $skip_fw, > + ); > + } > } > restore_configuration_from_etc_vzdump($vmid, $rootdir, $conf, $restricted, $unique, $skip_fw); > } > @@ -258,6 +367,38 @@ sub restore_configuration_from_proxmox_backup { > } > } > > +sub restore_configuration_from_external_backup { > + my ($backup_provider, $vmid, $storage_cfg, $archive, $rootdir, $conf, $restricted, $unique, $skip_fw) = @_; > + > + my ($storeid, $volname) = PVE::Storage::parse_volume_id($archive); > + my $scfg = PVE::Storage::storage_config($storage_cfg, $storeid); > + > + my ($vtype, $name, undef, undef, undef, undef, $format) = > + PVE::Storage::parse_volname($storage_cfg, $archive); > + > + my $oldconf = recover_config_from_external_backup($storage_cfg, $archive, $vmid); > + > + sanitize_and_merge_config($conf, $oldconf, $restricted, $unique); > + > + my $firewall_config = > + $backup_provider->restore_get_firewall_config($volname, $storeid); > + > + if ($firewall_config) { > + my $pve_firewall_dir = '/etc/pve/firewall'; > + my $pct_fwcfg_target = "${pve_firewall_dir}/${vmid}.fw"; > + if ($skip_fw) { > + warn "ignoring firewall config from backup archive, lacking API permission to modify firewall.\n"; > + warn "old firewall configuration in '$pct_fwcfg_target' left in place!\n" > + if -e $pct_fwcfg_target; > + } else { > + mkdir $pve_firewall_dir; # make sure the directory exists > + PVE::Tools::file_set_contents($pct_fwcfg_target, $firewall_config); > + } > + } > + > + return; > +} > + > sub sanitize_and_merge_config { > my ($conf, $oldconf, $restricted, $unique) = @_; > > -- > 2.39.5 > > > > _______________________________________________ > pve-devel mailing list > pve-devel@lists.proxmox.com > https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel > > > _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel