Oracle Solaris Packaging for Administrators

by Glynn FosterPublished November 2013

Hands-On Labs of the System Admin and Developer Community of OTN

This lab explores what's required to create a new software package in Oracle Solaris 11 for Nagios.

Lab 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.

In this lab, we will explore what's required to create a new software package in Oracle Solaris 11 for Nagios. We will publish the new package to a package repository and install it on our system. In addition, we will also explore other methods to integrate this application into the operating system and take advantage of unique service availability and security features to make it a first-class citizen in Oracle Solaris 11.

Prerequisites

Familiarity with administering Oracle Solaris 11 systems, including the new packaging system is an advantage.

The Environment

You will be working on Oracle Solaris 11 virtual machines using Oracle VM VirtualBox. You can treat the Oracle Solaris 11 virtual machines as a bare-metal instance as far as this lab is concerned. The virtual machine has been preinstalled with Oracle Solaris 11.

For the purposes of this lab, we will use the login credentials shown in Table 1. The ouser account has been assigned the root role. Compared to other operating systems, Oracle Solaris 11 doesn't allow root to directly log in to the system for auditing reasons—instead, an individual user account must inherit the root role after login.

Table 1. Login Credentials
User ID Password
ouser Oracle 123
root solaris11

Lab Outline

The lab is divided into a number of different exercises that cover many of the basic administration tasks. Each exercise is independent of the others.

At the end of the exercises, additional tasks are provided in the event that you wish to focus on more-advanced administration. The steps to complete these additional tasks are not listed, so you will need to refer to the product documentation, online how-to guides, and manual pages, if necessary.

Table 2. Exercises
Exercise Name Topics Covered
1 Building Nagios
  • Installing GCC
  • Compiling Nagios
2 Creating a Package Manifest
  • Creating package metadata
  • Generating a file and directory list
  • Calculating dependencies
3 Publishing and Installing a Package
  • Creating a package repository
  • Publishing the package
  • Installing the package
4 Creating a Service Management Facility Service
  • Generating a manifest using the Service Management Facility of Oracle Solaris
  • Adding the Service Management Facility manifest to the package manifest
  • Republishing the package
  • Updating the package
5 Additional Tasks
  • Adding user and groups to the package
  • Creating a package archive for distribution
  • Creating a new package repository and transferring a package to it

Lab Goals

At the end of this lab, you will be familiar with basic package creation and publication in Oracle Solaris 11. In addition, you will understand the necessary steps to integrate applications more fully into the operating system, including adding a Service Management Facility service for application availability and the basics of adding more security to your application. You will be comfortable researching and performing future administrative tasks by referring to product documentation, manual pages, or online how-to articles, and you will know where to get help.

Exercise 1: Building Nagios

The first task we will do is to build Nagios. We will use the GCC software compiler to quickly install it into a PROTO area. A PROTO area is essentially an isolated location on the file system that allows us to easily collect the executables, libraries, documentation, and any other accompanying files into a package.

For this lab we'll take on the root role as follows:



ouser@solaris:~$ su -
Password: solaris11
root@solaris:~# 

Let's start by searching for the GCC compiler using the pkg search command:



ouser@solaris:~$ su -
Password: solaris11
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

We will use the developer/gcc-45 package to compile Nagios. So let's use the pkg install command to install it:



root@solaris:~# pkg install gcc-45
           Packages to install:  5
       Create boot environment: No
Create backup boot environment: No
            Services to change:  1

DOWNLOAD                       PKGS         FILES    XFER (MB)   SPEED
Completed                       5/5     1154/1154  111.3/111.3  1.5M/s

PHASE                                          ITEMS
Installing new actions                     1490/1490
Updating package state database                 Done 
Updating image state                            Done 
Creating fast lookup database                   Done 

Since Nagios is a PHP application, let's also install the PHP packages:

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

Download the Nagios application (version 3.5.0) from http://www.nagios.org. Then unpack the tarball:



root@solaris:~# tar -zxf files/nagios-3.5.0.tar.gz 
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

Let's now create a PROTO area that we will use to compile our application into:

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

Now we are ready to build our application. Nagios uses the standard configure command to check its environment, and we will use the default configuration to install into a /usr/local prefix.



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 3.5.0 03-15-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

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

Review the options above for accuracy.  If they look okay,
type 'make all' to compile the main program and CGIs.

root@solaris:~/nagios# 

Now that everything looks like it is configured correctly, we can start compiling this package with GCC using the gmake all target:



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
....
If you have questions about configuring or running Nagios,
please make sure that you:

     - Look at the sample config files
     - Read the documentation on the Nagios Library at:
           http://library.nagios.com

before you post a question to one of the mailing lists.
Also make sure to include pertinent information that could
help others help you.  This might include:

     - What version of Nagios you are using
     - What version of the plugins you are using
     - Relevant snippets from your config files
     - Relevant error messages from the Nagios log file

For more information on obtaining support for Nagios, visit:

       http://support.nagios.com

*************************************************************

Enjoy.

root@solaris:~/nagios#

Once everything has compiled, we now 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. In order for this to be completed successfully, we will need to create the nagios user and nagios group. We will use the useradd and groupadd commands to quickly do this:



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.

root@solaris:~/nagios#

Great; everything has been built and installed successfully. Now, we can look at the contents of our PROTO directory:



root@solaris:~/nagios# ls ../PROTO/usr/local/nagios
bin    etc    lib    sbin   share  var
root@solaris:~/nagios# ls ../PROTO/usr/local/nagios/bin/
nagios      nagiostats
root@solaris:~/nagios# cd ..
root@solaris:~#

We can see we have a number of directories in the PROTO area: bin, lib, sbin, share, and var. Within the bin directory, we have two executables: nagios and nagiostats. Now we could easily run these binaries from this directory, but in this hands-on lab, we will create a package using the Image Packaging System feature of Oracle Solaris and learn about package manifests.

Exercise 2: Creating a Package Manifest

Behind each package is a package manifest that describes how the package is assembled. It contains information about the package name, its version, package dependencies, and a list of files, directories, links, and other package contents. We will need to create a manifest for our Nagios package as part of the process of publishing to the repository.

We can take a look at a typical package manifest 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=41df24b2bc4fe0cc705642f7bcad54f8d96017d919865d12da22bbb42ab451b2d1e28c50c0d2b5a52b1e4
9e2732aeae9296216a3418c57fab6ed68624d492e68b8f8a4c728ec03f823608c2f95437ced3591a957fc8c9a69
fdbb3e5f0e45cf6a74b9341c97d727a60ef1f8be78a91114e378d84b530ae1b6565e15e060802f96fdbbea19823
f0e2c8e4dc2e5f6f82c6e9b85362c227704ecefc4460fc56dc947af2d872823138378e4c1d224012f135281c567
ef854b63cc75b43336142a5db78c0544f3e31cd101a347a55c25b77463431ce65db04f5821fe9e7d5e27718fb9b
e71373d110ca8eea4a82b5b3571684a6a182910b87e7f65c22d590a8e6523f9 version=0

There's quite a bit to take in here. Each line defines an action—whether it's setting some metadata about the package (such as name and description) or specifying files and directories to include in the package. While we create a package manifest for the Nagios package, we'll split the manifest up 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 the following 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 including the following:



set name=pkg.fmri value=nagios@3.5.0,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)

Let's quickly go through the parts of this initial manifest. The set action represents a way to set package attributes, such as the package version, summary, and description. We will set the package FMRI (fault managed resource indicator) to nagios@3.5.0,5.11-0, which indicates we're using Nagios 3.5.0 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 (that is, have a single package for both SPARC and x86). We will set variant.arch to a variable that we will substitute later.

Generating a File and Directory Listing

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 using the pkgsend generate command. We will also pipe it through the pkgfmt command to make the output nicer, and we'll put it into the nagios.p5m.gen file, as shown in Listing 1:



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
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 1

In Listing 1, we see a few new actions: file and dir. These specify the package contents and their user and group ownership and permissions. We will 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. We can do this by adding another a few lines to our transform:


<transform dir path=usr/local/nagios/var$ -> set owner nagios>
<transform dir path=usr/local/nagios/var$ -> set group nagios>
<transform dir path=usr/local/nagios/var/rw$ -> set owner nagios>
<transform dir path=usr/local/nagios/var/rw$ -> set group nagios>
<transform dir path=usr/local/nagios/var/spool/checkresults$ -> set owner nagios>
<transform dir path=usr/local/nagios/var/spool/checkresults$ -> set group nagios>

If we were planning on installing Nagios into /usr/bin, good packaging practices for Oracle Solaris 11 dictate that we go through this list to check which directories are being installed by Nagios and which are already provided as part of a default system installation. The directories that have been provided already 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. Therefore, we will need to remove the /usr directory 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>

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



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@3.5.0,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=i386
....
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/spool owner=root group=bin mode=0755
dir  path=usr/local/nagios/var/spool/checkresults owner=nagios group=nagios mode=0775

Listing 2

You'll see in Listing 2 that we have merged these two files. Notice how we now have a value of i386 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 the package to try to detect what dependencies might exist. It does this by detecting the file type, whether it's a script or an executable.

If the file is a script, it will check the #! line at the start of the script to identify whether it's a Perl, Python, or Bash script or some other type of shell script. If the file is an executable, it will look at the 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 generate command, and we pass it in the location of our PROTO area, as shown in Listing 3:



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 
.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 3

We can see in Listing 3 that we have generated a number of lines starting with the depend action. If you look closely at the lines we printed, you can see the pkg.debug.depend.file value is libc.so.1 or libsocket.so.1, so these are 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 caused these dependencies 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, as shown in Listing 4:



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=root group=bin mode=0775
dir  path=usr/local/nagios/var/archives owner=root group=bin mode=0775
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
depend fmri=pkg:/system/library/math@0.5.11-0.175.1.0.0.19.0 type=require
depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.24.2 type=require
depend fmri=pkg:/system/linker@0.5.11-0.175.1.0.0.24.2 type=require

Listing 4

In the last three lines of Listing 4, we can see that we have successfully resolved the dependencies to just three packages: system/library/math, system/library, and system/linker. We now have our completed our final package manifest, nagios.p5m.dep.res, which we will use during package publication.

Exercise 3: Publishing and Installing a Package

The next step is to take our compiled Nagios application and our package manifest and publish them to a package repository. Let's quickly create a new ZFS data set to house our repository, and then use the pkgrepo create command to create it:



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 will 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

Now that our repository is 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 IPS package manifest.



root@solaris:~# pkgsend -s /extra-software publish -d PROTO nagios.p5m.dep.res 
pkg://extra-software/nagios@3.5.0,5.11-0:20130811T210125Z
PUBLISHED
root@solaris:~# pkgrepo -s /extra-software refresh
root@solaris:~# pkgrepo -s /extra-software info
PUBLISHER      PACKAGES STATUS           UPDATED
extra-software 1        online           2013-08-11T21:01:31.353448Z

Now that we have published our package, let's try to install it onto our system. To do this, we will need to add our new repository using the pkg set-publisher command:

root@solaris:~# pkg set-publisher -g /extra-software extra-software

root@solaris:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release
extra-software              origin   online F file:///extra-software/

And, finally, we use pkg install to install our 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       373/373      1.8/1.8    0B/s

PHASE                                          ITEMS
Installing new actions                       403/403
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: 3.5.0
 Build Release: 5.11
        Branch: 0
Packaging Date: August  8, 2013 02:24:32 AM 
          Size: 4.54 MB
          FMRI: pkg://extra-software/nagios@3.5.0,5.11-0:20130811T210125Z

To verify that this package works, we'll need to do a few things. First, let's configure the Apache HTTP server to know about Nagios by adding 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 5:



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

Listing 5

Finally, we can run the Nagios command from the /usr/local/nagios/bin directory using a sample configuration file, as follows:



root@solaris:~# /usr/local/nagios/bin/nagios \
/usr/local/nagios/etc/nagios.cfg

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

Figure 1

Figure 1. Successful installation of the Nagios package.

Exercise 4: Creating a Service Management Facility Service

It would be nice to be able to manage Nagios with the Service Management Facility. In Listing 5, we used the svcadm enable command to start the Apache instance. This gives us the benefit that if the Apache instance dies for any reason, the Service Management Facility will automatically restart it. Let's do the same 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, usually located in /lib/svc/manifest. While we could write a manifest manually, we will use the svcbundle command to generate a simple one for us.

svcbundle 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 to deal with a common set of cases that are detailed in the manual page, including automatically starting the service by default.

We can create a Service Management Facility manifest as follows:



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 (2013-Aug-12 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>

The next step is to integrate this service definition into our package. We will first need to generate the equivalent of /lib/svc/manifest/site within our PROTO area, and then copy the nagios.xml file there:



root@solaris:~# mkdir -p PROTO/lib/svc/manifest/site
root@solaris:~# cp nagios.xml PROTO/lib/svc/manifest/site

Once we have done this, we need to go back through generating a new package manifest. You might need to refer to previous sections for how to do this.

First of all, let's modify nagios.mog to update the version number so we can simply use pkg update nagios to install our new version:

set name=pkg.fmri value=nagios@3.5.0,5.11-1

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 add a new transform to handle our Service Management Facility manifest, as shown in Listing 6:



<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 6

The last transform in Listing 6 finds any file within the lib/svc/manifest directory that has a .xml extension 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's service framework.

Once we have done this, let's generate our final Image Packaging System manifest again:



root@solaris:~# pkgsend generate PROTO | pkgfmt > nagios.p5m.gen
root@solaris:~# pkgmogrify -DARCH=`uname -p` nagios.p5m.gen nagios.mog | pkgfmt > nagios.p5m.mog
root@solaris:~# pkgdepend generate -md PROTO nagios.p5m.mog > nagios.p5m.dep
root@solaris:~# pkgdepend resolve -m nagios.p5m.dep
root@solaris:~# pkgsend -s /extra-software/ publish -d PROTO nagios.p5m.dep.res
pkg://extra-software/nagios@3.5.0,5.11-1:20130812T005707Z
PUBLISHED

And, finally, we can install the new version, as shown in Listing 7:

root@solaris:~# pkg update nagios

            Packages to update:   1
       Create boot environment:  No
Create backup boot environment: Yes
            Services to change:   1

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

PHASE                                          ITEMS
Installing new actions                           3/3
Updating modified actions                        2/2
Updating package state database                 Done 
Updating package cache                           1/1 
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: 3.5.0
 Build Release: 5.11
        Branch: 1
Packaging Date: August 12, 2013 12:57:07 AM 
          Size: 4.55 MB
          FMRI: pkg://extra-software/nagios@3.5.0,5.11-1:20130812T005707Z

Listing 7

Notice in Listing 7 how the update required only one additional file to be installed for the Service Management Facility manifest. The Image Packaging System does not uninstall and reinstall the package.

Let's now check to see whether our service has been registered:



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

Our Nagios instance is up and running and managed by Service Management Facility.

Exercise 5: Additional Tasks

Congratulations for completing this hands-on lab! With luck, you've had a chance to work through most of the sections, and you are feeling confident enough to take on some of the following additional tasks.

  • When we were initially packaging Nagios, we manually created a nagios user and group. While our package worked well on the system on which we developed the package, we will need to provide that configuration on other target systems. Fortunately this is easy with the Image Packaging System. Try to see if you can include the nagios user and group within the Image Packaging System package to ensure they are created for new installations.
  • The Image Packaging System supports the concept of package archives, which are standalone files that can be distributed through, say, USB drives. Create a package archive of the Nagios package for distribution.
  • Administrators can easily transfer package content between repositories. Create a new package repository and transfer the Nagios package between /extra-software and your new repository.

See Also

The following is a list of good resources about administering Oracle Solaris 11:

About the Author

Glynn Foster is a principal product manager for Oracle Solaris and works on technology areas that include the Image Packaging System and Service Management Facility. Glynn joined Oracle in 2010 as part of the Sun Microsystems acquisition.

Revision 1.0, 11/13/2013