X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=lib%2Fmcollective%2Fdiscovery.rb;fp=lib%2Fmcollective%2Fdiscovery.rb;h=824baf68c07a7b7697edf0246117c35ad6c641fb;hb=b87d2f4e68281062df1913440ca5753ae63314a9;hp=0000000000000000000000000000000000000000;hpb=ab0ea530b8ac956091f17b104ab2311336cfc250;p=packages%2Fprecise%2Fmcollective.git diff --git a/lib/mcollective/discovery.rb b/lib/mcollective/discovery.rb new file mode 100644 index 0000000..824baf6 --- /dev/null +++ b/lib/mcollective/discovery.rb @@ -0,0 +1,143 @@ +module MCollective + class Discovery + def initialize(client) + @known_methods = find_known_methods + @default_method = Config.instance.default_discovery_method + @client = client + end + + def find_known_methods + PluginManager.find("discovery") + end + + def has_method?(method) + @known_methods.include?(method) + end + + def force_direct_mode? + discovery_method != "mc" + end + + def discovery_method + method = "mc" + + if @client.options[:discovery_method] + method = @client.options[:discovery_method] + else + method = @default_method + end + + raise "Unknown discovery method %s" % method unless has_method?(method) + + unless method == "mc" + raise "Custom discovery methods require direct addressing mode" unless Config.instance.direct_addressing + end + + return method + end + + def discovery_class + method = discovery_method.capitalize + + PluginManager.loadclass("MCollective::Discovery::#{method}") unless self.class.const_defined?(method) + + self.class.const_get(method) + end + + def ddl + @ddl ||= DDL.new(discovery_method, :discovery) + + # if the discovery method got changed we might have an old DDL cached + # this will detect that and reread the correct DDL from disk + unless @ddl.meta[:name] == discovery_method + @ddl = DDL.new(discovery_method, :discovery) + end + + return @ddl + end + + # Agent filters are always present no matter what, so we cant raise an error if the capabilities + # suggest the discovery method cant do agents we just have to rely on the discovery plugin to not + # do stupid things in the presense of a agent filter + def check_capabilities(filter) + capabilities = ddl.discovery_interface[:capabilities] + + unless capabilities.include?(:classes) + raise "Cannot use class filters while using the '%s' discovery method" % discovery_method unless filter["cf_class"].empty? + end + + unless capabilities.include?(:facts) + raise "Cannot use fact filters while using the '%s' discovery method" % discovery_method unless filter["fact"].empty? + end + + unless capabilities.include?(:identity) + raise "Cannot use identity filters while using the '%s' discovery method" % discovery_method unless filter["identity"].empty? + end + + unless capabilities.include?(:compound) + raise "Cannot use compound filters while using the '%s' discovery method" % discovery_method unless filter["compound"].empty? + end + end + + # checks if compound filters are used and then forces the 'mc' discovery plugin + def force_discovery_method_by_filter(filter) + unless discovery_method == "mc" + unless filter["compound"].empty? + Log.info "Switching to mc discovery method because compound filters are used" + @client.options[:discovery_method] = "mc" + + return true + end + end + + return false + end + + # if a compound filter is specified and it has any function + # then we read the DDL for each of those plugins and sum up + # the timeout declared in the DDL + def timeout_for_compound_filter(compound_filter) + return 0 if compound_filter.nil? || compound_filter.empty? + + timeout = 0 + + compound_filter.each do |filter| + filter.each do |statement| + if statement["fstatement"] + pluginname = Data.pluginname(statement["fstatement"]["name"]) + ddl = DDL.new(pluginname, :data) + timeout += ddl.meta[:timeout] + end + end + end + + timeout + end + + def discovery_timeout(timeout, filter) + timeout = ddl.meta[:timeout] unless timeout + + unless (filter["compound"] && filter["compound"].empty?) + timeout + timeout_for_compound_filter(filter["compound"]) + else + timeout + end + end + + def discover(filter, timeout, limit) + raise "Limit has to be an integer" unless limit.is_a?(Fixnum) + + force_discovery_method_by_filter(filter) + + check_capabilities(filter) + + discovered = discovery_class.discover(filter, discovery_timeout(timeout, filter), limit, @client) + + if limit > 0 + return discovered[0,limit] + else + return discovered + end + end + end +end