#!/usr/bin/ruby # == Synopsis # # Retrieve the client configuration from the central puppet server and apply # it to the local host. # # Currently must be run out periodically, using cron or something similar. # # = Usage # # puppetd [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose] # [-l|--logdest |console>] [--fqdn ] # [-o|--onetime] [-w|--waitforcert ] [--centrallogging] # # = Description # # This is the main puppet client. Its job is to retrieve the local machine's # configuration from a remote server and apply it. In order to successfully # communicate with the remote server, the client must have a certificate signed # by a certificate authority that the server trusts; the recommended method # for this, at the moment, is to run a certificate authority as part of the # puppet server (which is the default). The client will connect and request # a signed certificate, and will continue connecting until it receives one. # # Once the client has a signed certificate, it will retrieve its configuration # and apply it. # # = Options # # Note that any configuration parameter that's valid in the configuration file # is also a valid long argument. For example, 'server' is a valid configuration # parameter, so you can specify '--server ' as an argument. # # See the configuration file for the full list of acceptable parameters. # # centrallogging:: # Send all produced logs to the central puppetmasterd system. This currently # results in a significant slowdown, so it is not recommended. # # debug:: # Enable full debugging. # # fqdn:: # Set the fully-qualified domain name of the client. This is only used for # certificate purposes, but can be used to override the discovered hostname. # If you need to use this flag, it is generally an indication of a setup problem. # # help:: # Print this help message # # logdest:: # Where to send messages. Choose between syslog, the console, and a log file. # Defaults to sending messages to syslog, or the console if debugging or # verbosity is enabled. # # onetime:: # Run the configuration once, rather than as a long-running daemon. This is # useful for interactively running puppetd. # # verbose:: # Turn on verbose reporting. # # version:: # Print the puppet version number and exit. # # waitforcert:: # Have the process wait around, continuously retrying for the certificate # each seconds. # # = Example # # puppetd --server puppet.domain.com # # = Author # # Luke Kanies # # = Copyright # # Copyright (c) 2005, 2006 Reductive Labs, LLC # Licensed under the GNU Public License require 'puppet' require 'puppet/server' require 'puppet/client' require 'getoptlong' $haveusage = true begin require 'rdoc/usage' rescue LoadError $haveusage = false end options = [ [ "--centrallogging", GetoptLong::NO_ARGUMENT ], [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--fqdn", "-f", GetoptLong::REQUIRED_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ], [ "--logdest", "-l", GetoptLong::REQUIRED_ARGUMENT ], [ "--onetime", "-o", GetoptLong::NO_ARGUMENT ], [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ], [ "--version", "-V", GetoptLong::NO_ARGUMENT ], [ "--waitforcert", "-w", GetoptLong::REQUIRED_ARGUMENT ] ] # Add all of the config parameters as valid options. Puppet.config.addargs(options) result = GetoptLong.new(*options) server = "puppet" fqdn = nil args = {} waitforcert = false onetime = false centrallogs = false setdest = false begin result.each { |opt,arg| case opt # First check to see if the argument is a valid configuration parameter; # if so, set it. when "--centrallogging" centrallogs = true when "--help" if $haveusage RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" exit end when "--version" puts "%s" % Puppet.version exit when "--verbose" Puppet::Log.level = :info Puppet::Log.newdestination(:console) when "--debug" Puppet::Log.level = :debug Puppet::Log.newdestination(:console) when "--fqdn" fqdn = arg when "--onetime" onetime = true when "--port" args[:Port] = arg when "--logdest" begin Puppet::Log.newdestination(arg) setdest = true rescue => detail $stderr.puts detail.to_s end when "--waitforcert" waitforcert = arg.to_i else Puppet.config.handlearg(opt, arg) end } rescue GetoptLong::InvalidOption => detail $stderr.puts detail $stderr.puts "Try '#{$0} --help'" # FIXME RDoc::usage doesn't seem to work #if $haveusage # RDoc::usage(1,'usage') #end exit(1) end Puppet.genconfig Puppet.genmanifest # Now parse the config if Puppet[:config] and File.exists? Puppet[:config] Puppet.config.parse(Puppet[:config]) end if Puppet::Log.level == :debug or Puppet::Log.level == :info args[:Daemonize] = false else args[:Daemonize] = true end unless setdest Puppet::Log.newdestination(:syslog) end args[:Server] = Puppet[:server] if fqdn args[:FQDN] = fqdn end if centrallogs logdest = args[:Server] if args.include?(:Port) logdest += ":" + args[:Port] end Puppet::Log.newdestination(logdest) end Puppet.notice "Starting Puppet client version %s" % [Puppet.version] client = Puppet::Client::MasterClient.new(args) unless client.readcert if waitforcert begin while ! client.requestcert do Puppet.notice "Did not receive certificate" sleep waitforcert end rescue => detail Puppet.err "Could not request certificate: %s" % detail.to_s exit(23) end else unless client.requestcert Puppet.notice "No certificates; exiting" exit(1) end end # Now, because the Net::HTTP object cannot be modified once we've connected, # we need to recreate the client with the certs intact client = Puppet::Client::MasterClient.new(args) unless client.readcert PUppet.err "Could not read certificates after retrieving them" exit(34) end end if args[:Daemonize] #exit(13) client.daemonize end # now set up the network client with the certs, now that we have them client.setcerts trap(:INT) { client.shutdown } if onetime begin client.run rescue => detail Puppet.err detail.to_s if Puppet[:debug] puts detail.backtrace end end else client.start # Mmm, hackish Puppet.start end # $Id: puppetd 895 2006-02-09 21:15:38Z lutter $