[pve-devel] [PATCH v2 container 1/2] Use lock_container when checking locks

Fabian Grünbichler f.gruenbichler at proxmox.com
Tue Jan 19 13:47:23 CET 2016


This should prevent race conditions by preventing config
file changes inbetween checking locks and actually doing
the start/stop/.. operation.

Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
---
 src/PVE/API2/LXC/Status.pm | 130 +++++++++++++++++++++++++--------------------
 1 file changed, 72 insertions(+), 58 deletions(-)

diff --git a/src/PVE/API2/LXC/Status.pm b/src/PVE/API2/LXC/Status.pm
index 6b468cf..a94bffa 100644
--- a/src/PVE/API2/LXC/Status.pm
+++ b/src/PVE/API2/LXC/Status.pm
@@ -151,30 +151,34 @@ __PACKAGE__->register_method({
 
 	} else {
 
-	    my $realcmd = sub {
-		my $upid = shift;
+	    my $lockcmd = sub {
+		my $realcmd = sub {
+		    my $upid = shift;
 
-		syslog('info', "starting CT $vmid: $upid\n");
+		    syslog('info', "starting CT $vmid: $upid\n");
 
-		my $conf = PVE::LXC::load_config($vmid);
+		    my $conf = PVE::LXC::load_config($vmid);
 
-		die "you can't start a CT if it's a template\n"
-		    if PVE::LXC::is_template($conf);
+		    die "you can't start a CT if it's a template\n"
+			if PVE::LXC::is_template($conf);
 
-		PVE::LXC::check_lock($conf);
+		    PVE::LXC::check_lock($conf);
 
-		my $storage_cfg = cfs_read_file("storage.cfg");
+		    my $storage_cfg = cfs_read_file("storage.cfg");
 
-		PVE::LXC::update_lxc_config($storage_cfg, $vmid, $conf);
+		    PVE::LXC::update_lxc_config($storage_cfg, $vmid, $conf);
 
-		my $cmd = ['lxc-start', '-n', $vmid];
+		    my $cmd = ['lxc-start', '-n', $vmid];
 
-		run_command($cmd);
+		    run_command($cmd);
 
-		return;
+		    return;
+		};
+
+		return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
 	    };
 
-	    return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
+	    return PVE::LXC::lock_container($vmid, 10, $lockcmd);
 	}
     }});
 
@@ -231,23 +235,27 @@ __PACKAGE__->register_method({
 
 	} else {
 
-	    my $realcmd = sub {
-		my $upid = shift;
+	    my $lockcmd = sub {
+		my $realcmd = sub {
+		    my $upid = shift;
 
-		syslog('info', "stopping CT $vmid: $upid\n");
+		    syslog('info', "stopping CT $vmid: $upid\n");
 
-		my $conf = PVE::LXC::load_config($vmid);
+		    my $conf = PVE::LXC::load_config($vmid);
 
-		PVE::LXC::check_lock($conf);
+		    PVE::LXC::check_lock($conf);
 
-		my $cmd = ['lxc-stop', '-n', $vmid, '--kill'];
+		    my $cmd = ['lxc-stop', '-n', $vmid, '--kill'];
 
-		run_command($cmd);
+		    run_command($cmd);
 
-		return;
+		    return;
+		};
+
+		return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
 	    };
 
-	    return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
+	    return PVE::LXC::lock_container($vmid, 10, $lockcmd);
 	}
     }});
 
@@ -299,45 +307,48 @@ __PACKAGE__->register_method({
 
 	die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
 
-	my $realcmd = sub {
-	    my $upid = shift;
+	my $lockcmd = sub {
+	    my $realcmd = sub {
+		my $upid = shift;
+
+		syslog('info', "shutdown CT $vmid: $upid\n");
 
-	    syslog('info', "shutdown CT $vmid: $upid\n");
+		my $cmd = ['lxc-stop', '-n', $vmid];
 
-	    my $cmd = ['lxc-stop', '-n', $vmid];
+		$timeout = 60 if !defined($timeout);
 
-	    $timeout = 60 if !defined($timeout);
+		my $conf = PVE::LXC::load_config($vmid);
 
-	    my $conf = PVE::LXC::load_config($vmid);
+		PVE::LXC::check_lock($conf);
 
-	    PVE::LXC::check_lock($conf);
+		my $storage_cfg = PVE::Storage::config();
 
-	    my $storage_cfg = PVE::Storage::config();
+		push @$cmd, '--timeout', $timeout;
 
-	    push @$cmd, '--timeout', $timeout;
+		eval { run_command($cmd, timeout => $timeout+5); };
+		my $err = $@;
+		if ($err && $param->{forceStop}) {
+		    $err = undef;
+		    warn "shutdown failed - forcing stop now\n";
 
-	    eval { run_command($cmd, timeout => $timeout+5); };
-	    my $err = $@;
-	    if ($err && $param->{forceStop}) {
-		$err = undef;
-		warn "shutdown failed - forcing stop now\n";
+		    my $cmd = ['lxc-stop', '-n', $vmid, '--kill'];
+		    run_command($cmd);
+		}
 
-		my $cmd = ['lxc-stop', '-n', $vmid, '--kill'];
+		# make sure container is stopped
+		$cmd = ['lxc-wait',  '-n', $vmid, '-t', 5, '-s', 'STOPPED'];
 		run_command($cmd);
-	    }
+		$err = $@;
 
-	    # make sure container is stopped
-	    $cmd = ['lxc-wait',  '-n', $vmid, '-t', 5, '-s', 'STOPPED'];
-	    run_command($cmd);
-	    
-	    die $err if $err;
+		die $err if $err;
 
-	    return;
-	};
+		return;
+	    };
 
-	my $upid = $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
+	    return $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
+	};
 
-	return $upid;
+	return PVE::LXC::lock_container($vmid, 10, $lockcmd);
     }});
 
 __PACKAGE__->register_method({
@@ -373,24 +384,27 @@ __PACKAGE__->register_method({
 
         die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
 
-        my $realcmd = sub {
-            my $upid = shift;
+	my $lockcmd = sub {
+	    my $realcmd = sub {
+		my $upid = shift;
+
+		syslog('info', "suspend CT $vmid: $upid\n");
 
-            syslog('info', "suspend CT $vmid: $upid\n");
+		my $conf = PVE::LXC::load_config($vmid);
 
-	    my $conf = PVE::LXC::load_config($vmid);
+		PVE::LXC::check_lock($conf);
 
-	    PVE::LXC::check_lock($conf);
-	    my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/lib/vz/dump'];
+		my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/lib/vz/dump'];
 
-	    run_command($cmd);
+		run_command($cmd);
 
-            return;
-        };
+		return;
+	    };
 
-        my $upid = $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
+	    return $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
+	};
 
-        return $upid;
+	return PVE::LXC::lock_container($vmid, 10, $lockcmd);
     }});
 
 __PACKAGE__->register_method({
-- 
2.1.4





More information about the pve-devel mailing list