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
|
require 'puppet/transaction'
class Puppet::Transaction::EventManager
attr_reader :transaction, :events
def initialize(transaction)
@transaction = transaction
@event_queues = {}
@events = []
end
def relationship_graph
transaction.relationship_graph
end
# Respond to any queued events for this resource.
def process_events(resource)
restarted = false
queued_events(resource) do |callback, events|
r = process_callback(resource, callback, events)
restarted ||= r
end
if restarted
queue_events(resource, [resource.event(:name => :restarted, :status => "success")])
transaction.resource_status(resource).restarted = true
end
end
# Queue events for other resources to respond to. All of these events have
# to be from the same resource.
def queue_events(resource, events)
@events += events
# Do some basic normalization so we're not doing so many
# graph queries for large sets of events.
events.inject({}) do |collection, event|
collection[event.name] ||= []
collection[event.name] << event
collection
end.collect do |name, list|
# It doesn't matter which event we use - they all have the same source
# and name here.
event = list[0]
# Collect the targets of any subscriptions to those events. We pass
# the parent resource in so it will override the source in the events,
# since eval_generated children can't have direct relationships.
relationship_graph.matching_edges(event, resource).each do |edge|
next unless method = edge.callback
next unless edge.target.respond_to?(method)
queue_events_for_resource(resource, edge.target, method, list)
end
queue_events_for_resource(resource, resource, :refresh, [event]) if resource.self_refresh? and ! resource.deleting?
end
end
def queue_events_for_resource(source, target, callback, events)
source.info "Scheduling #{callback} of #{target}"
@event_queues[target] ||= {}
@event_queues[target][callback] ||= []
@event_queues[target][callback] += events
end
def queued_events(resource)
return unless callbacks = @event_queues[resource]
callbacks.each do |callback, events|
yield callback, events
end
end
private
def process_callback(resource, callback, events)
process_noop_events(resource, callback, events) and return false unless events.detect { |e| e.status != "noop" }
resource.send(callback)
resource.notice "Triggered '#{callback}' from #{events.length} events"
return true
rescue => detail
resource.err "Failed to call #{callback}: #{detail}"
transaction.resource_status(resource).failed_to_restart = true
puts detail.backtrace if Puppet[:trace]
return false
end
def process_noop_events(resource, callback, events)
resource.notice "Would have triggered '#{callback}' from #{events.length} events"
# And then add an event for it.
queue_events(resource, [resource.event(:status => "noop", :name => :noop_restart)])
true # so the 'and if' works
end
end
|