OpenSolaris Distribution Constructor Guide
Previous Next

Using the Finalizer Scripts

The distribution constructor application includes default scripts in the /usr/share/distro_const directory and subdirectories. These scripts are referenced in the finalizer section of the manifest files.


Note - It is recommended that you use the default scripts without editing them. You do have the option to write your own scripts to perform additional operations.


For example, some of the finalizer scripts that are used to create an x86 Slim CD are as follows:

  • pre_bootroot_pkg_image_mod – Image area modifications for all types of images

  • slim_cd/slimcd_pre_bootroot_pkg_image_mod – Image area modifications specific to Slim CD

  • slim_cd/slimcd_gen_cd_content – Generate the list of files that are part of the Slim Live CD image.

  • bootroot_initialize.py – Boot-root initialization

  • slim_cd/slimcd_bootroot_configure – Boot-root configuration specific to Slim CD

  • bootroot_configure – Boot-root configuration

  • bootroot_archive.py – Boot-root archiving

  • slim_cd/slimcd_post_bootroot_pkg_image_mod – Post-boot-root image area modification specific to Slim CD

  • grub_setup – Initialization of grub menu

  • post_bootroot_pkg_image_mod – Post-boot-root image area modification

  • create_iso – ISO image creation

  • create_usb – USB image creation

These finalizer scripts are referenced in the finalizer section of the Slim CD manifest. You can view the complete contents of the default Slim CD manifest, including the finalizer section where the scripts are referenced, at Slim CD Manifest File.


Note - Some of the scripts listed above are also used to create SPARC or x86 ISO images for automated installations. But, the automated installer manifests reference other finalizer scripts that are specific to the SPARC or x86 automated installation processes.


Customizing Finalizer Scripts

You can use the default scripts without editing them. However, you can also create custom scripts to perform additional tasks as follows:

  1. Create new scripts by using the existing scripts as models for your new scripts. Review the characteristics of finalizer scripts as described below. Also, see the custom script examples that are provided below.

  2. Add your new scripts to the /usr/share/distro_const directory or anywhere on the system or network. Make sure that root can execute these scripts.

  3. Add the new script names in the finalizer section of the appropriate manifest file. Be sure to specify the full path to your scripts in the manifest file, even if they are in the /usr/share/distro_const directory.

  4. When you add a reference for a new script in the finalizer section of a manifest file, you must specify a checkpoint name that is used to pause the image build before or after this script performs its task. Optionally, you can include a custom message associated with the checkpoint name. If this message is omitted, the path of the script is used as the default checkpoint message.


    Note - Use meaningful names for checkpoint names instead of using numbers. If new scripts are added, the new steps for those new scripts will disrupt a prior numbered checkpoint order.


    For example, the following reference in a manifest file specifies the checkpoint name of “br-arch” for a boot root archiving script, and the associated message is “Boot root archiving.”

    <script name="/usr/share/distro_const/bootroot_archive.py">
    <checkpoint name="br-arch" message="Boot root archiving"/>

    In this example, when you build your image, you could refer to the “br-arch” checkpoint in the distro_const command. This checkpoint would enable you to pause building the image just before the boot root archiving script performs its task.

    For instructions about how to refer to checkpoints in the distro_const command, see Using Checkpointing to Create an Image.

    To see further examples of finalizer script references, see the finalizer section of the Slim CD Manifest File.

Characteristics of Finalizer Scripts

When you create your own scripts, note the following characteristics of the finalizer scripts:

  • Scripts can be Python programs, shell scripts, or binaries.

  • Scripts are executed in the order that they are listed in the manifest file.

  • The stdout and stderr information for the scripts is captured in the log files.

  • The argslist, which can accept a list of items, uses double-quotes to delimit the list arguments. When no double-quotes are used, or if one set of double-quotes envelopes the entire string, the entire string including spaces and newlines is interpreted as one argument. Do not use commas between arguments.

  • The distribution constructor passes five initial arguments to all scripts which are executed. These five arguments are not included as entries in the manifest file. The manifest file specifies additional arguments passed in after these five arguments. The initial arguments are as follows:

Table 3-2 Finalizer Script Arguments

Argument

Description

Server socket file name

The first argument is the manifest reader socket. This argument specifies the socket that is used with /usr/bin/ManifestRead for accessing the manifest data. See the section below about Using the ManifestReader.

Package image area path

The second argument is the PKG_IMG_PATH, which specifies the path to the area where the package image is created. Use this argument to locate a file in the package image area. The following example checks whether the user “jack” is in the password file.

PKG_IMG_PATH=$2
/usr/bin/grep jack $PKG_IMG_PATH/etc/passwd >/dev/null
if [[ $? == "0" ]] ; then
   print "Found Jack"
fi 

Temp directory

The third argument specifies a directory that is used when creating temporary files needed during the build process. In the following example, we want to create a file in the temporary directory for building the boot root.

TMP_DIR=$3
/usr/sbin/mkfile $TMP_DIR/bootroot_archive
/usr/sbin/lofiadm -a $TMP_DIR/bootroot_archive 

Bootroot build area

The fourth argument is the boot root build area, where the boot root files are gathered. See the following example from the bootroot_archive.py module. The module references the boot root build area in order to size the boot root before creating the archive.

BR_BUILD = sys.argv[4]          # Bootroot build area

print "Sizing bootroot requirements..."
cmd = /usr/bin/du + " -sk " + BR_BUILD + " | " + /usr/bin/awk + " '{print $1}'"
bootroot_size = int(Popen(cmd, shell=True,
   stdout=PIPE).communicate()[0].strip()) 

Media area

The fifth argument specifies where the finished media is deposited. In the following example, the create_iso script uses this argument to place the resultant ISO image.

MEDIA_DIR=$5
...
DIST_ISO=${MEDIA_DIR}/${DISTRO_NAME}.iso
... 

Additional arguments

A list of additional arguments to be passed into a script is tagged in the manifest with the <argslist> tag. The first of these arguments is passed in as arg6.

In the following example from the slim_cd.xml manifest file, two additional arguments are passed to the bootroot_configure script, as arg6 and arg7:

<argslist>
     "/usr/share/distro_const/slim_cd/slimcd_generic_live.xml"
     ".livecd"
</argslist>

Another method for specifying additional arguments is to use key-value pairs. See the following section.

Using the ManifestReader

The distribution constructor passes the manifest reader socket argument into finalizer scripts. This argument specifies the socket that is used with /usr/bin/ManifestRead for accessing the manifest data.

The following example calls ManifestRead to request the name item from the manifest file. ManifestRead returns zero or more items, each on its own line. If ManifestRead is given multiple items to search for, the lines returned contain both the item being searched for and a result.

MFEST_SOCKET=$1

VOLNAME=`/usr/bin/ManifestRead ${MFEST_SOCKET} "name"`
if [ "XX${VOLNAME}" == "XX" ] ; then
       print -u2 "$0: Error retrieving volume ID"
       exit 1
fi

The following example shows how to make use of ManifestRead from a python script:

from osol_install.ManifestRead import ManifestRead

# get the manifest reader object from the socket
manifest_reader_obj = ManifestRead(MFEST_SOCKET)

# get bootroot compression type

BR_COMPR_TYPE = get_manifest_value(manifest_reader_obj,
   "img_params/output_image/bootroot/compression/type")
if (BR_COMPR_TYPE == None):
       raise Exception, (sys.argv[0] +
           ": bootroot compression type missing from manifest")
Specifying Key-Value Pairs

Another method for passing arguments into scripts is to specify a key-value pair. This method is useful for passing the same argument into multiple scripts without duplication. A script can access a keyed value by specifying the key to /usr/bin/ManifestRead from within the script. Provide the server socket as the first argument and then provide the nodepaths to the items whose values are needed, as in the following examples.

Example 3-1 Shell Script
...
  MFEST_SOCKET=$1
  ...
  /usr/bin/ManifestRead -k $MFEST_SOCKET iso_sort
  iso_sort_file=`/usr/bin/ManifestRead $MFEST_SOCKET iso_sort`

The above example calls ManifestRead from a shell script to get a keyed value as in this sample script.

Example 3-2 Python Script
from osol_install.ManifestRead import ManifestRead

...
  IS_KEY = True

  iso_sort_file = manifest_reader_obj.get_values("iso_sort", IS_KEY)
  fd = open(iso_sort_file,....)

The above example calls ManifestRead from python to get the same keyed value.

Examples of Custom Finalizer Scripts

The following examples illustrate some practical applications for custom finalizer scripts.

Adding Packages

When putting together an image, you can experiment with how an image works when packages are added or removed from a working set. This type of experimentation is supported by the distribution constructor. Additional packages can be added to the existing list in the package section of a manifest file. And, packages that you want to remove can be added to the post_install_remove_package section. After you made your modifications to the manifest file to add or remove packages, you need to restart the build process from the beginning, and re-download all the packages. That can take time. You can do these modifications more rapidly by using finalizer scripts.

The following custom script adds an IPS package to the image from an alternate repository specified in the manifest file. The package is added to the package image area. The name of the package to add is included in the script. This example also demonstrates how to use the ManifestRead program to get values from the manifest file.

Example 3-3 Script for Adding Packages
#!/bin/ksh
#
#
# Args:
#
#   5 arguments are passed in by default from the DC.
#
#   MFEST_SOCKET: Socket needed to get manifest data via ManifestRead object
#   PKG_IMG_PATH: Package image area
#   TMP_DIR: Temporary directory 
#   BR_BUILD: Area where bootroot is put together (not used in this example)
#   MEDIA_DIR: Area where the media is put (not used)
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

if [ "$#" != "5" ] ; then
        print -u2 "Usage: $0: Requires 5 args:"
        print -u2 "    Reader socket, pkg_image area, tmp dir,"

        print -u2 "    bootroot build area, media area"
        exit 1
fi

MFEST_SOCKET=$1

PKG_IMG_PATH=$2
if [ ! -d $PKG_IMG_PATH ] ; then
        print -u2 "$0: Image package area $PKG_IMG_PATH is not valid"
        exit 1
fi

PKGCMD="/bin/pkg"

#Hard code package to install
TEST_PKGS="SUNWcdrw"

#
# You would have specified the additional repository like this in the manifest
#
#                 
#   <pkg_repo_addl_authority>
#        <main url="http://localhost:10000" authname="localtest"/>
#   </pkg_repo_addl_authority>

# Get the alternate repository URL from the manifest
add_url=/usr/bin/ManifestRead ${MFEST_SOCKET} \
"distro_constr_params/pkg_repo_addl_authority/main/url"

# Get the alternate repository authority from the manifest
add_auth=/usr/bin/ManifestRead ${MFEST_SOCKET} \
"distro_constr_params/pkg_repo_addl_authority/main/authname"

added_authority=0

#
# Check to see if authority is already set in the package image area
# if not, add it in
#
${PKGCMD} -R $PKG_IMG_PATH authority $add_auth > /dev/null 2>& 1
if [ $? != 0 ] ; then
        ${PKGCMD} -R $PKG_IMG_PATH  set-authority -O ${add_url} ${add_auth}
        added_authority=1
fi

if [$? != "0" ] ; then
        print -u2 "$0: Unable to set additional authority"
        exit 1
fi

for t in ${TEST_PKGS} ; do
        pkg_name="pkg://${add_auth}/${t}"
        ${PKGCMD} -R $PKG_IMG_PATH install ${pkg_name}
        if [$? != "0" ] ; then
                print -u2 "$0: Unable to install ${pkg_name}"

                exit 1
        fi
done

# if we have added the additional authority, unset it so it doesn't pollute what's
# originally there
if [ $added_authority == 1 ] ; then
         ${PKGCMD} -R $PKG_IMG_PATH  unset-authority ${add_auth}
fi

return 0

Because this type of finalizer script adds or removes packages from the package image area, you must reference the script as the first finalizer script in the <finalizer> section of the manifest file. Include in this reference a checkpoint name that indicates the point in the image-building process where you want to restart the build to test your added package.

For example, if you have created a script, export/home/user1/test_my_pkg, to test your custom package, you would reference the script as follows in the finalizer section of the manifest file. Note that a checkpoint, named “my_test,” indicates where the build will restart.

<finalizer>
      <script name="/export/home/user1/test_my_pkg">
           <checkpoint name="my_test" message="Running my test package"
      </script>
      <script name="/usr/share/distro_const/pre_bootroot_pkg_image_mod">
           <checkpoint name="im-mod" message="Image area modifications"/>
      </script>
      ........
</finalizer>

After you made the changes to the manifest file to reference your new script, you can start building your image from the beginning once. After that, if you make any changes to your package, you do not need to restart from the beginning . You can generate an image with your modified package by starting at the checkpoint that runs your script.

The following are the sequence of commands a user would execute to repeatedly test their modifications to packages.

  1. Run the build from the beginning after modifying the manifest. Do this only once.

    distro_const build /my_updated_manifest.xml
  2. Check steps that are resumable.

    distro_const build -l /my_updated_manifest.xml
  3. Restart from the step of your package modification. You can restart from this step as many times as you need while you debugging your modified contents.

    distro_const build -r my_test /my_updated_manifest.xml

For further information about using the distro_const command with checkpointing options, as demonstrated in this example, see Using Checkpointing to Create an Image.

Testing Packages

When a particular package is specified in the package section of a manifest file, that package is installed in the package image area by the distribution constructor. If you have an alternate version of this package, such as your own private copy of a package, you could test this version of the package by using a custom finalizer script. The finalizer script would replace the previously installed version of the package with a test version from an alternate repository.

In the following custom script, an IPS repository server is running on http://localhost:10000. The name of the package to replace is passed as an argument. The script first uninstalls the existing version of the package, then installs the test version from the alternate repository. This custom script also demonstrates how to get arguments passed in as finalizer script arguments. Note the comments in the script that explain how the script accomplishes these tasks.

Example 3-4 Script for Testing an Alternate Package
#!/bin/ksh
#
#
# Args:
#
#   These Arguments are passed in by default from the DC.
#
#   MFEST_SOCKET: Socket needed to get manifest data via ManifestRead object \
# (not used in this example)
#   PKG_IMG_PATH: Package image area
#   TMP_DIR: Temporary directory
#   BR_BUILD: Area where bootroot is put together (not used in this example)
#   MEDIA_DIR: Area where the media is put (not used)
#   PKG_NAMES: Package to replace with one from the test repo. 
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

if [ "$#" != "6" ] ; then
        print -u2 "Usage: $0: Requires 6 args:"

        print -u2 "    Reader socket, pkg_image area, tmp dir,"
        print -u2 "    bootroot build area, media area, pkg_name"
        exit 1
fi


PKG_IMG_PATH=$2
if [ ! -d $PKG_IMG_PATH ] ; then
        print -u2 "$0: Image package area $PKG_IMG_PATH is not valid"
        exit 1
fi

PKGCMD="/bin/pkg"

#The test packages are passed in as arguments to this finalizer script
#You would have specified the argument like this in the finalizer section
#to pass in the argument
#
#
#  <finalizer>
#       <script name="/my/update_my_pkg_test">
#               <checkpoint name="update-pkg" message= \
"Replaces an existing package with my own"/>
#                    <argslist>

#                       "SUNWcdrw"
#                    </argslist>
#        </script>
#  </finalizer>
#
TEST_PKG=$6

#hard code alternate repository and authority.  Assume that my test package resides in
#a repository running on port 10000 of the localhost.

# Get the alternate repository URL from the manifest
add_url="http://localhost:10000"

# Get the alternate repository authority from the manifest
add_auth="MY_TEST"

added_authority=0

# Check to see if authority is already set in the package image area, if not,
# add it in
${PKGCMD} -R $PKG_IMG_PATH authority $add_auth > /dev/null 2>& 1
if [ $? != 0 ] ; then
        ${PKGCMD} -R $PKG_IMG_PATH  set-authority -O ${add_url} ${add_auth}
        added_authority=1
fi


if [$? != "0" ] ; then
        print -u2 "$0: Unable to set additional authority"
        exit 1
fi

# Remove the package that's currently in the package image area.
${PKGCMD} -R $PKG_IMG_PATH uninstall ${TEST_PKG}
if [$? != "0" ] ; then
        print -u2 "$0: Unable to uninstall ${TEST_PKG}"
        exit 1
fi

# Install the package from test repo
pkg_name="pkg://${add_auth}/${TEST_PKG}"

${PKGCMD} -R $PKG_IMG_PATH install ${pkg_name}
if [$? != "0" ] ; then
        print -u2 "$0: Unable to install ${pkg_name}"
        exit 1
fi

# if we have added the additional authority, unset it so it doesn't pollute what's
# originally there
if [ $added_authority == 1 ] ; then
         ${PKGCMD} -R $PKG_IMG_PATH  unset-authority ${add_auth}
fi

return 0
Adding a SVR4 Package

If you have a package that is in SVR4 format, you can test that package in an image before you convert it into an IPS package. You can use a finalizer script to add the content of a SVR4 package to the image. See the following custom script and note the comments in the script that explain how the script accomplishes this task.

Example 3-5 Script for Adding a SVR4 Package
#!/bin/ksh
#
#
# Args:
#
#   5 arguments are passed in by default from the DC.
#
#   MFEST_SOCKET: Socket needed to get manifest data via ManifestRead object (not used)
#   PKG_IMG_PATH: Package image area
#   TMP_DIR: Temporary directory
#   BR_BUILD: Area where bootroot is put together (not used in this example)
#   MEDIA_DIR: Area where the media is put (not used)
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

if [ "$#" != "5" ] ; then
        print -u2 "Usage: $0: Requires 5 args:"

        print -u2 "    Reader socket, pkg_image area, tmp dir,"
        print -u2 "    bootroot build area, media area, pkg_name"
        exit 1
fi

PKG_IMG_PATH=$2
if [ ! -d $PKG_IMG_PATH ] ; then
        print -u2 "$0: Image package area $PKG_IMG_PATH is not valid"
        exit 1
fi

TMP_DIR=$3

#
# Install a SVR4 packages into the package image area
#

#create an admin file for non-interactive pkgadd's

ADMIN_FILE=${TMP_DIR}/admin.$$
cat << \ADMIN_EOF > $ADMIN_FILE
mail=
instance=unique
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=nocheck
setuid=nocheck
conflict=nocheck
action=nocheck
networktimeout=60
networkretries=3
authentication=quit
keystore=/var/sadm/security
proxy=
basedir=default
ADMIN_EOF

#
# Path to your new packages
#
PKG_PATH=/path/to/my/test/svr4_pkg

#
# Test package name 
#
SVR4_TEST_PKG=SUNWmy-test

/usr/sbin/pkgadd -n -a ${ADMIN_FILE} -d $PKG_PATH -R ${PKG_IMG_PATH} ${SVR4_TEST_PKG}

if [ $? != "0" ] ; then
        echo "installing package failed"

        exit 1
fi

/bin/rm ${ADMIN_FILE}

return 0
Previous Next