JBoss Web Server

In this article, we'll discuss how to use the redhat.jws Ansible collection to automate the upgrade of a Red Hat JBoss Web Server instance from 5.7 to the version 6.0. First, we'll use Ansible to install JBoss Web Server 5.7 on the target system and then we'll use another playbook to perform the migration, thus ensuring that the target JBoss Web Server instance has been upgraded successfully.

Prerequisites

To support this demonstration you will first need to have a working Ansible environment. This involves having Ansible installed on the local (control) machine and one or several target hosts. As we are using the certified Ansible collection provided by Red Hat, Ansible needs to be configured to use Red Hat Ansible automation hub to retrieve content. Refer to the official documentation on how to configure your machine.

Once complete, install the redhat.jws collection on the control node using ansible-galaxy:

$ ansible-galaxy collection install redhat.jws
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://console.redhat.com/api/automation-hub/v3/plugin/ansible/content/published/collections/artifacts/redhat-jws-1.2.4.tar.gz to /root/.ansible/tmp/ansible-local-377j77fwws/tmpog8w22ut/redhat-jws-1.2.4-pi6vhlev
Installing 'redhat.jws:1.2.4' to '/root/.ansible/collections/ansible_collections/redhat/jws'
Downloading https://console.redhat.com/api/automation-hub/v3/plugin/ansible/content/published/collections/artifacts/redhat-runtimes_common-1.1.3.tar.gz to /root/.ansible/tmp/ansible-local-377j77fwws/tmpog8w22ut/redhat-runtimes_common-1.1.3-pg3nqnfm redhat.jws:1.2.4 was installed successfully
Downloading https://console.redhat.com/api/automation-hub/v3/plugin/ansible/content/published/collections/artifacts/ansible-posix-1.5.4.tar.gz to /root/.ansible/tmp/ansible-local-377j77fwws/tmpog8w22ut/ansible-posix-1.5.4-kt8e4_oe Installing 'redhat.runtimes_common:1.1.3' to '/root/.ansible/collections/ansible_collections/redhat/runtimes_common' redhat.runtimes_common:1.1.3 was installed successfully
Installing 'ansible.posix:1.5.4' to '/root/.ansible/collections/ansible_collections/ansible/posix' ansible.posix:1.5.4 was installed successfully

Note that the installation of the collection also ensures that the required dependencies are available.

Once all of the prerequisites have been completed, you can either download the ZIP files of JBoss Web Server versions 5.7 and 6.0 from the Red Hat Customer Portal manually or provide details related to your Red Hat service account to Ansible. You can find more information about how to create a service account here:

$ cat service_account.yml
---
rhn_username: <service_account_id> 
rhn_password: <password>

For simplicity’s sake, in this demonstration, we'll work with already downloaded ZIP files, placed in the main directory of the Ansible project. Note that it means the ZIP files are located on the controller, not the target systems.

Install JBoss Web Server 5.7

In real life, there is a good chance that users will already have an existing deployment of JBoss Web Server (or maybe Apache Tomcat) they want to migrate from. For the demonstration in this article to be easily reproducible, however, we'll install a JWS server from the beginning to simulate this situation.

Using the redhat.jws collection, you can easily install and set up a JWS server using the following playbook:

---
- name: "Red Hat JBoss Web Server installation and configuration"
  hosts: all
  become: True
  vars_files:
    - jws5_vars.yml 
  collections:
    - redhat.jws roles:
    - redhat.jws.jws

The playbook is mostly self-explanatory, however, we'll provide additional commentary on the meaning of a few variables located in the jws5_vars.yml file:

# version java used to run JWS 
jws_java_version: 11
# name of the systemd service associated JWS
jws_service_name: jws5
# Path to directory containing the zip files retrieved from Red Hat Customer Portal
jws_archive_repository: "{{ lookup('env', 'PWD') }}"
# Version of JWS used 
jws_version: 5.7.0
# Name of the zipfile on the controller 
zipfile_name: jws-5.7.0-application-server.zip

Let's run the playbook to install our "legacy" JWS server:

$ ansible-playbook -i inventory jws5.yml

PLAY [Red Hat JBoss Web Server installation and configuration] *****************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [redhat.jws.jws : Validating arguments against arg spec 'main'] ***********
ok: [localhost]

TASK [redhat.jws.jws : Set default values] *************************************
skipping: [localhost]

TASK [redhat.jws.jws : Set default values (jws)] *******************************
ok: [localhost]

TASK [redhat.jws.jws : Set jws_home to /opt/jws-5.7/tomcat if not already defined] ***
ok: [localhost]

TASK [redhat.jws.jws : Check that jws_home has been defined.] ******************
ok: [localhost] => {
	"changed": false,
	"msg": "All assertions passed"
}

TASK [redhat.jws.jws : Add firewalld to dependencies list (if enabled).] *******
skipping: [localhost]

TASK [redhat.jws.jws : Install required dependencies] **************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=zip)
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=unzip)
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=tzdata)

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package zip is already installed] ***************
ok: [localhost]

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package unzip is already installed] *************
ok: [localhost]

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package tzdata is already installed] ************
ok: [localhost]

TASK [redhat.jws.jws : Install required dependencies for natives] **************
skipping: [localhost] => (item=openssl)
skipping: [localhost] => (item=apr)
skipping: [localhost]

TASK [redhat.jws.jws : Ensure tomcatjss rpm is not installed] ******************
ok: [localhost]

TASK [redhat.jws.jws : Include tasks for java jvm installation] ****************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/java_install.yml for localhost

TASK [redhat.jws.jws : Set rpm name with version] ******************************
ok: [localhost]

TASK [redhat.jws.jws : Install java-11-openjdk-headless] ***********************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package java-11-openjdk-headless is already installed] ***
ok: [localhost]

TASK [redhat.jws.jws : Determine JAVA_HOME for selected JVM RPM] ***************
ok: [localhost]

TASK [redhat.jws.jws : Create group: tomcat] ***********************************
ok: [localhost]

TASK [redhat.jws.jws : Create user: tomcat] ************************************
changed: [localhost]

TASK [redhat.jws.jws : Check state of install_dir: /opt] ***********************
ok: [localhost]

TASK [redhat.jws.jws : Ensure install dir is created: /opt] ********************
skipping: [localhost]

TASK [redhat.jws.jws : Include install tasks] **********************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Check working directory /work for local repository] *****
ok: [localhost]

TASK [redhat.jws.jws : Display install method] *********************************
ok: [localhost] => {
	"msg": "Install method: zipfiles"
}

TASK [redhat.jws.jws : Set defaults values based on facts (if values not provided)] ***
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/defaults.yml for localhost

TASK [redhat.jws.jws : Set filename for JWS zipfile] ***************************
skipping: [localhost]

TASK [redhat.jws.jws : Set native zipfile architecture (if not provided)] ******
ok: [localhost]

TASK [redhat.jws.jws : Set RHEL major version based on facts (if not provided).] ***
ok: [localhost]

TASK [redhat.jws.jws : Set filename for JWS native zipfile] ********************
ok: [localhost]

TASK [redhat.jws.jws : Include installation tasks using zipfiles method] *******
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/local.yml for localhost

TASK [redhat.jws.jws : Deploy jws-5.7.0-application-server.zip to target.] *****
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/deploy_archive.yml for localhost

TASK [redhat.jws.jws : Check that required parameters have been provided.] *****
ok: [localhost]

TASK [redhat.jws.jws : Check download archive path on target: /opt/jws-5.7.0-application-server.zip] ***
ok: [localhost]

TASK [redhat.jws.jws : Retrieve zipfiles, if missing, from RHN (if credentials provided)] ***
skipping: [localhost]

TASK [redhat.jws.jws : Retrieve zipfiles from URL (if provided).] **************
skipping: [localhost]

TASK [redhat.jws.jws : Copy archives /work/jws-5.7.0-application-server.zip to target nodes: /opt/jws-5.7.0-application-server.zip] ***
changed: [localhost]

TASK [redhat.jws.jws : Deploy jws-5.7.0-application-server-RHEL8-x86_64.zip to target.] ***
skipping: [localhost]

TASK [redhat.jws.jws : Include installation tasks for zip operations] **********
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/zipfiles.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Add zipfile to unarchive list] **************************
ok: [localhost]

TASK [redhat.jws.jws : Add native zipfile to unarchive list] *******************
skipping: [localhost]

TASK [redhat.jws.jws : Install Jboss Web Server and required binaries from local zipfiles (install method: zipfiles) to /opt] ***
changed: [localhost] => (item={'src': 'jws-5.7.0-application-server.zip', 'creates': '/opt/jws-5.7/tomcat/bin'})

TASK [redhat.jws.jws : Move the zipfile extracted directory to custom jws_home] ***
skipping: [localhost]

TASK [redhat.jws.jws : Move the version.txt to custom jws_home] ****************
skipping: [localhost]

TASK [redhat.jws.jws : Include installation tasks for rpm method] **************
skipping: [localhost]

TASK [redhat.jws.jws : Include systemd tasks] **********************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/systemd/systemd.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Ensure requirements for systemd] ************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=systemd)
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=procps-ng)

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package systemd is already installed] ***********
ok: [localhost]

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package procps-ng is already installed] *********
ok: [localhost]

TASK [redhat.jws.jws : Set required default for jws_service_conf if not provided.] ***
ok: [localhost]

TASK [redhat.jws.jws : Set required default for jws_service_conf if not provided.] ***
ok: [localhost]

TASK [redhat.jws.jws : Set required default for jws_service_conf if not provided.] ***
ok: [localhost]

TASK [redhat.jws.jws : Ensure service script is deployed] **********************
changed: [localhost]

TASK [redhat.jws.jws : Ensure service configurations files is deployed: /opt/jws-5.7/tomcat/conf/jws5.conf] ***
changed: [localhost]

TASK [redhat.jws.jws : Ensure systemd service is configured] *******************
changed: [localhost]

TASK [redhat.jws.jws : Include patch install tasks] ****************************
skipping: [localhost]

TASK [redhat.jws.jws : Ensure /opt/jws-5.7/tomcat/ directories have appropriate privileges] ***
ok: [localhost] => (item=conf)
ok: [localhost] => (item=temp)
ok: [localhost] => (item=logs)
ok: [localhost] => (item=webapps)
ok: [localhost] => (item=bin)

TASK [redhat.jws.jws : Ensure /opt/jws-5.7/tomcat/ files have the recommended priviliges, owner and group] ***
changed: [localhost] => (item=./conf/catalina.properties)
changed: [localhost] => (item=./conf/catalina.policy)
changed: [localhost] => (item=./conf/logging.properties)
changed: [localhost] => (item=./conf/jaspic-providers.xml)
changed: [localhost] => (item=conf/tomcat-users.xml)

TASK [redhat.jws.jws : Include ajp sanity check tasks] *************************
skipping: [localhost]

TASK [redhat.jws.jws : Include https sanity check tasks] ***********************
skipping: [localhost]

TASK [redhat.jws.jws : Deploy custom configuration files] **********************
changed: [localhost] => (item={'template': 'templates/server.xml.j2', 'dest': '/opt/jws-5.7/tomcat/./conf/server.xml'})
changed: [localhost] => (item={'template': 'templates/web.xml.j2', 'dest': '/opt/jws-5.7/tomcat/./conf/web.xml'})
changed: [localhost] => (item={'template': 'templates/context.xml.j2', 'dest': '/opt/jws-5.7/tomcat/./conf/context.xml'})
changed: [localhost] => (item={'template': 'templates/catalina.properties.j2', 'dest': '/opt/jws-5.7/tomcat/./conf/catalina.properties'})

TASK [redhat.jws.jws : Include selinux configuration tasks] ********************
skipping: [localhost]

TASK [redhat.jws.jws : Remove apps] ********************************************
ok: [localhost] => (item=examples)

TASK [redhat.jws.jws : Create vault configuration (if enabled)] ****************
skipping: [localhost]

TASK [redhat.jws.jws : Ensure firewalld, if enabled, allows communication over 8080.] ***
skipping: [localhost]

RUNNING HANDLER [redhat.jws.jws : Reload Systemd] ******************************
ok: [localhost]

RUNNING HANDLER [redhat.jws.jws : Ensure Jboss Web Server runs under systemd] ***
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/systemd/service.yml for localhost

RUNNING HANDLER [redhat.jws.jws : Check arguments] *****************************
ok: [localhost]

RUNNING HANDLER [redhat.jws.jws : Enable jws.service] **************************
changed: [localhost]

RUNNING HANDLER [redhat.jws.jws : Start jws.service] ***************************
changed: [localhost]

RUNNING HANDLER [redhat.jws.jws : Restart Jboss Web Server service] ************
changed: [localhost]

Let's verify that the server is, indeed, successfully installed and available:

$ systemctl status jws5 ● jws5.service - Jboss Web Server
Loaded: loaded (/usr/lib/systemd/system/jws5.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2023-11-29 16:23:54 UTC; 8s ago
Process: 2137 ExecStop=/opt/jws-5.7/tomcat/bin/systemd-service.sh stop (code=exited, status=0/SUCCESS)
Main PID: 2187 (java)
CGroup: /system.slice/jws5.service └─2187 /etc/alternatives/jre_11/bin/java -Djava.util.logging.config.file=/opt/jws-5.7/tomcat/conf/logging.properties -Djava.>
Nov 29 16:23:54 62bfd7b30ce4 systemd[1]: Started Jboss Web Server.
Nov 29 16:23:54 62bfd7b30ce4 systemd-service.sh[2178]: Tomcat started.
Nov 29 16:23:54 62bfd7b30ce4 systemd-service.sh[2177]: Tomcat runs with PID: 2187

Performing the migration to JBoss Web Server 6

Now that we have a "legacy" system in place, we can focus on the migration. In order to migrate a system from JBoss Web Server 5 to JBoss Web Server 6, we'll first need to shut down the existing service (JBoss Web Server 5) before performing the install of JBoss Web Server 6. For this last part, we'll simply reuse the same role from the redhat.jws collection we used previously. We'll also use the same vars file to reuse the same configuration of the server, overriding only the few variables that differ for this new version of the server.

The following playbook could be written to accomplish migrating JBoss Web Server from version 5 to 6:

---
- name: "Migrate JWS5 to JWS6"
  hosts: all
  gather_facts: no
  serial:
	- 1
	- 30%
	- 60%
  vars_files:
	- vars.yml
  pre_tasks:
	- name: "Ensure JWS5 is no longer running"
  	ansible.builtin.service:
    	name: "{{ jws_service_name }}"
    	state: stopped
  tasks:
    - name: "Migrate to JWS 6"
      ansible.builtin.include_role:
        name: redhat.jws.jws
      vars:
         # overriding only the vars required
          jws_version: 6.0.0
          jws_service_name: jws6
          zipfile_name: jws-6.0.0-application-server.zip

Now, let's run this new playbook:

$ ansible-playbook -i inventory jws5-to-6.yml
PLAY [Migrate JWS5 to JWS6] ****************************************************

TASK [Ensure JWS5 is no longer running] ****************************************
ok: [localhost]

TASK [Install JWS 6] ***********************************************************

TASK [redhat.jws.jws : Validating arguments against arg spec 'main'] ***********
ok: [localhost]

TASK [redhat.jws.jws : Set default values] *************************************
skipping: [localhost]

TASK [redhat.jws.jws : Set default values (jws)] *******************************
ok: [localhost]

TASK [redhat.jws.jws : Set jws_home to /opt/jws-6.0/tomcat if not already defined] ***
ok: [localhost]

TASK [redhat.jws.jws : Check that jws_home has been defined.] ******************
ok: [localhost] => {
	"changed": false,
	"msg": "All assertions passed"
}

TASK [redhat.jws.jws : Add firewalld to dependencies list (if enabled).] *******
skipping: [localhost]

TASK [redhat.jws.jws : Install required dependencies] **************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=zip)
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=unzip)
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=tzdata)

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package zip is already installed] ***************
ok: [localhost]

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package unzip is already installed] *************
ok: [localhost]

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package tzdata is already installed] ************
ok: [localhost]

TASK [redhat.jws.jws : Install required dependencies for natives] **************
skipping: [localhost] => (item=openssl)
skipping: [localhost] => (item=apr)
skipping: [localhost]

TASK [redhat.jws.jws : Ensure tomcatjss rpm is not installed] ******************
ok: [localhost]

TASK [redhat.jws.jws : Include tasks for java jvm installation] ****************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/java_install.yml for localhost

TASK [redhat.jws.jws : Set rpm name with version] ******************************
ok: [localhost]

TASK [redhat.jws.jws : Install java-11-openjdk-headless] ***********************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package java-11-openjdk-headless is already installed] ***
ok: [localhost]

TASK [redhat.jws.jws : Determine JAVA_HOME for selected JVM RPM] ***************
ok: [localhost]

TASK [redhat.jws.jws : Create group: tomcat] ***********************************
ok: [localhost]

TASK [redhat.jws.jws : Create user: tomcat] ************************************
changed: [localhost]

TASK [redhat.jws.jws : Check state of install_dir: /opt] ***********************
ok: [localhost]

TASK [redhat.jws.jws : Ensure install dir is created: /opt] ********************
skipping: [localhost]

TASK [redhat.jws.jws : Include install tasks] **********************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Check working directory /work for local repository] *****
ok: [localhost]

TASK [redhat.jws.jws : Display install method] *********************************
ok: [localhost] => {
	"msg": "Install method: zipfiles"
}

TASK [redhat.jws.jws : Set defaults values based on facts (if values not provided)] ***
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/defaults.yml for localhost

TASK [redhat.jws.jws : Set filename for JWS zipfile] ***************************
skipping: [localhost]

TASK [redhat.jws.jws : Set native zipfile architecture (if not provided)] ******
ok: [localhost]

TASK [redhat.jws.jws : Set RHEL major version based on facts (if not provided).] ***
ok: [localhost]

TASK [redhat.jws.jws : Set filename for JWS native zipfile] ********************
ok: [localhost]

TASK [redhat.jws.jws : Include installation tasks using zipfiles method] *******
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/local.yml for localhost

TASK [redhat.jws.jws : Deploy jws-6.0.0-application-server.zip to target.] *****
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/deploy_archive.yml for localhost

TASK [redhat.jws.jws : Check that required parameters have been provided.] *****
ok: [localhost]

TASK [redhat.jws.jws : Check download archive path on target: /opt/jws-6.0.0-application-server.zip] ***
ok: [localhost]

TASK [redhat.jws.jws : Retrieve zipfiles, if missing, from RHN (if credentials provided)] ***
skipping: [localhost]

TASK [redhat.jws.jws : Retrieve zipfiles from URL (if provided).] **************
skipping: [localhost]

TASK [redhat.jws.jws : Copy archives /work/jws-6.0.0-application-server.zip to target nodes: /opt/jws-6.0.0-application-server.zip] ***
changed: [localhost]

TASK [redhat.jws.jws : Deploy jws-6.0.0-application-server-RHEL8-x86_64.zip to target.] ***
skipping: [localhost]

TASK [redhat.jws.jws : Include installation tasks for zip operations] **********
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/install/zipfiles.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Add zipfile to unarchive list] **************************
ok: [localhost]

TASK [redhat.jws.jws : Add native zipfile to unarchive list] *******************
skipping: [localhost]

TASK [redhat.jws.jws : Install Jboss Web Server and required binaries from local zipfiles (install method: zipfiles)] ***
changed: [localhost] => (item={'src': 'jws-6.0.0-application-server.zip', 'creates': '/opt/jws-6.0/tomcat/bin'})

TASK [redhat.jws.jws : Move the zipfile extracted directory to custom jws_home] ***
skipping: [localhost]

TASK [redhat.jws.jws : Move the version.txt to custom jws_home] ****************
skipping: [localhost]

TASK [redhat.jws.jws : Include installation tasks for rpm method] **************
skipping: [localhost]

TASK [redhat.jws.jws : Include systemd tasks] **********************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/systemd/systemd.yml for localhost

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Ensure requirements for systemd] ************************
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=systemd)
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/fastpackage.yml for localhost => (item=procps-ng)

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package systemd is already installed] ***********
ok: [localhost]

TASK [redhat.jws.jws : Check arguments] ****************************************
ok: [localhost]

TASK [redhat.jws.jws : Test if package procps-ng is already installed] *********
ok: [localhost]

TASK [redhat.jws.jws : Set required default for jws_service_conf if not provided.] ***
ok: [localhost]

TASK [redhat.jws.jws : Set required default for jws_service_conf if not provided.] ***
ok: [localhost]

TASK [redhat.jws.jws : Set required default for jws_service_conf if not provided.] ***
ok: [localhost]

TASK [redhat.jws.jws : Ensure service script is deployed] **********************
changed: [localhost]

TASK [redhat.jws.jws : Ensure service configurations files is deployed: /opt/jws-6.0/tomcat/conf/jws6.conf] ***
changed: [localhost]

TASK [redhat.jws.jws : Ensure systemd service is configured] *******************
changed: [localhost]

TASK [redhat.jws.jws : Include patch install tasks] ****************************
skipping: [localhost]

TASK [redhat.jws.jws : Ensure /opt/jws-6.0/tomcat/ directories have appropriate privileges] ***
ok: [localhost] => (item=conf)
ok: [localhost] => (item=temp)
ok: [localhost] => (item=logs)
ok: [localhost] => (item=webapps)
ok: [localhost] => (item=bin)

TASK [redhat.jws.jws : Ensure /opt/jws-6.0/tomcat/ files have the recommended priviliges, owner and group] ***
changed: [localhost] => (item=./conf/catalina.properties)
changed: [localhost] => (item=./conf/catalina.policy)
changed: [localhost] => (item=./conf/logging.properties)
changed: [localhost] => (item=./conf/jaspic-providers.xml)
changed: [localhost] => (item=conf/tomcat-users.xml)

TASK [redhat.jws.jws : Include ajp sanity check tasks] *************************
skipping: [localhost]

TASK [redhat.jws.jws : Include https sanity check tasks] ***********************
skipping: [localhost]

TASK [redhat.jws.jws : Deploy custom configuration files] **********************
changed: [localhost] => (item={'template': 'templates/server.xml.j2', 'dest': '/opt/jws-6.0/tomcat/./conf/server.xml'})
changed: [localhost] => (item={'template': 'templates/web.xml.j2', 'dest': '/opt/jws-6.0/tomcat/./conf/web.xml'})
changed: [localhost] => (item={'template': 'templates/context.xml.j2', 'dest': '/opt/jws-6.0/tomcat/./conf/context.xml'})
changed: [localhost] => (item={'template': 'templates/catalina.properties.j2', 'dest': '/opt/jws-6.0/tomcat/./conf/catalina.properties'})

TASK [redhat.jws.jws : Include selinux configuration tasks] ********************
skipping: [localhost]

TASK [redhat.jws.jws : Remove apps] ********************************************
ok: [localhost] => (item=examples)

TASK [redhat.jws.jws : Create vault configuration (if enabled)] ****************
skipping: [localhost]

TASK [redhat.jws.jws : Ensure firewalld, if enabled, allows communication over 8080.] ***
skipping: [localhost]

RUNNING HANDLER [redhat.jws.jws : Reload Systemd] ******************************
ok: [localhost]

RUNNING HANDLER [redhat.jws.jws : Ensure Jboss Web Server runs under systemd] ***
included: /root/.ansible/collections/ansible_collections/redhat/jws/roles/jws/tasks/systemd/service.yml for localhost

RUNNING HANDLER [redhat.jws.jws : Check arguments] *****************************
ok: [localhost]

RUNNING HANDLER [redhat.jws.jws : Enable jws.service] **************************
changed: [localhost]

RUNNING HANDLER [redhat.jws.jws : Start jws.service] ***************************
changed: [localhost]

RUNNING HANDLER [redhat.jws.jws : Restart Jboss Web Server service] ************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost              	: ok=65   changed=11   unreachable=0	failed=0	skipped=18   rescued=0	ignored=0   

Verify that the new jws6 service is indeed up and running:


# systemctl status jws6 ● jws6.service - Jboss Web Server
Loaded: loaded (/usr/lib/systemd/system/jws6.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2023-11-30 08:56:13 UTC; 36s ago
Process: 2220 ExecStop=/opt/jws-6.0/tomcat/bin/systemd-service.sh stop (code=exited, status=0/SUCCESS)
Main PID: 2261 (java)
Tasks: 42 (limit: 1638)
Memory: 213.1M
CGroup: /system.slice/jws6.service └─2261 /etc/alternatives/jre_11/bin/java -Djava.util.logging.config.file=/opt/jws-6.0/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.pr>
Nov 30 08:56:13 5e179d9cdf66 systemd[1]: Started Jboss Web Server.
Nov 30 08:56:13 5e179d9cdf66 systemd-service.sh[2252]: Tomcat started.
Nov 30 08:56:13 5e179d9cdf66 systemd-service.sh[2251]: Tomcat runs with PID: 2261

Configure the JWS server

Again, for simplicity's sake, the configuration of the JWS server is rather straightforward. We only needed to define a few parameters, such as the version of the OpenJDK required to run the server and the name of the systemd service. It is, however, important to note that because both installation playbooks (JBoss Web Server 5 and JBoss Web Server 6) use the same vars file, their configuration will be the same. The Ansible collection for JWS supports additional features including enabling HTTPS, using Tomcat Vault, and deploying and managing native libraries. Please refer to the official documentation of the Ansible collection for Red Hat JBoss Web Server.

Even if the legacy system had a more finer-grained configuration (changes in the server.xml), this can be carried over the new version as the collection supports overriding the default template used to generate for the server's configuration files:

jws_conf_properties: './conf/catalina.properties' 
jws_conf_policy: './conf/catalina.policy' 
jws_conf_loggging: './conf/logging.properties'
jws_conf_context: './conf/context.xml' 
jws_conf_server: './conf/server.xml' 
jws_conf_web: './conf/web.xml' 
jws_conf_users: 'conf/tomcat-users.xml' 
jws_conf_jaspic_providers: './conf/jaspic-providers.xml' jws_conf_templates_context: 'templates/context.xml.j2' 
jws_conf_templates_server: 'templates/server.xml.j2’

The variables above were provided as a reference to showcase how configurations can be provided. But, for our purposes, we can omit their use.

Handling failure during migration

There is another benefit of using Ansible to automate the migration to JBoss Web Server 6. Ansible can also be used to ensure that the legacy system is still operational in the event of a failure at some point during the migration. Let's modify our playbook to handle such scenario:

...
	- name: "Migrate to JWS 6"
        block:
          - name: "Install and run JWS 6"
          	ansible.builtin.include_role:
              name: redhat.jws.jws
          	vars:
              # overriding only the vars required
              jws_version: 6.0.0
              jws_service_name: jws6
              zipfile_name: jws-6.0.0-application-server.zip
        rescue:
          - name: "Restart JWS5 as migration to JWS6 failed."
          	ansible.builtin.service:
              name: jws5
              state: started

Upgrade strategy

Remediation is not the only area where Ansible's feature can help the migration. Indeed, if you are migrating a large set of servers, you may not want to stop all of them at the same time. Especially, if there is a chance the migration does not always run smoothly. You may prefer to instead operate on a subset of instances, first one or two servers, to check the migration works as expected, and then another subset afterward.

Let's modify our playbook to specify the value of the serial attribute in Ansible, which will implement this strategy when the the playbook runs:

---
- name: "Migrate JWS5 to JWS6" hosts: all gather_facts: 
  no serial:
    - 1
    - 30%
    - 60%
  vars_files:
    - vars.yml
  pre_tasks: 
…

Summary

In this article, we hope to have not only demonstrated how Ansible aids in migrating from one version of Red Hat JBoss Web Server to another, but also provided an excellent framework for managing automation at scale. We have also illustrated several features of Ansible (including handling errors and execution strategy) that can be the key to a successful, smooth migration of a large set of servers.

Last updated: February 5, 2024