N1 Grid Service Provisioning System User's Guide and Release Notes for the OS Provisioning Plug-In 1.0

Appendix C Creating Custom JET Modules

Scope

The module is the glue between the JET 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 cooperation between module developers, the modules can be written in such a way that they work happily in isolation, but when put together they provide 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 behavior in the standalone scenarios can be summarized as follows:

What the hints actually represent is totally up to the module developer. Close cooperation 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 know 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 File)

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 use the toolkit make_template command to create a template, a single flat file is produced. This file concatenates the core base_config configuration file with the configuration files from each of the selected modules. 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. The configuration file 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 sds 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 
# 
sds_product_version="4.2.1"

In this example, a default value of 4.2.1 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 life cycle 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 Interface

Called on

JumpStart server

Arguments
<patches|packages> version srcdir destdir arch
Required or optional?

Required

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, and so on), 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 bunch of Solaris packages.

make_template Interface

Called on

JumpStart server

Arguments

none

Required or 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 Interface

Called on

JumpStart server

Arguments

none

Required or 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 Interface

Called on

target server

Arguments

none

Required or 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 Interface

Called on

target server

Arguments

none

Required or 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 cannot 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 ingenuity of 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 its configuration from the current environment. This technique avoids the problem of each module installation script requiring different numbers of arguments etc.

check_client Interface

Called on

target server

Arguments

none

Required or 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 utilized 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 in which they reside.

Adding a JET Module

This section describes how you can add additional JET modules to the Solaris boot and install (JET) server. Although the process is describes in the context of a Flash module, the logic extends to other JET modules.

ProcedureHow to Add a Flash Module

Steps
  1. Download the JetFLASH.pkg onto the Solaris boot and install server.

  2. Install the JetFLASH package.

    Use commands similar to the following example:


    # cat >/tmp/admin-file <<- _EOF
    mail=\n
    instance=unique
    partial=quit
    runlevel=ask
    idepend=quit
    rdepend=nocheck
    space=quit
    setuid=nocheck
    conflict=nocheck
    action=nocheck
    basedir=/opt/SUNWjet/Products
    _EOF
      pkgadd -a /tmp/admin-file -d JetFLASH.pkg 
  3. Copy the Flash image to the Solaris boot and install server.

    Use commands similar to the following example:


    # telnet solaris-bis-ip-address 
      # cp flash-archive /export/install/flash/sol10_xall_sparc.flar
    
  4. Create a Solaris Profile for this Flash image.

    Use commands similar to the following example:


    # cat > /tmp/flash-profile <<- _EOF
    flash-with-ra
    Solaris10 Flash Archive With SPS RA
    base_config flash spsra
    _EOF
    cr_cli -cmd pe.p.run -u admin -p admin -PID NM:/com/sun/n1osp/untyped/SolarisImage-attach \
    -tar H:NM:masterserver-jet -comp + -vs solaris10 -pto 120 -nto 120 -f /tmp/flash-profile

    Tip –

    You can also create the Profile component through the N1 Grid SPS browser interface. Use the Solaris Image: create profile option.


  5. Edit the Profile component that you created in the previous step.

    The profile is located at /com/sun/n1osp/autogen-masterserver-jet/provision/. In this example task, the Profile component is /com/sun/n1osp/autogen-masterserver-jet/provision/Solaris_10.flash.

  6. In the Profile component, change the archive_locations_flash variable value to point to the flash archive.

    For example:

    archive_locations_flash nfs://10.216.0.55/export/install/flash/sol10_xall_sparc.flar
  7. Check in the component.

    You are now ready to use the above Solaris Profile to deploy on desired target host.