diff options
author | danielsdeleo <dan@opscode.com> | 2012-08-23 15:36:04 -0700 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2012-08-23 15:36:04 -0700 |
commit | 4bfaf9269f96fef21608a8b66e5ae2b14cfdccb4 (patch) | |
tree | f3471956f8a38abf2ae76aa08383225bfe89de11 | |
parent | e75192fc8e4594b9169c155a3f9b002d9b1274a3 (diff) | |
download | chef-4bfaf9269f96fef21608a8b66e5ae2b14cfdccb4.tar.gz |
[CHEF-867] move RunLock code out to its own file
-rw-r--r-- | chef/lib/chef/client.rb | 44 | ||||
-rw-r--r-- | chef/lib/chef/run_lock.rb | 62 | ||||
-rw-r--r-- | chef/spec/functional/run_lock_spec.rb | 6 | ||||
-rw-r--r-- | chef/spec/unit/client_spec.rb | 4 | ||||
-rw-r--r-- | chef/spec/unit/run_lock_spec.rb | 6 |
5 files changed, 71 insertions, 51 deletions
diff --git a/chef/lib/chef/client.rb b/chef/lib/chef/client.rb index f3f4e3ce8b..8538507f37 100644 --- a/chef/lib/chef/client.rb +++ b/chef/lib/chef/client.rb @@ -41,6 +41,7 @@ require 'chef/formatters/doc' require 'chef/formatters/minimal' require 'chef/version' require 'chef/resource_reporter' +require 'chef/run_lock' require 'ohai' require 'rbconfig' @@ -384,49 +385,6 @@ class Chef raise end - class RunLock - attr_reader :runlock - attr_reader :runlock_file - - # TODO: add lockfile config option to chef/config.rb - def initialize(config) - @runlock_file = config[:lockfile] || "#{config[:file_cache_path]}/chef-client-running.pid" - @runlock = nil - end - - def acquire - @runlock = File.open(runlock_file,'w+') - unless runlock.flock(File::LOCK_EX|File::LOCK_NB) - # Another chef client running... - runpid = runlock.read.strip.chomp - Chef::Log.info("Chef client #{runpid} is running, will wait for it to finish and then run.") - runlock.flock(File::LOCK_EX) - end - # We grabbed the run lock. Save the pid. - runlock.truncate(0) - runlock.rewind # truncate doesn't reset position to 0. - runlock.write(Process.pid.to_s) - end - - def release - if runlock - runlock.flock(File::LOCK_UN) - runlock.close - # Don't unlink the pid file, if another chef-client was waiting, it - # won't be recreated. Better to leave a "dead" pid file than not have - # it available if you need to break the lock. - reset - end - end - - private - - def reset - @runlock = nil - end - - end - private # Do a full run for this Chef::Client. Calls: diff --git a/chef/lib/chef/run_lock.rb b/chef/lib/chef/run_lock.rb new file mode 100644 index 0000000000..eb0857e252 --- /dev/null +++ b/chef/lib/chef/run_lock.rb @@ -0,0 +1,62 @@ +# +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2012 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +class Chef + class RunLock + attr_reader :runlock + attr_reader :runlock_file + + # TODO: add lockfile config option to chef/config.rb + def initialize(config) + @runlock_file = config[:lockfile] || "#{config[:file_cache_path]}/chef-client-running.pid" + @runlock = nil + end + + def acquire + @runlock = File.open(runlock_file,'w+') + unless runlock.flock(File::LOCK_EX|File::LOCK_NB) + # Another chef client running... + runpid = runlock.read.strip.chomp + Chef::Log.info("Chef client #{runpid} is running, will wait for it to finish and then run.") + runlock.flock(File::LOCK_EX) + end + # We grabbed the run lock. Save the pid. + runlock.truncate(0) + runlock.rewind # truncate doesn't reset position to 0. + runlock.write(Process.pid.to_s) + end + + def release + if runlock + runlock.flock(File::LOCK_UN) + runlock.close + # Don't unlink the pid file, if another chef-client was waiting, it + # won't be recreated. Better to leave a "dead" pid file than not have + # it available if you need to break the lock. + reset + end + end + + private + + def reset + @runlock = nil + end + + end +end + diff --git a/chef/spec/functional/run_lock_spec.rb b/chef/spec/functional/run_lock_spec.rb index 04b9d02d60..9ef409aa70 100644 --- a/chef/spec/functional/run_lock_spec.rb +++ b/chef/spec/functional/run_lock_spec.rb @@ -18,13 +18,13 @@ require File.expand_path('../../spec_helper', __FILE__) require 'chef/client' -describe Chef::Client::RunLock do +describe Chef::RunLock do # This behavior is believed to work on windows, but the tests use UNIX APIs. describe "when locking the chef-client run", :unix_only => true do it "allows only one chef client run per lockfile" do read, write = IO.pipe - run_lock = Chef::Client::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") + run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") p1 = fork do run_lock.acquire write.puts 1 @@ -54,7 +54,7 @@ describe Chef::Client::RunLock do it "clears the lock if the process dies unexpectedly" do read, write = IO.pipe - run_lock = Chef::Client::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") + run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") p1 = fork do run_lock.acquire write.puts 1 diff --git a/chef/spec/unit/client_spec.rb b/chef/spec/unit/client_spec.rb index fa657a8fb7..2182bd654f 100644 --- a/chef/spec/unit/client_spec.rb +++ b/chef/spec/unit/client_spec.rb @@ -124,8 +124,8 @@ shared_examples_for Chef::Client do Chef::REST.should_receive(:new).with(Chef::Config[:chef_server_url]).and_return(mock_chef_rest_for_node_save) mock_chef_rest_for_node_save.should_receive(:put_rest).with("nodes/#{@fqdn}", @node).and_return(true) - Chef::Client::RunLock.any_instance.should_receive(:acquire) - Chef::Client::RunLock.any_instance.should_receive(:release) + Chef::RunLock.any_instance.should_receive(:acquire) + Chef::RunLock.any_instance.should_receive(:release) # Post conditions: check that node has been filled in correctly @client.should_receive(:run_started) diff --git a/chef/spec/unit/run_lock_spec.rb b/chef/spec/unit/run_lock_spec.rb index 191c13d1dc..4e62b110b9 100644 --- a/chef/spec/unit/run_lock_spec.rb +++ b/chef/spec/unit/run_lock_spec.rb @@ -18,16 +18,16 @@ require File.expand_path('../../spec_helper', __FILE__) require 'chef/client' -describe Chef::Client::RunLock do +describe Chef::RunLock do describe "when first created" do it "locates the lockfile in the file cache path by default" do - run_lock = Chef::Client::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => nil) + run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => nil) run_lock.runlock_file.should == "/var/chef/cache/chef-client-running.pid" end it "locates the lockfile in the user-configured path when set" do - run_lock = Chef::Client::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") + run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") run_lock.runlock_file.should == "/tmp/chef-client-running.pid" end end |