WBEMfor Solaris on Sun Developer's Guide

Chapter 7 Writing a Provider Program

This chapter describes how to write a provider, including the following topics:

For detailed information on the provider APIs, see the Javadoc reference pages.

About Providers

Providers are classes that communicate with managed objects to access data. Providers forward this information to the CIM Object Manager for integration and interpretation. When the CIM Object Manager receives a request from a management application for data that is not available from the CIM Object Manager Repository, it forwards the request to a provider.

Object providers must be installed on the same machine as the CIM Object Manager. The CIM Object Manager uses object provider application programming interfaces (APIs) to communicate with locally installed providers.

When an application requests dynamic data from the CIM Object Manager, the CIM Object Manager uses the provider interfaces to pass the request to the provider.

Providers perform the following functions in response to a request from the CIM Object Manager:

Types of Providers

Providers are categorized according to the types of requests they service. The Sun WBEM SDK supports three types of providers:

A single provider can support both methods and instances, which can be convenient.

Most providers are pull providers, which means they maintain their own data, generating it dynamically when necessary. Pull providers have minimal interaction with the CIM Object Manager and the CIM Repository. The data managed by a pull provider typically changes frequently, requiring the provider to either generate the data dynamically or retrieve it from a local cache whenever an application issues a request. A provider can also contact the CIM Object Manager.

A single provider can act simultaneously as a class, instance, and method provider by proper registration and implementation of all relevant methods.

Implementing a Provider Interface

Providers implement a provider interface that supports the type of service specific to their role. In order to implement the interface, a provider class must first declare the interface in an implements clause, and then it must provide an implementation (a body) for all of the abstract methods of the interface. The following table describes the provider interfaces. You can include a method provider, instance provider, and property provider in a single Java class file, or store each provider in a separate file.

Providers can communicate with the CIM Object Manager using the initialize method. The initialize method takes an argument of type CIMOMhandle, which is a reference to the CIM Object Manager. The CIMOMhandle class contains methods that providers can use to transfer data to and from the CIM Object Manager.

Table 7-1 Provider Interfaces

Interface 

Description 

CIMProvider

Base interface implemented by all providers. 

InstanceProvider

Base interface implemented by instance providers. Instance providers serve dynamic instances of classes. 

MethodProvider

Interface implemented by method providers, which provide implementation for all methods of CIM classes. 

PropertyProvider

Interface implemented by property providers, which are used to retrieve and update dynamic properties. Dynamic data is not stored in the CIM Object Manager Repository. 

The Instance Provider Interface (InstanceProvider)

The following table describes the methods in the instance provider interface in the Provider package (com.sun.wbem.provider).

These methods each take the op argument, the CIM object path of the specified CIM class or CIM instance. The object path includes the namespace, class name, and keys (if the object is an instance). The namespace is a directory that can contain other namespaces, classes, instances, and qualifier types. A key is a property that uniquely identifies an instance of a class. Key properties have a KEY qualifier.

For example, the following object path has two parts:

\\myserver\root\cimv2\Solaris_ComputerSystem:Name=mycomputer:
   CreationClassName=Solaris_ComputerSystem

Table 7-2 InstanceProvider Interface Methods

Method 

Description 

enumInstances

Enumerates all instances of the class specified in the object path. You can do deep or shallow enumeration, but currently the CIM Object Manager only requests shallow enumeration. 

getInstance

Returns the instance specified in the object path (op).

setInstance

Sets the instance specified in the object path (op). If the instance does not exist, it must be added.

deleteInstance

Deletes the instance specified in the object path (op).

Example -- Implementing an Instance Provider

The code segment in Example 7-1, creates a Solaris instance provider class that routes requests for instance data from the CIM Object Manager to one or more specialized providers. These specialized providers service requests for dynamic data for a particular type of Solaris object. For example, the Solaris_Package provider services requests for instances of the Solaris_Package class.

An instance provider must implement all methods in the InstanceProvider interface. The code segment in Example 7-1 shows only two methods:


Example 7-1 Implementing an Instance Provider

public class Solaris implements InstanceProvider
{
   /**
    * Top-level provider class routes requests from the CIM
    * Object Manager to the appropriate provider.
    */
 
    public void initialize(CIMONHandle, ch) 
    throws CIMException {
    }
 
    public void cleanup() 
    throws CIMException {
    }
 
    /* This class returns a vector of enumerated instances of the 
    specified object in the specified class. If the object is a 
    Solaris package, it calls the Solaris_Package provider to return 
    a list of the Solaris packages on the system. If the object is a 
    Solaris patch, it calls the Solaris_Patch provider to return a 
    list of the Solaris patches on the system. */
 
    public Vector enumInstances(CIMObjectPath op, CIMClient.DEEP, CIMClass cc)
    throws CIMException {
        if (op.getObjectName().equalsIgnoreCase("solaris_package")) {
            Solaris_Package sp = new Solaris_Package();
            return sp.enumerateInstances(op);
        }
        if (op.getObjectName().equalsIgnoreCase("solaris_patch")) {
            Solaris_Patch sp = new Solaris_Patch();
            return sp.enumerateInstances(op);
        }
       return new Vector();
    }
 
 
    /* This class returns an instance of the specified object in the 
    specified class. If the object is a Solaris package, it
    calls the Solaris_Package provider to return the data for the
    specified Solaris package. If the object is a Solaris patch, it 
    calls the Solaris_Patch provider to return the data for the 
    specified Solaris patch. */
 
    public CIMInstance getInstance(CIMObjectPath op, CIMClass cc) 
    throws CIMException {
        if (op.getObjectName().equalsIgnoreCase("solaris_package")) {
            Solaris_Package sp = new Solaris_Package();     
            return sp.getInstance(op,cc);
        }
        if (op.getObjectName().equalsIgnoreCase("solaris_patch")) {
            Solaris_Patch sp = new Solaris_Patch();         
            return sp.getInstance(op,cc);
        } 
}
 


The specialized Solaris instance providers use the API to get and set instances of objects. These providers also declare native methods that call C functions to get Solaris-specific values, such as host name, serial number, release, machine, architecture, and manufacturer.

The code segment in Example 7-2 shows the solaris_package class, which is called in Example 7-1. This code segment implements the getInstance method. This method creates a new instance of the specified class and then fills it with properties returned from native C functions, such as GetPkgArchitecture().


Example 7-2 Solaris Package Provider

public class Solaris_Package 
{
    public CIMInstance getInstance(CIMObjectPath op, CIMClass cc) {
        String pkgName = "";
 
        for (Enumeration e = op.getKeys().elements(); e.hasMoreElements();) {
            CIMProperty cp = (CIMProperty)e.nextElement();
            if (cp.getName().equalsIgnoreCase("name")) {
                pkgName = (String) ((CIMValue)(cp.getValue())).getValue();
            }
        }
 
 
        CIMInstance ci = cc.newInstance();
        ci.setProperty("Name", new CIMValue(pkgName));
        ci.setProperty("TargetOperatingSystem", 
                          new CIMValue(new UnsignedInt16(29)));
 
        ci.setProperty("Status", 
                     new CIMValue(GetPkgStatus(pkgName)));
  			 ci.setProperty("Architecture", 
                          new CIMValue(GetPkgArchitecture(pkgName)));
        ci.setProperty("Description", new CIMValue(GetPkgDescription(pkgName)));
        ci.setProperty("Caption", new CIMValue(GetPkgDescription(pkgName)));
        ci.setProperty("Manufacturer", new CIMValue(GetPkgVendor(pkgName)));
        ci.setProperty("Category", new CIMValue(GetPkgCategory(pkgName)));
        ci.setProperty("Basedir", new CIMValue(GetPkgBasedir(pkgName)));
       return ci;
    }
 
    native String GetPkgDescription(String pkgName);
    native String GetPkgArchitecture(String pkgName);
    native String GetPkgVersion(String pkgName);
    native String GetPkgVendor(String pkgName);
    native String GetPkgBasedir(String pkgName);
    native String GetPkgCategory(String pkgName);
    native String GetPkgStatus(String pkgName);
 
 
   static {
       System.loadLibrary("NativeUnix");
   
    }
 
}
 

The Property Provider Interface (PropertyProvider)

The following table describes the methods in the property provider interface.

Table 7-3 PropertyProvider Interface Methods

Method 

Description 

getPropertyValue

Returns the value of the property for the specified instance.  

setPropertyValue

Sets the value of the property for the specified instance 

Example -- Implementing a Property Provider

The code segment in Example 7-3 creates a property provider (fruit_prop_provider) class that is registered in Example 7-5. The fruit_prop_provider implements the PropertyProvider interface.

This sample property provider illustrates the getPropertyValue method, which returns a property value for the specified class, parent class, and property name. A CIM property is defined by its name and origin class. Two or more properties can have the same name, but the origin class uniquely identifies the property.


Example 7-3 Implementing a Property Provider

fruit_prop_provider implements PropertyProvider 
{
public CIMValue getPropertyValue(CIMObjectpath op, string originclass, 
	string PropertyName){
 
		if (PropertyName.euqals("a")
			return new CIMValue("fooa")
 
		else
			return new CIMValue("foob");
}
...
}
 


The Method Provider Interface (MethodProvider)

The MethodProvider method takes the following arguments:

The following table describes the method in the Method Provider interface.

Table 7-5 MethodProvider Interface Methods

Method 

Description 

invokeMethod

The CIM Object Manager calls this method when the specified method is invoked. 

Example -- Implementing a Method Provider

The code segment in Example 7-4 creates a Solaris provider class that routes requests to execute methods from the CIM Object Manager to one or more specialized providers. These specialized providers service requests for dynamic data for a particular type of Solaris object. For example, the Solaris_Package provider services requests to execute methods in the Solaris_Package class.

The method provider in this example implements a single method invokeMethod that calls the appropriate provider to perform one of following operations:


Example 7-4 Implementing a Method Provider

public class Solaris implements MethodProvider
{
 
    public void initialize(CIMONHandle, ch) 
    throws CIMException {
    }
 
    public void cleanup() 
    throws CIMException {
    }
   public CIMValue invokeMethod(CIMObjectPath op, String methodName, 
        Vector inParams, Vector outParams) throws CIMException {
        if (op.getObjectName().equalsIgnoreCase("solaris_computersystem")) {
            Solaris_ComputerSystem sp = new Solaris_ComputerSystem();
            if (methodName.equalsIgnoreCase("reboot")) {
               return new CIMValue (sp.Reboot());
            }
        }
        if (op.getObjectName().equalsIgnoreCase("solaris_operatingsystem")) {
            Solaris_OperatingSystem sos = new Solaris_OperatingSystem();
            if (methodName.equalsIgnoreCase("reboot")) {
               return new CIMValue (sos.Reboot());
            }
            if (methodName.equalsIgnoreCase("shutdown")) {
               return new CIMValue (sos.Shutdown());
            }
        }
        if (op.getObjectName().equalsIgnoreCase("solaris_serialport")) {
            Solaris_SerialPort ser = new Solaris_SerialPort();
            if (methodName.equalsIgnoreCase("disableportservice")) {
               return new CIMValue (ser.DeletePort(op));
            }
        }
        return null;
    }
}
 


Writing a Native Provider

Providers get and set information on managed devices. A native provider is a machine-specific program written to run on a managed device. For example, a provider that accesses data on a Solaris system will most likely include C functions to query the Solaris system. Two common reasons for writing a native provider are:

The Java Native Interface is the native programming interface for Java that is part of the JDK. By writing programs using the JNI, you ensure that your code is completely portable across all platforms. The JNI allows Java code that runs within a Java Virtual Machine (VM) to operate with applications and libraries written in other languages, such as C, C++, and assembly.

For more information on writing and integrating Java programs with native methods, visit the Java web site at http://www.javasoft.com/docs/books/tutorial/native1.1/index.html.

Installing a Provider

After you write a Provider, you must specify the location of the provider class files and any shared library files.

How to Install a Provider Program
  1. Specify the location of shared library files in one of the following ways:

    • Set the LD_LIBRARY_PATH environment variable to the location of the shared library files. For example, using the C shell:

      % setenv LD_LIBRARY_PATH /wbem/provider/
      

      For example, using the Borne shell:

      % set LD_LIBRARY_PATH = /wbem/provider/
      

    • Copy the shared library files to the directory specified by the LD_LIBRARY_PATH environment variable. The installation sets this environment variable to /install_dir/opt/SUNWconn/wbem/lib. For example:

    % cp libnative.so /install_dir/opt/SUNWconn/wbem/lib
    % cp native.c /install_dir/opt/SUNWconn/wbem/lib
     
    

  2. Move the provider class files to /install_dir/opt/SUNWconn/wbem/bin.

  3. Set the CLASSPATH variable to the directory that contains the provider class files.

    For example, if you put the provider files in:

    /install_dir/opt/SUNWconn/wbem/bin/com/mycomp/wbem/provider/
    

    you would set your CLASSPATH variable as follows, using the C shell:

    % setenv CLASSPATH  com/mycomp/wbem/provider/myprovider
    

    For the Borne shell, use the following syntax:

    $ set CLASSPATH = com/mycomp/wbem/provider/myprovider
    

  4. Make sure the CIM Object Manager is running.

    The installation starts the CIM Object Manager. If it is not running, see "Restarting the CIM Object Manager".

Registering a Provider

Providers register with the CIM Object Manager to publish information about the data and operations they support and their physical implementation. The CIM Object Manager uses this information to load and initialize the provider and to determine the right provider for a particular client request. All types of providers follow the same procedure for registration. Neither the CIM Object Manager or the provider needs to be running during the registration process.

How To Register a Provider
  1. Create a MOF file defining a CIM class.

  2. Assign the provider qualifier to the class. Assign a provider name to the provider qualifier.

    The provider name identifies the Java class to serve as the provider for this class. You must specify the complete class name. For example:


    Note -

    We recommend following Java class and package naming conventions for providers so that provider names are unique. The prefix of a unique package name is always written in all-lowercase ASCII letters and should be one of the top-level domain names, currently com, edu, gov, mil, net, org, or one of the English two-letter codes identifying countries as specified in ISO Standards 3166, 1981.

    Subsequent components of the package name vary according to an organizations own internal naming conventions. Such conventions might specify that certain directory name components be division, department, project, machine, or login names, for example com.mycompany.wbem.myprovider.


    [Provider("com.kailee.wbem.providers.provider_name")]
    Class_name {
    ...
    };

  3. Compile the MOF file. For example:

    mofcomp class_name

Example -- Registering a Provider

The sample MOF file in Example 7-5 creates a class called Fruit that registers an instance provider (fruit_class_provider), a property provider (fruit_prop_provider), and a method provider (fruit_method_provider).


Example 7-5 Registering an Instance, Property, and Method Provider

 
// Registers fruit_class_provider as the provider for the Fruit class
[Provider("com.food.fruitprovider.fruit_class_provider")] 
 
Fruit {
 
// fruit_prop_provider is the provider for property a
		[Provider("com.food.fruitprovider.fruit_class_provider")] 
-		string a;
 
		// fruit_prop_provider is also the provider for property b
		[Provider("com.food.fruitprovider.fruit_class_provider")] 
		string b;
 
		// fruit_method_provider is the provider for method b
		[Provider("com.food.fruitprovider.fruit_class_provider")] 
		int b();
};
 


Modifying a Provider

You can make changes to a Provider class while the CIM Object Manager and provider are running. But you must stop and restart the CIM Object Manager to make the changes take effect.

To Modify a Provider
  1. Edit the provider source file.

  2. Compile the provider source file. For example:

    % java MyProvider.java
    

  3. Become root on your system by typing the following command at the system prompt:

    % su
    

  4. Type the root password when you are prompted.

  5. Change directories to the location of the init.wbem command by typing the following command:

    # cd /etc/init.d/
    

  6. Stop the CIM Object Manager by typing the following command:

    # init.wbem -stop
    

  7. Restart the CIM Object Manager by typing the following command:

    # init.wbem -start
    

Provider Examples

Chapter 8, Using Sun WBEM SDK Examples explains how to set up and run the Provider examples.