diff options
Diffstat (limited to 'lib/puppet/client/master.rb')
-rw-r--r-- | lib/puppet/client/master.rb | 86 |
1 files changed, 67 insertions, 19 deletions
diff --git a/lib/puppet/client/master.rb b/lib/puppet/client/master.rb index 1da921aa4..d3e7d2e8a 100644 --- a/lib/puppet/client/master.rb +++ b/lib/puppet/client/master.rb @@ -1,5 +1,9 @@ # The client for interacting with the puppetmaster config server. +require 'sync' + class Puppet::Client::MasterClient < Puppet::Client + @@sync = Sync.new + Puppet.setdefaults("puppetd", :puppetdlockfile => [ "$statedir/puppetdlock", "A lock file to temporarily stop puppetd from doing anything."], @@ -95,15 +99,19 @@ class Puppet::Client::MasterClient < Puppet::Client @cachefile end - # Disable running the configuration. - def disable - Puppet.notice "Disabling puppetd" + # Disable running the configuration. This can be used from the command line, but + # is also used to make sure only one client is running at a time. + def disable(running = false) + text = nil + if running + text = Process.pid + else + text = "" + Puppet.notice "Disabling puppetd" + end Puppet.config.use(:puppet) - #unless FileTest.exists? File.dirname(Puppet[:puppetdlockfile]) - # Puppet.recmkdir(File.dirname(Puppet[:puppetdlockfile])) - #end begin - File.open(Puppet[:puppetdlockfile], "w") { |f| f.puts ""; f.flush } + File.open(Puppet[:puppetdlockfile], "w") { |f| f.puts text } rescue => detail raise Puppet::Error, "Could not lock puppetd: %s" % detail end @@ -126,9 +134,12 @@ class Puppet::Client::MasterClient < Puppet::Client end end - # Enable running again. - def enable - Puppet.notice "Enabling puppetd" + # Enable running again. This can be used from the command line, but + # is also used to make sure only one client is running at a time. + def enable(running = false) + unless running + Puppet.notice "Enabling puppetd" + end if FileTest.exists? Puppet[:puppetdlockfile] File.unlink(Puppet[:puppetdlockfile]) end @@ -259,6 +270,37 @@ class Puppet::Client::MasterClient < Puppet::Client return @objects end + # Make sure only one client runs at a time, and make sure only one thread + # runs at a time. However, this does not lock local clients -- you could have + # as many separate puppet scripts running as you want. + def lock + if @local + yield + else + @@sync.synchronize(Sync::EX) do + disable(true) + begin + yield + ensure + enable(true) + end + end + end + end + + def locked? + if FileTest.exists? Puppet[:puppetdlockfile] + text = File.read(Puppet[:puppetdlockfile]).chomp + if text =~ /\d+/ + return text + else + return true + end + else + return false + end + end + # Retrieve the cached config def retrievecache if FileTest.exists?(self.cachefile) @@ -270,18 +312,24 @@ class Puppet::Client::MasterClient < Puppet::Client # The code that actually runs the configuration. def run - if FileTest.exists? Puppet[:puppetdlockfile] - Puppet.notice "%s exists; skipping configuration run" % + if pid = locked? + t = "" + if pid == true + PUppet.notice "Locked by process %s" % pid + end + Puppet.notice "Lock file %s exists; skipping configuration run" % Puppet[:puppetdlockfile] else - self.getconfig + lock do + self.getconfig - if defined? @objects and @objects - unless @local - Puppet.notice "Starting configuration run" - end - benchmark(:notice, "Finished configuration run") do - self.apply + if defined? @objects and @objects + unless @local + Puppet.notice "Starting configuration run" + end + benchmark(:notice, "Finished configuration run") do + self.apply + end end end end |