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
|
require 'puppet/network/http'
require 'puppet/util/pidlock'
class Puppet::Network::Server
attr_reader :server_type, :protocols, :address, :port
# Put the daemon into the background.
def daemonize
if pid = fork()
Process.detach(pid)
exit(0)
end
# Get rid of console logging
Puppet::Util::Log.close(:console)
Process.setsid
Dir.chdir("/")
begin
$stdin.reopen "/dev/null"
$stdout.reopen "/dev/null", "a"
$stderr.reopen $stdout
Puppet::Util::Log.reopen
rescue => detail
File.open("/tmp/daemonout", "w") { |f|
f.puts "Could not start %s: %s" % [Puppet[:name], detail]
}
raise "Could not start %s: %s" % [Puppet[:name], detail]
end
end
# Create a pidfile for our daemon, so we can be stopped and others
# don't try to start.
def create_pidfile
Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
unless Puppet::Util::Pidlock.new(pidfile).lock
raise "Could not create PID file: %s" % [pidfile]
end
end
end
# Remove the pid file for our daemon.
def remove_pidfile
Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
locker = Puppet::Util::Pidlock.new(pidfile)
if locker.locked?
locker.unlock or Puppet.err "Could not remove PID file %s" % [pidfile]
end
end
end
# Provide the path to our pidfile.
def pidfile
Puppet[:pidfile]
end
def initialize(args = {})
@server_type = Puppet[:servertype] or raise "No servertype configuration found." # e.g., WEBrick, Mongrel, etc.
http_server_class || raise(ArgumentError, "Could not determine HTTP Server class for server type [#{@server_type}]")
@address = args[:address] || Puppet[:bindaddress] || raise(ArgumentError, "Must specify :address or configure Puppet :bindaddress.")
@port = args[:port] || Puppet[:masterport] || raise(ArgumentError, "Must specify :port or configure Puppet :masterport")
@protocols = [ :rest, :xmlrpc ]
@listening = false
@routes = {}
@xmlrpc_routes = {}
self.register(args[:handlers]) if args[:handlers]
self.register_xmlrpc(args[:xmlrpc_handlers]) if args[:xmlrpc_handlers]
# Make sure we have all of the directories we need to function.
Puppet.settings.use(:main, :ssl, Puppet[:name])
end
# Register handlers for REST networking, based on the Indirector.
def register(*indirections)
raise ArgumentError, "Indirection names are required." if indirections.empty?
indirections.flatten.each do |name|
Puppet::Indirector::Indirection.model(name) || raise(ArgumentError, "Cannot locate indirection '#{name}'.")
@routes[name.to_sym] = true
end
end
# Unregister Indirector handlers.
def unregister(*indirections)
raise "Cannot unregister indirections while server is listening." if listening?
indirections = @routes.keys if indirections.empty?
indirections.flatten.each do |i|
raise(ArgumentError, "Indirection [%s] is unknown." % i) unless @routes[i.to_sym]
end
indirections.flatten.each do |i|
@routes.delete(i.to_sym)
end
end
# Register xmlrpc handlers for backward compatibility.
def register_xmlrpc(*namespaces)
raise ArgumentError, "XMLRPC namespaces are required." if namespaces.empty?
namespaces.flatten.each do |name|
Puppet::Network::Handler.handler(name) || raise(ArgumentError, "Cannot locate XMLRPC handler for namespace '#{name}'.")
@xmlrpc_routes[name.to_sym] = true
end
end
# Unregister xmlrpc handlers.
def unregister_xmlrpc(*namespaces)
raise "Cannot unregister xmlrpc handlers while server is listening." if listening?
namespaces = @xmlrpc_routes.keys if namespaces.empty?
namespaces.flatten.each do |i|
raise(ArgumentError, "XMLRPC handler '%s' is unknown." % i) unless @xmlrpc_routes[i.to_sym]
end
namespaces.flatten.each do |i|
@xmlrpc_routes.delete(i.to_sym)
end
end
def listening?
@listening
end
def listen
raise "Cannot listen -- already listening." if listening?
@listening = true
http_server.listen(:address => address, :port => port, :handlers => @routes.keys, :xmlrpc_handlers => @xmlrpc_routes.keys, :protocols => protocols)
end
def unlisten
raise "Cannot unlisten -- not currently listening." unless listening?
http_server.unlisten
@listening = false
end
def http_server_class
http_server_class_by_type(@server_type)
end
def start
create_pidfile
listen
end
def stop
unlisten
remove_pidfile
end
private
def http_server
@http_server ||= http_server_class.new
end
def http_server_class_by_type(kind)
Puppet::Network::HTTP.server_class_by_type(kind)
end
end
|