diff --git a/ext/ldap/puppet.schema b/ext/ldap/puppet.schema index bbad23eab..d8dc4260d 100644 --- a/ext/ldap/puppet.schema +++ b/ext/ldap/puppet.schema @@ -1,22 +1,22 @@ # These OIDs are all fake. No guarantees there won't be conflicts. # # $Id$ attributetype ( 1.1.3.10 NAME 'puppetclass' DESC 'Puppet Node Class' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.1.3.9 NAME 'parentnode' DESC 'Puppet Parent Node' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -attributetype ( 1.1.3.9 NAME 'environment' +attributetype ( 1.1.3.11 NAME 'environment' DESC 'Puppet Node Environment' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) objectclass ( 1.1.1.2 NAME 'puppetClient' SUP top AUXILIARY DESC 'Puppet Client objectclass' MAY ( puppetclass $ parentnode $ environment )) diff --git a/lib/puppet/network/xmlrpc/client.rb b/lib/puppet/network/xmlrpc/client.rb index f6a5e8db6..357a766a1 100644 --- a/lib/puppet/network/xmlrpc/client.rb +++ b/lib/puppet/network/xmlrpc/client.rb @@ -1,150 +1,155 @@ require 'puppet/sslcertificates' require 'puppet/network/http_pool' require 'openssl' require 'puppet/external/base64' require 'xmlrpc/client' require 'net/https' require 'yaml' module Puppet::Network class ClientError < Puppet::Error; end class XMLRPCClientError < Puppet::Error; end class XMLRPCClient < ::XMLRPC::Client attr_accessor :puppet_server, :puppet_port @clients = {} class << self include Puppet::Util include Puppet::Util::ClassGen end # Create a netclient for each handler def self.mkclient(handler) interface = handler.interface namespace = interface.prefix # Create a subclass for every client type. This is # so that all of the methods are on their own class, # so that their namespaces can define the same methods if # they want. constant = handler.name.to_s.capitalize name = namespace.downcase newclient = genclass(name, :hash => @clients, :constant => constant) interface.methods.each { |ary| method = ary[0] if public_method_defined?(method) raise Puppet::DevError, "Method %s is already defined" % method end newclient.send(:define_method,method) { |*args| Puppet.debug "Calling %s.%s" % [namespace, method] begin call("%s.%s" % [namespace, method.to_s],*args) rescue OpenSSL::SSL::SSLError => detail if detail.message =~ /bad write retry/ Puppet.warning "Transient SSL write error; restarting connection and retrying" self.recycle_connection retry end + ["certificate verify failed", "hostname was not match", "hostname not match"].each do |str| + if detail.message.include?(str) + Puppet.warning "Certificate validation failed; considering using the certname configuration option" + end + end raise XMLRPCClientError, "Certificates were not trusted: %s" % detail rescue ::XMLRPC::FaultException => detail raise XMLRPCClientError, detail.faultString rescue Errno::ECONNREFUSED => detail msg = "Could not connect to %s on port %s" % [@host, @port] raise XMLRPCClientError, msg rescue SocketError => detail Puppet.err "Could not find server %s: %s" % [@host, detail.to_s] error = XMLRPCClientError.new( "Could not find server %s" % @host ) error.set_backtrace detail.backtrace raise error rescue Errno::EPIPE, EOFError Puppet.warning "Other end went away; restarting connection and retrying" self.recycle_connection retry rescue => detail if detail.message =~ /^Wrong size\. Was \d+, should be \d+$/ Puppet.warning "XMLRPC returned wrong size. Retrying." retry end Puppet.err "Could not call %s.%s: %s" % [namespace, method, detail.inspect] error = XMLRPCClientError.new(detail.to_s) error.set_backtrace detail.backtrace raise error end } } return newclient end def self.handler_class(handler) @clients[handler] || self.mkclient(handler) end def http unless @http @http = Puppet::Network::HttpPool.http_instance(@host, @port, true) end @http end def initialize(hash = {}) hash[:Path] ||= "/RPC2" hash[:Server] ||= Puppet[:server] hash[:Port] ||= Puppet[:masterport] hash[:HTTPProxyHost] ||= Puppet[:http_proxy_host] hash[:HTTPProxyPort] ||= Puppet[:http_proxy_port] if "none" == hash[:HTTPProxyHost] hash[:HTTPProxyHost] = nil hash[:HTTPProxyPort] = nil end super( hash[:Server], hash[:Path], hash[:Port], hash[:HTTPProxyHost], hash[:HTTPProxyPort], nil, # user nil, # password true, # use_ssl 120 # a two minute timeout, instead of 30 seconds ) @http = Puppet::Network::HttpPool.http_instance(@host, @port) end # Get rid of our existing connection, replacing it with a new one. # This should only happen if we lose our connection somehow (e.g., an EPIPE) # or we've just downloaded certs and we need to create new http instances # with the certs added. def recycle_connection @http = Puppet::Network::HttpPool.http_instance(@host, @port, true) # reset the instance end def start begin @http.start unless @http.started? rescue => detail Puppet.err "Could not connect to server: %s" % detail end end def local false end def local? false end end end diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb index 2611f0369..03d8a5bdd 100644 --- a/lib/puppet/reports/rrdgraph.rb +++ b/lib/puppet/reports/rrdgraph.rb @@ -1,135 +1,137 @@ Puppet::Reports.register_report(:rrdgraph) do desc "Graph all available data about hosts using the RRD library. You must have the Ruby RRDtool library installed to use this report, which - you can get from `the RubyRRDTool RubyForge page`_. This package requires - the binary rrdtool2 package to be installed. + you can get from `the RubyRRDTool RubyForge page`_. This package may also + be available as ``ruby-rrd`` or ``rrdtool-ruby`` in your distribution's package + management system. The library and/or package will both require the binary + ``rrdtool`` package from your distribution to be installed. .. _the RubyRRDTool RubyForge page: http://rubyforge.org/projects/rubyrrdtool/ This report will create, manage, and graph RRD database files for each of the metrics generated during transactions, and it will create a few simple html files to display the reporting host's graphs. At this point, it will not create a common index file to display links to all hosts. All RRD files and graphs get created in the ``rrddir`` directory. If you want to serve these publicly, you should be able to just alias that directory in a web server. If you really know what you're doing, you can tune the ``rrdinterval``, which defaults to the ``runinterval``." def hostdir unless defined? @hostdir @hostdir = File.join(Puppet[:rrddir], self.host) end @hostdir end def htmlfile(type, graphs, field) file = File.join(hostdir, "%s.html" % type) File.open(file, "w") do |of| of.puts "%s graphs for %s" % [type.capitalize, host] graphs.each do |graph| if field == :first name = graph.sub(/-\w+.png/, '').capitalize else name = graph.sub(/\w+-/, '').sub(".png", '').capitalize end of.puts "
" % graph end of.puts "" end return file end def mkhtml images = Dir.entries(hostdir).find_all { |d| d =~ /\.png/ } periodorder = %w{daily weekly monthly yearly} periods = {} types = {} images.each do |n| type, period = n.sub(".png", '').split("-") periods[period] ||= [] types[type] ||= [] periods[period] << n types[type] << n end files = [] # Make the period html files periodorder.each do |period| unless ary = periods[period] raise Puppet::Error, "Could not find graphs for %s" % period end files << htmlfile(period, ary, :first) end # make the type html files types.sort { |a,b| a[0] <=> b[0] }.each do |type, ary| newary = [] periodorder.each do |period| if graph = ary.find { |g| g.include?("-%s.png" % period) } newary << graph else raise "Could not find %s-%s graph" % [type, period] end end files << htmlfile(type, newary, :second) end File.open(File.join(hostdir, "index.html"), "w") do |of| of.puts "Report graphs for %s" % host files.each do |file| of.puts "%s
" % File.basename(file).sub(".html",'').capitalize end of.puts "" end end def process(time = nil) time ||= Time.now.to_i unless File.directory?(hostdir) and FileTest.writable?(hostdir) # Some hackishness to create the dir with all of the right modes and ownership config = Puppet::Util::Settings.new config.setdefaults(:reports, :hostdir => {:default => hostdir, :owner => Puppet[:user], :mode => 0755, :group => Puppet[:group], :desc => "eh"}) # This creates the dir. config.use(:reports) end self.metrics.each do |name, metric| metric.basedir = hostdir if name == "time" timeclean(metric) end metric.store(time) metric.graph end unless FileTest.exists?(File.join(hostdir, "index.html")) mkhtml() end end # Unfortunately, RRD does not deal well with changing lists of values, # so we have to pick a list of values and stick with it. In this case, # that means we record the total time, the config time, and that's about # it. We should probably send each type's time as a separate metric. def timeclean(metric) metric.values = metric.values.find_all { |name, label, value| [:total, :config_retrieval].include?(name) } end end