Tags

refs
filesystems
retro gaming
raspberry pi
sinatra
3d printing
nethack
gcc
compiler
fedora
virtfs
project
gaming
vim
grep
sed
aikido
philosophy
splix
android
lvm
storage
bitcoin
projects
sig315
miq
db
polisher
meditation
hopex
conferences
omega
simulator
bundler_ext
rubygems
ruby
book review
google code in
isitfedoraruby
svn
gsoc
design patters
jsonrpc
rjr
aeolus
ohiolinuxfest
rome
europe
travel
brno
gtk
python
puppet
conference
fudcon
html5
snap
tips
ssh
linux
hardware
libvirt
virtualization
engineering expo
cloud
rpm
yum
rake
redmine
plugins
screencasting
jruby
fosscon
pidgin
gnome-shell
distros
notacon
presentation
rails
deltacloud
apache
qmf
passenger
syrlug
hackerspace
music
massive attack
backups
crypto
vnc
xsd
rxsd
x3d
mercurial
webdev
qpid
ovirt
haikus
poetry
legaleese
jquery
selenium
testing
xpath
git
sshfs
svg
ldap
autotools
pygtk
xmlrpc
slackware

Nov 12 2010 apache qmf

Getting Started w/ Apache QMF

The Qpid Management Framework is a powerful open source remoting framework which developers can use to query and invoke methods on managed objects residing on a remote host. As with most other things its fairly straightforward to use when you know it, but it is currently still relatively early in development, and thus there isn't a whole lot of great documentation out there.

To start of, you should read this document thoroughly to familiarize yourself with all the necessary terms. In a gist, a developer will write an 'agent' who is responsible for dispatching requests to managed objects locally, returning results as neccessary. The objects provided and associated properties/methods are detailed via a 'schema'. The agent will register the object classes that it is managing with a 'broker' who is responsible for establishing and maintaining the communication channels, locating the correct agent when a client, known as a 'console', makes a request for a certain object class. With Apache QMF, the Apache QPID daemon also provides QMF broker functionality.

I've written and attached a sample QMF agent/console I've written for anyone who'se looking to start off. It is based of the more complete/robust ovirt-agent (though simplified greatly since its a new developer tutorial), and confusingly enough the agent was written using the Ruby QMF module while the console was written using Ruby QPID::QMF (see my findings on the difference here, I went this way since the example I'm basing this off of, ovirt-agent, does as well).

######################################## Agent

#!/usr/bin/ruby
#
# Simple QMF Agent Example

require 'qmf'

# class which will do the work 
# we need for our application
class Widget
 public
  attr_accessor :socket
  def initialize
     @socket = "foo"
  end

  def do_something(data)
     puts "doing something with " + data.to_s
  end
end

# setup the Widget Qmf schema
# -or- use something like 
#  http://git.et.redhat.com/?p=ovirt-server.git;a=blob;f=src/ovirt-agent/lib/ovirt/schema_parser.rb
$widget_schema = Qmf::SchemaObjectClass.new("org.morsi.test", "Widget")
$widget_schema.add_property(Qmf::SchemaProperty.new("socket", Qmf::TYPE_SSTR))
$do_something_schema = Qmf::SchemaMethod.new("do_something")
$do_something_schema.add_argument(Qmf::SchemaArgument.new("data", Qmf::TYPE_SSTR, {:dir => Qmf::DIR_IN}))
$widget_schema.add_method($do_something_schema)

# will handle incoming requests for objects and method invocations
class WidgetAgent < Qmf::AgentHandler

   # implementation of Qmf::AgentHandler.get_query callback
   # called when a client requests an object
   def get_query(context, query, user_id)
      puts "Query: context=#{context} class=#{query.class_name} object_id=#{query.object_id} user_id=#{user_id}"

      # !!! you should actually handle get_query here, by using the specified 
      # class_name and query attributes to lookup and return matching objects
      widget = Widget.new
      obj = Qmf::AgentObject.new($widget_schema)
      obj[:socket] = widget.socket
      obj.set_object_id(@agent.alloc_object_id)

      # get_query must perform these steps to return the response
      @agent.query_response(context, obj)
      @agent.query_complete(context)
   end

   # implementation of Qmf::AgentHandler.method_call callback
   # called when a client invokes a method on an object
   def method_call(context, name, object_id, args, user_id)
      puts "Method: context=#{context} method=#{name} object_id=#{object_id}, args=#{args} user_id=#{user_id}"

      # !!! you should actually handle method_call here, by using the speicifed
      # class_name, object_id, and method name / args to invoke the correct method
      # on the correct object
      Widget.new.do_something(args["data"])

      @agent.method_response(context, 0, "OK", args)
   end

   def initialize
      # connect to specified broker & register self as agent handler
      @settings = Qmf::ConnectionSettings.new
      @settings.host = "localhost"
      #@settings.port = port
      @connection = Qmf::Connection.new(@settings)
      @agent = Qmf::Agent.new(self)

      # register classes that we provide
      @agent.register_class($widget_schema)
    end

  def mainloop
    Thread.abort_on_exception = true
    @agent.set_connection(@connection)
    sleep
  end
end

widget_agent = WidgetAgent.new
widget_agent.mainloop


######################################## Console

#!/usr/bin/ruby
#
# Simple QMF Console Example

require 'qpid'

@session = Qpid::Qmf::Session.new
@session.add_broker
@session.objects(:class => "queue", 
                 :package => "org.apache.qpid.broker").each { |q|
  puts "Queue " + q.to_s
}

widgets = @session.objects(:class => "Widget", 
                           :package => "org.morsi.test")
widgets.each { |w|
  puts "Widget " + w.to_s + " " + w.socket.to_s
  for (key, val) in w.properties
    puts "    property: #{key}, #{val}"
  end
  result = w.do_something('4.20')
}

########################################

Check this blog again (or subscribe to the feed) for more about qmf in the future. Enjoy!