The public interfaces are exported in the following three modules:
rad.auth – Useful functions or classes for performing authentication
rad.client – The client implementation of the RAD protocol and associated useful functionality
rad.connect – Useful functions or classes for connecting to a RAD instance
Alternatively, you can import the module and examine the module help.
Example 30 Python Language – Accessing Help for a Binding Moduleuser@host1:/var/tmp# python Python 2.6.8 (unknown, Feb 5 2013, 00:27:10) [C] on sunos5 Type "help", "copyright", "credits" or "license" for more information. >>> import rad.bindings.com.oracle.solaris.rad.zonemgr_1 as zonemgr >>> help(zonemgr)
The RAD instances can communicate through the RADConnection class. There are various mechanism to get different types of connections to RAD. Each mechanism returns a RADConnection instance, which provides a standard interface to interact with RAD.
The preferred method for managing a connection is to use the with keyword. The connection uses the system resources and this ensures that the resource is closed correctly when the object goes out of scope. If the system resources are not used, the system resources can be reclaimed explicitly with the close() method.
You can connect to a local instance using the radcon.connect_unix() function. An implicit authentication is performed against your user ID and most RAD tasks you request with this connection are performed with the privileges available to your user account.
Example 31 Python Language – Creating a RAD Local Connection>>> import rad.connect as radcon >>> with radcon.connect_unix() as rc:
When connecting to a remote instance, no implicit authentication is performed. The connection is not established until you authenticate. The rad.auth module provides a utility class (RadAuth), which may be used to perform a PAM login. If you provide a username and password, authentication is non-interactive. If you do not provide username and password, you will receive a console prompt for the missing information.
Example 32 Python Language – Creating a RAD Remote Connection Over TLS>>> import rad.connect as radcon >>> import rad.auth as rada >>> rc=radcon.connect_tls("host1") >>> # Illustrate examining RadConnection state. >>> print rc <open RadConnection > >>> auth = rada.RadAuth(rc) >>> auth.pam_login("garypen", "xxxpasswordxxx") >>> <now authenticated and can use this connection> >>> rc.close() >>> print rc <closed RadConnection> >>>
You can use a URI to connect to a local or remote RAD instance. You can use the class RadURI() to connect to a RAD instance. The methods or functions are not required in Python because you can read the attributes of the RAD instances that you create instead of using defined methods. For more information, see Connecting in Python to a RAD Instance by Using a URI.
The following constructor is supported.
def __init__(self, src, schemes = RAD_SCHEMES):
String, which is the URI of a RAD instance
List of strings that specify the schemes to be recognized
The following method is supported:
def connect(self, cred = None):
Credentials that are required for authentication
You can use PAMCredentials class to create PAM credentials for PAM authentication or you can use def get_pam_cred(passw) function, which returns a PAMCredentials object for use in the RadURI.connect() method.
Most RAD objects that are represented in the ADR document as <interfaces>. You can find RAD objects by searching the RAD namespace. To access a RAD object, you need a proxy, which is used to search the RAD namespace. An interface proxy class enables you to use a proxy to search the RAD namespace. The interface proxy is defined in the binding module of each interface.
The proxy provides the base name and version details for interface instances and is structured as follows:
<domain name>:type=<interface name>[,optional additional key value pairs]
The <domain name> and the <interface name> are automatically derived from the ADR IDL definition and are stored in the module binding.
Certain interfaces return or accept object references directly to or from clients. These objects might not be named. Objects that are not named are anonymous. Anonymous objects cannot be looked up in the RAD namespace, but the interface provides access methods that make it simple to interact with them.
The RAD object names are structured, consisting of a domain and one or more key-value pairs.
For example, you can create a name for a zonemgr zone instance as follows:
>>> ADRName("com.oracle.solaris.rad.zonemgr", { "type": "Zone", "name" : "radtest-zone", "id" : "1" })
When you create a name, you can handle key-value pairs. This removes any issues in processing names where values contain special characters (for example, commas (,), and equal signs (=).
The RADConnection class provides mechanisms for listing objects by name and for obtaining a remote object reference.
A module developer creates a singleton to represent an interface. This interface can be accessed easily. For example, the zonemgr module defines a singleton interface, ZoneInfo. It contains information about the zone that contains the RAD instance with which you are communicating.
Example 33 Python Language – Obtaining a Reference to a RAD Singleton>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr >>> import rad.connect as radcon >>> with radcon.connect_unix() as rc: ... zi = rc.get_object(zonemgr.ZoneInfo()) ... print zi.name ... global >>>
In this example, you have imported the RAD bindings and the rad.connect module, and connected to the local RAD instance. After connecting to the local RAD instance, obtain a remote object reference directly by using a proxy instance. After you have the remote reference, you can access properties and methods directly as you would with any Python object.
An interface can contain multiple RAD instances. For example, the zonemgr module defines a Zone interface and there is an instance for each zone on the system. The RADConnection class provides the list_objects() method to list the interface instances as shown in the following example.
Example 34 Python Language – Listing RAD Interface Instances>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr >>> import rad.connect as radcon >>> with radcon.connect_unix() as rc: ... zonelist = rc.list_objects(zonemgr.Zone()) ... print zonelist ... [Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=test-0,id=-1 Version: (1.0), Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=test-1,id=-1 Version: (1.0), Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=NOT-TEST,id=-1 Version: (1.0)] >>>
Names (ADRName is the class name) are returned by the RADConnection list_objects method. Once you have a name, you can obtain a remote object reference easily.
Example 35 Python Language – Obtaining a RAD Remote Object Reference>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr >>> import rad.connect as radcon >>> with radcon.connect_unix() as rc: ... zonelist = rc.list_objects(zonemgr.Zone()) ... zone = rc.get_object(zonelist[0]) ... print zone.name ... test-0 >>>
You can search for a zone by its name or ID or a set of zones by pattern matching. You can extend the basic definition of a name provided by a proxy. For example, if zones are uniquely identified by the key name, then you can find a zone with the name test-0 as shown in the following example. The example uses glob patterns to find a zone.
Example 36 Python Language – Using Glob Patterns in RAD>>> 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: ... zonelist = rc.list_objects(zonemgr.Zone(), radc.ADRGlobPattern({"name" : "test-0"})) ... print zonelist ... [Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=test-0,id=-1 Version: (1.0)] >>>
In this example, the ADRGlobPattern class (imported from the rad.client module) is used to refine the search. The list_objects() method from the RADConnection class is used, but the search is refined by extending the name definition. The ADRGlobPattern class takes a key:value dictionary and extends the name used for the search.
You can use a glob pattern to find zones with wildcard pattern matching. Keys and values in the pattern may contain an asterisk (*), which is interpreted as wildcard pattern matching. The following example shows how to find all zones with a name which begins with test.
Example 37 Python Language – Using Glob Patterns With Wildcards in RAD>>> 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: ... zonelist = rc.list_objects(zonemgr.Zone(), radc.ADRGlobPattern({"name" : "test*"})) ... print zonelist ... [Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=test-0,id=-1 Version: (1.0), Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=test-1,id=-1 Version: (1.0)] >>>
You can also use ERE search capabilities of RAD. The following example shows how to find only zones with name test-0 or test-1.
Example 38 Python Language – Using Regex Patterns in RAD>>> 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: ... zonelist = rc.list_objects(zonemgr.Zone(), radc.ADRRegexPattern({"name" : "test-0|test-1"})) ... print zonelist... [Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=test-0,id=-1 Version: (1.0), Name: com.oracle.solaris.rad.zonemgr:type=Zone,name=test-1,id=-1 Version: (1.0)] >>>
The key and the value must be valid EREs as determined by the instance of RAD to which you are connected. The expression is compiled and executed on the server.
An API is defined by a module developer. It contains one or more of the following components, each of which performs a task:
Enumerations
Values
Structures
Fields
Dictionary
Interfaces
Properties
Methods
Events
These components are defined in an ADR IDL document. The radadrgen utility is used to process the document to generate language specific components which facilitate client-server interactions within RAD. For more information about the role of ADR and RAD, see Abstract Data Representation. Brief descriptions of each component follows.
Enumerations are primarily used to offer a restricted range of choices for a property, an interface method parameter, result, or error.
To access an enumerated type, import the binding and interact with the enumeration.
Example 39 Python Language – Using RAD Enumerations>>> import rad.bindings.com.oracle.solaris.rad.zonemgr as zonemgr >>> print zonemgr.ErrorCode.NONE NONE >>> print zonemgr.ErrorCode.COMMAND_ERROR COMMAND_ERROR >>>
Structures, or "structs", are used to define new types and are composed from existing built-in types and other user defined types. Structs are simple form of interfaces with no methods or events. They are not included in the RAD namespace.
The zonemgr module defines a Property struct which represents an individual zone configuration property. The structure has the following members: name, type, value, value, listValue, and complexValue. Like enumerations, structures can be interacted with directly once the binding is imported.
Example 40 Python Language – Using RAD 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 >>>
You can use the built-in dictionary type in Python. For example, the Python code to set the sample dictionary property as defined in Example 49, Defining a Dictionary can be as follows:
object.DictProp = {1: 'value1', 2: 'value2'}
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.
See the RAD Namespace in Python section.
Once you have an object reference, you can use this object reference to interact with RAD directly. All attributes and methods defined in the IDL are accessible directly as Python object attributes that are returned by the get_object() function.
The following example gets a reference to a zone and then boots the zone.
Example 41 Python Language – Working With RAD 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 this example, you have connected to the RAD instance, created a search for a specific object, retrieved a reference to the object, and accessed a remote property on it. No error handling occurred.
The following example shows how to access a remote property.
Example 42 Python Language – Accessing a Remote RAD 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, you have accessed the list of global resource properties of the Zone and searched the list of properties for the brand property. When you find it, print the value of the brand property and then terminate the loop.
This example shows how to subscribe to and handle 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 43 Python Language – Subscribing to and Handling RAD Eventsimport 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()
In this example, you have subscribed to a single event by passing a handler and a reference to the ZoneManager object. The handler is invoked asynchronously by the framework with various event details and user data. The user data is an optional argument at subscription. If the user data is not provided, the handler receives None as the user parameter.
Python provides a exception handling mechanism and propagates RAD errors by using this mechanism. RAD delivers a variety of error codes that you can handle with rad.client.ObjectError. The following example shows how to handle RAD errors.
Example 44 Python Language – Handling RAD Errorsimport 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)
You can use the standard URI format to connect to a RAD instance. The URI format is as follows:
scheme://user?@host:port?auth=value
(Mandatory) The supported schemes are unix, rad, rads, and ssh.
(Optional) The user who is connecting to the remote RAD instance. If you do not specify the user, the current user is assumed.
(Mandatory) The system that contains the remote RAD instance.
(Optional) The port number. The default port is 12302 (RAD IANA port).
(Optional) The authentication method that is used to connect to the remote RAD instance. The supported values are pam and gss. If you do not specify the authentication, then pam is assumed. If you are using SSH as the transport protocol, you must not specify the authentication mechanism.
The following example shows how to open a TCP connection as jdoe to the system abc at port 10000 with default authentication.
rad://jdoe@abc.example.com:10000
The following example shows how to open a TLS connection as hg to the system abc at the default RAD port with gss authentication.
rads://hg@abc.example.com?auth=gss
The following example shows how to open an SSH connection as the current user to the system abc at the default SSH port.
ssh://abc.example.com
The following example shows how to open a connection to a local RAD instance.
unix:///path