IBM Support

ITNCM: Searching for Units of Work with the Java API

Technical Blog Post


Abstract

ITNCM: Searching for Units of Work with the Java API

Body

Overview

This blog looks at a simple example of how to use the ITNCM (IBM Tivoli Network Configuration Manager) Java API.  The example we will look at shows how to connect to ITNCM, set up a search for completed work or UOWs in ITNCM, execute the search, and process the results of the search.

 

ITNCM Java API concepts

The ITNCM Java API provides a programmatic way to perform most tasks that are typically done using the ITNCM GUI.  Like the ITNCM GUI client, the API does not provide direct access to the ITNCM database or to ITNCM work servers. “Manager” interfaces in the API provide methods to access data or to submit work using a similar approach to when using the ITNCM GUI client. 

The ITNCM Java API can be called from a remote client or on the ITNCM server. It has behavior similar to Java RMI, but uses a “proxy” servlet on the ITNCM server to avoid J2EE library conflicts. Data is transmitted between API clients and the proxy servlet using XML over HTTP/S.

 

API structure

  • The API is structured into packages roughly corresponding to ITNCM GUI functionality, plus packages for interfaces representing ITNCM resource data objects and for managing API connections. Most packages contain a “Manager” interface with methods to manipulate or manage data objects related to that package, and a “DataFactory” interface to create instances of data objects that can be managed by the Manager interface in the package. For instance, for the packages we will use in this example:
    • com.intelliden.icos.api
      • Contains an ApiSession interface that represents an API connection to the ITNCM server, and an ApiFactory class used to create instances of ApiSession.  The ApiSession instances are later used to create instances of the Manager interfaces in the other packages.
    • com.intelliden.icos.resources
      • Contains a Manager (ResourceManager) interface and a DataFactory interface to work with ITNCM resources such as Network Resources, Configurations, Command Sets, Authentication Resources, Device Scripts, etc.
      • Also contains a NetworkResourceManager interface that manages certain specific aspects of Network Resources. Many methods in this interface are deprecated in favor of ResourceManager methods; ResourceManager methods should be used instead whenever possible.
    • com.intelliden.icos.workflow
      • Contains a Manager (WorkflowManager) interface use to submit and manage UOWs in the ITNCM workflow, and a DataFactory interface used to create the data objects related to UOWs and workflows.
    • com.intelliden.icos.idc
      • Contains interfaces for all data objects used by the API.  These are the data objects created using the DataFactory interfaces. These data objects represent resources in ITNCM such as Network Resources, Configurations, types of Work and types of Commands used with various Work types, and Keys and Descriptors used to fetch and access ITNCM resources.

For more detailed information regarding the ITNCM Java API, please see http://www.ibm.com/support/knowledgecenter/SS7UH9_6.4.2/ncm/wip/ref/concept/ncm_ref_japioverview.dita

 

Typical program flow

In a simple API program, you will typically use a flow similar to this:

  • Create an ApiSession instance to represent your connection to the ITNCM server. This step also authenticates your ITNCM user credentials with the ITNCM server.
  • Call methods on the ApiSession to create instances of the “Manager” interfaces you will need to perform the work you want your program to do. For instance:
    • You will need a ResourceManager instance (and possibly a NetworkResourceManager instance) to fetch NetworkResource and Configuration data from ITNCM.
    • You will need a WorkflowManager instance to submit or manage UOWs in the ITNCM workflow.
  • Call methods on the Manager interface instances to create the DataFactory instances. DataFactory instances are needed to create instances of the data objects you will need to represent ITNCM resources in your program.
  • Call methods on the Manager interface instances to interact with the ITNCM server; fetching data or submitting work as needed to carry out the work your program is intended to do.
    • The API is very low level in this area.
    • There is frequently a considerable amount of setup work required on data objects prior to using them as arguments for methods on Manager interfaces.
    • It is often necessary to make a sequence of method calls on Manager interfaces to fetch the data you are really interested in.  For instance, if you know the name of a Network Resource in ITNCM, you can use that name as input to method call that will return a Key or Descriptor object containing high level data about the Network Resource. To get more detailed data about the Network Resource, you will need to use the Key or Descriptor as input to other method calls.

 

Setting up your development and API client run-time environment

You can use any Java programming tools of your choice, from a text editor and command line Java commands to an IDE such as Eclipse.   This blog assumes that you have basic Java skills, and will not attempt to teach you to program with Java. It will cover only the example source code and the related ITNCM concepts.

An ITNCM client installer is available that installs the API javadocs, the ITNCM jar files needed by the API, and a set of example API programs on your local development workstation.  For ITNCM v6.4.2, you can copy the file ITNCMClient.zip to your development workstation from <ITNCM_install_location>/dist on the ITNCM server and use IBM Installation Manager to install it.

For this example, you can simply copy the required ITNCM jar files from <ITNCM_install_location>/lib directory on the ITNCM server.  However, if you wish to have the javadocs and additional examples available, you should install the ITNCM client.

  • Java versions 1.7 and 1.8 are supported for the API client environment.
    • If you plan to use an Oracle JRE instead of an IBM JRE you will need to download the following jar files from an external location and add them to your classpath.
      • xalan.jar
      • serializer.jar
      • xercesImpl.jar
      • xml-apis.jar
  • You need the following ITNCM jar files in your classpath.  If you did not install the ITNCM client, you can copy them from the <ITNCM_install_location>/lib directory on your ITNCM server. It is important to use the same version of these jar files on the API client as are used on the ITNCM server.
    • appframework.jar
    • common.jar
    • commons-codec-1.4.jar
    • commons-logging-1.1.jar
    • driverinterface.jar
    • httpclient-4.0.1.jar
    • httpcore-4.0.1.jar
    • ibm_tivoli-dataaccess.jar
    • ibm_tivoli-definitions.jar
    • ibm_tivoli-events.jar
    • intelliden-soap-apis.jar
    • log4j-1.2.14.jar
    • mibble-commercial-parser-2.9.2.jar
    • presentation.jar
    • xstream-1.3.1.jar

 

  • You will need an ITNCM application user account with sufficient privileges to perform the work you want to do in ITNCM.  For this example, you will need privileges to view UOWs that were executed against the target set of Network Resources in ITNCM.
  • If you are not executing your example code directly on the ITNCM server, you will need network connectivity to the ITNCM server.
  • Parts of the API or routines called by the API use log4j for logging.  To avoid warning messages about log4j initialization, put the log4j.properties file included with the example source code in your classpath.  The file contains a single line:
    • log4j.rootCategory=error

 

API example: searching for failed UOWs in ITNCM

The example scenario

The particular example we will look at in this blog is based on a customer request that is not covered by the set of examples that are included with the ITNCM API client. In this case the customer wanted to be able to programmatically search for failed UOWs in ITNCM. 

As background information, a single UOW can include multiple “tasks”.  For instance:

  • A UOW with one device and one command set includes one task.
  • A UOW with three devices and two command sets includes six tasks.
  • A UOW for backing up 200 devices includes 200 tasks.

There are several UOW outcomes that could be considered as failure:

  • The UOW completed and all tasks in the UOWs failed.
  • The UOW completed and only some of the tasks in the UOW failed.
  • The UOW was not started prior to the end of its allowed execution window, and so it was never executed.
  • The UOW required approval and was rejected prior to execution.
  • The UOW was de-queued (cancelled) prior to start or completion of execution.

For the purposes of our example, we will consider failed work to be a UOW that completed and at least some of the tasks failed.  UOWs with the other outcomes listed above could be searched for using logic similar to what we will see in our example, but with different search filters.

 

Walkthrough of key sections of the example code

Connecting to the ITNCM server

To connect and authenticate to the ITNCM server, we must call the getSession method on the ApiFactory class, passing in the user name and password of an ITNCM application user account, the name or IP address of the ITNCM server, and the port the ITNCM server is listening on.

  • For ITNCM versions prior to 6.4.2 the default listening port is 7001
  • For ITNCM version 6.4.2 the default listening port is 16310

If authentication is successful, an ApiSession object is returned.  The ApiSession object will be used to create the various “Manger” objects we need to retrieve data from ITNCM or to submit work into the ITNCM workflow.

In this example, we will create the ApiSession object in the main method of our example class, and then pass that ApiSession object to other methods in the class.

 

Connect to the ITNCM Server:

public static void main(String[] args) {

      String server = args[0];

            int port = Integer.parseInt(args[1]);

      String user = args[2];

      String password = args[3];

      String startDateStr = args[4];

      String endDateStr = args[5];

      ApiSession session = null;

 

      try {

            session = ApiFactory.getSession(user, password, server, port);

      } catch (IntellidenException ie) {

            System.err.println("Error logging in to the ITNCM server");

            throw ie;

      }

 

Create the “Manager” objects:

We need to create a ResourceManager and ResourceDataFactory object in order to create our Search object and to be able to fetch NetworkResourceKeys in order to restrict our search to specific network devices.  We will also need a WorkflowManager object to execute a search for Work (UOW) type objects and to retrieve audit log (UOW log) data for each Work object returned by the search.

// ResourceManager is an interface used to manage ITNCM resources such

// as NetworkResources, CommandSets, etc.

ResourceManager rm = session.resourceManager();

 

// ResourceDataFactory is the data factory for creating objects used by

// the ResourceMananger interface

ResourceDataFactory rdFactory = rm.dataFactory();

 

// WorkflowManager is the interface used to submit new work (UOWs) into

// the ITNCM workflow, and to manage existing work.

WorkflowManager wfManager = session.workflowManager();

 

 

Search for failed work

We will use a UnitOfWorkSearch object to search for work.  We will search for work that has completed.  The search will return a Collection of Work objects.  We will then iterate over that Collection to return only failed Work objects.

We can further restrict our UnitOfWorkSearch based on:

  • A date range.
  • Work that was done for a collection of network devices.
  • Work association: Whether the Work was submitted by the user doing the search or by a member of any ITNCM groups that user belongs to.
  • Work visibility: Whether the Work uses commands to access device information, or commands to change device information.
  • Work hierarchy: Whether to search for only “root” Work (UOWs that were submitted by users or the API), or child Work that was spawned by root Work, or both.

 

Create the UnitOfWorkSearch and set it to only search for completed work:

UnitOfWorkSearch search = rdFactory.newUnitOfWorkSearch();

Collection<WorkState> workStates = new ArrayList<WorkState>();

workStates.add(WorkState.FINISHED);

search.setWorkStates(workStates);

 

Allow filtering by device (NetworkResource) name:

We need to set a Collection of NetworkResourceKeys on the UnitOfWorkSearch object to do this. We will look at the method for fetching a NetworkResourceKey based on a NetworkResource name later in this blog:

if ((deviceName != null) && !(deviceName.trim().isEmpty())) {

Collection<NetworkResourceKey> nrKeys = new ArrayList<NetworkResourceKey>();

NetworkResourceKey nrKey = getNetworkResourceKey(session, deviceName);

nrKeys.add(nrKey);

search.setResourceKeys(nrKeys)

}

 

Set the date range for the search:

You can use fixed dates or relative dates.  In this example we will use fixed dates, but the example code includes commented sections showing how to use relative dates.  The date information was passed in and formatted in the main method, but is shown here for ease of understanding how it was obtained:

SimpleDateFormat dateFormatter = new SimpleDateFormat(DATEPATTERN);

Date startTime = dateFormatter.parse(startDateStr);

Date endTime = dateFormatter.parse(endDateStr);

 

search.setStartDate(startDate);

search.setEndDate(endDate);

 

Set the search settings for work association, visibility, and hierarchy:

// Find work submitted by users in all ITNCM groups that you belong to

search.setAssociation(WorkAssociation.GROUP);

 

/*

* Visibility:

* A value of null is assumed to be 1.

* 5 - Maximum - Shows all commands.

* 4 - Only shows commands that access managed device data.

* 3 - Only shows commands that access devices or change their managed

*     state.

* 2 - Only shows commands that access devices.

* 1 - Minimum - Only shows commands that may change devices.

*/

search.setVisibilityLevel(5);

 

// WorkHierarchy - Defines the different types of work hierarchy (Root,

// Child, ALL)

// Null defaults to both (ALL).

search.setHierarchy(WorkHierarchy.ALL);

 

Execute the UnitOfWorkSearch and return a Collection of Work objects meeting the criteria of the search:

The Collection will contain all Work that completed within the specified date range and that was submitted by members of any ITNCM groups that you belong to.  If you passed in a device name to filter on, only Work for that device will be returned. Otherwise Work for all devices you have access to in ITNCM will be returned

// Execute the search and return all matching UOWs.

Collection<Work> workCollection = wfManager.getAllWork(search);

Collection<Work> failedWorkCollection = new ArrayList<Work>();

 

Next iterate over the Collection, putting any Work with an execution status other than SUCCESS in a Collection of failed Work, and then return the Collection of failed Work:

if (workCollection != null) {

      for (Work work : workCollection) {

            // This will add only UOWs with exec status of FAILURE and

            // PARTIAL_SUCCESS

            if (!work.getExecutionStatus().equalsIgnoreCase("SUCCESS")) {

                  failedWorkCollection.add(work);

            }    

}

}

return failedWorkCollection;

 

Extract and display the UOW data:

Now that we have a collection of failed Work, we will look at how to extract some of the details for each UOW. In this example we are just sending the details to stdout for simplicity.  For Work that executed Commands, we extract and display additional details. In many cases the UOW logs will contain a large amount of data, so you may want to fetch and parse the log data only if it is really needed.

boolean fetchDebug = false;

for (Work work : workCollection) {

WorkKey workKey = work.getWorkKey();

      System.out.println("\nFound failed UOW");

      System.out.println("UOW ID: " + work.getUOWID() + "; "

                              + work.getStartTime());

      System.out.println("Execution Status: "

                              + work.getExecutionStatus());

      System.out.println("UOW Comment: " + work.getComment());

      System.out.println("UOW Description: "

                              + work.getDescription());

      if (work instanceof CommandWork) {

            CommandWork cmdWork = (CommandWork) work;

            Command command = cmdWork.getCommand();

            ArrayList<CommandComponentStatus> statusList

= command.getCommandComponentStatuses();

            System.out.println("\nListing command component data");

            for (CommandComponentStatus statusData : statusList) {

                  System.out.println(statusData);

            }

      }

      byte[] logBytes = wfManager.getWorkLog(workKey, fetchDebug);

      System.out.println("UOW log:\n" + new String(logBytes));

}

 

Fetching a NetworkResourceKey using a NetworkResource name

Earlier in this blog we referenced a method to get a NetworkResourceKey based on the name of the NetworkResource. Keys or ResourceContentDescriptors for resources such as NetworkResources are needed in most API calls that work with resources. However, only the names of the resources can be seen in the ITNCM GUI, so extra work is required to get the Key or Descriptor.  This example program includes a method to get a NetworkResourceKey using the name of the NetworkResource as input.  This method fetches the ResourceContentDescriptor for the NetworkResource, then extracts the NetworkResourceKey from the ResourceContentDescriptor.

 

NetworkResourceKey nrKey = null;

 

// Get the required “Manager” objects

ResourceManager rm = session.resourceManager();

ResourceDataFactory rdFactory = rm.dataFactory();

 

// Set up and execute the search

// deviceName is the name of the NetworkResource, passed in as a String

ResourceSearch resSearch = rdFactory.newResourceSearch();

resSearch.setResourceName(deviceName);

Collection<String> resTypes = new ArrayList<String>();

resTypes.add(Resource.RESOURCE_NETWORKERSOURCE);

resSearch.setResourceTypes(resTypes);   

Collection<ResourceContentDescriptor> devResults = rm.search(resSearch);

 

// Evaluate the results of the search

if (null != devResults && devResults.size() > 0) {

      //should only be one object in the collection, warn if there are more.

      if (devResults.size() > 1) {

System.out.println("Warning: More than one resource was “ + “returned in the search for " + deviceName);

      }

      //Return the first object in the collection, there should be only one.

      ResourceContentDescriptor descriptor = devResults.iterator().next();

      nrKey = (NetworkResourceKey) descriptor.getResourceKey();

} else {

      // Nothing was found, cannot proceed to get the key.

      System.out.println("No device named " + deviceName

+ " was found. Exiting now.");

}

return nrKey;

 

Source code for this example

In this blog we walked through key sections of the example source code to explain important ITNCM Java API concepts. The complete source code is available in the file uow_search_example.zip|View Details, and it is heavily commented to further help in understanding this example. The source code has been tested on ITNCM v6.4.1.x and v6.4.2 using an IBM Java 1.7 JRE.

Source code with methods added to do a more refined search that returns and displays less data is available in the file uow_search_example_2.zip|View Details.

 

[{"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Product":{"code":"","label":""},"Component":"","Platform":[{"code":"","label":""}],"Version":"","Edition":"","Line of Business":{"code":"","label":""}}]

UID

ibm11082349