[pve-devel] [[PATCH_2 pve-container]] Add the functionality of full clone
Wolfgang Bumiller
w.bumiller at proxmox.com
Mon Apr 25 11:29:21 CEST 2016
On Wed, Apr 20, 2016 at 11:14:13AM +0200, Thomas Lamprecht wrote:
> some general comments inline:
>
> On 04/20/2016 08:06 AM, Wolfgang Link wrote:
> > ---
> > src/PVE/API2/LXC.pm | 21 +++++++++----------
> > src/PVE/LXC.pm | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 68 insertions(+), 11 deletions(-)
(...)
> > diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
> > index fe97d31..7c773bf 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;
Considering the datastructures we're dealing with, this seems a bit
overkill. Simply copying the first level and then replacing the keys we
want replaced should be enough.
See below for the replacements.
> > use Data::Dumper;
> >
> > @@ -1348,5 +1349,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
> > + my $tmp_mp = $mp->{mp};
> > + $mp->{mp} = '/';
We don't modify values, we only replace them, so it should be enough to
just copy the outer hash:
$mp = {%$mp}; # copy
$mp->{mp} = '/';
Then we don't need to pray that none of the non-eval{} parts of the code
die and leave the caller's object in a modified state.
>
> as I'm not that involved with mount points this may be a really stupid
> question, but what is that for?
> seems a little weird and the comment isn't helping me.
> A comment explaining why and not you're doing would be helpful, e.g. for
> an not mp involved Dev who needs to touch this.
mountpoint_mount() mounts to "$root/$mp" and we're using temporary
directories where the "$root" is empty, so there's no point in creating
the subdirectories
> > +
> > + my $new_mp = Storable::dclone($mp);
> > + $new_mp->{volume} = $new_volid;
Same:
my $new_mp = {%$mp}; # copy
$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]);
That \ is not necessary.
> > +
> > + };
> > + my $err = $@;
> > + eval { PVE::Tools::run_command(['/bin/umount', '-f', $src], errfunc => sub{})};
> > + warn "Can't umount $src\n" if $@;
> > + eval { PVE::Tools::run_command(['/bin/umount', '-f', $dest], errfunc => sub{})};
> > + warn "Can't umount $src\n" if $@;
> > +
> > + rmdir $dest;
> > + rmdir $src;
>
> if the previous umount fails those will also fail (rmdir works on empty
> directory only).
Valid point, but rmdir() doesn't die() and instead returns a boolean, so
this won't be an issue.
> Also is a force umount a good way, shouldn't be checked if the caches
> are all written (i.e. executing a fsync previously),
> or am I wrong?
-f only affects NFS and fuse, so here the real question is: do we want
to kill the NFS mount or just leave it up to the user/sysadmin to have a
working storage? I'd say -f here hides a different problem which IMO
needs to be addressed first, so not using it might indeed be better.
> > + rmdir $mount_dir;
> > +
> > + #set it back to orgin value
> s/orgin/original/
> > + $mp->{mp} = $tmp_mp;
With the suggested change this line can go.
> > +
> > + if ($err) {
> > + PVE::Storage::vdisk_free($storage_cfg, $new_volid);
> > + die $err;
> > + }
> > + return $new_volid;
> > +}
> >
> > 1;
More information about the pve-devel
mailing list