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:/firstname.lastname@example.org type=require depend fmri=pkg:/email@example.com 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 firstname.lastname@example.org \ mypackage.manifest.3.res PUBLISHED pkg://email@example.com,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:/firstname.lastname@example.org # 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.