diff options
| author | Luke Kanies <luke@madstop.com> | 2009-01-19 17:25:50 -0600 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2009-02-06 18:08:40 -0600 |
| commit | 37692e5851dd3f7b15bde1caf785fb7801c97a25 (patch) | |
| tree | 6db0d82fc4509805c8af4a3d2f34fafd708b39e7 /lib/puppet/network | |
| parent | 15d8768c5050a0c409b88fcabe38e05f30ee9a78 (diff) | |
| download | puppet-37692e5851dd3f7b15bde1caf785fb7801c97a25.tar.gz puppet-37692e5851dd3f7b15bde1caf785fb7801c97a25.tar.xz puppet-37692e5851dd3f7b15bde1caf785fb7801c97a25.zip | |
Renmaing Puppet::Network::Client::Master to Puppet::Agent
Made minor changes, including removing the parent class.
The functionality hasn't changed yet -- that comes in later patches --
but all but a couple of the older tests pass.
Signed-off-by: Luke Kanies <luke@madstop.com>
Diffstat (limited to 'lib/puppet/network')
| -rw-r--r-- | lib/puppet/network/client/master.rb | 523 |
1 files changed, 0 insertions, 523 deletions
diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb deleted file mode 100644 index 047f2b82a..000000000 --- a/lib/puppet/network/client/master.rb +++ /dev/null @@ -1,523 +0,0 @@ -# The client for interacting with the puppetmaster config server. -require 'sync' -require 'timeout' -require 'puppet/network/http_pool' - -class Puppet::Network::Client::Master < Puppet::Network::Client - unless defined? @@sync - @@sync = Sync.new - end - - attr_accessor :catalog - attr_reader :compile_time - - class << self - # Puppetd should only have one instance running, and we need a way - # to retrieve it. - attr_accessor :instance - include Puppet::Util - end - - def self.facts - # Retrieve the facts from the central server. - if Puppet[:factsync] - self.getfacts() - end - - down = Puppet[:downcasefacts] - - Facter.clear - - # Reload everything. - if Facter.respond_to? :loadfacts - Facter.loadfacts - elsif Facter.respond_to? :load - Facter.load - else - Puppet.warning "You should upgrade your version of Facter to at least 1.3.8" - end - - # This loads all existing facts and any new ones. We have to remove and - # reload because there's no way to unload specific facts. - loadfacts() - facts = Facter.to_hash.inject({}) do |newhash, array| - name, fact = array - if down - newhash[name] = fact.to_s.downcase - else - newhash[name] = fact.to_s - end - newhash - end - - # Add our client version to the list of facts, so people can use it - # in their manifests - facts["clientversion"] = Puppet.version.to_s - - # And add our environment as a fact. - unless facts.include?("environment") - facts["environment"] = Puppet[:environment] - end - - facts - end - - # Return the list of dynamic facts as an array of symbols - # NOTE:LAK(2008/04/10): This code is currently unused, since we now always - # recompile. - def self.dynamic_facts - # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] - x = Puppet.settings[:dynamicfacts].split(/\s*,\s*/).collect { |fact| fact.downcase } - end - - # Cache the config - def cache(text) - Puppet.info "Caching catalog at %s" % self.cachefile - confdir = ::File.dirname(Puppet[:localconfig]) - ::File.open(self.cachefile + ".tmp", "w", 0660) { |f| - f.print text - } - ::File.rename(self.cachefile + ".tmp", self.cachefile) - end - - def cachefile - unless defined? @cachefile - @cachefile = Puppet[:localconfig] + ".yaml" - end - @cachefile - 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 - - # Let the daemon run again, freely in the filesystem. Frolick, little - # daemon! - def enable - lockfile.unlock(:anonymous => true) - end - - # Stop the daemon from making any catalog runs. - def disable - lockfile.lock(:anonymous => true) - end - - # Retrieve the config from a remote server. If this fails, then - # use the cached copy. - def getconfig - dostorage() - - # Retrieve the plugins. - getplugins() if Puppet[:pluginsync] - - facts = nil - Puppet::Util.benchmark(:debug, "Retrieved facts") do - facts = self.class.facts - end - - raise Puppet::Network::ClientError.new("Could not retrieve any facts") unless facts.length > 0 - - Puppet.debug("Retrieving catalog") - - # If we can't retrieve the catalog, just return, which will either - # fail, or use the in-memory catalog. - unless marshalled_objects = get_actual_config(facts) - use_cached_config(true) - return - end - - begin - case Puppet[:catalog_format] - when "marshal": objects = Marshal.load(marshalled_objects) - when "yaml": objects = YAML.load(marshalled_objects) - else - raise "Invalid catalog format '%s'" % Puppet[:catalog_format] - end - rescue => detail - msg = "Configuration could not be translated from %s" % Puppet[:catalog_format] - msg += "; using cached catalog" if use_cached_config(true) - Puppet.warning msg - return - end - - self.setclasses(objects.classes) - - # Clear all existing objects, so we can recreate our stack. - clear() if self.catalog - - # Now convert the objects to a puppet catalog graph. - begin - @catalog = objects.to_catalog - rescue => detail - clear() - puts detail.backtrace if Puppet[:trace] - msg = "Configuration could not be instantiated: %s" % detail - msg += "; using cached catalog" if use_cached_config(true) - Puppet.warning msg - return - end - - if ! @catalog.from_cache - self.cache(marshalled_objects) - end - - # Keep the state database up to date. - @catalog.host_config = true - end - - # A simple proxy method, so it's easy to test. - def getplugins - self.class.getplugins - end - - # Just so we can specify that we are "the" instance. - def initialize(*args) - Puppet.settings.use(:main, :ssl, :puppetd) - super - - self.class.instance = self - @running = false - @splayed = false - 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 - - # Retrieve the cached config - def retrievecache - if FileTest.exists?(self.cachefile) - return ::File.read(self.cachefile) - else - return nil - end - 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 = {}) - got_lock = false - splay - Puppet::Util.sync(:puppetrun).synchronize(Sync::EX) do - if !lockfile.lock - Puppet.notice "Lock file %s exists; skipping catalog run" % - lockfile.lockfile - else - got_lock = true - begin - duration = thinmark do - self.getconfig - end - rescue => detail - puts detail.backtrace if Puppet[:trace] - Puppet.err "Could not retrieve catalog: %s" % detail - end - - if self.catalog - @catalog.retrieval_duration = duration - Puppet.notice "Starting catalog run" unless @local - benchmark(:notice, "Finished catalog run") do - @catalog.apply(options) - end - 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 - end - - lockfile.unlock - - # Did we get HUPped during the run? If so, then restart now that we're - # done with the run. - if self.restart? - Process.kill(:HUP, $$) - end - end - ensure - # Just make sure we remove the lock file if we set it. - lockfile.unlock if got_lock and lockfile.locked? - clear() - end - - def running? - lockfile.locked? - end - - # Store the classes in the classfile, but only if we're not local. - def setclasses(ary) - if @local - return - end - unless ary and ary.length > 0 - Puppet.info "No classes to store" - return - end - begin - ::File.open(Puppet[:classfile], "w") { |f| - f.puts ary.join("\n") - } - rescue => detail - Puppet.err "Could not create class file %s: %s" % - [Puppet[:classfile], detail] - end - end - - private - - # Download files from the remote server, returning a list of all - # changed files. - def self.download(args) - hash = { - :path => args[:dest], - :recurse => true, - :source => args[:source], - :tag => "#{args[:name]}s", - :owner => Process.uid, - :group => Process.gid, - :purge => true, - :force => true, - :backup => false, - :noop => false - } - - if args[:ignore] - hash[:ignore] = args[:ignore].split(/\s+/) - end - downconfig = Puppet::Resource::Catalog.new("downloading") - downconfig.add_resource Puppet::Type.type(:file).new(hash) - - Puppet.info "Retrieving #{args[:name]}s" - - files = [] - begin - Timeout::timeout(self.timeout) do - downconfig.apply do |trans| - trans.changed?.find_all do |resource| - yield resource if block_given? - files << resource[:path] - end - end - end - rescue Puppet::Error, Timeout::Error => detail - if Puppet[:debug] - puts detail.backtrace - end - Puppet.err "Could not retrieve %ss: %s" % [args[:name], detail] - end - - # Now clean up after ourselves - downconfig.clear - - return files - end - - # Retrieve facts from the central server. - def self.getfacts - # Download the new facts - path = Puppet[:factpath].split(":") - files = [] - download(:dest => Puppet[:factdest], :source => Puppet[:factsource], - :ignore => Puppet[:factsignore], :name => "fact") do |resource| - - next unless path.include?(::File.dirname(resource[:path])) - - files << resource[:path] - end - end - - # Retrieve the plugins from the central server. We only have to load the - # changed plugins, because Puppet::Type loads plugins on demand. - def self.getplugins - download(:dest => Puppet[:plugindest], :source => Puppet[:pluginsource], - :ignore => Puppet[:pluginsignore], :name => "plugin") do |resource| - - next if FileTest.directory?(resource[:path]) - path = resource[:path].sub(Puppet[:plugindest], '').sub(/^\/+/, '') - unless Puppet::Util::Autoload.loaded?(path) - next - end - - begin - Puppet.info "Reloading downloaded file %s" % path - load resource[:path] - rescue => detail - Puppet.warning "Could not reload downloaded file %s: %s" % - [resource[:path], detail] - end - end - end - - def self.loaddir(dir, type) - return unless FileTest.directory?(dir) - - Dir.entries(dir).find_all { |e| e =~ /\.rb$/ }.each do |file| - fqfile = ::File.join(dir, file) - begin - Puppet.info "Loading %s %s" % - [type, ::File.basename(file.sub(".rb",''))] - Timeout::timeout(self.timeout) do - load fqfile - end - rescue => detail - Puppet.warning "Could not load %s %s: %s" % [type, fqfile, detail] - end - end - end - - def self.loadfacts - # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] - x = Puppet[:factpath].split(":").each do |dir| - loaddir(dir, "fact") - end - end - - 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 - - loadfacts() - - # Actually retrieve the catalog, either from the server or from a - # local master. - def get_actual_config(facts) - begin - Timeout::timeout(self.class.timeout) do - return get_remote_config(facts) - end - rescue Timeout::Error - Puppet.err "Configuration retrieval timed out" - return nil - end - end - - # Retrieve a config from a remote master. - def get_remote_config(facts) - textobjects = "" - - textfacts = CGI.escape(YAML.dump(facts)) - - benchmark(:debug, "Retrieved catalog") do - # error handling for this is done in the network client - begin - textobjects = @driver.getconfig(textfacts, Puppet[:catalog_format]) - begin - textobjects = CGI.unescape(textobjects) - rescue => detail - raise Puppet::Error, "Could not CGI.unescape catalog" - end - - rescue => detail - Puppet.err "Could not retrieve catalog: %s" % detail - return nil - end - end - - return nil if textobjects == "" - - @compile_time = Time.now - Puppet::Util::Storage.cache(:configuration)[:facts] = facts - Puppet::Util::Storage.cache(:configuration)[:compile_time] = @compile_time - - return textobjects - end - - def lockfile - unless defined?(@lockfile) - @lockfile = Puppet::Util::Pidlock.new(Puppet[:puppetdlockfile]) - end - - @lockfile - end - - def splayed? - @splayed - end - - # Sleep when splay is enabled; else just return. - def splay - return unless Puppet[:splay] - return if splayed? - - time = rand(Integer(Puppet[:splaylimit]) + 1) - Puppet.info "Sleeping for %s seconds (splay is enabled)" % time - sleep(time) - @splayed = true - end - - private - - # Use our cached config, optionally specifying whether this is - # necessary because of a failure. - def use_cached_config(because_of_failure = false) - return true if self.catalog - - if because_of_failure and ! Puppet[:usecacheonfailure] - @catalog = nil - Puppet.warning "Not using cache on failed catalog" - return false - end - - return false unless oldtext = self.retrievecache - - begin - @catalog = YAML.load(oldtext).to_catalog - @catalog.from_cache = true - @catalog.host_config = true - rescue => detail - puts detail.backtrace if Puppet[:trace] - Puppet.warning "Could not load cached catalog: %s" % detail - clear - return false - end - return true - end -end |
