How to create a plugin for openQRM ?
by Matt Rechenburg
This how to is dedicated for all people who would like to integrate their own,
custom services within the openQRM data-center management console. It provides
an overview about the openQRM plugin API and gives detailed examples how to use it.
The explanations in this howto will be based on an integration of an example service
working in a common client-server way. This service which is going to be integrated
will be called "myservice" and has a "myservice-server" and a "myservice-client".
An example of such a service already integrated in openQRM is the Nagios-plugin.
The Nagios-plugin automatically starts the Nagios-server part on the openQRM-server and
the Nagios-client (NRPE) on the managed nodes. In this howto the integration of the
example service "myservice" will work in a similar way.
Contents
Requirements
Creating the plugin skeleton
Creating the plugin definition and function file
Creating the init-scripts for "myservice"
Test-building the "myservice" plugin
Completing the "myservice" plugin
Connecting the "myservice-server" to openQRM
Connecting the "myservice-client" to the systems manged by openQRM
Building and installing the "myservice" plugin
Building rpm-packages for the "myservice" plugin
Summary (part 1)
Get the files used for part 1
Adding a web-page to the plugin
Creating a menu entry for the custom web-page
Adding a simple web-service to "myservice-serverd"
Re-compiling and re-installing the "myservice" plugin
Screenshot of the web-page and menu integration
Summary (part 2)
Get the files used for part 2
Events in openQRM
Adding a custom event to openQRM via the "myservice" plugin
Adding an EventListerner to the "myservice" plugin
Creating the command-script connected to the EventListener
Re-compiling and re-installing the "myservice" plugin
Calling the custom event via the qrm-cli
Summary (part 3)
Get the files used for part 3
Adding java code to the "myservice" plugin
Adding maven build configuration
Interfacing with the openQRM-server objects
Example: Creating a "id to ip" calculator
Adding the menu item for the "id to ip" calculator
Re-compiling and re-installing the "myservice" plugin
Screenshot of the "id to ip" calculator
Summary (part 4)
Get the files used for part 4
Urls
Revision History
Plugin basics (part 1)
Requirements
For starting with plugin-development you need to have openQRM compiled from
its sources. It is recommended to use the sources from the cvs because this
will generally include the latest fixes.
To compile openQRM you need to have the development components installed on
your build-system (gcc/c++, make, autoconf, etc.).
Also the java jdk version 1.5 from sun and maven version 1.0.2 is required.
Please notice that you need to have exactly this java + maven versions !
Hint: to speed up compilation please remove all plugin-directories from the
.../src/plugins/ directory expect e.g. the dhcpd plugin.
Creating the plugin skeleton
First create a new directory in the openQRM sources at ../src/plugins/ called "myservice". This directory should be named as plugin you plan to create.
cd ../src/plugins/
mkdir -p myservice
Then create a basic Makefile with the following content :
#
# openQRM plugin myservice Makefile
#
# standard definitions for the build- packaging-system
export PACKAGE_PREFIX = openqrm
export PACKAGE_GROUP = plugin
export PACKAGE_NAME = myservice
export PACKAGE_F_NAME = $(PACKAGE_PREFIX)-$(PACKAGE_GROUP)-$(PACKAGE_NAME)
# defining the output directory :
# ../../../out for general compilation
# ../../../pkg_stage/$(PACKAGE_F_NAME)/opt for rpm/deb packaging
ifdef PACKAGE_TYPE
OUTDIR := ../../../pkg_stage/$(PACKAGE_F_NAME)/opt
else
OUTDIR := ../../../out
endif
# define which files should be installed
INSTALL_FILES := etc/myservice.xml, -m 0700 etc/init.d, include
INSTALL_FILES_DEST := $(OUTDIR)/qrm/plugins/myservice
# include the build- and packaging-functions
INC_NAME := ../../build/Makefile.inc
include $(INC_NAME)
RPM_INC_NAME := ../../build/Makefile.rpm.inc
include $(RPM_INC_NAME)
all: check
# Do everything here to e.g. create the binaries for
# your plugin. This section should compile your component "myservice"
@echo "making the myservice-plugin"
install:
# Do everything here additional needed to install "myservice" in
# the OUT_DIR. No compilation should be done in this step
# Files in INSTALL_FILES will be installed automatically
@echo "installing myservice for Qrm"
clean: check
# Do everything here to clean-up the install-section
@echo "cleaning up myservice"
@/bin/rm -rf $(OUTDIR)/qrm/plugins/myservice
realclean: clean
@echo "making realclean for the myservice plugin"
@/bin/rm -rf $(QRM_CACHE_DIR)/myservice \
$(QRM_ROOT_DIR)/build/myservice
configure:
# You can use this section to pre-configure your plugin build
check:
@if [ -z $(QRM_CACHE_DIR) ]; then echo "ERROR: QRM_CACHE_DIR not set!"; exit 1; fi
@if [ -z $(QRM_ROOT_DIR) ]; then echo "ERROR: QRM_ROOT_DIR not set!"; exit 1; fi
This Makefile-skeleton should be self-explaining from the included comments.
Now let's create the directory structure for the "myservice" plugin.
Since plugins in openQRM should be separated from the base-server the concept
is that each plugin will "work" within its plugin directory and not put and/or
use files on system-level. Based on that a plugin should have a directory layout
similar to the system-director layout and manage their services within their own
directories. This mechanism makes it also easy to find plugin components e.g.
in our example the init-script for the "myservice-server" should be located at
../src/plugins/myservice/etc/init.d/.
For now we just create an etc/init.d and include dir :
cd myservice
mkdir -p etc/init.d include
Creating the plugin definition and function file
For giving openQRM some initial informations about the "myservice" plugin we create its definition in a xml-file at ../src/plugins/myservice/etc/myservice.xml :
<?xml version="1.0"?>
<plugin>
<properties>
<name>myservice</name>
<version>0.1</version>
<description>Provides the myservice-service</description>
<schema_version>1.0</schema_version>
</properties>
<config/>
</plugin>
For building and automatic packaging later we also need to create an info.xml file for the "myservice" plugin at ../src/plugins/myservice/include/myservice-info.xml with the following content :
<?xml version="1.0"?>
<package>
<module>
<name>myservice</name>
<version>0</version>
<type>plugin</type>
<release>1</release>
<license>Qlusters Public License Version 1.1</license>
<group>QRM/plugins</group>
<arch>i386</arch>
<summary>myservice plugin</summary>
<description>Provides myservice for openQRM</description>
</module>
</package>
To let openQRM know what to do when installing, uninstalling, starting and stopping the "myservice" plugin a functions file needs to be created at ../src/plugins/myservice/include/myservice-functions. It should look like :
#!/bin/bash
function myservice_install() {
echo "installing the myservice plugin"
# this function will run during installing the plugin
}
function myservice_uninstall() {
echo "uninstalling the myservice plugin"
# this function will run during uninstallation
}
function myservice_start() {
echo "starting the myservice plugin"
# this function will run immeadiatly after the openQRM-server is started
# to start the myservice plugin service
}
function myservice_stop() {
echo "stopping the myservice plugin"
# this function will run before the openQRM-server gets stopped
# to stop the myservice plugin service
}
function myservice_run_once() {
echo "running run_once for the myservice plugin"
# this function will run once after the plugins installation
# phase and can be used to e.g. register new components or
# apply any updates/changes to the configuration
}
Creating the init-scripts for "myservice"
For this howto we defined that "myservice" is based on a common client-server model.
That means we need to create one init-script for the "myservice-server" which will
be running on the openQRM-server and one "myservice-client" init-script for the
starting the client component on the systems managed by openQRM.
First let's create the "myservice-server" init-script ../src/plugins/myservice/etc/init.d/myservice-server as following :
#!/bin/bash
# init script for the myservice plugin managing myservice-server
QRM_SERVER_BASE_DIR=$(pushd $(dirname $0)/../../../../.. > /dev/null; echo $PWD; popd > /dev/null)
PLUGIN_BASE_DIR=$QRM_SERVER_BASE_DIR/qrm/plugins/myservice
LOCKFILE=$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/var/lock/subsys/myservice-server
mkdir -p $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/var/lock/subsys/
function start() {
echo "starting openQRM myservice plugin"
$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-serverd &
touch $LOCKFILE
}
function stop() {
echo "Stopping openQRM myservice plugin"
killall myservice-serverd 1>/dev/null 2>&1
rm -f $LOCKFILE
}
function status() {
if [ -s $LOCKFILE ]; then
echo "openQRM myservice-server is running"
else
echo "openQRM myservice-server is stopped"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
sleep 1
start
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
esac
exit $?
Then create the "myservice-client" init-script at ../src/plugins/myservice/etc/init.d/myservice-client as following :
#!/bin/bash
# openQRM init script for the myservice plugin managing myservice-client
#
# chkconfig: 345 97 18
# description: openQRM is the next generation Linux Data Center management. \
# Please see www.openQRM.org for more details.
export `eval cat /proc/cmdline`
. /var/qrm/conf/qrm.conf.$id
. $QRM_NODES_BASE_DIR/qrm/include/qrm-nodes-functions
LOCKFILE=$QRM_NODES_BASE_DIR/qrm/plugins/myservice/var/lock/subsys/myservice-client
mkdir -p $QRM_NODES_BASE_DIR/qrm/plugins/myservice/var/lock/subsys/
function start() {
echo "starting openQRM myservice plugin (myservice-client)"
$QRM_NODES_BASE_DIR/qrm/plugins/myservice/sbin/myservice-clientd &
touch $LOCKFILE
}
function stop() {
echo "Stopping openQRM myservice plugin (myservice-client)"
killall myservice-clientd 1>/dev/null 2>&1
rm -f $LOCKFILE
}
function status() {
if [ -s $LOCKFILE ]; then
echo "openQRM myservice-client is running"
else
echo "openQRM myservice-client is stopped"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
sleep 1
start
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
esac
exit $?
Test-building the "myservice" plugin
We created the initial skeleton of the "myservice" plugin and we have now the following files :
./etc/init.d/myservice-client
./etc/init.d/myservice-server
./etc/myservice.xml
./include/myservice-functions
./include/myservice-info.xml
./Makefile
We can now attempt to build it for testing. Here an example output of the build procedure :
[root@demo myservice]# make clean
# Do everything here to clean-up the install-section
cleaning up myservice
[root@demo myservice]# make
# Do everything here to e.g. create the binaries for
# your plugin. This section should compile your component "myservice"
making the myservice-plugin
[root@demo myservice]# make install
/usr/bin/install -D etc/myservice.xml ../../../out/qrm/plugins/myservice/etc/myservice.xml
/usr/bin/install -D -m 0700 etc/init.d/myservice-client ../../../out/qrm/plugins/myservice/etc/init.d/myservice-client
/usr/bin/install -D -m 0700 etc/init.d/myservice-server ../../../out/qrm/plugins/myservice/etc/init.d/myservice-server
/usr/bin/install -D include/myservice-functions ../../../out/qrm/plugins/myservice/include/myservice-functions
/usr/bin/install -D include/myservice-info.xml ../../../out/qrm/plugins/myservice/include/myservice-info.xml
touch ../../../out/qrm/plugins/myservice/include/.files_installed
# Do everything here additional needed to install "myservice" in
# the OUT_DIR. No compilation should be done in this step
# Files in INSTALL_FILES will be installed automatically
installing myservice for Qrm
[root@demo myservice]#
Completing the "myservice" plugin
We have now created the initial directory structure and files for the "myservice" plugin. Still we are missing the actual "myservice-server/client" daemons and for now almost all functions are still empty.
For this howto we will create very simply scripts for the "myservice-server" and
the "myservice-client". In a real integration those daemons/binaries will be created through the plugins compile procedure defined in the plugins Makefiles "all" section.
The "myservice-serverd" and "myservice-clientd" script should be located in the plugins sbin directory so let's create it by running :
mkdir -p sbin
Here the "myservice-serverd" script which should be saved at ../src/plugins/myservice/sbin/myservice-serverd :
#!/bin/bash
# this is a simple example server daemon for the "howto create an openQRM plugin" howto
echo "myservice-server started"
while (true); do
sleep 1000
done
And a "myservice-clientd" script which should be saved at ../src/plugins/myservice/sbin/myservice-clientd :
#!/bin/bash
# this is a simple example client daemon for the "howto create an openQRM plugin" howto
echo "myservice-client started"
while (true); do
sleep 1000
done
To automatically add those two new file to the plugins installation please add them to the INSTALL_FILES variable in the Makefile. It should now look like :
INSTALL_FILES := etc/myservice.xml, -m 0700 etc/init.d, include, -m 700 sbin
Connecting the "myservice-server" to openQRM
Starting the "myservice-server" daemon as an additional plugin service is easy. Just add its start (and stop) commands to the "myservice_start" and "myservice_stop" functions in ../src/plugins/myservice/include/myservice-functions. Those two functions should now look like :
function myservice_start() {
echo "starting the myservice plugin"
# this function will run immeadiatly after the openQRM-server is started
# to start the myservice plugin service
$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/etc/init.d/myservice-server start
}
function myservice_stop() {
echo "stopping the myservice plugin"
# this function will run before the openQRM-server gets stopped
# to stop the myservice plugin service
$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/etc/init.d/myservice-server stop
}
Connecting the "myservice-client" to the systems manged by openQRM
For the "myservice-client" which should be running automatically on the systems managed by openQRM we have to do some more work. An openQRM plugin extension callled "BootService" is used to make a system, associated with this boot-service, do the following steps during init :
download a specified boot-service package from the openQRM-server
(this is a zip file containing all required files to start the boot-service)
unpack the boot-service package
run a specified init-script
Let's first create the boot-service package for the "myservice" plugin.
For starting the "myservice-client" we basically just need the daemon file and its init-script. To pack them during the "make install" stage of the plugin build please update the Makefile's "install" section to look like :
install:
# Do everything here additional needed to install "myservice" in
# the OUT_DIR. No compilation should be done in this step
# Files in INSTALL_FILES will be installed automatically
@echo "installing myservice for Qrm"
mkdir -p $(OUTDIR)/qrm/plugins/myservice/client
tar -C $(OUTDIR)/qrm/ --exclude CVS --exclude Makefile -czf $(OUTDIR)/qrm/plugins/myservice/client/myservice-client.tgz plugins/myservice/etc/init.d/myservice-client plugins/myservice/sbin/myservice-clientd
Next we need to create the boot-service definition which is done via a simple xml configuration file. Please create ../src/plugins/myservice/etc/myservice-plugin.xml with the following content :
<?xml version="1.0"?>
<!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 0.2" "http://jpf.sourceforge.net/plugin_0_2.dtd">
<plugin id="com.qlusters.qrm.plugins.puppet-plugin" version="0.0.1" >
<requires>
<import plugin-id="com.qlusters.qrm.plugins.core"/>
</requires>
<extension plugin-id="com.qlusters.qrm.plugins.core" point-id="BootService" id="myservice">
<parameter id="name" value="myservice"/>
<parameter id="runlevel" value="35"/>
<parameter id="package" value="http://$QRM_SERVER_IP_ADDRESS/unsecure/myservice/myservice-client.tgz"/>
<parameter id="init" value="plugins/myservice/etc/init.d/myservice-client"/>
</extension>
</plugin>
This definition creates a new boot-service in openQRM named "myservice". All systems associated with this boot-service will download the myservice-client.tgz package, unpack it and run its init-script at init 3 or 5.
Please add this file to the INSTALL_FILES variable in the Makefile. INSTALL_FILES should now look like :
INSTALL_FILES := etc/myservice.xml, -m 0700 etc/init.d, include, -m 700 sbin, etc/myservice-plugin.xml
To make the myservice-client.tgz package available for download we copy it to a public section of the webserver. This step should happen during the installation of the plugin so the "myservice_install" and "myservice_uninstall" functions in ../src/plugins/myservice/include/myservice-functions should be updated as following :
function myservice_install() {
echo "installing the myservice plugin"
# this function will run during installing the plugin
mkdir -p $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice
/bin/cp -f $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/client/myservice-client.tgz $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice/
}
function myservice_uninstall() {
echo "uninstalling the myservice plugin"
# this function will run during uninstallation
/bin/rm -rf $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice
}
Last step for the boot-service setup is to associate it with the systems managed by openQRM. This step should happen once during installation so the "myservice_run_once" function (also in ../src/plugins/myservice/include/myservice-functions) should be used and updated as following :
function myservice_run_once() {
echo "running run_once for the myservice plugin"
# this function will run once after the plugins installation
# phase and can be used to e.g. register new components or
# apply any updates/changes to the configuration
# boot-services for images
$QRM_SERVER_BASE_DIR/qrm/bin/qrm-cli boot associate -k myservice -t image
}
Not to forget is that this boot-service should be removed during uninstallation of the "myservice" plugin. Please update again the "myservice_uninstall" function and add the line to disassociate the boot-service. It should look like :
function myservice_uninstall() {
echo "uninstalling the myservice plugin"
# this function will run during uninstallation
/bin/rm -rf $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice
$QRM_SERVER_BASE_DIR/qrm/bin/qrm-cli boot dissociate -k myservice -t image
}
Building and installing the "myservice" plugin
The "myservice" plugin is now ready to be build and installed. To build/rebuild it please run "make clean && make && make install" in the "myservice" plugin directory. Here an example output :
[root@demo myservice]# make clean && make && make install
# Do everything here to clean-up the install-section
cleaning up myservice
# Do everything here to e.g. create the binaries for
# your plugin. This section should compile your component "myservice"
making the myservice-plugin
/usr/bin/install -D etc/myservice.xml ../../../out/qrm/plugins/myservice/etc/myservice.xml
/usr/bin/install -D -m 0700 etc/init.d/myservice-client ../../../out/qrm/plugins/myservice/etc/init.d/myservice-client
/usr/bin/install -D -m 0700 etc/init.d/myservice-server ../../../out/qrm/plugins/myservice/etc/init.d/myservice-server
/usr/bin/install -D include/myservice-functions ../../../out/qrm/plugins/myservice/include/myservice-functions
/usr/bin/install -D -m 700 sbin/myservice-clientd ../../../out/qrm/plugins/myservice/sbin/myservice-clientd
/usr/bin/install -D -m 700 sbin/myservice-serverd ../../../out/qrm/plugins/myservice/sbin/myservice-serverd
/usr/bin/install -D etc/myservice-plugin.xml ../../../out/qrm/plugins/myservice/etc/myservice-plugin.xml
touch ../../../out/qrm/plugins/myservice/include/.files_installed
# Do everything here additional needed to install "myservice" in
# the OUT_DIR. No compilation should be done in this step
# Files in INSTALL_FILES will be installed automatically
installing myservice for Qrm
mkdir -p ../../../out/qrm/plugins/myservice/client
tar -C ../../../out/qrm/ --exclude CVS --exclude Makefile -czf ../../../out/qrm/plugins/myservice/client/myservice-client.tgz plugins/myservice/etc/init.d/myservice-client plugins/myservice/sbin/myservice-clientd
[root@demo myservice]#
This compile procedure now created the "installable" plugin at ../../../out/qrm/plugins/myservice.
To install the "myservice" plugin please copy the ../../../out/qrm/plugins/myservice directory into the plugins directory of your running openQRM-server and enable the "myservice" plugin via the qrm-installer :
[root@demo myservice]# /bin/cp -aR ../../../out/qrm/plugins/myservice /opt/qrm/plugins/
[root@demo myservice]# cd /opt/qrm
[root@demo qrm]# ./qrm-installer -i -m myservice
#####################################################
# #
# #
# Welcome to OpenQRM 3.1.4 #
# installation procedure #
# #
# by Qlusters Inc #
#####################################################
(logfile for the installation at /var/log/qrm/qrm-installer.log)
Components will be installed in following order:
1. myservice
Please notice
QRM will be installed with the following configuration :
General setup:
--------------
QRM server interface : eth0
QRM server base directory : /opt
QRM server log directory : /var/log/qrm
QRM nodes base directory : /opt
QRM nodes logs directory : syslog
QRM default kernel :
Database setup:
---------------
IP : localhost
name : qrm
port : 3306
socket : /var/lib/mysql/mysql.sock
username : root
password :
Component myservice Configuration
------------------------------------------
There is no configurable parameters for this component
Is the configuration correct? (y - continue, n - cancel , c - configure)? (y/n/c) [y]
==================================
Running components sanity checks
==================================
myservice........
[ OK ]
==================================
Running install stage for components
==================================
myservice..............
Installing myservice
installing the myservice plugin
[ OK ]
Do you want to restart QRM server? (y/n) [y]
Stopping the Qrm-server ------------/ [ OK ]
Starting the Qrm-server ---------/ [ OK ]
#################################################################
Installation finished
Components with status SUCCESS : myservice
#################################################################
[root@demo qrm]#
The "myservice" plugin is now installed and enabled on the openQRM-server.
To check the "myservice-server" plugin service came up correctly we check that the "myservice-serverd" is running by "ps" :
[root@demo ~]# ps -C myservice-serverd
PID TTY TIME CMD
10021 pts/2 00:00:00 myservice-serve
[root@demo ~]#
To check the "myservice-client" plugin service came up correctly we can quickly deploy a VE and check that the "myservice-clientd" is running on that system :
[root@fc4_test_small_nfs-1 ~]# ps -C myservice-clientd
PID TTY TIME CMD
1992 ? 00:00:00 myservice-clien
[root@fc4_test_small_nfs-1 ~]#
Building rpm-packages for the "myservice" plugin
The "myservice" plugin is now fully integrated into the openQRM build-system. To create rpm-packages for the "myservice" plugin you can simply run :
make clean PACKAGE_TYPE=rpm
make all PACKAGE_TYPE=rpm
make install PACKAGE_TYPE=rpm
make pack_rpm PACKAGE_TYPE=rpm
from the main source dir. This will create rpm-packages for the openQRM-base and all plugin available in the plugins source directory.
To create Debian (.deb) packages you can use the following make commands :
make clean PACKAGE_TYPE=deb
make all PACKAGE_TYPE=deb
make install PACKAGE_TYPE=deb
make pack_rpm PACKAGE_TYPE=deb
Summary (part 1)
We have now successfully integrated the example "myservice" client-server based service into openQRM via a custom plugin.
How to go on from here ?
We (the openQRM-Team) are working on further parts of this openQRM plugin-howto which will cover :
- working with custom Resource-, Image- and VE-parameter
- adding custom menu-items and web-pages
- interacting with the objects in the openQRM-server via java
- and more
Get the files used for part 1
You can download all files used in for this howto (part 1) packed in a .tgz at :
http://downloads.openqrm.net/contrib/plugin-howto/myservice-plugin-1.0.tgz
Web-page and menu integration (part 2)
Part 1 of this howto explained how to integrate a custom, client-server based
service into openQRM as a plugin. This, part 2, will give an overview and example
of the web-page and menu integration capabilities of the openQRM plugin API.
It will go into detail how to add a custom web-page and menu-entry to openQRM.
Adding a web-page to the plugin
To add a custom web-page we first create a web directory within the
sources of the "myservice" plugin :
cd ../src/plugins/myservice
mkdir -p web
Since we added a new directory we must also add it to the INSTALL_FILES variable
in the plugins Makefile. It should now look like :
INSTALL_FILES := etc/myservice.xml, -m 0700 etc/init.d, include, -m 700 sbin, etc/myservice-plugin.xml, web
Web-pages in openQRM are based on templates and tiles which can be populated
via iframes. The template sets up how the tiles are displayed and with which
content they are filled. For this example we create a template for the custom,
myservice web-page at ../src/plugins/myservice/web/myservice.jsp with the following content :
<%@ taglib uri='/WEB-INF/tld/struts-tiles-1.2.tld' prefix='tiles' %>
<tiles:insert page='/templates/qrm_template.jsp'>
<tiles:put name="title" value="MyService" />
<tiles:put name="onPageLoad" value="javascript:showAlerts();" />
<tiles:put name="calendar" value="" />
<tiles:put name='header' value='/action/header.do' />
<tiles:put name='sidebar' value='/action/sidebar.do' />
<tiles:put name='content' value='/unsecure/myservice/web/myservice_int.jsp'/>
<tiles:put name='footer' value='/include/footer.jsp'/>
</tiles:insert>
This template for the myservice web-page sets up all basic tiles and forwards the "content" tile
to a custom (jsp) web-page which we create in the next step by creating ../src/plugins/myservice/web/myservice_int.jsp
with the following content :
<% pageContext.setAttribute("myservice", "http://"+ request.getServerName() + ":8090"); %>
<iframe
scrolling="auto"
marginwidth="0"
marginheight="0"
frameborder="0"
vspace="0" hspace="0"
width="100%"
height="100%"
src="${myservice}">
</iframe>
This creates the iframe for the "content" tile filled with the server-output on port 8090 of the openQRM-server system.
We will care to create a simple service on this port for this example later in this howto.
To populate the web-directory of the plugin during its installation
please add a line in the ../src/plugins/myservice/include/myservice-functions
"myservice_install" function to copy the web content into the web-directory of
the tomcat server (the openQRM-server).
After your editing the myservice_install function should look like this :
function myservice_install() {
echo "installing the myservice plugin"
# this function will run during installing the plugin
mkdir -p $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice
/bin/cp -f $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/client/myservice-client.tgz $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice/
/bin/cp -aR $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/web $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice/
}
Creating a menu entry for the custom web-page
Now let's create the menu-entry for this custom web-page within the main openQRM-menu.
We just need to define it in the myservice plugins xml-configuration file at ../src/plugins/myservice/etc/myservice-plugin.xml
by adding a second MenuItem extension (next to our previous configured BootService extentsion). After editing the file should look like this :
<?xml version="1.0" ?>
<!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 0.2" "http://jpf.sourceforge.net/plugin_0_2.dtd">
<plugin id="com.qlusters.qrm.plugins.puppet-plugin" version="0.0.1" >
<requires>
<import plugin-id="com.qlusters.qrm.plugins.core"/>
</requires>
<extension plugin-id="com.qlusters.qrm.plugins.core" point-id="BootService" id="myservice">
<parameter id="name" value="myservice"/>
<parameter id="runlevel" value="35"/>
<parameter id="package" value="http://$QRM_SERVER_IP_ADDRESS/unsecure/myservice/myservice-client.tgz"/>
<parameter id="init" value="plugins/myservice/etc/init.d/myservice-client"/>
</extension>
<extension plugin-id="com.qlusters.qrm.plugins.core" point-id="MenuItem" id="MyService">
<parameter id="hierarchy" value="<strong>Management Tools</strong>" />
<parameter id="key" value="navigation"/>
<parameter id="title" value="MyService"/>
<parameter id="description" value="Myservice web-page"/>
<parameter id="url" value="/unsecure/myservice/web/myservice.jsp"/>
<parameter id="composite" value="false"/>
<parameter id="item-id" value="Myservice web-page"/>
</extension>
</plugin>
The second, new MenuItem extension adds a "MyService" menu entry under the Managetement Tools menu in openQRM
and points it to /unsecure/myservice/web/myservice.jsp, our custom web-page for this howto.
Adding a simple web-service to "myservice-serverd"
For this howto we enhance our example "myservice-serverd" daemon with a simple
web-service on port 8090 vi the "nc" utility (netcat). This is easy. Just replace the
line "sleep 1000" in the myservice-serverd script located the myservice plugins sbin directory
with a nc command. It should look like this :
#!/bin/bash
# this is a simple example server daemon for the "howto create an openQRM plugin" howto
echo "myservice-server started"
while (true); do
`dirname $0`/../../../sbin/nc -l -p 8090 -e `which uptime`
done
This is enough to report the uptime and load average of the system on port 8090.
Re-compiling and re-installing the "myservice" plugin
We are finished with the custom web-page integration and will now :
- uninstall the previous version of the myservice plugin
- re-compile the updated myservice plugin
- re-install the updated myservice plugin
First let's uninstall. Here the sample output of a developement systems :
[root@demo ~]# cd /opt/qrm
[root@demo qrm]# ./qrm-installer -u -m myservice
#####################################################
# #
# #
# Welcome to OpenQRM 3.1.4 #
# uninstall procedure #
# #
# by Qlusters Inc #
#####################################################
Uninstalling myservice
uninstalling the myservice plugin
Plugin myservice un-installed successfully.
[ OK ]
Do you want to restart QRM server ? (y/n) [n] y
Stopping the Qrm-server -------------/ [ OK ]
Starting the Qrm-server --------| [ OK ]
[root@demo qrm]#
Then we re-compile the updated myservice plugin in the source directory :
cd ../src/plugins/myservice/
make clean && make && make install
This compiles the myservice plugin to ../out/qrm/plugins/myservice.
We now need to update the myservice plugin directory on the installed
openQRM server with the content of the updated ../out/qrm/plugins/myservice directory.
rm -rf /opt/qrm/plugins/myservice
/bin/cp -aRv ../../../out/qrm/plugins/myservice/ /opt/qrm/plugins/
Now we just need to re-install the plugin via the qrm-installer.
Here again the output of one of the development servers :
[root@demo qrm]# ./qrm-installer -i -m myservice
#####################################################
# #
# #
# Welcome to OpenQRM 3.1.4 #
# installation procedure #
# #
# by Qlusters Inc #
#####################################################
(logfile for the installation at /var/log/qrm/qrm-installer.log)
Components will be installed in following order:
1. myservice
Please notice
QRM will be installed with the following configuration :
General setup:
--------------
QRM server interface : eth0
QRM server base directory : /opt
QRM server log directory : /var/log/qrm
QRM nodes base directory : /opt
QRM nodes logs directory : syslog
QRM default kernel :
Database setup:
---------------
IP : localhost
name : qrm
port : 3306
socket : /var/lib/mysql/mysql.sock
username : root
password :
Component myservice Configuration
------------------------------------------
There is no configurable parameters for this component
Is the configuration correct? (y - continue, n - cancel , c - configure)? (y/n/c) [y] y
==================================
Running components sanity checks
==================================
myservice........
[ OK ]
==================================
Running install stage for components
==================================
myservice..............
Installing myservice
installing the myservice plugin
[ OK ]
Do you want to restart QRM server? (y/n) [y] y
Stopping the Qrm-server ------------ [ OK ]
Starting the Qrm-server ---------\ [ OK ]
[root@demo qrm]#
#################################################################
Installation finished
Components with status SUCCESS : myservice
#################################################################
[root@demo qrm]#
Screenshot of the web-page and menu integration
Here a screenshot of the myservice plugin including the integrated web-page and menu entry :
Summary (part 2)
Part 2 of this howto explained how custom web-page can be integrated
within openQRM in an easy way using the plugin API and its extension points.
Similar to the myservice plugin used in this howto there are lots of possible
tools providing web-ouput of their results which can be easily combined and
even connected by integrating them within openQRM's single-management data-center console.
We (the openQRM-Team) will continue working on further parts of this howto to
cover details about mechanism to connect events from external tools (integrated
via a plugin) to openQRM-actions and how to interact with the internal objects
in the openQRM-server via java.
.. to be continued
Get the files used for part 2
You can download all files used in for this howto (part 2) packed in a .tgz at :
http://downloads.openqrm.net/contrib/plugin-howto/myservice-plugin-1.1.tgz
Listening and responding to events (part 3)
Part 3 of this HowTo will give an overview and example how to listen to events in openQRM and connect them to custom commands.
This mechanism is often used by plugins to execute custom commands on specific events.
Events in openQRM
In openQRM every action results in a specific event. Also error conditions are causing events within the openQRM-server.
The EventListener extension provided by the openQRM plugin API supports to hook custom
commands to every event happening in the openQRM-server. It also allows plugins to define their
own events.
As an example the Xen-plugin is using an EventListern listening for the "Resource.State.Operation.ShuttingSystem" and
"Resource.State.Role.Deassigning" event to check if it needs to re-write the systems pxe-configuration file.
Please find a list of the possible events in the openQRM-server at :
http://openqrm.cvs.sourceforge.net/openqrm/base/openqrm-3.1.4/src/base/java/main/resources/events.properties?revision=1.1&view=markup
This file can also be found on an installed openQRM-server at :
/opt/qrm/java/webapp/WEB-INF/classes/events.properties
Adding a custom event to openQRM via the "myservice" plugin
Plugins can add their own events to the openQRM-server in an easy way by simply
providing an "events.properties" file within the plugins /etc directory.
For the example "myservice" plugin we add a custom "MyService.Custom.Notice" event by creating
../src/plugins/myservice/etc/events.properties with the following content :
MyService.Custom.Notice$level=Event
MyService.Custom.Notice$message=Custom MyService event arrived.
Please do not forget to add this new file to the INSTALL_FILES variable in the
Makefile. The INSTALL_FILES in the Makefile should look like this :
INSTALL_FILES := etc/myservice.xml, -m 0700 etc/init.d, include, -m 700 sbin, etc/myservice-plugin.xml, etc/events.properties, web
Adding an EventListerner to the "myservice" plugin
Now we would like to listen for this "MyService.Custom.Notice" event.
We simply add an EventListern to the plugins xml-configuration file to defines
for which event to check and which command to run when the event happens.
Please edit ../src/plugins/myservice/etc/myservice-plugin.xml and add the following section :
<extension id="MyServiceCustomListener" plugin-id="com.qlusters.qrm.plugins.core" point-id="EventListener">
<parameter id="eventKey" value="MyService.Custom.Notice"/>
<parameter id="execution">
<parameter id="type" value="exec"/>
<parameter id="resource" value="path=$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-custom-cmd"/>
</parameter>
<parameter id="inTransaction" value="false"/>
</extension>
The whole ../src/plugins/myservice/etc/myservice-plugin.xml file should now look like this :
<?xml version="1.0" ?>
<!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 0.2" "http://jpf.sourceforge.net/plugin_0_2.dtd">
<plugin id="com.qlusters.qrm.plugins.puppet-plugin" version="0.0.1" >
<requires>
<import plugin-id="com.qlusters.qrm.plugins.core"/>
</requires>
<extension plugin-id="com.qlusters.qrm.plugins.core" point-id="BootService" id="myservice">
<parameter id="name" value="myservice"/>
<parameter id="runlevel" value="35"/>
<parameter id="package" value="http://$QRM_SERVER_IP_ADDRESS/unsecure/myservice/myservice-client.tgz"/>
<parameter id="init" value="plugins/myservice/etc/init.d/myservice-client"/>
</extension>
<extension plugin-id="com.qlusters.qrm.plugins.core" point-id="MenuItem" id="MyService">
<parameter id="hierarchy" value="<strong>Management Tools</strong>" />
<parameter id="key" value="navigation"/>
<parameter id="title" value="MyService"/>
<parameter id="description" value="Myservice web-page"/>
<parameter id="url" value="/unsecure/myservice/web/myservice.jsp"/>
<parameter id="composite" value="false"/>
<parameter id="item-id" value="Myservice web-page"/>
</extension>
<extension id="MyServiceCustomListener" plugin-id="com.qlusters.qrm.plugins.core" point-id="EventListener">
<parameter id="eventKey" value="MyService.Custom.Notice"/>
<parameter id="execution">
<parameter id="type" value="exec"/>
<parameter id="resource" value="path=$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-custom-cmd"/>
</parameter>
<parameter id="inTransaction" value="false"/>
</extension>
</plugin>
This defines to listen for the "MyService.Custom.Notice" (set in "eventkey") and then
run the command "$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-custom-cmd"
(set by "resource").
Creating the command-script connected to the EventListener
Now that we have created the EventListener we care about creating the custom command connected
to our custom event. Please create ../src/plugins/myservice/sbin/myservice-custom-cmd with the
following content :
#!/bin/bash
# this is a simple example custom command for the "howto create an openQRM plugin" howto
echo "MyService.Custom.Notice event happened in the openQRM-server"
Re-compiling and re-installing the "myservice" plugin
Please re-compile and re-install the "myservice" plugin in the same way
as after part 2
Calling the custom event via the qrm-cli
After re-compiling and re-installing the "myservice" plugin the new created
"MyService.Custom.Notice" event can be activated/called by adding it to the openQRM-servers
event-list via the qrm-cli.
Adding a "MyService.Custom.Notice" event as a global event :
./qrm-cli -u qrm -p qrm event add -g -k "MyService.Custom.Notice"
in /var/log/qrm/qrmlog :
...
2007-11-06 12:20:18,478 DEBUG [EventsManager] (http-443-Processor1:) Event: [49] Custom MyService event arrived. Entities are: QRM
2007-11-06 12:20:18,478 DEBUG [EventListenerManager] (http-443-Processor1:) Calling to fireEventCreated with event [id=49:creationTime=Tue Nov 06 12:20:18 CET 2007:levelInt=4:key=MyService.Custom.Notice:]:
2007-11-06 12:20:18,485 DEBUG [EventListenerManager] (http-443-Processor1:) Calling to afterCommit with event [id=49:creationTime=Tue Nov 06 12:20:18 CET 2007:levelInt=4:key=MyService.Custom.Notice:]:
2007-11-06 12:20:19,093 DEBUG [ExecutableDelegate] (http-443-Processor1:) Run of /opt/qrm/sbin/exec_wrapper.sh QRM_SESSION="0.20774404329788887" -- $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-custom-cmd returned:
Stdout:
MyService.Custom.Notice event happened in the openQRM-server
Stderr:
...
Adding a "MyService.Custom.Notice" event on behalf of a resource :
./qrm-cli -u qrm -p qrm event add --internal_cr_id 1 -k "MyService.Custom.Notice"
in /var/log/qrm/qrmlog :
...
2007-11-06 12:20:52,763 DEBUG [EventsManager] (http-443-Processor2:) Event: [50] Custom MyService event arrived. Entities are: Node 1
2007-11-06 12:20:52,763 DEBUG [EventListenerManager] (http-443-Processor2:) Calling to fireEventCreated with event [id=50:creationTime=Tue Nov 06 12:20:52 CET 2007:levelInt=4:key=MyService.Custom.Notice:]:
2007-11-06 12:20:52,771 DEBUG [EventListenerManager] (http-443-Processor2:) Calling to afterCommit with event [id=50:creationTime=Tue Nov 06 12:20:52 CET 2007:levelInt=4:key=MyService.Custom.Notice:]:
2007-11-06 12:20:53,492 DEBUG [ExecutableDelegate] (http-443-Processor2:) Run of /opt/qrm/sbin/exec_wrapper.sh QRM_SESSION="0.8713933908322177" -- $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-custom-cmd returned:
Stdout:
MyService.Custom.Notice event happened in the openQRM-server
Stderr:
...
Please notice that when the event was added to openQRM on behalf of a resource
it is possible to use additional commandline parameters for the custom script.
Those extra parameters are defined in the ../src/plugins/myservice/etc/myservice-plugin.xml
file and can be used by simply changing the parameter line :
<parameter id="resource" value="path=$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-custom-cmd"/>
to
<parameter id="resource" value="path=$QRM_SERVER_BASE_DIR/qrm/plugins/myservice/sbin/myservice-custom-cmd ${resource.id} ${resource.ipString}"/>
Then the myservice-custom-cmd will be executed with the resource ip and id as the first 2 commandline parameters.
Summary (part 3)
Part 3 of this howto explained how to listen to events in the openQRM-server, how to create custom events via a plugin
and how to connect specific events to custom commands by the example of a "MyService.Custom.Notice"
event connected to a plugin command (myservice-custom-cmd). This mechanism is especially useful for
the integration of third-party components because it makes it easy to map third-party-events
to openQRM-events which then can be handled automatically.
.. to be continued
Get the files used for part 3
You can download all files used in for this howto (part 3) packed in a .tgz at :
http://downloads.openqrm.net/contrib/plugin-howto/myservice-plugin-1.2.tgz
Using Java to communicate with internal openQRM-server objects (part 4)
Part 4 of this HowTo will give an overview and example how to interface directly
with the internal objects of the openQRM-server using the java-language. It desribes
how to add and integrate custom logic within openQRM using its well-defined plugin API.
In the example for this part 4 we will add a custom java class to the "myservice" plugin
which will act as a "id to ip" calculator. It will list all "idle" resources with internal
id and ip-address and execute a method from the custom java class. This example is useful for
integrating all kinds of client-server based components within openQRM.
Adding java code to the "myservice" plugin
Adding custom java classes to the openQRM-server engine is a simple task for a plugin.
For this HowTo we create a java class "MyServiceManager.java" at
../src/plugins/myservice/main/code/java/com/qlusters/qrm/plugins/myservice/MyServiceManager.java
with the following content :
package com.qlusters.qrm.plugins.myservice;
import java.util.*;
import java.io.*;
public class MyServiceManager {
public static String MyService(String ip) {
String ret;
ret = "Executing MyService on " + ip;
return ret;
}
}
A very simple java class with one method which accepts a string
as parameter and returns a string when being executed.
Of course this java class can use all internal objects provided by
the openQRM-server by importing their packages in the class definition.
For now we will keep it simple.
Adding maven build configuration
Now let's benefit from the automated build-system of openQRM. To compile the
java class created in the previous step please create the following 3 maven
configuration files in the "myservice" plugin base directory :
(some of those config files are quite long so we provide links for them below)
../src/plugins/myservice/maven.xml
../src/plugins/myservice/project.properties
../src/plugins/myservice/project.xml
After adding the maven configuration files we just need to add a few lines into
the "myservice" plugin Makefile. First we add a new target "make java" and then
we run this target during "make install". Here the updated section of the Makefile :
...
install:
# Do everything here additional needed to install "myservice" in
# the OUT_DIR. No compilation should be done in this step
# Files in INSTALL_FILES will be installed automatically
@echo "installing myservice for Qrm"
mkdir -p $(OUTDIR)/qrm/plugins/myservice/client
tar -C $(OUTDIR)/qrm/ --exclude CVS --exclude Makefile -czf $(OUTDIR)/qrm/plugins/myservice/client/myservice-client.tgz plugins/myservice/etc/init.d/myservice-client plugins/myservice/sbin/myservice-clientd
make java
java:
../../build/maven-helper.sh install -c $(QRM_CACHE_DIR)/java -t $(QRM_ROOT_DIR) -d $(INSTALL_FILES_DEST)/include -m myservice -w $(TOMCAT_DIR) -- $(MAVEN_OPTS)
....
The "make java" target will automatically build a myservice-plugin-1.0.jar to
../out/qrm/plugins/myservice/include/myservice-plugin-1.0.jar which then will be plug'ed into
the openQRM-server engine during the plugin installation.
One thing left to do is to add to the myservice_install/uninstall functions
in ../src/plugins/myservice/include/myservice-functions to link the myservice-plugin-1.0.jar
file to the openQRM-servers lib directory. The functions should now look like below :
function myservice_install() {
echo "installing the myservice plugin"
# this function will run during installing the plugin
mkdir -p $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice
/bin/cp -f $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/client/myservice-client.tgz $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice/
/bin/cp -aR $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/web $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice/
/bin/ln -sf $QRM_SERVER_BASE_DIR/qrm/plugins/myservice/include/myservice-plugin-1.0.jar ${QRM_SERVER_BASE_DIR}/qrm/java/webapp/WEB-INF/lib/myservice-plugin-1.0.jar
}
function myservice_uninstall() {
echo "uninstalling the myservice plugin"
# this function will run during uninstallation
/bin/rm -rf $QRM_SERVER_BASE_DIR/qrm/usr/tomcat/webapps/ROOT/unsecure/myservice
$QRM_SERVER_BASE_DIR/qrm/bin/qrm-cli boot dissociate -k myservice -t image
/bin/rm -f ${QRM_SERVER_BASE_DIR}/qrm/java/webapp/WEB-INF/lib/myservice-plugin-1.0.jar
}
The additional last line in the "myservice_install" function makes the custom jar file
available for the openQRM-server which will get access to the included classes and methods
after a restart (which is the default after the installation of addtional plugins).
In the "myservice_uninstall" function the symbolic link to the custom jar file simply
gets removed again during uninstallation of the plugin.
Interfacing with the openQRM-server objects
Basically there are two ways to inteface and communicate with the
internal objects in the openQRM-server :
- jsp (java server pages)
- pure java code
In section Adding java code to the "myservice" plugin we already
added some custom java code to the "myservice" plugin which gets plug'ed into openQRM
via a addtional jar file. To get access to the openQRM objects simply import their classes
into the plugins java source code and use them according their API.
To easily find out how the openQRM objects are working and how they can be used
we recommend to use Eclipse which has a nice built-in search functions for classes.
Of course your favourite editor and grep will do the same job.
Before going into more details let's see how to find informations about some
useful objects. In the following example we will create a "id to ip" calculator
which is using the "ComputeResourceData" object. This object represents a resource
in openQRM so it contains all informations about a managed system e.g. id, ip, mem, cpu, ...
In the sources of openQRM you find this class at :
/openqrm-3.1.4/src/base/java/main/code/com/qlusters/qrm/server/api/objects/ComputeResourceData.java
Please look into it a bit to find out how easy it is to e.g. get the systems ip-address
via the "getIpString()" method.
Now let's start with the "id to ip" calculator example.
Example: Creating a "id to ip" calculator
First we create a new webpage template at ../src/plugins/myservice/web/myservice-calculator.jsp
with the following content :
<%@ taglib uri='/WEB-INF/tld/struts-tiles-1.2.tld' prefix='tiles' %>
<tiles:insert page='/templates/qrm_template.jsp'>
<tiles:put name="title" value="MyService" />
<tiles:put name="onPageLoad" value="javascript:showAlerts();" />
<tiles:put name="calendar" value="" />
<tiles:put name='header' value='/action/header.do' />
<tiles:put name='sidebar' value='/action/sidebar.do' />
<tiles:put name='content' value='/unsecure/myservice/web/myservice-calculator_int.jsp'/>
<tiles:put name='footer' value='/include/footer.jsp'/>
</tiles:insert>
As described in the section Adding a web-page to the plugin webpages in
openQRM are based on tiles which get populated via Iframes. This template definition loads the
content of "/unsecure/myservice/web/myservice-calculator_int.jsp" in the main frame.
As the next step we create this content by creating ../src/plugins/myservice/web/myservice-calculator_int.jsp
as below :
<%@ taglib uri='/WEB-INF/tld/c-1.1.2.tld' prefix='c' %>
<%@include file="/include/metaData.inc"%>
<%@include file="/include/content.inc"%>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page import="com.qlusters.qrm.utils.StringUtils" %>
<%@ page import="com.qlusters.qrm.server.api.services.ApiServicesLocator" %>
<%@ page import="com.qlusters.qrm.server.api.objects.resources.*" %>
<%@ page import="com.qlusters.qrm.server.api.objects.*" %>
<%@ page import="com.qlusters.qrm.server.api.services.nodes.*" %>
<%@ page import="com.qlusters.qrm.server.api.objects.Paging" %>
<%@ page import="com.qlusters.qrm.server.api.objects.SortOrder" %>
<%@ page import="com.qlusters.qrm.server.api.objects.Sorter" %>
<%@ page import="com.qlusters.qrm.server.api.objects.filters.*" %>
<%@ page import="com.qlusters.qrm.plugins.myservice.*" %>
<html>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr class="h1Row">|
<h1>
<img src="/images/ind_resources.gif" align="middle"/>
Myservice Id2Ip Calculator
</h1>
</td>
</table>
<h2>Idle Resources
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr> |
<fieldset>
<legend>Resources
<table width="100%" border="2" cellspacing="0" cellpadding="1" class="dataTable">
<tr>
<%
ComputeResourceFilterData allfilter = new ComputeResourceFilterData();
allfilter.setIdle();
allfilter.setMaintenance(false);
Paging allpage = new Paging();
Sorter allsort = new Sorter("id", SortOrder.DESC);
List<ComputeResourceData> alldata = ApiServicesLocator.getInstance().getResourcesServices().getResources(allfilter, allpage, allsort);
ListIterator iter = alldata.listIterator();
while (iter.hasNext()) {
ComputeResourceData resource = (ComputeResourceData) iter.next();
out.println("<td>");
out.print("node " +resource.getExternalId());
out.println("</td><td>");
out.print(resource.getIpString());
out.println("</td>");
out.println("<td>");
%>
<%= (com.qlusters.qrm.plugins.myservice.MyServiceManager.MyService(resource.getIpString())) %>
<%
out.println("</td>");
}
%>
</tr>
</table>
</td></tr>
</table>
</body>
</html>
We will now go over each interesting step one by one.
1) Imports of the openQRM classes
<%@ taglib uri='/WEB-INF/tld/c-1.1.2.tld' prefix='c' %>
<%@include file="/include/metaData.inc"%>
<%@include file="/include/content.inc"%>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page import="com.qlusters.qrm.utils.StringUtils" %>
<%@ page import="com.qlusters.qrm.server.api.services.ApiServicesLocator" %>
<%@ page import="com.qlusters.qrm.server.api.objects.resources.*" %>
<%@ page import="com.qlusters.qrm.server.api.objects.*" %>
<%@ page import="com.qlusters.qrm.server.api.services.nodes.*" %>
<%@ page import="com.qlusters.qrm.server.api.objects.Paging" %>
<%@ page import="com.qlusters.qrm.server.api.objects.SortOrder" %>
<%@ page import="com.qlusters.qrm.server.api.objects.Sorter" %>
<%@ page import="com.qlusters.qrm.server.api.objects.filters.*" %>
<%@ page import="com.qlusters.qrm.plugins.myservice.*" %>
This section imports all needed openQRM classes for this example "id to ip" calculator.
It also imports the custom class "myservice" we created at Adding java code to the "myservice" plugin.
After importing those classes all included objects and methods are available within
the jsp web-page.
2) Using a filter for listing resources
After some pure html we find :
ComputeResourceFilterData allfilter = new ComputeResourceFilterData();
allfilter.setIdle();
allfilter.setMaintenance(false);
This creates a new ComputeResourceFilterData object named allfilter which is
then being set to filter only "idle" resources which are not in "maintainance mode".
3) Applying the sort order
Then a new page order is being created by the following lines :
Paging allpage = new Paging();
Sorter allsort = new Sorter("id", SortOrder.DESC);
It defines the order DESC by the objects "id".
4) Get a list of resource objects
The following line creates a list of ComputeResourceData objects using the
previously created filter and paging order :
List<ComputeResourceData> alldata = ApiServicesLocator.getInstance().getResourcesServices().getResources(allfilter, allpage, allsort);
So we now have a list of all "idle" resources which are not in maintainance, ordered DESC by their
"id" in the "alldata" object.
5) Iterating over the results
Now we simply create a new ListIterator object starting at the beginning of our
"alldata" object to iterate over the results and fetch some data per resource.
ListIterator iter = alldata.listIterator();
while (iter.hasNext()) {
ComputeResourceData resource = (ComputeResourceData) iter.next();
....
For each entry in the "alldata" list of our resources a new ComputeResourceData object
is being derived which then contains all informations for a resource in openQRM.
6) Fetching the results
To fetch information from the ComputeResourceData object we now can use its "get" methods :
..
out.print("node " +resource.getExternalId());
..
out.print(resource.getIpString());
..
7) Calling custom method from the plugins java class
The following line calls our method "MyService(String ip)" from the custom java class
we created for the "myservice" plugin at Adding java code to the "myservice" plugin
for each resource in the list.
<%= (com.qlusters.qrm.plugins.myservice.MyServiceManager.MyService(resource.getIpString())) %>
The rest is pure html.
Adding the menu item for the "id to ip" calculator
One thing left to do to complete our "id to ip" calculator example is to add a
menu entry for the calculator web-page as described at Creating a menu entry for the custom web-page.
Please add the following section to the "myservice" plugin xml-definition at ../src/plugins/myservice/etc/myservice-plugin.xml :
<extension plugin-id="com.qlusters.qrm.plugins.core" point-id="MenuItem" id="MyServiceCalc">
<parameter id="hierarchy" value="<strong>Management Tools</strong>" />
<parameter id="key" value="navigation"/>
<parameter id="title" value="MyServiceCalc"/>
<parameter id="description" value="Myservice Calculator"/>
<parameter id="url" value="/unsecure/myservice/web/myservice-calculator.jsp"/>
<parameter id="composite" value="false"/>
<parameter id="item-id" value="Myservice Calculator"/>
</extension>
Ready to re-compile and re-install it.
Re-compiling and re-installing the "myservice" plugin
Please re-compile and re-install the "myservice" plugin in the same way
as after part 2
Screenshot of the "id to ip" calculator
Summary (part 4)
This part 4 of the openQRM plugin HowTo explained how to integrate custom logic into openQRM and
how to interface with the internal server objects via the java language. It also gave an overview
of how to access the API of the openQRM-server, where to find the class definitions and how to use
those objects based on a simple "id to ip" calculator.
We hope it will encourage even more people (especially java developers) to look into openQRM's
pluggable architecture and to contribute by developing additional useful plugins for openQRM. Enjoy !
Get the files used for part 4
You can download all files used in for this howto (part 4) packed in a .tgz at :
http://downloads.openqrm.net/contrib/plugin-howto/myservice-plugin-1.3.tgz
or you can directly check them out from the openQRM cvs at sourceforge.net by :
cvs -d:pserver:anonymous@openqrm.cvs.sourceforge.net:/cvsroot/openqrm login
# (just press ENTER when it asks for a password)
cvs -z3 -d:pserver:anonymous@openqrm.cvs.sourceforge.net:/cvsroot/openqrm co -P plugins/myservice
Urls
openQRM website - http://www.openqrm.org/
openQRM project - http://sourceforge.net/projects/openqrm
Qlusters - http://qlusters.com/
Revision History
1.0 22.10.2007 - initial release (part 1)
1.1 30.10.2007 - added part 2 about web-page and menu integration
1.1 06.11.2007 - added part 3 about listening to events
1.2 20.11.2007 - added part 4 about interfacing with the internal openQRM-server objects via java
|