From: Fabian Grünbichler Date: Wed, 24 Feb 2016 11:28:34 +0000 (+0100) Subject: Add mp support to snapshots X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=5040d81c713e8dce4adbe91ecc079dc0beeb964f;p=pve-container.git Add mp support to snapshots Modelled after QemuServer's way of handling multiple drives. --- 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