X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;ds=sidebyside;f=doc%2Fclasses%2FMCollective%2FRPC%2FActionRunner.html;fp=doc%2Fclasses%2FMCollective%2FRPC%2FActionRunner.html;h=79686b99be99360f58d93d94c6a7ae5ea520d284;hb=d1f1649ba43c5cbc43c4beb2380096ba051d646a;hp=0000000000000000000000000000000000000000;hpb=8a3fe7daeecccf43dd71c59371c5005400d35101;p=packages%2Fprecise%2Fmcollective.git diff --git a/doc/classes/MCollective/RPC/ActionRunner.html b/doc/classes/MCollective/RPC/ActionRunner.html new file mode 100644 index 0000000..79686b9 --- /dev/null +++ b/doc/classes/MCollective/RPC/ActionRunner.html @@ -0,0 +1,534 @@ + + + + +
+Class | +MCollective::RPC::ActionRunner | +
In: | +
+
+ lib/mcollective/rpc/actionrunner.rb
+
+ + |
+
Parent: | ++ Object + | +
+A helper used by RPC::Agent#implemented_by to delegate an action to an +external script. At present only JSON based serialization is supported in +future ones based on key=val pairs etc will be added +
++It serializes the request object into an input file and creates an empty +output file. It then calls the external command reading the output file at +the end. +
++any STDERR gets logged at error level and any STDOUT gets logged at info +level. +
++It will interpret the exit code from the application the same way RPC::Reply#fail! and fail handles their codes +creating a consistent interface, the message part of the fail message will +come from STDERR +
++Generally externals should just exit with code 1 on failure and print to +STDERR, this is exactly what Perl die() does and translates perfectly to +our model +
++It uses the MCollective::Shell wrapper to call +the external application +
+ +action | +[R] | ++ |
agent | +[R] | ++ |
command | +[R] | ++ |
format | +[R] | ++ |
request | +[R] | ++ |
stderr | +[R] | ++ |
stdout | +[R] | ++ |
+ # File lib/mcollective/rpc/actionrunner.rb, line 26 +26: def initialize(command, request, format=:json) +27: @agent = request.agent +28: @action = request.action +29: @format = format +30: @request = request +31: @command = path_to_command(command) +32: @stdout = "" +33: @stderr = "" +34: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 117 +117: def canrun?(command) +118: File.executable?(command) +119: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 91 +91: def load_json_results(file) +92: return {} unless File.readable?(file) +93: +94: JSON.load(File.read(file)) || {} +95: rescue JSON::ParserError +96: {} +97: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 73 +73: def load_results(file) +74: Log.debug("Attempting to load results in #{format} format from #{file}") +75: +76: data = {} +77: +78: if respond_to?("load_#{format}_results") +79: tempdata = send("load_#{format}_results", file) +80: +81: tempdata.each_pair do |k,v| +82: data[k.to_sym] = v +83: end +84: end +85: +86: data +87: rescue Exception => e +88: {} +89: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 129 +129: def path_to_command(command) +130: unless command[0,1] == File::SEPARATOR +131: Config.instance.libdir.each do |libdir| +132: command_file = File.join(libdir, "agent", agent, command) +133: +134: return command_file if File.exist?(command_file) +135: end +136: end +137: +138: return command +139: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 36 +36: def run +37: unless canrun?(command) +38: Log.warn("Cannot run #{to_s}") +39: raise RPCAborted, "Cannot execute #{to_s}" +40: end +41: +42: Log.debug("Running #{to_s}") +43: +44: request_file = saverequest(request) +45: reply_file = tempfile("reply") +46: reply_file.close +47: +48: runner = shell(command, request_file.path, reply_file.path) +49: +50: runner.runcommand +51: +52: Log.debug("#{command} exited with #{runner.status.exitstatus}") +53: +54: stderr.each_line {|l| Log.error("#{to_s}: #{l.chomp}")} unless stderr.empty? +55: stdout.each_line {|l| Log.info("#{to_s}: #{l.chomp}")} unless stdout.empty? +56: +57: {:exitstatus => runner.status.exitstatus, +58: :stdout => runner.stdout, +59: :stderr => runner.stderr, +60: :data => load_results(reply_file.path)} +61: ensure +62: request_file.close! if request_file.respond_to?("close!") +63: reply_file.close! if reply_file.respond_to?("close") +64: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 113 +113: def save_json_request(req) +114: req.to_json +115: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 99 + 99: def saverequest(req) +100: Log.debug("Attempting to save request in #{format} format") +101: +102: if respond_to?("save_#{format}_request") +103: data = send("save_#{format}_request", req) +104: +105: request_file = tempfile("request") +106: request_file.puts data +107: request_file.close +108: end +109: +110: request_file +111: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 66 +66: def shell(command, infile, outfile) +67: env = {"MCOLLECTIVE_REQUEST_FILE" => infile, +68: "MCOLLECTIVE_REPLY_FILE" => outfile} +69: +70: Shell.new("#{command} #{infile} #{outfile}", :cwd => Dir.tmpdir, :stdout => stdout, :stderr => stderr, :environment => env) +71: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 125 +125: def tempfile(prefix) +126: Tempfile.new("mcollective_#{prefix}", Dir.tmpdir) +127: end ++
+ # File lib/mcollective/rpc/actionrunner.rb, line 121 +121: def to_s +122: "%s#%s command: %s" % [ agent, action, command ] +123: end ++