summaryrefslogtreecommitdiffstats
path: root/lib/puppet/configurer.rb
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2009-01-28 17:11:19 -0600
committerLuke Kanies <luke@madstop.com>2009-02-06 18:08:42 -0600
commitfc14b81f99adc9c9308a26d322adaa59a7b7716d (patch)
treedc731383d3195e37ea3658b9cbc7b0c428579d9f /lib/puppet/configurer.rb
parente8be6dcad2150769b51bf81e95c57491921e68c1 (diff)
downloadpuppet-fc14b81f99adc9c9308a26d322adaa59a7b7716d.tar.gz
puppet-fc14b81f99adc9c9308a26d322adaa59a7b7716d.tar.xz
puppet-fc14b81f99adc9c9308a26d322adaa59a7b7716d.zip
Splitting the Agent class into Agent and Configurer
Once I went to add runinterval support to the Agent class, I realized it's really two classes: One that handles starting, stopping, running, et al (still called Agent), and one that handles downloading the catalog, running it, etc. (now called Configurer). This commit includes some additional code, but 95% of it is just moving code around. Signed-off-by: Luke Kanies <luke@madstop.com>
Diffstat (limited to 'lib/puppet/configurer.rb')
-rw-r--r--lib/puppet/configurer.rb185
1 files changed, 185 insertions, 0 deletions
diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb
new file mode 100644
index 000000000..df531f494
--- /dev/null
+++ b/lib/puppet/configurer.rb
@@ -0,0 +1,185 @@
+# The client for interacting with the puppetmaster config server.
+require 'sync'
+require 'timeout'
+require 'puppet/network/http_pool'
+require 'puppet/util'
+
+class Puppet::Configurer
+ require 'puppet/configurer/fact_handler'
+ require 'puppet/configurer/plugin_handler'
+
+ include Puppet::Configurer::FactHandler
+ include Puppet::Configurer::PluginHandler
+
+ # For benchmarking
+ include Puppet::Util
+
+ attr_accessor :catalog
+ attr_reader :compile_time
+
+ # Provide more helpful strings to the logging that the Agent does
+ def self.to_s
+ "Puppet configuration client"
+ end
+
+ class << self
+ # Puppetd should only have one instance running, and we need a way
+ # to retrieve it.
+ attr_accessor :instance
+ include Puppet::Util
+ end
+
+ # How to lock instances of this class.
+ def self.lockfile_path
+ Puppet[:puppetdlockfile]
+ end
+
+ def clear
+ @catalog.clear(true) if @catalog
+ @catalog = nil
+ end
+
+ # Initialize and load storage
+ def dostorage
+ begin
+ Puppet::Util::Storage.load
+ @compile_time ||= Puppet::Util::Storage.cache(:configuration)[:compile_time]
+ rescue => detail
+ if Puppet[:trace]
+ puts detail.backtrace
+ end
+ Puppet.err "Corrupt state file %s: %s" % [Puppet[:statefile], detail]
+ begin
+ ::File.unlink(Puppet[:statefile])
+ retry
+ rescue => detail
+ raise Puppet::Error.new("Cannot remove %s: %s" %
+ [Puppet[:statefile], detail])
+ end
+ end
+ end
+
+ # Just so we can specify that we are "the" instance.
+ def initialize
+ Puppet.settings.use(:main, :ssl, :puppetd)
+
+ self.class.instance = self
+ @running = false
+ @splayed = false
+ end
+
+ # Prepare for catalog retrieval. Downloads everything necessary, etc.
+ def prepare
+ dostorage()
+
+ download_plugins()
+
+ download_fact_plugins()
+
+ upload_facts()
+ end
+
+ # Mark that we should restart. The Puppet module checks whether we're running,
+ # so this only gets called if we're in the middle of a run.
+ def restart
+ # If we're currently running, then just mark for later
+ Puppet.notice "Received signal to restart; waiting until run is complete"
+ @restart = true
+ end
+
+ # Should we restart?
+ def restart?
+ if defined? @restart
+ @restart
+ else
+ false
+ end
+ end
+
+ # Get the remote catalog, yo. Returns nil if no catalog can be found.
+ def retrieve_catalog
+ name = Facter.value("hostname")
+ catalog_class = Puppet::Resource::Catalog
+
+ # First try it with no cache, then with the cache.
+ result = nil
+ begin
+ duration = thinmark do
+ result = catalog_class.find(name, :use_cache => false)
+ end
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Could not retrieve catalog from remote server: %s" % detail
+ end
+
+ unless result
+ begin
+ duration = thinmark do
+ result = catalog_class.find(name, :use_cache => true)
+ end
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Could not retrieve catalog from cache: %s" % detail
+ end
+ end
+
+ return nil unless result
+
+ convert_catalog(result, duration)
+ end
+
+ # Convert a plain resource catalog into our full host catalog.
+ def convert_catalog(result, duration)
+ catalog = result.to_ral
+ catalog.retrieval_duration = duration
+ catalog.host_config = true
+ catalog.write_class_file
+ return catalog
+ end
+
+ # The code that actually runs the catalog.
+ # This just passes any options on to the catalog,
+ # which accepts :tags and :ignoreschedules.
+ def run(options = {})
+ unless catalog = retrieve_catalog
+ Puppet.err "Could not retrieve catalog; skipping run"
+ return
+ end
+
+ begin
+ benchmark(:notice, "Finished catalog run") do
+ catalog.apply(options)
+ end
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Failed to apply catalog: %s" % detail
+ end
+
+ # Now close all of our existing http connections, since there's no
+ # reason to leave them lying open.
+ Puppet::Network::HttpPool.clear_http_instances
+
+ # Did we get HUPped during the run? If so, then restart now that we're
+ # done with the run.
+ Process.kill(:HUP, $$) if self.restart?
+ end
+
+ private
+
+ def self.timeout
+ timeout = Puppet[:configtimeout]
+ case timeout
+ when String:
+ if timeout =~ /^\d+$/
+ timeout = Integer(timeout)
+ else
+ raise ArgumentError, "Configuration timeout must be an integer"
+ end
+ when Integer: # nothing
+ else
+ raise ArgumentError, "Configuration timeout must be an integer"
+ end
+
+ return timeout
+ end
+end