How To Add Pre-/Post-Scripts to IPS Packages

Package Scripting

My last post about Solaris 11 triggered an interesting discussion with UX-admin about IPS and the lack of pre-/post-scripts for installation/removal.

Assuming that Solaris 11 will be based on IPS just like OpenSolaris, it is certain that sysadmins will have to change a lot in how they create and manage packages, because IPS is fundamentally different from the good old System V packaging system.

So let's explore the lack of scripting hooks in IPS and see if we can find some ways of working around them:

The Problem

One of the fundamental differences between IPS and traditional System V packaging in versions of Solaris <= 10 is that in the old days, you could include pre-install, post-install, pre-remove and post-remove scripts along with any files into your package and the package installation/removal process would automatically start those scripts at the right time during the installation/removal process.

But IPS got rid of all scripts. The reasoning here is that scripting around the installation process introduced more evils than goods, in particular when the setting was more complicated than a plain vanilla standard installation. For a full discussion, check out Stephen Hahn's pkg(5): a no scripting zone article.

In essence, all IPS supports is copying files into the right directories at installation times, and removing those files at de-installation times, plus some simple IPS actions such as creating users/groups or (through the magic of setting special variables) starting/stopping SMF services as part of the package installation process. Check out this simple IPS creation example to get a feel for it.

So if (like UX-admin, whose real name I'd like to know) you really want to do something other than just copying files as part of the package installation process, you won't be happy with IPS alone.

The Background

As Stephen Hahn explained in the essay mentioned above, there's a conscious trade-off in the design of IPS that tries to separate the process of installation from the rest of the tasks that traditionally were part of package management.

Let's check the full package life-cycle in a traditional System-V package install/removal process:

  1. The admin starts the package installation process through pkgadd(1M).
  2. The pre-install script is executed, which carries out any useful tasks prior to package installation.
  3. The files that make up the package are installed.
  4. The post-install script is executed, performing any configuration and other post-install tasks.
  5. At some point, the admin decides she no longer want the package and starts the package removal process through pkgrm(1M)
  6. The pre-remove script is executed, cleaning up anything that needs to be cleaned up prior to the removal of any files.
  7. The files that make up the package are removed.
  8. The post-remove script carries out any last cleaning actions that had to wait for after file removal.
  9. Done.

A full discussion of these steps and how they're implemented in traditional System V packaging fashion in Solaris can be found in the Application Packaging Developer's Guide, particularly in the Procedure Scripts chapter.

(The whole thing is actually much more powerful and complex, but for the sake of brevity, lets concentrate here on procedure scripts alone.)

IMHO, the real issue here is that steps 3 and 7 above are very easy to handle (because they just involve copying/removing of files), while all the other steps (executing the scripts) can be arbitrarily complex, because the system has no control over what those scripts actually do, nor can the packaging infrastructure always trust the scripts to always behave correctly in all possible situations (such as complex network installations, zones, security constraints, etc.).

So the easy solution is: Only allow the installation of files, leave the rest to the admin.

Effectively, this separates the task of Package installation/removal from the task of Package lifecycle management. IPS takes care of the former, the latter is left as an exercise for and as a responsibility of the admin.

The Simple Solution

If all you want is to get your pre/post install/remove scripts back, then you could wrap your old scripts into two installer/uninstaller scripts, deliver these as an IPS package and ask the admin to execute them:

  1. The admin installs an IPS package, which copies the install/remove scripts into some staging area.
  2. The admin starts the install script, which goes through the same pre-install, copy files, post-install sequence outlined above.
  3. At some point, she decides to deinstall everything, so...
  4. The admin starts the uninstall script, which goes through the same pre-remove, delete files, post-remove sequence as with traditional package management.
  5. The admin removes the IPS package, which removes the install/remove scripts as well.
  6. Done.

While this should certainly work, this is not really elegant, because it relies too much on the sysadmin to think (and know) of the install/uninstall scripts. There has to be a better way.

The Comfortable Solution: SMF to the Rescue

And there is. One powerful feature of IPS is the ability to install a new SMF service (by copying its method script and manifest into the right directories), then activate it (by setting a magic variable like this: $ pkgsend add set restart_fmri=svc:/system/manifest-import:default xml_manifest).

We can now use this SMF service to watch over the package lifecycle and to execute the missing scripts at the right time. I'd like to call this SMF service a "shepherd" service, because it watches and takes care over our package in a loving way during its whole lifecycle.

Using SMF to manage the package lifecycle could look like this:

  1. Our admin now installs a new package through IPS.
  2. The IPS package installs the files to be installed into a staging area, then it installs a shepherd SMF service and activates it.
  3. The shepherd service notices that the actual package it's supposed to take care of isn't present yet. It then:
    1. Executes the pre-install script, just like in the old System V days,
    2. Copies the files from the staging area into the right locations,
    3. Executes the post-install script, just like in the old System V days.
    4. Writes the result and the success of its operations into some log file.
  4. Now the package is installed, in exactly the same way as if it was installed using the old, traditional System V method.
  5. After some time, our admin decides to get rid of the package, so she starts the package removal process by deinstalling the previously installed package through IPS:
  6. IPS stops the SMF shepherd service. This triggers its "shutdown" method, which:
    1. Executes the pre-remove script, just like in the old System V days,
    2. Removes the files from the right locations,
    3. Executes the post-remove script, just like in the old System V days.
    4. Logs any errors or progress to some log file.
  7. Now, the only job left to do for IPS is to remove the shepherd SMF service as well as the files from the staging area, which it can do automatically.

Notice that the shepherd SMF service now assumes responsibility for installing the "inner package" by making sure it's only executed once and that the execution completes successfully. Plenty of error potential here, but I guess this is the cost of making the install process script-based.

In theory, this should work and I see no reason why it shouldn't. Hopefully, this is a valid workaround for anybody who truely misses the good old pre/post install/remove scripts.

Of course, there's still potential for making this more elegant or sophisticated, for example, instead of staging the actual files to install, the shepherd could use a standard IPS "inner package" instead and issue the right commands to install/remove it.

Some care should be taken to avoid the whole thing to break by the sysadmin accidentally deactivating the shepherd service. This could be done by adding some code that detects the reason for it being called with the shutdown method. This may need some tweaking, but I doubt it would be difficult to do.

Conclusion

The limitations of IPS in terms of scripting have their reasons and IMHO, they're valid. On the other hand, there are other valid reasons for using scripts during the install process as well, for certain situations.

A potential solution is to use the combination of IPS and SMF to carry out both tasks of managing package files and managing the package lifecycle, including pre/post install/remove scripts. One example is outlined above, and I'm sure there are other possibilities.

The point here is: The old installation mechanism has introduced a lot of problems (particularly with patching, as Ben pointed out) and the new mechanism aims at removing complexity by reducing the package installation process to only copying/removing files (and some minor other things). This leads to simplicity, but still allows for arbitrary complexity (including getting your scripts back) through leveraging other features of Solaris, mainly SMF.

IPS is still in the beginning, who knows how it will look like when Solaris 11 is released? But I hope to have highlighted one way for package builders to have their package and script it, too.

What are your thoughts around IPS and scripting? Did anyone try to work around the scripting limitation? How? Do you find the approach above feasible?

Leave a comment!

Stay in Touch!

Did you like this article? Have you found it useful, interesting or entertaining?

Then click here to get free regular updates and help me reach my goal of 1,000 regular blog readers this summer!

Thank you for reading Constant Thinking.