Commit 6800ed38 authored by Dietmar Maurer's avatar Dietmar Maurer

fix container locking (avoid multiple restore processes)

Unlike flock, LockFile::Simple does not inherit locks to child process.
So we need to do the locking inside the child process.
parent 945563d9
...@@ -319,45 +319,50 @@ __PACKAGE__->register_method({ ...@@ -319,45 +319,50 @@ __PACKAGE__->register_method({
} }
}; };
my $code = sub { my $ostemplate = extract_param($param, 'ostemplate');
my $basecfg_fn = PVE::OpenVZ::config_file($vmid); my $archive;
if ($param->{force}) { if ($ostemplate eq '-') {
die "cant overwrite mounted container\n" if PVE::OpenVZ::check_mounted($conf, $vmid); die "pipe requires cli environment\n"
} else { if $rpcenv->{type} ne 'cli';
die "CT $vmid already exists\n" if -f $basecfg_fn; die "pipe can only be used with restore tasks\n"
} if !$param->{restore};
$archive = '-';
my $ostemplate = extract_param($param, 'ostemplate'); } else {
$archive = $rpcenv->check_volume_access($authuser, $storage_cfg, $vmid, $ostemplate);
die "can't find file '$archive'\n" if ! -f $archive;
}
my $archive; if (!defined($param->{searchdomain}) &&
!defined($param->{nameserver})) {
my $resolv = PVE::INotify::read_file('resolvconf');
if ($ostemplate eq '-') { $param->{searchdomain} = $resolv->{search} if $resolv->{search};
die "pipe requires cli environment\n"
if $rpcenv->{type} ne 'cli';
die "pipe can only be used with restore tasks\n"
if !$param->{restore};
$archive = '-';
} else {
$archive = $rpcenv->check_volume_access($authuser, $storage_cfg, $vmid, $ostemplate);
die "can't find file '$archive'\n" if ! -f $archive;
}
if (!defined($param->{searchdomain}) && my @ns = ();
!defined($param->{nameserver})) { push @ns, $resolv->{dns1} if $resolv->{dns1};
push @ns, $resolv->{dns2} if $resolv->{dns2};
my $resolv = PVE::INotify::read_file('resolvconf'); push @ns, $resolv->{dns3} if $resolv->{dns3};
$param->{searchdomain} = $resolv->{search} if $resolv->{search}; $param->{nameserver} = join(' ', @ns) if scalar(@ns);
}
my @ns = (); my $basecfg_fn = PVE::OpenVZ::config_file($vmid);
push @ns, $resolv->{dns1} if $resolv->{dns1};
push @ns, $resolv->{dns2} if $resolv->{dns2};
push @ns, $resolv->{dns3} if $resolv->{dns3};
$param->{nameserver} = join(' ', @ns) if scalar(@ns); my $check_vmid_usage = sub {
if ($param->{force}) {
die "cant overwrite mounted container\n"
if PVE::OpenVZ::check_mounted($conf, $vmid);
} else {
die "CT $vmid already exists\n" if -f $basecfg_fn;
} }
};
my $code = sub {
&$check_vmid_usage(); # final check after locking
PVE::OpenVZ::update_ovz_config($vmid, $conf, $param); PVE::OpenVZ::update_ovz_config($vmid, $conf, $param);
...@@ -365,45 +370,45 @@ __PACKAGE__->register_method({ ...@@ -365,45 +370,45 @@ __PACKAGE__->register_method({
PVE::Cluster::check_cfs_quorum(); PVE::Cluster::check_cfs_quorum();
my $realcmd = sub { if ($param->{restore}) {
if ($param->{restore}) { &$restore_openvz($private, $archive, $vmid, $param->{force});
&$restore_openvz($private, $archive, $vmid, $param->{force});
# is this really needed?
my $cmd = ['vzctl', '--skiplock', '--quiet', 'set', $vmid,
'--applyconfig_map', 'name', '--save'];
run_command($cmd);
# reload config # is this really needed?
$conf = PVE::OpenVZ::load_config($vmid); my $cmd = ['vzctl', '--skiplock', '--quiet', 'set', $vmid,
'--applyconfig_map', 'name', '--save'];
run_command($cmd);
# and initialize quota # reload config
my $disk_quota = $conf->{disk_quota}->{value}; $conf = PVE::OpenVZ::load_config($vmid);
if (!defined($disk_quota) || ($disk_quota != 0)) {
$cmd = ['vzctl', '--skiplock', 'quotainit', $vmid];
run_command($cmd);
}
} else { # and initialize quota
PVE::Tools::file_set_contents($basecfg_fn, $rawconf); my $disk_quota = $conf->{disk_quota}->{value};
my $cmd = ['vzctl', '--skiplock', 'create', $vmid, if (!defined($disk_quota) || ($disk_quota != 0)) {
'--ostemplate', $archive, '--private', $private]; $cmd = ['vzctl', '--skiplock', 'quotainit', $vmid];
run_command($cmd); run_command($cmd);
# hack: vzctl '--userpasswd' starts the CT, but we want
# to avoid that for create
PVE::OpenVZ::set_rootpasswd($private, $password)
if defined($password);
} }
PVE::AccessControl::lock_user_config($addVMtoPoolFn, "can't add VM to pool") if $pool; } else {
}; PVE::Tools::file_set_contents($basecfg_fn, $rawconf);
my $cmd = ['vzctl', '--skiplock', 'create', $vmid,
'--ostemplate', $archive, '--private', $private];
run_command($cmd);
# hack: vzctl '--userpasswd' starts the CT, but we want
# to avoid that for create
PVE::OpenVZ::set_rootpasswd($private, $password)
if defined($password);
}
return $rpcenv->fork_worker($param->{restore} ? 'vzrestore' : 'vzcreate', PVE::AccessControl::lock_user_config($addVMtoPoolFn, "can't add VM to pool") if $pool;
$vmid, $authuser, $realcmd);
}; };
return PVE::OpenVZ::lock_container($vmid, $code); my $realcmd = sub { PVE::OpenVZ::lock_container($vmid, 1, $code); };
&$check_vmid_usage(); # first check before locking
return $rpcenv->fork_worker($param->{restore} ? 'vzrestore' : 'vzcreate',
$vmid, $authuser, $realcmd);
}}); }});
my $vm_config_perm_list = [ my $vm_config_perm_list = [
...@@ -473,7 +478,7 @@ __PACKAGE__->register_method({ ...@@ -473,7 +478,7 @@ __PACKAGE__->register_method({
run_command($cmd); run_command($cmd);
}; };
PVE::OpenVZ::lock_container($vmid, $code); PVE::OpenVZ::lock_container($vmid, undef, $code);
return undef; return undef;
}}); }});
......
...@@ -1157,16 +1157,18 @@ sub generate_raw_config { ...@@ -1157,16 +1157,18 @@ sub generate_raw_config {
} }
sub create_lock_manager { sub create_lock_manager {
my ($max) = @_;
return LockFile::Simple->make(-format => '%f', return LockFile::Simple->make(-format => '%f',
-autoclean => 1, -autoclean => 1,
-max => 30, -max => defined($max) ? $max : 60,
-delay => 2, -delay => 1,
-stale => 1, -stale => 1,
-nfs => 0); -nfs => 0);
} }
sub lock_container { sub lock_container {
my ($vmid, $code, @param) = @_; my ($vmid, $max, $code, @param) = @_;
my $filename = $global_vzconf->{lockdir} . "/${vmid}.lck"; my $filename = $global_vzconf->{lockdir} . "/${vmid}.lck";
my $lock; my $lock;
...@@ -1174,12 +1176,11 @@ sub lock_container { ...@@ -1174,12 +1176,11 @@ sub lock_container {
eval { eval {
my $lockmgr = create_lock_manager(); my $lockmgr = create_lock_manager($max);
$lock = $lockmgr->lock($filename) || die "can't lock container $vmid\n"; $lock = $lockmgr->lock($filename) || die "can't lock container $vmid\n";
$res = &$code(@param); $res = &$code(@param);
}; };
my $err = $@; my $err = $@;
......
...@@ -18,7 +18,7 @@ use base qw(PVE::AbstractMigrate); ...@@ -18,7 +18,7 @@ use base qw(PVE::AbstractMigrate);
sub lock_vm { sub lock_vm {
my ($self, $vmid, $code, @param) = @_; my ($self, $vmid, $code, @param) = @_;
return PVE::OpenVZ::lock_container($vmid, $code, @param); return PVE::OpenVZ::lock_container($vmid, undef, $code, @param);
} }
sub prepare { sub prepare {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment