1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
# the available clients
require 'puppet'
require 'puppet/network/xmlrpc/client'
require 'puppet/util/subclass_loader'
require 'puppet/util/methodhelper'
require 'puppet/sslcertificates/support'
require 'puppet/network/handler'
require 'net/http'
# Some versions of ruby don't have this method defined, which basically causes
# us to never use ssl. Yay.
class Net::HTTP
def use_ssl?
if defined?(@use_ssl)
@use_ssl
else
false
end
end
# JJM: This is a "backport" of sorts to older ruby versions which
# do not have this accessor. See #896 for more information.
attr_accessor :enable_post_connection_check unless Net::HTTP.instance_methods.include? "enable_post_connection_check"
end
# The base class for all of the clients. Many clients just directly
# call methods, but some of them need to do some extra work or
# provide a different interface.
class Puppet::Network::Client
Client = self
include Puppet::Util
extend Puppet::Util::SubclassLoader
include Puppet::Util::MethodHelper
# This handles reading in the key and such-like.
include Puppet::SSLCertificates::Support
attr_accessor :schedule, :lastrun, :local, :stopping
attr_reader :driver
# Set up subclass loading
handle_subclasses :client, "puppet/network/client"
# Determine what clients look for when being passed an object for local
# client/server stuff. E.g., you could call Client::CA.new(:CA => ca).
def self.drivername
@drivername = self.name unless defined?(@drivername)
@drivername
end
# Figure out the handler for our client.
def self.handler
@handler = Puppet::Network::Handler.handler(self.name) unless defined?(@handler)
@handler
end
# The class that handles xmlrpc interaction for us.
def self.xmlrpc_client
@xmlrpc_client = Puppet::Network::XMLRPCClient.handler_class(self.handler) unless defined?(@xmlrpc_client)
@xmlrpc_client
end
# Create our client.
def initialize(hash)
# to whom do we connect?
@server = nil
if hash.include?(:Cache)
@cache = hash[:Cache]
else
@cache = true
end
driverparam = self.class.drivername
if hash.include?(:Server)
args = {:Server => hash[:Server]}
@server = hash[:Server]
args[:Port] = hash[:Port] || Puppet[:masterport]
@driver = self.class.xmlrpc_client.new(args)
self.read_cert
# We have to start the HTTP connection manually before we start
# sending it requests or keep-alive won't work. Note that with #1010,
# we don't currently actually want keep-alive.
@driver.start if @driver.respond_to? :start and Puppet::Network::HttpPool.keep_alive?
@local = false
elsif hash.include?(driverparam)
@driver = hash[driverparam]
if @driver == true
@driver = self.class.handler.new
end
@local = true
else
raise Puppet::Network::ClientError, "#{self.class} must be passed a Server or #{driverparam}"
end
end
# Are we a local client?
def local?
if defined?(@local) and @local
true
else
false
end
end
# Make sure we set the driver up when we read the cert in.
def recycle_connection
@driver.recycle_connection if @driver.respond_to?(:recycle_connection)
end
# A wrapper method to run and then store the last run time
def runnow
if self.stopping
Puppet.notice "In shutdown progress; skipping run"
return
end
begin
self.run
self.lastrun = Time.now.to_i
rescue => detail
puts detail.backtrace if Puppet[:trace]
Puppet.err "Could not run #{self.class}: #{detail}"
end
end
def run
raise Puppet::DevError, "Client type #{self.class} did not override run"
end
def scheduled?
if sched = self.schedule
return sched.match?(self.lastrun)
else
return true
end
end
def shutdown
if self.stopping
Puppet.notice "Already in shutdown"
else
self.stopping = true
Puppet::Util::Storage.store if self.respond_to? :running? and self.running?
rmpidfile()
end
end
# Start listening for events. We're pretty much just listening for
# timer events here.
def start
# Create our timer. Puppet will handle observing it and such.
timer = Puppet.newtimer(
:interval => Puppet[:runinterval],
:tolerance => 1,
:start? => true
) do
begin
self.runnow if self.scheduled?
rescue => detail
puts detail.backtrace if Puppet[:trace]
Puppet.err "Could not run client; got otherwise uncaught exception: #{detail}"
end
end
# Run once before we start following the timer
self.runnow
end
require 'puppet/network/client/proxy'
end
|