Building and Deploying Nagios on Oracle Solaris 11

by Joseph Balenzano and Edward Zhang
Published August 2014

How to use the Image Packaging System and Service Management Facility features of Oracle Solaris 11 to install Nagios on any Oracle Solaris 11 system by running a single command.

Introduction

Nagios is a popular open source system, network, and infrastructure monitoring application. Nagios offers monitoring and alerting services for servers, switches, applications, and services.

This article will take you through the steps of building Nagios 4.0.2 from source code on an Oracle Solaris 11 system, creating an Oracle Solaris Service Management Facility manifest for the Nagios service, and creating an Oracle Solaris 11 Image Packaging System package that can be installed using a single Oracle Solaris 11 command on any system running Oracle Solaris 11.

Note: It does not matter if the system is x64- or SPARC-based, and the procedures should work with all versions of Oracle Solaris 11 (for example, Oracle Solaris 11 and Oracle Solaris 11.1).

Prerequisites

Familiarity with administering Oracle Solaris 11 systems, including using the Image Packaging System, is an advantage. For more information, see the resources in the "See Also" section.

Summary of the Tasks

This article is divided into a number of different sections that cover many of the basic administration tasks. Each main section is independent of the others.

Table 1. Summary of the tasks

Main Section Topics Covered
Building Nagios Core
  • Preparing for the build process
  • Building Nagios using Oracle Solaris Studio
  • Building Nagios using the GNU compiler
  • Building Nagios plugins
Generating a Service Management Facility Manifest for Nagios Generating a Service Management Facility manifest for Nagios
Creating a Package Manifest
  • Generating a package manifest for Nagios
  • Creating a metadata package
  • Generating a file and directory list
  • Calculating dependencies for Nagios
Publishing and Installing a Package
  • Creating a package repository
  • Publishing the package
  • Installing the package

Building Nagios Core

You can build Nagios Core using either the GNU compiler or Oracle Solaris Studio. This article describes both way of doing it, so you can choose one of them to build Nagios Core.

Preparing for the Build Process

Before we start building Nagios, we need to install some required packages and finish some preparation for the building process.

First, since various components of Nagios require the PHP application, you need to install PHP on your system:

root@solaris:~# pkg install web/php-53 apache-php53

To use the Nagios diagram feature, the Graphics Draw Library package is needed. If the Graphics Draw Library is not installed on your system, use the following command to install it on your system:

root@solaris:~# pkg install gd

We will use a compiler to quickly install Nagios into a PROTO area. A PROTO area is essentially an isolated location in the file system that allows you to easily collect the executables, libraries, documentation, and any other accompanying files into a package.

Please download the latest stable release of Nagios Core. In this article, we will use version 4.0.2.

Untar the downloaded file, which creates the following directory structure:




root@solaris:~# tar -zxf nagios-4.0.2.tar.gz
root@solaris:~# mv nagios-4.0.2 nagios
root@solaris:~# cd nagios
root@solaris:~/nagios# ls
base            functions       Makefile.in     subst.in
cgi             html            mkpackage       t
Changelog       include         module          t-tap
common          indent-all.sh   nagios.spec     tap
config.guess    indent.sh       OutputTrap.pm   THANKS
config.sub      install-sh      p1.pl           tools
configure       INSTALLING      pkg             update-version
configure.in    LEGAL           pkginfo.in      UPGRADING
contrib         LICENSE         README          xdata
daemon-init.in  make-tarball    sample-config

Create a PROTO area that we will use to compile Nagios into:

root@solaris:~/nagios# mkdir ../PROTO

Now choose one of the following ways to compile and build Nagios Core—using Oracle Solaris Studio OR using the GNU compiler (gcc)—and use the corresponding procedure below. The Nagios configuration file will automatically detect which compiler you are using. If you have gcc already installed in your system, use that method.

Building Nagios Core Using Oracle Solaris Studio

If Oracle Solaris Studio is not installed on your system, you need to install it now.

First, go to http://pkg-register.oracle.com/ to obtain a certificate for Oracle Solaris Studio. Select Request Certificates and sign in to your My Oracle Support account. Choose Oracle Solaris Studio and click Submit. Follow the instruction to get your key and certificate for the solarisstudio publisher. Then follow the instructions on the website or run the following command to set up the solarisstudio publisher:




root@solaris:~# pkg set-publisher \
            -k /var/pkg/ssl/Oracle_Solaris_Studio.key.pem \
            -c /var/pkg/ssl/Oracle_Solaris_Studio.certificate.pem \
            -G '*' -g https://pkg.oracle.com/solarisstudio/release solarisstudio

After setting up the solarisstudio publisher, install Oracle Solaris Studio 12.3 on your system:

root@solaris:~# pkg install solarisstudio-123

We will use gnu-make to build Nagios, so if you don't have gnu-make on your system, install it now:

root@solaris:~# pkg install gnu-make

To make sure you use gnu-make and Oracle Solaris Studio, change the system path for the building process:

root@solaris:~# export PATH=$PATH:/usr/gnu/bin:/opt/solarisstudio12.3/bin/

Now that all the required packages have been installed, we can build Nagios version 4.0.2 of Nagios Core.

Nagios Core uses the standard configure command to check its environment, so run the command, as shown in Listing 1.




root@solaris:~/nagios# ./configure
checking for a BSD-compatible install... /usr/gnu/bin/install -c
checking build system type... sparc-sun-solaris2.11
checking host system type... sparc-sun-solaris2.11
checking for gcc... no
checking for cc... cc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... no
checking whether cc accepts -g... yes
checking for cc option to accept ISO C89... none needed
checking whether make sets $(MAKE)... yes
checking for strip... /usr/bin/strip
....
*** Configuration summary for nagios 4.0.2 11-25-2013 ***:

 General Options:
 -------------------------
        Nagios executable:  nagios
        Nagios user/group:  nagios,nagios
       Command user/group:  nagios,nagios
            Embedded Perl:  no
             Event Broker:  yes
        Install ${prefix}:  /usr/local/nagios
                Lock file:  ${prefix}/var/nagios.lock
   Check result directory:  ${prefix}/var/spool/checkresults
           Init directory:  /etc/init.d
  Apache conf.d directory:  /etc/httpd/conf.d
             Mail program:  /usr/bin/mail
                  Host OS:  solaris2.11
          IOBroker Method:  poll

 Web Interface Options:
 ------------------------
                 HTML URL:  http://localhost/nagios/
                  CGI URL:  http://localhost/nagios/cgi-bin/
 Traceroute (used by WAP):  /usr/sbin/traceroute

Listing 1

Review the options shown in Listing 1 for accuracy.

Before we can compile Nagios, there are a couple of source file changes that need to be made since this version of Nagios defines a structure (struct comment) that conflicts with a system structure of the same name in /usr/include/sys/pwd.h. Perform the following steps to fix this issue.

  1. Add the following line as line 28 of the ./worker/ping/worker-ping.c file:

    #include <pwd.h>

  2. Comment out the following line (line 144) in the ./include/config.h file:

    //#include <pwd.h>

  3. Change the following line (line 27) in the ./base/utils.c file from this:

    #include "../include/comments.h"

    To this:

    #include <pwd.h>

  4. Change the following line (line 14) in the ./base/Makefile file from this:

    CFLAGS=-Wall -I.. -g -DHAVE_CONFIG_H -DNSCORE

    To this:

    CFLAGS=-I.. -g -DHAVE_CONFIG_H -DNSCORE

  5. Change the following line (line 29) in the ./cgi/Makefile file from this:

    CFLAGS=-Wall -I.. -g -O2 -DHAVE_CONFIG_H -DNSCGI

    To this:

    CFLAGS=-I.. -g -O2 -DHAVE_CONFIG_H -DNSCGI -I/usr/include/gd2

Then run the following command to compile Nagios:




root@solaris:~/nagios# make all
cd ./base && make
make[1]: Entering directory `/root/projectNagios/nagios/base'
make -C ../lib
make[2]: Entering directory `/root/projectNagios/nagios/lib'
cc -g -DHAVE_CONFIG_H -c squeue.c -o squeue.o
cc -g -DHAVE_CONFIG_H -c kvvec.c -o kvvec.o
cc -g -DHAVE_CONFIG_H -c iocache.c -o iocache.o
....

Once everything has compiled, use the make install, make install-commandmode, and make install-config targets to install the compiled binaries and sample configuration into our PROTO area using the DESTDIR command-line substitution, as shown in Listing 2. In order for this to be successfully completed, we need to first create the nagios user and nagios group. Use the useradd(1M) and groupadd(1M) commands to quickly do this, as shown in Listing 2.




root@solaris:~/nagios# groupadd nagios
root@solaris:~/nagios# useradd -g nagios nagios
root@solaris:~/nagios# make install DESTDIR=/root/PROTO
cd ./base && make install
make[1]: Entering directory `/root/projectNagios/nagios/base'
make install-basic
make[2]: Entering directory `/root/projectNagios/nagios/base'
/usr/gnu/bin/install -c -m 775 -o nagios -g nagios -d 
/root/PROTO/usr/local/nagios/bin
/usr/gnu/bin/install -c -m 774 -o nagios -g nagios nagios 
/root/PROTO/usr/local/nagios/bin
/usr/gnu/bin/install -c -m 774 -o nagios -g nagios nagiostats 
/root/PROTO/usr/local/nagios/bin
....
  make install-config
     - This installs sample config files in /root/PROTO/usr/local/nagios/etc

make[1]: Leaving directory `/root/projectNagios/nagios'

root@solaris:~/nagios# make install-commandmode DESTDIR=/root/PROTO
/usr/gnu/bin/install -c -m 775 -o nagios -g nagios -d /root/PROTO/usr/local/nagios/var/rw
chmod g+s /root/PROTO/usr/local/nagios/var/rw

*** External command directory configured ***

root@solaris:~/nagios# make install-config DESTDIR=/root/PROTO
/usr/gnu/bin/install -c -m 775 -o nagios -g nagios -d 
/root/PROTO/usr/local/nagios/etc
/usr/gnu/bin/install -c -m 775 -o nagios -g nagios -d 
/root/PROTO/usr/local/nagios/etc/objects
/usr/gnu/bin/install -c -b -m 664 -o nagios -g nagios sample-config/nagios.cfg 
/root/PROTO/usr/local/nagios/etc/nagios.cfg
/usr/gnu/bin/install -c -b -m 664 -o nagios -g nagios sample-config/cgi.cfg 
/root/PROTO/usr/local/nagios/etc/cgi.cfg
....
*** Config files installed ***

Remember, these are *SAMPLE* config files.  You'll need to read
the documentation for more information on how to actually define
services, hosts, etc. to fit your particular needs.

Listing 2

Now add the following lines to PROTO/local/nagios/etc/cgi.cfg to get the correct authorization for Nagios:



default_user_name=nagiosadmin
authorized_for_system_information=nagiosadmin
authorized_for_system_commands=nagiosadmin
authorized_for_configuration_information=nagiosadmin
authorized_for_all_hosts=nagiosadmin
authorized_for_all_host_commands=nagiosadmin
authorized_for_all_services=nagiosadmin
authorized_for_all_service_commands=nagiosadmin

Building Nagios Core Using the GNU Compiler

Nagios can also be built using the GNU C compiler (gcc). If gcc is not installed on you system, install it now, as shown in Listing 3.




root@solaris:~# pkg search -p gcc

PACKAGE                                                   PUBLISHER
pkg:/developer/gcc-3@3.4.3-0.175.1.0.0.24.0               solaris
pkg:/developer/gcc-45@4.5.2-0.175.1.0.0.24.0              solaris
pkg:/library/gc@7.2-0.175.1.0.0.17.0                      solaris
pkg:/system/library/gcc-3-runtime@3.4.3-0.175.1.0.0.24.0  solaris
pkg:/system/library/gcc-45-runtime@4.5.2-0.175.1.0.0.24.0 solaris

Listing 3

There might be multiple versions of gcc in your repositories, as shown in Listing 3. In the following example, we are going to install the latest version, 4.5.2:

root@solaris:~# pkg install gcc-45

With the all the required packages installed, we can now build Nagios. We are working with version 4.0.2 of Nagios.

Nagios uses the standard configure command to check its environment, so run the command, as shown in Listing 4.




root@solaris:~/nagios# ./configure
checking for a BSD-compatible install... /usr/bin/ginstall -c
checking build system type... i386-pc-solaris2.11
checking host system type... i386-pc-solaris2.11
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
....
*** Configuration summary for nagios 4.0.2 11-25-2013 ***:

 General Options:
 -------------------------
        Nagios executable:  nagios
        Nagios user/group:  nagios,nagios
       Command user/group:  nagios,nagios
            Embedded Perl:  no
             Event Broker:  yes
        Install ${prefix}:  /usr/local/nagios
                Lock file:  ${prefix}/var/nagios.lock
   Check result directory:  ${prefix}/var/spool/checkresults
           Init directory:  /etc/init.d
  Apache conf.d directory:  /etc/httpd/conf.d
             Mail program:  /usr/bin/mail
                  Host OS:  solaris2.11
          IOBroker Method:  poll

 Web Interface Options:
 ------------------------
                 HTML URL:  http://localhost/nagios/
                  CGI URL:  http://localhost/nagios/cgi-bin/
 Traceroute (used by WAP):  /usr/sbin/traceroute

Listing 4

Review the options shown in Listing 4 for accuracy.

Before we can start compiling Nagios, there are a couple of source file changes that need to be made, since this version of Nagios defines a structure (struct comment) that conflicts with a system structure of the same name in /usr/include/sys/pwd.h. Perform the following steps to fix this issue.

  1. Add the following line as line 28 of the ./worker/ping/worker-ping.c file:

    #include <pwd.h>

  2. Comment out the following line (line 144) in the ./include/config.h file:

    //#include <pwd.h>

  3. Change the following line (line 27) in the ./base/utils.c file from this:

    #include "../include/comments.h"

    To this:

    #include <pwd.h>

  4. Change the following line (line 29) in the ./cgi/Makefile file from this:

    CFLAGS=-Wall -I.. -g -O2 -DHAVE_CONFIG_H -DNSCGI

    To this:

    CFLAGS=-Wall -I.. -g -O2 -DHAVE_CONFIG_H -DNSCGI -I/usr/include/gd2

Then run the following command to compile Nagios:




root@solaris:~/nagios# gmake all
cd ./base && gmake
gmake[1]: Entering directory `/root/nagios/base'
gcc -Wall -g -O2 -DHAVE_CONFIG_H -DNSCORE   -c -o broker.o broker.c
gcc -Wall -g -O2 -DHAVE_CONFIG_H -DNSCORE   -c -o nebmods.o nebmods.c
gcc -Wall -g -O2 -DHAVE_CONFIG_H -DNSCORE -c -o ../common/shared.o ../common/shared.c
gcc -Wall -g -O2 -DHAVE_CONFIG_H -DNSCORE   -c -o checks.o checks.c
gcc -Wall -g -O2 -DHAVE_CONFIG_H -DNSCORE   -c -o config.o config.c
...

Once everything has compiled, use the gmake install, gmake install-commandmode, and gmake install-config targets to install the compiled binaries and sample configuration into our PROTO area using the DESTDIR command-line substitution, as shown in Listing 5. In order for this to be successfully completed, we need to first create the nagios user and nagios group. Use the useradd(1M) and groupadd(1M) commands to quickly do this, as shown in Listing 5.




root@solaris:~/nagios# groupadd nagios
root@solaris:~/nagios# useradd -g nagios nagios
root@solaris:~/nagios# gmake install DESTDIR=/root/PROTO
cd ./base && gmake install
gmake[1]: Entering directory `/root/nagios/base'
gmake install-basic
gmake[2]: Entering directory `/root/nagios/base'
/usr/bin/ginstall -c -m 775 -o nagios -g nagios -d /root/PROTO/usr/local/nagios/bin
/usr/bin/ginstall -c -m 774 -o nagios -g nagios nagios 
/root/PROTO/usr/local/nagios/bin
/usr/bin/ginstall -c -m 774 -o nagios -g nagios nagiostats 
/root/PROTO/usr/local/nagios/bin
....
make install-config
     - This installs sample config files in /root/PROTO/usr/local/nagios/etc

gmake[1]: Leaving directory `/root/nagios'

root@solaris:~/nagios# gmake install-commandmode DESTDIR=/root/PROTO
/usr/bin/ginstall -c -m 775 -o nagios -g nagios -d 
/root/PROTO/usr/local/nagios/var/rw
chmod g+s /root/PROTO/usr/local/nagios/var/rw

*** External command directory configured ***

root@solaris:~/nagios# gmake install-config DESTDIR=/root/PROTO
/usr/bin/ginstall -c -m 775 -o nagios -g nagios -d /root/PROTO/usr/local/nagios/etc
/usr/bin/ginstall -c -m 775 -o nagios -g nagios -d 
/root/PROTO/usr/local/nagios/etc/objects
/usr/bin/ginstall -c -b -m 664 -o nagios -g nagios sample-config/nagios.cfg 
/root/PROTO/usr/local/nagios/etc/nagios.cfg
/usr/bin/ginstall -c -b -m 664 -o nagios -g nagios sample-config/cgi.cfg 
/root/PROTO/usr/local/nagios/etc/cgi.cfg
....
*** Config files installed ***

Remember, these are *SAMPLE* config files.  You'll need to read the documentation for
more information on how to actually define services, hosts, etc. to fit your 
particular needs.  

Listing 5

Now add the following lines to PROTO/local/nagios/etc/cgi.cfg to get the correct authorization for Nagios:




default_user_name=nagiosadmin
authorized_for_system_information=nagiosadmin
authorized_for_system_commands=nagiosadmin
authorized_for_configuration_information=nagiosadmin
authorized_for_all_hosts=nagiosadmin
authorized_for_all_host_commands=nagiosadmin
authorized_for_all_services=nagiosadmin
authorized_for_all_service_commands=nagiosadmin

Building Nagios Plugins

The next step is to build the Nagios plugins in our /root/PROTO area. You may choose to create a separate package for the plugins, but for simplicity, we will create a single package that has Nagios Core and the plugins.




root@solaris:~# wget https://www.nagios-plugins.org/download/nagios-plugins-1.5.tar.gz
root@solaris:~# tar -zxf nagios-plugins-1.5.tar.gz
root@solaris:~# cd nagios-plugins-1.5

For this particular version of the plugins, we have to modify the ./configure file and change line 18226 to the following:

elif $PATH_TO_SWAP -l 2>/dev/null | egrep -i "^swapfile +dev + swaplo +blocks +free" >/dev/null

Then run the following command:

root@solaris: ~/nagios-plugins-1.5# ./configure

Now install the plugins into our PROTO area:

root@solaris: ~/nagios-plugins-1.5# gmake install DESTDIR=/root/PROTO

Generating a Service Management Facility Manifest for Nagios

Service Management Facility manifests are used to describe a service, its configuration, and how it can be started, and stopped.

Service Management Facility manifests are XML-based files that are usually located in /lib/svc/manifest. While we could write a Service Management Facility manifest manually, we will use the svcbundle(1M) command to generate a simple one for us.

The svcbundle command allows administrators to create, and optionally install, a manifest or system profile for common scenarios. As a result, svcbundle makes a number of simple assumptions—which are detailed in the man page—to deal with these common scenarios, including automatically starting this service by default. We can create a Service Management Facility manifest as follows:




root@solaris:~# mkdir -p PROTO/lib/svc/manifest/site
root@solaris:~# cd PROTO/lib/svc/manifest/site
root@solaris:~# svcbundle -o nagios.xml \
 -s service-name=application/nagios \
 -s start-method="/usr/local/nagios/bin/nagios  /usr/local/nagios/etc/nagios.cfg"
root@solaris:~# cat nagios.xml
<?xml version="1.0" ?>
<!DOCTYPE service_bundle
  SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<!--
    Manifest created by svcbundle (2014-Feb-01 00:39:14+0000)
-->
<service_bundle type="manifest" name="application/nagios">
   <service version="1" type="service" name="application/nagios">
      <!--
          The following dependency keeps us from starting until the
          multi-user milestone is reached.
      -->
      <dependency restart_on="none" type="service"
          name="multi_user_dependency" grouping="require_all">
          <service_fmri value="svc:/milestone/multi-user"/>
      </dependency>
      <exec_method timeout_seconds="60" type="method" name="start"
          exec="/usr/local/nagios/bin/nagios /usr/local/nagios/etc/nagios.cfg"
        />
        <!--
        The exec attribute below can be changed to a command that SMF
        should execute to stop the service.  See smf_method(5) for more
        details.
        -->
        <exec_method timeout_seconds="60" type="method" name="stop"
            exec=":true"/>
        <!--
        The exec attribute below can be changed to a command that SMF
        should execute when the service is refreshed.  Services are
        typically refreshed when their properties are changed in the
        SMF repository.  See smf_method(5) for more details.  It is
        common to retain the value of :true which means that SMF will
        take no action when the service is refreshed.  Alternatively,
        you may wish to provide a method to reread the SMF repository
        and act on any configuration changes.
        -->
        <exec_method timeout_seconds="60" type="method" name="refresh"
            exec=":true"/>
        <property_group type="framework" name="startd">
            <propval type="astring" name="duration" value="transient"/>
        </property_group>
        <instance enabled="true" name="default"/>
        <template>
            <common_name>
                <loctext xml:lang="C">
                    <!--
                    Replace this comment with a short name for the
                    service.
                    -->
                </loctext>
            </common_name>
            <description>
                <loctext xml:lang="C">
                    <!--
                    Replace this comment with a brief description of
                    the service
                    -->
                </loctext>
            </description>
        </template>
    </service>
</service_bundle>

Creating a Package Manifest

Behind each package is a package manifest that describes how the package is assembled. It contains information such as the package name, its version, package dependencies, and a list of files, directories, links, and other package contents.

Generating a Package Manifest for Nagios

We will need to create a package manifest for our Nagios package as part of the publishing process to the repository.

You can take a look at a typical package manifest by using the pkg contents command with the -m option, as follows:




root@solaris:~/nagios# pkg contents -m gzip
set name=pkg.fmri value=pkg://solaris/compress/gzip@1.4,5.11-0.175.1.0.0.24.0:20120904T170603Z
set name=org.opensolaris.consolidation value=userland
set name=pkg.summary value="GNU Zip (gzip)"
set name=pkg.description value="The GNU Zip (gzip) compression utility"
set name=info.source-url value=ftp://ftp.gnu.org/gnu/gzip/gzip-1.4.tar.gz
set name=info.classification value="org.opensolaris.category.2008:Applications/System Utilities"
set name=info.upstream-url value=http://www.gnu.org/software/gzip/
set name=org.opensolaris.arc-caseid value=PSARC/2000/488
set name=variant.arch value=i386 value=sparc
depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/shell/bash@4.1.9-0.175.1.0.0.23.0 type=require
dir group=sys mode=0755 owner=root path=usr
dir group=bin mode=0755 owner=root path=usr/bin
dir group=sys mode=0755 owner=root path=usr/share
....
signature 235c7674d821032ae3eeda280c7837d1f1f4fdb5 algorithm=rsa-sha256 
chain="8e422c1bb80b05f08f7a849f3d7ae90a976e048e 
754665e03bd28ef63b05a416073eb6d649624781" 
chain.chashes="083e40bb50e6964834ebfd3c66b8720b46028068 
f85dabbb0d56b37de3c3de98663dd8f27a12ff8e" chain.csizes="1273 1326" chain.sizes="1773 
2061" chash=05654e46fc5cac3b9b9bd11c39512bc92bc85089 pkg.csize=1281 pkg.size=1753 
value=41df24b2bc4fe0cc705642f7bcad54f8d96017d919865d12da22bbb42ab451b2d1e28c50c0d2b5a
52b1e49e2732aeae9296216a3418c57fab6ed68624d492e68b8f8a4c728ec03f823608c2f95437ced3591
a957fc8c9a69fdbb3e5f0e45cf6a74b9341c97d727a60ef1f8be78a91114e378d84b530ae1b6565e15e06
0802f96fdbbea19823f0e2c8e4dc2e5f6f82c6e9b85362c227704ecefc4460fc56dc947af2d8728231383
78e4c1d224012f135281c567ef854b63cc75b43336142a5db78c0544f3e31cd101a347a55c25b77463431
ce65db04f5821fe9e7d5e27718fb9be71373d110ca8eea4a82b5b3571684a6a182910b87e7f65c22d590a
8e6523f9 version=0

Each line defines an action—whether it's setting some metadata about the package such as a name and description, or whether it's specifying files and directories to include in the package. When we create a package manifest for the Nagios package, we'll split the manifest into three different sections.

Creating Package Metadata

The first section is all about creating package metadata. At the start of the package manifest for gzip, we can see a number of lines:




set name=pkg.fmri value=pkg://solaris/compress/gzip@1.4,5.11-0.175.1.0.0.24.0:20120904T170603Z
set name=org.opensolaris.consolidation value=userland
set name=pkg.summary value="GNU Zip (gzip)"
set name=pkg.description value="The GNU Zip (gzip) compression utility"
set name=info.source-url value=ftp://ftp.gnu.org/gnu/gzip/gzip-1.4.tar.gz
set name=info.classification value="org.opensolaris.category.2008:Applications/System Utilities"
set name=info.upstream-url value=http://www.gnu.org/software/gzip/

We need to create similar metadata for Nagios. We'll start by editing a file called nagios.mog and include the lines shown in Listing 6:




set name=pkg.fmri value=nagios@4.0.2,5.11-0
set name=pkg.summary value="Nagios monitoring utility"
set name=pkg.description value="Nagios is a host/service/network monitoring program"
set name=variant.arch value=$(ARCH)

Listing 6

Let's quickly go through the parts of this initial manifest shown in Listing 6. The set action represents a way to set package attributes such as the package version, a summary, and a description. We set the package FMRI (Fault Management Resource Indicator) to nagios@4.0.2,5.11-0, which indicates we're using Nagios 4.0.2 on Oracle Solaris 11 (5.11). Variants are a feature of the Image Packaging System that allows us to package support for multiple architectures in a single package (for example, have a single package for both SPARC and x86). We set variant.arch to a variable that we will substitute in later.

Generating a File and Directory List

The next step will be to look in our PROTO directory and generate a list of files and directories that we wish to include in our package. Fortunately we can automate much of this task with the pkgsend(1) generate command. We will pipe the output through the pkgfmt(1) command to make the output nicer, and then put it into the nagios.p5m.gen file, as shown in Listing 7:

The nagios user, which Nagios is executing under, needs read-write access to the file we are creating by using the touch(1) command in Listing 7. We will set the file ownership and permissions in the manifest.




root@solaris:~# touch PROTO/usr/local/nagios/var/rw/nagios.cmd

root@solaris:~# pkgsend generate PROTO | pkgfmt > nagios.p5m.gen
root@solaris:~# cat nagios.p5m.gen 
dir  path=usr owner=root group=bin mode=0755
dir  path=usr/local owner=root group=bin mode=0755
dir  path=usr/local/nagios owner=root group=bin mode=0755
dir  path=usr/local/nagios/bin owner=root group=bin mode=0775
file usr/local/nagios/bin/nagios path=usr/local/nagios/bin/nagios owner=root \
    group=bin mode=0774
file usr/local/nagios/bin/nagiostats path=usr/local/nagios/bin/nagiostats \
    owner=root group=bin mode=0774
dir  path=usr/local/nagios/etc owner=root group=bin mode=0775
....
dir  path=usr/local/nagios/var/archives owner=root group=bin mode=0775
dir  path=usr/local/nagios/var/rw owner=root group=bin mode=0775
file usr/local/nagios/var/rw/nagios.cmd \
    path=usr/local/nagios/var/rw/nagios.cmd owner=root group=bin mode=0644
dir  path=usr/local/nagios/var/spool owner=root group=bin mode=0755
dir  path=usr/local/nagios/var/spool/checkresults owner=root group=bin mode=0775

Listing 7

In Listing 7, we see a few new actions: file and dir. These specify the package contents, plus their user and group ownership and permissions. We need to modify the user and group permissions of /usr/local/nagios/var, /usr/local/nagios/var/rw, and /usr/local/var/spool/checkresults to use the nagios user and group. To do this, edit nagios.p5m.gen and make the following changes to the five lines highlighted in bold:




file usr/local/nagios/bin/nagios path=usr/local/nagios/bin/nagios owner=nagios group=nagios mode=0774
....
dir  path=usr/local/nagios/var owner=nagios group=nagios mode=0775
dir  path=usr/local/nagios/var/archives owner=root group=root mode=0775
dir  path=usr/local/nagios/var/rw owner=nagios group=nagios mode=0775
file usr/local/nagios/var/rw/nagios.cmd \
    path=usr/local/nagios/var/rw/nagios.cmd owner=nagios group=nagios mode=0663
dir  path=usr/local/nagios/var/spool owner=root group=bin mode=0755
dir  path=usr/local/nagios/var/spool/checkresults owner=nagios group=nagios mode=0775


If we were planning on installing Nagios into /usr/bin, good packaging practices for Oracle Solaris 11 encourage that we go through this list and check which directories are being installed by Nagios and which are already provided as part of a default system installation. That list of directories could be dynamically removed from our package manifest, which is known as a transform. In our case, we are planning to install files into /usr, which is already provided by the system. So we need to remove it from our manifest. We can do this by adding the following line to our nagios.mog file to drop this dir action:

<transform dir path=usr$ -> drop>

Let's also add four additional transforms to drop /lib, /lib/svc, /lib/svc/manifest, and /lib/svc/manifest/application since these are system-provided locations, and let's add a new transform to handle our Service Management Facility manifest, as shown in Listing 8:




<transform dir path=lib$ -> drop>
<transform dir path=lib/svc$ -> drop>
<transform dir path=lib/svc/manifest$ -> drop>
<transform dir path=lib/svc/manifest/site$ -> drop>
<transform file path=lib/svc/manifest/.*\.xml$ -> \
    default restart_fmri svc:/system/manifest-import:default>

Listing 8

The last transform in Listing 8 finds any file with a .xml extension within the lib/svc/manifest directory and adds an actuator to restart the system/manifest-import service when the package is installed. This registers our Nagios service description with the Service Management Facility service framework.

Now that we have both nagios.mog and nagios.p5m.gen, let's merge them together to form nagios.p5m.mog using the pkgmogrify(1) command. We'll also substitute our architecture type in the $(ARCH) variable, as shown in Listing 9:




root@solaris:~# pkgmogrify -DARCH=`uname -p` nagios.p5m.gen nagios.mog | pkgfmt > nagios.p5m.mog
root@solaris:~# cat nagios.p5m.mog
set name=pkg.fmri value=nagios@4.0.2,5.11-0
set name=pkg.summary value="Nagios monitoring utility"
set name=pkg.description \
    value="Nagios is a host/service/network monitoring program"
set name=variant.arch value=sparc
....
dir  path=usr/local/nagios/var owner=nagios group=nagios mode=0775
dir  path=usr/local/nagios/var/archives owner=root group=bin mode=0775
dir  path=usr/local/nagios/var/rw owner=nagios group=nagios mode=0775
file usr/local/nagios/var/rw/nagios.cmd \
    path=usr/local/nagios/var/rw/nagios.cmd owner=nagios group=nagios mode=0663
dir  path=usr/local/nagios/var/spool owner=root group=bin mode=0755
dir  path=usr/local/nagios/var/spool/checkresults owner=nagios group=nagios mode=0775

Listing 9

In Listing 9, you can see that we have merged the two files. Notice that we now have a value of sparc for variant.arch.

Calculating Dependencies for Nagios

The next step is to generate package dependencies for Nagios. The Image Packaging System includes the ability to scan the contents of a package to try to detect what dependencies might exist. It does this by detecting the file type—whether the file is a script or an executable. If it's a script, the Image Packaging System will check the value of the #! statement at the beginning of the script to see whether the script is a Perl, Python, Bash, or other shell script. If the file is an executable, the Image Packaging System will look at the Executable and Linkable Format (ELF) header to see what other libraries are required for successful runtime execution. This is a two-step process, because we then need to make those file dependencies into package dependencies.

Let's first generate the list of file dependencies that Nagios has. We use the pkgdepend(1) generate command, and we pass in the location of our PROTO area, as shown in Listing 10:




root@solaris:~# pkgdepend generate -md PROTO nagios.p5m.mog > nagios.p5m.dep
root@solaris:~# tail nagios.p5m.dep
depend fmri=__TBD pkg.debug.depend.file=libc.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/sbin/outages.cgi pkg.debug.depend.type=elf 
type=require
depend fmri=__TBD pkg.debug.depend.file=libsocket.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/sbin/outages.cgi pkg.debug.depend.type=elf 
type=require
depend fmri=__TBD pkg.debug.depend.file=libsocket.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/sbin/status.cgi pkg.debug.depend.type=elf 
type=require
depend fmri=__TBD pkg.debug.depend.file=libc.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/sbin/showlog.cgi pkg.debug.depend.type=elf 
type=require
depend fmri=__TBD pkg.debug.depend.file=libc.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/bin/nagiostats
pkg.debug.depend.type=elf type=require
depend fmri=__TBD pkg.debug.depend.file=libc.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/sbin/config.cgi pkg.debug.depend.type=elf 
type=require
depend fmri=__TBD pkg.debug.depend.file=libsocket.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/bin/nagiostats pkg.debug.depend.type=elf 
type=require
depend fmri=__TBD pkg.debug.depend.file=libm.so.2 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/bin/nagiostats
pkg.debug.depend.type=elf type=require
depend fmri=__TBD pkg.debug.depend.file=libsocket.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/sbin/config.cgi pkg.debug.depend.type=elf 
type=require
depend fmri=__TBD pkg.debug.depend.file=libc.so.1 pkg.debug.depend.path=lib 
pkg.debug.depend.path=usr/lib pkg.debug.depend.reason=usr/local/nagios/sbin/cmd.cgi 
pkg.debug.depend.type=elf type=require
...

Listing 10

In Listing 10, we can see that we have generated a number of lines that start with the depend action. If you look closely, you can see the pkg.debug.depend.file value is libc.so.1 or libsocket.so.1 (in the lines that we printed), which indicates dependencies on shared objects. We can see that all of these dependencies have been found by looking at the ELF header, and we can also see the files that have caused this dependency by looking at the pkg.debug.depend.reason value.

We now need to resolve these dependencies into the packages that they come from. We use the pkgdepend resolve command to do this:




root@solaris:~# pkgdepend resolve -m nagios.p5m.dep
root@solaris:~# tail nagios.p5m.dep.res
file usr/local/nagios/share/stylesheets/trends.css 
path=usr/local/nagios/share/stylesheets/trends.css owner=root group=bin mode=0664
dir  path=usr/local/nagios/var owner=nagios group=nagios mode=0775
dir  path=usr/local/nagios/var/archives owner=root group=bin mode=0775
dir  path=usr/local/nagios/var/rw owner=nagios group=nagios mode=0775
file usr/local/nagios/var/rw/nagios.cmd \
    path=usr/local/nagios/var/rw/nagios.cmd owner=nagios group=nagios mode=0663
dir  path=usr/local/nagios/var/spool owner=root group=bin mode=0755
dir  path=usr/local/nagios/var/spool/checkresults owner=nagios group=nagios mode=0775
depend fmri=pkg:/image/library/libjpeg@6.0.2-0.175.0.0.0.0.0 type=require
depend fmri=pkg:/image/library/libpng@1.4.11-0.175.1.0.0.16.0 type=require
depend fmri=pkg:/library/gd@2.0.35-0.175.1.0.0.24.0 type=require
depend fmri=pkg:/library/openldap@2.4.30-0.175.1.14.0.3.0 type=require
depend fmri=pkg:/library/security/openssl@1.0.0.11-0.175.1.7.0.4.0 type=require
depend fmri=pkg:/library/zlib@1.2.3-0.175.1.0.0.24.0 type=require
depend fmri=pkg:/runtime/perl-512@5.12.5-0.175.1.8.0.4.0 type=require
depend fmri=pkg:/shell/ksh93@93.21.0.20110208-0.175.1.15.0.2.0 type=require
depend fmri=pkg:/system/library/math@0.5.11-0.175.1.13.0.4.0 type=require
depend fmri=pkg:/system/library@0.5.11-0.175.1.15.0.4.2 type=require
depend fmri=pkg:/system/linker@0.5.11-0.175.1.13.0.1.2 type=require

The pkgdepend command will not pick up the dependency for PHP and the Apache module for PHP, so we need to add those manually:




depend fmri=pkg:/web/php-53@5.3.14-0.175.1.0.0.24.0 type=require
depend fmri=pkg:/web/server/apache-22/module/apache-php53@5.3.14-0.175.1.0.0.24.0 type=require

At this point, we need to create a nagios user and group as part of the package installation. The Image Packaging System has two such actions for performing that task. Here are the two lines that you need to add to nagios.p5m.dep.res:




group groupname=nagios
user username=nagios group=nagios

We now have our completed final package manifest that we will use during package publication: nagios.p5m.dep.res.

Publishing and Installing a Package

The next step that we will do is to take the compiled Nagios application and the package manifest and publish them to a package repository.

Creating a Package Repository

First, we will create a new ZFS data set to house our repository, and then we will use the pkgrepo create command to create the repository:




root@solaris:~# zfs create rpool/extra-software
root@solaris:~# zfs set mountpoint=/extra-software rpool/extra-software
root@solaris:~# pkgrepo create /extra-software
root@solaris:~# ls /extra-software
pkg5.repository

We need to set the publisher prefix of this repository using the pkgrepo set command:

root@solaris:~# pkgrepo -s /extra-software set publisher/prefix=extra-software

If we want to make this zone/machine the local repository and install on other zones/machines, we need to set up the repository server using the following commands:




root@solaris:~# svccfg -s application/pkg/server setprop \ 
pkg/inst_root=/extra-software
root@solaris:~# svccfg -s application/pkg/server setprop pkg/port=9001
root@solaris:~# svccfg -s application/pkg/server setprop \ 
pkg/readonly=false
root@solaris:~# svcadm enable application/pkg/server
root@solaris:~# svcs application/pkg/server
STATE          STIME    FMRI
online         Jan_28   svc:/application/pkg/server:default

Publishing the Package

Now that our repository has been created, let's publish our package. To do this, we use the pkgsend publish command and provide it the location of our repository, our PROTO area, and the final Image Packaging System package manifest.




root@solaris:~# pkgsend -s http://localhost:9001 publish -d PROTO nagios.p5m.dep.res

root@solaris:~# pkgrepo -s http://localhost:9001 refresh
root@solaris:~# pkgrepo -s http://localhost:9001 info
PUBLISHER      PACKAGES STATUS           UPDATED
extra-software 1        online           2013-08-11T21:01:31.353448Z

Installing the Package

Now that we have published our package, it's a good time to try to install the package on your system. You can either install it on localhost or on any zone that can connect to the localhost zone. You can set the publisher to http://localhost:9001 or to http://ip-address:9001. To do this, you need to add our new repository using the pkg set-publisher command:




root@solaris:~# pkg set-publisher -p http://ip-address-of-the-localrepo:9001

root@solaris:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
...
extra-software              origin   online F http://ip-address:9001/

And finally, use pkg install to install the package:




root@solaris:~# pkg install nagios
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No

DOWNLOAD                                PKGS         FILES    XFER (MB)   SPEED
Completed                                1/1       432/432      4.8/4.8    0B/s

PHASE                                          ITEMS
Installing new actions                       496/496
Updating package state database                 Done
Updating image state                            Done
Creating fast lookup database                   Done
root@solaris:~# pkg info nagios
          Name: nagios
       Summary: Nagios monitoring utility
   Description: Nagios is a host/service/network monitoring program
         State: Installed
     Publisher: extra-software
       Version: 4.0.2
 Build Release: 5.11
        Branch: 0
Packaging Date: Wed Jan 29 22:10:54 2014
          Size: 11.43 MB
          FMRI: pkg://extra-software/nagios@4.0.2,5.11-0:20140129T221054Z

To verify that this package works, we need to do a few things. First, let's configure Apache to be able to know about Nagios. Let's add the following lines to /etc/apache2/2.2/httpd.conf:




<IfModule alias_module>
    ScriptAlias /nagios/cgi-bin "/usr/local/nagios/sbin"
    Alias /nagios /usr/local/nagios/share
</IfModule>
<Directory "/usr/local/nagios/sbin/">
    Options ExecCGI
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
<Directory "/usr/local/nagios/share">
    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

Also let's enable the Apache service and check that it's online, as shown in Listing 11:




root@solaris:~# svcadm enable apache22
root@solaris:~# svcs apache22
STATE          STIME    FMRI
online          2:10:22 svc:/network/http:apache22

root@solaris:~# svcs nagios
STATE          STIME    FMRI
online          1:02:12 svc:/application/nagios:default

Listing 11

In Listing 11, we can see that our Nagios instance is up and running and being managed by the Service Management Facility.

Start a web browser and navigate to http://localhost/nagios; you should see something similar to Figure 1. If you don't see this, check any output from the command line for errors.

Figure 1. Screen that indicates Nagios was installed

Figure 1. Screen that indicates Nagios was installed

See Also

The following is a list of good resources where you can find more information about administering Oracle Solaris 11:

And here are some additional resources:

About the Authors

Joseph Balenzano is a principal software engineer in Oracle's ISV Engineering team. Joe's work is primarily focused on working with independent software vendors (ISVs) that specialize in cloud technology, virtualization, and system management software.

Edward Zhang is a software engineer in Oracle's ISV Engineering team. Edward's work is focused on Oracle Solaris system administration for ISVs.

Revision 1.0, 08/27/2014