[pve-devel] [PATCH container 2/3] Add mp support to snapshots
Fabian Grünbichler
f.gruenbichler at proxmox.com
Wed Feb 24 12:28:34 CET 2016
Modelled after QemuServer's way of handling multiple drives.
---
src/PVE/LXC.pm | 97 +++++++++++++++++++++++++++++++--------------------
src/PVE/VZDump/LXC.pm | 20 +++++++----
2 files changed, 73 insertions(+), 44 deletions(-)
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 6046c46..dcec775 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1892,10 +1892,6 @@ sub has_feature {
return if $vzdump && $ms ne 'rootfs' && !$mountpoint->{backup};
$err = 1 if !PVE::Storage::volume_has_feature($storecfg, $feature, $mountpoint->{volume}, $snapname);
-
- # TODO: implement support for mountpoints
- die "unable to handle mountpoint '$ms' - feature not implemented\n"
- if $ms ne 'rootfs';
});
return $err ? 0 : 1;
@@ -1970,43 +1966,54 @@ sub sync_container_namespace {
die "failed to sync container namespace\n" if $? != 0;
}
+sub check_freeze_needed {
+ my ($vmid, $config, $save_vmstate) = @_;
+
+ my $ret = check_running($vmid);
+ return ($ret, $ret);
+}
+
sub snapshot_create {
my ($vmid, $snapname, $save_vmstate, $comment) = @_;
my $snap = snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
+ $save_vmstate = 0 if !$snap->{vmstate};
+
my $conf = load_config($vmid);
- my $running = check_running($vmid);
-
- my $unfreeze = 0;
+ my ($running, $freezefs) = check_freeze_needed($vmid, $conf, $snap->{vmstate});
my $drivehash = {};
eval {
- if ($running) {
- $unfreeze = 1;
+ if ($freezefs) {
PVE::Tools::run_command(['/usr/bin/lxc-freeze', '-n', $vmid]);
sync_container_namespace($vmid);
- };
+ }
my $storecfg = PVE::Storage::config();
- my $rootinfo = parse_ct_rootfs($conf->{rootfs});
- my $volid = $rootinfo->{volume};
+ foreach_mountpoint($conf, sub {
+ my ($ms, $mountpoint) = @_;
- PVE::Storage::volume_snapshot($storecfg, $volid, $snapname);
- $drivehash->{rootfs} = 1;
+ return if $snapname eq 'vzdump' && $ms ne 'rootfs' && !$mountpoint->{backup};
+ PVE::Storage::volume_snapshot($storecfg, $mountpoint->{volume}, $snapname);
+ $drivehash->{$ms} = 1;
+ });
};
my $err = $@;
- if ($unfreeze) {
- eval { PVE::Tools::run_command(['/usr/bin/lxc-unfreeze', '-n', $vmid]); };
- warn $@ if $@;
+ if ($running) {
+ if ($freezefs) {
+ eval { PVE::Tools::run_command(['/usr/bin/lxc-unfreeze', '-n', $vmid]); };
+ warn $@ if $@;
+ }
}
if ($err) {
+ warn "snapshot create failed: starting cleanup\n";
eval { snapshot_delete($vmid, $snapname, 1, $drivehash); };
- warn "$@\n" if $@;
+ warn "$@" if $@;
die "$err\n";
}
@@ -2020,6 +2027,7 @@ sub snapshot_delete {
my $prepare = 1;
my $snap;
+ my $unused = [];
my $unlink_parent = sub {
my ($confref, $new_parent) = @_;
@@ -2061,7 +2069,11 @@ sub snapshot_delete {
if ($remove_drive eq 'vmstate') {
die "implement me - saving vmstate\n";
} else {
- die "implement me - remove drive\n";
+ my $value = $snap->{$remove_drive};
+ my $mountpoint = $remove_drive eq 'rootfs' ? parse_ct_rootfs($value, 1) : parse_ct_mountpoint($value, 1);
+ delete $snap->{$remove_drive};
+ add_unused_volume($snap, $mountpoint->{volume})
+ if (!is_volume_in_use($snap, $mountpoint->{volume}));
}
}
@@ -2070,6 +2082,10 @@ sub snapshot_delete {
} else {
delete $conf->{snapshots}->{$snapname};
delete $conf->{lock} if $drivehash;
+ foreach my $volid (@$unused) {
+ add_unused_volume($conf, $volid)
+ if (!is_volume_in_use($conf, $volid));
+ }
}
write_config($vmid, $conf);
@@ -2086,17 +2102,22 @@ sub snapshot_delete {
};
# now remove all volume snapshots
- # only rootfs for now!
- eval {
- my $rootfs = $snap->{rootfs};
- my $rootinfo = parse_ct_rootfs($rootfs);
- my $volid = $rootinfo->{volume};
- PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snapname);
- };
- if (my $err = $@) {
- die $err if !$force;
- warn $err;
- }
+ foreach_mountpoint($snap, sub {
+ my ($ms, $mountpoint) = @_;
+
+ return if $snapname eq 'vzdump' && $ms ne 'rootfs' && !$mountpoint->{backup};
+ if (!$drivehash || $drivehash->{$ms}) {
+ eval { PVE::Storage::volume_snapshot_delete($storecfg, $mountpoint->{volume}, $snapname); };
+ if (my $err = $@) {
+ die $err if !$force;
+ warn $err;
+ }
+ }
+
+ # save changes (remove mp from snapshot)
+ lock_config($vmid, $updatefn, $ms) if !$force;
+ push @$unused, $mountpoint->{volume};
+ });
# now cleanup config
$prepare = 0;
@@ -2125,12 +2146,11 @@ sub snapshot_rollback {
my $snap = &$get_snapshot_config();
- # only for rootfs for now!
- my $rootfs = $snap->{rootfs};
- my $rootinfo = parse_ct_rootfs($rootfs);
- my $volid = $rootinfo->{volume};
+ foreach_mountpoint($snap, sub {
+ my ($ms, $mountpoint) = @_;
- PVE::Storage::volume_rollback_is_possible($storecfg, $volid, $snapname);
+ PVE::Storage::volume_rollback_is_possible($storecfg, $mountpoint->{volume}, $snapname);
+ });
my $updatefn = sub {
@@ -2174,8 +2194,11 @@ sub snapshot_rollback {
lock_config($vmid, $updatefn);
- # only rootfs for now!
- PVE::Storage::volume_snapshot_rollback($storecfg, $volid, $snapname);
+ foreach_mountpoint($snap, sub {
+ my ($ms, $mountpoint) = @_;
+
+ PVE::Storage::volume_snapshot_rollback($storecfg, $mountpoint->{volume}, $snapname);
+ });
$prepare = 0;
lock_config($vmid, $updatefn);
diff --git a/src/PVE/VZDump/LXC.pm b/src/PVE/VZDump/LXC.pm
index 1d24036..7269ce8 100644
--- a/src/PVE/VZDump/LXC.pm
+++ b/src/PVE/VZDump/LXC.pm
@@ -104,13 +104,14 @@ sub prepare {
my $disks = $task->{disks} = [];
my $exclude_dirs = $task->{exclude_dirs} = [];
+ my $volids = $task->{volids} = [];
$task->{hostname} = $conf->{'hostname'} || "CT$vmid";
my ($id_map, $rootuid, $rootgid) = PVE::LXC::parse_id_maps($conf);
$task->{userns_cmd} = PVE::LXC::userns_command($id_map);
- my $volid_list = [];
+ my $volids = $task->{volids} = [];
PVE::LXC::foreach_mountpoint($conf, sub {
my ($name, $data) = @_;
my $volid = $data->{volume};
@@ -125,7 +126,7 @@ sub prepare {
}
push @$disks, $data;
- push @$volid_list, $volid
+ push @$volids, $volid
if $type eq 'volume';
});
@@ -146,12 +147,12 @@ sub prepare {
&$check_mountpoint_empty($rootdir);
# set snapshot_count (freezes CT if snapshot_count > 1)
- $task->{snapshot_count} = scalar(@$volid_list);
+ $task->{snapshot_count} = scalar(@$volids);
} elsif ($mode eq 'stop') {
my $rootdir = $default_mount_point;
mkpath $rootdir;
&$check_mountpoint_empty($rootdir);
- PVE::Storage::activate_volumes($storage_cfg, $volid_list);
+ PVE::Storage::activate_volumes($storage_cfg, $volids);
} elsif ($mode eq 'suspend') {
my $pid = PVE::LXC::find_lxc_pid($vmid);
foreach my $disk (@$disks) {
@@ -220,13 +221,12 @@ sub snapshot {
if !($conf->{snapshots} && $conf->{snapshots}->{vzdump});
my $disks = $task->{disks};
- #todo: reevaluate bind/dev mount handling when implementing snapshots for mps
- my $volid_list = [map { $_->{volume} } @$disks];
+ my $volids = $task->{volids};
my $rootdir = $default_mount_point;
my $storage_cfg = $self->{storecfg};
- PVE::Storage::activate_volumes($storage_cfg, $volid_list, 'vzdump');
+ PVE::Storage::activate_volumes($storage_cfg, $volids, 'vzdump');
foreach my $disk (@$disks) {
$disk->{dir} = "${rootdir}$disk->{mp}";
PVE::LXC::mountpoint_mount($disk, $rootdir, $storage_cfg, 'vzdump');
@@ -320,6 +320,12 @@ sub archive {
push @sources, ".$disk->{mp}";
}
$task->{snapdir} = $rootdir;
+ } elsif ($task->{mode} eq 'snapshot') {
+ # mounting the vzdump snapshots and setting $snapdir is already done,
+ # but we need to include all mountpoints here!
+ foreach my $disk (@$disks) {
+ push @sources, ".$disk->{mp}";
+ }
} else {
# the data was rsynced to a temporary location, only use '.' to avoid
# having mountpoints duplicated
--
2.1.4
More information about the pve-devel
mailing list