[pve-devel] [PATCH 1/2] Add the functionality of full clone
Wolfgang Link
w.link at proxmox.com
Thu Apr 14 17:38:59 CEST 2016
---
src/PVE/API2/LXC.pm | 21 ++++++++++-----------
src/PVE/LXC.pm | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 90cdba6..e64ee17 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1073,6 +1073,7 @@ __PACKAGE__->register_method({
my $storage = extract_param($param, 'storage');
+ die "Full clone require a storage.\n"if $param->{full} && !$storage;
my $localnode = PVE::INotify::nodename();
my $storecfg = PVE::Storage::config();
@@ -1126,10 +1127,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
@@ -1176,18 +1173,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::clone_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 fe97d31..b51f5a0 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1348,5 +1348,54 @@ sub userns_command {
return [];
}
+sub clone_volume {
+ my ($mp, $vmid, $newid, $storage, $storage_cfg, $conf, $sanpshot) = @_;
+ my $dir = "/tmp/$vmid";
+ my $dest = "$dir\/dest";
+ my $src = "$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);
+
+ $mp->{mp} =~ s!.*$/!!;
+ my $new_mp = PVE::LXC::Config->parse_ct_rootfs($new_volid);
+ 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 $dir;
+ mkdir $dest;
+ mkdir $src;
+
+ 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$mp->{mp}\/.", $dest.$new_mp->{mp}]);
+
+ };
+ my $err = $@;
+ eval { PVE::Tools::run_command(['/bin/umount', '-f', $src.$mp->{mp}], errfunc => sub{})};
+ warn "Can't umount $src.$mp->{mp}\n" if $@;
+ eval { PVE::Tools::run_command(['/bin/umount', '-f', $dest.$new_mp->{mp}], errfunc => sub{})};
+ warn "Can't umount $src.$new_mp->{mp}\n" if $@;
+
+ rmdir $src.$mp->{mp};
+ rmdir $dest.$new_mp->{mp};
+ rmdir $dest;
+ rmdir $src;
+ rmdir $dir;
+
+ 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