UKOUG Technology Conference

Friday, May 30, 2008

Solaris SMF manifest for mimedefang

I have been using MIMEDefang for some time and I thought I would write a Solaris SMF manifest so it would fit with the new Solaris 10 services.

I started off looking at a collection of existing manifest files from smtp-sendmail.xml to ssh.xml and a few online pages. So to convert your existing installation to use SMF do:

[updated 3rd July 2008 : init-script.in]

1) Rename the old startup files (you can delete them at a later date):
# ls /etc/rc?.d/*mimedefang
/etc/rc0.d/K38mimedefang /etc/rc1.d/K38mimedefang /etc/rc2.d/S82mimedefang /etc/rcS.d/K38mimedefang
# mv /etc/rc0.d/K38mimedefang etc/rc0.d/_K38mimedefang
# mv /etc/rc1.d/K38mimedefang etc/rc1.d/_K38mimedefang
# mv /etc/rc2.d/S82mimedefang etc/rc2.d/_S82mimedefang
# mv /etc/rcS.d/K38mimedefang etc/rc1.d/_S38mimedefang

2) Copy the startup file to a different location. You could put it in /lib/svc/method where all the Solaris ones are located, but I decided to keep it with the other mimedefang software (if you do change the location make sure you update the manifest file correctly):
# cp /etc/init.d/mimedefang /usr/local/mimedefang/bin/init-mimedefang

3) You can use your existing startup file and it will work with this manifest, but if you want to make full use of the manifest, then use this new version.

4) The download version is a replacement for the "examples/init-script.in" found in the source code directory, so you will need to to be put it in place before you build mimedefang (init-script is built when you run configure) and then copy init-script to in new location.
# cp  examples/init-script   /usr/local/mimedefang/bin/init-mimedefang
Changes are:
- Altered it to get rid of some none Solaris options.
- Altered the stop_it routines so it does a better job (better use of kill and more checking), which means that mimedefang will auto restart if it dies.
- Altered so it makes use of the properties of the service.
# diff -u init-script.orig init-script.in
--- init-script.orig    Thu Oct 18 17:46:05 2007
+++ init-script.in    Thu Jul 3 12:19:29 2008
@@ -1,15 +1,22 @@
#!/bin/sh
#
-# FreeBSD/NetBSD start/stop script for MIMEDefang.
+# Solaris 10 start/stop script for MIMEDefang.
#
# PROVIDE: mimedefang
# REQUIRE: LOGIN
# BEFORE: mail
# KEYWORD: shutdown
+Modified 3rd July 2008
+    - added extra test in stop_it so mimedefang restarts after a "pkill -u defang"

-RETVAL=0
+. /lib/svc/share/smf_include.sh
+
+RETVAL=$SMF_EXIT_OK
prog='mimedefang'
-SPOOLDIR='@SPOOLDIR@'
+
+# Obtain SPOOLDIR (default=/var/spool/MIMEDefang)
+SPOOLDIR=`/usr/bin/svcprop -p config/spooldir $SMF_FMRI`
+SPOOLDIR=${SPOOLDIR:-'@SPOOLDIR@'}
PID="$SPOOLDIR/$prog.pid"
MXPID="$SPOOLDIR/$prog-multiplexor.pid"

@@ -40,7 +47,8 @@
# SOCKET=$SPOOLDIR/mimedefang.sock

# Run the multiplexor and filters as this user, not root. RECOMMENDED
-MX_USER=@DEFANGUSER@
+MX_USER=`/usr/bin/svcprop -p config/mx_user $SMF_FMRI`
+MX_USER=${MX_USER:-'@DEFANGUSER@'}

# Syslog facility
# SYSLOG_FACILITY=mail
@@ -51,6 +59,8 @@

# "yes" turns on the multiplexor relay checking function
# MX_RELAY_CHECK=no
+MX_RELAY_CHECK=`/usr/bin/svcprop -p config/mx_relay_check $SMF_FMRI`
+MX_RELAY_CHECK=${MX_RELAY_CHECK:-'no'}

# "yes" turns on the multiplexor HELO checking function
# MX_HELO_CHECK=no
@@ -57,9 +67,13 @@

# "yes" turns on the multiplexor sender checking function
# MX_SENDER_CHECK=no
+MX_SENDER_CHECK=`/usr/bin/svcprop -p config/mx_sender_check $SMF_FMRI`
+MX_SENDER_CHECK=${MX_SENDER_CHECK:-'no'}

# "yes" turns on the multiplexor recipient checking function
# MX_RECIPIENT_CHECK=no
+MX_RECIPIENT_CHECK=`/usr/bin/svcprop -p config/mx_recipient_check $SMF_FMRI`
+MX_RECIPIENT_CHECK=${MX_RECIPIENT_CHECK:-'no'}

# Set to yes if you want the multiplexor to log events to syslog
MX_LOG=yes
@@ -112,7 +126,8 @@

# Minimum number of processes to keep. The default of 0 is probably
# too low; we suggest 2 instead.
-MX_MINIMUM=2
+MX_MINIMUM=`/usr/bin/svcprop -p config/mx_minimum $SMF_FMRI`
+MX_MINIMUM=${MX_MINIMUM:-'2'}

# Maximum number of processes to run (mail received while this many
# processes are running is rejected with a temporary failure, so be
@@ -119,7 +134,8 @@
# wary of how many emails you receive at a time). This applies only
# if you DO use the multiplexor. The default value of 2 is probably
# too low; we suggest 10 instead
-MX_MAXIMUM=10
+MX_MAXIMUM=`/usr/bin/svcprop -p config/mx_maximum $SMF_FMRI`
+MX_MAXIMUM=${MX_MAXIMUM:-'10'}

# Uncomment to log slave status; it will be logged every
# MX_LOG_SLAVE_STATUS_INTERVAL seconds
@@ -173,29 +189,6 @@
     . @CONFDIR_EVAL@/$prog.conf
fi

-# BSD specific setup
-if [ -f /etc/rc.subr ]
-then
-    . /etc/rc.subr
-
-    name=$prog
-    rcvar=`set_rcvar`
-    # default to not enabled, enable in rc.conf
-    eval $rcvar=\${$rcvar:-NO}
-
-    load_rc_config $name
-
-    pidfile=$MXPID
-    procname=$PROGDIR/$prog-multiplexor
-    start_cmd="start_it"
-    stop_cmd="stop_it"
-    sig_reload="INT"
-    reread_cmd="reread_it"
-    # provide both "reload", the FreeBSD default, with a direct signal to
-    # the multiplexor, and "reread", the MIMEDefang default, using md-mx-ctrl
-    extra_commands="reload reread"
-fi
-
# Make sure required vars are set
SOCKET=${SOCKET:=$SPOOLDIR/$prog.sock}
MX_SOCKET=${MX_SOCKET:=$SPOOLDIR/$prog-multiplexor.sock}
@@ -288,11 +281,32 @@
     # Stop daemon
     printf "%-60s" "Shutting down $prog: "
     if test -f "$PID" ; then
-    kill `cat $PID`
-    RETVAL=$?
+    if kill -0 `cat $PID` > /dev/null 2>&1 ; then
+        kill `cat $PID`
+        RETVAL=$?
+    else
+        echo "mimedefang (`cat $PID`) has already been stopped."
+        # double check kill mimedefang , but all should be OK
+        # is this over the top?
+        RETVAL=$SMF_EXIT_OK
+        pkill -0 -u $MX_USER -x $prog > /dev/null 2>&1
+        if [ $? -eq 0 ]; then
+        pkill -u $MX_USER -x $prog
+        RETVAL=$?
+        fi
+    fi
     else
-    RETVAL=1
+    echo "mimedefang has already been stopped."
+    # double check kill mimedefang , but all should be OK
+    # is this over the top?
+    RETVAL=$SMF_EXIT_OK
+    pkill -0 -u $MX_USER -x $prog > /dev/null 2>&1
+    if [ $? -eq 0 ]; then
+        pkill -u $MX_USER -x $prog
+        RETVAL=$?
+    fi
     fi
+
     if [ $RETVAL = 0 ] ; then
    echo "[ OK ]"
     else
@@ -302,10 +316,30 @@
     # Stop daemon
     printf "%-60s" "Shutting down $prog-multiplexor: "
     if test -f "$MXPID" ; then
-    kill `cat $MXPID`
-    RETVAL=$?
+    if kill -0 `cat $MXPID` > /dev/null 2>&1 ; then
+        kill `cat $MXPID`
+        RETVAL=$?
+    else
+        echo "mimedefang-multiplexor (`cat $MXPID`) has already stopped."
+        # double check kill mimedefang-mult(iplexor) but all should be OK
+        # is this over the top?
+        RETVAL=$SMF_EXIT_OK
+        pkill -0 -u $MX_USER -x $prog-mult > /dev/null 2>&1
+        if [ $? -eq 0 ]; then
+        pkill -u $MX_USER -x $prog-mult
+        RETVAL=$?
+        fi
+    fi
     else
-    RETVAL=1
+    echo "mimedefang-multiplexor has already stopped."
+    # double check kill mimedefang-mult(iplexor) but all should be OK
+    # is this over the top?
+    RETVAL=$SMF_EXIT_OK
+    pkill -0 -u $MX_USER -x $prog-mult > /dev/null 2>&1
+    if [ $? -eq 0 ]; then
+        pkill -u $MX_USER -x $prog-mult
+        RETVAL=$?
+    fi
     fi
     if [ $RETVAL = 0 ] ; then
    echo "[ OK ]"


5) Create the manifest file (download version):
# cd /var/svc/manifest/network
# cat > mimedefang.xml
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
  Created by Andrew Watkins 9th May 2008
  References:
    /var/svc/manifest/network
    http://opensolaris.org/os/community/smf
    http://www.sun.com/bigadmin
  Thanks to
    David F. Skoll
    Kimmo Jaskari
  Modified 14th May 2008
    - major rewrite
    - added properties
    - dependent on sendmail
-->

<service_bundle type='manifest' name='mimedefang'>
<service name='network/mimedefang' type='service' version='1'>
    <single_instance />

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

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

    <dependency name='system-log' grouping='optional_all'
        restart_on='none' type='service'>
        <service_fmri value='svc:/system/system-log' />
    </dependency>

    <dependent name='mimedefang_multi-user'
        grouping='optional_all' restart_on='none'>
        <service_fmri value='svc:/milestone/multi-user' />
    </dependent>

    <dependent name='mimedefang_sendmail'
        grouping='optional_all' restart_on='none'>
        <service_fmri value='svc:/network/smtp:sendmail' />
    </dependent>

    <instance name='default' enabled='false'>
    <!-- instance-specific properties, methods, etc. go here. -->
      <dependency name='config-file' grouping='require_all'
          restart_on='refresh' type='path'>
          <service_fmri
            value='file://localhost/etc/mail/mimedefang-filter' />
      </dependency>

      <exec_method type='method' name='start'
        exec='/usr/local/mimedefang/bin/init-mimedefang start'
        timeout_seconds='60' />

      <exec_method type='method' name='stop'
        exec='/usr/local/mimedefang/bin/init-mimedefang stop'
        timeout_seconds='120' />

      <exec_method type='method' name='refresh'
        exec='/usr/local/mimedefang/bin/init-mimedefang reread'
        timeout_seconds='60' />

      <exec_method type='method' name='restart'
        exec='/usr/local/mimedefang/bin/init-mimedefang restart'
        timeout_seconds='60' />

      <property_group name='startd' type='framework'>
        <propval name='ignore_error' type='astring'
          value='core,signal' />
      </property_group>

      <property_group name='config' type='application'>
        <stability value='Evolving' />
        <propval name='spooldir' type='astring' value='/var/spool/MIMEDefang' />
        <propval name='mx_socket' type='astring' value='mimedefang-multiplexor.sock' />
        <propval name='mx_user' type='astring' value='defang' />
        <propval name='mx_relay_check' type='astring' value='no' />
        <propval name='mx_sender_check' type='astring' value='no' />
        <propval name='mx_recipient_check' type='astring' value='no' />
        <propval name='mx_maximum' type='integer' value='10' />
        <propval name='mx_minimum' type='integer' value='2' />
      </property_group>

      <template>
        <common_name>
            <loctext xml:lang='C'>
            mimedefang filtering e-mail system
            </loctext>
        </common_name>
        <documentation>
            <doc_link name='mimedefang' uri='http://www.mimedefang.org' />
        </documentation>
      </template>

    </instance>
    <stability value='Unstable' />
</service>
</service_bundle>
^D
#


6) Check and setup the manifest:
# svccfg validate /var/svc/manifest/network/mimedefang.xml
# svccfg import /var/svc/manifest/network/mimedefang.xml

7) See if it all worked:
# svcs -a mimedefang
STATE          STIME    FMRI
disabled       16:58:48 svc:/network /mimedefang:default

8) Check what properties are available to be altered:
# /usr/bin/svcprop -p config mimedefang:default
config/mx_socket astring mimedefang-multiplexor.sock
config/spooldir astring /var/spool/MIMEDefang
config/stability astring Evolving
config/mx_maximum integer 10
config/mx_minimum integer 2
config/mx_relay_check astring no
config/mx_sender_check astring no
config/mx_recipient_check astring no
config/mx_user astring defang

9) Change any which need to be altered
# svccfg -s mimedefang:default setprop config/mx_maximum = 10
# svccfg -s mimedefang:default setprop config/mx_user = "defang5"
# svccfg -s mimedefang:default setprop config/mx_relay_check = "yes"
# svccfg -s mimedefang:default setprop config/mx_sender_check = 'yes'
# svccfg -s mimedefang:default setprop config/mx_recipient_check = "yes"
# svcadm refresh mimedefang


10) Start it up
# svcadm enable mimedefang
# svcs -a mimedefang
STATE          STIME    FMRI
online         16:59:48 svc:/network /mimedefang:default


11) Check the log file
# svcs -l mimedefang:default
fmri svc:/network/mimedefang:default
name mimedefang filtering e-mail system
enabled true
state online
next_state none
state_time Tue May 27 15:06:25 2008
logfile /var/svc/log/network-mimedefang:default.log
restarter svc:/system/svc/restarter:default
contract_id 284
dependency require_all/refresh file://localhost/etc/mail/mimedefang-filter (online)
dependency require_all/none svc:/system/filesystem/local (online)
dependency require_all/none svc:/network/service (online)
dependency optional_all/none svc:/system/system-log (online)

# cat /var/svc/log/network-mimedefang:default.log

References
smf(5) Frequently Asked Questions
Solaris Service Management Facility - Service Developer Introduction

2 comments:

Andrew Watkins said...

This is a re-post - sorry for any confusions. Andrew

Ulver said...

my question could be off topic..

have you ever mangle "received headers" with mimedefang?