Chapter 15. Collecting Responses

One of the features which makes MCollective truly unique is the ability to send requests from one client, and to process the responses with a different client or Listener.

Request responses return via a custom queue to a Listener
Figure 15-1. A separate Listener to process results from requests

Create a Listener

The first thing we’ll do here is to create a listener. What I’ll introduce to you here is a working listener from which you can debug any problem. You can also copy it and add new functionality. I put my listeners in the $libdir directory just like every other plugin, but that’s not necessary nor standard.

$ cat /usr/libexec/mcollective/mcollective/listener/debugger.rb
# Parse options, load config, and start an MCollective client.
require 'mcollective'
optparser = MCollective::Optionparser.new
options = optparser.parse
config = MCollective::Config.instance
config.loadconfig(options[:config])
MCollective::PluginManager["security_plugin"].initiated_by = :client
connector = MCollective::PluginManager['connector_plugin']
connector.connect

# Get pretty-print and the Log object
require 'pp'
Log = MCollective::Log

# Get a reply queue name from anywhere, hardcoded here
replyqueue = 'debugger'
queuename = '/queue/mcollective.reply.' + replyqueue

# Here is the queue we want to listen to
connector.connection.subscribe( queuename, {}, "$$".to_i )

# consume all the things...
loop do
  # Get an mcollective Message object and configure it as a reply
  message = connector.receive
  message.type = :reply
  message.decode!          # security plugin validates authentication

  # This is the real data, everything else is envelope
  data = message.payload[:body][:data]

  # Do anything you want here
  pp data[:text]
end

Submit Reply-To

Now that we have a listener listening to our response queue, let’s kick off some commands:

$ mco rpc --agent service --action status --argument service=puppet --reply-to=/queue/mcollective.reply.debugger
Request sent with id: 12afa18ae2105390a73302967edddab8 replies to /queue/mcollective.reply.debugger

Warning

At the time this book was written, you had to use the direct RPC invocation of the agent to get a useful response back. This is filed under Puppet Labs BUG MCO-207 and I am hoping to remove this notice before the book goes to print.

Using a client application with the --reply-to option produces the following error message:

$ mco puppet status --reply-to /queue/mcollective.reply.mylistener

The mco application failed to run, use -v for full error backtrace details: undefined method `length' for nil:NilClass

$ mco ping --reply-to /queue/mcollective.reply.mylistener

---- ping statistics ----
No responses received

Both of those commands will work—you’ll receive the results on your response queue. But mco will produce the error message and return a failure response code.

You’ll notice that ping claims no responses. That’s because it’s a simple application, and didn’t realize you sent the result elsewhere. Ping also has a different response format, which we will discuss in the next section.

Process Responses

Let’s look at the results we receive. We’re expecting the hostname, agent, statusmessage, and a pretty-print output of the body:

$ ruby debugger.rb
geode/service: OK=0
{:status=>"running"}
sunstone/service: OK=0
{:status=>"running"}
heliotrope/service: OK=0
{:status=>"running"}

Yup, that’s exactly what we go. Now what about if we send it ping status? Ping is a discovery test that doesn’t include status messages. That’s the bottom part of the if/then in the code block. Here we just output the hostname and the body text.

$ ruby debugger.rb
ruby listen.rb
geode: "pong"
fireagate: "pong"
heliotrope: "pong"
sunstone: "pong"

How about if we do something with more data in the fields, like puppet status ?

geode/puppet: OK=0
{:daemon_present=>true,
 :status=>"idling",
 :enabled=>true,
 :message=>"Currently idling; last completed run 26 minutes 23 seconds ago",
 :idling=>true,
 :applying=>false,
 :lastrun=>1393571918,
 :disable_message=>"",
 :since_lastrun=>1583}
heliotrope/puppet: OK=0
...etc

As you can see, there are considerably more fields available to use in your output.

What if you want to see all the gory details? You might want to try adding one of the follow pretty-print commands. Each one of these is a little farther down, so you only need one of them. Looking at this output is an exercise for the reader: you’ll get to see a lot more of how a reply message is structured.

# Only use one of these, as each includes the ones beneath it.
  # All the gory details
  #pp message

  # Everything we care about is here
  #pp message.payload

  # This contains just the data in the response
  pp message.payload[:body]

How might you use this data? There’s no limit, really. Anything you can do in Ruby. Here’s a short list:

  1. Store it in NoSQL like Memcache, Mongo, or Hadoop
  2. Store it in a database (better keep that connection open for speed)
  3. Store it in a file
  4. Submit it to another system using a REST API

…I think you get the idea. Even the sky is not the limit, I hear that most satellites support RESTful APIs these days.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.81.43