diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-24 06:01:58 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-24 06:01:58 +0000 |
commit | ae2575b45de1e8f4c0ec956cebe0eed2bafbcf57 (patch) | |
tree | 9c2b7c839087c285c228374f525315e55c392a34 /lib/puppet/client | |
parent | 18e8e74a2e3b4c5d092fc0aae38bbc5455d4db48 (diff) | |
download | puppet-ae2575b45de1e8f4c0ec956cebe0eed2bafbcf57.tar.gz puppet-ae2575b45de1e8f4c0ec956cebe0eed2bafbcf57.tar.xz puppet-ae2575b45de1e8f4c0ec956cebe0eed2bafbcf57.zip |
Adding the event-loop stuff to the repository and switching to using it. Also, breaking many classes out into their own class files.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@848 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet/client')
-rw-r--r-- | lib/puppet/client/ca.rb | 17 | ||||
-rw-r--r-- | lib/puppet/client/dipper.rb | 78 | ||||
-rw-r--r-- | lib/puppet/client/file.rb | 20 | ||||
-rw-r--r-- | lib/puppet/client/log.rb | 17 | ||||
-rw-r--r-- | lib/puppet/client/master.rb | 244 | ||||
-rw-r--r-- | lib/puppet/client/proxy.rb | 27 | ||||
-rw-r--r-- | lib/puppet/client/status.rb | 7 |
7 files changed, 410 insertions, 0 deletions
diff --git a/lib/puppet/client/ca.rb b/lib/puppet/client/ca.rb new file mode 100644 index 000000000..11989230c --- /dev/null +++ b/lib/puppet/client/ca.rb @@ -0,0 +1,17 @@ +class Puppet::Client::CAClient < Puppet::Client::ProxyClient + @drivername = :CA + + # set up the appropriate interface methods + @handler = Puppet::Server::CA + self.mkmethods + + def initialize(hash = {}) + if hash.include?(:CA) + hash[:CA] = Puppet::Server::CA.new() + end + + super(hash) + end +end + +# $Id$ diff --git a/lib/puppet/client/dipper.rb b/lib/puppet/client/dipper.rb new file mode 100644 index 000000000..281d0bab7 --- /dev/null +++ b/lib/puppet/client/dipper.rb @@ -0,0 +1,78 @@ +module Puppet + class Client + # The client class for filebuckets. + class Dipper < Puppet::Client + @drivername = :Bucket + + def initialize(hash = {}) + if hash.include?(:Path) + bucket = Puppet::Server::FileBucket.new( + :Bucket => hash[:Path] + ) + hash.delete(:Path) + hash[:Bucket] = bucket + end + + super(hash) + end + + def backup(file) + unless FileTest.exists?(file) + raise(BucketError, "File %s does not exist" % file, caller) + end + contents = File.open(file) { |of| of.read } + + string = Base64.encode64(contents) + #puts "string is created" + + sum = @driver.addfile(string,file) + #puts "file %s is added" % file + return sum + end + + def restore(file,sum) + restore = true + if FileTest.exists?(file) + contents = File.open(file) { |of| of.read } + + cursum = Digest::MD5.hexdigest(contents) + + # if the checksum has changed... + # this might be extra effort + if cursum == sum + restore = false + end + end + + if restore + #puts "Restoring %s" % file + if tmp = @driver.getfile(sum) + newcontents = Base64.decode64(tmp) + newsum = Digest::MD5.hexdigest(newcontents) + changed = nil + unless FileTest.writable?(file) + changed = File.stat(file).mode + File.chmod(changed | 0200, file) + end + File.open(file,File::WRONLY|File::TRUNC) { |of| + of.print(newcontents) + } + if changed + File.chmod(changed, file) + end + else + Puppet.err "Could not find file with checksum %s" % sum + return nil + end + #puts "Done" + return newsum + else + return nil + end + + end + end + end +end + +# $Id$ diff --git a/lib/puppet/client/file.rb b/lib/puppet/client/file.rb new file mode 100644 index 000000000..116624003 --- /dev/null +++ b/lib/puppet/client/file.rb @@ -0,0 +1,20 @@ +class Puppet::Client::FileClient < Puppet::Client::ProxyClient + @drivername = :FileServer + + # set up the appropriate interface methods + @handler = Puppet::Server::FileServer + + self.mkmethods + + def initialize(hash = {}) + if hash.include?(:FileServer) + unless hash[:FileServer].is_a?(Puppet::Server::FileServer) + raise Puppet::DevError, "Must pass an actual FS object" + end + end + + super(hash) + end +end + +# $Id$ diff --git a/lib/puppet/client/log.rb b/lib/puppet/client/log.rb new file mode 100644 index 000000000..e20c0532c --- /dev/null +++ b/lib/puppet/client/log.rb @@ -0,0 +1,17 @@ +class Puppet::Client::LogClient < Puppet::Client::ProxyClient + @drivername = :Logger + + # set up the appropriate interface methods + @handler = Puppet::Server::Logger + self.mkmethods + + def initialize(hash = {}) + if hash.include?(:Logger) + hash[:Logger] = Puppet::Server::Logger.new() + end + + super(hash) + end +end + +# $Id$ diff --git a/lib/puppet/client/master.rb b/lib/puppet/client/master.rb new file mode 100644 index 000000000..f0204c418 --- /dev/null +++ b/lib/puppet/client/master.rb @@ -0,0 +1,244 @@ +# The client for interacting with the puppetmaster config server. +class Puppet::Client::MasterClient < Puppet::Client + @drivername = :Master + + def self.facts + facts = {} + Facter.each { |name,fact| + facts[name] = fact.downcase + } + + facts + end + + # This method is how the client receives the tree of Transportable + # objects. For now, just descend into the tree and perform and + # necessary manipulations. + def apply + dostorage() + unless defined? @objects + raise Puppet::Error, "Cannot apply; objects not defined" + end + + #Puppet.err :yay + #p @objects + #Puppet.err :mark + #@objects = @objects.to_type + # this is a gross hack... but i don't see a good way around it + # set all of the variables to empty + Puppet::Transaction.init + + # For now we just evaluate the top-level object, but eventually + # there will be schedules and such associated with each object, + # and probably with the container itself. + transaction = @objects.evaluate + #transaction = Puppet::Transaction.new(objects) + transaction.toplevel = true + begin + transaction.evaluate + rescue Puppet::Error => detail + Puppet.err "Could not apply complete configuration: %s" % + detail + rescue => detail + Puppet.err "Found a bug: %s" % detail + if Puppet[:debug] + puts detail.backtrace + end + ensure + Puppet::Storage.store + end + Puppet::Metric.gather + Puppet::Metric.tally + if Puppet[:rrdgraph] == true + Metric.store + Metric.graph + end + + return transaction + end + + # Cache the config + def cache(text) + Puppet.info "Caching configuration at %s" % self.cachefile + confdir = File.dirname(Puppet[:localconfig]) + unless FileTest.exists?(confdir) + Puppet.recmkdir(confdir, 0770) + end + 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 + + # Initialize and load storage + def dostorage + begin + Puppet::Storage.init + Puppet::Storage.load + rescue => detail + Puppet.err "Corrupt state file %s: %s" % [Puppet[:checksumfile], detail] + begin + File.unlink(Puppet[:checksumfile]) + retry + rescue => detail + raise Puppet::Error.new("Cannot remove %s: %s" % + [Puppet[statefile], detail]) + end + end + end + + # Check whether our configuration is up to date + def fresh? + unless defined? @configstamp + return false + end + + # We're willing to give a 2 second drift + if @driver.freshness - @configstamp < 1 + return true + else + return false + end + end + + # Retrieve the config from a remote server. If this fails, then + # use the cached copy. + def getconfig + if self.fresh? + Puppet.info "Config is up to date" + return + end + Puppet.debug("getting config") + dostorage() + + facts = self.class.facts + + unless facts.length > 0 + raise Puppet::ClientError.new( + "Could not retrieve any facts" + ) + end + + objects = nil + if @local + # If we're local, we don't have to do any of the conversion + # stuff. + objects = @driver.getconfig(facts, "yaml") + @configstamp = Time.now.to_i + + if objects == "" + raise Puppet::Error, "Could not retrieve configuration" + end + else + textobjects = "" + + textfacts = CGI.escape(YAML.dump(facts)) + + # error handling for this is done in the network client + begin + textobjects = @driver.getconfig(textfacts, "yaml") + rescue => detail + Puppet.err "Could not retrieve configuration: %s" % detail + end + + fromcache = false + if textobjects == "" + textobjects = self.retrievecache + if textobjects == "" + raise Puppet::Error.new( + "Cannot connect to server and there is no cached configuration" + ) + end + Puppet.notice "Could not get config; using cached copy" + fromcache = true + end + + begin + textobjects = CGI.unescape(textobjects) + @configstamp = Time.now.to_i + rescue => detail + raise Puppet::Error, "Could not CGI.unescape configuration" + end + + if @cache and ! fromcache + self.cache(textobjects) + end + + begin + objects = YAML.load(textobjects) + rescue => detail + raise Puppet::Error, + "Could not understand configuration: %s" % + detail.to_s + end + end + + unless objects.is_a?(Puppet::TransBucket) + raise NetworkClientError, + "Invalid returned objects of type %s" % objects.class + end + + if classes = objects.classes + self.setclasses(classes) + else + Puppet.info "No classes to store" + end + + # Clear all existing objects, so we can recreate our stack. + if defined? @objects + Puppet::Type.allclear + end + @objects = nil + + # First create the default scheduling objects + Puppet.type(:schedule).mkdefaultschedules + + # Now convert the objects to real Puppet objects + @objects = objects.to_type + + if @objects.nil? + raise Puppet::Error, "Configuration could not be processed" + end + #@objects = objects + + # and perform any necessary final actions before we evaluate. + Puppet::Type.finalize + + return @objects + end + + # Retrieve the cached config + def retrievecache + if FileTest.exists?(self.cachefile) + return File.read(self.cachefile) + else + return "" + end + end + + # The code that actually runs the configuration. + def run + self.getconfig + self.apply + end + + def setclasses(ary) + 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 +end + +# $Id$ diff --git a/lib/puppet/client/proxy.rb b/lib/puppet/client/proxy.rb new file mode 100644 index 000000000..2ea0a87f9 --- /dev/null +++ b/lib/puppet/client/proxy.rb @@ -0,0 +1,27 @@ +# unlike the other client classes (again, this design sucks) this class +# is basically just a proxy class -- it calls its methods on the driver +# and that's about it +class Puppet::Client::ProxyClient < Puppet::Client + def self.mkmethods + interface = @handler.interface + namespace = interface.prefix + + interface.methods.each { |ary| + method = ary[0] + Puppet.debug "%s: defining %s.%s" % [self, namespace, method] + self.send(:define_method,method) { |*args| + begin + @driver.send(method, *args) + rescue XMLRPC::FaultException => detail + #Puppet.err "Could not call %s.%s: %s" % + # [namespace, method, detail.faultString] + #raise NetworkClientError, + # "XMLRPC Error: %s" % detail.faultString + raise NetworkClientError, detail.faultString + end + } + } + end +end + +# $Id$ diff --git a/lib/puppet/client/status.rb b/lib/puppet/client/status.rb new file mode 100644 index 000000000..ed1445e04 --- /dev/null +++ b/lib/puppet/client/status.rb @@ -0,0 +1,7 @@ +class Puppet::Client::StatusClient < Puppet::Client::ProxyClient + # set up the appropriate interface methods + @handler = Puppet::Server::ServerStatus + self.mkmethods +end + +# $Id$ |