N1 Grid Service Provisioning System 5.0 Plug-in Development Guide

Creating Components and Plans

To be able to effectively reproduce a given solution across an enterprise, you need to define components, resources, and plans that identify common parts of the solution. In addition, you need to define a process for deploying them. For more information about plans, components, and how to manage them, see N1 Grid Service Provisioning System 5.0 Plan and Component Developer’s Guide.

Building Components

A key piece in developing your solution is creating components. In the N1 Grid Service Provisioning System environment, components are deployable objects. Some examples of the objects you might have in components include the following:

For information about creating components by using the N1 Grid Service Provisioning System browser interface, see How to Create a Component in N1 Grid Service Provisioning System 5.0 Plan and Component Developer’s Guide.

Simple and Composite Components

Simple components contain a single physical resource, such as a file, directory, archive file, or application. Simple components do not reference other components.

Composite components only reference other simple or composite components. Composite components do not directly contain any physical resources.


Example 2–1 XML for a Simple Component

The following XML example shows a simple component that extends the system component type system#CR Simple Base to contain a JAR file. For more information about the specific elements and attributes used to define a component, see Chapter 3, Component Schema, in N1 Grid Service Provisioning System 5.0 XML Schema Reference Guide.

<?xml version="1.0" encoding="UTF-8"?>
<component xmlns='http://www.sun.com/schema/SPS' name='plugin-core.jar' 
    version='5.0' description='Jar file implementation of core plugin services' 
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' author='system' 
    softwareVendor='Sun Microsystems' path='/system' 
    xsi:schemaLocation='http://www.sun.com/schema/SPS component.xsd'>
  <extends>
    <type name='system#CR Simple Base'>
    </type>
  </extends>
  <resourceRef>
    <resource name='/system/plugin-core.jar' version='1.1'>
    </resource>
  </resourceRef>
</component>

Variables

When you create a component or plan, you can define variables to use when that component is deployed or the plan is executed. Many component types include common variables, such as installPath, which defines where to install the component. The value of the installPath variable is determined for a given host when the component is installed on that host.

Some common variables that you might see include the following:

A variable can refer to another variable, such as the variable of a container component. For example, the value of the installPath variable for a simple component could be the value of the installPath variable for its parent container component.

When defined, each variable must have a name and a default value attribute. The default value can be obtained from several places:

For detailed information about using these attributes, see Types of Variables Available for Substitution in N1 Grid Service Provisioning System 5.0 Plan and Component Developer’s Guide.

You can define a variable through the browser interface or directly in the XML file. Within the XML file, variables are defined using the <var> element and contained within a <varList> element.


Example 2–2 Variable Definitions in XML

The following XML fragment shows several variable definitions.

<varList>
    <var name='installPath' 
         default=':[target:sys.raDataDir]:[/]systemcomps'>
    </var>
    <var name='pluginClasspath' 
         default=':[installPath]:[/]plugin-core.jar'>
    </var>
    <var name='fileBrowser' 
          default='com.sun.n1.sps.pluginimpl.system.browse.FilesystemBrowserFactory'>
    </var>
    <var name='directoryBrowser' 
          default='com.sun.n1.sps.pluginimpl.system.browse.FilesystemBrowserFactory'>
    </var>
    <var name='symlinkBrowser' 
          default='com.sun.n1.sps.pluginimpl.system.browse.FilesystemBrowserFactory'>
    </var>
</varList>

Configuration Templates

A configuration template is a special type of file component. The configuration template enables you to do token substitution in a file that you are deploying. An example of this usage would be deploying the DNS /etc/resolv.conf file. The goal for deployment might be to have the file use a variable substitution and use a host type attribute to define the closest DNS server. The configuration template might look like the following example:

search :[search_path]
nameserver :[primary_dns]
nameserver :[secondary_dns]

In this case, the configuration template would automatically create component variables called search_path, primary_dns, secondary_dns. Then you could use variable substitutions in plans or component controls to provide appropriate values.

ProcedureHow to Define a Configuration Template

Step

    To designate a file component as a configuration template, select “configuration template” in the Options section of the Component Details page.

Defining Component Types

Many basic component types are included with the N1 Grid Service Provisioning System product. Some of these basic component types include such items as files and directories. You can also define specific component types for use with a specific application or platform. For example, perhaps your application has some specific file types that would always exist for this application. You could then define a new component type for your application that is based on the system#CR Simple Base component type but extends that component type for your specific application.

The component type definition is stored in an XML file like any other component XML file. When you define your plug-in, you provide a path to the file for the backing component in the <component> element in the descriptor file. You use the <componentType> child element of the <component> element to provide additional information, such as its name, description, and so on. For more information, see Example 2–15.

ProcedureHow to Create a Component Type

Steps
  1. Determine what component types you need to create.

  2. From the Administrative section of the browser interface, click Component Types.

  3. From the Component Types page, click Create in the Action column.


    Note –

    You can type a name for the component type before you choose the Create action or you can type or change the name in the Edit window. Once you check in the component type, you cannot change its name.


  4. Accept the name or change it.

    A component type name has a maximum of 64 characters. The name must start with a letter or underscore, followed by any number of letters, digits, or special characters, such as underscore (_), period (.), plus (+), minus (-), and space ( ). Unicode letters and digits are permitted.

  5. (Optional) Type a menu group name.

    Group names follow the same requirements as the component type name . In addition, a group can be declared as hidden, which prevents the type from showing up in the component type drop-down list on the component list page.

  6. Type an alpha-numeric string for the menu order.

    The menu order is a maximum of 18 characters. In addition to Unicode letters and digits, any character that you can type on an ASCII keyboard is permitted. The order should be sufficient to sequence all of the types that are defined within a particular plug-in.

  7. Type a numeric value between 0 and 10 for the indent level.

    The indent level specifies how types should appear within the component type drop-down list on the component list page. Indents are used in conjunction with ordering to imply relationships between component types. For example, a wep app type might have related types web app configuration and web app archive that are indented more to highlight the relationship.

  8. (Optional) Type a description.

    The description must be less than 1024 characters in length. In addition to Unicode letters and digits, any character that you can type on an ASCII keyboard is permitted.

  9. Select a backing component.

    A backing component provides a template for the component type.

  10. Click Save.

Creating Plans

A plan is a sequence of instructions that is used to manage one or more components on the specified hosts. For example, a plan might install three components and initiate the startup control of another component. To create most plans, you have to edit the XML. The one exception to this rule is an auto-generated plan. The N1 Grid Service Provisioning System software can automatically generate a plan consisting of direct run procedures. For example, you could auto-generate a plan that consists of installing a single component. You could then run this plan directly or save it for use as a template for authoring more complex plans.

Simple and Composite Plans

Simple plans contain a series of deployment instructions, or steps. Simple plans are executed on a single host or host set. Simple plans can call common procedures, such as install or uninstall, and can also use conditional programming constructs.

Composite plans contain calls to simple plans. Composite plans can apply some procedures to one host, while applying other procedures to a different host or host set.


Example 2–3 XML for a Simple Plan

A simple plan might look like the following example. This plan provides an install block and an uninstall block. For more information about the specific elements and attributes used to define a plan, see Chapter 4, Plan Schema, in N1 Grid Service Provisioning System 5.0 XML Schema Reference Guide.

<?xml version="1.0" encoding="UTF-8"?>
<!-- generated by N1 SPS -->
<executionPlan xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
    name='plugin-core.jar-1096573592002' version='5.0' 
    xsi:schemaLocation='http://www.sun.com/schema/SPS plan.xsd' 
    xmlns='http://www.sun.com/schema/SPS' path='/system/autogen'>
    <simpleSteps>
        <install blockName='default'>
            <component name='plugin-core.jar' path='/system' version='1.1'>
            </component>
        </install>
        <uninstall blockName='default'>
            <installedComponent name='plugin-core.jar' versionOp='=' 
                 version='1.1' path='/system'>
            </installedComponent>
        </uninstall>
    </simpleSteps>
</executionPlan>


Example 2–4 XML for a Composite Plan

A composite plan might look like the following example. This example calls three sub-plans.

<executionPlan 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  name="apache-tomcat-uninstall" version="4.0"
  xsi:schemaLocation="http://www.centerrun.com/schema/CR plan.xsd"
  xmlns="http://www.centerrun.com/schema/CR">
    <compositeSteps>
        <execSubplan planName="mod-jk-uninstall" />
        <execSubplan planName="apache-uninstall" />
        <execSubplan planName="tomcat-uninstall" />
    </compositeSteps>
</executionPlan>


Example 2–5 XML for a More Sophisticated Plan

The following example shows a more complicated plan that determines what to execute based on some conditions.

<?xml version="1.0" encoding="UTF-8"?>
<!-- generated by CR -->
<executionPlan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    name="BAM_backout_new_version_NODE-A" version="4.0" 
    xsi:schemaLocation="http://www.centerrun.com/schema/CR plan.xsd" 
    xmlns="http://www.centerrun.com/schema/CR" path="/plans/uat">
   <paramList>
      <param name="backout_type" prompt="Enter type of backout (all,ear,prop)"></param>
   </paramList>
   <varList>
      <var name="admin_server" default="wusx119"></var>
      <var name="node" default="wust3022"></var>
      <var name="wl_server_name" default="bamC"></var>
      <var name="apphome" default="/opt/uat/ceodomain"></var>
      <var name="prop_args" default="-s wust3022"></var>
      <var name="application_name" default="bam"></var>
      <var name="staging_base" default="/usr/local"></var>
      <var name="user" default="weblogic"></var>
   </varList>
   <simpleSteps limitToHostSet="uat-bam">
      <if>
         <condition>
            <or>
               <equals value2="all" value1=":[backout_type]"></equals>
               <equals value2="prop" value1=":[backout_type]"></equals>
               <equals value2="ear" value1=":[backout_type]"></equals>
            </or>
         </condition>
      <then>
         <call blockName="backout_application">
            <argList application_name=":[application_name]" 
                 staging_base=":[staging_base]" 
                 backout_type=":[backout_type]" 
                 user=":[user]">
            </argList>
            <installedComponent name="deploy_tools" 
                  path="/components/function_library">
             </installedComponent>
         </call>
         <call blockName="wl_stop">
            <argList wl_server_name=":[wl_server_name]" 
                  node=":[node]" apphome=":[apphome]" user=":[user]">
            </argList>
            <installedComponent name="deploy_tools" 
                  path="/components/function_library">
            </installedComponent>
         </call>
         <if>
            <condition>
              <equals value2="all" value1=":[backout_type]"></equals>
            </condition>
         <then>
               <call blockName="clusterdeploy">
                  <argList application_name=":[application_name]" 
                        staging_base=":[staging_base]" node=":[node]" user=":[user]">
                  </argList>
                  <installedComponent name="deploy_tools" 
                        path="/components/function_library">
                  </installedComponent>
               </call>
               <call blockName="deploy_prop">
                  <argList application_name=":[application_name]" 
                        prop_args=":[prop_args]" staging_base=":[staging_base]" 
                        user=":[user]">
                  </argList>
                  <installedComponent name="deploy_tools" 
                        path="/components/function_library">
                     </installedComponent>
                  </call>
                  <call blockName="wl_startjsp">
                     <argList application_name=":[application_name]" 
                        wl_server_name=":[wl_server_name]" 
                        node=":[node]" apphome=":[apphome]" user=":[user]">
                     </argList>
                     <installedComponent name="deploy_tools" 
                        path="/components/function_library">
                     </installedComponent>
                  </call>
               </then>
            </if>
            <if>
               <condition>
                  <equals value2="ear" value1=":[backout_type]"></equals>
               </condition>
               <then>
                  <call blockName="clusterdeploy">
                     <argList application_name=":[application_name]" 
                        staging_base=":[staging_base]" node=":[node]" user=":[user]">
                     </argList>
                     <installedComponent name="deploy_tools" 
                        path="/components/function_library">
                     </installedComponent>
                  </call>
                  <call blockName="wl_startjsp">
                     <argList application_name=":[application_name]" 
                        wl_server_name=":[wl_server_name]" 
                        node=":[node]" apphome=":[apphome]" user=":[user]">
                     </argList>
                     <installedComponent name="deploy_tools" 
                        path="/components/function_library">
                     </installedComponent>
                  </call>
               </then>
            </if>
            <if>
               <condition>
                  <equals value2="prop" value1=":[backout_type]"></equals>
               </condition>
               <then>
                  <call blockName="deploy_prop">
                     <argList application_name=":[application_name]" 
                        prop_args=":[prop_args]" 
                        staging_base=":[staging_base]" user=":[user]">
                     </argList>
                     <installedComponent name="deploy_tools" 
                        path="/components/function_library">
                     </installedComponent>
                  </call>
                  <call blockName="wl_start">
                     <argList application_name=":[application_name]" 
                        wl_server_name=":[wl_server_name]" 
                        node=":[node]" 
                        apphome=":[apphome]" 
                        user=":[user]">
                     </argList>
                     <installedComponent name="deploy_tools" 
                        path="/components/function_library">
                     </installedComponent>
                  </call>
               </then>
            </if>
         </then>
         <else>
            <raise message="Please enter a valid deployment type (all/ear/prop)"></raise>
         </else>
      </if>
   </simpleSteps>
</executionPlan>

ProcedureHow to Generate a Plan

Steps
  1. Go to the Components page.

  2. Select the component for which you want to generate the plan.

  3. View the component's details.

  4. If needed, scroll down the page until you see Component Procedures.

  5. Select the procedures that you want to use in the plan.

  6. Click Generate Plan with Checked Procedures.

    The Plans editing page appears. From this page, you can modify the XML to include more complex steps, like those shown in Example 2–5.

Using Native Commands in Plans and Components (<execNative> Step)

The <execNative> XML step enables you to run native commands from within your plans and components. For example, if you need to verify that a process has started, you might use <execNative> to call the UNIX ps command. For more information about the <execNative> schema, attributes, and child elements, see <execNative> Step in N1 Grid Service Provisioning System 5.0 XML Schema Reference Guide.

Before <execNative> executes the specified command, the N1 Grid Service Provisioning System software verifies that the command exists and that the specified user has permission to run the command. If either of these checks fail, <execNative> exits with an error.


Example 2–6 Using <execNative> to Invoke a Simple Command

The following <execNative> example performs the equivalent of the UNIX ps -ef command.

<execNative>
    <exec cmd="ps">
        <arg value="-ef" />
    </exec>
</execNative>


Example 2–7 Using <execNative> to Start an Application

The following <execNative> example starts a web server instance.

<execNative
  dir="/opt/ns/https-admserv"                Set working directory
  userToRunAs="webadmin"                     Equates to "su -webadmin"
  timeout="5">
    <inputText>
        start.sh                             Input parameters to command
    </inputText>
    <exec cmd="sh />                         Command to run
    <successCriteria status="0" />           execNative succeeds only if exit code is "0"
</execNative>

Calling Java-based Objects in Plans and Components (<execJava>)

The <execJava> mechanism enables agent-side, in-process execution of client-provided Java code within a plan or component definition. <execJava> is similar to <execNative>, but is specifically intended to enable execution of Java code.

The <execJava> feature is provided as an XML step and as a Java-based API. For information about the XML schema, attributes, and child elements, see <execJava> Step in N1 Grid Service Provisioning System 5.0 XML Schema Reference Guide. For more information about the execJava API, including examples, see execJava API.

The <execJava> XML step has one required and two optional attributes:

The <execJava> mechanism can pass arguments to the Java Executor using the <argList> child element.


Example 2–8 Using <execJava> in Component XML

<varList>
   <var name="installPath" default="/opt/util"/>
</varList>
<resourceList defaultInstallPath=":[installPath]">
   <resource resourceName="util/propPrint.jar" installName="propPrint.jar"/>
</resourceList>
   ...
<controlList>
   <control name="showProp"/>
   <paramList>
       <param name="propName">
   </paramList>
   <execJava
       className="com.raplix.util.PropertyPrinterFactory"
       classPath="$[installPath]/propPrint.jar">
       <argList>
           <arg name="propertyName" value=":[propName]"/>
       </argList>
       <successCriteria outputMatches="<undefined>" inverse="true"/>
   </execJava>


Example 2–9 Using <execJava> in Plan XML

<executionPlan xmlns="http://www.sun.com/schema/SPS" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://www.sun.com/schema/SPSplan.xsd" 
   name="execJavaExample" version="5.0">
   <paramList>
       <param name="name"></param>
       <param name="value"></param>
   </paramList>
   <varList>
       <var name="classpath" 
           default=":[target:sys.raDataDir]:[/]systemcomps:[/]plugin-com.sun.sample.jar"/>
   </varList>
   <simpleSteps>
       <execJava className="com.sun.n1.sps.pluginimpl.sample.executor.SampleExecutorFactory"
           classPath=":[classpath]">
           <argList nameParam=":[name]" valueParam=":[value]" />
       </execJava>
   </simpleSteps>
</executionPlan>

Conditional Elements

Within a plan or a component, you can use the <if> element to conditionally perform a block of steps. Similar to traditional programming if-then-else constructs, the statement within the <if> element is evaluated. If that statement is true, then the steps of the <then> element are performed. Otherwise, the steps of the <else> element are performed. If no <else> element exists, then no action is taken.


Example 2–10 XML for <if> Element

The following example uses the <if> element to allow users to decide at deployment time whether to take a snapshot.

<if>
    <condition>
        <istrue value=:[createSnapshot]"></istrue>
    </condition>
    <then>
        <createSnapshot blockName="default"></createSnapshot>
    </then>
</if>

Error Handling

The XML schemas provides a set of elements for handling possible errors . The parent of this set of elements is the <try> element. You might use these elements for situations similar to the following examples:

The <try> element includes a block of steps that are executed in order until either all complete successfully or a step fails. If a step fails and a <catch> element exists, then the steps in the <catch> element are executed in order until they succeed or a step fails. If a <finally> element is defined, the steps in the <finally> element are executed in order until all steps complete or a step fails regardless of whether the <try> and <catch> elements succeeded. Typically, the <finally> element is used to perform clean-up functions or release resources.

The <raise> element is used to indicate a failure condition without having to create a step to do so. The <raise> step always fails. Although the <raise> element can be used by itself, it is often contained within a <catch> element block.


Example 2–11 XML for <try> Element

The following XML example uses the <try> element to determine whether a fresh install or an upgrade install should be performed.

<installSteps blockName="default">
    <try>
        <block>
            <checkDependency>
                <installedComponent name="foo" version="1.0" />
            </checkDependency>
        </block>
        <catch>
        </catch>
    </try>
</installSteps>