[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