December 08, 2006

Solaris SMF manifest for a multi–instance jboss service

Today I have mostly been writing SMF manifests. We typically run several JBoss instances per physical server (or zone), using the JBoss service binding framework to take care of port allocations. I couldn’t find a decent SMF manifest that would be safe to use in a context where you’ve got lots of JBosses running, so I wrote my own. Here it is…

It’s still a tad rough around the edges.
  • It assumes you’ll name your SMF instances the same as your JBoss server instances
  • The RMI port for shutdowns is specified as a per-instance property – in theory one could parse it out of the service bindings file, but doing that robustly is just too much like hard work at the moment.
  • It assumes that you’ll want to run the service as a user called jboss, whose primary group is webservd – adjust to suit.
  • The jvm_opts instance property allows you to pass specific options (for example, heap size) into the JVM
  • It assumes that you’ll have a log directory per instance, located in /var/jboss/log/{instance name}-{rmi port}. The PID file is stored there, and the temp. file dir is set to there too (using /tmp for temporary files is a bad idea if you hoover your temp dir periodically, as you’ll delete useful stuff)
  • The stop method waits for the java process to terminate (otherwise restart won’t work. The start method doesn’t wait for the server to be ready and to have opened it’s HTTP listener, just for the VM to be created. I might add that next, although given that svcadm invocations are asynchronous there doesn’t seem much point.

The manifest itself:

<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='export'>
  <service name='application/jboss' type='service' version='0'>
    <instance name='default' enabled='true'>
      <dependency name='network' grouping='require_all' restart_on='error' type='service'>
        <service_fmri value='svc:/milestone/network:default'/>
      </dependency>
      <dependency name='sysconfig' grouping='require_all' restart_on='error' type='service'>
        <service_fmri value='svc:/milestone/sysconfig:default'/>
      </dependency>
      <dependency name='fs-local' grouping='require_all' restart_on='error' type='service'>
        <service_fmri value='svc:/system/filesystem/local:default'/>
      </dependency>
      <exec_method name='start' type='method' exec='/usr/local/jboss/bin/svc-jboss start' timeout_seconds='180'>
        <method_context>
            <method_credential user='jboss' group='webservd' />
        </method_context>
      </exec_method>
      <exec_method name='stop' type='method' exec='/usr/local/jboss/bin/svc-jboss stop' timeout_seconds='180'>
        <method_context/>
      </exec_method>
      <property_group name='jboss' type='application'>
        <propval name='instance-rmi-port' type='astring' value='1099'/>
        <propval name='jvm-opts' type='astring' value='-server -Xmx1G -Xms1G'/>
      </property_group>
    </instance>
    <stability value='Evolving'/>
    <template>
      <common_name>
        <loctext xml:lang='C'>JBoss J2EE application server</loctext>
      </common_name>
    </template>
  </service>
</service_bundle>

... and the service method

#!/usr/bin/sh
#

. /lib/svc/share/smf_include.sh

# General config
#
JAVA_HOME=/usr/java/
JBOSS_HOME=/usr/local/jboss
JBOSS_CONSOLE=/dev/null

# instance-specific stuff:
# sed the instance name out of the FMRI
JBOSS_SERVICE=`echo $SMF_FMRI | sed 's/.*:\(.*\)/\1/'`
JBOSS_SERVICE_RMI_PORT=`svcprop -p jboss/instance-rmi-port $SMF_FMRI`
SERVICE_JVM_OPTS=`svcprop -p jboss/jvm-opts $SMF_FMRI`

# Derived stuff
#
JBOSS_VAR=/var/jboss/jboss-3.2.7/${JBOSS_SERVICE}-${JBOSS_SERVICE_RMI_PORT}
PIDFILE=${JBOSS_VAR}/JBOSS_${JBOSS_SERVICE}.PID
JAVA=${JAVA_HOME}/bin/java
JAVA_OPTS="-Djava.io.tmpdir=${JBOSS_VAR} -Djava.awt.headless=true" 

if [ -z "$SMF_FMRI" ]; then
        echo "JBOSS startup script must be run via the SMF framework" 
        exit $SMF_EXIT_ERR_NOSMF
fi

if [ -z "$JBOSS_SERVICE" ]; then
        echo "Unable to parse service name from SMF FRMI $SMF_FRMI" 
        exit $SMF_EXIT_ERR_NOSMF
fi

jboss_start(){
        echo "starting jboss.." 
        JBOSS_CLASSPATH=${JBOSS_HOME}/bin/run.jar:${JAVA_HOME}/lib/tools.jar
        if [ ! -z "$SERVICE_JVM_OPTS" ]; then
           JAVA_OPTS="${JAVA_OPTS} ${SERVICE_JVM_OPTS}" 
        fi

        $JAVA -classpath $JBOSS_CLASSPATH $JAVA_OPTS $SERVICE_JVM_OPTS org.jboss.Main -c ${JBOSS_SERVICE} >$JBOSS_CONSOLE 2>&1 & echo $! >${PIDFILE}
}

jboss_stop(){
        echo "stopping jboss.." 
        stop_service="--server=localhost:${JBOSS_SERVICE_RMI_PORT}" 
        JBOSS_CLASSPATH=${JBOSS_HOME}/bin/shutdown.jar:${JBOSS_HOME}/client/jnet.jar
        $JAVA -classpath $JBOSS_CLASSPATH org.jboss.Shutdown $stop_service
        PID=`cat ${PIDFILE}`
        echo "waiting for termination of process $PID ..." 
        pwait $PID
        rm $PIDFILE
}

case $1 in
'start')
        jboss_start
        ;;

'stop')
        jboss_stop
;;

'restart')
        echo "Restarting jboss" 
        jboss_stop
        jboss_start
        ;;

*)
        echo "Usage: $0 { start | stop | restart }" 
        exit 1
        ;;
esac

        

enjoy!

postscript I wrote above that parsing the service-bindings file to find the RMI port is too hard; this turns out not to be true. Praise be to Blastwave!

pkg-get install xmlstarlet

xml sel -t -v "/service-bindings/server[@name='${INSTANCE_NAME}']/service-config[@name='jboss:service=Naming']/binding/@port" service-bindings.xml 

- No comments Not publicly viewable


Add a comment

You are not allowed to comment on this entry as it has restricted commenting permissions.

Most recent entries

Loading…

Search this blog

on twitter...


    Tags

    Not signed in
    Sign in

    Powered by BlogBuilder
    © MMXXI