JBoss Operations Network 2.4

Using the Remote API: The JBoss ON CLI and Java Clients

for using the CLI and the remote API

Edition 4

Ella Deon Lackey

Red Hat Engineering Content Services

Legal Notice

Copyright © 2010 Red Hat, Inc..
This document is licensed by Red Hat under the Creative Commons Attribution-ShareAlike 3.0 Unported License. If you distribute this document, or a modified version of it, you must provide attribution to Red Hat, Inc. and provide a link to the original. If the document is modified, all Red Hat trademarks must be removed.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat Software Collections is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack Logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
July 29, 2010, updated on December 15, 2010

Abstract

This has some examples and information for using the CLI and the remote API.

Abstract

 

Chapter 1. Introduction to the JBoss ON CLI Interface

A large subset of JBoss Operations Network functionality is exposed through its remote APIs. These APIs allow clients to access the server functionality — alerting, monitoring, managing inventory and resources, even agents. JBoss ON has several different ways that clients can leverage the remote API. Two of them are supplied with JBoss ON automatically: the JBoss ON web UI and the JBoss ON Java CLI. Custom clients can be written using the remote API for customers to create their own management interfaces, like desktop clients, provisioning automation, or alert reporting integration.
This guide primarily focuses on using the JBoss ON CLI to interact with the remote APIs. The JBoss ON CLI can be used as pointers for writing a custom Java application and a simple custom Java app is included at the end of this manual. The complete remote API reference is available with the JBoss ON documentation.
This manual is intended primarily for administrators who will be using the default JBoss ON CLI to manage JBoss ON. This manual has a secondary audience for plug-in writers and developers who intend to write custom applications which leverage the remote API.

1.1. About JBoss ON Interfaces

The backend logic that defines the JBoss Operations Network subsystems, functionality, and interactions is contained in the Enterprise JavaBeans for the server. These EJBs expose the relevant JBoss ON APIs to different interfaces. JBoss ON supports two kinds of interfaces:
  • Web services, like the JBoss ON UI, using SOAP and leveraging the JBoss Remoting framework for communication
  • Java clients using (obviously) Java and calling the remote JBoss ON APIs
JBoss ON already ships with a client of each type. The JBoss ON server GUI uses the web services and Remoting framework to connect to the server. The additional JBoss ON CLI which can be downloaded and installed locally uses Java and the remote API to support scripting and command line services.
Custom services can be built for web UIs using SOAP or for Java Enterprise (JEE) clients written in any JVM-compatible language, including Java, Scala, and Groovy.
Building custom user interfaces is outside the scope of this guide. For reference, there is an example JEE client in Chapter 6, Example: Writing a Custom Java Client and references to the JBoss ON public remote API, available at https://docs.redhat.com/docs/en-US/JBoss_Operations_Network/2.4/html/API_Guides/index.html. Otherwise, this guide is concerned with explaining how to use the default Java CLI to connect to JBoss ON servers to manage resources.

1.2. About the JBoss ON CLI

The default JBoss ON CLI is a Java-based scripting interface. This contrasts with the JBoss ON web UI, which provides a simple, visual way to manage JBoss ON.
The CLI is a standalone Java application that uses the Java Scripting API. The CLI better integrates JBoss ON into a network environment because administrators can interact with JBoss ON programmatically.
The JBoss ON CLI has a JavaScript-style scripting environment by using the Rhino engine in Java 6. By using the Remoting services in the JBoss ON communications system, the CLI can be used for remote scripting services, not just local operations.

NOTE

Java 6 ships with the Rhino JavaScript engine, so JavaScript is the supported scripting language in the CLI.
The JBoss Operations Network CLI itself is a Java shell the allows administrators to connect to the JBoss ON server over the command line. Essentially, the CLI is a script execution engine. It treats the JBoss ON API as if it was written in a scripting language, which makes it more convenient to manage the JBoss ON server.
The JBoss ON CLI is opened through a script, rhq-cli.sh|bat. This script emulates a shell, accepting basic commands and allowing administrators to navigate the server with shell tools like autocomplete.

1.3. About the JBoss ON API

Three areas of the JBoss ON services are exposed in the public JBoss ON API:
  • The core server functionality, including alerts, authorization, authentication, server cloud management, monitoring, and inventory, in the Domain API.
  • Server functionality that is streamlined to integrate smoothly with any remote services, both Java and web-based, by leveraging the JBoss Remoting framework, in the Remote API.
  • The server-side plug-in management for server plug-ins related to server functionality, like content and alerting, in the Plug-in API.

IMPORTANT

The remote API cannot be run from a client inside an application server. For example, the remote API cannot be run from a client inside an EAP instance; it fails with errors like the following:
Caused by: java.lang.IllegalArgumentException: interface
org.rhq.enterprise.server.auth.SubjectManagerRemote is not visible from class
loader
at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
at
org.rhq.enterprise.client.RemoteClientProxy.getProcessor(RemoteClientProxy.java:69)

1.5. Installing the JBoss ON Command-Line Tool

The JBoss ON server contains packages called the Remote Client, which contain the JBoss ON CLI packages, rhq-client-2.4.zip.

NOTE

Only the corresponding version of the CLI can be used to manage the JBoss ON server. Other versions are not compatible.
To install the CLI:
  1. Open the JBoss ON GUI.
    http://server.example.com:7080
    
  2. Click the Administration link in the main menu.
  3. Select the Downloads menu item.
  4. Scroll to the Command Line Client Download section, and click Download Client Installer.
  5. Save the .zip file into the directory where the CLI should be installed.
  6. Unzip the packages.
    unzip rhq-client-version.zip

Chapter 2. Running the JBoss ON CLI

The JBoss ON CLI is a shell and interpreter so that commands and statements can be executed interactively against the JBoss ON server. Scripts stored in files can also be executed, so it is possible to automate operations for the JBoss ON server.
The CLI script, rhq-cli.sh|bat, is run directly from its cli-install-dirbin directory and used to log into the server. There are two files associated with launching the JBoss ON CLI:
  • A script
  • A file of environment variables

Table 2.1. JBoss ON CLI Files

Operating System CLI Script Environment Variables File
Red Hat Enterprise Linux rhq-cli.sh rhq-cli-env.sh
Microsoft Windows rhq-cli.bat rhq-cli-env.bat

The environment variables in the rhq-cli-env.sh|bat file use defaults that are reasonable for most deployments, so this file usually does not need to be edited. It is possible to reset variables to point a server that doesn't follow the default installation, such as a virtual machine or a JVM that isn't the default. If any variables need to be edited, always set them in this file. The comments at the top of the rhq-cli-env.|bat file contain a detailed list of available environment variables.

IMPORTANT

Do not edit the rhq-cli.sh|bat file. Only set environment variables through the terminal or in the rhq-cli-env.sh|bat file, not the script itself.

NOTE

Be sure to set the correct path to the Java 6 installation in the RHQ_CLI_JAVA_HOME or the RHQ_CLI_JAVA_EXE_FILE_PATH variable.
The rhq-cli.sh|bat script has the following general syntax:
		

rhq-cli.sh|bat [ options ] [ commands ]

It is possible to launch the CLI script, without any arguments. This opens the CLI client without connecting to the server.
cliRoot/rhq-remoting-cli-2.4.0.GA1/bin/rhq-cli.sh
RHQ - RHQ Enterprise Remote CLI 3.0.0-SNAPSHOT
unconnected$
While scripts can be executed without logging in, most of the functionality of the CLI is unavailable. To truly use the JBoss ON CLI, log into the server as a JBoss ON user.
rhq-cli -u rhqadmin -p rhqadmin
The CLI provides two modes of operation: interactive and non-interactive. Interactive mode executes an individual statement. In non-interactive mode, multiple commands can be executed in sequence, in the form of a script. Non-interactive mode provides the capability to automate tasks such as collecting metrics on managed resources or executing a scheduled operation. (Interactive mode provides a simple environment for prototyping, testing, learning and discovering features of the CLI, and these examples are given in interactive mode, though they are also available in non-interactive mode.)
After logging in, any commands (covered in Section 2.2, “JBoss ON CLI Commands”) can be passed to the server.

2.1. JBoss ON CLI Options

Both rhq-cli.bat and rhq-cli.sh scripts accept the options listed in Table 2.2, “Command-Line Options”.

Table 2.2. Command-Line Options

Short Option Long Option Description
-h --help Displays the help text of the command line options of the CLI.
-u --user The username used to log into the JBoss ON server.
-p --password The password used to log into the JBoss ON server.
-P Displays a password prompt where input is not echoed backed to the screen.
-s --host The JBoss ON server against which the CLI executes commands. Defaults to localhost.
-t --port The port on which the JBoss ON server is accepting HTTP requests. The default is 7080.
-c --command A command to be executed. The command must be encased in double quotes. The CLI will exit after the command has finished executing.
-f --file The pathname of a script to execute. See Executing Scripts below for additional information on running scripts.
-v --version Displays CLI and JBoss ON server version information once connected to the the CLI.
--transport Determines whether or not SSL will be used for the communication layer protocol between the CLI and the JBoss ON server. If not specified the value is determined from the {port} option. If you use a port that ends in 443, SSL will be used. You only need to explicitly specify the transport when your JBoss ON server is listening over SSL on a port that does not end with 443.
--args-style Indicates the style or format of arguments passed to the script. See the Executing Scripts below for additional information.

2.2. JBoss ON CLI Commands

2.2.1. login

Logs into a JBoss ON server with the specified username and password. The host name (or IP address) and port can be specified. The host name defaults to localhost and the port defaults to 7080. The transport argument is optional. It determines whether or not SSL will be used for the communication layer protocol between the CLI and the JBoss ON server. If not specified, the value is determined from the port argument. If you use a port that ends in 443, SSL will be used. You only need to explicitly specify the transport when your JBoss ON server is listening over SSL on a port that does not end in 443.
login username password [host] [port]

2.2.2. logout

Logs off of the JBoss ON server but does not exit from the CLI.
logout

2.2.3. quit

Exits the CLI.
quit

2.2.4. exec

Executes a statement or a script with the specified file name. A statement wraps onto multiple lines using backslashes.
exec statement | [-s indexed|named] -f file [args]
Option Description
-f, --file
The file name of the script to execute. A valid file name must be specified.
-s, --style
Indicates the style or format of arguments passed to the script. It must have a value of either indexed or named. See the section, Executing scripts for additional details.

Example 2.1. Executing a Single Statement

localhost:7080> exec var x = 1

Example 2.2. Executing a Multi-Line Statement

localhost:7080(rhqadmin)> for (i = 1; i < 3; ++i) { \
localhost:7080(rhqadmin)>    println(i); \
localhost:7080(rhqadmin)> }
1
2
		
localhost:7080(rhqadmin)>

Example 2.3. Executing a Named Script without Arguments

localhost:7080(rhqadmin)> exec -f myscript.js

Example 2.4. Executing a Named Script with Arguments

localhost:7080(rhqadmin)> exec -f myscript.js 1 2 3

Example 2.5. Executing a Named Script with Named Arguments

localhost:7080(rhqadmin)> exec --style=named -f myscript.js x=1 y=2 y=3

2.2.5. record

Records user input commands to a file.
record [-b | -e] [-a] -f
Option Description
-b, --start
Specify this option to start recording.
-e, --end
Specify this option to stop recording.
-a, --append
Appends output to the end of a file. If not specified, output will be written starting at the beginning of the file.
-f, --file
The file where output will be written.

2.3. Available Implicit Variables in the JBoss ON API

The JBoss ON API makes a number of variables available to interfaces. These variables are bound to the CLI script context.
In the Java programming language, classes in the java.lang package do not have to be imported; they are automatically made available. Classes in other packages, however, have to be explicitly imported.
In the JBoss ON CLI, there are a number of classes from various packages that likely to be used on a routine basis. To simplify using the JBoss ON CLI and remote clients, certain classes are also imported. Everything under the org.rhq.core.domain class is automatically imported, which makes it easier to use the CLI for managing resources, alerts, and other aspects of JBoss ON.
For example, the class org.rhq.core.domain.critiera.ResourceCriteria is commonly used to query resources. The entire class path can be given when calling that class:
var criteria = new org.rhq.core.domain.criteria.ResourceCriteria();
var resource = new org.rhq.core.domain.resource.Resource();
Because the domain class is already imported, this can be more succinctly written as:
var criteria = new ResourceCritiera();
var resource = new Resource();
Common variables used with the CLI scripts are listed in Table 2.3, “Variables Available by Default to the JBoss ON CLI”.

Table 2.3. Variables Available by Default to the JBoss ON CLI

Variable Type Description Access Requires Login
subject org.rhq.core.domain.auth.Subject Represents the current, logged in user. For security purposes, all remote service invocations require the subject to be passed; however, the CLI will implicitly pass the subject for you. YES
pretty
org.rhq.enterprise.client.TabularWriter
Provides for tabular-formatted printed and handles converting objects, particularly domain objects in the packages under org.rhq.core.domain, into a format suitable for display in the console. NO
unlimitedPageControl org.rhq.core.domain.util.PageControl NO
pageControl org.rhq.core.domain.util.PageControl Used to specify paging and sorting on data retrieval operations NO
exporter
org.rhq.enterprise.client.Exporter
Used to export output to a file. Supported formats are plain text in tabular format and CSV. NO
ProxyFactory
org.rhq.enterprise.client.utility.ResourceClientProxy.Factory
NO
rhq
org.rhq.enterprise.client.Controller
Exposes methods of the same name for the built-in commands - login, logout, quit. NO
scriptUtil
org.rhq.enterprise.client.utility.ScriptUtil
Provides methods that can be useful when writing scripts. NO
AlertManager org.rhq.enterprise.server.alert.AlertManagerRemote Provides an interface into the alerts subsystem. YES
AlertDefinitionManager org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote Provides an interface into the alerts definition subsystem. YES
AvailabilityManager org.rhq.enterprise.server.measurement.AvailabilityManagerRemote Provides an interface into the measurement subsystem that can be used to determine resources' availability. YES
CallTimeDataManager org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote Provides an interface into the measurement subsystem for retrieving call-time metric data. YES
RepoManager org.rhq.enterprise.server.content.RepoManagerRemote Provides an interface into the content subsystem for working with repositories. YES
ConfigurationManager org.rhq.enterprise.server.configuration.ConfigurationManagerRemote Provides an interface into the configuration subsystem. YES
DataAccess org.rhq.enterprise.server.report.DataAccessRemote Provides an interface for executing user-defined queries. YES
EventManager org.rhq.enterprise.server.event.EventManagerRemote Provides an interface into the events subsystem. YES
MeasurementBaselineManager org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote Provides an interface into the measurement subsystem for working with measurement baselines. YES
MeasurementDataManager org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote Provides an interface into the measurement subsystem for working with measurement data. YES
MeasurementDefinitionManager org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote Provides an interface into the measurement subsystem for working with measurement definitions. YES
MeasurementScheduleManager org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote Provides an interface into the measurement subsystem for working with measurement schedules. YES
OperationManager org.rhq.enterprise.server.operation.OperationManagerRemote Provides an interface into the operation subsystem. YES
ResourceManager org.rhq.enterprise.server.resource.ResourceManagerRemote Provides an interface into the resource subsystem. YES
ResourceGroupManager org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote Provides an interface into the resource group subsystem. YES
ResourceTypeManager org.rhq.enterprise.server.resource.ResourceTypeManagerRemote Provides an interface into the resource subsystem for working with resource types. YES
RoleManager org.rhq.enterprise.server.authz.RoleManagerRemote Provides an interface into the security subsystem for working with security rules and roles. YES
SubjectManager org.rhq.enterprise.server.auth.SubjectManagerRemote Provides an interface into the security subsystem for working with users. YES
SupportManager org.rhq.enterprise.server.support.SupportManagerRemote Provides an interface into the reporting subsystem for getting reports of managed resources. YES

2.4. Passing Script Arguments in the JBoss ON CLI

A feature common to most programming languages is the ability to pass arguments to the program to be executed. In Java, the entry point into a program is a class's main method, and it takes a String array as an argument. That array holds any arguments passed to the program. Similarly, arguments can be passed to CLI scripts. Arguments passed to a script can be accessed in the implicit args array:

Example 2.6. Handling Script Arguments

if (args.length > 2) {
    throw "Not enough arguments!";
}
		
for (i in args) {
     println('args[' + i '] = ' + args[i]);
}


IMPORTANT

The args variable is only available when executing a script in non-interactive mode or with exec -f.
In addition to the traditional style of indexed-based arguments, named arguments can also be passed to a script:
rhqadmin@localhost:7080$ exec -f echo_args.js --args-style=named x=1, y=2

Example 2.7. echo_args.js

for (i in args) {
     println('args[' + i '] = ' + args[i]);
}
println('named args...');
println('x = ' + x);
println('y = ' + y);


This produces the following output:

Example 2.8. echo_args.js

args[0] = 1
args[1] = 2
named args...
		
x = 1
y = 2


Be aware of the following:
  • You have to explicitly specify that you are using named arguments via the --args-style option
  • The values of the named arguments are still accessible via the implicit args array
  • The named arguments, x and y, are bound into the script context as variables
The CLI is built using the Java Scripting API that was introduced in Java 6. The majority of commands and scripts used with the 7JON; CLI are executed by the underlying script engine. Built-in commands, however, are native Java code and are not executed by the underlying script engine. This is similar to other interpreters like Python where some modules are implemented in C and built into the interpreter. This distinction is important because built-in commands cannot be processed by the script engine. Objects, however, that provide hooks into the built-in commands, are exposed to the scripting environment.

2.5. Configuring Criteria-Based Searching

All of the managers define operations for retrieving data. Most of the managers define criteria-based operations for data retrieval. The criteria API provides a flexible framework for fine-tuned query operations.
The criteria classes reside in the org.rhq.core.domain.criteria package. Criteria-based searches can be implemented in several different ways.

2.5.1. Setting Basic Search Criteria

The simplest criteria is to define results based on what they are, such as resource type.
rhqadmin@localhost:7080$ var criteria = new ResourceCriteria()
rhqadmin@localhost:7080$ var resources = ResourceManager.findResourcesByCriteria(criteria)
It isn't necessary to import the ResourceCriteria class because the org.rhq.core.domain.criteria package is automatically imported.
The method, findResourcesByCriteria follows the naming format of all criteria-based query operations, findXXXByCriteria. This basic criteria search is translated into the following JPA-QL query:
SELECT r
FROM Resource r
WHERE ( r.inventoryStatus = InvetoryStatus.COMMITTED
This fetches all committed resources in the inventory.

2.5.2. Using Sorting

The basic search criteria can be refined so that the resource results are sorted by plug-in.
rhqadmin@localhost:7080$ criteria.addSortPluginName(PageOrdering.ASC)
rhqadmin@localhost:7080$ resources = ResourceManager.findResourcesByCriteria(criteria)
This criteria is translated into the following JPA-QL query:
SELECT r
FROM Resource r
WHERE ( r.inventoryStatus = InventoryStatus.COMMITTED )
ORDER BY r.resourceType.plugin ASC
To add sorting, call criteria.addSortPluginName(). Sorting criteria have methods in the form addSortXXX(PageOrdering order).

2.5.3. Using Filtering

Adding additional matching criteria, like resource name in this example, further narrows the search results.
rhqadmin@localhost:7080$ criteria.addFilterResourceTypeName('JBossAS Server')
rhqadmin@localhost:7080$ resources = ResourceManager.findResourcesByCriteria(criteria)
To add filtering to any criteria, use methods of the form addFilterXXX(). The resulting JPA-QL query will appear as follows:
SELECT r
FROM Resource r
WHERE ( r.inventoryStatus = InventoryStatus.COMMITTED
AND LOWER( r.resourceType.name )  like 'JBossAS Server' ESCAPE '\\' )
This code is all that is required to retrieve all JBoss servers in your inventory. You can further refine your criteria to find JBoss servers that have been registered by a particular agent:
rhqadmin@localhost:7080$ criteria.addFilterResourceTypeName('JBossAS Server')
rhqadmin@localhost:7080$ criteria.addFilterAgentName('localhost.localdomain')
rhqadmin@localhost:7080$ resources = ResourceManager.findResourcesByCriteria(criteria)
This generates the following JPA-QL query:
SELECT r
FROM Resource r
WHERE ( r.inventoryStatus = InventoryStatus.COMMITTED
AND LOWER( r.agent.name )  like 'localhost.localdomain' ESCAPE '\\' )

2.5.4. Fetching Associations

After retrieving the resources, it is possible to view child resources. For example:
rhqadmin@localhost:7080$ criteria.addFilterResourceTypeName('JBossAS Server')
rhqadmin@localhost:7080$ resources = ResourceManager.findResourcesByCriteria(criteria)
rhqadmin@localhost:7080$ resource = resources.get(0)
rhqadmin@localhost:7080$ if (resource.childResources == null) print('no child resources')
This code will print the string no child resources, even if the JBoss server has child resources. The reason for this is that lazy loading is used throughout the domain layer for one-to-many and many-to-many associations. Since child resources are lazily loaded, specify the criteria for the fetch order.
rhqadmin@localhost:7080$ criteria.addFilterResourceTypeName('JBossAS Server')
rhqadmin@localhost:7080$ criteria.fetchChildResources(true)
rhqadmin@localhost:7080$ resources = ResourceManager.findResourcesByCriteria(criteria)
rhqadmin@localhost:7080$ resource = resources.get(0)
rhqadmin@localhost:7080$ if (resource.childResources == null) print('no child resources'); else pretty.print(resource.childResources)
As with the call criteria.fetchChildResources(true), all criteria methods that specify that a particular lazy association should be fetched are of the form, fetchXXX().
rhqadmin@localhost:7080$ if (resource.childResources == null) print('no child resources'); else pretty.print(resource.childResources)
id  name                                                 versio resourceType
----------------------------------------------------------------------------------------------------------------------
222 AlertManagerBean                                            EJB3 Session Bean
222 SchedulerBean                                               EJB3 Session Bean
222 AlertDefinitionManagerBean                                  EJB3 Session Bean
222 AlertConditionConsumerBean                                  EJB3 Session Bean
222 PartitionEventManagerBean                                   EJB3 Session Bean
222 AlertTemplateManagerBean                                    EJB3 Session Bean
223 RHQ Server Group Definition / DynaGroups Subsystem          RHQ Server Group Definition / DynaGrou
222 DiscoveryTestBean                                           EJB3 Session Bean
222 PerspectiveManagerBean                                      EJB3 Session Bean
222 ResourceAvailabilityManagerBean                             EJB3 Session Bean
222 AlertDampeningManagerBean                                   EJB3 Session Bean
218 localhost.localdomain  Embedded JBossWeb Server 2.0. 2.0.1. Embedded Tomcat Server
222 ResourceGroupManagerBean                                    EJB3 Session Bean
222 FailoverListManagerBean                                     EJB3 Session Bean
222 ResourceFactoryManagerBean                                  EJB3 Session Bean
222 AccessBean                                                  EJB3 Session Bean
222 MeasurementTestBean                                         EJB3 Session Bean
223 wstools.sh                                                  Script
222 EventManagerBean                                            EJB3 Session Bean
222 ContentSourceManagerBean                                    EJB3 Session Bean
223 RHQ Server Alerts Engine Subsystem                          RHQ Server Alerts Engine Subsystem
222 AlertConditionManagerBean                                   EJB3 Session Bean
222 ResourceMetadataManagerBean                                 EJB3 Session Bean
222 ResourceManagerBean                                         EJB3 Session Bean
222 GroupDefinitionExpressionBuilderManagerBean                 EJB3 Session Bean
222 MeasurementViewManagerBean                                  EJB3 Session Bean
218 JmsXA Connection Factory                                    ConnectionFactory
222 ResourceTypeManagerBean                                     EJB3 Session Bean
223 JBoss Cache subsystem                                1.0    JBossCacheSubsystem
218 NoTxRHQDS Datasource                                        Datasource
222 DataAccessBean                                              EJB3 Session Bean
222 AlertConditionCacheManagerBean                              EJB3 Session Bean
222 MeasurementProblemManagerBean                               EJB3 Session Bean
222 ServerManagerBean                                           EJB3 Session Bean
222 OperationHistorySubsystemManagerBean                        EJB3 Session Bean
222 ClusterManagerBean                                          EJB3 Session Bean
222 run.sh                                                      Script
...
The output will vary depending on what you have inventoried. These are the child resources of the JBoss ON server we have used in these examples. The JPA-QL query that is generated appears as follows:
SELECT r
FROM Resource r
LEFT JOIN FETCH r.childResources
WHERE ( r.inventoryStatus = InventoryStatus.COMMITTED
AND LOWER( r.resourceType.name )  like 'JBossAS Server' ESCAPE '\\' )

2.6. Displaying Output

2.6.1. TabularWriter

TabularWriter provides for tabular-formatted output. In addition to formatting, it handles converting objects, particularly domain objects in the packages under org.rhq.core.domain, into a format suitable for display in the interactive console. Let's look at an example to illustrate the utility of TabularWriter:
rhqadmin@localhost:7080$ criteria = ResourceCriteria()
rhqadmin@localhost:7080$ criteria.addFilterResourceTypeName('service-alpha')
rhqadmin@localhost:7080$ criteria.addFilterParentResourceName('server-omega-0')
rhqadmin@localhost:7080$ resources = ResourceManager.findResourcesByCriteria(criteria)
id    name            version resourceType
----------------------------------------------------------------------------------------------------------------------
11373 service-alpha-8 1.0     service-alpha
11374 service-alpha-1 1.0     service-alpha
11375 service-alpha-0 1.0     service-alpha
11376 service-alpha-4 1.0     service-alpha
11377 service-alpha-2 1.0     service-alpha
11378 service-alpha-3 1.0     service-alpha
11379 service-alpha-5 1.0     service-alpha
11380 service-alpha-9 1.0     service-alpha
11381 service-alpha-6 1.0     service-alpha
11382 service-alpha-7 1.0     service-alpha
10 rows
The TabularWriter instance that is bound in the script context under the name pretty is implicitly invoked to display the results of ResourceManager.findResourcesByCriteria. The returned resources are displayed in very readable, tabular format. Now let's look at the output if we do not use TabularWriter.
rhqadmin@localhost:7080$ println(resources)
PageList[Resource[id=11373, type=service-alpha, key=service-alpha-8, name=service-alpha-8, version=1.0],
Resource[id=11374, type=service-alpha, key=service-alpha-1, name=service-alpha-1, version=1.0], 
Resource[id=11375, type=service-alpha, key=service-alpha-0, name=service-alpha-0, version=1.0], 
Resource[id=11376, type=service-alpha, key=service-alpha-4, name=service-alpha-4, version=1.0], 
Resource[id=11377, type=service-alpha, key=service-alpha-2, name=service-alpha-2, version=1.0], 
Resource[id=11378, type=service-alpha, key=service-alpha-3, name=service-alpha-3, version=1.0], 
Resource[id=11379, type=service-alpha, key=service-alpha-5, name=service-alpha-5, version=1.0], 
Resource[id=11380, type=service-alpha, key=service-alpha-9, name=service-alpha-9, version=1.0], 
Resource[id=11381, type=service-alpha, key=service-alpha-6, name=service-alpha-6, version=1.0], 
Resource[id=11382, type=service-alpha, key=service-alpha-7, name=service-alpha-7, version=1.0]]
For display purposes, this output is not very usable. Let's look at one more example in which we display a single entity.
rhqadmin@localhost:7080$ pretty.print(resources.get(0))
Resource:
	          id: 11373
	        name: service-alpha-8
	     version: 1.0
	resourceType: service-alpha
The formatting is different when displaying a single object.
Only a subset of the properties in the Resource class are displayed. TabularWriter determines the properties to display through the Summary annotation. If a field of an entity has the @Summary annotation, TabularWriter will include it in the output.

2.6.2. Exporter

An implicit script variable that can assist with writing output to a file is exporter. It uses TabularWriter; however, in addition to writing plain text in a tabular format, it also supports CSV-formatting. First, we will look at an example of exporting to a file as plain text:
rhqadmin@localhost:7080$ exporter.setTarget('raw', 'output.txt')
rhqadmin@localhost:7080$ exporter.write(resources)
File IO operations like opening or closing the file are not a problem because exporter handles the IO operations.
Next, export the results to a CSV file:
rhqadmin@localhost:7080$ exporter.setTarget('csv', 'output.csv')
rhqadmin@localhost:7080$ exporter.write(resources)

2.7. Simple CLI Examples

Example 2.9. Logging in to a Specified Server

You will be connected to the CLI and logged in with the specified credentials on the JBoss ON server running on localhost.
rhq-cli -u rhqadmin -p rhqadmin -s 192.168.1.100 -t 70443
You will be connected to the CLI and logged into the JBoss ON server on 192.168.1.100 that is listening on port 70443. Because the port number ends with 443, the CLI will attempt to communicate with the JBoss ON server over SSL using the sslservlet transport strategy.

Example 2.10. Prompting for a Password

rhq-cli -u rhqadmin -P
You will be connected to the CLI and prompted for a password.

Example 2.11. Passing Variables to the Server

rhq-cli -u rhqadmin -u rhqadmin -c "pretty.print(ResourceTypeManager.findResourceTypesByCriteria(new ResourceTypeCriteria()))" > resource_types.txt
This connects you to the CLI, logs you into the JBoss ON server running on localhost, executes the command in quotes, and redirects the output to the file resource_types.txt.
The ResourceTypeManager.findResourceTypesByCriteria(new ResourceTypeCriteria()) class invokes the findResourceTypesByCriteria operation on ResourceTypeManager. A new ResourceTypeCriteria object is passed as the argument.
Nothing has been specified on the criteria object so all resource types will be returned. The next portion is pretty.print(...). An implicit object made available to commands and scripts by the CLI, pretty is useful for outputting objects in a readable, tabular format, designed with enhanced capabilities for domain objects. This single command provides a nicely formatted, text-based report of the resource types in the inventory.

Example 2.12. Running a Script in the JBoss ON CLI

cliRoot/rhq-remoting-cli-2.4.0.GA1/bin/rhq-cli.sh -f my_script.js
This connects you to the CLI and executes the script file, my_script.js. The CLI will terminate immediately after the script has finished executing.

Chapter 3. Using Resource Proxies

Resource proxies are custom objects generated in the CLI that simplify interacting with the remote and domain APIs. Proxies are obtained through the ProxyFactory by calling getResource() and providing a resource identifier:
var rhelServerOne = ProxyFactory.getResource(10001);
From there, the proxy exhibits the behavior of a custom local interface for that resource. It exposes methods to invoke operations. There will be properties for viewing metrics that connect to the live metric system. There is also support for viewing and editing current configurations and updating and deploying content.
rhqadmin@localhost:7080$ ProxyFactory.getResource(10001)
ResourceClientProxy_$$_javassist_2:
		OSName: MacOSX
           OSVersion: 10.5.7
	  architecture: i386
	  contentTypes: {}
	   createdDate: Thu Aug 06 16:59:32 EDT 2009
	   description: Mac OS X Operating System
	    freeMemory: 120.2MB
	 freeSwapSpace: 984.7MB
	      hostname: ghinklembp.local
	            id: 10001
	          idle: 40%
	  measurements: [Used Memory, Wait Load, Total Memory, System Load, 
			OS Name, Free Memory, Hostname, Architecture, Idle, 
			Total Swap Space, Used Swap Space, User Load, OS Version, 
			Free Swap Space]
	  modifiedDate: Thu Aug 06 16:59:32 EDT 2009
		  name: ghinklembp
	    operations: [org.rhq.enterprise.client.proxy.ResourceClientProxy$Operation@234a98fa,
	                org.rhq.enterprise.client.proxy.ResourceClientProxy$Operation@7681572f]
	  resourceType: Mac OS X
	    systemLoad: 0%
	   totalMemory: 4GB
	totalSwapSpace: 4GB
	    usedMemory: 3.9GB
	 usedSwapSpace: 3GB
	      userLoad: 50%
	       version: MacOSX 10.5.7
	      waitLoad: 0%

3.1. Running Operations

To run an operation on the proxy, call the bound method representing that operation. For example:
platform.viewProcessList();
	
agent.updateAllPlugins();
	
jbossas.restart();

3.2. Configuring Proxies

The resource proxy offers access both to the connection properties and the configuration of the resource itself. Configuration data for a resource such as a data source can be viewed and edited live.
datasource.getResourceConfiguration()
The proxy also integrates with the interactive resource configuration editing wizard to update configurations via a question and answer session. This wizard asks for the values of each configuration property and has some special keystrokes to simplify editing:
  • Pressing return will select the default or existing value for a property.
  • Pressing ctrl-d is equivalent to setting the unset checkbox in the configuration UI.
  • Pressing ctrl-k will exit out of the wizard at any point.
  • Pressing ctrl-e will display the help description for the current property.
After the wizard closes, you have the option to review, save, cancel, or edit the configuration again. Once the configuration is saved, it is updated live on the remote resource.
datasource.editResourceConfiguration()

3.3. Backing Content

The content features for resources that support backing content, such as JBoss Application Server EAR and WAR resources, will be exposed to the proxy allowing you to retrieve or update the content behind that deployed resource.
The following will retrieve the EAR file from the agent and download it to the CLI, saving it as a file with the same name as the deployed file. You can also pass in a relative or fully qualified path to save the content to:
myCustomEAR.retrieveBackingContent(null);
You can send a new version of the content via the following command by passing in the name of the file to send. This will deploy a new version of your custom application content and automatically increment the internal version tracking:
myCustomEAR.updateBackingContent('CustomEAR_v2.ear');

Chapter 4. Example: Scripting Resource Deployments

A common use case for management tools is to automate deployments of new or existing applications. This example creates an easy script for basic management tasks:
  • Find all JBoss EAP instances for a specified JBoss ON group.
  • Shut down each EAP instance.
  • Update binaries for existing deployed applications or create new deployments.
  • Restart the EAP instance.
  • End the loop.

4.1. Creating the Script

The script should have two command-line parameters. The first should be the path of the new application that is installed in the group. The second is the name of the group itself. These parameters are parsed in the script (as described in more detail in Section 2.4, “Passing Script Arguments in the JBoss ON CLI”.
For example:
if( args.length < 2 ) usage();
				
var fileName = args[0];
var groupName = args[1];
Next, check if the path is valid and if the current user can read it. This is done by using Java classes as shown here:
// check that the file exists and that we can read it
var file = new java.io.File(fileName);
				
if( !file.exists() ) {
    println(fileName + " does not exist!");
    usage();
}
				
if( !file.canRead() ) {
    println(fileName + " can't be read!");
    usage();
}
Verify that the group really exists on my JBoss ON server:
// find resource group
var rgc = new ResourceGroupCriteria();
rgc.addFilterName(groupName);
rgc.fetchExplicitResources(true);
var groupList = ResourceGroupManager.findResourceGroupsByCriteria(rgc);
The important part here is the call the resources.
rgc.fetchExplicitResources(true);
Check if there is a group found:
if( groupList == null || groupList.size() != 1 ) {
    println("Can't find a resource group named " + groupName);
    usage();
}
				
var group = groupList.get(0);
				
println("  Found group: " + group.name );
println("  Group ID   : " + group.id );
println("  Description: " + group.description);
After validating that there is a group with the specified name, check if the group contains explicit resources:
if( group.explicitResources == null || group.explicitResources.size() == 0 ) {
    println("  Group does not contain explicit resources --> exiting!" );
    usage();
}
var resourcesArray = group.explicitResources.toArray();
resourceArray now contains all resources which are part of the group. Next, check if there are JBoss AS Server instances which need to be restarted before the application is deployed.
for( i in resourcesArray ) {
    var res = resourcesArray[i];
    var resType = res.resourceType.name;
    println("  Found resource " + res.name + " of type " + resType + " and ID " + res.id);
				
    if( resType != "JBossAS Server") {
        println("    ---> Resource not of required type. Exiting!");
        usage();
    }
				
    // get server resource to start/stop it and to redeploy application
    var server = ProxyFactory.getResource(res.id);
}
This requires a group with only JBossAS Server resource types as top level resources. Now server contains the JBossAS instance. This requires re-reading the server because it needs to be fully populated. Internally, the CLI is using simple JPA persistence, and it is necessary to not always fetch all dependent objects.
Next, traverse all the children of the server instance and find the resource name of the application:
var children = server.children;
for( c in children ) {
    var child = children[c];
				
    if( child.name == packageName ) {
    }
}
packageName is the name of the application without version information and path as shown in the JBoss ON GUI as deployed applications.
Create a backup of the original version of the application:
println("    download old app to /tmp");
child.retrieveBackingContent("/tmp/" + packageName + "_" + server.name + "_old");
A copy of the old application with the server name decoded in path is available in the /tmp/ directory.
Shut down the server and upload the new application content to the server. The shutdown function for AS4 servers is shutdown() and for AS5 servers is shutDown().
println("    stopping " + server.name + "....");
try {
    server.shutdown();
}
catch( ex ) {
    println("   --> Caught " + ex );
}
				
				
println("    uploading new application code");
child.updateBackingContent(fileName);
				
println("    restarting " + server.name + "....." );
				
try {
    server.start();
}
catch( ex ) {
    println("   --> Caught " + ex );
}

4.2. Creating a New Resource

At this point, existing application can be updated. The next step is to create the resource through the CLI and then deploy it to the JBoss server.

NOTE

This example is for creating a JBoss AS 4 resource. The plug-in name and available deployConfig parameters are different for a JBoss AS 5 resource. Check out the Resource Monitoring Reference for information on the JBoss AS 5 plug-in and configuration parameters.
First, get the resource type for the application. This depends on several parameters:
  1. The type of the application (e.g., WAR or EAR)
  2. The type of the container the app needs to be deployed on (such as Tomcat or JBoss AS)
var appType = ResourceTypeManager.getResourceTypeByNameAndPlugin( appTypeName, "JBossAS" );
if( appType == null ) {
    println("  Could not find application type. Exit.");
    usage();
}
Then get the package type of the application.
var realPackageType = ContentManager.findPackageTypes( appTypeName, "JBossAS" );
				
if( realPackageType == null ) {
    println("  Could not find JBoss ON's packageType. Exit.");
    usage();
}
Each resource in JBoss ON has some configuration parameters, including the WARs or EARs deployed on a JBoss AS. To be able to create a new resource, these parameters need to be filled in.
// create deployConfig 
var deployConfig = new Configuration();
deployConfig.put( new PropertySimple("deployDirectory", "deploy"));
deployConfig.put( new PropertySimple("deployZipped", "true"));
deployConfig.put( new PropertySimple("createBackup", "false"));
The property names can be retrieved by calling a list of supported properties by the package type by calling this method:
var deployConfigDef = ConfigurationManager.getPackageTypeConfigurationDefinition(realPackageType.getId());
Provide the package bits as a byte array:
var inputStream = new java.io.FileInputStream(file);
var fileLength = file.length();
var fileBytes = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, fileLength);
for (numRead=0, offset=0; ((numRead >= 0) && (offset < fileBytes.length)); offset += numRead ) {
    numRead = inputStream.read(fileBytes, offset, fileBytes.length - offset); 	
}
Then, create the resource:
ResourceFactoryManager.createPackageBackedResource(
    server.id,
    appType.id,
    packageName,
    null,  // pluginConfiguration
    packageName,
    packageVersion,
    null, // architectureId        
    deployConfig,
    fileBytes
);
Make sure that the given JBoss AS server instance is still running and that JBoss ON knows that it is running, or it will throw an exception saying that the JBoss ON agent is not able to upload the binary content to the server.

Chapter 5. Example: Managing Grouped Servers through the CLI

Oracle and IBM, along with other enterprise servers, have a concept of managed servers. A managed server means that there is a central instance that delivers deployment artifacts to all registered managed application servers. Using managed servers helps administrators ensure that all active application servers have the same version of the deployed packages and configuration.
Using a scripting interface to manage those managed servers and to gather required measurements is extremely helpful, and the JBoss Operations Network CLI can be used to control those managed servers for both JBoss Operations Network and JBoss AS servers. This builds on the basic management outlined in Chapter 4, Example: Scripting Resource Deployments.
Executing the management scripts requires JBoss EAP 4.x or 5.x, in addition to the JBoss ON CLI and JDK 6.

5.1. Creating the Wrapper Script

To make it easier to use scripts with JBoss ON, create a simple wrapper script. This script takes the command-line arguments and calls the JBoss ON CLI with one of the scripts as argument.
#!/bin/bash
#
# groupcontrol
# ------------
# This is a simple wrapper script for all the java script scripts in this folder.
# Start this script with some parameters to automate group handling from within the
# command line.
# 
# With groupcontrol you can do the following:
#   deploy: Deploys an application to all AS instances specified by group name
#   create: Create a new group
#   delete: Delete an existing group
#   start : start all EAP instances specified by group name
#   stop  : stop all EAP instances specified by group name
#   add   : Add a new EAP instance to the specified group
#   remove: Remove an existing EAP instance from the specified group
#   status: Print the status of all resources of a group
#
# 
			
## Should not be run as root.
if [ "$EUID" = "0" ]; then
   echo " Please use a normal user account and not the root account"
   exit 1
fi
		
## Figure out script home
MY_HOME=$(cd `dirname $0` && pwd)
SCRIPT_HOME=$MY_HOME/scripts
			
## Source some defaults
. $MY_HOME/groupcontrol.conf
			
## Check to see if we have a valid CLI home
if [ ! -d ${JON_CLI_HOME} ]; then
     echo "JON_CLI_HOME not correctly set. Please do so in the file"
     echo $MY_HOME/groupcontrol.conf
     exit 1
fi
			
RHQ_OPTS="-s $JON_HOST -u $JON_USER -t $JON_PORT"
# If JBoss ON_PWD is given then use it as argument. Else let the user enter the password
if [ "x$JON_PWD" == "x" ]; then
     RHQ_OPTS="$RHQ_OPTS -P"
else
     RHQ_OPTS="$RHQ_OPTS -p $JON_PWD"
fi
			
#echo "Calling groupcontrol with $RHQ_OPTS"
			
usage() {
     echo "  Usage $0:"
     echo "  Use this tool to control most group related tasks with a simple script."
     echo "  ------------------------------------------------------------------------- "
     <....>
}
			
doDeploy() {
     $JON_CLI_HOME/bin/rhq-cli.sh $RHQ_OPTS -f $SCRIPT_HOME/deployToGroup.js $2 $3
}
			
			
case "$1" in
'deploy')
	doDeploy $*
	;;     
*)
        usage $*
        ;;
esac
This script needs a groupcontrol.conf file which gets sourced into the execution context of this script. The .conf file looks like this:
##	
## This file contains some defaults for the groupcontrol script
##
JON_CLI_HOME=/opt/jon/jon-server-2.4.0.GA1/rhq-remoting-cli-1.3.0.GA
JON_HOST=localhost
JON_PORT=7080
			
# The user you want to connect with
JON_USER=rhqadmin
			
# if you omit the password here, you'll be prompted for it.
JON_PWD=rhqadmin

5.2. Creating the JBoss ON Scripts

5.2.1. Creating a Compatible Group

To be able to simulate this managed server functionality, all of the resources have to be properly grouped. A group can be a set of servers which belong to the productive environment. A group could also be a set of servers of one domain of the production environment.
Create a group:
// Now just create the group
var rg = new ResourceGroup(groupName, resType);
rg.setRecursive(true);
rg.setDescription("Created via groupcontrol scripts on " + new java.util.Date().toString());
				
ResourceGroupManager.createResourceGroup(rg);
Then, verify that the group exists and set the allowed group resource type. This example creates a compatible group, so only resources of the same type will be grouped together. This is controlled with resType:
// First find resourceType specified by pluginName
var resType = ResourceTypeManager.getResourceTypeByNameAndPlugin("JBossAS Server", pluginName);
The resource pluginName is either JBossAS or JBossAS5.

5.2.2. Adding Resources to a Group

Add resources to the blank group as follows:
// now, search for EAP resources based on criteria
criteria = new ResourceCriteria();
criteria.addFilterName(searchPattern);
criteria.addFilterResourceTypeName("JBossAS Server");
				
var resources = ResourceManager.findResourcesByCriteria(criteria);
This means that JBoss AS Server instances should be based on the given searchPattern. For example:
tolnedra.belgariad JBoss EAP 4.3.0.GA_CP03 node1 (192.168.100.50:1099)
tolnedra.belgariad JBoss EAP 4.3.0.GA_CP03 node2 (192.168.100.51:1099)
Searching the node returns both instances, while searching only for node1 returns only node1.
A resource should only be added if a single instance was found:
if( resources != null ) {
  if( resources.size() > 1 ) {
	println("Found more than one JBossAS Server instance. Try to specialize.");
     for( i =0; i < resources.size(); ++i) {
	  var resource = resources.get(i);
          println("  found " + resource.name );
     }
  }
  else if( resources.size() == 1 ) {
     resource = resources.get(0);
     println("Found one JBossAS Server instance. Trying to add it.");
     println("  " + resource.name );
        ResourceGroupManager.addResourcesToGroup(group.id, [resource.id]);
     println("  Added to Group!");
  }
  else {
        println("Did not find any JBossAS Server instance matching your pattern. Try again.");
  }
}

5.2.3. Getting Inventory and Status Information

Now, create a group and add resources to it. The inventory information is available by using the AvailabilityManager call:
// get server resource to start/stop it and to redeploy application
var server = ProxyFactory.getResource(res.id);
var avail  = AvailabilityManager.getCurrentAvailabilityForResource(server.id);
				
println("  " + server.name );
println("    - Availability: " + avail.availabilityType.getName());
println("    - Started     : " + avail.startTime.toGMTString());
println("");

5.2.4. Deploying Applications

Deploying new or existing applications was explained in Chapter 4, Example: Scripting Resource Deployments.
This method is similar, but it doesn't require stopping and restarting the server:
// we need check to see if the given server is up and running
var avail = AvailabilityManager.getCurrentAvailabilityForResource(server.id);
				
// unfortunately, we can only proceed with deployment if the server is running. Why?
if( avail.availabilityType.toString() == "DOWN" ) {
	   println("  Server is DOWN. Please first start the server and run this script again!");
	   println("");
	   continue;
}

5.2.5. Starting, Stopping, and Restarting the Server

JBoss ON servers can be started and stopped by iterating through all the resources in a specific group and issuing the corresponding operation:
  • shutdown() for AS4 servers and shutDown() for AS5 servers
  • start()
  • restart()
var resourcesArray = group.explicitResources.toArray();
				
for( i in resourcesArray ) {
     var res = resourcesArray[i];
     var resType = res.resourceType.name;
     println("  Found resource " + res.name + " of type " + resType + " and ID " + res.id);
				
     if( resType != "JBossAS Server") {
	  println("    ---> Resource not of required type. Exiting!");
	  usage();
     }
				
     // get server resource to start/stop it and to redeploy application
     var server = ProxyFactory.getResource(res.id);
     println("    Starting " + server.name + "....");
     try {
	  server.start();
     }
     catch( ex ) {
	  println("   --> Caught " + ex );
     }
}

5.2.6. Scheduling an Operation

Even after the script to start and stop the resources, it takes some time for the operation to be executed and for JBoss ON to detect the change. This is due to the fact that an availability report needs to be sent from the agent to the server. The OperationManager class can schedule an executeAvailabilityScan operation for all agents.
First, get a list of all agent resources:
println("Scanning all RHQ Agent instances");
var rc = ResourceCriteria();
var resType = ResourceTypeManager.getResourceTypeByNameAndPlugin("RHQ Agent", "RHQAgent");
rc.addFilterResourceTypeName(resType.name);          
resources = ResourceManager.findResourcesByCriteria(rc).toArray();
				
var idx=0;
for( i in resources ) {
     if( resources[i].resourceType.id == resType.id ) {
	  agents[idx] = resources[i];
	  idx = idx + 1;
     }
}
Then, traverse the agents array and schedule the required operation:
for( a in agents ) {
     var agent = agents[a];
				
     println("  executing availability scan on agent" );
     println("    -> " + agent.name + " / " + agent.id);
     var config = new Configuration();
     config.put(new PropertySimple("changesOnly", "true") );
				
     var ros = OperationManager.scheduleResourceOperation(
	  agent.id, 
	  "executeAvailabilityScan", 
	  0,   // delay
	  1,   // repeatInterval
	  0,   // repeat Count
	  10000000,  // timeOut
	  config,    // config
	  "test from cli" // description
     );
				
     println(ros);
     println("");
}
To get the name of the operation, use a method on the OperationManger. This provides a list of all operation definitions:
var odc = new OperationDefinitionCriteria();
odc.addFilterResourceTypeName("RHQ Agent");
var oppList = OperationManager.findOperationDefinitionsByCriteria(odc);
oppList now contains a set of OperationDefinitions, including the name of the operation, the description and whether the operation needs to get some parameters. Nearly all resource types have operations defined that can be issued or scheduled in that way, so it is possible to invoke the agent's executePromptCommand operation. This operation requires a Configuration element to define the command and its parameters.

5.2.7. Gathering Metric Data of Managed Servers

Another area which is particularly useful to an administrator is the health status of an application server. This can be determined through the JBoss ON CLI by creating a script that is able to connect to the Measurement interface of JBoss ON.
JBoss ON is designed for complex monitoring; nearly all existing resources have a set of metrics that are collected by an active agent. The agent collects these metrics and sends a summary to the connected JBoss ON server which then stores the data in a database. JBoss ON is also designed to be as generic as possible, so that it is simple to write a custom plug-in that collects its own metrics.
To be able to store those metrics, JBoss ON needs to have a set of metadata which describes a metric. This metadata can be numeric, performance, or string-based, whatever represents the expected results from the plug-in.
To retrieve some life metric data, first define which metric to retrieve the value for using the MeasurementDefinitionManager class:
var mdc = MeasurementDefinitionCriteria();
mdc.addFilterResourceTypeName("JBossAS Server"); 
mdc.addFilterDisplayName(metricName);
var mdefs = MeasurementDefinitionManager.findMeasurementDefinitionsByCriteria(mdc);
This whole process is building and filling a Criteria object. The next part, then, is to request metric definitions of resources of type JBossAS Server, filtered by the metric display name such as JVM Total Memory.
Once there is a metric definition, the MeasurementDataManager class finds life data for the metric and the given resource:
var metrics = MeasurementDataManager.findLiveData(resId, [metricDefId]); 
if( metrics == null || metrics.size() == 0 ) {
     return 0;
}
else {
     var metric = metrics.toArray()[0];
     if( metric != null && metric.value != null ) {
	  return metric.value.longValue();
     }
     else {
	  return 0;
     }
}
The value of the metric could be anything; in this case, it is a numeric value.
findLiveData() tries to find live metric data. It only works if the agent of the resource is up and running. To ensure this, check the agent's status field. If it returns -1, the agent is not connected. If it is 0, everything is connected and the method can be called.

Chapter 6. Example: Writing a Custom Java Client

As alluded to in Chapter 1, Introduction to the JBoss ON CLI Interface, the clients in JBoss ON use either the JBoss Remoting framework or the JBoss ON remote APIs to access server functionality. The JBoss ON CLI is essentially a Java skin over the remote API. Any application written in Java or a JVM-compatible language can access the JBoss ON remote API.

IMPORTANT

The remote API cannot be run from a client inside an application server. For example, the remote API cannot be run from a client inside an EAP instance; it fails with errors like the following:
Caused by: java.lang.IllegalArgumentException: interface
org.rhq.enterprise.server.auth.SubjectManagerRemote is not visible from class
loader
at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
at
org.rhq.enterprise.client.RemoteClientProxy.getProcessor(RemoteClientProxy.java:69)
The power of the JBoss ON Java interface is the programmatic way that it handles remote clients. The Java interface creates a client object and works with it as if that client object were in the command line:
{
	Client joprClient = new Client(...)
	jopClient.getResourceManager().findResources(...)
	...
}
This is the recommended approach for a programmatic remote client.

6.1. Getting the API

The JBoss ON remote API is downloaded and installed with the JBoss ON CLI package, as described in Section 1.5, “Installing the JBoss ON Command-Line Tool”. The CLI usage examples in this guide can be used as general guidelines for calling the API in the Java code.
The javadocs for the JBoss ON remote API can be viewed at https://docs.redhat.com/docs/en-US/JBoss_Operations_Network/2.4/html/API_Guides/index.html.

6.2. Example Custom Java Client

This example creates an LDAP integration for LDAP group-based authorization for JBoss ON. The sample Java class pulls in the authorization and search classes from the JBoss ON API, and then the script starts a simple synchronization service that maps the LDAP groups and users to the JBoss ON roles and users.

NOTE

LDAP-based group authorization is already configured in JBoss ON. This client is simply used as an example to show how a remote Java client can interact with the JBoss ON server.

6.2.1. Sample Java Class Using the JBoss ON API

This Java class uses the JBoss ON API for users, permissions, roles, and searching and sorting resource entries. The class then sets up a mapping between the LDAP database and the JBoss ON database, so that the user and role information in each is synchronized.
package org.rhq.sample.client.java.ldap;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.authz.Role;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.criteria.ResourceGroupCriteria;
import org.rhq.core.domain.criteria.RoleCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.client.RemoteClient;
import org.rhq.enterprise.server.auth.SubjectManagerRemote;
import org.rhq.enterprise.server.authz.RoleManagerRemote;
import org.rhq.enterprise.server.resource.ResourceManagerRemote;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;

/**
 * This sample program utilizes the RHQ Remote API via a Java Client.
 * 
 * The RHQ CLI is the preferred remote client approach for script-based clients.  Programmatic Java clients
 * can utilize the Remote API via the same mechanism used by the CLI, making use of ClientMain object, as
 * done in this sample.  This is the recommended mechanism although a remote Java client could als use the 
 * remote API exposed as WebServices. 
 * 
 * @author Jay Shaughnessy
 */
public class SampleLdapClientMain {
    // A remote session always starts with a login, define default user/password/server/port
    private static String username = "rhqadmin";
    private static String password = "rhqadmin";
    private static String host = "localhost";
    private static int port = 7080;

    /**
     * This is a standalone remote client but calls to the remote API could be embedded into another application.
     */
    public static void main(String[] args) {
        if (args.length > 0) {
            if ((args.length != 2) && (args.length != 4)) {
                System.out
                    .println("\nUsage: SampleLdapClientMain [ [ username password ] | [username password host port] ]");
                System.out.println("\n\nDefault credentials: rhqadmin/rhqadmin");
                System.out.println("\n\nDefault host: determined from wsconsume of WSDL");
                return;
            } else {
                username = args[0];
                password = args[1];

                if (args.length == 4) {
                    host = args[2];
                    port = Integer.valueOf(args[3]);
                }
            }
        }

        LdapClient ldapClient = null;

        try {
            ldapClient = new LdapClient();
            ldapClient.synchLdapJbasManagers();

        } catch (Throwable t) {
            System.out.println("Error: " + t);
            t.printStackTrace();
        } finally {
            if (null != ldapClient) {
                // clean up the session by logging out from the RHQ server
                ldapClient.logout();
            }
        }
    }

    /**
     * The LdapClient interacts with the RHQ Server to help synchronize a (fake) LDAP server with RHQ.  
     */
    public static class LdapClient {
        // group containing all jbas resources
        private static final String JBAS_GROUP = "jbas-resource-group";

        // role for jbas managers
        private static final String JBAS_MANAGER_ROLE = "jbas-manager-role";

        // the users that should be assigned the JBAS_MANAGER_ROLE    
        private static final List<String> JBAS_MANAGERS = new ArrayList<String>();

        // the prmissions that should be assigned the JBAS_MANAGER_ROLE
        private static final Set<Permission> JBAS_MANAGER_PERMISSIONS = new HashSet<Permission>();

        // jbas AS Server resource type (note, this picks up AS4 and AS5 resources as they share the same type name)
        private static final String JBAS_SERVER_NAME = "JBossAS Server";

        /* The Remote API offers different remote "managers" roughly broken down by subsystem/function
         * Below are the managers needed by this client, there are several others that offer
         * interfaces into areas such as operations, alerting, content, etc. See the API. 
         */
        private ResourceGroupManagerRemote resourceGroupManager;
        private ResourceManagerRemote resourceManager;
        private RoleManagerRemote roleManager;
        private SubjectManagerRemote subjectManager;

        /* This represents the RHQ user that is logged in and making the remote calls. This user must
         * already exist.  For the work being done here the user must also have SECURITY_MANAGER permissions.
         */
        private Subject subject;

        /* This is the object through which we access the remote API */
        private RemoteClient remoteClient;

        static {
            // add some fake users since we're not actually hooked into an ldap server
            JBAS_MANAGERS.add("mgr-1");
            JBAS_MANAGERS.add("mgr-2");

            // add some permissions since we're not actually hooked into an ldap server
            JBAS_MANAGER_PERMISSIONS.addAll(Permission.RESOURCE_ALL);
        }

        public LdapClient() throws Exception {
            this.remoteClient = new RemoteClient(null, host, port);
            this.subject = remoteClient.login(username, password);

            this.resourceGroupManager = this.remoteClient.getResourceGroupManagerRemote();
            this.resourceManager = this.remoteClient.getResourceManagerRemote();
            this.roleManager = this.remoteClient.getRoleManagerRemote();
            this.subjectManager = this.remoteClient.getSubjectManagerRemote();
        }

        /*
         * This method simulates a synch between an Ldap server that has defined a group of JBAS managers
         * and wants to associate them with a role allowing jbas management.  Meaning, a role that 
         * has the proper permissions and is associated with the jbas resources.
         */
        private void synchLdapJbasManagers() throws Exception {

            // create the jbas manager role if necessary            
            // use a criteria search with a name filter to look for the role
            RoleCriteria roleCriteria = new RoleCriteria();
            roleCriteria.setFilterName(JBAS_MANAGER_ROLE);
            PageList<Role> jbasManagerRoles = roleManager.findRolesByCriteria(subject, roleCriteria);
            Role jbasManagerRole;
            if (1 == jbasManagerRoles.size()) {
                jbasManagerRole = jbasManagerRoles.get(0);
            } else {
                // if it doesn't exist, create it
                jbasManagerRole = new Role(JBAS_MANAGER_ROLE);
                jbasManagerRole = roleManager.createRole(subject, jbasManagerRole);
            }
            // ensure the proper permissions are granted to the role by using an update
            jbasManagerRole.setPermissions(JBAS_MANAGER_PERMISSIONS);
            roleManager.updateRole(subject, jbasManagerRole);

            // create, populate and associate the jbas group if necessary
            ResourceGroupCriteria resourceGroupCriteria = new ResourceGroupCriteria();
            resourceGroupCriteria.addFilterName(JBAS_GROUP);
            PageList<ResourceGroup> jbasGroups = resourceGroupManager.findResourceGroupsByCriteria(subject,
                resourceGroupCriteria);
            ResourceGroup jbasGroup;
            if (1 == jbasGroups.size()) {
                jbasGroup = jbasGroups.get(0);
            } else {
                jbasGroup = new ResourceGroup(JBAS_GROUP);
                jbasGroup = resourceGroupManager.createResourceGroup(subject, jbasGroup);
                // Ensure the group is recursive to make all the children available.
                // In this case a specific method is available, so a general update call is not needed.
                resourceGroupManager.setRecursive(subject, jbasGroup.getId(), true);
            }

            // Now find all of the JBAS server resources by adding a criteria filter on resource type name
            ResourceCriteria resourceCriteria = new ResourceCriteria();
            resourceCriteria.addFilterResourceTypeName(JBAS_SERVER_NAME);
            PageList<Resource> jbasServers = resourceManager.findResourcesByCriteria(subject, resourceCriteria);
            if (!jbasServers.isEmpty()) {
                int[] jbasServerIds = new int[jbasServers.size()];
                int i = 0;
                for (Resource jbasServer : jbasServers) {
                    jbasServerIds[i++] = jbasServer.getId();
                }

                // ..and add them to the group which will be associated with the manager role
                resourceGroupManager.addResourcesToGroup(subject, jbasGroup.getId(), jbasServerIds);
            }

            // Now, associate the mixed group of Jbas servers to the manager role  
            roleManager.addResourceGroupsToRole(subject, jbasManagerRole.getId(), new int[] { jbasGroup.getId() });

            // synch managers with the role
            // 1. remove obsolete managers
            roleCriteria = new RoleCriteria();
            roleCriteria.setFilterId(jbasManagerRole.getId());
            // add a fetch criteria to the criteria object to get the optionally returned subjects for the role.
            roleCriteria.setFetchSubjects(true);
            jbasManagerRole = roleManager.findRolesByCriteria(subject, roleCriteria).get(0);
            Set<Subject> subjects = jbasManagerRole.getSubjects();
            if ((null != subjects) && !subjects.isEmpty()) {
                for (Subject subject : subjects) {
                    if (!JBAS_MANAGERS.contains(subject.getName())) {
                        roleManager.removeSubjectsFromRole(subject, jbasManagerRole.getId(), new int[] { subject
                            .getId() });
                    }
                }
            }

            // 2. add new managers, create subjects for the managers, if necessary
            Subject jbasManagerSubject;
            for (String jbasManager : JBAS_MANAGERS) {
                jbasManagerSubject = subjectManager.getSubjectByName(jbasManager);
                // add the required fields for a subject, note that we skip credentials since this is 
                // simulating ldap
                if (null == jbasManagerSubject) {
                    jbasManagerSubject = new Subject();
                    jbasManagerSubject.setName(jbasManager);
                    jbasManagerSubject.setEmailAddress("jbas.manager@sample.com");
                    jbasManagerSubject.setFactive(true);
                    jbasManagerSubject.setFsystem(false);
                    jbasManagerSubject = subjectManager.createSubject(subject, jbasManagerSubject);
                }

                // Finally, make sure my current set of jbas managers is associated with the manager role.
                roleManager.addSubjectsToRole(subject, jbasManagerRole.getId(),
                    new int[] { jbasManagerSubject.getId() });
            }
        }

        public void logout() {
            if ((null != subjectManager) && (null != subject)) {
                try {
                    subjectManager.logout(subject);
                } catch (Exception e) {
                    // just suppress the exception, nothing else we can do
                }
            }
        }
    }
}

6.2.2. Sample LDAP Script

The sample .bat script invokes the custom Java class.
@echo off

rem ===========================================================================
rem RHQ Remote Client LDAP Example Startup Script
rem
rem The following variables must be set
rem
rem RHQ_CLIENT_HOME    The home directory of the RHQ Client Installation.  The
rem                    RHQ Client can be downloaded from the RHQ GUI under
rem                    the Administration->Downloads menu.
rem ===========================================================================

rem ----------------------------------------------------------------------
rem Set Environment Variables
rem ----------------------------------------------------------------------
set RHQ_CLIENT_HOME=*MUST BE SET*


rem ----------------------------------------------------------------------
rem Prepare the classpath
rem Add all jar files supplied by the RHQ remote client install
rem ----------------------------------------------------------------------

set CLASSPATH=.
call :append_classpath "%RHQ_CLIENT_HOME%\conf"
for /R "%RHQ_CLIENT_HOME%\lib" %%G in ("*.jar") do (
   call :append_classpath "%%G"
)

rem ----------------------------------------------------------------------
rem Prepare the VM command line options to be passed in
rem ----------------------------------------------------------------------

if not defined RHQ_CLIENT_JAVA_OPTS (
   set RHQ_CLIENT_JAVA_OPTS=-Xms64m -Xmx128m -Djava.net.preferIPv4Stack=true
)

rem ----------------------------------------------------------------------
rem Uncomment For debugging on port 9999
rem ----------------------------------------------------------------------

rem set RHQ_CLIENT_ADDITIONAL_JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,address=9999,server=y,suspend=y


rem ----------------------------------------------------------------------
rem Execute the VM which starts the CLIENT
rem ----------------------------------------------------------------------

set CMD="%JAVA_HOME%\bin\java.exe" %RHQ_CLIENT_JAVA_OPTS% %RHQ_CLIENT_ADDITIONAL_JAVA_OPTS% -cp "%CLASSPATH%" org.rhq.sample.client.java.ldap.SampleLdapClientMain %RHQ_CLIENT_CMDLINE_OPTS% %*

cmd.exe /S /C "%CMD%"

goto :done

rem ----------------------------------------------------------------------
rem CALL subroutine that appends the first argument to CLASSPATH
rem ----------------------------------------------------------------------

:append_classpath
set _entry=%1
if not defined CLASSPATH (
   set CLASSPATH=%_entry:"=%
) else (
   set CLASSPATH=%CLASSPATH%;%_entry:"=%
)
goto :eof

rem ----------------------------------------------------------------------
rem CALL subroutine that exits this script normally
rem ----------------------------------------------------------------------

:done

endlocal

exit /B 0