Navigating the IBM Cloud with Workload Deployer and PureApplication Systems

Part 3: Creating Script Packages

Introduction

If you have been following this series, you will have noticed that Part 1 introduced cloud computing concepts in general. Part 2 introduced the concept of patterns and explained how to create virtual system patterns in IBM Workload Deployer and IBM Pure Application Systems. Following that discussion, this article show how script packages work and how they link virtual system patterns with the actual systems that get deployed with those patterns.

Script packages
Script packages
provide a way for you to customize parts in virtual system patterns, beyond the customizations already provided by IBM® Workload Deployer or IBM PureApplication Systems. Part 2 taught you how to create and deploy virtual system patterns composed of preconfigured virtual images called parts. But connecting parts to create a virtual system pattern is only half the story. These parts will usually need further customization to meet the needs of a specific application. For example, creating and deploying a virtual system pattern consisting of a WebSphere Application Server Deployment Manager part and two custom node parts will federate the nodes to the deployment manager, but not automatically cluster the application servers. Additional tasks such as these are done through script packages.

When editing a virtual system pattern in the Pattern Editor, you can attach a script package to a part by simply dragging and dropping it directly onto that part:

A part can contain multiple script packages and, as Part 2 of this series explains, you can order which parts and script packages should execute first throughout the pattern via the Ordering view. This view lets you drag and drop parts and scripts to establish their execution order.

Script packages also let you specify parameters that get passed as environment variables to the part so that you can make the scripting configurable and reusable. This enables a single script to be used for multiple parts, requiring only that the person deploying the pattern change specific values. This also, of course, makes the parts reusable. Similarly, you can save a set of connected parts and their scripts as a single reusable virtual system pattern.

Preparing for script packages
The example presented here is quite simple, the equivalent of a “Hello World” example for script packages. The goal is to show you step-by-step how script packages work, without unnecessarily complicating things. Therefore, this article focuses specifically on script packaging tasks and is not intended to teach shell scripting or Jython programming. A basic understanding of virtual patterns and how you build them from parts and scripts is assumed. If you need a refresher, see Part 2 of this series.

To begin, perform the following steps:

  1. Create a simple virtual system pattern that uses a “Standalone server” part. The part used in this example is labeled, Standalone server, WebSphere Application Server 8.0.0.1, ESX, RHEL 64-Bit 5. If you don’t have that one in your catalog, a similar part should do. For information on how to create a virtual system pattern, see Part 2 of this series.
  2. Deploy the virtual system pattern, and wait until its corresponding virtual machine starts.
  3. After the virtual machine starts, expand its node to display system information, such as the hypervisor and the cloud group it is running on, its hardware, software, and networks configuration, environment metrics, and any associated script packages. Find and click the blue link titled, Show all environment variables. This will open a separate browser window that shows environment variables available to your script package:

Environment variables
The variables that appear are called script package environment variables because the system passes them to the virtual machine together with your script package so that the scripts can read them and behave accordingly. For example, an environment variable called CELL_NAME allows a script running on the virtual machine to know the name of the cell to which that virtual machine belongs.

The way the system passes environment variables to a virtual machine is by placing them in a file called virtualimage.properties in the virtual machine’s /etc directory. You can access the virtual machine through SSH or the VNC viewer to easily confirm that:

Each virtual machine gets its own virtualimage.properties file, which contains the default environment variables in addition to any new variables defined in the script package. The default variables that are included will depend partially on the content of the virtual machine itself. For example, if a virtual machine is a custom node, its virtualimage.properties file will contain variables relating to IBM WebSphere® Application Server. Similarly, a DB2 node will contain variables pertaining to IBM DB2®. In addition to these middleware-specific variables, the virtualimage.properties file will also include variables that point to specific scripts and locations for managing the lifecycle of the virtual machine.

Some environment variables that appear in the web interface, might not be included in the corresponding virtualimage.properties file. Examples of these include OS_TYPE, OS_NAME, and OS_VERSION_LEVEL. Similarly, the virtualimage.properties file might include additional variables used by the IBM Workload Deployer or IBM PureApplication System that will not appear in the web interface. Examples of these include variables that start with the prefixes WCA_ or PUREAPPLICATION_.

Inside a Script Package
A script package is simply a .zip or .tgz (.tar.gz) file that contains:

  • One or more scripts; these are usually shell scripts or Jython scripts, but can be anything executable from the command line or from other scripts.
  • A JSON object inside a file called cbscript.json that describes the script package and points to the location of the main script, among other things. The cbscript.json file must be located in the root directory of the script package.

A script package can contain many scripts, each performing specific tasks, and invoking other scripts as needed, but the cbscript.json file must be located in the root directory of the .zip or .tgz file, and it must point to the script that will be the starting point of execution. Listing 1 shows a simple script, and Listing 2 shows the corresponding cbscript.json file used for this example.

Listing 1. helloscriptworld.sh

Listing 2. cbscript.json

To continue with this example, create the files shown in Listings 1 and 2, and then compress them using the tar command under Linux®:

If you are working with Windows®, you can create a .zip file instead using any zip tool available. This example uses a .zip file called helloscriptworld.zip. Either way, for purposes of this example, the final compressed file must contain two files: cbscript.json and helloscriptworld.sh, both in the root directory.

NOTE: Because the content of the script package will be running on Linux, if you create the .json and script files in Windows, make sure you use an editor that supports UNIX®-style text files; that is, you will need to save these files with an editor that can write a single Line Feed (LF) character to signify a new line (UNIX mode) instead of a typical Windows-style Carriage Return + Line Feed (CRLF). Otherwise your scripts won’t run in Linux. There are many free editors available that support saving text files in the Linux manner.

Uploading the script package
Once you have prepared your .zip or .tgz file, you can upload the script package into the IBM Workload Deployer or IBM PureApplication System, as outlined in the following steps:

  1. Select Script Packages from the Catalog menu.
  2. From the Script Packages pane, click the green plus sign to create a new script. You will notice that some scripts, such as Add IBM HTTP Server node, are added by default to the system.
  3. Name your script Hello Script World and click OK. The result should look similar to this:

Click Browse… and select your script package; then press Upload. Shortly after, you should see a screen similar to this:

Notice a few things:

  • The system reads the cbscript.json file to determine the initial script that should run (in this case: /etc/helloscriptworld.sh), as well as the different directory locations it should use. Working directory is where the system will place and extract the script package files, and Logging directory is where it will place log files. You can also specify command line arguments that should be passed to the script, and select whether the script should execute when the virtual machine gets created, when it gets deleted, or when the user manually initiates it via the Execute Now link which appears below the link for displaying the virtual machine’s environment variable.
  • The Environment section shows the variable you defined in the cbscript.json file, under the “keys” section (Listing 2). This variable, called NAME, with a default value of “World,” will get automatically added to the resulting /etc/virtualimage.properties file of any part that uses this script. It will also be one of the parameters for the script that you can configure from either the Pattern Editor or during deploy time.
  • The Environment section lets you add additional variables. These too would be automatically added to the resulting etc/virtualimage.properties file. The following two figures illustrate this point:

You may have noticed that, for every key defined in the cbscript.json file, there is a scriptvalue field and a scriptdefaultvalue field. The difference between these is that using scriptvalue sets a non-editable value into the associated key, while using scriptdefaultvalue sets a default value that the user can edit.

Using passwords as parameters
If you use a script key that contains the word “password,” whether in upper- or lowercase, the IBM Workload Deployer or IBM PureApplication System will automatically consider that a password field and treat it accordingly; that is, when a user enters a value for a password-based parameter the system will only display bullets versus the typed text for security reasons.

Adding a script package to a part
Now, it’s time to add the uploaded script package to the Simple Script Example virtual system pattern you created earlier:

  1. Open the Simple Script Example pattern and add the Hello Script World script by finding it in the Script section of the Pattern Editor and dragging it onto the Standalone server part. You should see the Hello Script World script added to your part.
  2. Click the Parameters button for the script to verify that the NAME parameter you defined in the cbscript.json file appears and shows the default value “World.” The NAME parameter appears because you either defined it in the cbscript.json file or added it directly from the GUI after uploading the script package. This parameter, in turn, is added to the /etc/virtualimage.properties file of the virtual machine when the pattern is deployed, so that it becomes accessible to the script.

3. Press Done Editing when finished.

Executing your script
To test your script, you will need to redeploy the virtual system pattern. First, delete the existing virtual system instance created earlier and then redeploy the pattern to create a new instance. Once the virtual machine starts, log into it via SSH or through the VNC viewer, and verify that your script ran correctly. This is what things should look like:

The section within the yellow outline confirms that the script package files were placed in the /etc directory as requested in the cbscript.json file, and the section inside the red outline shows the output of the script as it was piped into the greeting.txt file.

Scripts run by default using the root user context. If you need to run certain tasks in the context of a different user, you can use the su command and start a second script to perform those tasks.

Working with variables not known until deployment time
Finally, there are some situations in which you will need to work with a variable that is not known until deployment time. Hostname, used earlier, is a good example. Because the IBM Workload Deployer or IBM PureApplication System assigns hostnames and IP addresses to virtual machines as they get deployed, if a script running on a virtual machine needs to automatically pick up the hostname of a different virtual machine that is part of the same pattern, the script will not have visibility to that information until after the deployment of the pattern, at which point it might be too late. For situations like these, you need to use the following syntax:

This format allows you to reference variables whose value will be known at a later time. Recall that each part you drag onto the canvas of the Pattern Editor is assigned a name. You can view this name by clicking the Properties button of the part in the Pattern Editor:

In this case, the part’s name is StandalonePart. That’s the name that corresponds to part-name in the syntax above.

Using the ${part-name.property-name} formula for a particular value tells the system to resolve the value of property-name before placing the new variable in the virtualimage.properties file of the requesting virtual machine.

Let’s explore a quick example:

  • Assume virtual machine A has a script that needs to know the hostname of virtual machine B as part of its script.
  • Since virtual machines correspond to parts in a virtual system pattern, let’s call the first virtual machine PartA and call the second one PartB.
  • PartA has a single script that runs and which needs to know the hostname of PartB in order to perform certain configuration tasks.
  • For this to work, the script package for PartA needs to include a variable that defines the following as its value (the part in bold below):
    HostnameofPartB = ${PartB.hostname}
  • This tells the system to place a new variable called HostnameofPartB in the virtualimage.properties file of PartA after, of course, it has figured out the hostname of PartB.
  • The script in PartA will then be able to use the variable HostnameofPartB whenever it needs to reference the hostname of PartB.

Besides custom property names, you also have access to these built-in values:

Network-related

  • hostname
  • domain
  • ipaddr
  • netmask
  • gateway
  • pri_dns
  • sec_dns

WebSphere Application Server-related

  • cell_name
  • node_name
  • augment_list

Locale-related

  • language
  • country
  • encoding

Conclusion
This concludes our discussion on creating script packages. Script packages provide the glue that enable virtual system patterns to be customized for specific needs. Through the right use of property names and parameters, script packages can be made reusable across different parts and virtual system patterns. A script package can be made as simple as a single script file and a JSON object, or as complex as an entire product. How you create your own packages will depend on the needs of your enterprise and on how you want to build your catalog of reusable parts, scripts, and patterns.

José is a Thought Leader Executive Architect with IBM, specializing in Cloud Architectures and App Modernization.