Advanced Administration with the Image Packaging System (IPS) on Oracle Solaris 11

November 2011, July 2018

by Glynn Foster

Take a deeper look at advanced IPS to learn how to determine package dependencies, explore manifests, perform advanced searches, and analyze the state of your system.


Oracle Solaris 11 takes a new approach to lifecycle and package management to greatly simplify the process of managing system software helping to reduce the risk of operating system maintenance, including reducing unplanned and planned downtime. With Image Packaging System (IPS), administrators can install and update software from locally connected or remote software package repositories using a much-improved and modernized process.

If you'd like to download software, participate in forums, and get access to other technical how-to goodies in addition to content like this, become an OTN member. No spam!

In another article, Introducing the Basics of Image Packaging System (IPS) on Oracle Solaris 11, we covered the basics of administration including how to install and uninstall packages, how to discover basic information about packages installed on the system and in the repository, and how to update a system.

This article covers advanced topics for using IPS, including detailing different package dependencies, exploring package manifests, using advanced search queries, browsing logs, and recovering from unexpected events. To learn more about IPS, check out a variety of content at the Lifecycle Management Technology Spotlight page on Oracle Technology Network. Also see the Oracle Solaris 11 Cheat Sheet for Image Packaging System.

Understanding Package Dependencies

In many cases, one software package depends on another package. For example, one package might require functionality that is in a second package in order to function or install correctly. These relationships, or dependencies, between packages are important for automating package installation operations and for upgrading system software to known and well-tested states. IPS supports a number of different relationships between packages, some of which are listed in Table 1.

Table 1. Package Relationships
Dependency Description
require This dependency is required. A package cannot be installed if any of its required dependencies cannot be satisfied.
optional If this dependency is present on the system already then it must be at a specified version level or greater.
exclude This dependency enforces a restriction such that a package cannot be installed if the specified package is present at the specified version level or greater.
incorporate This dependency is optional, but the version range has both a lower and an upper bound, allowing only further dot-separated integers to be added to the existing sequences.
conditional This dependency is required only if another predicate package is installed on the system. This is often used to allow packages to provide support for features (such as X11 or language bindings) only if the features are already present on the system.
group This dependency is required unless the package is on the avoid list, in which case, the system will try to avoid installing this package. However, if another package requires this dependency, it will be installed regardless of whether it is on the avoid list.
parent This dependency is used to ensure that global zones and non-global zones are kept in sync for all kernel components and any software that spans the zone boundary.

Let's take a look at how these relationships are expressed by IPS by looking at how packages are described in what's known as a package manifest.

Exploring Package Manifests

A package manifest describes how a package is assembled and provides basic information about the package (such as the name, version, description, categorization, and so on), what files the package includes, and what other packages or services the package relies on to meet its dependencies. While many package commands filter this information into a presentable form, it is sometimes useful to look at the package manifest directly using the pkg contents -m command, as shown in Listing 1.

Listing 1: Looking at the Package Manifest
# pkg contents -m gzip
set name=pkg.fmri value=pkg://solaris/compress/gzip@1.8,5.11-11.4.0.0.1.10.0:20180702T152838Z
set name=variant.arch value=i386 value=sparc
set name=com.oracle.info.description value="GNU zip"
set name=com.oracle.info.tpno value=28039
set name=info.source-url value=https://ftp.gnu.org/gnu/gzip/gzip-1.8.tar.gz
set name=com.oracle.info.version value=1.8
set name=pkg.description value="The GNU Zip (gzip) compression utility"
set name=org.opensolaris.arc-caseid value=PSARC/1999/555
set name=com.oracle.info.consolidation.repository-changeset value=75d67fe8de04
set name=pkg.summary value="GNU Zip (gzip)"
set name=info.upstream-url value=https://www.gnu.org/software/gzip
set name=com.oracle.info.consolidation.repository-url value=https://github.com/oracle/solaris-userland.git
set name=org.opensolaris.consolidation value=userland
set name=info.classification value="org.opensolaris.category.2008:Applications/System Utilities"
set name=com.oracle.info.name value=gzip
set name=pkg.tmp.incorporate value=consolidation/userland/userland-incorporation
depend fmri=pkg:/runtime/python-27@2.7.14-11.4.0.0.1.9.0 type=require
depend fmri=pkg:/system/xopen/xcu4@11.4-11.4.0.0.1.9.1 type=require
depend fmri=pkg:/system/library@11.4-11.4.0.0.1.9.1 type=require
depend fmri=pkg:/shell/bash@4.4.19.19-11.4.0.0.1.9.0 type=require
file a9c8c18c7167b2ea86b580f0413d881f89644617 chash=75937161849f5a60a9fe8b7949b9cc0f32bde38d elfarch=sparc \
elfbits=64 elfhash=8f1c0b6e63fca885eea02bced751f9e794ae03ef group=bin mode=0555 owner=root path=usr/bin/gzip \
pkg.content-hash=gelf:sha512t_256:ea15eadf4d66c20f096272a7e60879d1b464cbfaf5d3d9c5a08190819b589848 \
pkg.content-hash=gelf.unsigned:sha512t_256:a0bcb185f82ad59033b4e4e49662dfb171f31ac538d753897a61fdd90f0b87f8 \
pkg.content-hash=file:sha512t_256:f376714517d82e9ca2e7fa3c3947a916b9003871cc63fb2eae0b249fc4f000ba \
pkg.content-hash=gzip:sha512t_256:ada909316b9de10361f3de48d31b4792c3bd97f9e080497dea95265a3a9e1097 \
pkg.csize=112209 pkg.size=269064 variant.arch=sparc
file de0aece1c7a7eb076367b70e794c26ae07e6e211 chash=a5ae73f0421f0f5a5e7188b3271d491c8e88731d \
facet.doc.man=all group=bin mode=0444 owner=root path=usr/share/man/man1/gzdiff.1 \
pkg.content-hash=file:sha512t_256:ad558e05c841b77c2c966e5df8fa676bca52a850112fd1a8fca02f53780e7e8b \
pkg.content-hash=gzip:sha512t_256:dcb3bd3b4c0326572d8227fa4022a4f2115d8924f0b1768f259949e26aa3e81a \
pkg.csize=803 pkg.size=1564
file bac116819b16143907ba95311a74da8f7c8ead1b chash=ca69eb2e0def78aaa8a93f5b028672db223a2157 \
group=bin mode=0555 owner=root path=usr/bin/gznew \
pkg.content-hash=file:sha512t_256:3d685ebe1f0f6cfd880b8f3f7f1f7fd82d3065781f6ffa07b06a36ea1be0aad3 \
pkg.content-hash=gzip:sha512t_256:5be71819bafd706e0fd822eef0ddf5953b2384a1dccee62c758cd072eb967877 \
pkg.csize=1816 pkg.size=4441
file a2a356f1f3077d794403e109a5cc1515e22bcbfa chash=3144e0c915a919d590869b2626c7c80b320190f8 \
group=bin mode=0555 owner=root path=usr/bin/gzmore \
pkg.content-hash=file:sha512t_256:1964cdc0013c6532a08706056e7aad134c71e38280d1111dac4d630804cae131 \
pkg.content-hash=gzip:sha512t_256:c4adcb66bb61161e3198f20e42bd93c205379fa74b927e4d598fed41d60f09e3 \
pkg.csize=940 pkg.size=1819
....

Each line within the manifest is called an action. Actions describe a small part of the overall package. The first part of each line describes the action type: set, license, depend, dir, file, and so on. Midway down the manifest, we can see how package dependencies are expressed. In this case, the package has four dependencies: one for /runtime/python-27, one for /system/xopen/xcu4, one for pkg:/shell/bash, and one for pkg:/system/library, as shown below.

...
depend fmri=pkg:/runtime/python-27@2.7.14-11.4.0.0.1.9.0 type=require
depend fmri=pkg:/system/xopen/xcu4@11.4-11.4.0.0.1.9.1 type=require
depend fmri=pkg:/system/library@11.4-11.4.0.0.1.9.1 type=require
depend fmri=pkg:/shell/bash@4.4.19.19-11.4.0.0.1.9.0 type=require
...

Notice that we include two versions of the /usr/bin/gzip binary executable for different architectures, SPARC and x86, as shown in Listing 2.

Listing 2: Specifying SPARC and x86 Binary Executables in the Package Manifest
...
file a9c8c18c7167b2ea86b580f0413d881f89644617 chash=75937161849f5a60a9fe8b7949b9cc0f32bde38d elfarch=sparc \
elfbits=64 elfhash=8f1c0b6e63fca885eea02bced751f9e794ae03ef group=bin mode=0555 owner=root path=usr/bin/gzip \
pkg.content-hash=gelf:sha512t_256:ea15eadf4d66c20f096272a7e60879d1b464cbfaf5d3d9c5a08190819b589848 \
pkg.content-hash=gelf.unsigned:sha512t_256:a0bcb185f82ad59033b4e4e49662dfb171f31ac538d753897a61fdd90f0b87f8 \
pkg.content-hash=file:sha512t_256:f376714517d82e9ca2e7fa3c3947a916b9003871cc63fb2eae0b249fc4f000ba \
pkg.content-hash=gzip:sha512t_256:ada909316b9de10361f3de48d31b4792c3bd97f9e080497dea95265a3a9e1097 \
pkg.csize=112209 pkg.size=269064 variant.arch=sparc
...
file 2f83a5eac9e8c808da3587914909f9667941318d chash=b1beb2c1301436beaef073adb638ff13df339fcf elfarch=i386 \
elfbits=64 elfhash=aa6c711f8eb8b876f226fafda039c7977fefd634 group=bin mode=0555 owner=root path=usr/bin/gzip \
pkg.content-hash=gelf:sha512t_256:3d66e7188f2e1466b634d26283690d7893d9267f9cab412c3a00bebbf6cdbb43 \
pkg.content-hash=gelf.unsigned:sha512t_256:5daa3cb8f9bd3214b8fb3092002eab97e3024419965ea54cf83d9638030050b3 \
pkg.content-hash=file:sha512t_256:cde529ebc6398dc5b8e40ca0894b677cd3771aadfa875e7682bb41982c8542a1 \
pkg.content-hash=gzip:sha512t_256:dc4ab30dbb1cf1fdf6edf637240db065325e5ab4b9cfc9033922bcf0bea68c1a \
pkg.csize=91622 pkg.size=273096 variant.arch=i386
...

The ability to include support for different architectures in a single package is a key IPS feature called variants. Depending on your system architecture, IPS will know which version to install on your system. From a development and administration point of view, this feature drastically reduces the work needed to maintain separate software packages and keep them in sync, and it lowers the cost of storage since you need only one version of the architecture-independent portion of the package. More details about package manifests and how they are created are covered in another article, How to Create and Publish Packages to an IPS Repository on Oracle Solaris 11.

Now that we've had a quick look at package manifests, let's look at some complicated search examples.

Advanced Searching

The pkg contents and pkg search commands are used to view and search for package content. These two commands are related and can be used to provide similar information, especially when piped to other commands for filtering.

Quite often, before you install a package, it's useful to see what packages will be installed due to dependency relationships specified in the package you plan to install. Let's look at a concrete example using the pkg contents command. We will use the -r option to give us results from the remote repository, since we want to query uninstalled packages rather than installed packages.

# pkg contents -r -o fmri,type -t depend php-71
FMRI                                                         TYPE
pkg:/compress/bzip2@1.0.6-11.4.0.0.1.9.0                     require
pkg:/database/berkeleydb-5@5.3.21-11.4.0.0.1.9.0             require
pkg:/image/library/libjpeg@6.0.2-11.4.0.0.1.9.0              require
pkg:/image/library/libpng14@1.4.20-11.4.0.0.1.9.0            require
pkg:/library/gmp@6.1.2-11.4.0.0.1.9.0                        require
pkg:/library/icu@11.4-11.4.0.0.1.9.0                         require
pkg:/library/libxml2@2.9.5-11.4.0.0.1.9.0                    require
pkg:/library/libxslt@1.1.28-11.4.0.0.1.9.0                   require
pkg:/library/ncurses@6.0.0.20170708-11.4.0.0.1.9.0           require
pkg:/library/readline@6.3-11.4.0.0.1.9.0                     require
pkg:/library/security/openssl@1.0.2.15-11.4.0.0.1.9.0        require
pkg:/library/spell-checking/enchant@1.6.0-11.4.0.0.1.9.0     require
pkg:/library/zlib@1.2.11-11.4.0.0.1.9.0                      require
pkg:/shell/ksh93@93.21.1.20120801-11.4.0.0.1.9.0             require
pkg:/system/library/freetype-2@2.9.1-11.4.0.0.1.9.0          require
pkg:/system/library/gcc/gcc-c++-runtime@7.3.0-11.4.0.0.1.9.0 require
pkg:/system/library/gcc/gcc-c-runtime@7.3.0-11.4.0.0.1.9.0   require
pkg:/system/library/math@11.4-11.4.0.0.1.4.0                 require
pkg:/system/library@11.4-11.4.0.0.1.9.1                      require
pkg:/system/management/snmp/net-snmp@5.7.3-11.4.0.0.1.9.0    require
pkg:/system/network/ldap/openldap@2.4.45-11.4.0.0.1.9.0      require
pkg:/text/gnu-sed@4.4-11.4.0.0.1.9.0                         require
pkg:/text/tidy@5.4.0-11.4.0.0.1.9.0                          require
pkg:/web/curl@7.60.0-11.4.0.0.1.9.0                          require
pkg:/web/php-common                                          require
pkg:/x11/library/libxpm@3.5.12-11.4.0.0.1.9.0                require

The output shows a list of packages that PHP depends on (installed or not installed) in the first column, represented by the value of the fmri attribute from the package manifest, and a list of the dependency types in the second column, represented by the value of the type attribute from the package manifest.

In this case, we get a list of all dependencies that are required in order to successfully install this package. Also note that we used the -r flag to enable a query on the repository rather than to query locally, since we do not yet have the PHP package installed on the system. A similar output can be displayed using pkg search, as follows:

# pkg search -o search.match,search.match_type 'web/php-71@:depend::'
SEARCH.MATCH                                                 SEARCH.MATCH_TYPE
pkg:/compress/bzip2@1.0.6-11.4.0.0.1.9.0                     require
pkg:/database/berkeleydb-5@5.3.21-11.4.0.0.1.9.0             require
pkg:/image/library/libjpeg@6.0.2-11.4.0.0.1.9.0              require
pkg:/image/library/libpng14@1.4.20-11.4.0.0.1.9.0            require
pkg:/library/gmp@6.1.2-11.4.0.0.1.9.0                        require
pkg:/library/icu@11.4-11.4.0.0.1.9.0                         require
pkg:/library/libxml2@2.9.5-11.4.0.0.1.9.0                    require
pkg:/library/libxslt@1.1.28-11.4.0.0.1.9.0                   require
pkg:/library/ncurses@6.0.0.20170708-11.4.0.0.1.9.0           require
pkg:/library/readline@6.3-11.4.0.0.1.9.0                     require
pkg:/library/security/openssl@1.0.2.15-11.4.0.0.1.9.0        require
pkg:/library/spell-checking/enchant@1.6.0-11.4.0.0.1.9.0     require
pkg:/library/zlib@1.2.11-11.4.0.0.1.9.0                      require
pkg:/shell/ksh93@93.21.1.20120801-11.4.0.0.1.9.0             require
pkg:/system/library@11.4-11.4.0.0.1.9.1                      require
pkg:/system/library/freetype-2@2.9.1-11.4.0.0.1.9.0          require
pkg:/system/library/gcc/gcc-c++-runtime@7.3.0-11.4.0.0.1.9.0 require
pkg:/system/library/gcc/gcc-c-runtime@7.3.0-11.4.0.0.1.9.0   require
pkg:/system/library/math@11.4-11.4.0.0.1.4.0                 require
pkg:/system/library@11.4-11.4.0.0.1.9.1                      require
pkg:/system/management/snmp/net-snmp@5.7.3-11.4.0.0.1.9.0    require
pkg:/system/network/ldap/openldap@2.4.45-11.4.0.0.1.9.0      require
pkg:/text/gnu-sed@4.4-11.4.0.0.1.9.0                         require
pkg:/text/tidy@5.4.0-11.4.0.0.1.9.0                          require
pkg:/web/curl@7.60.0-11.4.0.0.1.9.0                          require
pkg:/web/php-common                                          require
pkg:/x11/library/libxpm@3.5.12-11.4.0.0.1.9.0                require

The pkg contents and pkg search commands are related; both are used to query the system for the contents of packages. The contents command displays actions in one or more packages, filtering the output based on the options you chose. The search command approaches the query from the other direction, looking for packages that contain a user-supplied token.

In the first column of this example (represented by the search package name match), we have a list of packages, and in the second column (represented by the match type), we have a list of dependency types.

The search command uses a field or structured query that takes the form of pkg_name:action_type:key:token. In this case, we use web/php-71@ as the package name since we want to search for pkg:/web/php-71 and not other matches, for example, pkg:/web/php-71/extensions/php-pear. The action_type in this case is depend.

We leave the other two fields blank, because we want to search for all dependencies. If we wanted to be more specific, we could specify require as our key and set *zlib as our token, for example, to determine whether pkg:/web/php-71 has a required dependency on pkg:/library/zlib (which it does).

As another example, let's do the reverse and see what installed packages depend on pkg:/library/libxml2 with a required dependency. Let's continue to use the pkg search command, as shown in Listing 3.

Listing 3: Using Search to Determine Dependencies for Installed Packages
# pkg search -l -o pkg.name 'depend:require:library/libxml2'
PKG.NAME
system/management/ilomconfig
print/cups/filter/foomatic-db-engine
system/zones
system/core-os
system/library
system/resource-mgmt/resource-pools
system/library/hmp-libs
library/python/libxsl-27
system/fault-management
system/management/raidconfig
data/docbook/docbook-style-xsl
system/management/rad/client/rad-c
network/dns/bind
system/management/rad
security/compliance/openscap
service/network/dns/bind
data/docbook/docbook-dtds
library/python/lxml-34
system/ksplice
library/python/libxml2-27
web/server/apache-24
system/management/hwmgmtd
library/libarchive
library/libxslt
system/ldoms/ldomsmanager
system/storage/nvme-utilities
library/python/lxml-27
library/python/libxml2-34
system/management/fwupdate
data/shared-mime-info
diagnostic/wireshark/wireshark-common
system/management/hwmgmtcli

In this example, we use the -l flag to search for installed packages. Many more searches are possible with IPS, and they can be referenced in the man pages or formal documentation.

Analyzing the State of your System

If something unexpected happens, it might be necessary to analyze the state of your system a little further. There are three additional IPS commands that allow you to check a history log of all package operations performed on a given system, check the validity of a package or set of packages installed on a system and, if there are problems, fix them.

To check the history log of all package operations, use the pkg history command, as shown in Listing 4.

Listing 4: Checking the History Log of All Package Operations
# pkg history
START                    OPERATION                CLIENT             OUTCOME
2018-06-18T12:40:27      set-property             transfer module    Succeeded
2018-06-18T12:40:27      image-create             transfer module    Succeeded
2018-06-18T12:40:28      add-publisher            transfer module    Succeeded
2018-06-18T12:40:28      refresh-publishers       transfer module    Succeeded
2018-06-18T12:40:43      rebuild-image-catalogs   transfer module    Succeeded
2018-06-18T12:40:47      set-property             transfer module    Succeeded
2018-06-18T12:40:47      set-property             transfer module    Succeeded
2018-06-18T12:40:48      install                  transfer module    Succeeded
2018-06-18T12:47:49      update-publisher         transfer module    Succeeded
2018-06-18T12:51:16      revert                   pkg                Succeeded
2018-06-27T19:19:31      uninstall                transfer module    Succeeded
2018-06-27T19:20:00      fix                      pkg                Succeeded
2018-06-27T19:23:17      set-property             pkg                Succeeded
2018-06-27T19:29:55      refresh-publishers       pkg                Succeeded
2018-06-27T19:29:55      update-publisher         pkg                Succeeded
2018-06-27T19:30:08      rebuild-image-catalogs   pkg                Succeeded
2018-07-10T20:10:24      update                   pkg                Succeeded
2018-07-10T20:10:26      refresh-publishers       pkg                Succeeded
2018-07-10T20:10:42      rebuild-image-catalogs   pkg                Succeeded
2018-07-19T19:40:54      install                  pkg                Succeeded
2018-07-19T19:53:10      fix                      pkg                Succeeded
2018-07-19T20:02:02      rebuild-index            pkg                Succeeded

In the output, the order is by date, and the output lists the operation that was done and who called the operation (in this case, transfer module is during the installation of this system and pkg is the command line client). Additionally, we can easily search through the history using a set of date stamps (in this case, all package commands between July 10, 2018 and July 20, 2018), as follows:

# pkg history -t 2018-07-10T00:00:00-2018-07-20T00:00:00
START                    OPERATION                CLIENT             OUTCOME
2018-07-10T20:10:24      update                   pkg                Succeeded
2018-07-10T20:10:26      refresh-publishers       pkg                Succeeded
2018-07-10T20:10:42      rebuild-image-catalogs   pkg                Succeeded
2018-07-19T19:40:54      install                  pkg                Succeeded
2018-07-19T19:53:10      fix                      pkg                Succeeded
2018-07-19T20:02:02      rebuild-index            pkg                Succeeded

It is also possible to output some different column headers using pkg history - o including, among other options, the time it took for the packaging operation to complete, what boot environment it was applied to, and the user who started the operation.

# pkg history -o user,be,time,command -t 2018-07-10T00:00:00-2018-07-20T00:00:00
USER      BE                  TIME      COMMAND
root      solaris             0:07:30   /usr/bin/pkg update
root      solaris             0:00:22   /usr/bin/pkg update
root      solaris             0:00:05   /usr/bin/pkg update
root      solaris-1           0:01:14   /usr/bin/pkg install git
root      solaris-1           0:00:30   /usr/bin/pkg fix system/file-system/smb
root      solaris-1           0:00:58   /usr/bin/pkg rebuild-index

While ZFS snapshots and clones are a great way to recover from errors in the system, IPS also provides the facility to validate the installation of packages on a system. Using the pkg verify command, you can check a specific package or groups of packages:

# pkg verify -v gzip
PACKAGE                                                                 STATUS
pkg://solaris/compress/gzip                                                 OK

In this case, we use the -v flag to get more information on the command line. If the -v flag is not used, there is no output if the packages are validated successfully.

As an example, let's deliberately make some modifications to /usr/bin/gzip by writing 1024 bytes on top of it and try the verification process again:

# mkfile 1024 /usr/bin/gzip
# pkg verify -v gzip
PACKAGE                                                                 STATUS
pkg://solaris/compress/gzip                                              ERROR
        file: usr/bin/gzip
                ERROR: Mode: 0600 should be 0555
                ERROR: Unexpected Exception: Elf error 0

IPS detected an incorrect permission on the file /usr/bin/gzip and raised an exception due to not being able to validly check the ELF headers for the binary executable. Fortunately for us, we can quickly fix the problem using the pkg fix command, as shown in Listing 5.

Listing 5: Fixing a Package Problem
# pkg fix gzip
               Packages to fix:   1
       Create boot environment:  No
Create backup boot environment: Yes

Repairing: pkg://solaris/compress/gzip@1.8,5.11-11.4.0.0.1.10.0:20180702T152838Z
PACKAGE                                                                 STATUS
pkg://solaris/compress/gzip                                              ERROR
        file: usr/bin/gzip
                ERROR: Mode: 0600 should be 0555
                ERROR: Unexpected Exception: Elf error 0
PHASE                                          ITEMS
Updating modified actions                        1/1
Updating package state database                 Done 
Updating package cache                           0/0 
Updating image state                            Done 
Creating fast lookup database                   Done 
Updating package cache                           1/1

As shown in the output, IPS quickly downloads the appropriate content and repairs the package. In this case, since the content was cached on the system, IPS did not have to download anything.

Summary

The Oracle Solaris 11 Image Packaging System is a major advancement in software management providing an integrated user experience and improved safety for system updates. IPS takes much of the complexity out of managing Oracle Solaris by providing improved automation and auditing, allowing administrators to flexibly manage multiple application environments across virtualized and non-virtualized instances of the operating system.

For More Information

Here are some additional resources:

Revision 1.1, 07/20/2018
Revision 1.0, 11/02/2011