Updated mcollective.init according to OSCI-658
[packages/precise/mcollective.git] / lib / mcollective / rpc.rb
diff --git a/lib/mcollective/rpc.rb b/lib/mcollective/rpc.rb
new file mode 100644 (file)
index 0000000..575d069
--- /dev/null
@@ -0,0 +1,182 @@
+require 'pp'
+
+module MCollective
+  # Toolset to create a standard interface of client and agent using
+  # an RPC metaphor, standard compliant agents will make it easier
+  # to create generic clients like web interfaces etc
+  module RPC
+    autoload :ActionRunner, "mcollective/rpc/actionrunner"
+    autoload :Agent, "mcollective/rpc/agent"
+    autoload :Audit, "mcollective/rpc/audit"
+    autoload :Client, "mcollective/rpc/client"
+    autoload :Helpers, "mcollective/rpc/helpers"
+    autoload :Progress, "mcollective/rpc/progress"
+    autoload :Reply, "mcollective/rpc/reply"
+    autoload :Request, "mcollective/rpc/request"
+    autoload :Result, "mcollective/rpc/result"
+    autoload :Stats, "mcollective/rpc/stats"
+
+    # Creates a standard options hash, pass in a block to add extra headings etc
+    # see Optionparser
+    def rpcoptions
+      oparser = MCollective::Optionparser.new({:verbose => false, :progress_bar => true}, "filter")
+
+      options = oparser.parse do |parser, options|
+        if block_given?
+          yield(parser, options)
+        end
+
+        Helpers.add_simplerpc_options(parser, options)
+      end
+
+      return options
+    end
+
+    # Wrapper to create clients, supposed to be used as
+    # a mixin:
+    #
+    # include MCollective::RPC
+    #
+    # exim = rpcclient("exim")
+    # printrpc exim.mailq
+    #
+    # or
+    #
+    # rpcclient("exim") do |exim|
+    #    printrpc exim.mailq
+    # end
+    #
+    # It will take a few flags:
+    #    :configfile => "etc/client.cfg"
+    #    :options => options
+    #    :exit_on_failure => true
+    #
+    # Options would be a build up options hash from the Optionparser
+    # you can use the rpcoptions helper to create this
+    #
+    # :exit_on_failure is true by default, and causes the application to
+    # exit if there is a failure constructing the RPC client. Set this flag
+    # to false to cause an Exception to be raised instead.
+    def rpcclient(agent, flags = {})
+      configfile = flags[:configfile] || "/etc/mcollective/client.cfg"
+      options = flags[:options] || nil
+
+      if flags.key?(:exit_on_failure)
+        exit_on_failure = flags[:exit_on_failure]
+      else
+        # We exit on failure by default for CLI-friendliness
+        exit_on_failure = true
+      end
+
+      begin
+        if options
+          rpc = Client.new(agent, :configfile => options[:config], :options => options)
+          @options = rpc.options
+        else
+          rpc = Client.new(agent, :configfile => configfile)
+          @options = rpc.options
+        end
+      rescue Exception => e
+        if exit_on_failure
+          puts("Could not create RPC client: #{e}")
+          exit!
+        else
+          raise e
+        end
+      end
+
+      if block_given?
+        yield(rpc)
+      else
+        return rpc
+      end
+    end
+
+    # means for other classes to drop stats into this module
+    # its a bit hacky but needed so that the mixin methods like
+    # printrpcstats can easily get access to it without
+    # users having to pass it around in params.
+    def self.stats(stats)
+      @@stats = stats
+    end
+
+    # means for other classes to drop discovered hosts into this module
+    # its a bit hacky but needed so that the mixin methods like
+    # printrpcstats can easily get access to it without
+    # users having to pass it around in params.
+    def self.discovered(discovered)
+      @@discovered = discovered
+    end
+
+    # Prints stats, requires stats to be saved from elsewhere
+    # using the MCollective::RPC.stats method.
+    #
+    # If you've passed -v on the command line a detailed stat block
+    # will be printed, else just a one liner.
+    #
+    # You can pass flags into it:
+    #
+    #   printrpcstats :caption => "Foo", :summarize => true
+    #
+    # This will use "Foo" as the caption to the stats in verbose
+    # mode and print out any aggregate summary information if present
+    def printrpcstats(flags={})
+      return unless @options[:output_format] == :console
+
+      flags = {:summarize => false, :caption => "rpc stats"}.merge(flags)
+
+      verbose = @options[:verbose] rescue verbose = false
+
+      begin
+        stats = @@stats
+      rescue
+        puts("no stats to display")
+        return
+      end
+
+      puts stats.report(flags[:caption], flags[:summarize], verbose)
+    end
+
+    # Prints the result of an RPC call.
+    #
+    # In the default quiet mode - no flattening or verbose - only results
+    # that produce an error will be printed
+    #
+    # To get details of each result run with the -v command line option.
+    def printrpc(result, flags = {})
+      verbose = @options[:verbose] rescue verbose = false
+      verbose = flags[:verbose] || verbose
+      flatten = flags[:flatten] || false
+      format = @options[:output_format]
+      forced_mode = @options[:force_display_mode] || false
+
+      result_text =  Helpers.rpcresults(result, {:verbose => verbose, :flatten => flatten, :format => format, :force_display_mode => forced_mode})
+
+      if result.is_a?(Array) && format == :console
+        puts "\n%s\n" % [ result_text ]
+      else
+        # when we get just one result to print dont pad them all with
+        # blank spaces etc, just print the individual result with no
+        # padding
+        puts result_text unless result_text == ""
+      end
+    end
+
+    # Wrapper for MCollective::Util.empty_filter? to make clients less fugly
+    # to write - ticket #18
+    def empty_filter?(options)
+      if options.include?(:filter)
+        Util.empty_filter?(options[:filter])
+      else
+        Util.empty_filter?(options)
+      end
+    end
+
+    def self.const_missing(const_name)
+      super unless const_name == :DDL
+
+      Log.warn("MCollective::RPC::DDL is deprecatd, please use MCollective::DDL instead")
+      MCollective::DDL
+    end
+  end
+end