[pve-devel] [PATCH container 1/5] fix #996: automatically restore mountpoints from backup

Fabian Grünbichler f.gruenbichler at proxmox.com
Mon May 30 11:45:53 CEST 2016


if the mountpoint configuration is not explicitly provided
via -rootfs or -mpX , recreate all volume mountpoints on the
provided -storage , restore the archive and then finally add
non-volume mountpoints back to the configuration.

if -rootfs (and optionally any -mpX) are provided, the old
configuration contained in the backup archive is completely
ignored. this allows reconfiguration of mountpoints when
restoring a backup, e.g. to change mountpoint paths or other
mountpoint options.
---
 src/PVE/API2/LXC.pm          | 51 ++++++++++++++++++++++++++++++++------------
 src/PVE/LXC/Create.pm        | 20 +++++++++++------
 src/PVE/VZDump/ConvertOVZ.pm |  4 ++--
 3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 95932a9..d2b03ea 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -256,11 +256,18 @@ __PACKAGE__->register_method({
 	my $conf = {};
 
 	my $no_disk_param = {};
+	my $mp_param = {};
+	my $storage_only_mode = 1;
 	foreach my $opt (keys %$param) {
 	    my $value = $param->{$opt};
 	    if ($opt eq 'rootfs' || $opt =~ m/^mp\d+$/) {
 		# allow to use simple numbers (add default storage in that case)
-		$param->{$opt} = "$storage:$value" if $value =~ m/^\d+(\.\d+)?$/;
+		if ($value =~ m/^\d+(\.\d+)?$/) {
+		    $mp_param->{$opt} = "$storage:$value";
+		} else {
+		    $mp_param->{$opt} = $value;
+		}
+		$storage_only_mode = 0;
 	    } elsif ($opt =~ m/^unused\d+$/) {
 		warn "ignoring '$opt', cannot create/restore with unused volume\n";
 		delete $param->{$opt};
@@ -269,8 +276,12 @@ __PACKAGE__->register_method({
 	    }
 	}
 
+	die "mountpoints configured, but 'rootfs' not set - aborting\n"
+	    if !$storage_only_mode && !defined($mp_param->{rootfs});
+
 	# check storage access, activate storage
-	PVE::LXC::Config->foreach_mountpoint($param, sub {
+	my $delayed_mp_param = {};
+	PVE::LXC::Config->foreach_mountpoint($mp_param, sub {
 	    my ($ms, $mountpoint) = @_;
 
 	    my $volid = $mountpoint->{volume};
@@ -279,6 +290,12 @@ __PACKAGE__->register_method({
 	    if ($mountpoint->{type} ne 'volume') { # bind or device
 		die "Only root can pass arbitrary filesystem paths.\n"
 		    if $authuser ne 'root at pam';
+		if ($restore) {
+		    die "Restoring to non-volume rootfs is not allowed.\n"
+			if $ms eq 'rootfs';
+		    $delayed_mp_param->{$ms} = $mp_param->{$ms};
+		    delete $mp_param->{$ms};
+		}
 	    } else {
 		my ($sid, $volname) = PVE::Storage::parse_volume_id($volid);
 		&$check_and_activate_storage($sid);
@@ -286,7 +303,7 @@ __PACKAGE__->register_method({
 	});
 
 	# check/activate default storage
-	&$check_and_activate_storage($storage) if !defined($param->{rootfs});
+	&$check_and_activate_storage($storage) if !defined($mp_param->{rootfs});
 
 	PVE::LXC::Config->update_pct_config($vmid, $conf, 0, $no_disk_param);
 
@@ -308,22 +325,25 @@ __PACKAGE__->register_method({
 	    my $vollist = [];
 
 	    eval {
-		if (!defined($param->{rootfs})) {
+		if ($storage_only_mode) {
 		    if ($restore) {
-			my (undef, $rootfsinfo) = PVE::LXC::Create::recover_config($archive);
-			die "unable to detect disk size - please specify rootfs (size)\n"
-			    if !defined($rootfsinfo->{size});
-			my $disksize = $rootfsinfo->{size} / (1024 * 1024 * 1024); # create_disks expects GB as unit size
-			delete $rootfsinfo->{size};
-			delete $rootfsinfo->{ro} if defined($rootfsinfo->{ro});
-			$rootfsinfo->{volume} = "$storage:$disksize";
-			$param->{rootfs} = PVE::LXC::Config->print_ct_mountpoint($rootfsinfo, 1);
+			(undef, $mp_param, $delayed_mp_param) = PVE::LXC::Create::recover_config($archive);
+			PVE::LXC::Config->foreach_mountpoint($mp_param, sub {
+			    my ($ms, $mountpoint) = @_;
+			    die "unable to detect disk size - please specify $ms (size)\n"
+				if !defined($mountpoint->{size});
+			    my $disksize = $mountpoint->{size} / (1024 * 1024 * 1024); # create_disks expects GB as unit size 
+			    delete $mountpoint->{size};
+			    $mountpoint->{volume} = "$storage:$disksize";
+			    $mp_param->{$ms} = PVE::LXC::Config->print_ct_mountpoint($mountpoint, $ms eq 'rootfs');
+			});
 		    } else {
-			$param->{rootfs} = "$storage:4"; # defaults to 4GB
+			$mp_param->{rootfs} = "$storage:4"; # defaults to 4GB
 		    }
 		}
 
-		$vollist = PVE::LXC::create_disks($storage_cfg, $vmid, $param, $conf);
+		$vollist = PVE::LXC::create_disks($storage_cfg, $vmid, $mp_param, $conf);
+
 
 		PVE::LXC::Create::create_rootfs($storage_cfg, $vmid, $conf,
 						$archive, $password, $restore,
@@ -332,6 +352,9 @@ __PACKAGE__->register_method({
 		$conf->{hostname} ||= "CT$vmid";
 		$conf->{memory} ||= 512;
 		$conf->{swap} //= 512;
+		foreach my $mp (keys %$delayed_mp_param) {
+		    $conf->{$mp} = $delayed_mp_param->{$mp};
+		}
 		PVE::LXC::Config->write_config($vmid, $conf);
 	    };
 	    if (my $err = $@) {
diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
index fe47fc1..560d5b6 100644
--- a/src/PVE/LXC/Create.pm
+++ b/src/PVE/LXC/Create.pm
@@ -107,7 +107,8 @@ sub recover_config {
     PVE::Tools::run_command(['tar', '-xpOf', $archive, $conf_file, '--occurrence'], outfunc => $out);
 
     my $conf;
-    my $rootfsinfo;
+    my $mp_param = {};
+    my $delayed_mp_param = {};
 
     if ($conf_file =~ m/pct\.conf/) {
 
@@ -115,21 +116,26 @@ sub recover_config {
 
 	delete $conf->{snapshots};
 	delete $conf->{template}; # restored CT is never a template
-	
-	if (defined($conf->{rootfs})) {
-	    $rootfsinfo = PVE::LXC::Config->parse_ct_rootfs($conf->{rootfs});
-	}
+
+	PVE::LXC::Config->foreach_mountpoint($conf, sub {
+	    my ($ms, $mountpoint) = @_;
+	    if ($mountpoint->{type} eq 'volume') {
+		$mp_param->{$ms} = $conf->{$ms};
+	    } else {
+		$delayed_mp_param->{$ms} = $conf->{$ms};
+	    }
+	});
 	
     } elsif ($conf_file =~ m/vps\.conf/) {
 	
-	($conf, $rootfsinfo) = PVE::VZDump::ConvertOVZ::convert_ovz($raw);
+	($conf, $mp_param, $delayed_mp_param) = PVE::VZDump::ConvertOVZ::convert_ovz($raw);
 	
     } else {
 
        die "internal error";
     }
 
-    return wantarray ? ($conf, $rootfsinfo) : $conf;
+    return wantarray ? ($conf, $mp_param, $delayed_mp_param) : $conf;
 }
 
 sub restore_and_configure {
diff --git a/src/PVE/VZDump/ConvertOVZ.pm b/src/PVE/VZDump/ConvertOVZ.pm
index 8942453..616e30d 100644
--- a/src/PVE/VZDump/ConvertOVZ.pm
+++ b/src/PVE/VZDump/ConvertOVZ.pm
@@ -314,7 +314,7 @@ sub convert_ovz {
 
    $conf->{hostname} = $ovz_conf->{hostname}->{value};
 
-   my $rootfsinfo = { size => $disksize, mp => '/' };
+   my $mp_param = { rootfs => "local:convertedovz,size=$disksize" };
 
-   return wantarray ? ($conf, $rootfsinfo) : $conf;
+   return wantarray ? ($conf, $mp_param, {}) : $conf;
 }
-- 
2.1.4





More information about the pve-devel mailing list