Class | MCollective::RPC::Agent |
In: |
lib/mcollective/rpc/agent.rb
|
Parent: | Object |
A wrapper around the traditional agent, it takes care of a lot of the tedious setup you would do for each agent allowing you to just create methods following a naming standard leaving the heavy lifting up to this clas.
See marionette-collective.org/simplerpc/agents.html
It only really makes sense to use this with a Simple RPC client on the other end, basic usage would be:
module MCollective module Agent class Helloworld<RPC::Agent matadata :name => "Test SimpleRPC Agent", :description => "A simple test", :author => "You", :license => "1.1", :url => "http://your.com/, :timeout => 60 action "hello" do reply[:msg] = "Hello #{request[:name]}" end action "foo" do implemented_by "/some/script.sh" end end end end
If you wish to implement the logic for an action using an external script use the implemented_by method that will cause your script to be run with 2 arguments.
The first argument is a file containing JSON with the request and the 2nd argument is where the script should save its output as a JSON hash.
We also currently have the validation code in here, this will be moved to plugins soon.
config | [R] | |
ddl | [R] | |
logger | [R] | |
meta | [RW] | |
reply | [RW] | |
request | [RW] | |
timeout | [R] |
By default RPC Agents support a toggle in the configuration that can enable and disable them based on the agent name
Example an agent called Foo can have:
plugin.foo.activate_agent = false
and this will prevent the agent from loading on this particular machine.
Agents can use the activate_when helper to override this for example:
activate_when do
File.exist?("/usr/bin/puppet")
end
# File lib/mcollective/rpc/agent.rb, line 143 143: def self.activate? 144: agent_name = self.to_s.split("::").last.downcase 145: 146: Log.debug("Starting default activation checks for #{agent_name}") 147: 148: should_activate = Config.instance.pluginconf["#{agent_name}.activate_agent"] 149: 150: if should_activate 151: Log.debug("Found plugin config #{agent_name}.activate_agent with value #{should_activate}") 152: unless should_activate =~ /^1|y|true$/ 153: return false 154: end 155: end 156: 157: return true 158: end
# File lib/mcollective/rpc/agent.rb, line 44 44: def initialize 45: # Default meta data unset 46: @meta = {:timeout => 10, 47: :name => "Unknown", 48: :description => "Unknown", 49: :author => "Unknown", 50: :license => "Unknown", 51: :version => "Unknown", 52: :url => "Unknown"} 53: 54: @timeout = meta[:timeout] || 10 55: @logger = Log.instance 56: @config = Config.instance 57: @agent_name = self.class.to_s.split("::").last.downcase 58: 59: # Loads the DDL so we can later use it for validation 60: # and help generation 61: begin 62: @ddl = DDL.new(@agent_name) 63: rescue Exception => e 64: Log.debug("Failed to load DDL for agent: #{e.class}: #{e}") 65: @ddl = nil 66: end 67: 68: # if we have a global authorization provider enable it 69: # plugins can still override it per plugin 70: self.class.authorized_by(@config.rpcauthprovider) if @config.rpcauthorization 71: 72: startup_hook 73: end
# File lib/mcollective/rpc/agent.rb, line 75 75: def handlemsg(msg, connection) 76: @request = RPC.request(msg) 77: @reply = RPC.reply 78: 79: begin 80: # Calls the authorization plugin if any is defined 81: # if this raises an exception we wil just skip processing this 82: # message 83: authorization_hook(@request) if respond_to?("authorization_hook") 84: 85: 86: # Audits the request, currently continues processing the message 87: # we should make this a configurable so that an audit failure means 88: # a message wont be processed by this node depending on config 89: audit_request(@request, connection) 90: 91: before_processing_hook(msg, connection) 92: 93: if respond_to?("#{@request.action}_action") 94: send("#{@request.action}_action") 95: else 96: raise UnknownRPCAction, "Unknown action: #{@request.action}" 97: end 98: rescue RPCAborted => e 99: @reply.fail e.to_s, 1 100: 101: rescue UnknownRPCAction => e 102: @reply.fail e.to_s, 2 103: 104: rescue MissingRPCData => e 105: @reply.fail e.to_s, 3 106: 107: rescue InvalidRPCData => e 108: @reply.fail e.to_s, 4 109: 110: rescue UnknownRPCError => e 111: @reply.fail e.to_s, 5 112: 113: rescue Exception => e 114: @reply.fail e.to_s, 5 115: 116: end 117: 118: after_processing_hook 119: 120: if @request.should_respond? 121: return @reply.to_hash 122: else 123: Log.debug("Client did not request a response, surpressing reply") 124: return nil 125: end 126: end