[pve-devel] [PATCH container] implement CT reinstall option for restore

Fabian Grünbichler f.gruenbichler at proxmox.com
Thu Apr 9 11:00:40 CEST 2020


On April 1, 2020 12:44 pm, Oguz Bektas wrote:
> this adds the 'reinstall' flag, which is a special forced restore
> (overwrites an existing container with chosen template)

isn't this backwards? a reinstall should be a special force create 
(based on the current config, instead of an empty one), not a restore? 
else you run into all kinds of potential trouble by passing in an 
ostemplate as backup archive into methods that are designed to handle 
backup archives..

e.g., if you 'reinstall' using an archive that contains a file 
/etc/vzdump/pct.conf, that get's parsed as container config and 
restored, instead of the current/reinstall config..

> 
> testing command example:
> 
> pct restore <CTID> /path/to/template/file --reinstall --storage local-lvm --unprivileged 1 --password 123456
> 
> should reinstall the CT with the given template (different distros can
> be chosen as well, f.e. existing alpine container reinstalled as
> archlinux).
> password or ssh key is required for this, since it calls setup
> routines like post_create_hook (otherwise we won't be able to log-in to
> CT).
> 
> Signed-off-by: Oguz Bektas <o.bektas at proxmox.com>
> ---
>  src/PVE/API2/LXC.pm   | 40 ++++++++++++++++++++++++++++++++++++----
>  src/PVE/LXC/Create.pm | 11 ++++++++---
>  2 files changed, 44 insertions(+), 7 deletions(-)
> 
> diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
> index f4c1a49..f1cd67e 100644
> --- a/src/PVE/API2/LXC.pm
> +++ b/src/PVE/API2/LXC.pm
> @@ -147,6 +147,11 @@ __PACKAGE__->register_method({
>  		type => 'boolean',
>  		description => "Mark this as restore task.",
>  	    },
> +	    reinstall => {
> +		optional => 1,
> +		type => 'boolean',
> +		description => "Reinstall container using a template.",
> +	    },
>  	    unique => {
>  		optional => 1,
>  		type => 'boolean',
> @@ -208,26 +213,39 @@ __PACKAGE__->register_method({
>  	my $unprivileged = extract_param($param, 'unprivileged');
>  	my $restore = extract_param($param, 'restore');
>  	my $unique = extract_param($param, 'unique');
> +	my $reinstall = extract_param($param, 'reinstall');
>  
>  	# used to skip firewall config restore if user lacks permission
>  	my $skip_fw_config_restore = 0;
> +	my $force = extract_param($param, 'force');
> +
> +	if ($reinstall) {
> +	    # reinstall is handled as a special force restore (possibly w/ extra config opts
> +	    # given in the call)
> +	    $restore = 1;
> +	    $force = 1;
> +	}
>  
>  	if ($restore) {
>  	    # fixme: limit allowed parameters
>  	}
>  
> -	my $force = extract_param($param, 'force');
>  
> +	my $reinstall_conf;
>  	if (!($same_container_exists && $restore && $force)) {
>  	    PVE::Cluster::check_vmid_unused($vmid);
>  	} else {
>  	    die "can't overwrite running container\n" if PVE::LXC::check_running($vmid);
>  	    my $conf = PVE::LXC::Config->load_config($vmid);
> +	    $reinstall_conf = $conf;
>  	    PVE::LXC::Config->check_protection($conf, "unable to restore CT $vmid");
>  	}
>  
>  	my $password = extract_param($param, 'password');
>  	my $ssh_keys = extract_param($param, 'ssh-public-keys');
> +	if ($reinstall && !defined($password) && !defined($ssh_keys)) {
> +	    die "password/ssh key required during reinstall. aborting...\n";
> +	}
>  	PVE::Tools::validate_ssh_public_keys($ssh_keys) if defined($ssh_keys);
>  
>  	my $pool = extract_param($param, 'pool');
> @@ -354,7 +372,15 @@ __PACKAGE__->register_method({
>  		    die "can't overwrite running container\n" if PVE::LXC::check_running($vmid);
>  		    if ($is_root && $archive ne '-') {
>  			my $orig_conf;
> -			($orig_conf, $orig_mp_param) = PVE::LXC::Create::recover_config($storage_cfg, $archive);
> +			if ($reinstall) {
> +			    PVE::LXC::Config->foreach_mountpoint($reinstall_conf, sub {
> +				my ($ms, $mountpoint) = @_;
> +				$orig_mp_param->{$ms} = $reinstall_conf->{$ms};
> +			    });
> +			}
> +			else {
> +			    ($orig_conf, $orig_mp_param) = PVE::LXC::Create::recover_config($storage_cfg, $archive);
> +			}
>  			$was_template = delete $orig_conf->{template};
>  			# When we're root call 'restore_configuration' with restricted=0,
>  			# causing it to restore the raw lxc entries, among which there may be
> @@ -365,7 +391,12 @@ __PACKAGE__->register_method({
>  		}
>  		if ($storage_only_mode) {
>  		    if ($restore) {
> -			if (!defined($orig_mp_param)) {
> +			if ($reinstall) {
> +			    PVE::LXC::Config->foreach_mountpoint($reinstall_conf, sub {
> +			        my ($ms, $mountpoint) = @_;
> +				$orig_mp_param->{$ms} = $reinstall_conf->{$ms};
> +			    });
> +			} elsif (!defined($orig_mp_param)) {
>  			    (undef, $orig_mp_param) = PVE::LXC::Create::recover_config($storage_cfg, $archive);
>  			}
>  			$mp_param = $orig_mp_param;
> @@ -417,9 +448,10 @@ __PACKAGE__->register_method({
>  		    PVE::LXC::Create::restore_archive($storage_cfg, $archive, $rootdir, $conf, $ignore_unpack_errors, $bwlimit);
>  
>  		    if ($restore) {
> -			PVE::LXC::Create::restore_configuration($vmid, $storage_cfg, $archive, $rootdir, $conf, !$is_root, $unique, $skip_fw_config_restore);
> +			PVE::LXC::Create::restore_configuration($vmid, $storage_cfg, $archive, $rootdir, $conf, !$is_root, $unique, $skip_fw_config_restore, $reinstall_conf);
>  			my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir);
>  			$lxc_setup->template_fixup($conf);
> +			$lxc_setup->post_create_hook($password, $ssh_keys) if $reinstall;
>  		    } else {
>  			my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir); # detect OS
>  			PVE::LXC::Config->write_config($vmid, $conf); # safe config (after OS detection)
> diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
> index 9faec63..342e790 100644
> --- a/src/PVE/LXC/Create.pm
> +++ b/src/PVE/LXC/Create.pm
> @@ -251,7 +251,7 @@ sub recover_config_from_tar {
>  }
>  
>  sub restore_configuration {
> -    my ($vmid, $storage_cfg, $archive, $rootdir, $conf, $restricted, $unique, $skip_fw) = @_;
> +    my ($vmid, $storage_cfg, $archive, $rootdir, $conf, $restricted, $unique, $skip_fw, $reinstall_conf) = @_;
>  
>      my ($storeid, $volname) = PVE::Storage::parse_volume_id($archive, 1);
>      if (defined($storeid)) {
> @@ -260,7 +260,7 @@ sub restore_configuration {
>  	    return restore_configuration_from_proxmox_backup($vmid, $storage_cfg, $archive, $rootdir, $conf, $restricted, $unique, $skip_fw);
>  	}
>      }
> -    restore_configuration_from_etc_vzdump($vmid, $rootdir, $conf, $restricted, $unique, $skip_fw);
> +    restore_configuration_from_etc_vzdump($vmid, $rootdir, $conf, $restricted, $unique, $skip_fw, $reinstall_conf);
>  }
>  
>  sub restore_configuration_from_proxmox_backup {
> @@ -332,13 +332,16 @@ sub sanitize_and_merge_config {
>  }
>  
>  sub restore_configuration_from_etc_vzdump {
> -    my ($vmid, $rootdir, $conf, $restricted, $unique, $skip_fw) = @_;
> +    my ($vmid, $rootdir, $conf, $restricted, $unique, $skip_fw, $reinstall_conf) = @_;
>  
>      # restore: try to extract configuration from archive
>  
>      my $pct_cfg_fn = "$rootdir/etc/vzdump/pct.conf";
>      my $pct_fwcfg_fn = "$rootdir/etc/vzdump/pct.fw";
>      my $ovz_cfg_fn = "$rootdir/etc/vzdump/vps.conf";
> +
> +    my $reinstall = defined($reinstall_conf);
> +
>      if (-f $pct_cfg_fn) {
>  	my $raw = PVE::Tools::file_get_contents($pct_cfg_fn);
>  	my $oldconf = PVE::LXC::Config::parse_pct_config("/lxc/$vmid.conf", $raw);
> @@ -380,6 +383,8 @@ sub restore_configuration_from_etc_vzdump {
>  	}
>  	unlink($ovz_cfg_fn);
>  
> +    } elsif ($reinstall) {
> +	sanitize_and_merge_config($conf, $reinstall_conf, $restricted, $unique);
>      } else {
>  	print "###########################################################\n";
>  	print "Backup archive does not contain any configuration\n";
> -- 
> 2.20.1
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
> 
> 




More information about the pve-devel mailing list