diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-11-26 09:55:04 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-11-26 09:55:04 +0000 |
commit | ccd7b581bf990df618d410441c1f8d349aa225d9 (patch) | |
tree | 768e134483b5ed8f82adc69eebba7e8a7146b55e /lib/puppet | |
parent | c301b1b8f7fb417cf61b6ad4975eaa3714100306 (diff) | |
download | puppet-ccd7b581bf990df618d410441c1f8d349aa225d9.tar.gz puppet-ccd7b581bf990df618d410441c1f8d349aa225d9.tar.xz puppet-ccd7b581bf990df618d410441c1f8d349aa225d9.zip |
Intermediate commit -- I am ready to start pushing the graph stuff into the types and transactions, which will break everything for a little while.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1894 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/pgraph.rb | 170 | ||||
-rw-r--r-- | lib/puppet/relationship.rb | 51 | ||||
-rw-r--r-- | lib/puppet/transaction.rb | 8 | ||||
-rw-r--r-- | lib/puppet/type/component.rb | 19 | ||||
-rw-r--r-- | lib/puppet/util/graph.rb | 23 |
5 files changed, 248 insertions, 23 deletions
diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb new file mode 100644 index 000000000..fba93d20c --- /dev/null +++ b/lib/puppet/pgraph.rb @@ -0,0 +1,170 @@ +#!/usr/bin/env ruby +# +# Created by Luke A. Kanies on 2006-11-24. +# Copyright (c) 2006. All rights reserved. + +require 'puppet/gratr/digraph' +require 'puppet/gratr/import' +require 'puppet/gratr/dot' +require 'puppet/relationship' + +# This class subclasses a graph class in order to handle relationships +# among resources. +class Puppet::PGraph < GRATR::Digraph + # Collect all of the targets for the list of events. Basically just iterates + # over the sources of the events and returns all of the targets of them. + def collect_targets(events) + events.collect do |event| + source = event.source + start = source + + # Get all of the edges that this vertex points at + adjacent(source, :direction => :out, :type => :edges).find_all do |edge| + edge.match?(event.event) + end.collect { |event| + target = event.target + if target.respond_to?(:ref) + source.info "Scheduling %s of %s" % + [event.callback, target.ref] + end + target + } + end.flatten + end + + # The dependencies for a given resource. + def dependencies(resource) + tree_from_vertex(resource, :dfs).keys + end + + # Override this method to use our class instead. + def edge_class() + Puppet::Relationship + end + + # Determine all of the leaf nodes below a given vertex. + def leaves(vertex, type = :dfs) + tree = tree_from_vertex(vertex, type) + leaves = tree.keys.find_all { |c| adjacent(c, :direction => :out).empty? } + return leaves + end + + # Take container information from another graph and use it + # to replace any container vertices with their respective leaves. + # This creates direct relationships where there were previously + # indirect relationships through the containers. + def splice!(other, type) + vertices.each do |vertex| + # Go through each vertex and replace the edges with edges + # to the leaves instead + next unless vertex.is_a?(type) + + leaves = other.leaves(vertex) + next if leaves.empty? + + # First create new edges for each of the :in edges + adjacent(vertex, :direction => :in).each do |up| + leaves.each do |leaf| + add_edge!(up, leaf) + if cyclic? + raise ArgumentError, + "%s => %s results in a loop" % + [up, leaf] + end + end + end + + # Then for each of the out edges + adjacent(vertex, :direction => :out).each do |down| + leaves.each do |leaf| + add_edge!(leaf, down) + if cyclic? + raise ArgumentError, + "%s => %s results in a loop" % + [leaf, down] + end + end + end + + # And finally, remove the vertex entirely. + remove_vertex!(vertex) + end + end + + # Trigger any subscriptions to a child. This does an upwardly recursive + # search -- it triggers the passed object, but also the object's parent + # and so on up the tree. + def trigger(child) + obj = child + callbacks = Hash.new { |hash, key| hash[key] = [] } + sources = Hash.new { |hash, key| hash[key] = [] } + + trigged = [] + while obj + if @targets.include?(obj) + callbacks.clear + sources.clear + @targets[obj].each do |event, sub| + # Collect all of the subs for each callback + callbacks[sub.callback] << sub + + # And collect the sources for logging + sources[event.source] << sub.callback + end + + sources.each do |source, callbacklist| + obj.debug "%s[%s] results in triggering %s" % + [source.class.name, source.name, callbacklist.join(", ")] + end + + callbacks.each do |callback, subs| + message = "Triggering '%s' from %s dependencies" % + [callback, subs.length] + obj.notice message + # At this point, just log failures, don't try to react + # to them in any way. + begin + obj.send(callback) + @resourcemetrics[:restarted] += 1 + rescue => detail + obj.err "Failed to call %s on %s: %s" % + [callback, obj, detail] + + @resourcemetrics[:failed_restarts] += 1 + + if Puppet[:debug] + puts detail.backtrace + end + end + + # And then add an event for it. + trigged << Puppet::Event.new( + :event => :triggered, + :transaction => self, + :source => obj, + :message => message + ) + + triggered(obj, callback) + end + end + + obj = obj.parent + end + + if trigged.empty? + return nil + else + return trigged + end + end + + def to_jpg(name) + gv = vertices() + Dir.chdir("/Users/luke/Desktop/pics") do + induced_subgraph(gv).write_to_graphic_file('jpg', name) + end + end +end + +# $Id$ diff --git a/lib/puppet/relationship.rb b/lib/puppet/relationship.rb new file mode 100644 index 000000000..cbd15b2af --- /dev/null +++ b/lib/puppet/relationship.rb @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby +# +# Created by Luke A. Kanies on 2006-11-24. +# Copyright (c) 2006. All rights reserved. + +require 'puppet/gratr' + +# subscriptions are permanent associations determining how different +# objects react to an event + +class Puppet::Relationship < GRATR::Edge + # Return the callback + def callback + label[:callback] + end + + # Return our event. + def event + label[:event] + end + + def initialize(source, target, label = nil) + if label + unless label.is_a?(Hash) + raise Puppet::DevError, "The label must be a hash" + end + + if label[:event] and label[:event] != :NONE and ! label[:callback] + raise Puppet::DevError, "You must pass a callback for non-NONE events" + end + else + label = {} + end + + super(source, target, label) + end + + # Does the passed event match our event? This is where the meaning + # of :NONE comes from. + def match?(event) + if event == :NONE or self.event == :NONE + return false + elsif self.event == :ALL_EVENTS or event == :ALL_EVENTS or event == self.event + return true + else + return false + end + end +end + +# $Id$ diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index a7ea48a19..1551acbb6 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -29,7 +29,7 @@ class Transaction # First make sure there are no failed dependencies child.eachdependency do |dep| skip = false - if @failures[dep] > 0 + if fails = failed?(dep) child.notice "Dependency %s[%s] has %s failures" % [dep.class.name, dep.name, @failures[dep]] skip = true @@ -209,7 +209,11 @@ class Transaction # Determine whether a given object has failed. def failed?(obj) - @failures[obj] > 0 + if @failures[obj] > 0 + return @failures[obj] + else + return false + end end # this should only be called by a Puppet::Container object now diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb index c159ccc83..3165d9e11 100644 --- a/lib/puppet/type/component.rb +++ b/lib/puppet/type/component.rb @@ -5,6 +5,7 @@ require 'puppet' require 'puppet/type' require 'puppet/transaction' +require 'puppet/pgraph' module Puppet newtype(:component) do @@ -149,6 +150,24 @@ module Puppet end } end + + # Convert to a graph object with all of the container info. + def to_graph + graph = Puppet::PGraph.new + + delver = proc do |obj| + obj.each do |child| + if child.is_a?(Puppet::Type) + graph.add_edge!(obj, child) + delver.call(child) + end + end + end + + delver.call(self) + + return graph + end def to_s return "component(%s)" % self.title diff --git a/lib/puppet/util/graph.rb b/lib/puppet/util/graph.rb index c32d15cb4..d9e122c7b 100644 --- a/lib/puppet/util/graph.rb +++ b/lib/puppet/util/graph.rb @@ -2,18 +2,7 @@ # Copyright (c) 2006. All rights reserved. require 'puppet' -require 'puppet/gratr/digraph' -require 'puppet/gratr/import' -require 'puppet/gratr/dot' - -class GRATR::Digraph - # Determine all of the leaf nodes below a given vertex. - def leaves(vertex, type = :dfs) - tree = tree_from_vertex(vertex, type) - leaves = tree.keys.find_all { |c| adjacent(c, :direction => :out).empty? } - return leaves - end -end +require 'puppet/pgraph' # A module that handles the small amount of graph stuff in Puppet. module Puppet::Util::Graph @@ -23,7 +12,7 @@ module Puppet::Util::Graph def to_graph(graph = nil, &block) # Allow our calling function to send in a graph, so that we # can call this recursively with one graph. - graph ||= GRATR::Digraph.new + graph ||= Puppet::PGraph.new self.each do |child| unless block_given? and ! yield(child) @@ -45,14 +34,6 @@ module Puppet::Util::Graph graph end - - def to_jpg(graph = nil) - graph ||= to_graph - gv = graph.vertices - Dir.chdir("/Users/luke/Desktop/pics") do - graph.induced_subgraph(gv).write_to_graphic_file('jpg', 'graph') - end - end end # $Id$
\ No newline at end of file |