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({
}
};
my $code = sub {
my $ostemplate = extract_param($param, 'ostemplate');
my $basecfg_fn = PVE::OpenVZ::config_file($vmid);
my $archive;
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 $ostemplate = extract_param($param, 'ostemplate');
if ($ostemplate eq '-') {
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;
}
my $archive;
if (!defined($param->{searchdomain}) &&
!defined($param->{nameserver})) {
my $resolv = PVE::INotify::read_file('resolvconf');
if ($ostemplate eq '-') {
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;
}
$param->{searchdomain} = $resolv->{search} if $resolv->{search};
if (!defined($param->{searchdomain}) &&
!defined($param->{nameserver})) {
my $resolv = PVE::INotify::read_file('resolvconf');
my @ns = ();
push @ns, $resolv->{dns1} if $resolv->{dns1};
push @ns, $resolv->{dns2} if $resolv->{dns2};
push @ns, $resolv->{dns3} if $resolv->{dns3};
$param->{searchdomain} = $resolv->{search} if $resolv->{search};
$param->{nameserver} = join(' ', @ns) if scalar(@ns);
}
my @ns = ();
push @ns, $resolv->{dns1} if $resolv->{dns1};
push @ns, $resolv->{dns2} if $resolv->{dns2};
push @ns, $resolv->{dns3} if $resolv->{dns3};
my $basecfg_fn = PVE::OpenVZ::config_file($vmid);
$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);
......@@ -365,45 +370,45 @@ __PACKAGE__->register_method({
PVE::Cluster::check_cfs_quorum();
my $realcmd = sub {
if ($param->{restore}) {
&$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);
if ($param->{restore}) {
&$restore_openvz($private, $archive, $vmid, $param->{force});
# reload config
$conf = PVE::OpenVZ::load_config($vmid);
# is this really needed?
my $cmd = ['vzctl', '--skiplock', '--quiet', 'set', $vmid,
'--applyconfig_map', 'name', '--save'];
run_command($cmd);
# and initialize quota
my $disk_quota = $conf->{disk_quota}->{value};
if (!defined($disk_quota) || ($disk_quota != 0)) {
$cmd = ['vzctl', '--skiplock', 'quotainit', $vmid];
run_command($cmd);
}
# reload config
$conf = PVE::OpenVZ::load_config($vmid);
} else {
PVE::Tools::file_set_contents($basecfg_fn, $rawconf);
my $cmd = ['vzctl', '--skiplock', 'create', $vmid,
'--ostemplate', $archive, '--private', $private];
# and initialize quota
my $disk_quota = $conf->{disk_quota}->{value};
if (!defined($disk_quota) || ($disk_quota != 0)) {
$cmd = ['vzctl', '--skiplock', 'quotainit', $vmid];
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',
$vmid, $authuser, $realcmd);
PVE::AccessControl::lock_user_config($addVMtoPoolFn, "can't add VM to pool") if $pool;
};
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 = [
......@@ -473,7 +478,7 @@ __PACKAGE__->register_method({
run_command($cmd);
};
PVE::OpenVZ::lock_container($vmid, $code);
PVE::OpenVZ::lock_container($vmid, undef, $code);
return undef;
}});
......
......@@ -1157,16 +1157,18 @@ sub generate_raw_config {
}
sub create_lock_manager {
my ($max) = @_;
return LockFile::Simple->make(-format => '%f',
-autoclean => 1,
-max => 30,
-delay => 2,
-max => defined($max) ? $max : 60,
-delay => 1,
-stale => 1,
-nfs => 0);
}
sub lock_container {
my ($vmid, $code, @param) = @_;
my ($vmid, $max, $code, @param) = @_;
my $filename = $global_vzconf->{lockdir} . "/${vmid}.lck";
my $lock;
......@@ -1174,12 +1176,11 @@ sub lock_container {
eval {
my $lockmgr = create_lock_manager();
my $lockmgr = create_lock_manager($max);
$lock = $lockmgr->lock($filename) || die "can't lock container $vmid\n";
$res = &$code(@param);
};
my $err = $@;
......
......@@ -18,7 +18,7 @@ use base qw(PVE::AbstractMigrate);
sub lock_vm {
my ($self, $vmid, $code, @param) = @_;
return PVE::OpenVZ::lock_container($vmid, $code, @param);
return PVE::OpenVZ::lock_container($vmid, undef, $code, @param);
}
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