Scope
The module is the glue between the JumpStart Enterprise Toolkit framework and the facilities provided to perform the actual installation of the product software. The module presents a set of configuration options in the template to allow per-target server options to be set, which are then used to drive the product installation according to those parameters.
There are no special requirements or restrictions about the scope of what options are presented in the template, or how to drive the product installation. There are some guidelines however, to try to ensure that modules co-exist with each other as much as possible and have no strange dependencies etc.
Module Design Guidelines
The toolkit itself was designed around some basic principles. The modules that were initially created alongside the toolkit also followed this style. While every module developer has the option of going down their own path, the following should be at least considered and followed if possible!
Module Coverage
Each module should cover a particular scope of an application, preferably without replicating the functionality available in another module. In addition, a module should be appropriately sized; if the module can be sensibly broken into sub components, then smaller modules should be created instead of one large monolithic module.
For example:
A designer may decide to write a module to provide security services to a target server installation. As part of this module, the designer decides to install a firewall and a set of hardening scripts.
In this case, the designer should investigate whether another module already covers either of these two areas and could be leveraged. In addition, if either the firewall or hardening scripts may be used elsewhere in isolation from each other, it may be more flexible to create them as two modules rather than bundling them together.
Module Dependencies
Each module should be self sufficient and not expect or rely on another module to be present. If such interaction is required (and sometimes it does make sense), then the module should be clearly identified as being dependent on the other module.
If the situation does arise, it should be determined whether the functionality is best represented in distinct modules or whether the two modules that are dependent on each other are better represented in one encompassing module.
The basic premise is to keep items together where it makes sense and not to create lots of smaller modules just for the sake of it.
Module Interactions
Where the case is strong for module separation and the modules are dependent (in at least one direction), the modules should try to interact with each other so that the correct (desirable) outcome is achieved.
The toolkit has a simplistic mechanism for setting and retrieving hints on a per module basis. Whether a module will pick up the hints, is up to the designer of the module, but with co-operation between module developers, the modules can be written in such a way that they work happily in isolation, but when put together they prodvide a stronger solution.
For example:
From a real-world example, the Sun Cluster 3 product places dependencies on how Solstice Disksuite is configured, but does not always need Disksuite installed, nor does Disksuite require the cluster software installed - indeed it is very valuable to be installed on non-clustered machines.
In this case, we have two very distinct modules; one that covers Disksuite and one that covers the Sun Cluster product. Each works fine in isolation, but when they are combined within the same target server configuration, the Sun Cluster module influences the Disksuite module so it conforms to the restrictions placed on Disksuite by Sun Cluster 3.0.
This interaction is done through the use of module hints and their behaviour in the standalone scenarios can be summarised as follows:
- When only the Sun Cluster module is active, Sun Cluster sets the hints, but Disksuite is not present to pick them up
- When only Disksuite is active, it looks for the hints, but they have not been set by any other module, so it uses it's regular default behaviour.
What the hints actually represent is totally up to the module developer. Close co-operation between module developers will enable the most efficient use of hints; if possible, the hints should be documented within the module Release Notes, so other module developers may take advantage of the additional interfaces.
Module Coding
The module developer should try to select a standard scripting language that will be available during the JumpStart installation. For example, the use of a 'bash' is not possible, as the NFS boot image the target server uses does not contain that shell.
Where possible, the Bourne Shell should be used as this is known to exist on all versions of Solaris. Only as a last resort should a compiled language be considered.
Module Directory
Every module has its own directory structure, located in the 'Products' subdirectory from where the main toolkit framework was installed. The name of the directory is the name used by the toolkit to reference the particular module.
For example, the module 'sds' (Solstice Disksuite) resides in ..../Products/sds/, and it alone controls what resides in that directory and how it is used; with some notable exceptions listed below.
No further interaction is required to 'register' a module with the toolkit - the presence of the directory is sufficient. It is not advisable to create symbolic links in the 'Products' directory to other locations outside of the main toolkit installation point; the target servers may not be able to access such directories during the installation, unless other measures have been taken to provide such functionality.
Module configuration
<module>.conf
Each module is intended to be configurable to some extent by the user; although this is not a mandatory requirement, it is normally expected to be implemented.
The toolkit takes a very simplistic view on providing module configuration to the user. When a template is created through the toolkit 'make_template' command, a single flat file containing the concatenation of the core 'base_config' configuration file, followed by the configuration files from each of the modules that have been selected, is produced.
By providing a configuration file named after the module itself and with a '.conf' suffix, the toolkit 'make_template' command will do the rest of the work.
The configuration file is a simple Bourne Shell script, and should present configurable options in the form of variables to the user; each variable should be prefixed with the module name and an underscore, to preserve the variable namespace of the module and prevent one module corrupting another.
For example, the module 'vts' presents an option to the user to select the version of the software to be installed; the corresponding part of the configuration file is as follows:
############ # # Which version of the product is to be installed # vts_product_version="6.2"
In this example, a default value of 6.2 is already populated in the configuration file, as this was the most recent version of the product when the module was written.
Module Interfaces
The toolkit calls particular interfaces within the module during the lifecycle of the JumpStart process - both on the target server and the JumpStart server. Each interface is expected to be an executable shell script (or worst case, a binary), with the context of the target server supplied through environmental variables.
copy_media
| Called on | JumpStart server |
| Arguments | <patches|packages> <version> <srcdir> <destdir> <arch> |
| Required/Optional | Optional |
The copy_media script is called when the user calls the copy_product_media or copy_product_patches scripts to manage the media for this module. The script should understand what format the application is delivered in, and perform the copy from the passed source media location, to the appropriate media location on the server.
This function allows the module to handle exotic forms of media (tar.gz, zip, bz2, etc), without the main toolkit requiring to be updated for each media type. It also enables the module developer to place the media onto the server in a known state. For example, a product may require a whole directory tree to be visible, or just a collection of Solaris packages.
make_template
| Called on | JumpStart server |
| Arguments | none |
| Required/Optional | Optional |
When an administrator wants to create a new definition for a server build, they will execute the top level command 'make_template' supplied in /opt/SUNWjet/bin. This top level make_template script will set up the basic target server configuration information and then call each module specific make_template script, if it is present. The module specific make_template script can perform additional work on the template; for example, populating per-client defaults for the user to edit.
make_client
| Called on | JumpStart server |
| Arguments | none |
| Required/Optional | Optional |
When an administrator wants to set up a target server for installation, they will execute the top level command 'make_client' supplied in the bin directory of the toolkit. This top level make_client script will set up the basic target server configuration information and then call each module specific make_client script if it is present. The module specific make_client script can perform additional work in the target server specific '/opt/SUNWjet/Clients' directory, it may configure module hints, modify the target server profile, sysidcfg or other files accordingly.
begin
| Called on | target server |
| Arguments | none |
| Required/Optional | Optional |
During the 'begin' phase of the JumpStart process, the toolkit will check to see if the module has a script called 'begin', and if it is present, the script will be executed. Any variables set in the module configuration section of the template will be present in the environment for the script to access.
install
| Called on | target server |
| Arguments | none |
| Required/Optional | Required |
The install script is the main workhorse of the module. It is called on the target server after the main Solaris installation has completed, during the 'finish' script phase. Its purpose is to instigate the installation or configuration of the particular application.
The script itself is called prior to the first reboot of the newly installed target server. At this point, the root directory (/) is actually an NFS mounted filesystem from the JumpStart server. The real disk based root directory is located through the use of the environment variable $ROOTDIR, traditionally set to '/a'.
If the application can not be installed when root is located on $ROOTDIR, the install script should use the post-installation functionality provided by the toolkit, to schedule a subsequent installation after the first reboot. After the first reboot, the target server will actually boot of its own disk, and root will really be on '/'.
The install script is responsible for taking the user supplied configuration and driving the actual application installation and configuration appropriately. How this is achieved, is up to the module developer, although a number of utility functions are available from the main toolkit, to assist with the common tasks; such as package or patch installation, file copies, message reporting etc.
Prior to the module 'install' script being called, the module configuration as defined in the template - and originally populated from the <module>.conf file - is loaded into the shell environment. The 'install' script should not expect to be called with arguments, but should instead take it's configuration from the current environment. This technique avoids the problem of each module installation script requiring different numbers of arguments etc.
check_client
| Called on | target server |
| Arguments | none |
| Required/Optional | Optional |
The 'check_client' script can be employed by a module developer to perform basic checks about the configuration options specified in the template. When called, the environment will be configured with the variables set in the template, and the script can perform basic checking to try to reduce any installation errors.
The module may decide to check for valid options or that media exists for the selected version etc. The level of functionality provided is up to the implementor.
Support Functions in the Toolkit
The main toolkit supplies many common functions that can be utilised by modules; this allows for better code re-use and simpler modules. The best way to find out what functions are available, is to examine the directory '/opt/SUNWjet/Utils/lib' and '/opt/SUNWjet/Utils/serverlib' in which they reside.