Chapter 17. Patching

17.1. Patching a Fabric Container with a Rollup Patch

Abstract

Follow the procedures described in this section to patch a Fabric container with a rollup patch.

Overview

A rollup patch updates bundle JARs, other Maven artifacts, libraries, and static files in a Fabric. The following aspects of the fabric are affected:
  • Distribution of patched artifacts
  • Profiles
  • Configuration of the underlying container

Root container

Throughout this section, we refer to a root container, which is just a container chosen from the Fabric ensemble. Throughout the patching procedure, you invoke the patch:* commands from the console of the root container. If you are planning to distribute patch artifacts through the Maven proxy, it is convenient to choose the root container to be the ensemble container that is currently the master of the Maven proxy cluster (see Chapter 14, Fabric Maven Proxies). This would ensure that patch artifacts can immediately be downloaded by other containers in the cluster.

Distribution of patch artifacts

When patching an entire fabric of containers, you need to consider how the patch artifacts are distributed to the containers in the fabric. You can adopt one of the following approaches:
  • Through the Maven proxy (default approach)—when you add a rollup patch to your root container (using the patch:add command), the patch artifacts are installed into the root container's system/ directory, whose directory structure is laid out like a Maven repository. The root container can then serve up these patch artifacts to remote containers by behaving as a Maven proxy, enabling remote containers to download the required Maven artifacts (this process is managed by the Fabric agent running on each Fabric container). Alternatively, if you have installed the rollup patch to a container that is not hosting the Maven proxy, you can ensure that the patch artifacts are uploaded to the Maven proxy by invoking the patch:fabric-install command with the --upload option.
    There is a limitation to the Maven proxy approach, however, if the Fabric ensemble consists of multiple containers. In this case, it can happen that the Maven proxy fails over to a different ensemble container (not the original root container). This can result in the patch artifacts suddenly becoming unavailable to other containers in the fabric. If this occurs during the patching procedure, it will cause problems.
    Note
    Containers that are added to an ensemble do not automatically deploy the Maven proxy. To enable the Maven proxy, make sure that the fabric profile is deployed in the container.
    For more details, see Chapter 14, Fabric Maven Proxies.
  • Through a local repository (recommended approach)—to overcome the limitations of the Maven proxy approach, we recommend that you make the patch artifacts available directly to all of the containers in the Fabric by setting up a local repository on the file system. Assuming that you have a networked file system, all containers will be able to access the patch artifacts directly.
    For example, you might set up a local repository of patch artifacts, as follows:
    1. Given a rollup patch file, extract the contents of the system/ directory from the rollup patch file into the repositories/ subdirectory of a local Maven repository (which could be ~/.m2/repositories or any other location).
    2. Configure the Fabric agent and the Maven proxy to pick up artifacts from the local repository by editing the current version of the default profile, as follows:
      profile-edit --append --pid io.fabric8.agent/org.ops4j.pax.url.mvn.defaultRepositories="file:///PathToRepository" default
      Replace PathToRepository by the actual location of the local repository on your file system.
      Note
      Make sure that you make the edits to the default profile for all relevant profile versions. If some of your containers are using a non-default profile version, repeat the profile-edit commands while specifying the profile version explicitly as the last parameter.

Profiles

The rollup patching process updates all of the standard profiles, so that they reference the patched dependencies. Any custom profiles that you created yourself remain unaffected by these updates. However, in cases where you have already made some changes directly to the standard profiles (such as default, fabric, karaf, and so on), the patching mechanism attempts to merge your changes with the changes introduced by the patch.
Important
In the case where you have modified standard profiles, it is recommended that you verify your custom changes are preserved after patching. This is particularly important with respect to any changes made to the location of Maven repositories (which are usually configured in the default profile).

Configuration of the underlying container

If required, the rollup patching mechanism is capable of patching the underlying container (that is, files located under etc/, lib/, and so on). When a Fabric container is upgraded to a patched version (for example, using the fabric:container-upgrade command), the container's Fabric agent checks whether the underlying container must be patched. If yes, the Fabric agent triggers the patching mechanism to update the underlying container. Moreover, if certain critical files are updated (for example, lib/karaf.jar), the container status changes to requires full restart after the container is upgraded. This status indicates that a full manual restart is required (an automatic restart is not possible in this case).

io.fabric.version in the default profile

The io.fabric.version resource in the default profile plays a key role in the patching mechanism. This resource defines the version and build of JBoss A-MQ and of all of its main components. When upgrading (or rolling back) a Fabric container to a new version, the Fabric agent checks the version and build of JBoss A-MQ as defined in the io.fabric.version resource. If the JBoss A-MQ version changes between the original profile version and the upgraded profile version, the Fabric agent knows that an upgrade of the underlying container is required when upgrading to this profile version.

Patching the patch mechanism

(Recommended, if applicable) If there is no patch management package corresponding to the rollup patch you are about to install, then you can skip this procedure and install the rollup patch directly.
From time to time, important changes and improvements are made to the patch mechanism. In order to pick up these improvements, we recommend that you patch the patch mechanism to a higher level before upgrading JBoss A-MQ with a rollup patch. If you were to upgrade straight to the latest rollup patch version of JBoss A-MQ, the improved patch mechanism would become available after you completed the upgrade. But at that stage, it would be too late to benefit from the improvements in the patch mechanism.
To circumvent this bootstrap problem, the improved patch mechanism is made available as a separate download, so that you can patch the patch mechanism itself, before you upgrade to the new patch level. To patch the patch mechanism, proceed as follows:
  1. Download the appropriate patch management package. From the JBoss A-MQ 6.3.0 Software Downloads page, select a package named Red Hat JBoss A-MQ 6.3.0 Rollup N on Karaf Update Installer, where N is the number of the particular rollup patch you are about to install.
    Important
    The rollup number, N, of the downloaded patch management package must match the rollup number of the rollup patch you are about to install. For some rollup patches, there is no corresponding patch management package, in which case you can skip directly to the instructions for installing the rollup patch.
  2. Extract the contents of the patch management package, patch-management-for-amq-630-TargetVersion.zip, on top of the root container (that is, on top of the Fabric container that will be used to perform the remainder of the patching tasks). Use an archive utility to extract the contents on top of the root container installation, merging the contents of the archive system/ and patches/ directories with the container system/ and patches/ subdirectories.
    Note
    It does not matter whether the root container is running when you extract these files.
  3. Start the root container, if it is not already running.
  4. Create a new version, using the fabric:version-create command (where we assume that the current profile version is 1.0):
    JBossFuse:karaf@root> fabric:version-create --parent 1.0 1.0.1
    Created version: 1.0.1 as copy of: 1.0
    Important
    Version names are important! The tooling sorts version names based on the numeric version string, according to major.minor numbering, to determine the version on which to base a new one. You can safely add a text description to a version name as long as you append it to the end of the generated default name like this: 1.3 [.description]. If you abandon the default naming convention and use a textual name instead (for example, Patch051312), the next version you create will be based, not on the last version (Patch051312), but on the highest-numbered version determined by dot syntax.
  5. Update the patch property in the io.fabric8.version PID in the version 1.0.1 of the default profile, by entering the following Karaf console command:
    profile-edit --pid io.fabric8.version/patch=1.2.0.redhat-630xxx default 1.0.1
    Where you must replace 1.2.0.redhat-630xxx with the actual build version of the patch commands you are installing (for example, the build version xxx can be taken from the last three digits of the TargetVersion in the downloaded patch management package file name).
  6. Upgrade the root container to use the new patching mechanism, as follows:
    container-upgrade 1.0.1 root
  7. Likewise, for all other containers in your fabric that need to be patched (SSH, child, and so on), provision them with the new patching mechanism by upgrading them to profile version 1.0.1. For example:
    container-upgrade 1.0.1 container1 container2 container3
  8. After completing the container-upgrade, if patch commands are unavailable or if the console issues a prompt that a container restart is necessary, then restart the upgraded containers to complete the upgrade process.

Applying a rollup patch

To apply a rollup patch to a Fabric container:
  1. Before applying the rollup patch to your fabric, you must patch the patch mechanism, as described in the section called “Patching the patch mechanism”.
  2. For every top-level container (that is, any container that is not a child container), perform these steps, one container at a time:
    1. In the corresponding Karaf installation, remove the lib/endorsed/org.apache.karaf.exception-2.4.0.redhat-630xxx.jar file (where the build number, xxx, depends on the build being patched).
    2. Restart the container.
  3. Add the patch to the root container's environment using the patch:add command. For example, to add the patch.zip patch file:
    JBossFuse:karaf@root> patch:add file://patch.zip
    [name]            [installed] [description]                   
    PatchID         false       Description
    Important
    If you have decided to use a local repository to distribute the patch artifacts (recommended), set up the local repository now—see the section called “Distribution of patch artifacts”.
  4. Create a new version, using the fabric:version-create command:
    JBossFuse:karaf@root> fabric:version-create 1.1
    Created version: 1.1 as copy of: 1.0.1
    Important
    Version names are important! The tooling sorts version names based on the numeric version string, according to major.minor numbering, to determine the version on which to base a new one. You can safely add a text description to a version name as long as you append it to the end of the generated default name like this: 1.3[.description]. If you abandon the default naming convention and use a textual name instead (for example, Patch051312), the next version you create will be based, not on the last version (Patch051312), but on the highest-numbered version determined by dot syntax.
  5. Apply the patch to the new version, using the patch:fabric-install command. Note that in order to run this command you must provide the credentials, Username and Password, of a user with Administrator privileges. For example, to apply the PatchID patch to version 1.1:
    patch:fabric-install --username Username --password Password --upload --version 1.1 PatchID
    Note
    When you invoke the patch:fabric-install command with the --upload option, Fabric looks up the ZooKeeper registry to discover the URL of the currently active Maven proxy, and uploads all of the patch artifacts to this URL. Using this approach it is possible to make the patch artifacts available through the Maven proxy, even if the container you are currently logged into is not hosting the Maven proxy.
  6. Delete the old bundle overrides created by the old hot fix patch by modifying the parent profiles of the profile default and removing the old hot fix patch profile as being a parent of the default profile. For example,
    JBossFuse:karaf@root> fabric:profile-display --version 1.X default
    Attributes:
    parents: acls patch-jboss-fuse-6.2.1.redhat-186-12-r7hf10
    JBossFuse:karaf@root> fabric:profile-change-parents --version 1.X default acls
    
    Note
    The parent patch-jboss-fuse-6.2.1.redhat-186-12-r7hf10 is only visible if a hot fix patch was installed previously. The name of the parent patch is different based on the hot fix patch.
    The above commands shows that default profile has two parents:
    • acls - standard and must be present.
    • patch-jboss-fuse-6.2.1.redhat-186-12-r7hf10 - a profile that represents hotfix patch.
  7. Synchronize the patch information across the fabric, to ensure that the profile changes in version 1.1 are propagated to all containers in the fabric (particularly remote SSH containers). Enter the following console command:
    patch:fabric-synchronize
  8. Upgrade each existing container in the fabric using the fabric:container-upgrade command (but leaving the root container, where you installed the patch, until last). For example, to upgrade a container named remote, enter the following command:
    JBossFuse:karaf@root> fabric:container-upgrade 1.1 remote
    Upgraded container remote from version 1.0.1 to 1.1
    At this point, not only does the Fabric agent download and install the patched bundles into the specified container, but the agent also applies the patch to the underlying container (updating any static files in the container, if necessary). If necessary, the agent will then restart the target container automatically or set the container status to requires full restart (if an automatic restart is not possible), so that any changes made to the static files are applied to the running container.
    Important
    It is recommended that you upgrade only one or two containers to the patched profile version, to ensure that the patch does not introduce any new issues.
  9. If the current status of the upgraded container is requires full restart, you must now use one of the standard mechanisms to stop and restart the container manually. In some cases, it will be possible to do this using Fabric commands from the console of the root container.
    For example, you could stop the remote container as follows:
    fabric:container-stop remote
    And restart the remote container as follows:
    fabric:container-start remote
  10. Upgrade the root container last (that is, the container that you originally installed the patch on):
    fabric:container-upgrade 1.1 root
  11. (Windows only) If the root container status has changed to requires full restart and it is running on a Windows operating system, you must first shut down all of the root container's child containers (if any) before manually restarting the root container.
    For example, if the root container has three child containers, child1, child2, and child3, you would first shut them down, as follows:
    fabric:container-stop child1 child2 child3
    You can then shut down the root container with the shutdown command:
    shutdown

Rolling back a rollup patch

To roll back a rollup patch on a Fabric container, use the fabric:container-rollback command. For example, assuming that 1.0 is an unpatched profile version, you can roll the remote container back to the unpatched version 1.0 as follows:
fabric:container-rollback 1.0 remote
At this point, not only does the Fabric agent roll back the installed profiles to an earlier version, but the agent also rolls back the patch on the underlying container (restoring any static files to the state they were in before the patch was applied, if necessary). If necessary, the agent will then restart the target container automatically or set the container status to requires full restart (if an automatic restart is not possible), so that any changes made to the static files are applied to the running container.