Getting Started

Installation

First, install and start QPID (qpidd)

Then,

  1. Install gofer.

    yum install gofer python-gofer-qpid
    
  2. Edit the /etc/gofer/plugins/demo.conf and set the url to point at your broker. Then, set queue=123. Or, look in /var/log/messages to find the auto-assigned UUID for your system.

    [main]
    

    enabled = 1

    [messaging] url=qpid+amqp://localhost

    [model] queue=123

  3. Start the goferd service.

    service goferd start
    
  4. Now, invoke the remote operations provided by the demo plugin:

Python

>>> from gofer.proxy import Agent
>>>
>>> url = 'amqp://localhost'
>>> agent = Agent(url, '123')
>>> admin = agent.Admin()
>>> print admin.help()
    Plugins:
      demo
    Actions:
      demo.TestAction.hello() 0:10:00
    Methods:
     Admin.hello()
     Admin.help()
     Shell.run()
   Functions:
     demo.echo()

Writing A Plugin

The installing plugins is done in 6 easy steps.

  1. Write your plugin descriptor.
  2. Write your plugin module.
  3. Copy (or symlink) the plugin descriptor (myplugin.conf) to /etc/gofer/plugins/
  4. Copy (or symlink) the plugin module (myplugin.py) to /usr/lib/gofer/plugins/
  5. Restart goferd
  6. Add server side code to invoke remote methods

Let’s create a plugin named myplugin.

Step 1

Create your plugin descriptor (myplugin.conf) as follows:

[main]
enabled = 1

[messaging]
url=qpid+amqp://localhost

[model]
queue=123

Step 2

Write your plugin. It will be defined in a module named myplugin.py and would look something like this:

from gofer.decorators import  *

class MyClass:

   @remote
   def hello(self):
       return 'MyPlugin says, "hello".'

Stand alone (plain) functions may be decorated as remote.

Your class may have constructor arguments.

from gofer.decorators import  *

@remote
def hello(self):
   return 'MyPlugin says, "hello".'

Step 3

Install or update your plugin descriptor.

cp myplugin.conf /etc/gofer/plugins

Step 4

Install or update your plugin.

cp myplugin.py /usr/lib/gofer/plugins

Step 5

Restart the gofer daemon.

sudo /etc/sbin/service goferd restart

Step 6

Add server-side code to invoke methods on your plugin.

This is done by instantiating a proxy for the agent. You need to specifying the uuid of the agent (plugin).

...
# your server code
from gofer.proxy import Agent

url = 'amqp://localhost'
uuid = '123'
agent = Agent(url, uuid)
myclass = agent.MyClass()
myclass.hello()

Invoke the stand alone function. Instead of instantiating the remote class, the function is invoked directly using the plugin module’s namespace:

...
# your server code
from gofer.proxy import Agent

url = 'amqp://localhost'
uuid = '123'
agent = Agent(url, uuid)
agent.myplugin.hello()

Interactive Testing

After adding classes or methods in myplugin.py, you’ll want to test them. First, ensure the plugin is still loading properly. The easiest way to do this is by examining the gofer log file at: /var/log/gofer/agent. At start up, you should see something like:

2010-11-08 08:49:04,909 [INFO][MainThread] __import() @ plugin.py:103 - plugin "myplugin", imported as: "myplugin"

The gofer log (/var/log/messages) may be examined to verify that Actions are running as expected. Also, RMI requests (massages) are logged upon receipt in the gofer agent log.

Testing added remote methods, can be done easily using an interactive python (shell). Be sure your changes to your plugin have been picked up by Gofer by restarting goferd. Let’s say you added a new class named “Foo” that has a remote method named … you guessed it: “bar”. You can test your new stuff as follows:

[jortel@localhost pulp]$ python
Python 2.6.2 (r262:71600, Jun  4 2010, 18:28:04)
[GCC 4.4.3 20100127 (Red Hat 4.4.3-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from gofer.proxy import Agent
>>>
>>> url = 'amqp://localhost'
>>> uuid = '123'
>>> agent = Agent(url, uuid)
>>> myclass = agent.MyClass()
>>> print myclass.hello()
MyPlugin says, "hello".

Another useful tool, it invoke Admin.help() from within interactive python as follows:

[jortel@localhost pulp]$ python
Python 2.6.2 (r262:71600, Jun  4 2010, 18:28:04)
[GCC 4.4.3 20100127 (Red Hat 4.4.3-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from gofer.proxy import Agent
>>>
>>> url = 'amqp://localhost'
>>> uuid = '123'
>>> agent = Agent(url, uuid)
>>> admin = agent.Admin()
>>> print admin.help()

Plugins:
  demo
  myplugin
Actions:
  demo.TestAction 0:10:00
Methods:
  myplugin.MyClass.hello()
  demo.AgentAdmin.hello()
  demo.AgentAdmin.help()
  demo.Shell.run()
Functions:
  demo.echo()
>>>

Security

The @remote decorator and gofer infrastructure supports (1) option:

  • secret (default=None): A shared secret used for authentication. The value may be:
    • str
    • [str,..]
    • (str,..)
    • callable

In this example, MyClass.hello() must provide the secret to be invoked.

c = agent.MyClass(secret='mycathas9lives')
c.hello()
from gofer.decorators import  *

class MyClass:

   @remote(secret='mycathas9lives')
   def hello(self):
       return 'MyPlugin says, "hello".'

The decorator also support the secret being a callable that returns the secret matched to the request.

Example:

from gofer.decorators import  *

def getsecret():
   ...
  return secret

class MyClass:

   @remote(secret=getsecret)
   def hello(self):
       return 'MyPlugin says, "hello".'