ShowTable of Contents
Introduction
From the IBM Installation Manager Information Center:
"IBM Installation Manager is a tool that you can use to install and maintain your software packages. Each wizard guides you through the steps that you must take to install, modify, update, roll back, or uninstall your IBM products. Use Installation Manager to install individual software packages on your local machine, or in conjunction with the IBM Packaging Utility to perform software installations for an enterprise."
The Installation Manager (IM) provides seven wizards that help maintain a software package's life cycle. They include the following:
- install wizard
- update wizard
- modify wizard
- license management wizard
- import wizard
- roll back wizard
- uninstall wizard
A software package developed to be installable with the IM consists of the following form:
- offering. The name given for a product that's installable via the IM; it encloses an assembly (among other items).
- assembly. A container metadata construct that contains selectors (switches that determine what will be installed based on user feature selection or built-in logic), shareable units, and other assemblies.
- shareable unit (SU). The smallest unit that can be shared between offerings; generally encapsulates a software component or an install action, and consists of selectors and installable units.
- installable unit (IU). The smallest unit of installation; the IU contains the actions that are performed during install that modify the host system.
- artifact. Installation files.
Offerings, assemblies, SUs, and IUs details are all captured and expressed in files in an XML format. For the purposes of this article, we look at only those areas that pertain to version numbering and the use of timestamps for it.
Why use timestamps in version numbering?
The reasons for using timestamps in version numbering include:
- allowing test and development teams to know more precisely from which particular build a problem may arise, so that appropriate remedies can be efficiently and productively administered. For example, suppose the Test team discovers a defect and submits it to the development team for a fix; without knowing the build in which the issue occurs makes for wasted effort in trying to determine if this defect has already been fixed and when it was fixed.
- the IM uses the "latest" version, and without timestamps to differentiate artifacts, the IM will reuse an already-named artifact that it has stored in its cache/repository. This leads to lowered productivity owing to the confusion as to which artifacts have actually been installed and used.
Implementation details
To review the constituent parts of an installable software package, it may be helpful to view it from a bottom-up perspective.
Let's start with an artifact, the thing that is installed or used to modify the underlying system (for example, .jar and .zip files). The artifact is referenced within an IU because it is the smallest unit of installation, and any actions are expressed herein. IUs are grouped / connected via an SU, that is, the container for such things.
Listing 1 shows a snippet of code of an SU file from the IBM Connections installer.
Listing 1. Code snippet from SU file
<?xml version='1.0' encoding='UTF-8'?>
<?metadata version='0.0.4'?>
<su id='lc.installer' version='3.0.1.qualifier'>
<selector id='main' />
<selector id='news' />
<selector id='search' />
<selector id='activities' />
<selector id='blogs' />
<selector id='communities' />
<selector id='dogear' />
<selector id='files' />
<selector id='forum' />
<selector id='metrics' />
<selector id='mobile' />
<selector id='homepage' />
<selector id='profiles' />
<selector id='wikis' />
<selector id='moderation' />
...
<iu id='unzipCE_iu' adapterId='native' version='1.0.0.0'>
<selectedByExpression>
<or>
<selectedBy value='linux' id='os'/>
<selectedBy value='aix' id='os'/>
<selectedBy value='win32' id='os'/>
</or>
</selectedByExpression>
<adapterSpecificData>
<zip id='configengine' destination='${profile:installLocation}' tolerance='[0.0.0,0.0.0]' overwrite='true' downloadSize='10973860' installSize='12904209'/>
</adapterSpecificData>
</iu>
...
</su>
The next higher-up level is the assembly, which holds a collection of SUs (and other assemblies). You will not find any IUs in an assembly; they would be indirectly referenced via the SUs that they collect. Listing 2 is an example from the IBM Connections installer.
Listing 2. Example of an assembly
<?xml version='1.0' encoding='UTF-8'?>
<?metadata version='0.0.4'?>
<assembly version='3.0.1' id='com.ibm.lotus.installer'>
<selector id='main' />
...
<includedShareableEntity id='lc.installer' version='3.0.1.qualifier' tolerance='[3.0.0,4.0.0)'>
<includedSelector selectorId='main'>
<selectedBy id='main'/>
</includedSelector>
<includedSelector selectorId='news'>
<selectedBy id='news'/>
</includedSelector>
<includedSelector selectorId='search'>
<selectedBy id='search'/>
</includedSelector>
...
</includedShareableEntity>
</assembly>
The top level holds the offering. Listing 3 is an example from the IBM Connections installer.
Listing 3. Example of an offering
<?xml version='1.0' encoding='UTF-8'?>
<?metadata version='0.0.4'?>
<offering id='com.ibm.lotus.connections' version='3.0.1.qualifier' assemblyId='com.ibm.lotus.installer' assemblyVersion='3.0.1'>
<information name='Lotus Connections' version='3.0.1.0'>%Offering.description</information>
<property name='default.location.win32' value='${specialFolder:PROGRAM_FILES}\IBM\LotusConnections' />
<property name='default.location.linux' value='/opt/IBM/LotusConnections' />
<property name='default.location.aix' value='/opt/IBM/LotusConnections' />
<property name='default.location.win32.vista' value='${specialFolder:PROGRAM_FILES}\IBM\LotusConnections' />
<property name='default.user.location.win32' value='${specialFolder:PROGRAM_FILES}\IBM\LotusConnections' />
<property name='default.user.location.linux' value='/opt/IBM/LotusConnections' />
<property name='default.user.location.aix' value='/opt/IBM/LotusConnections' />
<property name='default.user.location.win32.vista' value='${specialFolder:PROGRAM_FILES}\IBM\LotusConnections' />
<property name='default.profile' value='%Profile.name' />
<property name='default.commonlocation.win32' value='${specialFolder:PROGRAM_FILES}\IBM\SSPShared' />
<property name='default.commonlocation.aix' value='/opt/IBM/SSPShared' />
<property name='default.commonlocation.win32.vista' value='${specialFolder:PROGRAM_FILES}\IBM\SSPShared' />
<property name='default.commonlocation.linux' value='/opt/IBM/SSPShared' />
<property name='default.user.commonlocation.win32' value='${specialFolder:PROGRAM_FILES}\IBM\SSPShared' />
<property name='default.user.commonlocation.aix' value='/opt/IBM/SSPShared' />
<property name='default.user.commonlocation.win32.vista' value='${specialFolder:PROGRAM_FILES}\IBM\SSPShared' />
<property name='default.user.commonlocation.linux' value='/opt/IBM/SSPShared' />
<property name='commonlocation.temp' value='/opt/IBM/SSPShared/STtemp' />
<property name='offering.RequiresAdmin' value='false'/>
<featureGroup kind='RequiredAndVisible'>
<featureGroup kind='RequiredAndVisible'>
<information name='%feature.lc.base.name'/>
<feature kind='RequiredAndVisible' selectionId='search' id='search'>
<information name='%feature.lc.search.name'>%feature.lc.search.description</information>
</feature>
<feature kind='RequiredAndVisible' selectionId='news' id='news'>
<information name='%feature.lc.news.name'>%feature.lc.news.description</information>
</feature>
<feature kind='RequiredAndVisible' selectionId='homepage' id='homepage'>
<information name='%feature.lc.homepage.name'>%feature.lc.homepage.description</information>
</feature>
</featureGroup>
...
</featureGroup>
...
</offering>
Version numbering
Now that we have a sense of how the various pieces are related, let's focus on the version-numbering aspect.
Artifacts have the following format for naming:
[name]_[version].[extension]
where "name" uniquely identifies the artifact, and "version" allows for updates to be delivered to the same file.
It is here that we can include a timestamp in the version number. IM recognizes the special text string "qualifier" and replaces such text strings with a timestamp in the following default format:
YYYYMMDD_hhmm
where YYYY represents the year, MM the month, DD the day of the month, and hhmm the time in hours and minutes.
The default format can be overridden with a user-supplied format. This is specified in the build script in the cic.build element of the qualifier attribute. For example,
; ${theQualifier} is a variable that holds the formatting specification as passed in by the user to the build script.
Here is an example from the IBM Connections installer using the special keyword "qualifier" in the version numbering:
<offering id='com.ibm.lotus.connections' version='3.0.1.qualifier' assemblyId='com.ibm.lotus.installer' assemblyVersion='3.0.1'>}}}
Unless there are specific reasons for setting the tolerance attribute to specific values or ranges, it can be set to [0.0.0,0.0.0]. This will make the IM choose the most recent version available; for example:
<adapterSpecificData>
<zip destination='${profile:installLocation}' id='product' tolerance='[0.0.0,0.0.0]' overwrite='true'/>
</adapterSpecificData>
Similarly, if the version is set to 0.0.0, the IM also uses the latest version. It should be noted that version numbering using timestamps is mainly for internal development use, and the external version can be static. The convention used in internal and external version numbering is as follows:
The external version can be any string, but it is recommended that it take the form <major>.<minor>.<micro>.<service>, in which all the components are numeric. The internal version should then be based on the external version as follows:
internal.major = external.major
internal.minor = external.minor
internal.micro = external.micro * 1000 + external.service
For example, if the external version was 3.0.1.0, the internal version would then be 3.0.1000.qualifier. Say the external version was instead 3.0.1.2, then the internal version would be calculated to be 3.0.1002.qualifier.
Now that we have decided how to name our internal and external versions, where do they actually get specified? The answer is in the <offering> and <information> tags. For instance:
<offering id='com.ibm.product' version='3.0.1000.qualifier' assemblyId='com.ibm.product.main' assemblyVersion='0.0.0'>
<information name='product' version='3.0.1.0'>
Very cool product
</information>
where the offering tag holds the internal version, and the information tag holds the external (user-visible) version.
Resources
Installation Manager (v1.3.x) Information Center:
http://publib.boulder.ibm.com/infocenter/install/v1r2/topic/com.ibm.cic.agent.ui.doc/helpindex_imic.html
developerWorks IBM Connections product page:
http://www.ibm.com/developerworks/lotus/products/connections/
About the author
Frank RQ Chen is an Advisory Software Engineer based at IBM China Development Lab in Shanghai. He joined IBM in 2008 working on the installer for Lotus Quickr 8.5 for WebSphere Portal. Currently, he is involved with the development of the installer for the next release of IBM Connections.You can reach him at frankch@cn.ibm.com.