puppet 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +0 -0
- data/COPYING +340 -0
- data/LICENSE +17 -0
- data/README +24 -0
- data/Rakefile +294 -0
- data/TODO +4 -0
- data/bin/cf2puppet +186 -0
- data/bin/puppet +176 -0
- data/bin/puppetca +213 -0
- data/bin/puppetd +246 -0
- data/bin/puppetdoc +184 -0
- data/bin/puppetmasterd +258 -0
- data/examples/code/allatonce +13 -0
- data/examples/code/assignments +11 -0
- data/examples/code/classing +35 -0
- data/examples/code/components +73 -0
- data/examples/code/execs +16 -0
- data/examples/code/failers/badclassnoparam +10 -0
- data/examples/code/failers/badclassparam +10 -0
- data/examples/code/failers/badcompnoparam +9 -0
- data/examples/code/failers/badcompparam +9 -0
- data/examples/code/failers/badtypeparam +3 -0
- data/examples/code/file.bl +11 -0
- data/examples/code/filedefaults +10 -0
- data/examples/code/fileparsing +116 -0
- data/examples/code/filerecursion +15 -0
- data/examples/code/functions +3 -0
- data/examples/code/groups +7 -0
- data/examples/code/head +30 -0
- data/examples/code/importing +8 -0
- data/examples/code/nodes +20 -0
- data/examples/code/one +8 -0
- data/examples/code/relationships +34 -0
- data/examples/code/selectors +28 -0
- data/examples/code/simpletests +11 -0
- data/examples/code/snippets/argumentdefaults +14 -0
- data/examples/code/snippets/casestatement +39 -0
- data/examples/code/snippets/classheirarchy.pp +15 -0
- data/examples/code/snippets/classincludes.pp +17 -0
- data/examples/code/snippets/classpathtest +11 -0
- data/examples/code/snippets/dirchmod +19 -0
- data/examples/code/snippets/failmissingexecpath.pp +13 -0
- data/examples/code/snippets/falsevalues.pp +3 -0
- data/examples/code/snippets/filecreate +11 -0
- data/examples/code/snippets/implicititeration +15 -0
- data/examples/code/snippets/multipleinstances +7 -0
- data/examples/code/snippets/namevartest +9 -0
- data/examples/code/snippets/scopetest +13 -0
- data/examples/code/snippets/selectorvalues.pp +22 -0
- data/examples/code/snippets/simpledefaults +5 -0
- data/examples/code/snippets/simpleselector +38 -0
- data/examples/code/svncommit +13 -0
- data/examples/root/bin/sleeper +69 -0
- data/examples/root/etc/configfile +0 -0
- data/examples/root/etc/debian-passwd +29 -0
- data/examples/root/etc/debian-syslog.conf +71 -0
- data/examples/root/etc/init.d/sleeper +65 -0
- data/examples/root/etc/otherfile +0 -0
- data/examples/root/etc/puppet/fileserver.conf +3 -0
- data/examples/root/etc/puppet/puppetmasterd.conf +10 -0
- data/ext/module:puppet +195 -0
- data/install.rb +270 -0
- data/lib/puppet.rb +249 -0
- data/lib/puppet/base64.rb +19 -0
- data/lib/puppet/client.rb +519 -0
- data/lib/puppet/config.rb +49 -0
- data/lib/puppet/daemon.rb +208 -0
- data/lib/puppet/element.rb +71 -0
- data/lib/puppet/event.rb +259 -0
- data/lib/puppet/log.rb +321 -0
- data/lib/puppet/metric.rb +250 -0
- data/lib/puppet/parsedfile.rb +38 -0
- data/lib/puppet/parser/ast.rb +1560 -0
- data/lib/puppet/parser/interpreter.rb +150 -0
- data/lib/puppet/parser/lexer.rb +226 -0
- data/lib/puppet/parser/parser.rb +1354 -0
- data/lib/puppet/parser/scope.rb +755 -0
- data/lib/puppet/server.rb +170 -0
- data/lib/puppet/server/authstore.rb +227 -0
- data/lib/puppet/server/ca.rb +140 -0
- data/lib/puppet/server/filebucket.rb +147 -0
- data/lib/puppet/server/fileserver.rb +477 -0
- data/lib/puppet/server/logger.rb +43 -0
- data/lib/puppet/server/master.rb +103 -0
- data/lib/puppet/server/servlet.rb +247 -0
- data/lib/puppet/sslcertificates.rb +737 -0
- data/lib/puppet/statechange.rb +150 -0
- data/lib/puppet/storage.rb +95 -0
- data/lib/puppet/transaction.rb +179 -0
- data/lib/puppet/transportable.rb +151 -0
- data/lib/puppet/type.rb +1354 -0
- data/lib/puppet/type/component.rb +141 -0
- data/lib/puppet/type/cron.rb +543 -0
- data/lib/puppet/type/exec.rb +316 -0
- data/lib/puppet/type/group.rb +152 -0
- data/lib/puppet/type/nameservice.rb +3 -0
- data/lib/puppet/type/nameservice/netinfo.rb +173 -0
- data/lib/puppet/type/nameservice/objectadd.rb +146 -0
- data/lib/puppet/type/nameservice/posix.rb +200 -0
- data/lib/puppet/type/package.rb +420 -0
- data/lib/puppet/type/package/apt.rb +70 -0
- data/lib/puppet/type/package/dpkg.rb +108 -0
- data/lib/puppet/type/package/rpm.rb +81 -0
- data/lib/puppet/type/package/sun.rb +117 -0
- data/lib/puppet/type/package/yum.rb +58 -0
- data/lib/puppet/type/pfile.rb +569 -0
- data/lib/puppet/type/pfile/checksum.rb +219 -0
- data/lib/puppet/type/pfile/create.rb +108 -0
- data/lib/puppet/type/pfile/group.rb +129 -0
- data/lib/puppet/type/pfile/mode.rb +131 -0
- data/lib/puppet/type/pfile/source.rb +264 -0
- data/lib/puppet/type/pfile/type.rb +31 -0
- data/lib/puppet/type/pfile/uid.rb +166 -0
- data/lib/puppet/type/pfilebucket.rb +80 -0
- data/lib/puppet/type/pprocess.rb +97 -0
- data/lib/puppet/type/service.rb +347 -0
- data/lib/puppet/type/service/base.rb +17 -0
- data/lib/puppet/type/service/debian.rb +50 -0
- data/lib/puppet/type/service/init.rb +145 -0
- data/lib/puppet/type/service/smf.rb +29 -0
- data/lib/puppet/type/state.rb +182 -0
- data/lib/puppet/type/symlink.rb +183 -0
- data/lib/puppet/type/tidy.rb +183 -0
- data/lib/puppet/type/typegen.rb +149 -0
- data/lib/puppet/type/typegen/filerecord.rb +243 -0
- data/lib/puppet/type/typegen/filetype.rb +316 -0
- data/lib/puppet/type/user.rb +290 -0
- data/lib/puppet/util.rb +138 -0
- data/test/certmgr/certmgr.rb +265 -0
- data/test/client/client.rb +203 -0
- data/test/executables/puppetbin.rb +53 -0
- data/test/executables/puppetca.rb +79 -0
- data/test/executables/puppetd.rb +71 -0
- data/test/executables/puppetmasterd.rb +153 -0
- data/test/executables/puppetmodule.rb +60 -0
- data/test/language/ast.rb +412 -0
- data/test/language/interpreter.rb +71 -0
- data/test/language/scope.rb +412 -0
- data/test/language/snippets.rb +445 -0
- data/test/other/events.rb +111 -0
- data/test/other/log.rb +195 -0
- data/test/other/metrics.rb +92 -0
- data/test/other/overrides.rb +115 -0
- data/test/other/parsedfile.rb +31 -0
- data/test/other/relationships.rb +113 -0
- data/test/other/state.rb +106 -0
- data/test/other/storage.rb +39 -0
- data/test/other/transactions.rb +235 -0
- data/test/parser/lexer.rb +120 -0
- data/test/parser/parser.rb +180 -0
- data/test/puppet/conffiles.rb +104 -0
- data/test/puppet/defaults.rb +100 -0
- data/test/puppet/error.rb +23 -0
- data/test/puppet/utiltest.rb +120 -0
- data/test/puppettest.rb +774 -0
- data/test/server/authstore.rb +209 -0
- data/test/server/bucket.rb +227 -0
- data/test/server/ca.rb +201 -0
- data/test/server/fileserver.rb +710 -0
- data/test/server/logger.rb +175 -0
- data/test/server/master.rb +150 -0
- data/test/server/server.rb +130 -0
- data/test/tagging/tagging.rb +80 -0
- data/test/test +51 -0
- data/test/types/basic.rb +119 -0
- data/test/types/component.rb +272 -0
- data/test/types/cron.rb +261 -0
- data/test/types/exec.rb +273 -0
- data/test/types/file.rb +616 -0
- data/test/types/filebucket.rb +167 -0
- data/test/types/fileignoresource.rb +287 -0
- data/test/types/filesources.rb +587 -0
- data/test/types/filetype.rb +162 -0
- data/test/types/group.rb +271 -0
- data/test/types/package.rb +205 -0
- data/test/types/query.rb +101 -0
- data/test/types/service.rb +100 -0
- data/test/types/symlink.rb +93 -0
- data/test/types/tidy.rb +124 -0
- data/test/types/type.rb +135 -0
- data/test/types/user.rb +371 -0
- metadata +243 -0
data/lib/puppet/log.rb
ADDED
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'syslog'
|
2
|
+
|
3
|
+
module Puppet # :nodoc:
|
4
|
+
# Pass feedback to the user. Log levels are modeled after syslog's, and it is
|
5
|
+
# expected that that will be the most common log destination. Supports
|
6
|
+
# multiple destinations, one of which is a remote server.
|
7
|
+
class Log
|
8
|
+
PINK="[0;31m"
|
9
|
+
GREEN="[0;32m"
|
10
|
+
YELLOW="[0;33m"
|
11
|
+
SLATE="[0;34m"
|
12
|
+
ORANGE="[0;35m"
|
13
|
+
BLUE="[0;36m"
|
14
|
+
RESET="[0m"
|
15
|
+
|
16
|
+
@levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit]
|
17
|
+
@loglevel = 2
|
18
|
+
|
19
|
+
@colors = {
|
20
|
+
:debug => SLATE,
|
21
|
+
:info => GREEN,
|
22
|
+
:notice => PINK,
|
23
|
+
:warning => ORANGE,
|
24
|
+
:err => YELLOW,
|
25
|
+
:alert => BLUE,
|
26
|
+
:emerg => RESET,
|
27
|
+
:crit => RESET
|
28
|
+
}
|
29
|
+
|
30
|
+
@destinations = {:syslog => Syslog.open("puppet")}
|
31
|
+
|
32
|
+
# Reset all logs to basics. Basically just closes all files and undefs
|
33
|
+
# all of the other objects.
|
34
|
+
def Log.close(dest = nil)
|
35
|
+
if dest
|
36
|
+
if @destinations.include?(dest)
|
37
|
+
Puppet.warning "Closing %s" % dest
|
38
|
+
if @destinations.respond_to?(:close)
|
39
|
+
@destinations[dest].close
|
40
|
+
end
|
41
|
+
@destinations.delete(dest)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
@destinations.each { |type, dest|
|
45
|
+
if dest.respond_to?(:flush)
|
46
|
+
dest.flush
|
47
|
+
end
|
48
|
+
if dest.respond_to?(:close)
|
49
|
+
dest.close
|
50
|
+
end
|
51
|
+
}
|
52
|
+
@destinations = {}
|
53
|
+
end
|
54
|
+
|
55
|
+
Puppet.info "closed"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Flush any log destinations that support such operations.
|
59
|
+
def Log.flush
|
60
|
+
@destinations.each { |type, dest|
|
61
|
+
if dest.respond_to?(:flush)
|
62
|
+
dest.flush
|
63
|
+
end
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
# Create a new log message. The primary role of this method is to
|
68
|
+
# avoid creating log messages below the loglevel.
|
69
|
+
def Log.create(hash)
|
70
|
+
if @levels.index(hash[:level]) >= @loglevel
|
71
|
+
return Puppet::Log.new(hash)
|
72
|
+
else
|
73
|
+
return nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Yield each valid level in turn
|
78
|
+
def Log.eachlevel
|
79
|
+
@levels.each { |level| yield level }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Return the current log level.
|
83
|
+
def Log.level
|
84
|
+
return @levels[@loglevel]
|
85
|
+
end
|
86
|
+
|
87
|
+
# Set the current log level.
|
88
|
+
def Log.level=(level)
|
89
|
+
unless level.is_a?(Symbol)
|
90
|
+
level = level.intern
|
91
|
+
end
|
92
|
+
|
93
|
+
unless @levels.include?(level)
|
94
|
+
raise Puppet::DevError, "Invalid loglevel %s" % level
|
95
|
+
end
|
96
|
+
|
97
|
+
@loglevel = @levels.index(level)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Create a new log destination.
|
101
|
+
def Log.newdestination(dest)
|
102
|
+
# Each destination can only occur once.
|
103
|
+
if @destinations.include?(dest)
|
104
|
+
return
|
105
|
+
end
|
106
|
+
|
107
|
+
case dest
|
108
|
+
when "syslog", :syslog
|
109
|
+
if Syslog.opened?
|
110
|
+
Syslog.close
|
111
|
+
end
|
112
|
+
@destinations[:syslog] = Syslog.open("puppet")
|
113
|
+
when /^\// # files
|
114
|
+
Puppet.info "opening %s as a log" % dest
|
115
|
+
# first make sure the directory exists
|
116
|
+
unless FileTest.exist?(File.dirname(dest))
|
117
|
+
begin
|
118
|
+
Puppet.recmkdir(File.dirname(dest))
|
119
|
+
Puppet.info "Creating log directory %s" %
|
120
|
+
File.dirname(dest)
|
121
|
+
rescue => detail
|
122
|
+
Log.destination = :console
|
123
|
+
Puppet.err "Could not create log directory: %s" %
|
124
|
+
detail
|
125
|
+
return
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
begin
|
130
|
+
# create the log file, if it doesn't already exist
|
131
|
+
file = File.open(dest,File::WRONLY|File::CREAT|File::APPEND)
|
132
|
+
rescue => detail
|
133
|
+
Log.destination = :console
|
134
|
+
Puppet.err "Could not create log file: %s" %
|
135
|
+
detail
|
136
|
+
return
|
137
|
+
end
|
138
|
+
@destinations[dest] = file
|
139
|
+
when "console", :console
|
140
|
+
@destinations[:console] = :console
|
141
|
+
when Puppet::Server::Logger
|
142
|
+
@destinations[dest] = dest
|
143
|
+
else
|
144
|
+
Puppet.info "Treating %s as a hostname" % dest
|
145
|
+
args = {}
|
146
|
+
if dest =~ /:(\d+)/
|
147
|
+
args[:Port] = $1
|
148
|
+
args[:Server] = dest.sub(/:\d+/, '')
|
149
|
+
else
|
150
|
+
args[:Server] = dest
|
151
|
+
end
|
152
|
+
@destinations[dest] = Puppet::Client::LogClient.new(args)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Route the actual message. FIXME There are lots of things this method should
|
157
|
+
# do, like caching, storing messages when there are not yet destinations,
|
158
|
+
# a bit more.
|
159
|
+
# It's worth noting that there's a potential for a loop here, if
|
160
|
+
# the machine somehow gets the destination set as itself.
|
161
|
+
def Log.newmessage(msg)
|
162
|
+
@destinations.each { |type, dest|
|
163
|
+
case dest
|
164
|
+
when Module # This is the Syslog module
|
165
|
+
next if msg.remote
|
166
|
+
# XXX Syslog currently has a bug that makes it so you
|
167
|
+
# cannot log a message with a '%' in it. So, we get rid
|
168
|
+
# of them.
|
169
|
+
if msg.source == "Puppet"
|
170
|
+
dest.send(msg.level, msg.to_s.gsub("%", '%%'))
|
171
|
+
else
|
172
|
+
dest.send(msg.level, "(%s) %s" %
|
173
|
+
[msg.source.to_s.gsub("%", ""), msg.to_s.gsub("%", '%%')]
|
174
|
+
)
|
175
|
+
end
|
176
|
+
when File:
|
177
|
+
dest.puts("%s %s (%s): %s" %
|
178
|
+
[msg.time, msg.source, msg.level, msg.to_s])
|
179
|
+
when :console
|
180
|
+
if msg.source == "Puppet"
|
181
|
+
puts @colors[msg.level] + "%s: %s" % [
|
182
|
+
msg.level, msg.to_s
|
183
|
+
] + RESET
|
184
|
+
else
|
185
|
+
puts @colors[msg.level] + "%s: %s: %s" % [
|
186
|
+
msg.level, msg.source, msg.to_s
|
187
|
+
] + RESET
|
188
|
+
end
|
189
|
+
when Puppet::Client::LogClient
|
190
|
+
unless msg.is_a?(String) or msg.remote
|
191
|
+
unless defined? @hostname
|
192
|
+
@hostname = Facter["hostname"].value
|
193
|
+
end
|
194
|
+
unless defined? @domain
|
195
|
+
@domain = Facter["domain"].value
|
196
|
+
if @domain
|
197
|
+
@hostname += "." + @domain
|
198
|
+
end
|
199
|
+
end
|
200
|
+
if msg.source =~ /^\//
|
201
|
+
msg.source = @hostname + ":" + msg.source
|
202
|
+
elsif msg.source == "Puppet"
|
203
|
+
msg.source = @hostname + " " + msg.source
|
204
|
+
else
|
205
|
+
msg.source = @hostname + " " + msg.source
|
206
|
+
end
|
207
|
+
begin
|
208
|
+
#puts "would have sent %s" % msg
|
209
|
+
#puts "would have sent %s" %
|
210
|
+
# CGI.escape(Marshal::dump(msg))
|
211
|
+
begin
|
212
|
+
tmp = CGI.escape(Marshal::dump(msg))
|
213
|
+
rescue => detail
|
214
|
+
puts "Could not dump: %s" % detail.to_s
|
215
|
+
return
|
216
|
+
end
|
217
|
+
# Add the hostname to the source
|
218
|
+
dest.addlog(tmp)
|
219
|
+
#dest.addlog(msg.to_s)
|
220
|
+
sleep(0.5)
|
221
|
+
rescue => detail
|
222
|
+
Puppet.err detail
|
223
|
+
@destinations.delete(type)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
else
|
227
|
+
raise Puppet::Error, "Invalid log destination %s" % dest
|
228
|
+
#puts "Invalid log destination %s" % dest.inspect
|
229
|
+
end
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
# Reopen all of our logs.
|
234
|
+
def Log.reopen
|
235
|
+
types = @destinations.keys
|
236
|
+
@destinations.each { |type, dest|
|
237
|
+
if dest.respond_to?(:close)
|
238
|
+
dest.close
|
239
|
+
end
|
240
|
+
}
|
241
|
+
@destinations.clear
|
242
|
+
# We need to make sure we always end up with some kind of destination
|
243
|
+
begin
|
244
|
+
types.each { |type|
|
245
|
+
Log.newdestination(type)
|
246
|
+
}
|
247
|
+
rescue => detail
|
248
|
+
if @destinations.empty?
|
249
|
+
Log.newdestination(:syslog)
|
250
|
+
Puppet.err detail.to_s
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# Is the passed level a valid log level?
|
256
|
+
def self.validlevel?(level)
|
257
|
+
@levels.include?(level)
|
258
|
+
end
|
259
|
+
|
260
|
+
attr_accessor :level, :message, :time, :tags, :remote
|
261
|
+
attr_reader :source
|
262
|
+
|
263
|
+
def initialize(args)
|
264
|
+
unless args.include?(:level) && args.include?(:message)
|
265
|
+
raise Puppet::DevError, "Puppet::Log called incorrectly"
|
266
|
+
end
|
267
|
+
|
268
|
+
if args[:level].class == String
|
269
|
+
@level = args[:level].intern
|
270
|
+
elsif args[:level].class == Symbol
|
271
|
+
@level = args[:level]
|
272
|
+
else
|
273
|
+
raise Puppet::DevError,
|
274
|
+
"Level is not a string or symbol: #{args[:level].class}"
|
275
|
+
end
|
276
|
+
@message = args[:message].to_s
|
277
|
+
@time = Time.now
|
278
|
+
# this should include the host name, and probly lots of other
|
279
|
+
# stuff, at some point
|
280
|
+
unless self.class.validlevel?(level)
|
281
|
+
raise Puppet::DevError, "Invalid message level #{level}"
|
282
|
+
end
|
283
|
+
|
284
|
+
if args.include?(:tags)
|
285
|
+
@tags = args[:tags]
|
286
|
+
end
|
287
|
+
|
288
|
+
if args.include?(:source)
|
289
|
+
self.source = args[:source]
|
290
|
+
else
|
291
|
+
@source = "Puppet"
|
292
|
+
end
|
293
|
+
|
294
|
+
Log.newmessage(self)
|
295
|
+
end
|
296
|
+
|
297
|
+
# If they pass a source in to us, we make sure it is a string, and
|
298
|
+
# we retrieve any tags we can.
|
299
|
+
def source=(source)
|
300
|
+
# We can't store the actual source, we just store the path. This
|
301
|
+
# is a bit of a stupid hack, specifically testing for elements, but
|
302
|
+
# eh.
|
303
|
+
if source.is_a?(Puppet::Element) and source.respond_to?(:path)
|
304
|
+
@source = source.path
|
305
|
+
else
|
306
|
+
@source = source.to_s
|
307
|
+
end
|
308
|
+
unless defined? @tags and @tags
|
309
|
+
if source.respond_to?(:tags)
|
310
|
+
@tags = source.tags
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def to_s
|
316
|
+
return @message
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
# $Id: log.rb 742 2005-11-16 17:12:11Z luke $
|
@@ -0,0 +1,250 @@
|
|
1
|
+
# included so we can test object types
|
2
|
+
require 'puppet'
|
3
|
+
|
4
|
+
module Puppet # :nodoc:
|
5
|
+
# A class for handling metrics. This is currently ridiculously hackish.
|
6
|
+
class Metric
|
7
|
+
def Metric.init
|
8
|
+
@@typemetrics = Hash.new { |typehash,typename|
|
9
|
+
typehash[typename] = Hash.new(0)
|
10
|
+
}
|
11
|
+
|
12
|
+
@@eventmetrics = Hash.new(0)
|
13
|
+
|
14
|
+
@@metrics = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def Metric.clear
|
18
|
+
Metric.init
|
19
|
+
end
|
20
|
+
|
21
|
+
def Metric.gather
|
22
|
+
Metric.init
|
23
|
+
|
24
|
+
# first gather stats about all of the types
|
25
|
+
Puppet::Type.eachtype { |type|
|
26
|
+
type.each { |instance|
|
27
|
+
hash = @@typemetrics[type]
|
28
|
+
hash[:total] += 1
|
29
|
+
if instance.managed?
|
30
|
+
hash[:managed] += 1
|
31
|
+
end
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
# the rest of the metrics are injected directly by type.rb
|
36
|
+
end
|
37
|
+
|
38
|
+
def Metric.add(type,instance,metric,count)
|
39
|
+
return unless defined? @@typemetrics
|
40
|
+
case metric
|
41
|
+
when :outofsync:
|
42
|
+
@@typemetrics[type][metric] += count
|
43
|
+
when :changes:
|
44
|
+
@@typemetrics[type][:changed] += 1
|
45
|
+
@@typemetrics[type][:totalchanges] += count
|
46
|
+
else
|
47
|
+
raise Puppet::DevError, "Unknown metric %s" % metric
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# we're currently throwing away the type and instance information
|
52
|
+
def Metric.addevents(type,instance,events)
|
53
|
+
return unless defined? @@eventmetrics
|
54
|
+
events.each { |event|
|
55
|
+
@@eventmetrics[event] += 1
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Iterate across all of the metrics
|
60
|
+
def Metric.each
|
61
|
+
@@metrics.each { |name,metric|
|
62
|
+
yield metric
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
# I'm nearly positive this method is used only for testing
|
67
|
+
def Metric.load(ary)
|
68
|
+
@@typemetrics = ary[0]
|
69
|
+
@@eventmetrics = ary[1]
|
70
|
+
end
|
71
|
+
|
72
|
+
def Metric.graph(range = nil)
|
73
|
+
@@metrics.each { |name,metric|
|
74
|
+
metric.graph(range)
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def Metric.store(time = nil)
|
79
|
+
require 'RRD'
|
80
|
+
unless time
|
81
|
+
time = Time.now.to_i
|
82
|
+
end
|
83
|
+
@@metrics.each { |name,metric|
|
84
|
+
metric.store(time)
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def Metric.tally
|
89
|
+
type = Metric.new("typecount","Types")
|
90
|
+
type.newvalue("Number",@@typemetrics.length)
|
91
|
+
|
92
|
+
metrics = {
|
93
|
+
:total => "Instances",
|
94
|
+
:managed => "Managed Instances",
|
95
|
+
:outofsync => "Out of Sync Instances",
|
96
|
+
:changed => "Changed Instances",
|
97
|
+
:totalchanges => "Total Number of Changes",
|
98
|
+
}
|
99
|
+
total = Hash.new(0)
|
100
|
+
@@typemetrics.each { |type,instancehash|
|
101
|
+
name = type.name.to_s
|
102
|
+
instmet = Metric.new("type-" + name,name.capitalize)
|
103
|
+
metrics.each { |symbol,label|
|
104
|
+
instmet.newvalue(symbol.to_s,instancehash[symbol],label)
|
105
|
+
total[symbol] += instancehash[symbol]
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
totalmet = Metric.new("typetotals","Type Totals")
|
110
|
+
metrics.each { |symbol,label|
|
111
|
+
totalmet.newvalue(symbol.to_s,total[symbol],label)
|
112
|
+
}
|
113
|
+
|
114
|
+
eventmet = Metric.new("events")
|
115
|
+
total = 0
|
116
|
+
@@eventmetrics.each { |event,count|
|
117
|
+
event = event.to_s
|
118
|
+
# add the specific event as a value, with the label being a
|
119
|
+
# capitalized version with s/_/ /g
|
120
|
+
eventmet.newvalue(
|
121
|
+
event,
|
122
|
+
count,
|
123
|
+
event.capitalize.gsub(/_/,' ')
|
124
|
+
)
|
125
|
+
|
126
|
+
total += count
|
127
|
+
}
|
128
|
+
eventmet.newvalue("total",total,"Event Total")
|
129
|
+
end
|
130
|
+
|
131
|
+
attr_accessor :type, :name, :value, :label
|
132
|
+
|
133
|
+
|
134
|
+
def create
|
135
|
+
dir = Puppet[:rrddir]
|
136
|
+
unless dir
|
137
|
+
raise "Cannot store metrics unless RRDDir is set"
|
138
|
+
end
|
139
|
+
|
140
|
+
unless FileTest.exist?(dir)
|
141
|
+
tmp = dir.sub(/^\//,'')
|
142
|
+
path = [File::SEPARATOR]
|
143
|
+
tmp.split(File::SEPARATOR).each { |d|
|
144
|
+
path.push d
|
145
|
+
unless FileTest.exist?(File.join(path))
|
146
|
+
Dir.mkdir(File.join(path))
|
147
|
+
end
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
unless FileTest.directory?(dir)
|
152
|
+
raise Puppet::Error.new("%s must be a directory" % dir)
|
153
|
+
end
|
154
|
+
|
155
|
+
path = self.path
|
156
|
+
args = [
|
157
|
+
path,
|
158
|
+
"--start", Time.now.to_i - 5,
|
159
|
+
"--step", "300", # XXX Defaulting to every five minutes, but prob bad
|
160
|
+
]
|
161
|
+
|
162
|
+
@values.each { |value|
|
163
|
+
args.push "DS:%s:GAUGE:600:U:U" % value[0]
|
164
|
+
}
|
165
|
+
args.push "RRA:AVERAGE:0.5:1:300"
|
166
|
+
|
167
|
+
begin
|
168
|
+
RRD.create(*args)
|
169
|
+
rescue => detail
|
170
|
+
raise "Could not create RRD file %s: %s" % [path,detail]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def initialize(name,label = nil)
|
175
|
+
@name = name
|
176
|
+
if label
|
177
|
+
@label = label
|
178
|
+
else
|
179
|
+
@label = name.capitalize
|
180
|
+
end
|
181
|
+
|
182
|
+
@values = []
|
183
|
+
if @@metrics.include?(self.name)
|
184
|
+
raise "Somehow created two metrics with name %s" % self.name
|
185
|
+
else
|
186
|
+
@@metrics[self.name] = self
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def newvalue(name,value,label = nil)
|
191
|
+
unless label
|
192
|
+
label = name.capitalize
|
193
|
+
end
|
194
|
+
@values.push [name,label,value]
|
195
|
+
end
|
196
|
+
|
197
|
+
def path
|
198
|
+
return File.join(Puppet[:rrddir],@name + ".rrd")
|
199
|
+
end
|
200
|
+
|
201
|
+
def graph(range = nil)
|
202
|
+
args = [self.path.sub(/rrd$/,"png")]
|
203
|
+
args.push("--title",self.label)
|
204
|
+
args.push("--imgformat","PNG")
|
205
|
+
args.push("--interlace")
|
206
|
+
colorstack = %w{#ff0000 #00ff00 #0000ff #099000 #000990 #f00990}
|
207
|
+
i = 0
|
208
|
+
defs = []
|
209
|
+
lines = []
|
210
|
+
@values.zip(colorstack).each { |value,color|
|
211
|
+
next if value.nil?
|
212
|
+
# this actually uses the data label
|
213
|
+
defs.push("DEF:%s=%s:%s:AVERAGE" % [value[0],self.path,value[0]])
|
214
|
+
lines.push("LINE3:%s%s:%s" % [value[0],color,value[1]])
|
215
|
+
}
|
216
|
+
args << defs
|
217
|
+
args << lines
|
218
|
+
args.flatten!
|
219
|
+
if range
|
220
|
+
args.push("--start",range[0],"--end",range[1])
|
221
|
+
end
|
222
|
+
|
223
|
+
begin
|
224
|
+
RRD.graph(*args)
|
225
|
+
rescue => detail
|
226
|
+
Puppet.err "Failed to graph %s: %s" % [self.name,detail]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def store(time)
|
231
|
+
unless FileTest.exists?(File.join(Puppet[:rrddir],@name + ".rrd"))
|
232
|
+
self.create
|
233
|
+
end
|
234
|
+
|
235
|
+
# XXX this is not terribly error-resistant
|
236
|
+
args = [time]
|
237
|
+
@values.each { |value|
|
238
|
+
args.push value[2]
|
239
|
+
}
|
240
|
+
arg = args.join(":")
|
241
|
+
begin
|
242
|
+
RRD.update(self.path,args.join(":"))
|
243
|
+
rescue => detail
|
244
|
+
raise Puppet::Error, "Failed to update %s: %s" % [self.name,detail]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# $Id: metric.rb 732 2005-10-28 05:39:59Z luke $
|