Overview:

This page describes the method used to add Service Management Facility (SMF) capabilities to CSW packages for a single instance of a service.

Components:

1) prototype - includes sections for legacy scripts and SMF files.  The section for legacy scripts is assigned to class smfno.  The section for SMF files is assigned to class smfyes.

2) pkginfo - not changed.  It still uses CLASSES=none by default.

3) checkinstall - this script is added to choose either class smfyes or smfno, depending on the availability of SMF binaries, and adds that class to the package installation.

4) class install files for class not equal none - Every class that is not a value of 'none' needs a script to install the files for that class.  The script name must be i.<class>.  For example, there is a i.smfyes and i.smfno script.

5) postinstall - Set variable smf to no for a default. If the SMF binaries are available, set variable smf to yes. For SMF installations, configure the service. For packages that start the service in postinstall: enable the service when variable smf is yes or run the rc script when variable smf is no. Note that the command used with chroot needs the full pathname.

6) space - This is not really required, but it does suppress a warning on package build.  The space file is used to inform the system of additional space required for files added manually.  Since the prototype contains both classes, the net effect on space is that it is actually reduced.  I have not done anything with this file, except to provide a blank file.

7) service manifest - This defines the service to SMF.  Study your dependency requirements carefully.  I also use the Solaris service manifests for samples. 

8) service method file - This is the script used by SMF to control the service.  It can be the same as the older rc script with the addition of line(s) to include some SMF functions.

9) preremove - Handles stopping the service for both smfyes and smfno and unregisters the service from SMF for smfyes.

Sample Code:

NOTE: Package pathnames in these examples are absolute pathnames.  $BASEDIR needs to be added for relocatable packages.

1) prototype - Here is a sample from CSWmsyql5.  Some entries are removed since they do not pertain to this discussion.  The entries that are needed are the type i entries and the entries for class smfno and class smfyes.  Permissions on the smf directories and files are the same as similar objects in the Solaris installation.
i pkginfo
i copyright
i depend
i checkinstall
i preremove
i postinstall
i i.smfno
i i.smfyes
i space
... (mysql specific files are here)
f smfno /etc/init.d/cswmysql5=cswmysql5 0755 root bin
l smfno /etc/rc0.d/K15cswmysql5=/etc/init.d/cswmysql5
l smfno /etc/rc1.d/K15cswmysql5=/etc/init.d/cswmysql5
l smfno /etc/rc2.d/K15cswmysql5=/etc/init.d/cswmysql5
l smfno /etc/rc3.d/S40cswmysql5=/etc/init.d/cswmysql5
l smfno /etc/rcS.d/K15cswmysql5=/etc/init.d/cswmysql5
d smfyes /opt/csw/var/svc 0755 root bin
d smfyes /opt/csw/var/svc/manifest 0755 root bin
d smfyes /opt/csw/var/svc/manifest/network 0755 root bin
f smfyes /opt/csw/var/svc/manifest/network/mysql5.xml=/mysql5.xml 0644 root bin
d smfyes /opt/csw/lib/svc 0755 root bin
d smfyes /opt/csw/lib/svc/method 0755 root bin
f smfyes /opt/csw/lib/svc/method/svc-mysql5=svc-mysql5 0755 root bin
2) pkginfo - Unchanged.  The default is to install class <none>.  The checkinstall script adds either the smfyes or smfno class.

3) checkinstall sample:  Adds the appropriate class to the CLASSES environment variable.
# mysql5 - checkinstall script
#
trap `exit 3` 15

# Assign Solaris release class to install release specific files
smf=no
if [ -f /usr/sbin/svccfg -a -f /usr/sbin/svcadm ] ; then smf=yes ; fi
if [ $smf = yes ]
then
        CLASSES='none smfyes'
else
        CLASSES='none smfno'
fi

# Make env variables available to other packaging scripts

cat >$1 <<!
CLASSES='$CLASSES'
!

exit 0

4) class install files:
For i.smfyes:
# mysql5 - i.smfyes script
#
# Copy the SMF specific files to the base directory.
# The files specific to SMF are:
# /opt/csw/var/svc
# /opt/csw/var/svc/manifest
# /opt/csw/var/svc/manifest/network
# /opt/csw/var/svc/manifest/network/mysql5.xml=/mysql5.xml
# /opt/csw/lib/svc
# /opt/csw/lib/svc/method
# /opt/csw/lib/svc/method/svc-mysql5
#
echo "Installing class <smfyes>."
while read src dest
do
        # Do copy
        /usr/bin/cp $src $dest || exit 2
        echo $dest
done
exit 0
For i.smfno:
# mysql5 - i.smfno script
#
# Copy the non-SMF specific files to the base directory.
# The files to copy are:
# /etc/init.d/cswmysql5=cswmysql5
# /etc/rc0.d/K15cswmysql5=/etc/init.d/cswmysql5
# /etc/rc1.d/K15cswmysql5=/etc/init.d/cswmysql5
# /etc/rc2.d/K15cswmysql5=/etc/init.d/cswmysql5
# /etc/rc3.d/S40cswmysql5=/etc/init.d/cswmysql5
# /etc/rcS.d/K15cswmysql5=/etc/init.d/cswmysql5
#
echo "Installing class <smfno>."
while read src dest
do
        # Do copy
        /usr/bin/cp $src $dest || exit 2
        echo $dest
done
exit 0
5) postinstall sample - Set a variable named smf to either yes or no, depending on whether or not SMF binaries are available.
# mysql5 - postinstall script
# 2006-01-02 Add SMF capability
#
2007-08-18 Fix PKG_INSTALL_ROOT usage.  Remove PKG_INSTALL_DIR.
#
# daemons are started by default
enable_daemon=yes

# Source csw.conf, if it exists
if [ -f $PKG_INSTALL_ROOT/opt/csw/etc/csw.conf ] ; then
  . $PKG_INSTALL_ROOT/opt/csw/etc/csw.conf
fi
if [ -f $PKG_INSTALL_ROOT/etc/opt/csw/csw.conf ] ; then
  . $PKG_INSTALL_ROOT/etc/opt/csw/csw.conf
fi

# If defined, autoenable for the specific daemon name takes precedence
if [ "$autoenable_mysql5" = "no" ] ; then
  enable_daemon=no
elif [ "$autoenable_daemons" = "no" -a ! -n "$autoenable_mysql5" ] ; then
  enable_daemon=no
fi

# Set variable smf depending on the availability of SMF binaries
smf=no
if [ -f /usr/sbin/svccfg -a -f /usr/sbin/svcadm ]
  then
  smf=yes
fi

#

... (mysql specific lines removed)

# If needed, configure SMF
if [ $smf = yes ]
then
  # Register with SMF
  echo "Configuring service in SMF"
  /usr/sbin/svccfg import /opt/csw/var/svc/manifest/network/mysql5.xml >/dev/null 2>&1
  /usr/sbin/svcadm disable svc:/network/cswmysql5 >/dev/null 2>&1
  echo "MySQL 5 is using Service Management Facility.  The FMRI is:"
  echo "  svc:/network/cswmysql5:default"
fi

# If enabled, start the daemon
if [ "$enable_daemon" = "yes" ] ; then
  echo "Starting mysql5"
  if [ $smf = no ]
  then
    /etc/init.d/cswmysql5 start
  else
    /usr/sbin/svcadm enable svc:/network/cswmysql5
  fi
fi

exit 0
6) space - sample

# No additional space is actually needed.
# In fact, only one set of the Solaris release specific files are installed.
# So the space required for this package is less than what is in pkgmap.

7) service manifest - For me, this is the biggest reason for using SMF.  Define your dependencies as needed.  I do not know any more about this subject than what I see in the Solaris service manifests and the sample on BigAdmin for mysql.  Note that the '<service name=' section defines the FMRI.  Please name the service with the service type plus '/csw' plus the application name. For example, the mysql5 daemon is given a service name of network/cswmysql5. 
<?xml version='1.0'?>
 <!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<!--
William Pool (Puddle) 02/05
Service manifest for MySQL
E-mail:
Modified for CSWmysql5 by Alex Moore 01/06
 -->

 <service_bundle type='manifest' name='mysql:mysql'>

  <service
 name='network/cswmysql5'
     type='service'
 version='1'>
 <create_default_instance enabled='false' />
 <single_instance />

<dependency name='fs'
grouping='require_all'
restart_on='none'
type='service'>
<service_fmri value='svc:/system/filesystem/local' />
</dependency>

<dependency name='net'
grouping='require_all'
restart_on='none'
type='service'>
<service_fmri value='svc:/network/loopback' />
</dependency>

<exec_method
type='method'
name='start'
exec='/opt/csw/lib/svc/method/svc-mysql5 start'
timeout_seconds='-1'>
<method_context>
<method_credential user='mysql' group='mysql' />
</method_context>
</exec_method>

<exec_method
type='method'
name='stop'
exec=':kill'
timeout_seconds='-1'>
</exec_method>

<exec_method
type='method'
name='restart'
exec='/opt/csw/lib/svc/method/svc-mysql5 restart'
timeout_seconds='-1'>
</exec_method>

  </service>

 </service_bundle>
8) service method file sample - The line `. /lib/svc/share/smf_include.sh' is all that is different from the previous version of the cswmysql5 rc script.  This line is not a requirement; but it does have some useful functions and defines.  This line is located near the top of the script.  See /lib/svc/share/README for details on include scripts for SMF.  The following text is the beginning of the rc script file, which is all that is important for the topic.  The added line is bold.
   #!/usr/bin/sh
#
# William Pool (Puddle) 01/05
# SMF Method file for MySQL
# E-mail:
# Modified for CSWmysql5 by Alex Moore 01/06
#
# This uses the CSW MySQL packages
# CSWmysql5 CSWmysql5client CSWmysql5rt
#
# NOTE: Make sure DB_DIR is owned BY the mysql user and group and chmod
# 700.
#
# Startup options may be overriden by creating and editing either
# /opt/csw/mysql5/etc/mysql5rc or /etc/opt/csw/mysql5rc. The template
# for mysql5rc is in /opt/csw/mysql5/share/mysql. You must use
# this template.
#
# For example,
# mkdir -p /etc/opt/csw
# cp /opt/csw/mysql5/share/mysql/mysql5rc /etc/opt/csw/
#
# If no mysql5rc file is available, the daemon starts with defaults.
#

. /lib/svc/share/smf_include.sh

#
# ... the rest of the original rc file continues ...
9) preremove sample - See man svcadm (1M) and man svccfg (1M).  I had to use the -s option for 'svcadm disable' to allow the service to completely stop before running 'svccfg delete'.  Otherwise, svccfg would not delete the service definition.
   # mysql5 - preremove script
#

# If removing from a filesystem that is not running the OS, exit this script.
if [ ! x"$PKG_INSTALL_ROOT" = x"" ] ; then exit 0 ; fi

# Stop mysqld if it is running.
# If removing from a non-global zone, the service may still be
# installed/running. Errors are ignored if nothing is done.
 smf=no
if [ -f /usr/sbin/svccfg -a -f /usr/sbin/svcadm ] ;
then smf=yes ; fi

if [ $smf = yes ]
then
# Disable service
/usr/sbin/svcadm disable -s svc:network/cswmysql5:default >/dev/null 2>&1
else
/etc/init.d/cswmysql5 stop >/dev/null 2>&1
fi

if [ $smf = yes ] ; then
# Unregister with SMF
/usr/sbin/svccfg delete svc:network/cswmysql5:default >/dev/null 2>&1
fi

exit 0
Enjoy,

Alex Moore

Updated: 2007-12-03