The XCAT Scriptable Application Managers


Introduction

The Scriptable Application Manager is an attempt to make a generic CCA Component, which can act as a proxy for the actual applications. The actual functionality of the Component is defined by the script it loads and executes inside an interpreter, and this is the way it differs from other existing CCA Components. This leads to the ability to change the behaviour of the Components at run time, and the ability to manage various applications with minimal compilation. The Manager also has the capability of sprouting predefined CCA ports at runtime, so that it can communicate with other CCA components, and use the services provided by them.


Design

The Manager itself is fairly uncomplicated. A major component of the Manager is the Jython Interpreter to which the remote script gets downloaded. The Manager exports a CCA provides port called the ScriptPort, which has most methods that are required to manage the applications. In particular, it has a method "runScript", which downloads the script into the Manager, and begins execution. Another method which can be invoked on the port, is the "add{Provides | Uses}Port" method, which dynamically adds a precompiled CCA Port to the Component. The script can now get a handle to the ports, so added, and invoke methods on them. This ability of the Manager helps design a system consisting of a few such Scriptable Proxies, having custom made ports, which communicate with each other.

The scripts running inside the Manager are written in Jython, but they are enhanced as they are capable of using some of the libraries which are provided. The Jython scripts can access Globus Grid Resources using COG. They can use the SOAPRMI Events subsystem to send events to an event channel, so that the users get real time feedback about the status of the execution.


Usage

The following are the steps that are typically followed to set up a set of applications using the Application Managers. We illustrate it with a toy example of two application managers (a generator, and a printer), where one has a dynamically added provides port (printer) and the other a uses port (generator). A script is downloaded into the generator, which grabs hold of the just created uses port, and transfers a string to the printer.

Step #1

Start the required number of components as follows :

# create a component wrapper
generator = cca.createComponent(xml_description_of_application_manager)
printer = cca.createComponent(xml_description_of_application_manager)

# assign a machine name
cca.setMachineName(generator, "exodus.extreme.indiana.edu")
cca.setMachineName(printer, "exodus.extreme.indiana.edu")

# set a creation mechanism
cca.setCreationMechanism(generator, "gram")
cca.setCreationMechanism(printer, "gram")

# create a live instance
print "Creating Instance"
cca.createInstance(generator)
cca.createInstance(printer)

Step #2

Add the required provides and uses ports to the above application managers as follows :

# Information for the ScriptPort on which the methods are invoked
usesPortClassName = "samples.idl.scriptPort.UsesScriptPort"
usesPortType = "http://www.extreme.indiana.edu/xcat/samples/wsdl#scriptPort"
providesPortName = "scriptPortProvidesPort"

# add a provides port to the printer
methodName = "addProvidesPort"
methodParams = zeros(4, Object)

# information about the String provides port to be added
methodParams[0] = String("providesPrint")
methodParams[1] = String("http://www.extreme.indiana.edu/xcat/samples/wsdl#string")
methodParams[2] = String("samples.idl.string.ProvidesString")
methodParams[3] = String("samples.printer.StringImpl")

cca.invokeMethodOnComponent(printer, usesPortClassName, usesPortType,
                            providesPortName, methodName, methodParams)

# add a uses port to the generator
methodName = "addUsesPort"
methodParams = zeros(3, Object)

# information about the String uses port to be added
methodParams[0] = String("usesPrint")
methodParams[1] = String("http://www.extreme.indiana.edu/xcat/samples/wsdl#string")
methodParams[2] = String("samples.idl.string.UsesString")

cca.invokeMethodOnComponent(generator, usesPortClassName, usesPortType,
                            providesPortName, methodName, methodParams)

Step #3

Connect the above ports together as follows :

print "Connecting ports"
cca.connectPorts(generator, "usesPrint", printer, "providesPrint")

Step #4

Download a script into remote component as follows :

# download a script into the generator
print "Invoking remote method"
methodName = "runScript"
methodParams = zeros(1, Object)
codefile = open("./generator.py", "r")
code = codefile.read()
methodParams[0] = code

cca.invokeMethodOnComponent(generator, usesPortClassName, usesPortType,
                            providesPortName, methodName, methodParams)

The script generator.py above does the following :

import sys

print "Grabbing hold of the uses port"
myPort = manager.getUsesPort("usesPrint")

print "Sending string : Hello World"
myPort.sendString("Hello World")