[pve-devel] [PATCHV3 pve-container 1/4] Add the functionality of full clone
Wolfgang Link
w.link at proxmox.com
Tue May 10 11:13:31 CEST 2016
---
src/PVE/API2/LXC.pm | 21 +++++++++----------
src/PVE/LXC.pm | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 11 deletions(-)
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 95932a9..0bcadc3 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1079,6 +1079,7 @@ __PACKAGE__->register_method({
my $storage = extract_param($param, 'storage');
+ die "Full clone requires a storage.\n"if $param->{full} && !$storage;
my $localnode = PVE::INotify::nodename();
my $storecfg = PVE::Storage::config();
@@ -1132,10 +1133,6 @@ __PACKAGE__->register_method({
if ($mp->{type} eq 'volume') {
my $volid = $mp->{volume};
if ($param->{full}) {
- die "fixme: full clone not implemented";
-
- die "Full clone feature for '$volid' is not available\n"
- if !PVE::Storage::volume_has_feature($storecfg, 'copy', $volid, $snapname, $running);
$fullclone->{$opt} = 1;
} else {
# not full means clone instead of copy
@@ -1182,18 +1179,20 @@ __PACKAGE__->register_method({
foreach my $opt (keys %$mountpoints) {
my $mp = $mountpoints->{$opt};
my $volid = $mp->{volume};
+ my $newvolid;
if ($fullclone->{$opt}) {
- die "fixme: full clone not implemented\n";
+ print "create full clone of mountpoint $opt ($volid)\n";
+ $newvolid = PVE::LXC::copy_volume($mp, $vmid, $newid, $storage, $storecfg, $conf);
} else {
print "create linked clone of mountpoint $opt ($volid)\n";
- my $newvolid = PVE::Storage::vdisk_clone($storecfg, $volid, $newid, $snapname);
- push @$newvollist, $newvolid;
- $mp->{volume} = $newvolid;
-
- $newconf->{$opt} = PVE::LXC::Config->print_ct_mountpoint($mp, $opt eq 'rootfs');
- PVE::LXC::Config->write_config($newid, $newconf);
+ $newvolid = PVE::Storage::vdisk_clone($storecfg, $volid, $newid, $snapname);
}
+ push @$newvollist, $newvolid;
+ $mp->{volume} = $newvolid;
+
+ $newconf->{$opt} = PVE::LXC::Config->print_ct_mountpoint($mp, $opt eq 'rootfs');
+ PVE::LXC::Config->write_config($newid, $newconf);
}
delete $newconf->{lock};
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index ea68b71..047b5d1 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -22,6 +22,7 @@ use PVE::AccessControl;
use PVE::ProcFSTools;
use PVE::LXC::Config;
use Time::HiRes qw (gettimeofday);
+use Storable;
use Data::Dumper;
@@ -1355,5 +1356,62 @@ sub userns_command {
return [];
}
+sub copy_volume {
+ my ($mp, $vmid, $newid, $storage, $storage_cfg, $conf) = @_;
+ my $mount_dir = "/tmp/$vmid";
+ my $dest = "$mount_dir\/dest";
+ my $src = "$mount_dir\/src";
+
+ my $new_format = $storage_cfg->{ids}->{$storage}->{type} eq "zfspool" ? 'subvol' : 'raw';
+
+ my $new_volid = PVE::Storage::vdisk_alloc($storage_cfg, $storage, $newid, $new_format, undef, $mp->{size}/1024);
+
+ #simplify mount struct. See mountpoint_mount().
+ my $tmp_mp = $mp->{mp};
+ $mp->{mp} = '/';
+
+ my $new_mp = Storable::dclone($mp);
+ $new_mp->{volume} = $new_volid;
+
+ #get id's for unprivileged container
+ my (undef, $rootuid, $rootgid) = parse_id_maps($conf);
+
+ my $path = PVE::Storage::path($storage_cfg, $new_volid, undef);
+
+ eval {
+ mkfs($path, $rootuid, $rootgid) if $new_format ne "subvol";
+
+ mkdir $mount_dir;
+ mkdir $dest;
+ mkdir $src;
+
+ #mount for copy mp
+ mountpoint_mount($mp, $src, $storage_cfg);
+ mountpoint_mount($new_mp, $dest, $storage_cfg);
+
+ PVE::Tools::run_command(['/usr/bin/rsync', '--stats', '-X', '-A', '--numeric-ids',
+ '--whole-file', '--inplace', '--one-file-system', '-aH',
+ "$src\/.", $dest]);
+
+ };
+ my $err = $@;
+ eval { PVE::Tools::run_command(['/bin/umount', '--lazy', $src], errfunc => sub{})};
+ warn "Can't umount $src\n" if $@;
+ eval { PVE::Tools::run_command(['/bin/umount', '--lazy', $dest], errfunc => sub{})};
+ warn "Can't umount $src\n" if $@;
+
+ rmdir $dest;
+ rmdir $src;
+ rmdir $mount_dir;
+
+ #set it back to orgin value
+ $mp->{mp} = $tmp_mp;
+
+ if ($err) {
+ PVE::Storage::vdisk_free($storage_cfg, $new_volid);
+ die $err;
+ }
+ return $new_volid;
+}
1;
--
2.1.4
More information about the pve-devel
mailing list