Intended audience

This page is aimed at patch developers with experience on Sentinel.

Patch development guideline

The general steps in creating a patch are:

  • a bug is identified and the system needs a fix

  • create a branch from the same release version of the product

  • replicate the problem by creating an integration test that simulates the bug

  • make the proper code modifications to solve the bug

  • if necessary create more integration tests

  • check the problem is fixed by running the system against specific integration tests

  • verify that all integration tests are passing to guarantee the fix didn’t break any other behaviour

  • create the patch

  • test the patch against the same installed version of the destination system

  • test the reverse patch against the system with the patch installed

  • review and add the proper information in the patch README.txt

  • release the patch to be applied

The steps above compose the recommended guideline to create a patch and the patch generator is just a step in the whole procedure.

Creating the patch

Creating a patch after the code changes were applied is simple:

  • build the product module that will be patched and check the jar is in the local cache or in the target/artifacts directory

  • have a Rhino running with the product to be patched

  • get the from the Artifactory and save it to the local machine

  • define a metadata file with the following format:

patchName: 'customer-name-VOLTE-1234'
productName: 'Volte'
productVersion: ''
patchVersion: '1'
ticket: 'VOLTE-1234'
description: 'Fix crash on call teardown'
    sentinel-volte: 45476adc
    sentinel-core: 33397cc

The recommended filename is metadata.yaml, but this is not important.

Note Use --dev-mode to avoid specifying the metadata. This shall not be used for production patches.
  • unzip

  • run the

"" \
    -c <rhino client dir>  \
    -o <destination patch dir> \
    -m <metadata file> \
    <replacement jars>

This will create (a zip file containing) the patch in the <destination patch dir>.

The patch is composed of

Item Description


Contains the information about the patch: how to use it, what components it changes, and what problems it fixes

The script that wraps the slee-patch-runner


Contains the instructions used to apply the patch

The log level definition for the patch runner


License information for third party libraries used by the patch runner

artifacts directory

Contains the original and patched components that will be applied to the system

lib directory

Contains the tools used to apply the patch to the system

profilespec directory

Contains database definitions

You can apply the patch locally to check it is working. For how to apply a patch see Applying patches to non live system.

Production patch

The production patch contains the patch generated above plus the orca tool. To pack the production patch do:

  • get the latest version of from operational-tools

  • decompress it

  • run

./generate-orca-bundle \
patch \
--patch-path <the absolute path to the patch zip file> \
--out <the zip bundle name> \
--product-name=<product name> \
--product-version=<product version> \
--ticket=<a ticket number related to the patch> \
--description="<description of the patch>" \
--patch-name=<name of the patch> \
--patch-version=<a number>

The generate-orca-bundle options for the patch command are:

usage: generate-orca-bundle patch [-h] --patch-path PATCH_PATH --patch-name
                                  PATCH_NAME --patch-version PATCH_VERSION
                                  --ticket TICKET --out OUT --product-name
                                  PRODUCT_NAME --product-version
                                  PRODUCT_VERSION --description DESCRIPTION

optional arguments:
  -h, --help            show this help message and exit
  --patch-path PATCH_PATH
                        Path of patch zip to be bundled
  --patch-name PATCH_NAME
                        Name of the patch, for the README
  --patch-version PATCH_VERSION
                        Version of the patch, for the README
  --ticket TICKET       A JIRA ticket, for the README
  --out OUT             Path of orca bundle to generate
  --product-name PRODUCT_NAME
                        Product name, for the README
  --product-version PRODUCT_VERSION
                        Product version, for the README
  --description DESCRIPTION
                        Description, for the README

What the patch generator does

The patch generator detects all the SLEE dependencies to the component being patched and creates a set of actions that the patch runner will execute.

The actions are:

  • check the SLEE component to be patched is installed and has the correct version and checksum

  • check all the SLEE service dependencies

  • stop the SLEE services and remove the dependencies

  • uninstall the component

  • install the new component

  • add the component dependencies and start the SLEE services

It also generates a basic README.txt with information about how to execute the patch and the components being patched.

For more information see Patch Generator.

What can be patched

Any type of SLEE component can be patched:

  • Service building block (SBB)

  • Service building block part (SBB part)

  • Library

  • Event type

  • Profile specification

  • Resource Adaptor Type

  • Resource Adaptor

Constraints on what can be patched

  • Components cannot be added.

  • Components cannot be removed.

  • Components are always packaged in deployable units. When replacing a SLEE component with a particular deployable unit, all the components in that DU must be patched.

  • The patched component must have exactly the same component ID as the original component.

    • Services are an exception to this rule—​they can differ only in the fourth part of their version. That is, when the version is of the form a.b.c.d, the d part can change.

    • Products whose component IDs change between release builds (such as SIS 2.5.* and earlier) would require patch-specific builds, in order to create a patched component with a matching version

Tool parameters --help

Usage: java ...PatchGeneratorMain [OPTION]... <INPUT_FILE>...

 INPUT_FILE                         : One or more SLEE components / deployable unit jars / service XML files containing the components to patch
 --dev-mode                         : Skip metadata validation. Do not use to create production patches.
 --nozip                            : Skip zip file generation. (default: false)
 -c (--rhino-client-dir) CLIENT_DIR : Client directory of the Rhino to base the patch on
 -g (--generator-dir) GENERATOR_DIR : Base directory of the patch generator
 -h (--help)                        : Print usage information (default: false)
 -l (--log-file) LOG_FILE           : Log file
 -m (--metadata-file) METADATA_FILE : YAML file with metadata used by the patch generator
 -o (--output-dir) OUTPUT_DIR       : Output directory: where to put the generated patch

Example of patch generation

Example of generating a patch for the Volte MMTel communication diversion and MMTel Call waiting feature: -c rhino/client -o $HOME/patch -m metadata.yaml mmtel-cdiv.jar
12:42:36,625 INFO  [patch.generator] Log file for SLEE patch generator.
12:42:36,638 INFO  [patch.generator] Using Rhino client home: /home/user/amauriala/rhino_client_2.7.0.6
12:42:36,638 INFO  [patch.generator] Using SLEE component, service XML, or DU jar file(s) as input: [../volte-2_7_0_7/units/mmtel-cdiv-]
12:42:36,638 INFO  [patch.generator] Using output patch dir: /home/user/amauriala/patches/test-all/cdiv
12:42:36,638 INFO  [patch.generator] Using generator dir: /home/user/amauriala/patches/test-all
12:42:36,638 INFO  [patch.generator] Using log file: /home/user/amauriala/patches/test-all/logs/patch-generator.log
12:42:36,638 INFO  [patch.generator] Connecting to Rhino...
12:42:37,052 INFO  [patch.generator] Connected to Rhino.
12:42:37,115 DEBUG [patch.generator] Preparing temp dir at '/home/user/amauriala/patches/test-all/tmp/patch-creation-original-artifacts3728006358016587614', to be deleted when the JVM exits.
12:42:37,115 DEBUG [patch.generator] Preparing temp dir at '/home/user/amauriala/patches/test-all/tmp/patch-creation-patched-artifacts6911442179420888524', to be deleted when the JVM exits.
12:42:37,116 DEBUG [patch.generator] Ensuring that directory 'cdiv' exists, creating it if necessary.
12:42:37,116 INFO  [patch.generator] Building patch model...
12:42:37,299 INFO  [patch.generator] Detected that '../volte-2_7_0_7/units/mmtel-cdiv-' is a deployable unit jar.
12:42:37,302 INFO  [patch.generator] Component IDs in du jar file at '../volte-2_7_0_7/units/mmtel-cdiv-':
 - SbbPartID[name=mmtel-cdiv,vendor=OpenCloud,version=2.7.0]
12:42:39,709 INFO  [patch.generator] Detected deployable unit to replace for du jar file at '../volte-2_7_0_7/units/mmtel-cdiv-':
 - DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-]
12:42:39,858 INFO  [patch.generator] Building patch model based on input file(s):
 - du jar file at '../volte-2_7_0_7/units/mmtel-cdiv-'
12:42:39,859 INFO  [patch.generator] Calculating component dependencies. (This usually takes a few seconds)
12:42:39,863 INFO  [patch.generator] Querying Rhino for currently deployed components...
12:42:39,863 INFO  [patch.generator] Gathering all installed component IDs
12:42:40,006 INFO  [patch.generator] Mapping components to descriptors...
12:42:41,111 INFO  [patch.generator] Querying Rhino for component dependencies...
12:42:41,111 INFO  [patch.generator] Filtering installed components...
12:42:41,120 INFO  [patch.generator] Building outgoing components map...
12:42:43,254 INFO  [patch.generator] Calculating DUs from components...
12:42:43,255 INFO  [patch.generator] targetDus:[DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-]]
12:42:43,847 INFO  [patch.generator] componentSetsDownstreamToUpstream:
12:42:44,435 INFO  [patch.generator] Detected service to update: ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=current]
12:42:44,503 INFO  [patch.generator] affected services:[ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=current]]
12:42:44,503 INFO  [patch.generator] affected bindings:[BindingDescriptorID[name=mmtel-cdiv-volte.sentinel.sip-bindings,vendor=opencloud,version=2.7.0]]
12:42:44,684 INFO  [patch.generator] All affected services:
 - ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=current]
12:42:44,685 INFO  [patch.generator] Building patch model based on component dependencies.
12:42:44,694 INFO  [patch.generator] Finished building patch model.
12:42:44,697 INFO  [patch.generator] Built patch model: PatchModel{metadata=Metadata{patchName='CDIV-patch', patchVersion='1', productName='VoLTE', productVersion='', ticket='OCS-1234', description='Fix fix for call forward unconditional', originalComponentIds=[SbbPart[mmtel-cdiv/OpenCloud/2.7.0]], patchedComponentIds=[SbbPart[mmtel-cdiv/OpenCloud/2.7.0]], patchToolsVersion='1.0.0-TRUNK.0-SNAPSHOT.r117-9bfb922', patchToolsCommit='9bfb922', buildInfo={sentinel-volte=123abc}}, commonConditions=[AssertServiceExists{componentId=Service[volte.sentinel.sip/OpenCloud/current]}, AssertInstallLevel{componentId=SbbPart[mmtel-cdiv/OpenCloud/2.7.0], installLevel=DEPLOYED}], preconditions=[DirectionalAction{forwardAction=AssertDeployableUnitInstalled{deployableUnitID=DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-], componentIdsToChecksums={SbbPart[mmtel-cdiv/OpenCloud/2.7.0]=f43407c155c4cc4ca5ee379428cc256261c30f0b}}, reverseAction=AssertDeployableUnitInstalled{deployableUnitID=DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-], componentIdsToChecksums={SbbPart[mmtel-cdiv/OpenCloud/2.7.0]=c5a6bbe4726448fd1868442948b09b5d5dd0d166}}}], disassemblyActions=[SaveServiceActivationState{componentId=Service[volte.sentinel.sip/OpenCloud/current]}, SaveTraceLevels{componentId=Service[volte.sentinel.sip/OpenCloud/current]}, DeactivateService{componentId=Service[volte.sentinel.sip/OpenCloud/current]}, AwaitServiceDeactivation{componentId=Service[volte.sentinel.sip/OpenCloud/current], timeoutSeconds=null}, RemoveBindings{componentId=Service[volte.sentinel.sip/OpenCloud/current], bindingDescriptors=[BindingDescriptorID[name=mmtel-cdiv-volte.sentinel.sip-bindings,vendor=opencloud,version=2.7.0]]}, DirectionalAction{forwardAction=UninstallDeployableUnit{deployableUnitID=DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-], componentIds=[SbbPart[mmtel-cdiv/OpenCloud/2.7.0]]}, reverseAction=UninstallDeployableUnit{deployableUnitID=DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-], componentIds=[SbbPart[mmtel-cdiv/OpenCloud/2.7.0]]}}], reassemblyActions=[DirectionalAction{forwardAction=InstallDeployableUnit{deployableUnitJarName=mmtel-cdiv-, url=file:modules/opencloud/mmtel-cdiv-, isPatched=true}, reverseAction=InstallDeployableUnit{deployableUnitJarName=mmtel-cdiv-, url=file:modules/opencloud/mmtel-cdiv-, isPatched=false}}, AddBindings{componentId=Service[volte.sentinel.sip/OpenCloud/current], bindingDescriptors=[BindingDescriptorID[name=mmtel-cdiv-volte.sentinel.sip-bindings,vendor=opencloud,version=2.7.0]]}, DeployService{componentId=Service[volte.sentinel.sip/OpenCloud/current]}, RestoreServiceActivationState{componentId=Service[volte.sentinel.sip/OpenCloud/current]}, RestoreTraceLevels{componentId=Service[volte.sentinel.sip/OpenCloud/current]}], postconditions=[DirectionalAction{forwardAction=AssertDeployableUnitInstalled{deployableUnitID=DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-], componentIdsToChecksums={SbbPart[mmtel-cdiv/OpenCloud/2.7.0]=c5a6bbe4726448fd1868442948b09b5d5dd0d166}}, reverseAction=AssertDeployableUnitInstalled{deployableUnitID=DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-], componentIdsToChecksums={SbbPart[mmtel-cdiv/OpenCloud/2.7.0]=f43407c155c4cc4ca5ee379428cc256261c30f0b}}}]}.
12:42:44,700 INFO  [patch.generator] Writing patch...
12:42:44,700 DEBUG [patch.generator] Assembling patch YAML at cdiv/patch.yaml
12:42:44,739 DEBUG [patch.generator] Creating artifacts dir
12:42:44,740 DEBUG [patch.generator] Ensuring that directory 'cdiv/artifacts' exists, creating it if necessary.
12:42:44,740 DEBUG [patch.generator] Ensuring that directory 'cdiv/artifacts/original' exists, creating it if necessary.
12:42:44,740 DEBUG [patch.generator] Ensuring that directory 'cdiv/artifacts/patched' exists, creating it if necessary.
12:42:44,740 DEBUG [patch.generator] Copying deployable unit jars to artifacts dir.
12:42:44,740 DEBUG [patch.generator] Copying '' script to output dir.
12:42:44,740 DEBUG [patch.generator] Copying file '' from '/home/user/amauriala/patches/test-all/resources' to 'cdiv',
12:42:44,746 DEBUG [patch.generator] Copying '' file to output dir.
12:42:44,746 DEBUG [patch.generator] Copying file '' from '/home/user/amauriala/patches/test-all/resources' to 'cdiv',
12:42:44,748 DEBUG [patch.generator] Copying library jars to output dir.
12:42:44,748 DEBUG [patch.generator] Ensuring that directory 'cdiv/lib' exists, creating it if necessary.
12:42:44,748 DEBUG [patch.generator] Copying file 'rhino-remote-2.7.0-TRUNK.0-M5-SNAPSHOT.r3482-f3a5e42.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,748 DEBUG [patch.generator] Copying file 'slee-patch-common.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,749 DEBUG [patch.generator] Copying file 'slee-patch-history-profile-1.0.0-TRUNK.0-SNAPSHOT.r117-9bfb922.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,749 DEBUG [patch.generator] Copying file 'log4j-1.2.17.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,759 DEBUG [patch.generator] Copying file 'guava-17.0.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,771 DEBUG [patch.generator] Copying file 'sdk-common-2.9.0-TRUNK.0-SNAPSHOT.r1353-301b05c.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,799 DEBUG [patch.generator] Copying file 'slf4j-api-1.7.7.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,799 DEBUG [patch.generator] Copying file 'args4j-2.32.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,808 DEBUG [patch.generator] Copying file 'snakeyaml-1.19.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,809 DEBUG [patch.generator] Copying file 'core-util-2.4.5-M1.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,820 DEBUG [patch.generator] Copying file 'slee-patch-runner.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,824 DEBUG [patch.generator] Copying file 'jline-2.12.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,829 DEBUG [patch.generator] Copying file 'gson-2.2.4.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,831 DEBUG [patch.generator] Copying file 'slee-1.1.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,832 DEBUG [patch.generator] Copying file 'slf4j-log4j12-1.7.7.jar' from '/home/user/amauriala/patches/test-all/lib' to 'cdiv/lib',
12:42:44,832 DEBUG [patch.generator] Copying history profile spec jar to output dir.
12:42:44,832 DEBUG [patch.generator] Ensuring that directory 'cdiv/profilespec' exists, creating it if necessary.
12:42:44,843 DEBUG [patch.generator] Copying file 'slee-patch-history-profile-1.0.0-TRUNK.0-SNAPSHOT.r117-9bfb922.du.jar' from '/home/user/amauriala/patches/test-all/profilespec' to 'cdiv/profilespec',
12:42:44,848 INFO  [patch.generator] Patch written to '/home/user/amauriala/patches/test-all/cdiv'.
12:42:44,848 INFO  [patch.generator] Reading in the YAML file to check that the model remains unchanged...
12:42:44,912 INFO  [patch.generator] Preview of actions to be executed by the patch...
12:42:44,915 INFO  [patch.generator] Dry-run actions against prototype install...
12:42:45,121 INFO  [patch.rhinoactionapplier] Updated installed services:
12:42:45,121 INFO  [patch.rhinoactionapplier]  - ServiceID[name=volte.sentinel.ss7,vendor=OpenCloud,version=]
12:42:45,121 INFO  [patch.rhinoactionapplier]  - ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=]
12:42:45,121 INFO  [patch.rhinoactionapplier]  - ServiceID[name=IM-SSF,vendor=OpenCloud,version=1.4.6]
12:42:45,121 INFO  [patch.rhinoactionapplier]  - ServiceID[name=sentinel.registrar,vendor=OpenCloud,version=]
12:42:45,122 INFO  [patch.generator] Starting to run 3 pre-patch checks.
12:42:45,134 INFO  [patch.generator] Running pre-patch check 1 of 3: Assert that 'Service[volte.sentinel.sip/OpenCloud/current]' is present in the target Rhino
12:42:45,159 INFO  [patch.rhinoactionapplier] Found service ServiceID[name=volte.sentinel.sip,vendor=OpenCloud,version=current]
12:42:45,159 INFO  [patch.generator] Finished pre-patch check 1 in 25ms
12:42:45,160 INFO  [patch.generator] Running pre-patch check 2 of 3: Assert that 'SbbPart[mmtel-cdiv/OpenCloud/2.7.0]' is installed, and is at the DEPLOYED install level.
12:42:45,163 INFO  [patch.rhinoactionapplier] Component SbbPartID[name=mmtel-cdiv,vendor=OpenCloud,version=2.7.0] is in state DEPLOYED
12:42:45,163 INFO  [patch.generator] Finished pre-patch check 2 in 3ms
12:42:45,163 INFO  [patch.generator] Running pre-patch check 3 of 3: Assert deployable unit 'DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-]' (or equivalent) is installed in the SLEE with the following components and SHA-1 checksums:
   - SbbPart[mmtel-cdiv/OpenCloud/2.7.0] -> f43407c155c4cc4ca5ee379428cc256261c30f0b
12:42:45,169 INFO  [patch.rhinoactionapplier] Found installed deployable unit DeployableUnitID[url=file:modules/opencloud/mmtel-cdiv-]
12:42:45,171 INFO  [patch.rhinoactionapplier]  - Found matching checksum for component SbbPartID[name=mmtel-cdiv,vendor=OpenCloud,version=2.7.0]
12:42:45,173 INFO  [patch.generator] Finished pre-patch check 3 in 10ms
12:42:45,173 INFO  [patch.generator] Writing patch documentation...
12:42:45,173 INFO  [patch.generator] Generating the patch documentation ...
12:42:45,176 INFO  [patch.generator] Writing documentation to cdiv/README.txt
12:42:45,182 INFO  [patch.generator] Patch documentation generated.
12:42:45,182 INFO  [patch.generator] Finished.
12:42:45,182 INFO  [patch.generator] Patch is ready, written to 'cdiv'.
Previous page Next page