Remote Administration Daemon Developer Guide

Exit Print View

Updated: July 2014
 
 

Interface Components

An API is defined by a module developer and contains a variety of components designed to accomplish a task. These components are:

  • Enums

    • Values

  • Structs

    • Fields

  • Interfaces

    • Properties

    • Methods

    • Events

These components are all defined in ADR Interface Description Language document. The radadrgen utility is used to process the document to generate language specific components which facilitate client/server interactions within RAD. More details in the role of ADR and rad can be found in Abstract Data Representation. Brief descriptions of each component follows.

Enumerations

Enumerations are primarily used to offer a restricted range of choices for a property, an interface method parameter, result, or error.

Using Enumeration Types

To access an enumerated type, simply import the binding and interact with the enumeration.

Example 3-39   Using Enumerations
>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr
>>> print zonemgr.ErrorCode.NONE
NONE
>>> print zonemgr.ErrorCode.COMMAND_ERROR
COMMAND_ERROR
>>> 

Structs

Structs are used to define new types and are composed from existing built-in types and other user defined types. In essence, they are simple forms of interfaces: no methods or events and they are not present in the RAD namespace.

Using Struct Types

The zonemgr module defines a Property struct which represents an individual Zone configuration property. The structure has the following members name, type, value, listValue, and complexValue. Like enumerations, structures can be interacted with directly once the binding is imported.

Example 3-40   Using Structs
>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr
>>> prop = zonemgr.Property("autoboot", "false")
>>> print prop
Property(name = 'autoboot', value = 'false', type = None, listvalue = None, complexvalue = None)
>>> prop.name = "my name"
>>> prop.value = "a value"
>>> print prop.name
my name
>>> print prop.value
a value
>>> 

Interfaces/Objects

Interfaces (also known as objects) are the entities which populate the RAD namespace. They must have a "name". An interface is composed of Events, Properties and Methods.

Obtaining an Object Reference

See the Rad Namespace section.

Working with Object References

Once we have an object reference we can use this to interact with RAD in a very straightforward fashion. All attributes and methods defined in the IDL are accessible directly as attributes of the python objects which are returned by get_object().

Here is an example which gets a reference to a zone and then boots the zone.

Example 3-41  Working with Object References
>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr
>>> import rad.client as radc
>>> import rad.connect as radcon
>>> with radcon.connect_unix() as rc:
...     patt = radc.ADRGlobPattern({"name" : "test-0"})
...     zone = rc.get_object(zonemgr.Zone(), patt)
...     print zone.name
...     zone.boot(None)
>>> 

In the above example we have connected to our RAD instance, created a search for a specific object, retrieved a reference to the object and accessed a remote property on it. This does not include error handling yet.

Accessing a Remote Property

Here is another example for accessing a remote property.

Example 3-42   Accessing a Remote Property
>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr
>>> import rad.client as radc
>>> import rad.connect as radcon
>>> with radcon.connect_unix() as rc:
...     name = rc.list_objects(zonemgr.Zone(), radc.ADRGlobPattern({"name" : "test-0"}))
...     zone = rc.get_object(name[0])
...     for prop in zone.getResourceProperties(zonemgr.Resource("global")):
...         if prop.name == "brand":
...             print "Zone: %s, brand: %s" % (zone.name, prop.value)
...             break
... 
Zone: test-0, brand: solaris
>>>

In this example, we accessed the list of Zone global resource properties and search the list of properties for a property with the name property of "brand". When we find it we print the value of the "brand" property and then terminate the loop.

RAD Event Handling

In this next example we are going to look at events. The ZoneManager instance defines a "stateChange" event which clients can subscribe to for information about changes in the runtime state of a zone.

Example 3-43   Subscribing and Handling Events
import rad.connect as radcon
import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr
import signal

def handler(event, payload, user):
   print "event: %s" % str(event)
   print "payload: %s" % str(payload)
   print "zone: %s" % str(payload.zone)
   print "old: %s" % str(payload.oldstate)
   print "new: %s" % str(payload.newstate)

with radcon.connect_unix() as rc:
    zm = rc.get_object(zonemgr.ZoneManager())
    rc.subscribe(zm, "stateChange", handler, zm)
    signal.pause()

This is a simple example. We subscribe to the single event and pass in a handler and a reference to our ZoneManager object. The handler will be invoked asynchronously by the framework with the various event details and the supplied user data. The user data is an optional argument at subscription and if not provided, the handler will receive None as the user parameter.

RAD Error Handling

Finally, a quick look at error handling when manipulating remote references. Python provides a rich exception handling mechanism and RAD errors are propagated using this mechanism. There are a variety of errors which can be delivered by RAD, but the main one which requires handling is rad.client.ObjectError. The following snippet, shows how it can be used:

Example 3-44   Handling RAD Errors
import rad.client as radc
import rad.conect as radcon
import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr
import logging
import sys

logging.basicConfig(filename='/tmp/example.log', level=logging.DEBUG)
with radcon.connect_unix() as rc:
    patt = radc.ADRGlobPattern({"name" : "test-0"})
    test0 = rc.get_object(zonemgr.Zone(), patt)
    print test0.name
    try:
        test0.boot(None)
    except radc.ObjectError as ex:
        error = ex.get_payload()
        if not error:
            sys.exit(1)
        if error.stdout is not None:
            logging.info(error.stdout)
        if error.stderr is not None:
            logging.info(error.stderr)
        sys.exit(1)

Note -  With ObjectError exceptions you may get a payload. This is only present if your interface method or property has defined an "error" element, in which case the payload is the content of that error. If there is no "error" element for the interface method (or property), then there is no payload and it will have a value of None.