How to Publish Your Own IPS Packages

Welcome back! This is the last of my three-part mini-series on IPS, the Image Packaging System, for Oracle Solaris 11. The topic of “How to Publish Your Own IPS Packages” builds upon the structure and information contained in Part 1 and Part 2. In Part 3, I will cover how to build your own IPS package, create a second local IPS repository for your own packages, publish the package to your repository, and test the pkg install process for the package.

As background information, we already have a system hosting the Oracle Solaris 11 (snv_167) IPS repository with an AI service properly configured. We will not need the AI service for this topic. However, keep in mind it is possible to customize your XML based AI manifest files to use the new IPS repository we will create here to automatically install your own IPS packages during a new system install. Also, remember we have already created a top-level ZFS file system, rpool/IPS mounted at /IPS as a step in Part 1. We begin by creating a new ZFS file system as a home for our packaging playground and for our new IPS repository.

# zfs list -r rpool/IPS
NAME                USED  AVAIL  REFER  MOUNTPOINT
rpool/IPS          5.88G  7.72G    32K  /IPS
rpool/IPS/s11-167  5.88G  7.72G  5.88G  /IPS/s11-167
# zfs create rpool/IPS/packaging
# zfs create rpool/IPS/myrepo
# zfs list -r rpool/IPS 
NAME                  USED  AVAIL  REFER  MOUNTPOINT
rpool/IPS            5.88G  7.72G    35K  /IPS
rpool/IPS/myrepo       31K  7.72G    31K  /IPS/myrepo
rpool/IPS/packaging    31K  7.72G    31K  /IPS/packaging
rpool/IPS/s11-167    5.88G  7.72G  5.88G  /IPS/s11-167
# 

Now, we will go ahead and create our own IPS repository using the name of mycompany and the location of /IPS/myrepo. We will also set our repository to have it’s own port for remote access via HTTP, so as not to interfere with our default IPS repository. We do this by first verifying the port on our default repository and then creating our new one.

# svccfg -s pkg/server listprop pkg/port 
pkg/port  count    10000
# pkgrepo create /IPS/myrepo 
# pkgrepo set -s /IPS/myrepo publisher/prefix=mycompany
# svccfg -s pkg/server add mycompany
# svccfg -s pkg/server:mycompany addpg pkg application 
# svccfg -s pkg/server:mycompany setprop pkg/port=10001
# svccfg -s pkg/server:mycompany setprop pkg/inst_root=/IPS/myrepo 
# svccfg -s pkg/server:mycompany setprop pkg/readonly=false
# svcadm refresh pkg/server:mycompany
# svcadm enable pkg/server:mycompany
# svcs pkg/server
STATE          STIME    FMRI
online         Aug_09   svc:/application/pkg/server:default
online         16:54:41 svc:/application/pkg/server:mycompany
# 

To keep our packaging process and naming schemes simple we will now create a sub directory called mypackage and create the files we need for our package. For mypackage, I am using the contents of an old package I created in Perl for some Oracle VM Server for SPARC (LDom) automation. However, you may use any type of files, symbolic links, or directories you need for your own package.

# zfs list -r rpool/IPS
NAME                  USED  AVAIL  REFER  MOUNTPOINT
rpool/IPS            5.88G  7.72G    35K  /IPS
rpool/IPS/myrepo     42.5K  7.72G  42.5K  /IPS/myrepo
rpool/IPS/packaging    31K  7.72G    31K  /IPS/packaging
rpool/IPS/s11-167    5.88G  7.72G  5.88G  /IPS/s11-167
# mkdir /IPS/packaging/mypackage
# cd /IPS/packaging/mypackage/
# mv /var/tmp/mypackage.tar ./
# tar xf mypackage.tar 
# rm mypackage.tar 

Now that we’ve painstakingly developed all of our code, created the directory structures, and placed them into our mypackge package directory, we need to create our package manifest using the pkgsend generate command.

# cd /IPS/packaging/
# pkgsend generate /IPS/packaging/mypackage > \
  /IPS/packaging/mypackage.manifest.1
# cat /IPS/packaging/mypackage.manifest.1 
dir group=bin mode=0755 owner=root path=etc
dir group=bin mode=0755 owner=root path=opt
dir group=bin mode=0755 owner=root path=etc/WFBldom
file etc/WFBldom/farmInfo group=bin mode=0644 owner=root \
  path=etc/WFBldom/farmInfo
dir group=bin mode=0755 owner=root path=opt/WFBldom
dir group=bin mode=0755 owner=root path=opt/WFBldom/lib
dir group=bin mode=0755 owner=root path=opt/WFBldom/conf
dir group=bin mode=0755 owner=root path=opt/WFBldom/bin
file opt/WFBldom/README group=bin mode=0644 owner=root \
  path=opt/WFBldom/README
file opt/WFBldom/lib/WFBldom.pm group=bin mode=0644 owner=root \
  path=opt/WFBldom/lib/WFBldom.pm
file opt/WFBldom/bin/ldmDestroy group=bin mode=0550 owner=root \
  path=opt/WFBldom/bin/ldmDestroy
file opt/WFBldom/bin/ldomReport group=bin mode=0550 owner=root \
  path=opt/WFBldom/bin/ldomReport
file opt/WFBldom/bin/mk_pam_changes_for_vas group=bin mode=0500 owner=root \
  path=opt/WFBldom/bin/mk_pam_changes_for_vas
file opt/WFBldom/bin/configure group=bin mode=0500 owner=root \
  path=opt/WFBldom/bin/configure
file opt/WFBldom/bin/create_ldom_xml_bkups.sh group=bin mode=0500 owner=root \
  path=opt/WFBldom/bin/create_ldom_xml_bkups.sh
file opt/WFBldom/bin/ldmAddVdisk group=bin mode=0550 owner=root \
  path=opt/WFBldom/bin/ldmAddVdisk
file opt/WFBldom/bin/format_luns.sh group=bin mode=0500 owner=root \
  path=opt/WFBldom/bin/format_luns.sh
file opt/WFBldom/bin/ldmRemoveVdisk group=bin mode=0550 owner=root \
  path=opt/WFBldom/bin/ldmRemoveVdisk
file opt/WFBldom/bin/adddisks.sh group=bin mode=0500 owner=root \
  path=opt/WFBldom/bin/adddisks.sh
file opt/WFBldom/bin/ldmusage group=bin mode=0550 owner=root \
  path=opt/WFBldom/bin/ldmusage
file opt/WFBldom/bin/label_luns.sh group=bin mode=0500 owner=root \
  path=opt/WFBldom/bin/label_luns.sh
file opt/WFBldom/bin/ldmCreate group=bin mode=0550 owner=root \
  path=opt/WFBldom/bin/ldmCreate
file opt/WFBldom/bin/fix_privs group=bin mode=0500 owner=root \
  path=opt/WFBldom/bin/fix_privs
# 

From the output above, we can see our local file structure matches the path to which they will be installed. Additionally, the pkgsend generate command also picked up our permissions (almost). It did get our file & directory modes correct, but the group ownerships need some adjusting and we need to eliminate the directories delivered by the SUNWcs package (/etc & /opt) so we don’t infringe on changes we should not own. We can do this by hand with an editor, but it’s much simpler to use pkgmogrify to automate the transformations using a transform file to ease the burden of package automation and eliminate potential mistakes. Refer to the pkgmogrify man page for details.

# cat mypackage.transform 
<transform -> edit group bin root>
<transform dir path=(etc|opt)$ -> drop>
# pkgmogrify mypackage.manifest.1 mypackage.transform > mypackage.manifest.2 
# egrep "path=etc$|path=opt$|group=bin" mypackage.manifest.2
# 

Next, we need to discover any dependencies our mypackage package may have. We do this by running the pkgdepend generate command.

# pkgdepend generate -md /IPS/packaging/mypackage mypackage.manifest.2 > \
  mypackage.manifest.3
# grep depend mypackage.manifest.3 | tail -3
depend fmri=__TBD pkg.debug.depend.file=bash pkg.debug.depend.path=usr/bin \
  pkg.debug.depend.reason=opt/WFBldom/bin/adddisks.sh \
  pkg.debug.depend.type=script type=require
depend fmri=__TBD pkg.debug.depend.file=perl pkg.debug.depend.path=usr/bin \
  pkg.debug.depend.reason=opt/WFBldom/bin/ldmAddVdisk \
  pkg.debug.depend.type=script type=require
depend fmri=__TBD pkg.debug.depend.file=perl pkg.debug.depend.path=usr/bin \
  pkg.debug.depend.reason=opt/WFBldom/bin/fix_privs \
  pkg.debug.depend.type=script type=require
# 

We can see our new manifest file now contains dependencies which we must resolve (noted by TBD in the fmri). In this particular case, our file /opt/WFBldom/bin/adddisks.sh has a dependency on the file /usr/bin/bash and our other two files have a dependency upon /usr/bin/perl. We need to automatically resolve these dependencies using the pkgdepend resolve command. This command will create a new, resolved manifest file with “.res” appended to our manifest name which allows multiple packages to be resolved at once. Additionally, this command may take a few moments to run, so be patient here.

# pkgdepend resolve -m mypackage.manifest.3
# grep depend mypackage.manifest.3.res | tail -3
depend fmri=pkg:/runtime/perl-584@5.8.4-0.167 type=require
depend fmri=pkg:/shell/bash@4.1.9-0.167 type=require
# 

Notice how the output above (same grep command as before on the “.res” file) resolved all of our dependencies down to only two packages. This is because all of my files for mypackage only contained BASH or Perl code. Your dependencies will vary based on the contents and specifics of your package. Now, let’s publish our package to the mycompany IPS repository we created at the beginning. To do this, we will use the pkgsend publish command providing the mypackage package version and the Solaris 11 build to which it can be applied (minimum build version). In this example we will use mypackage version 1.0.0 and 0.167 for the Solaris 11 build version, which can be verified with the pkg list kernel output.

# pkgsend -s http://10.36.136.7:10001/ publish -d \
  /IPS/packaging/mypackage mypackage@1.0.0-0.167 \
  mypackage.manifest.3.res 
PUBLISHED
pkg://mycompany/mypackage@1.0.0,5.11-0.167:20110811T204626Z
# 

With our new package published to an IPS repository available via HTTP, we can now query and install our package from another Solaris 11 system remotely. However, to do this, we will need to add our repository as a publisher on the remote system. Let’s do it.

# pkg set-publisher -g http://10.36.136.7:10001 mycompany
# pkgrepo info -s http://10.36.136.7:10001
PUBLISHER PACKAGES STATUS           UPDATED
mycompany 1        online           2011-08-11T20:46:26.848795Z
# pkg search mycompany/mypackage
INDEX      ACTION VALUE               PACKAGE
pkg.fmri   set    mycompany/mypackage pkg:/mypackage@1.0.0-0.167
# pkg install mypackage
               Packages to install:     1
           Create boot environment:    No
DOWNLOAD                                  PKGS       FILES    XFER (MB)
Completed                                  1/1       16/16      0.0/0.0$<3>
 
PHASE                                        ACTIONS
Install Phase                                  24/24 
 
PHASE                                          ITEMS
Package State Update Phase                       1/1 
Image State Update Phase                         2/2 
# pkg list mypackage
NAME (PUBLISHER)                                        VERSION              IFO
mypackage (mycompany)                                   1.0.0-0.167          i--
# ls -l /opt/WFBldom/bin/ldmCreate 
-r-xr-x---   1 root     root       19805 Aug 11 21:46 /opt/WFBldom/bin/ldmCreate
# 

There you have it. To recap, we created our own IPS repository called mycompany, our own mypackage package, published it, and installed it from a remote system. This wraps up the three-part mini-series on IPS for Oracle Solaris 11. I hope all of the examples provided in Part 1, Part 2, and Part 3 of this series has helped you gain a better understanding of IPS. I covered a lot of ground in only a few examples, so use the man pages to fill in the gaps as well as the documentation as needed.

Finally, I have to give credit to Bart Smaalders at Oracle for providing a nice blog on IPS packaging and to the creators of the Wiki page Introduction to IPS for Developers for providing Example 3-3.

Advertisements

Brad Hudson is an Established Leader in IT Infrastructure, Engineering, Operations, and Customer Service with extensive experience developing and delivering infrastructure solutions, building and growing customer service organizations, leading change initiatives, providing data center management, and managing implementation activities.

Tagged with: , , , , , , , , ,
Posted in IPS, Oracle, Solaris 11
About the Author

Brad Hudson is an Established Leader in IT Infrastructure, Engineering, Operations, and Customer Service with extensive experience developing and delivering infrastructure solutions, building and growing customer service organizations, leading change initiatives, providing data center management, and managing implementation activities.[Read More...]

%d bloggers like this: