X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;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 + + + + + + + + + + +
+ + + + + + + + + + + + + + +
ClassMCollective::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 +

+ +
+ + +
+ +
+

Methods

+ +
+ canrun?   + load_json_results   + load_results   + new   + path_to_command   + run   + save_json_request   + saverequest   + shell   + tempfile   + to_s   +
+
+ +
+ + + + +
+ + + + + +
+

Attributes

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
action [R] 
agent [R] 
command [R] 
format [R] 
request [R] 
stderr [R] 
stdout [R] 
+
+
+ + + + +
+

Public Class methods

+ +
+ + + + +
+

[Source]

+
+
+    # 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
+
+
+
+
+ +

Public Instance methods

+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/rpc/actionrunner.rb, line 117
+117:       def canrun?(command)
+118:         File.executable?(command)
+119:       end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # 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
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # 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
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # 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
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # 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
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/rpc/actionrunner.rb, line 113
+113:       def save_json_request(req)
+114:         req.to_json
+115:       end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # 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
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # 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
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/rpc/actionrunner.rb, line 125
+125:       def tempfile(prefix)
+126:         Tempfile.new("mcollective_#{prefix}", Dir.tmpdir)
+127:       end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/rpc/actionrunner.rb, line 121
+121:       def to_s
+122:         "%s#%s command: %s" % [ agent, action, command ]
+123:       end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file