This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Documentation

ansible-oracle

This is the Homepage of the project ansible-oracle hosted on https://github.com/oravirt/ansible-oracle.

Automated installation of

  • Oracle RAC databases
  • RAC One Node database and
  • single instance Oracle databases
  • Start with one or more clean Linux machine(s), end up with a fully configured Oracle database system

Features

  1. Full list of features of ansible-oracle
  2. More details https://github.com/oravirt/ansible-oracle

Getting Started

  1. Vagrant setup on Windows
  2. Beginners Guide

Next Steps

  1. APEX and ORDS in ansible-oracle
  2. How to develop in ansible-oracle
  3. List of roles in ansible-oracle

Pre-requisites

  • Ansible Version >= 2.14

    Version 2.14 or newer of Ansible is recommended

  • Oracle Linux (or any RHEL-based Linux System) >= 8

  • Oracle Database/Grid Infrastructure 21.3.0.0, 19.3.0.0

1 - Features

1.1 - Supported features in ansible-oracle

Warning
Please check the official Compatibility List from Oracle for RDBMS, Oracle Restart and Grid Infrastructure.
ansible-oracle only supports combinations from Oracle with exceptions from the following table.
Important
As of ansible-oracle 5.0 only Oracle 19c and 26ai are supported for RDBMS. Installation and tests are done for Single Instance databases without and with Oracle Restart.
Grid Infrastructure 26ai for a Cluster is supported (tested with a RAC database 26ai).
Older releases (11.2, 12.1, 12.2, 18c, 21c) are rejected by the assert of db_homes_config, see Breaking Changes - Upgrade Guide.
Note
The number of combinations of options is huge (operating system, Oracle release, Edition, Single Instance / Oracle Restart / Grid Infrastructure, device persistence for ASM, file system or ASM, …​). Only a few combinations are tested by the molecule scenarios of ansible-oracle.
All other combinations should work, as long as they are not explicitly excluded in this list and are supported by Oracle. Not tested means: not covered by an automated test, it does not mean does not work.
Important
All Editions from Oracle are supported. See documentation from Oracle for differences between Enterprise and Standard Edition (SE, SE One and SE2)
Note
Terms used in this document:
Oracle Restart: Grid Infrastructure for a Standalone Server (oracle_install_option_gi: HA_CONFIG), Single Instance databases with ASM on one host.
Grid Infrastructure: Grid Infrastructure for a Cluster (oracle_install_option_gi: CRS_CONFIG).
RAC (Real Application Clusters) and RAC One Node need Grid Infrastructure.
Both Oracle Restart and Grid Infrastructure use the software of Grid Infrastructure (oracle_home_gi).
Table 1. Featurelist
Group Option Version

OS

OracleLinux
Redhat Enterprise Linux

6 [1]
7 [1]
8
9

SuSE Linux Enterprise Server[3]

15, 15.3

Management of LVM, Filesystems and swap

all versions of all OS

ntp & chrony

all versions of all OS

custom motd (message of the day)

all versions of all OS

Software

Ansible

ansible-core 2.16 - 2.19 [9]

Oracle RDBMS

19c
26ai

Oracle Grid Infrastructure (cluster)

26ai [16]

Oracle Restart

19c
26ai

python-oracledb

Python 3

ASM

ASM Filter Driver (ASMFD)

19c

ASMlib

19c

udev

[3]

Installation Options

DB Options in Binaries

19c
26ai

Statspack for nonCDB, CDB and PDB

RMAN Backup with

  • cron management in /etc/cron.d

  • Catalog

  • Oracle-Wallet for Connection

  • checkmk mk_job monitoring

  • custom RMAN-scripts

dNFS (direct NFS)

Golden Image for RDBMS and Grid Infrastructure software (Oracle Restart)

  • Create from Installation

  • Install from Image

19c
26ai

readonly Homes for RDBMS

Oracle Data Guard: physical standby databases with Data Guard Broker (Standby Databases, experimental! [2]) [13]

19c
26ai

Database Migrations: Upgrade of PDBs with AutoUpgrade (Unplug/Plug, experimental! [2]) [12]

19c ⇒ 26ai

Prepatch installations [10]

not supported

Database Management

Grants

19c
26ai

init.ora Parameter [7])

  • possibility to set Parameters after DBCA execution

Pluggable Database Management [8]

Database Profiles

Redolog Groups [6]

Database Roles

Database Services [3]

Tablespaces

Users

Scripts with SQLPlus

Custom DBCA-Templates

Define Characterset during DBCA

Enable/Disable Archivelogmode & FRA

Timezone Upgrades

19c
26ai

Database Patching

Release Updates[11]

19c
26ai

OneOff Patches[11]

  • Install

  • Remove with unique patch id option

automatic datapatch execution[11]

Patch Download from Oracle

Out-of-Place Patching: switch of a database into another ORACLE_HOME [14]

19c
26ai

Out-of-Place Patching of Oracle Restart and Grid Infrastructure: switch of the Grid Infrastructure home [15]

26ai

Oracle APEX (experimental!)

Installation of APEX in PDB. Not supported for CDB or nonCDB.

19c
26ai

Oracle AutoUpgrade (experimental! [2])

AutoUpgrade with role autoupgrade

  • Installation and update of autoupgrade.jar on database server or Ansible controller

  • Keystore for My Oracle Support

  • Download of patches and gold images from My Oracle Support

  • Unplug/Plug upgrade of PDBs (analyze, fixups, deploy) [12]

  • Patching with AutoUpgrade is not implemented

Download: 19c, 21c, 23ai, 26ai
Upgrade: 19c ⇒ 26ai

Oracle Autonomous Health Framework (under development, experimental!)

AHF with roles ahf and ahf_fleet_insights

Important
Under development and experimental. Breaking changes can happen at any time and are not always documented.
  • Installation and upgrade of AHF (root or non-root)

  • Activation of TFA daemon and Compliance scheduler, settings for TFA and orachk

  • Central web interface with AHF Fleet Insights and registration of the clients

19c
26ai

Environment script

dynamic shell environment ocenv for Oracle

19c
26ai

Footnotes
1

Was supported by ansible-oracle. It is not tested anymore.

2

Still in development and not fully tested at the moment. Breaking changes in new commits are possible.
Please do not use this feature in production environments.

3

Limited support. Not tested for Oracle Restart and Grid Infrastructure.

4

Only tested with PDB on 19c+. May be work in nonCDB as well but noch in CDB.

5

in development and not implemented at the moment.

6

Not working in Real Application Cluster Setups

7

Limited to Parameter with SID="*"

8

only create/drop PDB

9

ansible-oracle 5.x supports ansible-core 2.16 - 2.19.
ansible-oracle 4.2 - 4.x supports ansible-core 2.14 - 2.18.

10

Use the Golden-Image feature as a workaround.

11

Supported for Single Instance databases without and with Oracle Restart. Not tested with Grid Infrastructure (cluster).

12

Source CDB (old release) and target CDB (new release) must run on the same host. See Upgrade of PDBs with AutoUpgrade.

13

Single Instance databases without Oracle Restart and without Grid Infrastructure only. Not supported for Oracle Restart, Grid Infrastructure (cluster), RAC and RAC One Node.

14

Single Instance primary databases without and with Oracle Restart. Not supported for Grid Infrastructure (cluster), RAC and RAC One Node.

15

Oracle Restart and Grid Infrastructure (cluster) 26ai (gridSetup.sh -switchGridHome, cluster: root.sh rolling), inside the same release (e.g. 23.26.3 ⇒ 23.26.4). Not supported for 19c. Grid Infrastructure (cluster): no switch back into a former home.

16

Tested with Grid Infrastructure 26ai on 2 nodes and a RAC database 26ai (molecule scenario rac), see Oracle Restart and Grid Infrastructure. Grid Infrastructure 19c, RAC databases 19c and RAC One Node are not tested.

2 - Guides

The examples for the guides are part of the project. They are located in example.

2.1 - Vagrant

2.1.1 - Vagrant on Windows

1. Overview

Important
This documentation describes the installation of the required tools for ansible-oracle on a Windows based hostsystem.
chocolatey
  • Requirements

    • Intel/AMD x86 CPU is mandatory
      no support for Mac with M1

    • 16 GB RAM

    • 150 GB free Disk space
      The free space is needed in your home directory in Windows.

    • Admin privileges on Host machine

    • Hyper-V disabled

    • no WSL/WSL2 for installation
      While you may try it, the documentation states that Hyper-V should be completely disabled and that no WSL/WSL2 is used.

Warning
There are many issues when Hyper-V is active on the host machine.
Please switch Hyper-V off completely, before starting the boxes with Vagrant.
If you do find a really good working solution with Vagrant + VirtualBox and Hyper-V, feedback is welcome.

2. Installation

2.1. Disable Hyper-V in Windows

Warning
There are numerous problems with Vagrant & VirtualBox when Hyper-V is enabled.
It is therefore recommended to disable it for ansible-oracle.
Important
All commands require a cmd.exe with admin rights.
Check setting of Hyper-V
bcdedit

The output should contain a line with hypervisorlaunchtype.
If the line is not shown or Off, Hyper-V is completely disabled.

Output
# bcdedit

Windows-Start-Manager
---------------------
...

Windows-Startladeprogramm
-------------------------
...
hypervisorlaunchtype    Off

If it is Auto or On

Disable Hyper-V with immediate reboot
bcdedit /set {current} hypervisorlaunchtype off
shutdown -r -t 0

2.2. Chocolatey

Important
The installation of Chocolatey is not mandatory for ansible-oracle.
All tools could be installed manually. Please ensure, that they are all executable from git+bash.
It is highly recommended to use Chocolatey with ansible-oracle.
Important
See the Homepage of chocolatey for more details.
Execute in PowerShell with Admin rights
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

2.3. git+bash, VirutalBox and Vagrant

Execute in cmd.exe with admin rights
choco install git vagrant virtualbox

2.4. ConEmu - Handy Windows Terminal

Important
This step is optional.

This is a really good alternative terminal to cmd.exe for windows.
It is not recommended for ansible-oracle but you should give it a try and enjoy it - especially when VSCode is not used.

Execute in cmd.exe with admin rights
choco install conemu

2.5. Visual Studio Code

Important
This step is optional.
You should use VSCode - especially when Advanced or Expert setups are planned for a later time.
Execute in cmd.exe with admin rights
choco install vscode.install

3. Configuration

3.1. SSH-Setup

Warning
The example expects the private key at the default location.
Important
Create a custom key and place the public key in same directory as the Vagrantfile. Do not use the created keys from Vagrant.
You should always use the ssh-agent to connect to all machines.
Important
All commands are executed in git+bash on the Host machine - not inside a VM!
Create a key when needed
ssh-keygen
Output
ssh-keygen

Generating public/private rsa key pair.

Enter file in which to save the key (/c/Users/User/.ssh/id_rsa): Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/User/.ssh/id_rsa
Your public key has been saved in /c/Users/User/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:Xq9EGKMUEXFkxeli4NilfvwEkOAmvkV1PiRteA+NQRQ ubuntu@ansible-oracle-bastion
Important
Enable Agent Forwarding for all SSH-Sessions.
This is mandatory for Visual Studio Code.
Enable Agent Forwarding for all SSH-Sessions.
code ~/.ssh/config

Host *
  ForwardAgent yes
Start a ssh-agent (bash)
eval $(ssh-agent)
Output
eval $(ssh-agent)
Agent pid 16840
Import a key
ssh-add ~/.ssh/id_rsa
Output
$ ssh-add ~/.ssh/id_rsa
Identity added: /c/Users/User/.ssh/id_rsa (User@unknown)
Show imported keys
ssh-add -l
Output
ssh-add -l
2048 SHA256:EsVIFzfCLUDTO2cMTf4q4qt2Eu0w1pA2sdcXxh9jyBs User@unknown (RSA)

3.2. Vagrant SSH-Setup

Important
The Vagrantfile has a provisioner script block which copy a stored id_rsa.pub into authorized_keys on the target machine.

The exact command to copy the key is shown during the deployment description.

3.3. Vagrant Plugins

The following modules are used by the tutorial examples.

  • install* vagrant-disksize
    This is an experimental plugin which is needed to resize the 1. disk of a vagrant box.

vagrant plugin install vagrant-disksize

4. See also

2.1.2 - Vagrant Basics

What is vagrant?

Vagrant is a tool that makes it EASIER and FASTER to setup virtual machines. Vagrant Boxes are pre-built base images (e.g. Oracle Linux) that can be imported into Vagrant as a starting point. For our use-case, we will use Vagrant together with Virtualbox and Oracle Linux

Installation

  1. Download and install Vagrant
  2. Download and install Oracle Virtualbox

Let’s start

Using Tim Halls’s guide, let’s play https://oracle-base.com/articles/vm/vagrant-a-beginners-guide

  1. hmm, cannot download that first OL box, let’s see the oracle doc https://yum.oracle.com/boxes/
  2. Note also that the default provider for vagrant has changed to libvirt (was virtualbox), so we will need to add “–provider virtualbox” to our vagrant add commands

Download Vagrant boxes

  • Instead of downloading a large DVD image, we can download a small vagrant box.
  • We can manually download a new box using the vagrant box add command.
  • We only need to do this once for each vagrant box (e.g. one time for Oracle Linux 7 and one time for Oracle Linux 8).
  • This download process would also happen automatically if required, when you reference a new box in a Vagrantfile

In a DOS command prompt…

vagrant box add --provider virtualbox https://oracle.github.io/vagrant-projects/boxes/oraclelinux/7.json
vagrant box add --provider virtualbox https://oracle.github.io/vagrant-projects/boxes/oraclelinux/8.json

Some vagrant addons

  1. allows us to resize disks (optional)

In a DOS command prompt…

vagrant plugin install vagrant-disksize
  1. ensure the virtualbox guest additions is updated, required to ensure that the guest additions are automatically updated for all new vagrant boxes

In a DOS command prompt…

vagrant plugin install vagrant-vbguest
  1. Automatically update the /etc/hosts

In a DOS command prompt…

vagrant plugin install vagrant-hostsupdater

Create the initial vagrantfile

To create the virtual machine, we first of all create a new directory, change to it and create the initial “vagrantfile”

In a DOS command prompt…

mkdir D:\vagrant\vol7db19
cd /D D:\vagrant\vol7db19
vagrant init

Start the VM

edit the vagrantfile (see Tim Hall’s website above) and when ready with our configuration, we can install, create and start the VM with the following command…

In a DOS command prompt…

vagrant up

Changing the vagrantfile

if you change the vagrantfile, destroy and recreate your virtual machine

In a DOS command prompt…

vagrant destroy -f
vagrant up

accessing the VM

  1. use the command “vagrant ssh” to access the VM per shh in your DOS command prompt
  2. or connect with ssh to 127.0.0.1, port 2222 with your favourite tool

Removing Vagrant boxes

  • We can remove any old boxes we are no longer using, with the vagrant box remove command.
  • These boxes will be automatically downloaded again if required.
  • It is best not to remove them, if still used regularly, as it takes a few minutes to download them

In a DOS command prompt…

vagrant box remove oraclelinux/7
vagrant box remove oraclelinux/8

2.2 - Beginners Guide

This guide installs an Oracle AI Database 26ai with a container database DB1 and the PDB ORCLPDB on an Oracle Linux 9 VM with ansible-oracle.

1. Overview

1.1. Architecture overview

Architecture

1.2. What are we going to do?

  1. Prepare the Ansible controller: Ansible in Ubuntu on WSL2 on Windows.

  2. Configure the inventory with the IP address and login user of the Oracle Linux 9 VM.

  3. Start the playbook playbooks/do_all.yml. It executes all needed playbooks:

    1. opitzconsulting.ansible_oracle.os: prepare the VM for AutoUpgrade

    2. playbooks/autoupgrade.yml: install AutoUpgrade on the VM and download a gold image from My Oracle Support. The gold image is a complete ORACLE_HOME including the Release Update.

    3. opitzconsulting.ansible_oracle.single_instance_fs: configure the OS, install the ORACLE_HOME from the gold image and create the database.

1.3. Defaults

Table 1. Defaults used in this guide
Value Description

~/git/ansible-oracle

git repository on the Ansible controller

~/git/ansible-oracle/example/beginner/ansible

Working directory for all Ansible commands

beginner-dbfs

Name of the VM in the inventory

192.168.66.161

IP address of the VM (ansible_host)

ol

Login user on the VM (ansible_user)

/u01/sw

Installation media on the VM, target of the download (oracle_sw_source_local)

/u01/stage

Staging directory on the VM (oracle_stage)

2. Requirements

2.1. Oracle Linux 9 VM

Any Oracle Linux 9 VM matching the requirements below can be used. See Create the VM with Hyper-V and Packer for an example with Hyper-V on Windows.

Table 2. Requirements for the VM
Item Requirement

Operating system

Oracle Linux 9 x86_64

CPU

2 vCPUs (recommended)

Memory

8 GB RAM (recommended)

Disk

/dev/sda with the volume group ol on /dev/sda3. The volume group needs min. 81 GB free space for swap (16 GB), /u01 (40 GB) and /u02 (25 GB). See host_fs_layout in group_vars/all/host.yml.

Network

Fixed IP address, reachable from the Ansible controller with SSH

Internet

Access to the Oracle Linux yum repositories and to My Oracle Support for AutoUpgrade (updates.oracle.com, login-ext.identity.oraclecloud.com, aru-akam.oracle.com)

Login user

User with SSH login and sudo privileges, e.g. ol

2.2. Create the VM with Hyper-V and Packer

The repository packer-hyperv builds an Oracle Linux 9 template with Packer and creates the VM for this guide on Hyper-V. See the README of the repository for the installation of packer and task.

Important
All steps in this chapter are executed in PowerShell on Windows, not in WSL.

The template uses

  • the login user ol with sudo privileges and SSH key login,

  • the volume group ol on /dev/sda3, as expected by host_fs_layout in this guide, and

  • the SSH public key %USERPROFILE%\.ssh\id_ed25519.pub.

Clone the repository
git clone https://github.com/Rendanic/packer-hyperv.git
cd packer-hyperv
Allow Hyper-V for the current user (once, elevated PowerShell, log off and on afterwards)
task hyperv:hyperv-add-admin-user
Build the Oracle Linux 9 template
task hyperv:packer-ol9
Build the template with another SSH public key
task hyperv:packer-ol9 SSH_KEY_FILE=C:\path\to\key.pub
Create the VM from the template
cd OL9
.\create-vm.ps1 -NewVMName beginner-dbfs -Hostname beginner-dbfs -ExternalSwitch intern_66 -FixedIP 192.168.66.161 -CPUs 2 -MemoryGB 8

create-vm.ps1 creates the VM with two network adapters:

  • Default Switch with DHCP for the internet access

  • the switch from -ExternalSwitch with the fixed IP address from -FixedIP. Use this address for ansible_host in inventory/hosts.yml.

Important
The template has a disk with 80 GB. The volume group ol has approx. 60 GB free space then, but the guide needs 81 GB.
Increase the disk of the VM, e.g. to 130 GB, before you start the installation.
Note
The SSH public key of the template must belong to the private key of the Ansible controller. Copy the key pair from Windows into WSL or use the public key from WSL for SSH_KEY_FILE.

2.3. Ansible controller

This guide uses Ubuntu on WSL2 on Windows as Ansible controller.

Note
Optionally, the database VM can be used as Ansible controller as well. Install the packages with dnf instead of apt in this case, e.g. sudo dnf install -y git python3. ansible_host and ansible_user in the inventory are used the same way, the VM connects to itself with SSH.
Table 3. Requirements for the Ansible controller
Item Requirement

Python

Python 3 with venv

Ansible

ansible-core >= 2.16

Internet

Access to GitHub and Ansible Galaxy

AutoUpgrade is executed on the VM, not on the Ansible controller. Java and the gold image are not needed on the Ansible controller.

2.4. My Oracle Support

A My Oracle Support account is needed for the download of the gold image.

3. Setup Ansible controller

Important
All steps are executed on the Ansible controller.
Install packages
sudo apt update
sudo apt install -y git python3-venv
Clone git repository
mkdir -p ~/git
cd ~/git

git clone https://github.com/oravirt/ansible-oracle.git
Create a Python virtual environment with Ansible
python3 -m venv ~/venv/ansible-oracle
source ~/venv/ansible-oracle/bin/activate

cd ~/git/ansible-oracle
pip install -r tools/dev/requirements_dev_2.16.txt
Tip
tools/dev/requirements_dev_2.19.txt installs ansible-core 2.19 instead of 2.16.
Important
Activate the virtual environment in each new shell with source ~/venv/ansible-oracle/bin/activate.
Install collections
cd ~/git/ansible-oracle/example/beginner/ansible
ansible-galaxy collection install -r requirements.yml

4. Configure inventory

4.1. IP address and login user

The VM is configured in inventory/hosts.yml. Change ansible_host and ansible_user for your VM.

inventory/hosts.yml
---
all:
  children:
    dbfs:
      hosts:
        beginner-dbfs:
          # IP address or DNS name of the Oracle Linux 9 VM
          ansible_host: 192.168.66.161
          # Login user on the VM with sudo privileges (SSH key login)
          ansible_user: ol
Note
beginner-dbfs is only the name of the host in the inventory. The host specific variables are in inventory/host_vars/beginner-dbfs/. Rename the directory as well, when you change the name.

4.2. SSH key

Ansible connects with an SSH key to the VM.

Create SSH key (skip it, when a key exists already)
ssh-keygen -t ed25519
Copy the public key to the VM
ssh-copy-id ol@192.168.66.161

4.3. Check the connection

Connection test
cd ~/git/ansible-oracle/example/beginner/ansible
ansible all -m ansible.builtin.ping
Test of sudo
ansible all -b -m ansible.builtin.command -a id
Tip
Add --ask-become-pass (-K) to all ansible and ansible-playbook commands, when sudo requires a password for the login user.

4.4. My Oracle Support credentials

The My Oracle Support credentials are read from the environment variables MOS_USERNAME and MOS_PASSWORD.

My Oracle Support credentials
export MOS_USERNAME=<your My Oracle Support login>
read -s MOS_PASSWORD && export MOS_PASSWORD

Alternatively, store the credentials in the file .env in the working directory and load it into the shell before starting ansible-playbook.

~/git/ansible-oracle/example/beginner/ansible/.env
MOS_USERNAME=<your My Oracle Support login>
MOS_PASSWORD=<your My Oracle Support password>
Load .env into the shell
cd ~/git/ansible-oracle/example/beginner/ansible
set -a; . ./.env; set +a
Important
.env contains your password. Restrict the permissions with chmod 600 .env.
The file is ignored by git (.gitignore).
Note
The lookups are defined in inventory/group_vars/all/mos_login.yml. Optionally, set mos_username and mos_password there statically instead of the environment variables. Encrypt the password with ansible-vault in this case.

4.5. Database passwords

The password for all database users is default_dbpass in inventory/group_vars/all/password.yml.

Warning
The default Oracle_123 is for test environments only. Change it and use ansible-vault for other environments.

5. AutoUpgrade on the VM

AutoUpgrade is executed on the VM (autoupgrade_run_local: false in inventory/group_vars/all/autoupgrade.yml). It downloads the gold image directly into /u01/sw on the VM. No installation media are copied from the Ansible controller (oracle_sw_copy: false).

The execution of AutoUpgrade on the VM requires:

  • the Python module pexpect for the keystore with the My Oracle Support credentials,

  • a JDK for autoupgrade.jar and

  • the download directory /u01/sw on the filesystem /u01.

The playbook os creates the filesystem /u01 (host_fs_layout in the inventory). playbooks/autoupgrade.yml installs the packages for the JDK and pexpect before the installation of AutoUpgrade. Therefore do_all.yml executes the playbook os before AutoUpgrade. The playbook os is executed a second time, because it is a fixed part of opitzconsulting.ansible_oracle.single_instance_fs. The second execution changes nothing.

Table 4. Download configuration in inventory/group_vars/all/autoupgrade.yml
Variable Value Description

autoupgrade_download_latest

true

Download the latest autoupgrade.jar from Oracle

autoupgrade_download_patches

target_version: 26, patch: RECOMMENDED, gold_image: ALL

Gold image for 26ai with all recommended patches

autoupgrade_download_gold_image_rename

true

Rename the gold image to db_home_<release>.zip, e.g. db_home_26.04.zip

autoupgrade_download_gold_image_latest

true

Symlink db_home_26_latest.zip to the latest gold image of 26ai

See Oracle AutoUpgrade for details.

Important
The gold image is built by Oracle on request.
When no suitable image is cached, the download can take a few hours.

The release update of the gold image is known only after the download. Therefore the inventory uses the symlink db_home_26_latest.zip as imagename instead of the real filename. The symlink points to the gold image with the highest release update in /u01/sw. It is changed only, when a newer gold image is downloaded - the download of an older release update keeps it unchanged.

Check the downloaded gold image on the VM
ls -l /u01/sw/db_home_*.zip
Example
db_home_26.04.zip
db_home_26_latest.zip -> db_home_26.04.zip
inventory/group_vars/all/db-homes.yml
  db26_si_ee: &db26_si_ee
    version: 26.1.0.0
    oracle_home: /u01/app/oracle/product/db26_si_ee
    edition: EE
    imagename: db_home_26_latest.zip
Tip
Use the real filename, e.g. imagename: db_home_26.04.zip, when an ORACLE_HOME must be installed with a fixed release update.

6. Install database with Ansible

Start installation
cd ~/git/ansible-oracle/example/beginner/ansible
ansible-playbook playbooks/do_all.yml
Note
The execution takes approx. 60 minutes plus the download of the gold image.
Table 5. Configuration of the database
Parameter Value

ORACLE_BASE

/u01/app/oracle

ORACLE_HOME

/u01/app/oracle/product/db26_si_ee

ORACLE_SID

DB1

PDB

ORCLPDB

db_create_file_dest

/u02/oradata

db_recovery_file_dest

/u02/fra

Listener

LISTENER, port 1521

7. How to work with the installed database

Login into the VM
ssh ol@192.168.66.161
Switch to user oracle
sudo -iu oracle
Initialize ocenv to set the environment variables
ocenv

ocenv shows the ORACLE_HOMEs, databases and listeners on the host. envhelp shows an overview of the commands.

Set ORACLE_SID
DB1
Start SQL*Plus
sql

2.3 - Advanced Guide

Warning
This guide is a work in progress!

1. Advanced Guide

Important
The setup of Vagrant, VirtualBox and SSH is not part of this documentation.
Please follow the documentation.

1.1. Overview

1.1.1. Architecture overview

Architecturview

1.1.2. Defaults

Table 1. Used defaults in this guide
Value Description

~/git/ansible-oracle

git Repository on Host System

~/git/ansible-oracle

git Repository in VM

~/.ssh/id_rsa

private Key on Host System

vagrant

SSH-User for Login and Ansible

~/git/ansible-oracle/ansible-oracle/example/beginner

Vagrantfile location

1.2. Setup Host System

Important
All steps are executed on the Host System inside a git+bash.
clone git Repository
mkdir ~/git
cd ~/git

git clone https://github.com/oravirt/ansible-oracle.git

1.2.1. Build Oracle Software tree

Important
It is highly recommended to use the following structure.
Do not change this until you really know what you are doing.

All installation media are searched in oracle_stage_remote on the database server.

Warning
It is assumed that oracle_stage_remote is set to /sw
1.2.1.1. Installation media
Important
Only LINUX.X64_193000_db_home.zip is needed as base media for the Advanced Guide.
Example oracle_stage_remote: /sw
/sw/LINUX.X64_180000_db_home.zip
/sw/LINUX.X64_193000_grid_home.zip
/sw/LINUX.X64_213000_grid_home.zip
/sw/LINUX.X64_193000_db_home.zip
/sw/LINUX.X64_213000_db_home.zip
1.2.1.2. OPatch archive
Important
Only p6880880_190000_Linux-x86-64.zip is needed for patching in the Advanced Guide.
Example oracle_stage_remote: /sw for OPatch
/sw/oracle/linux64/p6880880_112000_Linux-x86-64.zip
/sw/oracle/linux64/p6880880_180000_Linux-x86-64.zip
/sw/oracle/linux64/p6880880_190000_Linux-x86-64.zip
/sw/oracle/linux64/p6880880_210000_Linux-x86-64.zip
1.2.1.3. Patch structure

<todo wip>

Directory Description

1.2.2. Configure SSH-Key

Important
Do not skip the preparation for Vagrant and SSH.
Please follow the documentation.
Copy Public key into Vagrantfile directory
cp ~/.ssh/id_rsa.pub ~/git/ansible-oracle/ansible-oracle/example/beginner
Start ssh-Agent
eval $(ssh-agent)
Import the generated key
ssh-add ~/.ssh/id_rsa

1.2.3. Start Vagrantbox

Important
The Deployment und provisioning of the VM takes some minutes.
It highly depends on the speed of the internet connection.
Important
The SSH public key is configured during the provisioning phase of the VM.
Do not forget to copy the file before starting the box with vagrant up.
vagrant up
cd ~/git/ansible-oracle/ansible-oracle/example/beginner
VAGRANT_EXPERIMENTAL=disks vagrant up
1.2.3.1. What happens when I start vagrant?
  1. Using the vagrantfile, an Oracle Linux VM is installed (2x CPU, 4096MB RAM, 150GB HDD). IP = 192.168.56.161

  2. A mount point /vagrant is available in the Oracle Linux VM. This is a shared folder from your Windows machine.

  3. Your ssh key is used to connect to the VM in a secure way

  4. docker is installed in the Oracle Linux VM

  5. docker-compose is installed in the Oracle Linux VM

  6. The ansible-oracle repository is cloned to the Oracle Linux VM

  7. A docker container "Ansible Container" is built with docker-compose. This runs in the Oracle Linux VM

  8. No Oracle database is yet installed. See below

1.3. Working inside the VM

1.3.1. Connect to VM

Important
The next steps are done inside the VM.
The SSH-Setup from the previous chapter must be completed before continuing!
Connect into VM with SSH from git+bash
ssh -A vagrant@192.168.56.161

1.3.2. Note about Installation media

The installation media is mounted with vboxsf from Vagrant into the Linux VM, mounted as /vagrant.
Use the following command to check this…​

check for Installation media
[vagrant@beginner-dbfs-151-192-168-56-161 ~]$ ls /vagrant/LINUX.X64_193000_db_home.zip

/vagrant/LINUX.X64_193000_db_home.zip

1.3.3. Start Ansible-Container inside VM

Important
Check the prompt shown in this documentation, as to whether you should start the commands in the shell or inside the Ansible-Container.
ansible@ansible-oracle is for working inside the container. .Start Ansible-Container
cd ~/git/ansible-oracle/docker
docker-compose run --rm -w /git/ansible-oracle/example/beginner/ansible ansible bash
Example
[vagrant@beginner-dbfs-151-192-168-56-161 docker]$ docker-compose run --rm -w /git/ansible-oracle/example/beginner/ansible ansible bash
[+] Running 2/0
 ⠿ Network docker_default          Created
 ⠿ Volume "docker_ansible_galaxy"  Created

ansible@ansible-oracle:/git/ansible-oracle/example/beginner/ansible$
Important
The collection is installed once and stored on the docker volume.
Install Collections
ansible@ansible-oracle:/git/ansible-oracle/example/beginner/ansible$ ansible-galaxy collection install -r requirements.yml
Example
ansible@ansible-oracle:/git/ansible-oracle/example/beginner/ansible$ ansible-galaxy collection install -r requirements.yml
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/download/devsec-hardening-8.2.0.tar.gz to /home/ansible/.ansible/tmp/ansible-local-25z8isd809/tmp25w_hn4o/devsec-hardening-8.2.0-0j9481f1
Installing 'devsec.hardening:8.2.0' to '/ansible/galaxy/ansible_collections/devsec/hardening'
Downloading https://galaxy.ansible.com/download/opitzconsulting-ansible_oracle-3.2.0.tar.gz to /home/ansible/.ansible/tmp/ansible-local-25z8isd809/tmp25w_hn4o/opitzconsulting-ansible_oracle-3.2.0-x3wo4c3b
devsec.hardening:8.2.0 was installed successfully
Installing 'opitzconsulting.ansible_oracle:3.2.0' to '/ansible/galaxy/ansible_collections/opitzconsulting/ansible_oracle'
Downloading https://galaxy.ansible.com/download/ansible-posix-1.4.0.tar.gz to /home/ansible/.ansible/tmp/ansible-local-25z8isd809/tmp25w_hn4o/ansible-posix-1.4.0-1jub71c6
opitzconsulting.ansible_oracle:3.2.0 was installed successfully
Installing 'ansible.posix:1.4.0' to '/ansible/galaxy/ansible_collections/ansible/posix'
Downloading https://galaxy.ansible.com/download/community-mysql-3.5.1.tar.gz to /home/ansible/.ansible/tmp/ansible-local-25z8isd809/tmp25w_hn4o/community-mysql-3.5.1-lkcnbkd5
ansible.posix:1.4.0 was installed successfully
Installing 'community.mysql:3.5.1' to '/ansible/galaxy/ansible_collections/community/mysql'
Downloading https://galaxy.ansible.com/download/community-crypto-2.8.0.tar.gz to /home/ansible/.ansible/tmp/ansible-local-25z8isd809/tmp25w_hn4o/community-crypto-2.8.0-6sco_75m
community.mysql:3.5.1 was installed successfully
Installing 'community.crypto:2.8.0' to '/ansible/galaxy/ansible_collections/community/crypto'
Downloading https://galaxy.ansible.com/download/community-general-5.8.0.tar.gz to /home/ansible/.ansible/tmp/ansible-local-25z8isd809/tmp25w_hn4o/community-general-5.8.0-up2j_3iq
community.crypto:2.8.0 was installed successfully
Installing 'community.general:5.8.0' to '/ansible/galaxy/ansible_collections/community/general'
community.general:5.8.0 was installed successfully

1.3.4. Start Installation with Ansible

Important
Make sure to start the installation inside the Ansible Container.
The prompt shows the correct location.
The execution takes ~60 minutes.
Start installation with Ansible
cd /git/ansible-oracle/example/beginner/ansible
ansible-playbook -i inventory/ -e hostgroup=dbfs playbooks/single-instance-fs.yml

The Database creation is now complete.
See the following chapter for details about how to work with the VM. === How to work with installed database

1.3.5. Login as vagrant

Login with SSH from git+bash
ssh -A vagrant@192.168.56.161

1.3.6. Sudo oracle

sudo oracle
[vagrant@beginner-dbfs-151-192-168-56-161 ~]$ sudo su - oracle
Example
[vagrant@beginner-dbfs-151-192-168-56-161 ~]$ sudo su - oracle
Last login: Sun Nov  6 11:16:54 UTC 2022 on pts/2
execute ocenv to source Oracle Environment

1.3.7. Start ocenv

Initialize ocenv to set the environment variables
[oracle@beginner-dbfs-151-192-168-56-161 ~]$ ocenv
Example
[oracle@beginner-dbfs-151-192-168-56-161 ~]$ ocenv
#####################################################################################
## Version: 2022-08-10
## get command overview by typing envhelp
#####################################################################################
home   oracle       OraHome_OraDB19Home1                       /u01/app/oracle/product/19/db1
db     oracle       DB1              (up)                      /u01/app/oracle/product/19/db1
lsnr   oracle       LISTENER                                   /u01/app/oracle/product/19/db1
[oracle@beginner-dbfs-151-192-168-56-161] [] [~]

1.3.8. Switch to DB1

Set ORACLE_SID
[oracle@beginner-dbfs-151-192-168-56-161] [] [~]
$ DB1
Example
[oracle@beginner-dbfs-151-192-168-56-161] [] [~]
$ DB1
=================================
INSTANCE NAME       : DB1
INSTANCE STATUS     : OPEN (READ WRITE)
INSTANCE START TIME : 2022-11-06 11:34:06
DB NAME             : DB1
DB UNIQUE NAME      : DB1
DB ID               : 1713907024
DB LOGGING MODE     : NOARCHIVELOG
DB ROLE             : PRIMARY
DB FORCE LOGGING    : YES
DB FLASHBACK ON     : NO
DB is CDB           : YES
PDBs
   PDB NAME        STATUS     RESTRICTED OPEN TIME           LOCAL UNDO
   --------------- ---------- ---------- ------------------- ----------
   ORCLPDB         READ WRITE NO         2022-11-06 11:34:28 YES
=================================
[oracle@beginner-dbfs-151-192-168-56-161] [DB1] [~]

1.3.9. Database Login

Start SQLPlus
[oracle@beginner-dbfs-151-192-168-56-161] [DB1] [~]
$ sql
Example
[oracle@beginner-dbfs-151-192-168-56-161] [DB1] [~]
$ sql

SQL*Plus: Release 19.0.0.0.0 - Production on Sun Nov 6 11:41:40 2022
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

11:41:40 SYS@DB1
SQL>

2.4 - Ansible as a Docker Container

Important
This documentation is a work in progress!

The development and test of ansible-oracle is done in a Docker Container. This allows a simple switch between ansible versions and an easy implementation at a customer site, because you can use your own chosen version of Ansible for ansible-oracle.

Requirements:

  • Docker

  • docker-compose

  • ssh-agent
    The ssh-agent is configured inside the docker-compose.yml. It simplifies the connection to the target machines via SSH.

Build

cd docker
docker-compose build

Start Container

cd docker
docker-compose run --rm ansible bash

Install Collection

Important
ansible-oracle is designed to run as a container.
cd docker
docker-compose run --rm ansible bash
ansible-galaxy collection install -r requirements.yml

2.5 - HOWTO: Local Installation of Ansible-Oracle

1. Intro

This guide will show you how to get Ansible-Oracle up and running with a local installation (as opposed to a container or Vagrant setup).

It is assumed that the server is airgapped and doesn’t have Internet access and therefore it’s demonstrated how to install all necessary binaries manually.

Note
This guide aims at developers who want to test different setups with different dependencies. To enable you to run the Ansible-Oracle environment independently of other versions of Ansible, Python and Galaxy modules, everything will be encapsulated within a Python Virtual Environment (venv). If you prefer to install everything globally, you’ll find info on how to do so below.

The steps in this guide were tested with OL9.5, Python 3.9, Ansible 2.14 and Ansible-Oracle 4.11.1.

2. What you need

2.1. Server and OS

  • Oracle Linux 9 or RHEL 9 (this guide was tested with OL 9.5)

  • OS install DVD or ISO attached to your machine.

  • At least 50 MB free space in the /home filesystem.

2.2. Mandatory RPMs

These RPMs can be installed from the OS install image (DVD ISO).

  • git

  • ansible-core

  • python3-pip

2.3. Other mandatory files

Download these files on a device with Internet access and transfer them to the target server’s /tmp directory.

2.3.1. Optional:

  • tig, for easier navigation of git repos.

3. Setup Ansible

3.1. User

dnf install -y git ansible-core python3-pip
useradd ansible

su - ansible
mkdir .ssh
cd .ssh/
vi authorized_keys
ssh-keygen -t ed25519
## No password
## Paste the contents of id_ecdsa.pub into /root/.ssh/authorized_keys on target machine

3.2. Python Virtual Environment and Ansible Collections

# As ansible user
mkdir -p /home/ansible/ansible/inventory
cd ~/ansible
unzip /tmp/ansible-oracle-4.11.1.zip
mv ansible-oracle-4.11.1 ansible-oracle
cd ansible-oracle
echo ".venv/" >> .gitignore
python3 -m venv .venv

# Activate the virtual environment
source .venv/bin/activate

Install packages in the virtual environment:

Note
If you don’t want the dependencies within the venv, change the -p ~/ansible/ansible-oracle/.venv/lib/collections to -p ~/ansible/ansible-oracle/playbooks/collections. This is the default path for Ansible Navigator.
ansible-galaxy collection install /tmp/ansible_collections/ansible-posix-1.5.4.tar.gz -p ~/ansible/ansible-oracle/.venv/lib/collections
ansible-galaxy collection install /tmp/ansible_collections/ansible-utils-5.1.0.tar.gz -p ~/ansible/ansible-oracle/.venv/lib/collections
ansible-galaxy collection install /tmp/ansible_collections/community-general-9.5.4.tar.gz -p ~/ansible/ansible-oracle/.venv/lib/collections
ansible-galaxy collection install /tmp/ansible_collections/community-crypto-2.24.0.tar.gz -p ~/ansible/ansible-oracle/.venv/lib/collections
ansible-galaxy collection install /tmp/ansible_collections/community-mysql-3.12.0.tar.gz -p ~/ansible/ansible-oracle/.venv/lib/collections
ansible-galaxy collection install /tmp/ansible_collections/devsec-hardening-8.8.0.tar.gz -p ~/ansible/ansible-oracle/.venv/lib/collections
ansible-galaxy collection install /tmp/ansible_collections/opitzconsulting-ansible_oracle-4.11.1.tar.gz -p ~/ansible/ansible-oracle/.venv/lib/collections
Starting galaxy collection install process
[WARNING]: The specified collections path '/home/ansible/ansible/ansible-oracle/collections' is not part of the configured Ansible collections paths
'/home/ansible/.ansible/collections:/usr/share/ansible/collections'. The installed collection will not be picked up in an Ansible run, unless within a
playbook-adjacent collections directory.

For background info on Ansible in a Python venv, see: How to set up and use Python virtual environments for Ansible

3.3. Shell Alias

This alias for Bash sets the environment and jumps to the ansible-oracle directory.

alias aov='cd ~/ansible/ansible-oracle ; source .venv/bin/activate ; export ANSIBLE_COLLECTIONS_PATHS=".venv/lib/collections:$ANSIBLE_COLLECTIONS_PATHS"'

You could also define the path to the ansible collections in ansible.cfg:

[defaults]
collections_paths = .venv/lib/collections

3.4. SSH Key

For passwordless login, the ansible user needs a SSH key. This is optional, if you run on local connections or if you prefer to provide a password.

ssh-keygen -q -t ed25519 -N '' <<< $'\ny' >/dev/null 2>&1

Copy the contents of id_ed25519.pub to the target host’s root user into ~/.ssh/authorized_keys.

4. Target Host

4.1. python-oracledb

The target (database) host needs python-oracledb installed. The modules of Ansible-Oracle use this package in thick mode (Oracle Client libraries of the ORACLE_HOME) to issue database queries. The Playbook os.yml installs this package with the role pyoracledb. The version depends on the Python version of the target host (1.4.2 for Python 3.6 on OL8, 4.0.2 for Python 3.9 on OL9). Without access to the Python package index, put the wheel files into a directory and point to it from your inventory, e.g., pyoracledb_wheel_dir: /tmp/python-packages. pip selects the wheel file matching the Python version of the target host.

Otherwise, the package must be manually installed as root.

4.1.1. Optional: install python-oracledb manually

As shown above, on the target machine:

pip install /tmp/python-packages/oracledb-*.whl

Skip the installation with the role pyoracledb in this case: pyoracledb_install: false.

5. Ready to go!

Activate the virtual environment by issuing aov. Then, run your playbooks as usual.

2.6 - Installation & Patching Settings for the Inventory

1. Introduction

This guide explains the variables used in the inventory to configure RDBMS installation and patching. Usually, both are done at the same time, because for most scenarios you wouldn’t install just the base release of the Oracle RDBMS.

Not described are the details of patch provisioning, e. g., how to obtain the patch files and how to find and enter patch IDs in the inventory.

2. Typical Scenarios

Let’s look at some typical setups concerning where the Oracle software and patch binaries are placed and how they should be processed:

  1. The binaries are stored locally on the Ansible control node. From there they are copied over to the target, where they get unpacked and installed.

  2. The binaries are stored in compressed form on NFS and should be copied over to the target, where they get unpacked and installed.

  3. The binaries are stored in compressed form on NFS. The NFS share will be mounted on the target host and the files will be unpacked from there to /tmp on the target host, then installed from the temp directory.

  4. The binaries are stored uncompressed on NFS. The NFS share will be mounted on the target host and the files will be installed from there.

Here is how the inventory variables interact and what to set for each scenario.

3. Variable Reference

Variable Default Role

is_sw_source_local

true

true = copy from control node; false = download via HTTP

oracle_sw_copy

false if install_from_nfs, else true

Transfer archive to oracle_stage on the target

oracle_sw_unpack

false if install_from_nfs, else true

Unpack archive on the target

oracle_sw_source_local

/tmp

Path on the Ansible control node where archives are read from

install_from_nfs

false

Mount NFS on the target; sets both copy/unpack flags to false by default

oracle_stage

/u01/stage

Local staging directory on the target

oracle_stage_remote

{{ oracle_stage }}

NFS mount point on the target

oracle_patch_stage

{{ oracle_stage }}/patches

Local patch staging directory on the target

oracle_patch_stage_remote

{{ oracle_stage_remote }}/patches

Patch directory on the NFS share

4. Scenario Comparison Table

Setting Sc. 1: Local control node Sc. 2: NFS via control node Sc. 3: NFS on target, unpack first Sc. 4: NFS on target, direct install

install_from_nfs

false

false

true

true

is_sw_source_local

true

true

n/a

n/a

oracle_sw_copy

true

true

false

false

oracle_sw_unpack

true

true

false (*)

false

oracle_sw_source_local

path on control node

NFS mount on control node

—

—

oracle_stage_remote

—

—

NFS mount on target

NFS mount on target

oracle_sw_patches (patching)

required

required

not needed

not needed

Patches pre-extracted on NFS

no

no

yes

yes

(*) For Sc. 3 (installation only): set oracle_sw_unpack: true to unpack from the NFS mount to oracle_stage. For *patching*, this override has no effect — the unpack block requires oracle_sw_copy: true as well, so patches must be pre-extracted on NFS regardless.

5. Scenario Configurations

5.1. Scenario 1 — Binaries on the Ansible control node

# Installation + Patching
is_sw_source_local: true
oracle_sw_copy: true
oracle_sw_unpack: true
oracle_sw_source_local: /path/to/archives   # must contain RDBMS ZIP, patch ZIPs, OPatch ZIP
install_from_nfs: false

# Patching only
oracle_sw_patches:
  - filename: pXXXXXXXX_190000_Linux-x86-64.zip
    patchid: XXXXXXXX
    version: 19.3.0.0
    description: Database Release Update 19.30

db_homes_config:
  db19-si-ee:
    opatch:
      - patchid: XXXXXXXX
        patchversion: 19.30.0.0.260120
        stop_processes: true
        state: present

5.2. Scenario 2 — Compressed archives on NFS, copied via control node

Identical to Scenario 1. oracle_sw_source_local points to the NFS mount point on the control node.

is_sw_source_local: true
oracle_sw_copy: true
oracle_sw_unpack: true
oracle_sw_source_local: /mnt/nfs/orasw      # NFS mount point on the control node
install_from_nfs: false

oracle_sw_patches:
  - filename: pXXXXXXXX_190000_Linux-x86-64.zip
    patchid: XXXXXXXX
    version: 19.3.0.0

5.3. Scenario 3 — NFS mounted on target, unpack to local stage (installation), pre-extracted (patching)

install_from_nfs: true
oracle_sw_copy: false
oracle_sw_unpack: true          # installation only: unpack from NFS to oracle_stage
                                # patching: has no effect; patches must be pre-extracted on NFS
nfs_server_sw: nfs-server.example.com
nfs_server_sw_path: /orasw
oracle_stage_remote: /mnt/nfs  # oracle_patch_stage_remote = /mnt/nfs/patches

# oracle_sw_patches is NOT required
# Required NFS structure for patching:
#   /mnt/nfs/patches/19.3.0.0/XXXXXXXX/        <- extracted patch
#   /mnt/nfs/p6880880_190000_Linux-x86-64.zip  <- OPatch ZIP

5.4. Scenario 4 — Uncompressed binaries on NFS, install and patch directly from NFS

install_from_nfs: true
oracle_sw_copy: false           # default when install_from_nfs: true
oracle_sw_unpack: false         # default when install_from_nfs: true
nfs_server_sw: nfs-server.example.com
nfs_server_sw_path: /orasw
oracle_stage_remote: /mnt/nfs  # oracle_patch_stage_remote = /mnt/nfs/patches

# oracle_sw_patches is NOT required
# Required NFS structure for patching:
#   /mnt/nfs/patches/19.3.0.0/XXXXXXXX/        <- extracted patch
#   /mnt/nfs/p6880880_190000_Linux-x86-64.zip  <- OPatch ZIP

Note that the opatch part of the db home to be patched doesn’t need a path to be set when the required NFS path structure is as above. The patchid is enough in this case. Here’s an example of the settings for the DBRU 19.25:

apply_patches_db: true
db_homes_config:
  db1925-si-ee:
    version: 19.3.0.0
    oracle_home: /u01/app/oracle/product/19/dbhome_1
    edition: EE
    opatch_minversion: 12.2.0.1.44
    state: present
    opatchauto: []
    opatch:
      - patchid: 36912597
        # Database Release Update 19.25.0.0.240716
        patchversion: 19.25.0.0.241015
        stop_processes: true
        state: present
      - patchid: 36878697
        # Oracle JavaVM Component Release Update (OJVM RU) 19.25.0.0.241015
        stop_processes: true
        state: present

However, you could set a path attribute for each patchid if you want to deviate from the standard setups. This might be necessary when you use a "combo patch" instead of separate patch archives for DBRU, OJVM RU et al.

6. Key Behavioral Differences: Installation vs. Patching

For installation, setting oracle_sw_copy: false + oracle_sw_unpack: true (Scenario 3) causes the installer to read the archive from oracle_stage_remote (NFS) and extract directly to oracle_home_db.

For patching, the unpack block unconditionally requires oracle_sw_copy: true. When oracle_sw_copy: false, no copy or unpack step runs at all — the patch must already be extracted on the NFS share at oracle_patch_stage_remote/<version>/<patchid>/. Scenarios 3 and 4 are therefore identical from a patching perspective.

2.7 - Setup APEX and ORDS

Important
The installation of APEX and ORDS with ansible-oracle is currently experimental.

1. Requirements

1.1. APEX

  • RDBMS 19c or newer

  • APEX 20.x or newer is mandatory for RDBMS 19c

  • Tested with APEX 23.2, 24.1 - may work with older versions as well

  • Installation is tested with PDB only.

  • CDB and nonCDB is not supported at the moment.

  • Download ZIP from Oracle with Playbook patch_download.yml supported for Version 22.1 or newer

  • APEX only with ORDS - no old APEX Listener

Important Notes:

  • Primary Note for Oracle APEX Upgrades (Doc ID 1088970.1)

Known Issues:

  • ADMIN password of INTERNAL Workspace is wrong after APEX upgrade Silent script to reset ADMIN password depends on APEX Release.
    There was no reliable solution found for the moment…​

1.2. ORDS

  • OracleLinux 8 or 9 only

  • Installation with ords.rpm from the Oracle Linux oracle/software repository on yum.oracle.com

  • Limited database configuration - see documentation

2. APEX Configuration

Important
Install APEX before ORDS - otherwise, the ORDS will not detect and configure APEX.
ORDS is only tested with existing APEX installation.

2.1. Mandatory variables

The following global variables are needed for an APEX installation.

Table 1. Mandatory variables
Value Description

oraapex_default_admin_password

The parameter is mandatory, because it is the only way to configure a password for the admin user at the moment.

Table 2. Optional variables
Value Description

oraapex_base

Default: {{ oracle_base }}/product
The unzip is done into {{ oraapex_base }}/apex_<APEX Version>

oraapex_default_tablespace

Default: SYSAUX
Could be set in each PDB.

oraapex_default_files_tablespace

Default: SYSAUX
Could be set in each PDB.

oraapex_default_temp_tablespace

Default: TEMP
Could be set in each PDB.

oraapex_image_path

Default: /i/
Image path for apxsilentins.sql.
Could be set in each PDB.

2.2. APEX in PDB

APEX can be installed in each PDB.

Table 3. mandatory Variables in oracle_pdbs
Value Description

state

Must be present.
APEX is only installed in PDBs with state: present.

apex_state

State for APEX installation.
Only present supported at the moment.

apex_version

Version of APEX.
Is used to download the Archive from Oracle.

Table 4. optional Variables in oracle_pdbs
Value Description

oraapex_tablespace

Custom APEX Tablespace.

oraapex_files_tablespace

Custom APEX Tablespace for files.

oraapex_temp_tablespace

Custom APEX temporary Tablespace.

oraapex_image_path

Custom image path for apxsilentins.sql.

apex_use_cdn

Default: true
Set the APEX IMAGE_PREFIX to the Oracle CDN https://static.oracle.com/cdn/apex/<APEX Version>/.
The images are not loaded from ORDS when the CDN is used.

apex_patchid

Patchid for PSE BUNDLE FOR APEX

Important
The example shows the minimum attributes for an APEX installation.
That’s not the minimum needed to create a PDB.
Example oracle_pdbs
oracle_pdbs:
  - cdb: CDB1
    pdb_name: PDB1
    state: present
    apex_state: present
    apex_version: 24.1
    apex_patchid: 36695709
Important
oraapex does not use the default passwords from ansible-oracle.
You have to define them in dbpasswords.

oraapex needs the passwords for APEX_PUBLIC_USER and APEX_REST_PUBLIC_USER.
The keys could be written in lower or upper case.
ords_public_user is not used by oraapex, but could be referenced in oraords_db_pools_password (see ORDS Configuration).

The password of APEX_LISTENER is generated with the password lookup into /tmp/passwordfile on the Ansible controller.

Example dbpasswords for APEX in a PDB
dbpasswords:
  CDB1:
    PDB1:
      apex_public_user: ords123
      apex_rest_public_user: ords123
      ords_public_user: ords123
Important
Do not forget to download the APEX Patch when apex_patchid is set in oracle_pdbs.
The patch is not applied with OPatch. oraapex copies the patch into the APEX software directory and executes catpatch.sql in the PDB.

oraapex expects the archive p<apex_patchid>_<apex_version without dots>0_Generic.zip in oracle_sw_source_local, e.g. p36695709_2410_Generic.zip for APEX 24.1.

Example oracle_sw_patches
oracle_sw_patches:
  - filename: p36695709_2410_Generic.zip
    patchid: 36695709
    version: 24.1
    description: PSE BUNDLE FOR APEX 24.1

2.3. Playbook execution

The installation of APEX is part of playbooks/manage_db.yml.
This allows the creation of custom Tablespaces, Profiles etc. for APEX, without the need to use a dedicated Playbook.

3. ORDS Configuration

Important
The configuration of ORDS is limited to the following variables at the moment.
Table 5. Mandatory variables in oraords_db_pools
Value Description

db_pool

Database Pool.
default is the default pool of ORDS, all other names are created with --db-pool.

service

Database Service Name

Table 6. Optional variables in oraords_db_pools
Value Description

host

Database Hostname
Default: {{ inventory_hostname }}

port

Listener Port
Default: oraords_default_port (1521)

admin_user

Admin user for the ORDS installation
Default: oraords_default_admin_user (sys)

feature_db_api

true / false (Default)

feature_rest_enabled_sql

true / false (Default)

feature_sdw

true / false (Default)

Table 7. Optional global variables for ORDS
Value Description

oraords_apex_image_path

Directory with the APEX images on the ORDS host (standalone.static.path).
The role fails, when <oraords_apex_image_path>/css/apex.css does not exist.
Not needed when APEX uses the CDN (apex_use_cdn).

oraords_apex_image_context

Context path for the APEX images (standalone.static.context.path)

oraords_java_rpm

Default: java-21-openjdk

oraords_ords_bin

Default: /opt/oracle/ords/bin

oraords_ords_config

Default: /etc/ords/config

oraords_ords_logs

Default: /etc/ords/logs

oraords_db_pools:
  - db_pool: default
    admin_user: sys
    service: pdb1
    port: 1521
    host: "{{ inventory_hostname }}"
    feature_db_api: true
    feature_rest_enabled_sql: true
    feature_sdw: true

The passwords for Admin- and ORDS-User are defined in oraords_db_pools_password.
They are set in a dedicated variable to prevent no_log=true in loops over oraords_db_pools.
Referencing dbpasswords helps to reduce redundancy for passwords.

oraords_db_pools_password:
  default:
    admin_password: "{{ dbpasswords['CDB1']['sys'] }}"
    ords_password: "{{ dbpasswords['CDB1']['PDB1']['ords_public_user'] }}"

3.1. Playbook execution

The Playbook playbooks/manage_ords.yml is used to install ORDS.

Note
ords install is executed for each pool and the ORDS service is reloaded on every execution of the Playbook.

2.8 - Oracle AutoUpgrade

Important
The role autoupgrade is currently experimental.
At the moment it supports the installation of AutoUpgrade, the download of patches from My Oracle Support and the Unplug/Plug upgrade of PDBs.
Patching databases with AutoUpgrade is not implemented yet.
The upgrade of PDBs is described in Upgrade of PDBs with AutoUpgrade.

The role autoupgrade uses Oracle AutoUpgrade (autoupgrade.jar) for:

  • Installation of autoupgrade.jar on the database servers or on the Ansible controller

  • Download of the latest autoupgrade.jar from Oracle into the software repository

  • Management of the AutoUpgrade keystore with the My Oracle Support credentials

  • Download of patches from My Oracle Support (-patch -mode download)

  • Unplug/Plug upgrade of PDBs into a CDB of a new release (-mode analyze, -mode fixups, -mode deploy), see autoupgrade_upgrade.adoc

The variables of the role are described in roles/autoupgrade/README.md.

1. Requirements

  • Java on the host executing AutoUpgrade

    • Database server: e.g. the JDK from an ORACLE_HOME (autoupgrade_java_home)

    • Ansible controller: java from PATH or autoupgrade_local_java_home

  • Python module pexpect on the host executing AutoUpgrade for the keystore management (used by ansible.builtin.expect). It is checked by install.yml, but not installed by the role.

  • My Oracle Support account (mos_username, mos_password) for downloading patches

  • Downloads with AutoUpgrade are supported for the releases 19, 21, 23 and 26 (AutoUpgrade 26.6)

2. Proxy

The download of autoupgrade.jar (get_url) and AutoUpgrade itself (keystore, download of patches) use the proxy variables of ansible-oracle: http_proxy, https_proxy and no_proxy. AutoUpgrade reads the lowercase environment variable https_proxy.

AutoUpgrade needs access to updates.oracle.com, login-ext.identity.oraclecloud.com and aru-akam.oracle.com. Use DNS names in the proxy/firewall configuration - the addresses are part of a CDN.

Proxy with authentication
https_proxy: http://proxy.example.com:3128
http_proxy: http://proxy.example.com:3128
no_proxy: localhost,.example.com

autoupgrade_proxy_username: proxyuser
autoupgrade_proxy_password: "{{ vault_proxy_password }}"

The role adds the credentials URL encoded to http_proxy and https_proxy (http://proxyuser:<password>@proxy.example.com:3128). Credentials already contained in http_proxy / https_proxy are not changed.

Java disables Basic authentication for HTTPS tunneling through a proxy by default. With proxy credentials the role adds -Djdk.http.auth.tunneling.disabledSchemes= to the Java options of AutoUpgrade.

Table 1. Variables for the proxy
Variable Description

autoupgrade_proxy_username

Username for the proxy (optional)

autoupgrade_proxy_password

Password for the proxy (optional). Use Ansible Vault.

autoupgrade_java_options

Additional Java options for AutoUpgrade, e.g. a truststore for a proxy with TLS inspection

Truststore for a proxy with TLS inspection
autoupgrade_java_options:
  - -Djavax.net.ssl.trustStore=/etc/pki/java/cacerts
  - -Djavax.net.ssl.trustStorePassword=changeit
Note
A proxy with TLS inspection leads to unable to find valid certification path to requested target. The certificate of the proxy must be in the truststore used by Java.

2.1. Check of the connection

Configuration errors of the proxy lead to misleading errors of AutoUpgrade, e.g. "My Oracle Support credentials in keystore …​ are not valid" for a wrong proxy password. Therefore the role checks the connection to Oracle before (proxy_check.yml):

  • download_patches.yml: before the keystore is used. URLs: autoupgrade_proxy_check_urls.

  • install.yml with autoupgrade_download_latest: true: before the download. URL: autoupgrade_jar_url.

The check is executed on the same host, as the same user and with the same proxy settings (http_proxy, https_proxy, no_proxy, autoupgrade_proxy_username, autoupgrade_proxy_password) as the later download. Any HTTP response of the target counts as success (e.g. 302, 401). The upgrade of PDBs does not need the internet and does not execute the check.

Result of a successful check
https://login-ext.identity.oraclecloud.com => HTTP 401
https://transport.oracle.com => HTTP 302
https://updates.oracle.com => HTTP 302
https://aru-akam.oracle.com => HTTP 302
Proxy: http://proxyuser:***@proxy.example.com:3128

The password of the proxy is never shown. A failed check shows the error and a hint for each URL, then the play fails:

Failed check: wrong password of the proxy
No connection to Oracle
Executed on: dbserver1
Proxy:       http://proxyuser:***@proxy.example.com:3128
no_proxy:    localhost,.example.com
--- https://login-ext.identity.oraclecloud.com ---
Error: Request failed: <urlopen error Tunnel connection failed: 407 Proxy Authentication Required>
Hint:  Proxy authentication failed (407): check autoupgrade_proxy_username / autoupgrade_proxy_password or the credentials in https_proxy.
Table 2. Hints of the check
Error Hint

407 Proxy Authentication Required

wrong or missing credentials for the proxy

Tunnel connection failed: 403

the proxy does not allow the target

Name resolution failed

wrong hostname of the proxy - or no proxy configured, but the internet is reachable through a proxy only

Connection refused

wrong port of the proxy or proxy not running

Timeout, no route

firewall to the proxy - or no proxy configured

CERTIFICATE_VERIFY_FAILED

proxy with TLS inspection: CA of the proxy missing in the trust store

Note
The check uses Python (ansible.builtin.uri), AutoUpgrade uses Java. Problems specific to Java (e.g. the truststore of Java for a proxy with TLS inspection) are not detected by the check.
Table 3. Variables for the check
Variable Default Description

autoupgrade_proxy_check

true

false disables the check

autoupgrade_proxy_check_urls

hosts of AutoUpgrade 26

URLs for download_patches.yml

autoupgrade_proxy_check_timeout

30

Timeout in seconds per URL

The molecule scenario download tests the proxy: download has no route to the internet and reaches Oracle through a Squid with Basic authentication only. side_effect.yml checks the connection with the correct and with a wrong password of the proxy, also with autoupgrade_proxy_check: false (check by keystore.yml after a connection failure, the keystore stays unchanged).

3. Task files

Important
The role has no tasks/main.yml.
Each area of AutoUpgrade has its own task file, which must be called with tasks_from.
Table 4. Task files of role autoupgrade
Task file Description

assert.yml

Check variables and Java. Included by the other task files.

install.yml

Install autoupgrade.jar. Optional download of the latest version from Oracle.

keystore.yml

Create/update the keystore with the My Oracle Support credentials. Included by download_patches.yml.

download_patches.yml

Download patches with AutoUpgrade. Includes install.yml and keystore.yml.

upgrade_analyze.yml

Analyze phase for the Unplug/Plug upgrade of PDBs (analyze). Includes install.yml.

upgrade_fixups.yml

Fixups phase (fixups) in the source CDB/PDBs. Includes upgrade_analyze.yml.

upgrade_deploy.yml

Unplug/Plug upgrade of PDBs. Executes upgrade_analyze.yml first.

Example: call a task file
- name: Install AutoUpgrade
  ansible.builtin.import_role:
    name: opitzconsulting.ansible_oracle.autoupgrade
    tasks_from: install.yml

4. Playbooks

Table 5. Playbooks for AutoUpgrade
Playbook Description

playbooks/autoupgrade_install.yml

Install AutoUpgrade. hostgroup is mandatory. Use autoupgrade_run_local: false for the database servers.

playbooks/autoupgrade_download_patches.yml

Download patches with AutoUpgrade.

playbooks/autoupgrade_upgrade_analyze.yml

Analyze phase for the upgrade of PDBs. hostgroup is mandatory.

playbooks/autoupgrade_upgrade_fixups.yml

Fixups phase for the upgrade of PDBs. hostgroup is mandatory.

playbooks/autoupgrade_upgrade.yml

Unplug/Plug upgrade of PDBs (analyze phase + deploy). hostgroup is mandatory.

Install AutoUpgrade on database servers
ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_run_local=false \
  playbooks/autoupgrade_install.yml
Download patches and the latest autoupgrade.jar
ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_download_latest=true \
  playbooks/autoupgrade_download_patches.yml

5. Execution on Ansible controller or database server

autoupgrade_run_local defines, where AutoUpgrade is executed. The switch is valid for all task files.

Table 6. Execution of AutoUpgrade
autoupgrade_run_local Executed on Directory Java

true (default)

Ansible controller, run_once, no become

autoupgrade_local_home

autoupgrade_local_java_home

false

target host as oracle_user

autoupgrade_home

autoupgrade_java_home

Important
AutoUpgrade is executed on the Ansible controller by default.
Set autoupgrade_run_local: false for the execution on the database servers, e.g. for the installation on the database servers.
Install AutoUpgrade on the database servers and download patches on the Ansible controller
ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_run_local=false \
  playbooks/autoupgrade_install.yml

ansible-playbook -i inventory/ -e hostgroup=dbservers playbooks/autoupgrade_download_patches.yml

The host executing AutoUpgrade needs:

  • Java (see autoupgrade_java_home / autoupgrade_local_java_home)

  • Python module pexpect for the Python interpreter used by Ansible (keystore console). install.yml checks it at the beginning and fails with a clear message. The role does not install pexpect - install it e.g. with the package python3-pexpect or with pip.

  • With autoupgrade_run_local: false: autoupgrade_download_dir must be a directory on the target host, writable for oracle_user. The default oracle_sw_source_local is a directory on the Ansible controller.

  • With autoupgrade_run_local: false: oracle_user must exist (playbook os). oracle_base and oracle_base/cfgtoollogs are created by install.yml with the same attributes as in oraswdb_install. AutoUpgrade can be used before the installation of the Oracle software, e.g. for downloading the patches.

Important
With autoupgrade_run_local: true the tasks are executed only once (run_once) with the variables of the first host in the play.
oracle_sw_patches, db_homes_installed, db_homes_config, oracle_install_version_gi and autoupgrade_download_patches must be the same for all hosts in the play - e.g. defined in group_vars/all for the whole environment.
When they are defined per host, limit the playbook to one host (--limit <host>) or execute it for each host.

6. Installation of autoupgrade.jar

autoupgrade.jar is read from the software repository like all other installation media:

  • is_sw_source_local: true: copy from oracle_sw_source_local on the Ansible controller

  • is_sw_source_local: false: download from oracle_sw_source_www

  • oracle_sw_copy: false: copy from oracle_stage_remote on the database server (e.g. NFS mount)

  • autoupgrade_jar_filesource: full path to autoupgrade.jar, when it is not placed in the software repository

On the Ansible controller oracle_sw_copy is ignored and the file is always taken from oracle_sw_source_local or oracle_sw_source_www.

6.1. Download the latest version

autoupgrade_download_latest: true downloads the latest autoupgrade.jar from Oracle (autoupgrade_jar_url) into the software repository before the installation. The target depends on the location of the installation media:

Table 7. Target for the download of the latest version
Installation media Download on Target

oracle_sw_copy: true or autoupgrade_run_local: true

Ansible controller, run_once, no become. Requires is_sw_source_local: true.

autoupgrade_jar_filesource or oracle_sw_source_local/autoupgrade_jar

oracle_sw_copy: false

target host as oracle_user

autoupgrade_jar_filesource or oracle_stage_remote/autoupgrade_jar

Important
With oracle_sw_copy: false the target directory must exist on the target host and must be writable for oracle_user.
On a shared NFS directory each host downloads the file.

6.2. Update an existing installation

An existing autoupgrade.jar is not replaced by default.
autoupgrade_force_update: true replaces the file, when it differs from the file in the software repository.

Update AutoUpgrade on all database servers with the latest version from Oracle
ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_run_local=false \
  -e autoupgrade_download_latest=true -e autoupgrade_force_update=true \
  playbooks/autoupgrade_install.yml

7. Keystore for My Oracle Support

AutoUpgrade reads the My Oracle Support credentials from a keystore (autoupgrade_keystore). The keystore is managed by keystore.yml with mos_username and mos_password.

Note
AutoUpgrade only offers an interactive console (-load_password) for the keystore. The role uses ansible.builtin.expect for this console.
Table 8. Mandatory variables for the keystore
Variable Description

mos_username

Login for My Oracle Support

mos_password

Password for My Oracle Support

The role stores a fingerprint of mos_username in autoupgrade_keystore/.ansible_oracle_fingerprint. The keystore is created again, when mos_username is changed.

Note
AutoUpgrade writes the input of the keystore console into its log file - including mos_username, but not the passwords.

The keystore is handled as follows:

  1. Keystore exists: check the credentials with list (online check against My Oracle Support). Nothing is changed, when the credentials are valid.

  2. Credentials missing or invalid: add the credentials with add. This requires the keystore password.

  3. Keystore password rejected, keystore missing or fingerprint changed (mos_username): remove the keystore and create it again.

  4. Verify the credentials. The play fails, when the login is not possible (autoupgrade_keystore_fail_on_invalid_credentials: true).

The keystore password is autoupgrade_keystore_password. When it is empty (default), the SHA256 hash of mos_password is used. A changed mos_password changes the keystore password as well - the keystore is recreated automatically.

Important
The keystore is converted to auto-login. AutoUpgrade opens it without password.
The keystore password is only needed for changes.
Table 9. Optional variables for the keystore
Variable Default Description

autoupgrade_keystore_manage

true

false: the keystore must exist and is not changed by the role

autoupgrade_keystore_password

''

Keystore password (min. 16 characters). Empty: SHA256 of mos_password

autoupgrade_keystore_recreate

false

Remove and create the keystore in each execution

autoupgrade_keystore_fail_on_invalid_credentials

true

Fail, when the login into My Oracle Support is not possible

autoupgrade_keystore_no_log

true

false shows the output of tasks with passwords - for debugging only!

8. Download of patches

download_patches.yml creates the AutoUpgrade config file download_patches.cfg and executes autoupgrade.jar -patch -mode download. The patches are placed in autoupgrade_download_dir (default: oracle_sw_source_local).

Each entry in the patch list creates a patch<n> section in the config file. The patch list is built from:

  1. autoupgrade_download_patches: explicit entries with AutoUpgrade keywords

  2. oracle_sw_patches, db_homes_installed, db_homes_config and oracle_install_version_gi (same variables as role orasw_download_patches), when autoupgrade_download_use_oracle_sw_patches: true (default)

8.1. autoupgrade_download_patches

Table 10. Attributes in autoupgrade_download_patches
Attribute Mandatory Description

target_version

yes

Release, e.g. 19, 26

patch

yes

AutoUpgrade keywords and/or patch numbers, e.g. RECOMMENDED, RU,OPATCH,OJVM,DPBP, RU:19.24,OPATCH

platform

no

Default: autoupgrade_download_platform (LINUX.X64)

gold_image

no

NO, AUTO, YES, ALL. Default: autoupgrade_download_gold_image

Example autoupgrade_download_patches
autoupgrade_download_use_oracle_sw_patches: false

autoupgrade_download_patches:
  - target_version: 19
    patch: RU,OPATCH,OJVM,DPBP
    gold_image: "NO"
Resulting section in download_patches.cfg
patch1.target_version=19
patch1.platform=LINUX.X64
patch1.patch=RU,OPATCH,OJVM,DPBP
patch1.gold_image=NO
Important
RU without a version downloads the latest Release Update. A new Release Update from Oracle leads to new downloads. Use RU:<version> for a fixed release.

The attribute patch is passed unchanged to AutoUpgrade. It is a comma separated list of keywords and patch numbers.

Table 11. Keywords for patch (Oracle documentation, AutoUpgrade 26)
Keyword Description

RECOMMENDED

Alias for RU,OPATCH,OJVM,DPBP,AU. Default of AutoUpgrade, when patch is not set.

RU[:x.y]

Release Update. Without version: latest Release Update. Example: RU:19.24

OPATCH

Latest OPatch for the release

OJVM[:x.y]

OJVM Release Update. Without version: version of RU

OCW[:x.y]

Oracle Clusterware (Grid Infrastructure) patch. Without version: version of RU

DPBP

Data Pump Bundle Patch for the Release Update

MRP

Latest Monthly Recommended Patch. Linux only, 19c and 26ai (from 23.26)

AU

AutoUpgrade

<patch number>

One-off patch, e.g. 34672698

Note
Not every keyword is available for every release (e.g. MRP not for 21c). The Oracle documentation lists further keywords (e.g. SDOBP, TOOLS, OEM). See Common Parameters for the AutoUpgrade Configuration File in the Oracle documentation.

8.2. Additional patches

There are three ways to download additional patches. They can be combined.

Table 12. Ways to add patches
Way When to use

Patch number in patch of autoupgrade_download_patches

One-off patches without entry in oracle_sw_patches

Keyword in patch of autoupgrade_download_patches

Patch types, e.g. OCW for Grid Infrastructure, MRP

New entry in oracle_sw_patches

Patches, which are installed by ansible-oracle later (e.g. with db_homes_config)

Example: one-off patches and Clusterware patch in autoupgrade_download_patches
# patch numbers are placeholders
autoupgrade_download_patches:
  - target_version: 19
    patch: RU:19.24,OPATCH,OJVM,OCW,DPBP,34672698,34774667
    gold_image: "NO"
Example: additional patches in oracle_sw_patches
# one-off and Data Pump patch numbers/filenames are placeholders
oracle_sw_patches:
  # Release Update => RU:19.24
  - filename: p36582781_190000_Linux-x86-64.zip
    patchid: 36582781
    version: 19.3.0.0
    ru_version: 19.24.0.0.240716
    description: Database Release Update 19.24.0.0.240716
  # One-off patch => 34672698
  - filename: p34672698_1924000DBRU_Linux-x86-64.zip
    patchid: 34672698
    version: 19.3.0.0
    description: One-off patch for RU 19.24
  # Data Pump Bundle Patch: the keyword is forced with autoupgrade_patch
  - filename: p36682332_1924000DBRU_Generic.zip
    patchid: 36682332
    version: 19.3.0.0
    autoupgrade_patch: DPBP
    description: Data Pump Bundle Patch 19.24
Important
Only entries matching autoupgrade_download_filename_regex are used.
The Data Pump Bundle Patch in the example is a *_Generic.zip and is ignored with the default regex. Use the keyword DPBP in autoupgrade_download_patches or extend autoupgrade_download_filename_regex.

Hints for additional patches:

  • AutoUpgrade selects the file of a one-off patch for the platform and release itself. The filename can differ from filename in oracle_sw_patches, e.g. when the one-off patch exists for several Release Updates. The check after the download reports missing files as warning.

  • Release Updates must use the keyword RU:<x.y>. A patch number of a Release Update is rejected by AutoUpgrade.

  • Each entry of autoupgrade_download_patches creates its own section. Use separate entries for different platforms (platform) or different gold image settings (gold_image).

  • An explicit entry and the entries derived from oracle_sw_patches / db_homes_installed for the same release create two sections. This is accepted by AutoUpgrade. Set autoupgrade_download_use_oracle_sw_patches: false to use autoupgrade_download_patches only.

8.3. oracle_sw_patches

The patches from oracle_sw_patches are added to the section of the release from version (e.g. 19.3.0.0 ⇒ target_version=19).

Only entries are used, where

  • filename matches autoupgrade_download_filename_regex (database patches for Linux x86-64, e.g. p36582781_190000_Linux-x86-64.zip) and

  • the release from version is in autoupgrade_download_supported_releases.

Other entries (e.g. APEX patches *_Generic.zip, cvupack_linux_ol7_x86_64.zip) are ignored with a warning.

AutoUpgrade does not accept Release Updates by patch number. The entries are converted into AutoUpgrade keywords:

Table 13. Conversion of oracle_sw_patches into AutoUpgrade keywords
Entry in oracle_sw_patches AutoUpgrade

attribute autoupgrade_patch

value of the attribute, e.g. RU:19.24, OJVM, DPBP

attribute ru_version, e.g. 19.24.0.0.240716

RU:19.24

description contains OJVM

OJVM

others

patchid (one-off patch)

Important
Set ru_version for each Release Update in oracle_sw_patches.
A Release Update without ru_version is passed as patch number and rejected by AutoUpgrade (RU patches are not allowed to be specified individually).

OPATCH is added for each release of oracle_sw_patches, db_homes_installed and Grid Infrastructure/Oracle Restart (oracle_install_option_gi: CRS_CONFIG or HA_CONFIG).

Example oracle_sw_patches
oracle_sw_patches:
  - filename: p36582781_190000_Linux-x86-64.zip
    patchid: 36582781
    version: 19.3.0.0
    ru_version: 19.24.0.0.240716
    description: Database Release Update 19.24.0.0.240716
  - filename: p36414915_190000_Linux-x86-64.zip
    patchid: 36414915
    version: 19.3.0.0
    description: OJVM 19.24
Resulting section in download_patches.cfg
patch1.target_version=19
patch1.platform=LINUX.X64
patch1.patch=OPATCH,RU:19.24,OJVM

After the download, the role checks if all files from oracle_sw_patches exist in autoupgrade_download_dir. Missing files are reported as warning.

8.4. Gold Image

A gold image is a complete, patched database home (approx. 5 GB). AutoUpgrade requests it from the Oracle Update Advisor service (OUA) in the download mode. The service creates the gold image on demand, when no suitable image is cached.

Table 14. Values for gold_image in download mode (Oracle documentation)
Value Description

AUTO

Default of AutoUpgrade. Resolved to YES, when the connection to the Oracle Update Advisor service is possible, the platform is LINUX.X64 and the Release Update is available for the service. Otherwise NO.

NO

No gold image. All patches are downloaded from My Oracle Support. For 23.x/26ai NO forces the download of the Release Update instead of the gold image.

YES

Gold image with the latest OCW and MRP patches. Other patches (e.g. one-offs) are downloaded separately.

ALL

Gold image with all required patches, including the one-off patches.

The value is set for all sections with autoupgrade_download_gold_image or per entry with gold_image in autoupgrade_download_patches. An empty autoupgrade_download_gold_image (default of the role) does not write the parameter ⇒ AUTO.

8.4.1. Requirements

  • My Oracle Support credentials (mos_username, mos_password)

  • Platform LINUX.X64

  • Enough space in autoupgrade_download_dir

8.4.2. Download a gold image

Example: gold image with all patches for 19c
autoupgrade_download_patches:
  - target_version: 19
    patch: RU:19.24,OPATCH,OJVM,DPBP
    gold_image: ALL
Download the gold image in a dedicated run, default is NO
# inventory
autoupgrade_download_gold_image: "NO"

# command line
ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_download_gold_image=YES \
  playbooks/autoupgrade_download_patches.yml
Note
gold_image in an entry of autoupgrade_download_patches overrides autoupgrade_download_gold_image.
Remove gold_image from the entry, when the gold image should be controlled from the command line.

8.4.3. Hints for gold images

  • Time: When the Oracle Update Advisor service has to create the gold image, this can take a few hours. AutoUpgrade waits for the gold image. Request gold images well in advance of the maintenance window.
    One-off patches (ALL) reduce the chance that a suitable gold image is already cached.

  • Individual images: The gold images are built by Oracle on request of AutoUpgrade. Their content depends on the requirements sent by AutoUpgrade (e.g. release update, patch list, one-off patches, gold_image YES or ALL). Each download can therefore result in an individual image.

  • Filename: Because each gold image can be individual, AutoUpgrade generates a new filename for each download. The filename contains a timestamp (db_goldimage_<release>_<update>_<timestamp>.zip). It cannot be changed.

  • Repeated downloads: Because of the new filename, AutoUpgrade cannot detect an existing gold image. It downloads the gold image again in each execution with AUTO, YES or ALL.
    Recommendation: autoupgrade_download_gold_image: "NO" in the inventory and a gold image only in dedicated runs.

  • Disk space: Old gold images are not removed by AutoUpgrade or the role. Remove them manually from autoupgrade_download_dir.

  • Usage: AutoUpgrade uses gold images from download_folder for the creation of new Oracle homes (create_home mode). This is not implemented in the role yet.
    db_homes_config supports golden images (imagename, filesource) for the installation with oraswdb_install. Whether a gold image from AutoUpgrade can be used there, is not tested.

  • Information: patches_info.json in autoupgrade_download_dir lists the downloaded gold images with release update and included patches.

Disable the download of gold images for all sections
autoupgrade_download_gold_image: "NO"
Note
Quote "NO" in YAML. An unquoted NO is a boolean - the role converts true/false into YES/NO anyway.

8.5. Repeated downloads

AutoUpgrade does not download patches again, when they already exist in autoupgrade_download_dir. The output shows LOCATED for existing files and VALIDATED for downloaded files. The task is reported as changed, when at least one file was downloaded.

AutoUpgrade writes patches_info.json into autoupgrade_download_dir.

9. Known limitations

  • Patching databases with AutoUpgrade is not implemented yet.

  • The download on the Ansible controller uses the variables of the first host in the play (see above).

  • An explicit entry in autoupgrade_download_patches and the derived entry from db_homes_installed / oracle_sw_patches for the same release create two sections in the config file. Set autoupgrade_download_use_oracle_sw_patches: false, when only autoupgrade_download_patches should be used.

  • The filename of a downloaded gold image cannot be changed. Gold images are downloaded again in each execution.

2.9 - Upgrade of PDBs with AutoUpgrade (Unplug/Plug)

Important
The upgrade of PDBs is experimental.
Supported is the Unplug/Plug upgrade of PDBs from a CDB of the old release (e.g. 19c) into an existing CDB of the new release (e.g. 26ai) on the same host.

The role autoupgrade upgrades PDBs with Oracle AutoUpgrade (autoupgrade.jar). AutoUpgrade unplugs the PDBs from the source CDB, plugs them into the target CDB and upgrades them there. The installation of AutoUpgrade and the general settings are described in autoupgrade.adoc.

The upgrade is split into 3 phases. The names are the AutoUpgrade modes:

Table 1. Phases of the upgrade
Phase Task file Playbook AutoUpgrade Downtime Database changed

Analyze

upgrade_analyze.yml

autoupgrade_upgrade_analyze.yml

-mode analyze

no

no

Fixups

upgrade_fixups.yml

autoupgrade_upgrade_fixups.yml

-mode fixups

no

yes, the source CDB/PDBs (e.g. statistics, recyclebin)

Deploy

upgrade_deploy.yml

autoupgrade_upgrade.yml

analyze phase, then -mode deploy

yes, for the PDBs

yes

Important
The analyze phase is always the first step.
upgrade_deploy.yml executes upgrade_analyze.yml first and starts the upgrade only, when the analyze phase was successful.
The fixups phase is optional. It applies the fixups some time before the deploy and shortens the downtime. Without it, AutoUpgrade applies the fixups during the deploy.

1. End state in oracle_pdbs

oracle_pdbs always defines the end state of a PDB. For the upgrade this is the PDB in the target CDB of the new release:

  • cdb: the target CDB

  • home: the target ORACLE_HOME

The source of the PDB is defined with the attribute autoupgrade of the PDB. It is used by the role autoupgrade only.

Warning

Do not execute playbook manage_db between the change of oracle_pdbs and the upgrade!

As soon as a PDB in oracle_pdbs points to the target CDB, oradb_manage_pdb (playbook manage_db) tries to reach this end state. It does not know AutoUpgrade and creates a new, empty PDB in the target CDB instead of migrating the existing PDB.

  • The analyze phase detects this situation (PDB exists in source and target CDB, state conflict) and fails. The empty PDB must be dropped manually before the upgrade.

  • Execute manage_db again only after a successful upgrade (autoupgrade_upgrade.yml).

  • Prepare everything, which needs manage_db (e.g. the target CDB), before oracle_pdbs is changed.

2. Upgrade vs. Out-of-Place Patching

Both procedures move a database into a new ORACLE_HOME. They must not be mixed up.

Table 2. Upgrade vs. Out-of-Place Patching
Topic Upgrade (this guide) Out-of-Place Patching

Release of the new ORACLE_HOME

new release, e.g. 19c ⇒ 26ai

same release, new Release Update, e.g. 19.32 ⇒ 19.33

Object

PDB, moved into another CDB

CDB with all PDBs

Executed by

role autoupgrade (upgrade_deploy.yml)

role oradb_manage_db (switch_home.yml)

Inventory

cdb/home in oracle_pdbs (end state) + attribute autoupgrade (source)

change of home in oracle_databases

Playbook

autoupgrade_upgrade.yml - not manage_db

manage_db

Dictionary

upgraded by AutoUpgrade

datapatch

oradb_manage_db refuses the switch of the ORACLE_HOME of a CDB, when the release of the old and the new ORACLE_HOME differs (oraversion -majorVersion).

3. Requirements

  • Source and target ORACLE_HOME are installed (db_homes_config, db_homes_installed, playbook swdb)

  • The source CDB is running from the source ORACLE_HOME

  • The target CDB exists and is running from the target ORACLE_HOME. It is created with playbook manage_db before the PDBs are changed in oracle_pdbs. 26ai supports Container Databases only.

  • AutoUpgrade (autoupgrade.jar) in the software repository. It is installed on the database server by the task files.

  • Java: the JDK of the target ORACLE_HOME is used, when autoupgrade_java_home is empty

  • AutoUpgrade is executed on the database server as oracle_user. The playbooks set autoupgrade_run_local: false. The task files fail with autoupgrade_run_local: true.

  • The Python module pexpect is not needed for the upgrade

  • Upgrade paths, minimum Release Updates, character sets, components etc. follow the rules of Oracle for AutoUpgrade

4. Configuration

4.1. Attribute autoupgrade in oracle_pdbs

Only PDBs with the attribute autoupgrade and state: present are processed.

Table 3. Attributes of autoupgrade in oracle_pdbs
Attribute Mandatory Description

source_cdb

yes

oracle_db_name of the source CDB. Must differ from cdb.

source_home

no

Key in db_homes_config of the source ORACLE_HOME. Default: home of source_cdb in oracle_databases. Mandatory, when the source CDB is not in oracle_databases.

source_sid

no

SID of the source CDB. Default: oracle_db_instance_name, oracle_db_unique_name or oracle_db_name of source_cdb in oracle_databases, otherwise source_cdb.

source_pdb_name

no

Name of the PDB in the source CDB. Default: pdb_name. A different name renames the PDB (upg1.target_pdb_name.<pdb>).

copy_option

no

upg1.target_pdb_copy_option.<pdb>, e.g. file_name_convert=NONE. Default: NOCOPY - the datafiles are reused, no fallback with the source CDB. See Datafiles: NOCOPY or copy.

restoration

no

true: Guaranteed Restore Point before the upgrade. Default: autoupgrade_upgrade_restoration (false)

parameters

no

Dict with AutoUpgrade parameters (upg1.<key>=<value>). Overrides autoupgrade_upgrade_parameters.

The target is taken from the PDB itself (end state):

  • cdb: target CDB. It must be defined in oracle_databases.

  • home: target ORACLE_HOME. It must be the same as home of the target CDB in oracle_databases.

Example: move ORCLPDB1 from DB2 (19c) into DB26 (26ai)
db_homes_config:
  db1932-si-ee:
    version: 19.3.0.0
    oracle_home: /u01/app/oracle/product/19/db_19.32
    edition: EE
    readonly_home: true
    oracle_home_name: db1932siee
  db26-si-ee:
    version: 26.1.0.0
    oracle_home: /u01/app/oracle/product/26/db_26.1
    edition: EE
    readonly_home: true
    oracle_home_name: db261siee

oracle_databases:
  - oracle_db_name: DB2          # source CDB in 19c
    home: db1932-si-ee
    state: present
    # ...
  - oracle_db_name: DB26         # target CDB in 26ai - created before the upgrade
    home: db26-si-ee
    is_container: true
    state: present
    # ...

oracle_pdbs:
  - cdb: DB26                    # end state: target CDB
    home: db26-si-ee             # end state: target ORACLE_HOME
    pdb_name: ORCLPDB1
    state: present
    autoupgrade:
      source_cdb: DB2            # source CDB
      parameters:
        timezone_upg: "yes"

4.2. AutoUpgrade jobs

All PDBs with the same source CDB and the same target CDB are upgraded in one AutoUpgrade job.

  • Config file: autoupgrade_home/cfg/upgrade_<source SID>_<target SID>.cfg

  • Log directory: autoupgrade_log_dir/<source SID>_<target SID>

  • restoration and parameters must be identical for all PDBs of a job

  • Only PDBs, which are still in the source CDB, are written into upg1.pdbs. An interrupted upgrade continues with the remaining PDBs.

Table 4. Parameters set by the role
AutoUpgrade Value

upg1.sid

SID of the source CDB

upg1.source_home

oracle_home of the source ORACLE_HOME in db_homes_config

upg1.target_home

oracle_home of home of the PDB in db_homes_config

upg1.target_cdb

SID of cdb of the PDB

upg1.pdbs

PDBs in the source CDB (source_pdb_name)

upg1.target_pdb_name.<pdb>

pdb_name, when it differs from source_pdb_name

upg1.target_pdb_copy_option.<pdb>

copy_option

upg1.log_dir

autoupgrade_log_dir/<job>

upg1.restoration

restoration or autoupgrade_upgrade_restoration ⇒ yes/no

global.global_log_dir

autoupgrade_log_dir/<job> - recovery data of AutoUpgrade per job

sid, source_home, target_home, target_cdb, pdbs, log_dir and restoration must not be used in parameters.

Resulting config file upgrade_DB2_DB26.cfg
global.global_log_dir=/u01/app/oracle/cfgtoollogs/autoupgrade

upg1.sid=DB2
upg1.source_home=/u01/app/oracle/product/19/db_19.32
upg1.target_home=/u01/app/oracle/product/26/db_26.1
upg1.target_cdb=DB26
upg1.pdbs=ORCLPDB1
upg1.log_dir=/u01/app/oracle/cfgtoollogs/autoupgrade/DB2_DB26
upg1.restoration=no
upg1.timezone_upg=yes

4.3. Further parameters

All other AutoUpgrade parameters are passed unchanged. Booleans are converted into yes/no.

Table 5. Parameters for the upgrade
Variable Scope Result

autoupgrade_upgrade_parameters

all jobs

upg1.<key>=<value>

autoupgrade.parameters in oracle_pdbs

one job, overrides autoupgrade_upgrade_parameters

upg1.<key>=<value>

autoupgrade_upgrade_global_parameters

config file

global.<key>=<value>

Table 6. Frequently used AutoUpgrade parameters (see Oracle documentation)
Parameter Description

timezone_upg

yes: upgrade the time zone file of the PDB during the upgrade

drop_grp_after_upgrade

yes: drop the guaranteed restore point after a successful upgrade

run_utlrp

Recompile invalid objects after the upgrade

before_action / after_action

Scripts before/after the upgrade

4.4. Variables of the role

Table 7. Variables for the upgrade
Variable Default Description

autoupgrade_upgrade_pdbs

[]

Limit to these PDBs (pdb_name). Empty: all PDBs with attribute autoupgrade.

autoupgrade_upgrade_restoration

false

Guaranteed Restore Point before the upgrade (upg1.restoration)

autoupgrade_upgrade_parameters

{}

AutoUpgrade parameters for all jobs

autoupgrade_upgrade_global_parameters

{}

Additional global.* parameters

autoupgrade_upgrade_fail_on_precheck_errors

true

Fail the analyze/fixups phase on errors without automatic fixup

autoupgrade_upgrade_clear_recovery_data

false

Discard the recovery data of AutoUpgrade before the analyze phase. See Recovery data of AutoUpgrade.

autoupgrade_upgrade_timeout

21600

Maximum runtime in seconds of the deploy per job

autoupgrade_upgrade_poll

60

Poll interval in seconds during the deploy

autoupgrade_java_home

''

JAVA_HOME. Empty: <target ORACLE_HOME>/jdk

Note
The attribute autoupgrade in oracle_databases is not supported. The analyze phase fails, when it is found.

5. Datafiles: NOCOPY or copy

During the Unplug/Plug upgrade AutoUpgrade unplugs the PDB from the source CDB into an XML file and creates the PDB in the target CDB with create pluggable database …​ using '<xml file>'. The attribute copy_option in oracle_pdbs (AutoUpgrade parameter target_pdb_copy_option.<pdb>) defines, what happens with the datafiles.

Table 8. Options for the datafiles
copy_option Datafiles Disk space Duration Fallback into the source CDB

not set (default)

NOCOPY: the target CDB uses the existing datafiles. They stay in their directory, e.g. oradata/DB2/<GUID>/datafile.

none

short, independent of the size

no - the datafiles are upgraded to the new release

file_name_convert=NONE

copied as Oracle Managed Files into db_create_file_dest of the target CDB

size of the PDB

copy of all datafiles

yes - the source datafiles stay unchanged

file_name_convert=('<old>', '<new>')

copied, <old> in the path is replaced by <new>

size of the PDB

copy of all datafiles

yes - the source datafiles stay unchanged

5.1. NOCOPY (default)

oracle_pdbs:
  - cdb: DB1
    home: db26-si-ee
    pdb_name: ORCLPDB1
    state: present
    autoupgrade:
      source_cdb: DB2
      # no copy_option => NOCOPY
  • Fastest way. Recommended for big PDBs, when a backup of the PDB exists.

  • After the upgrade the datafiles of the PDB in the target CDB are still in the directory of the source CDB, e.g. /u01/app/oracle/oradata/DB2/<GUID of the PDB>/datafile/. They can be moved later online with alter database move datafile in the target CDB.

  • There is no way back. Oracle: "Backups are the only fallback strategy." Flashback Database (restoration) does not work across the Unplug/Plug.

Warning

With NOCOPY the target CDB uses datafiles in the directories of the source CDB.
Do not remove these directories (e.g. rm -rf /u01/app/oracle/oradata/DB2), when the source CDB is dropped later. Check the datafiles of the target CDB first:

select name from v$datafile where con_id = (select con_id from v$pdbs where name = 'ORCLPDB1');

5.2. Copy as Oracle Managed Files

oracle_pdbs:
  - cdb: DB1
    home: db26-si-ee
    pdb_name: ORCLPDB1
    state: present
    autoupgrade:
      source_cdb: DB2
      copy_option: file_name_convert=NONE
  • Recommended for OMF and ASM (AutoUpgrade: "For ASM/OMF, use: file_name_convert=none").

  • The target CDB needs db_create_file_dest (or pdb_file_name_convert). Otherwise the analyze phase reports "The target database …​ requires the PDB_FILE_NAME_CONVERT or DB_CREATE_FILE_DEST system parameter defined when the target_pdb_copy_option config parameter is set to file_name_convert=NONE". Set it with init_parameters of the target CDB in oracle_databases.

  • The datafiles are created in the directory of the target CDB, e.g. oradata/DB1/<GUID>/datafile.

  • Needs disk space and time for a complete copy of the PDB. The downtime of the PDB includes the copy.

5.3. Copy with path conversion

oracle_pdbs:
  - cdb: DB1
    home: db26-si-ee
    pdb_name: ORCLPDB1
    state: present
    autoupgrade:
      source_cdb: DB2
      copy_option: "file_name_convert=('/u01/app/oracle/oradata/DB2/', '/u01/app/oracle/oradata/DB1/')"
  • For datafiles with fixed paths (no OMF). Each occurrence of <old> in the path of a datafile is replaced by <new>.

  • More than one pair is possible: file_name_convert=('/a/', '/x/', '/b/', '/y/').

  • The target directories must exist and must be writable for oracle_user.

  • Quote the value in YAML because of the brackets and quotes.

5.4. Fallback after a copy

With a copy the datafiles of the source PDB stay unchanged in the release of the source CDB. AutoUpgrade has unplugged the PDB into an XML file in the job directory:

<autoupgrade_log_dir>/<job>/<source SID>/<job number>/drain/<source SID>-<PDB>.xml

keep_source_pdb (AutoUpgrade parameter, set with parameters) controls the source CDB:

Table 9. keep_source_pdb
Value Source CDB after the upgrade

no (default)

The PDB is dropped from the source CDB (drop pluggable database …​ keep datafiles). The datafiles are kept.

yes

The PDB is kept in the source CDB in a closed state (AutoUpgrade: "kept in a closed state instead of being removed from the source CDB").

    autoupgrade:
      source_cdb: DB2
      copy_option: file_name_convert=NONE
      parameters:
        keep_source_pdb: "yes"

The role ignores PDBs with status UNPLUGGED in the source CDB. A kept source PDB is not reported as conflict.

The fallback itself is a manual task and is not implemented in the role:

  1. Drop the upgraded PDB from the target CDB, if needed (drop pluggable database ORCLPDB1 including datafiles - only with a copy, never with NOCOPY!)

  2. Plug the PDB into the source CDB again, e.g. with the XML file and the unchanged datafiles: create pluggable database ORCLPDB1 using '<xml file>' nocopy; and open it

  3. Change oracle_pdbs back to the source state

Note
The fallback with keep_source_pdb and the copy options is not tested with molecule yet. Test the procedure before you use it in production.

5.5. Recommendation

Table 10. Which option to use
Situation Option

Big PDB, short downtime, backup available

NOCOPY (default)

Fallback into the source CDB needed, enough disk space

file_name_convert=NONE + keep_source_pdb: "yes"

OMF/ASM

file_name_convert=NONE

Fixed paths without OMF, new directory for the target CDB

file_name_convert=('<old>', '<new>')

Important
Take a backup of the PDB before the deploy phase - independent of the option.

6. Process overview

  1. Preparation with manage_db (no downtime) - oracle_pdbs still points to the source CDB

    1. Install the target ORACLE_HOME with playbook swdb (db_homes_installed)

    2. Add the target CDB to oracle_databases and create it with playbook manage_db

  2. Change the inventory to the end state

    1. cdb and home of the PDBs in oracle_pdbs: target CDB and target ORACLE_HOME

    2. Add the attribute autoupgrade with source_cdb to the PDBs

    3. From now on: no manage_db until the upgrade is done!

  3. Analyze phase (no downtime): autoupgrade_upgrade_analyze.yml

    1. Install autoupgrade.jar on the database server

    2. Read the PDBs of the source and the target CDB (v$pdbs)

    3. AutoUpgrade analyze for the PDBs in the source CDB

    4. Evaluate the prechecks. Fail on errors without automatic fixup.

  4. Fix the reported problems and repeat the analyze phase until it is successful

  5. Fixups phase (no downtime, optional): autoupgrade_upgrade_fixups.yml

    1. AutoUpgrade fixups for the PDBs in the source CDB, e.g. some days before the deploy

    2. Evaluate the prechecks like the analyze phase

  6. Deploy phase (downtime of the PDBs): autoupgrade_upgrade.yml

    1. Analyze phase (again)

    2. AutoUpgrade deploy: prechecks, fixups, unplug, plug, upgrade, postupgrade

    3. Check that the PDBs are open READ WRITE in the target CDB

  7. Post tasks

    1. Execute playbook manage_db - the PDBs are in their end state now

    2. Remove the attribute autoupgrade from oracle_pdbs (optional - upgraded PDBs are skipped)

    3. Remove the source CDB, when it is not needed anymore (state: absent in oracle_databases)

7. Analyze phase

ansible-playbook -i inventory/ -e hostgroup=dbservers playbooks/autoupgrade_upgrade_analyze.yml

The role reads the PDBs of the source and the target CDB from v$pdbs. The ORACLE_HOME of a CDB is taken from the running instance (/proc/<pid of pmon>/exe).

Table 11. State of a PDB in the analyze phase
Source CDB Target CDB State Action

PDB exists

PDB missing

pending

AutoUpgrade analyze (fixups phase: fixups), upgrade in the deploy phase

PDB missing

PDB exists

upgraded

nothing - the PDB is skipped

PDB exists

PDB exists

conflict

fail. Usually manage_db was executed after the change of oracle_pdbs and created an empty PDB in the target CDB.

PDB missing

PDB missing

missing

fail

Further checks:

  • The target CDB must be running from the target ORACLE_HOME.

  • The source CDB must be running from the source ORACLE_HOME, when PDBs are pending. It is not needed anymore, when all PDBs are upgraded.

7.1. Evaluation of the prechecks

AutoUpgrade writes the results of the prechecks into the job directory:

<autoupgrade_log_dir>/<job>/<source SID>/<job number>/
  autoupgrade_<date>.log
  autoupgrade_<date>_user.log
  prechecks/
    *_checklist.json
    *_preupgrade.html

The role reads all *_checklist.json of the newest job and evaluates each check with the attribute severity:

Table 12. Evaluation of the prechecks
severity fixup_available runfix Result

ERROR

not YES

-

blocking

ERROR

YES

NO

blocking

ERROR

YES

YES or missing

fixed by AutoUpgrade in the deploy

WARNING, RECOMMEND, INFO

-

-

reported only

The analyze phase fails, when at least one check is blocking (autoupgrade_upgrade_fail_on_precheck_errors: true) or when no *_checklist.json was found.

Note
Oracle does not document the structure of *_checklist.json. The role collects all objects with an attribute severity at any level of the files.

At the end of the analyze phase the role shows for each job:

  • Logfile: detailed logfile of the AutoUpgrade job (<job number>/autoupgrade_<date>.log)

  • User log: summary of the AutoUpgrade job (<job number>/autoupgrade_<date>_user.log)

  • Reports: HTML reports of the prechecks (*_preupgrade.html)

The paths are shown before the evaluation fails, so they are available in case of blocking checks, too.

Result of the analyze phase
"_autoupgrade_upgrade_state": {
    "DB2_DB26": {
        "blocking": [],
        "checks": 51,
        "errors": 0,
        "warnings": 12,
        "log_dir": "/u01/app/oracle/cfgtoollogs/autoupgrade/DB2_DB26",
        "logfile": "/u01/app/oracle/cfgtoollogs/autoupgrade/DB2_DB26/DB2/100/autoupgrade_20261025.log",
        "user_logfile": "/u01/app/oracle/cfgtoollogs/autoupgrade/DB2_DB26/DB2/100/autoupgrade_20261025_user.log",
        "mode": "analyze",
        "pdbs": ["ORCLPDB1"],
        "upgraded_pdbs": [],
        "reports": ["..."],
        "state": "analyzed"
    }
}

8. Fixups phase

ansible-playbook -i inventory/ -e hostgroup=dbservers playbooks/autoupgrade_upgrade_fixups.yml

The fixups phase is the analyze phase with AutoUpgrade in mode fixups (upgrade_fixups.yml includes upgrade_analyze.yml):

  • Same checks of the source and the target CDB and the same states of the PDBs

  • AutoUpgrade executes the prechecks and applies the fixups (e.g. dictionary statistics, purge recyclebin) in the source CDB/PDBs. The PDBs are changed, but stay in the source CDB.

  • Same evaluation of the prechecks, logfiles and reports as the analyze phase. It fails on errors without automatic fixup.

The fixups phase is optional. Execute it some time before the deploy to shorten the downtime. Without it, AutoUpgrade applies the fixups during the deploy.

9. Deploy phase

ansible-playbook -i inventory/ -e hostgroup=dbservers playbooks/autoupgrade_upgrade.yml

# one PDB only
ansible-playbook -i inventory/ -e hostgroup=dbservers -e '{"autoupgrade_upgrade_pdbs": ["ORCLPDB1"]}' \
  playbooks/autoupgrade_upgrade.yml

upgrade_deploy.yml:

  1. executes the analyze phase (upgrade_analyze.yml)

  2. executes autoupgrade.jar -config upgrade_<job>.cfg -mode deploy -noconsole for each job in state analyzed (async: autoupgrade_upgrade_timeout, poll: autoupgrade_upgrade_poll)

  3. checks that all PDBs of the job are open READ WRITE in the target CDB and are gone from the source CDB

The jobs are executed one after the other.

Follow the progress on the database server
tail -f /u01/app/oracle/cfgtoollogs/autoupgrade/DB2_DB1/cfgtoollogs/upgrade/auto/autoupgrade.log

9.1. Repeated execution

  • PDBs in the target CDB are skipped (state upgraded). The playbook can be executed again without changes.

  • An interrupted or failed deploy is resumed by the next execution of autoupgrade_upgrade.yml, see Recovery data of AutoUpgrade.

9.2. Recovery data of AutoUpgrade

AutoUpgrade keeps recovery data after each deploy in autoupgrade_log_dir/<job>/cfgtoollogs/upgrade/auto (config_files/upgradeJobs.bin, state.txt) - for a finished deploy as well as for an interrupted or failed one. As long as the recovery data exists, AutoUpgrade refuses analyze, fixups and a new deploy with the same config file:

There is an unfinished execution of a deploy mode. Run the AutoUpgrade in deploy mode to resume from failure point

The role reads [Status] of the jobs from state.txt before the PDBs are checked:

Table 13. Handling of the recovery data
Recovery data Analyze/fixups phase Deploy phase

none

normal

normal

finished deploy (FINISHED), PDBs pending

cleared automatically (-clear_recovery_data), then normal

cleared automatically, then normal

finished deploy (FINISHED), all PDBs upgraded

kept - needed for -restore

kept

unfinished deploy (other status or no state.txt)

fails with a hint to resume with the deploy phase

state resume: no checks of the PDBs, AutoUpgrade deploy resumes the job with the existing config file

The checks of the PDBs are skipped for resume, because the PDB can be in any intermediate state during a deploy (e.g. unplugged from the source CDB, but not plugged into the target CDB yet). After the resumed deploy the PDBs are checked like after a normal deploy.

autoupgrade_upgrade_clear_recovery_data: true discards the recovery data in any case. Use it only, when the PDBs were restored manually and the upgrade must start from the beginning. An unfinished deploy cannot be resumed anymore afterwards.

ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_upgrade_clear_recovery_data=true \
  playbooks/autoupgrade_upgrade_analyze.yml

9.3. Fallback

  • See Datafiles: NOCOPY or copy: a fallback into the source CDB is possible with a copy of the datafiles only.

  • restoration: true / autoupgrade_upgrade_restoration: true: AutoUpgrade creates a Guaranteed Restore Point (upg1.restoration=yes). Requires a Fast Recovery Area and Enterprise Edition. Check the Oracle documentation, how the restore point is used for an Unplug/Plug upgrade.

The fallback is not implemented in the role.

Important
Take a backup before the upgrade.

10. After the upgrade

oracle_pdbs describes the end state already. Nothing has to be changed for the PDBs.

  • Execute playbook manage_db. It manages the PDBs in the target CDB now (tablespaces, users, services, …​).

  • The attribute autoupgrade can be removed from oracle_pdbs. Upgraded PDBs are skipped anyway.

  • Services, tnsnames.ora entries and wallets, which point to the source CDB, must be changed to the target CDB.

  • Remove the source CDB, when it is not needed anymore (state: absent in oracle_databases), and the source ORACLE_HOME (db_homes_installed).

11. Molecule scenario upgrade

The scenario extensions/molecule/upgrade tests the Unplug/Plug upgrade of ORCLPDB1 from DB2 (19c, db1932-si-ee) into DB1 (26ai, db26-si-ee). The inventory is in extensions/molecule/shared_config/inventory/host_vars/dbfs-upg.yml.

Table 14. Steps in scenario upgrade
Step Playbooks Result

converge

os, swdb, sql_zauberkasten, manage_db

19c and 26ai installed, DB2 with ORCLPDB1 in 19c, empty target CDB DB1 in 26ai, listener from 26ai. oracle_pdbs points to DB2 (source state).

side_effect

autoupgrade_upgrade_analyze, autoupgrade_upgrade_fixups, autoupgrade_upgrade

oracle_pdbs is set to the end state in side_effect.yml (never in the inventory used by converge). Analyze, fixups and deploy phase for ORCLPDB1, controlled by AUTOUPGRADE_PHASE.

verify

ORCLPDB1 is open READ WRITE in DB1 (26ai). Only valid after the deploy phase.

The listener runs from the 26ai ORACLE_HOME: a listener can serve databases of the same or an older release only.

Installation media in MOLECULE_SW_DIR:

  • db_home_19.32.zip (Golden Image 19.32, e.g. from scenario download with autoupgrade_download_gold_image_rename: true)

  • LINUX.X64_2326100_db_home.zip (26ai)

  • autoupgrade.jar

Execute scenario upgrade
cd extensions
task converge S=upgrade
task side-effect S=upgrade

The phases in side_effect.yml are controlled with the environment variable AUTOUPGRADE_PHASE. It is a comma separated list of phases. The phases are always executed in the order analyze, fixups, deploy.

Table 15. AUTOUPGRADE_PHASE for side_effect.yml
Value Executed Use case

all (default, not set)

analyze, fixups, deploy

complete test

analyze

analyze phase only. The databases are not changed.

analyze changes before the deploy, repeat as often as needed

fixups

fixups phase only. The source CDB/PDB is changed, the PDB stays in the source CDB.

test the fixups

deploy

deploy phase only (upgrade_deploy.yml executes the analyze checks internally)

test the deploy without the separate analyze/fixups plays

analyze,fixups

analyze and fixups phase

everything before the deploy

cd extensions
AUTOUPGRADE_PHASE=analyze task side-effect S=upgrade
AUTOUPGRADE_PHASE=fixups task side-effect S=upgrade
AUTOUPGRADE_PHASE=analyze,fixups task side-effect S=upgrade
AUTOUPGRADE_PHASE=deploy task side-effect S=upgrade
task side-effect S=upgrade        # analyze + fixups + deploy

The deploy phase moves ORCLPDB1 into DB1. A new test of the deploy needs a new environment (task destroy S=upgrade and task converge S=upgrade).

Warning
Do not execute task converge S=upgrade during or after the deploy phase without task destroy S=upgrade. The inventory of converge contains the source state (ORCLPDB1 in DB2). manage_db creates a new, empty ORCLPDB1 in DB2 after AutoUpgrade has unplugged it. The deploy phase reports this as conflict.
Important
side_effect.yml must never import playbook manage_db. With oracle_pdbs in the end state it would create an empty ORCLPDB1 in DB1 (see warning above).

12. Known limitations

  • Unplug/Plug upgrade of PDBs into an existing CDB on the same host only. Upgrade of a whole CDB, non-CDB to PDB conversion, RAC, Oracle Restart and Data Guard are not supported.

  • The jobs are executed one after the other. AutoUpgrade can execute jobs in parallel - not used by the role.

  • The fallback is not implemented in the role.

  • manage_db must not be executed between the change of oracle_pdbs and the upgrade (see warning above).

  • The evaluation of the prechecks depends on *_checklist.json, which is not documented by Oracle.

  • Patching of databases with AutoUpgrade (-patch) is not implemented.

2.10 - Oracle Autonomous Health Framework (AHF)

Important
The roles ahf and ahf_fleet_insights are under development and experimental.
Breaking changes can happen at any time and are not always documented (e.g. in Breaking Changes - Upgrade Guide).

Oracle Autonomous Health Framework (AHF) bundles the diagnostic and health check tools of Oracle:

  • Trace File Analyzer (TFA): collection of diagnostic data for Service Requests, automatic collections after incidents

  • Compliance checks with orachk (exachk on Engineered Systems)

  • AHF Insights: offline HTML reports about the state of the server and the databases

  • OS Watcher, Cluster Health Monitor and Cluster Health Advisor (Grid Infrastructure)

AHF is not needed in every environment. This guide helps with the decisions for an installation and describes the usage in ansible-oracle:

  • Role ahf: installation, upgrade and configuration of AHF on the database servers

  • Role ahf_fleet_insights: AHF Fleet Insights as central web interface for many database servers

The variables are described in roles/ahf/README.md and roles/ahf_fleet_insights/README.md.

1. Architecture overview

Architecture

The role ahf installs AHF on every database server. The role ahf_fleet_insights is optional and installs the central web interface AHF Fleet Insights on a separate server. AHF works without Fleet Insights - the data is then evaluated locally on each database server.

Table 1. Data storage
Location Content Owner Remark

ahf_loc (/opt/oracle.ahf) on the database server

AHF software: TFA, orachk, ahfctl

root

Replaced by an upgrade. No data.

ahf_data_dir (/opt/oracle.ahf/data) on the database server

AHF repository: TFA collections, Compliance results, Insights reports, logs of AHF

root

Primary storage of the data. Local filesystem (no NFS), size limit with reposizeMB, purge with minfileagetopurge.

ahf_ansible_state_file (/opt/oracle.ahf.ansible.json) on the database server

Settings applied by the role ahf

root

Detection of changed settings, see Settings.

ahf_fi_install_dir ({{ oracle_base }}/ahffi) on the Fleet Insights server

Fleet Insights software, embedded Nginx, logs, processing of uploads

ahf_fi_install_user

Plan 4 GB per registered cluster.

Repository database (19c or newer)

Uploaded data of all clients: Compliance results and TFA collections

schema AHFFI

Central copy for the evaluation. Available when a database server is down.

The data flows in one direction only: from the database servers to Fleet Insights (push over HTTPS). The local AHF repository stays the primary storage - a database server keeps working when Fleet Insights is not reachable. Fleet Insights needs no access to the database servers, neither for the collection nor for the evaluation in the browser.

Note
The diagram is rendered by plantuml.com from the master branch on GitHub. Changes of doc/guides/ahf.puml are visible after the merge.

2. When is AHF useful?

Table 2. Use cases for AHF
Situation Recommendation

Grid Infrastructure (RAC, Oracle Restart)

AHF is recommended. Oracle Support requests TFA collections for most Service Requests. GI contains an older TFA - a current AHF replaces it.

Single instance on filesystem with Oracle Support contract

Useful for faster Service Requests (tfactl diagcollect) and regular Compliance checks.

Many database servers

AHF with AHF Fleet Insights gives a central view of the Compliance results and the collections.

Test/development VMs, short-lived environments

Normally not needed. The TFA daemon and the Compliance scheduler need CPU, memory and disk space.

3. Decisions before the installation

3.1. root or non-root installation

Table 3. Installation modes (ahf_install_mode)
Feature root (default) extract (non-root)

User for the installation

root

oracle_user

TFA daemon (systemd), automatic collections

yes

no

Compliance scheduler (ahfctl startahf -compliance)

yes

no

Access to OS logs (/var/log/messages)

yes

no

AHF Fleet Insights client

yes

no

Default ahf_loc / ahf_data_dir

/opt

oracle_base

Recommended by Oracle

yes

only when root is not possible

3.2. Installation directory and data directory

ahf_setup creates oracle.ahf below ahf_loc (software) and oracle.ahf/data below ahf_data_dir (repository with collections, Compliance results and Insights reports).

Table 4. Default directories
Variable Default Reason

ahf_loc

/opt ⇒ /opt/oracle.ahf

Default of Oracle. The binaries are executed by root.

ahf_data_dir

ahf_loc ⇒ /opt/oracle.ahf/data

Default of Oracle. At least 5 GB, 10 GB recommended.

Important
With ahf_install_mode: root every directory in the path of ahf_loc and ahf_data_dir must be owned by root. ahf_setup rejects a data directory in a path of another owner (AHF-00014: AHF Data Location …​ is not owned by root in directory hierarchy).
A directory below oracle_base or below a mount point of host_fs_layout (e.g. /u01, owned by oracle_user by default) is not possible: oracle_user could rename or replace a directory in the path and get the binaries executed by root. The role checks the owner of all directories of ahf_loc and ahf_data_dir before the installation.

The software and the data need about 10 GB in /opt/oracle.ahf. Use a logical volume of its own for /opt/oracle.ahf, owned by root, when the root filesystem has not enough space. A full AHF repository does not fill the root filesystem then.

Logical volume of its own for AHF (role orahost)
host_fs_layout:
  - vgname: vgora
    state: present
    filesystem:
      - { mntp: /u01, lvname: lvorabase, lvsize: 25G, fstype: xfs }
      - { mntp: /opt/oracle.ahf, lvname: lvahf, lvsize: 10G, fstype: xfs, owner: root, group: root, mode: "0755" }
    disk:
      - { device: /dev/sdb, pvname: /dev/sdb1 }
Note
The installer appends oracle.ahf to ahf_loc and oracle.ahf/data to ahf_data_dir. With the defaults, software and data are both in /opt/oracle.ahf and therefore on this logical volume.

3.3. Resource requirements

The values are from the documentation of Oracle and measured in the molecule scenario ahf (AHF 26.10.2, AHF Fleet Insights 25.2.1, freshly installed, idle, 8 CPUs).

Table 5. Database server (role ahf)
Resource Value Source

Disk: software /opt/oracle.ahf

1.2 GB

measured

Disk: data /opt/oracle.ahf/data

at least 5 GB, 10 GB recommended. Grows with collections and Compliance results, limit with reposizeMB

Oracle

Memory: TFA daemon

about 170 MB RSS (Java with -Xmx256m)

measured

CPU: TFA daemon

limit by default: the lower of 4 CPUs or 75% of the CPUs (ahfctl getresourcelimit: cpu 4.0)

Oracle, measured

Compliance checks (orachk)

only during the scheduled runs (default: daily 02:03, Sunday 03:03)

not measured

Table 6. AHF Fleet Insights server (role ahf_fleet_insights)
Resource Value Source

CPU / memory

4 cores, 16 GB RAM (minimum recommendation)

Oracle

Memory idle

about 2.5 GB RSS (34 processes)

measured

Disk: software ahf_fi_install_dir

0.8 GB

measured

Disk: data

4 GB per registered cluster

Oracle

Repository database

separate database (19c or newer), e.g. Oracle Database Free: about 2.2 GB memory

measured

The CPU and memory of TFA can be limited with ahfctl setresourcelimit (only on Linux with a root installation):

Limit TFA to 2 CPUs and 1 GB memory
ahfctl setresourcelimit -value 2
ahfctl setresourcelimit -resource kmem -value 1024
ahfctl getresourcelimit
Note
The documentation of Oracle has different ranges for the memory limit in different releases. Check the allowed values with the installed release. The role ahf does not manage the limits.

3.4. Which components should be active?

Table 7. Components and variables
Component Variable Default Recommendation

TFA daemon

ahf_tfa_enabled

true

Active for GI and production. Disable on small test systems - tfactl stays usable on-demand.

Automatic diagnostic collections

ahf_tfa_settings.autodiagcollect

Oracle: OFF

ON for production with Service Requests. Needs space in the repository.

Compliance scheduler (orachk)

ahf_compliance_autostart

false

Active, when the results are evaluated (mail or AHF Fleet Insights).

AHF Insights

ahf_tfa_settings.autoinsights

Oracle: ON

Insights are created with collections. Usable for the static web server (see below).

AHF Fleet Insights client

ahf_fleet_insights_client

false

Active, when an AHF Fleet Insights server exists.

Minimal installation: TFA on-demand only
ahf_tfa_enabled: false
ahf_compliance_autostart: false
Full installation for production
ahf_tfa_enabled: true
ahf_tfa_settings:
  autodiagcollect: "ON"
  reposizeMB: 10240
  ahfnotificationaddress: dba@example.com
ahf_compliance_autostart: true
ahf_compliance_settings:
  autostart_client:
    COLLECTION_RETENTION: 30
ahf_fleet_insights_client: true
ahf_fleet_insights_url: https://ahffi.example.com:5005
ahf_fleet_insights_user: ahfclient
ahf_fleet_insights_password: "{{ vault_ahf_fleet_insights_password }}"

3.5. systemd, cron or nothing?

The role creates no cron jobs or systemd units for AHF:

  • The TFA daemon is started by AHF itself (oracle-tfa.service / init.tfa).

  • The Compliance checks have their own scheduler (ahfctl startahf -compliance). Oracle recommends the scheduler instead of cron. The schedule is changed with AUTORUN_SCHEDULE of an autorun ID in ahf_compliance_settings.

  • AHF Fleet Insights clients upload their data automatically.

  • The AHF Fleet Insights server starts and monitors its processes with cron entries of ahf_fi_install_user - created by the installer.

A systemd timer is only needed for the static web server without AHF Fleet Insights (see below).

4. Installation media

AHF should be up to date. Oracle releases a new version every quarter.

Table 8. Sources of the installation media
Source Filename Remark

AutoUpgrade (role autoupgrade)

name from My Oracle Support

AHF in autoupgrade_download_patches - always the latest version

My Oracle Support Doc ID 2550798.1 / patch 30166242

AHF-LINUX_v<version>.zip or p30166242_*.zip

manual download into the software repository

Download AHF with AutoUpgrade into the software repository
autoupgrade_download_patches:
  - target_version: 26
    patch: AHF
    platform: LINUX.X64
ansible-playbook -i inventory/ opitzconsulting.ansible_oracle.autoupgrade_download_patches

The role ahf uses the newest file (modification time) matching ahf_installer_patterns in oracle_sw_source_local (Ansible controller) or oracle_stage_remote (oracle_sw_copy: false, e.g. NFS). A fixed file is set with ahf_installer_archive.

The version is taken from the filename AHF-LINUX_v<version>.zip. Patch 30166242 is extracted to find the version of the inner AHF-LINUX_v<version>.zip. Set ahf_installer_version, when the version is not part of the filename.

Note
AHF can upgrade itself (ahfctl setupgrade -autoupgrade on -swstage <dir>). This is not used by ansible-oracle. An upgrade with the role is reproducible, uses the software repository and the signature check, and is executed at a planned time.

5. Installation and configuration with role ahf

Requirements:

  • Perl 5.10 or newer with all core modules - the package perl, perl-interpreter alone is not enough (AHF-00074: Required Perl Modules not found). The role installs perl, openssl and unzip (ahf_packages, ahf_manage_packages).

  • Python module pexpect on the database server for the registration in AHF Fleet Insights

The role executes these steps:

  1. Check of variables, Perl and the owner of ahf_loc

  2. Installation with ahf_setup -silent -local when AHF is missing, or upgrade when the installation media is newer (ahf_upgrade)

  3. Check of the signature of ahf_setup (ahf_verify_signature)

  4. Start/stop of TFA and the Compliance scheduler, tfactl set and orachk -set for changed settings

  5. Registration or deregistration in AHF Fleet Insights

Install AHF on all database servers
ansible-playbook -i inventory/ opitzconsulting.ansible_oracle.ahf -e hostgroup=dbfs

5.1. Settings

ahf_tfa_settings is executed with tfactl set <key>=<value>, ahf_compliance_settings with orachk -set "<key>=<value>;…​" -id <autorun ID> - one call per autorun ID. orachk -set requires AUTORUN_SCHEDULE in every call: the role adds the current schedule, when it is not part of the settings.

The Compliance settings are stored per autorun ID by AHF. The autoruns exist only with a running Compliance scheduler: ahfctl stopahf -compliance removes them, ahfctl startahf -compliance does not recreate them. The role creates the default autoruns of Oracle with orachk -autostart, when they are missing, and applies ahf_compliance_settings again. ahf_compliance_settings requires ahf_compliance_autostart: true.

A new installation has two autorun IDs (orachk -get all -id all shows them with the prefix orachk.):

Table 9. Autoruns of a new installation (AHF 26.10)
Autorun ID AUTORUN_SCHEDULE Checks COLLECTION_RETENTION

autostart_client_oratier1

3 2 * * 1,2,3,4,5,6 (Monday - Saturday 02:03)

profile oratier1

7 days

autostart_client

3 3 * * 0 (Sunday 03:03)

all checks

14 days

Daily checks at 01:30 and a longer retention of the weekly results
ahf_compliance_settings:
  autostart_client_oratier1:
    AUTORUN_SCHEDULE: "30 1 * * 1-6"
  autostart_client:
    COLLECTION_RETENTION: 30

The role stores the applied settings in ahf_ansible_state_file (/opt/oracle.ahf.ansible.json). A setting is executed only, when it differs from the last run. Manual changes with tfactl are not detected. -e ahf_settings_force=true executes all settings again.

Note
Removing a key from ahf_tfa_settings does not reset the setting in AHF. Set the default value of Oracle instead.

5.2. Cluster

The role installs AHF with -local on each host of the play. Execute tfactl syncnodes once after the installation on all nodes of a cluster. An existing TFA of Grid Infrastructure is upgraded by ahf_setup.

ahf_setup uses the Perl of the Grid Infrastructure home on hosts with Oracle Restart or RAC. This Perl is owned by the GI owner and is rejected for a root installation (AHF-00026: Perl is not owned by root). The role passes the Perl of the OS with -perlhome /usr (ahf_perl_home) and checks its owner.

5.3. Uninstall

Uninstall AHF
ansible-playbook -i inventory/ opitzconsulting.ansible_oracle.ahf -e hostgroup=dbfs -e ahf_state=absent

The repository in ahf_data_dir is kept. ahf_uninstall_delete_repo: true removes it.

6. Central evaluation of many servers

6.1. Architecture

The data stays on the database servers and is pushed to a central server:

  • The AHF repository is a local directory on the database server. An NFS share for the repository is not needed - a hanging NFS server has no impact on the database server.

  • The database servers send their data to the central server (push). The central server needs no access to the database servers - neither for the collection nor for the evaluation.

  • The data is available on the central server, when the database server is down.

A pull from the central server (e.g. rsync over SSH from each database server) is possible as well, but requires access of the central server to all database servers.

6.2. AHF Fleet Insights

AHF Fleet Insights is the web interface of Oracle for many AHF clients (My Oracle Support Doc ID 3043060.1).

  • Registered clients upload Compliance results (orachk) and TFA collections automatically.

  • The data is stored in a repository database (Oracle Database 19c or newer). Oracle AI Database 26ai needs no additional license for the repository.

  • The web application (with an embedded Nginx) runs as non-root user on port ahf_fi_port (5005) with HTTPS.

  • Requirements: Oracle Linux / RHEL 8 or newer (x86_64), Java 22 or newer, Oracle Instant Client (Basic, SQL*Plus), 4 cores, 16 GB RAM and 4 GB disk space per registered cluster.

  • Clients need AHF 24.9 or newer.

Important
The Oracle documentation describes the registration for clusters ("AHF Client must be running on a cluster"), but describes the fleet as "database clusters or single-instance systems". Check the registration of single instance servers before planning AHF Fleet Insights for them.

6.2.1. Repository database

Fleet Insights needs a schema user in the repository database, before the role ahf_fleet_insights is executed. The role does not create it. The installation media contains the script create_db_user.sql (in ahf_fleet_setup_onprem.zip) with placeholders for the password and the tablespace:

create_db_user.sql of AHFFI-LINUX_v25.2.1.zip
CREATE USER AHFFI IDENTIFIED BY <password> DEFAULT TABLESPACE <tablespace>;
GRANT CREATE SESSION TO AHFFI;
GRANT CONNECT, RESOURCE TO AHFFI;
GRANT CREATE TABLE TO AHFFI;
GRANT INSERT ANY TABLE TO AHFFI;
alter user AHFFI quota unlimited on <tablespace>;

Optionally, the repository database and the user are managed with ansible-oracle, e.g. a PDB in oracle_pdbs with the user in users (role oradb_manage_users). The password is taken from dbpasswords like for every other user.

Schema user for Fleet Insights in a PDB of ansible-oracle
oracle_pdbs:
  - cdb: DB1
    home: db26-si-ee
    pdb_name: AHFFI
    pdbadmin_user: PDBADMIN
    listener_port: 1521
    state: present
    users:
      - schema: AHFFI
        state: present
        default_tablespace: USERS
        grants:
          - create session
          - connect
          - resource
          - create table
          - insert any table
        quotas:
          - tablespace: USERS
            size: unlimited

dbpasswords:
  DB1:
    AHFFI:
      AHFFI: "{{ vault_ahf_fi_db_password }}"

ahf_fi_db_service: AHFFI
ahf_fi_db_user: AHFFI
ahf_fi_db_password: "{{ vault_ahf_fi_db_password }}"
Note
Check the grants of create_db_user.sql of a new release of Fleet Insights. The molecule scenario ahf creates the user directly with SQL*Plus in an Oracle Database Free container.

6.2.2. Installation

Inventory for AHF Fleet Insights
ahf_fi_db_host: ahffi.example.com
ahf_fi_db_port: 1521
ahf_fi_db_service: ahffi.example.com
ahf_fi_db_user: AHFFI
ahf_fi_db_password: "{{ vault_ahf_fi_db_password }}"
ahf_fi_registration_user: ahfclient
ahf_fi_registration_password: "{{ vault_ahf_fleet_insights_password }}"
Install AHF Fleet Insights
ansible-playbook -i inventory/ opitzconsulting.ansible_oracle.ahf_fleet_insights -e hostgroup=ahffi

The role:

  1. installs cronie, iproute, hostname, the Oracle JDK and Oracle Instant Client (ahf_fi_packages)

  2. installs Fleet Insights with ahf_fleet_setup -quiet <properties> as ahf_fi_install_user and creates the registration user, or patches an existing installation when the installation media is newer

  3. opens ahf_fi_port in firewalld

  4. starts Fleet Insights (ahffi start), when ahffi status does not report it as running, and waits for the web application on ahf_fi_port (ahf_fi_start_timeout)

  5. provides the public certificate as fact ahf_fi_public_cert and optionally as file on the Ansible controller (ahf_fi_public_cert_fetch)

  6. shows ahffi status and the registration command from ahffi info

The properties file with the passwords is removed after the installation.

Fleet Insights has no systemd unit. Its processes are started by cron entries of ahf_fi_install_user, created by the installer - crond must be running.

The installer creates a self-signed certificate with the hostname as CN, but without Subject Alternative Name (SAN). AHF clients (AHF 26.x, Python 3.13) check only the SAN and reject it with CERTIFICATE_VERIFY_FAILED …​ Hostname mismatch, certificate is not valid for '<host>'. The role replaces it (ahffi importcert, Fleet Insights is restarted):

  • ahf_fi_cert_generate: true (default): self-signed certificate with the SAN ahf_fi_cert_names (default: hostname and FQDN). The clients must use one of these names in ahf_fleet_insights_url.

  • ahf_fi_cert_file / ahf_fi_cert_key_file: own certificate, e.g. from an internal CA.

6.2.3. Login to the web interface

The URL of the web interface is shown by ahffi info (Application URL), e.g. https://ahffi.example.com:5005/ahfservice.

Table 10. Default login of the installer
User Password Remark

fleet_admin

welcome1

UI administrator with access to the data of the whole fleet. The password must be changed at the first login.

Important
Change the password of fleet_admin immediately after the installation. The generic registration user (ahf_fi_registration_user) is only used by the AHF clients for the registration and the upload, not for the web interface.
Note
In the molecule scenario ahf the web interface is published on the host: https://localhost:5005/ahfservice.
6.2.3.1. Reset the password of fleet_admin

Oracle documents no reset of a forgotten password of fleet_admin. The UI users are stored in the table AHFFI_USERS of the repository schema (ahf_fi_db_user). The installer writes the hash of the default password welcome1 into this table (install_ahf_service.sh, variable ahffi_admin_default). Setting this hash again resets the password to welcome1, the new password is set at the next login.

Warning
This procedure is derived from the installer of AHF Fleet Insights 25.2.1 and is not documented by Oracle.
Reset the password of fleet_admin to welcome1 (as ahf_fi_install_user on the Fleet Insights server)
cd <ahf_fi_install_dir>
HASH=$(sed -n 's/^ahffi_admin_default="\(.*\)"/\1/p' install_ahf_service.sh)

sqlplus <ahf_fi_db_user>@//<ahf_fi_db_host>:<ahf_fi_db_port>/<ahf_fi_db_service> <<EOF
update ahffi_users
   set user_password = '${HASH}', status = 'ENABLED', update_date = sysdate
 where user_id = 'fleet_admin';
commit;
EOF
Note
The installer sets the default password, when the hash in AHFFI_USERS differs from it (register_admin_user). Check the password of fleet_admin after a patch of Fleet Insights.

6.2.4. Registration of the clients

Register the database servers
ahf_fleet_insights_client: true
ahf_fleet_insights_url: https://ahffi.example.com:5005
ahf_fleet_insights_user: ahfclient
ahf_fleet_insights_password: "{{ vault_ahf_fleet_insights_password }}"
# self-signed certificate of Fleet Insights (ahf_fi_public_cert_fetch of role ahf_fleet_insights)
ahf_fleet_insights_public_cert: "{{ lookup('ansible.builtin.file', inventory_dir + '/files/ahffi_cert.pem') }}"

The client checks the certificate of Fleet Insights. With the self-signed certificate of the installer the registration fails with CERTIFICATE_VERIFY_FAILED, unless the certificate is passed with ahf_fleet_insights_public_cert (ahf configuration set --public-cert). Fetch it with ahf_fi_public_cert_fetch while installing Fleet Insights:

Fetch the certificate to the Ansible controller
ahf_fi_public_cert_fetch: "{{ inventory_dir }}/files/ahffi_cert.pem"

The URL must use a name of the SAN of the certificate (ahf_fi_cert_names). The certificate file on the client must be readable by the owner only (AHF-07275), the role writes it with mode 0600.

The registration asks twice for the password of the registration user, the role answers it with ansible.builtin.expect (Python module pexpect on the database server). It is executed with --os-user {{ oracle_user }} (ahf_fleet_insights_os_user). Without an OS user for the REST access, the registration fails with AHF-02119: Fleet Insights configuration succeeded, but the REST Agent was not started.

ansible-playbook -i inventory/ opitzconsulting.ansible_oracle.ahf -e hostgroup=dbfs

The URL is the URL of ahffi info without /ahfservice. ahf_fleet_insights_force_register: true registers again, e.g. after a password change. ahf_fleet_insights_client: false deregisters a client registered by the role.

6.2.5. Data in AHF Fleet Insights

A registered client uploads its data automatically. The views of Fleet Insights are filled by different data:

Table 11. Data and views of Fleet Insights
Data View in Fleet Insights Automatic on the client Manual start (as root) Inventory (role ahf)

Topology: database servers, databases (CDB, PDB), ASM, clusters

Fleet Topology, Databases, Database Servers

AHF Insights collection at 05:00 and 17:00

tfactl diagcollect -insights -last 1h -silent

ahf_fleet_insights_client: true (no further setting)

Problems, events, OS issues, system changes, patches, RPMs, space

Insights (Detected Problems, Events, …​), Space Analysis

AHF Insights collection at 05:00 and 17:00

tfactl diagcollect -insights -last 1h -silent

ahf_fleet_insights_client: true (no further setting)

Compliance results (orachk)

Insights > Best Practice Issues

Compliance scheduler

orachk -usediscovery -profile ahf -showpass -tag manual_check -readenvconfig

ahf_compliance_autostart: true, schedule in ahf_compliance_settings

Diagnostic collections with log and trace files

collections of the clients

automatic collections after incidents

tfactl diagcollect -database <db> -last 1h -silent

ahf_properties: {ahf.fleet-insights.upload-only-minimal-files: "false"}, ahf_tfa_settings: {autodiagcollect: "ON"}

Capacity

Fleetwide Capacity Analysis, Cluster-Wise Usage Trends

capacity plugin of Fleet Insights and exachk (Exadata)

-

not supported

Table 12. Collector options on the CLI and in the inventory of the role ahf
Option CLI (as root) Inventory (role ahf)

Automatic diagnostic collections after incidents

tfactl set autodiagcollect=ON

ahf_tfa_settings: {autodiagcollect: "ON"}

AHF Insights in automatic collections

tfactl set autoinsights=ON

ahf_tfa_settings: {autoinsights: "ON"}

Size of the TFA repository

tfactl set reposizeMB=10240

ahf_tfa_settings: {reposizeMB: 10240}

Upload of complete collections (log and trace files)

ahf configuration set --property ahf.fleet-insights.upload-only-minimal-files --value false

ahf_properties: {ahf.fleet-insights.upload-only-minimal-files: "false"}

Alert History: timeline of ASM events (only ASM: dismount, dismount_force, offline, mount, last 30 days), view with ahf analysis create --type alert-history --component ASM

ahf configuration set --property ahf.collectors.alert-history --value on

ahf_properties: {ahf.collectors.alert-history: "on"}

Events of the alert logs of databases, ASM and Clusterware (base of the automatic collections), view with tfactl events

always active with a running TFA daemon

ahf_tfa_enabled: true

Enhanced OS metrics

ahf configuration set --property ahf.collectors.enhanced_os_metrics --value on

ahf_properties: {ahf.collectors.enhanced_os_metrics: "on"}

Checks excluded from the Compliance checks

ahf configuration set --property ahf.compliance.excluded-check-ids --value <id>

ahf_properties: {ahf.compliance.excluded-check-ids: "<id>"}

Compliance scheduler

ahfctl startahf -compliance / ahfctl stopahf -compliance

ahf_compliance_autostart: true / false

Schedule and retention of a Compliance autorun

orachk -set "AUTORUN_SCHEDULE=30 1 * * 1-6;COLLECTION_RETENTION=30" -id autostart_client_oratier1

ahf_compliance_settings: {autostart_client_oratier1: {AUTORUN_SCHEDULE: "30 1 * * 1-6", COLLECTION_RETENTION: 30}}

Additional directory for collections

tfactl directory add <dir> -public -noexclusions (asks for component, database, instance)

ahf_tfa_directories: [{path: <dir>, component: RDBMS, database: <db>, instance: <sid>, collection: noexclusions}]

TFA daemon

tfactl enable + ahfctl startahf -tfa / ahfctl stopahf -tfa + tfactl disable

ahf_tfa_enabled: true / false

Registration in Fleet Insights

ahf configuration set --type fleet-insights --user-name <user> --url <url> --public-cert <file> --os-user oracle

ahf_fleet_insights_client: true, ahf_fleet_insights_url, ahf_fleet_insights_user, ahf_fleet_insights_password, ahf_fleet_insights_public_cert

CPU and memory limit of TFA

ahfctl setresourcelimit -value 2

not supported, see Resource requirements

The role executes a setting only, when it differs from the last run (state file ahf_ansible_state_file). Manual changes on the CLI are not detected - -e ahf_settings_force=true executes all settings again.

The data is processed about 2 minutes after the upload. A new client shows its databases after the first Insights collection. The role ahf does not start a collection - start one manually, when the data is needed immediately.

6.2.5.1. Log files and diag_dest of the databases

TFA discovers the directories of Grid Infrastructure, ASM, listeners and the running databases automatically, including the ADR (diag_dest) of each database with the database and instance name:

Directories discovered by TFA (example from Oracle Restart, shortened)
tfactl print directories
| /u01/app/oracle/diag/rdbms/dbhas/DBHAS/trace | [RDBMS]{RDBMS|database=dbhas, RDBMS|instance=DBHAS} | public | root |
| /u01/app/oracle/diag/asm/+asm/+ASM/trace     | [ASM]{ASM|instance=+ASM}                            | public | root |

Directories, which are not discovered (e.g. audit files or log files of an application), are added with ahf_tfa_directories. The role answers the questions of tfactl directory add (component, database, instance) and removes directories, which it has added and which are no longer in the list.

By default the clients upload only minimal files into Fleet Insights: the Insights data and the Compliance results. Diagnostic collections with the log and trace files are uploaded only with ahf.fleet-insights.upload-only-minimal-files: false.

Note
The property ahf.fleet-insights.upload-only-minimal-files is not documented by Oracle. The behavior is observed with AHF 26.10: with true (default) a tfactl diagcollect -database is not uploaded, with false it is uploaded. Complete collections need more space in the repository database and on the Fleet Insights server.
Upload of log files and an additional directory
ahf_properties:
  ahf.fleet-insights.upload-only-minimal-files: "false"

ahf_tfa_directories:
  - path: /u01/app/oracle/admin/DB1/adump
    component: RDBMS
    database: db1
    instance: DB1
    collection: noexclusions

The properties of AHF are set with ahf configuration set --property <name> --value <value> (ahf_properties). ahf configuration get --help lists the supported properties, ahf configuration get --property <name> shows the value.

6.2.6. Check the upload on the client

ahf configuration check --type fleet-insights tests the upload of a client into Fleet Insights. The commands for the clients and the Fleet Insights server, the manual start of a collection with upload and the known errors are described in Troubleshooting.

6.3. Alternative: static web server with AHF Insights

This variant is not implemented in ansible-oracle. It is an option for environments without a repository database.

AHF Insights reports are offline HTML reports (zip file with index.html) - they need no server component.

  1. A systemd timer on the database server creates a report and copies it to the web server:

    # /etc/systemd/system/ahf-insights-push.service
    [Unit]
    Description=Create AHF Insights report and push it to the web server
    
    [Service]
    Type=oneshot
    ExecStart=/opt/oracle.ahf/bin/ahf analysis create --type insights --last 24h
    ExecStart=/usr/bin/rsync -a --include='*/' --include='*insights*.zip' --exclude='*' \
      /u01/app/oracle/ahf/oracle.ahf/data/repository/ ahfpush@web.example.com:
    # /etc/systemd/system/ahf-insights-push.timer
    [Timer]
    OnCalendar=daily
    RandomizedDelaySec=1h
    Persistent=true
    
    [Install]
    WantedBy=timers.target
  2. The SSH key of the database server is restricted to a directory on the web server with rrsync (command="rrsync -wo /srv/ahf/<host>" in authorized_keys).

  3. The web server (Nginx/httpd) extracts the reports (e.g. with a systemd path unit) and serves the directories as static files.

A systemd timer is preferred to cron: random delay (RandomizedDelaySec), catch-up after downtime (Persistent) and the output in the journal.

Table 13. Comparison of the variants
Criteria AHF Fleet Insights Static web server

Product

Oracle, supported

own solution

Data

Compliance results and TFA collections, aggregated

single Insights reports per host and day

Requirements

repository database, Java, Instant Client, 16 GB RAM

web server, SSH/rsync

Transport

HTTPS by the AHF client

rsync over SSH

Overview of the fleet

yes

no - one report per host

The Health Check Collection Manager (APEX application for orachk -setdbupload) is an older alternative for Compliance results only. It is not supported by ansible-oracle.

7. Troubleshooting

The commands are executed as root on the database server (/opt/oracle.ahf/bin with the default ahf_loc) and as ahf_fi_install_user in ahf_fi_install_dir on the Fleet Insights server.

7.1. Database server (AHF client)

7.1.1. Status

Table 14. Status of AHF on the database server
Command Description

ahfctl statusahf

Status of TFA (PID, port, version) and the Compliance scheduler

ahf software get-version --component all

Installed versions of AHF, TFA and Compliance

tfactl print config

Settings of TFA (ahf_tfa_settings)

tfactl print directories

Trace directories discovered by TFA, e.g. CRS, ASM, RDBMS with Oracle Restart

ahfctl getresourcelimit

CPU and memory limits of TFA

orachk -get all -id all

Compliance autoruns with AUTORUN_SCHEDULE and COLLECTION_RETENTION (ahf_compliance_settings)

cat /opt/oracle.ahf.ansible.json

Settings and registration applied by the role ahf (ahf_ansible_state_file)

7.1.2. Connection to Fleet Insights

Test the upload into Fleet Insights
ahf configuration check --type fleet-insights

The command uploads a test file (TestUploadFile.txt) into Fleet Insights and checks the complete path including the certificate:

  • Parameters for 'odbda' are configured correctly (rc 0): the upload works.

  • Parameters are not configured correctly to upload (rc 1): the upload fails. The message has no details, check the known errors below. After a new installation or a new certificate of Fleet Insights, run the role ahf again - it registers the client again, when the certificate has changed. ahf_fleet_insights_force_register: true registers again in any case.

The client has no log of its uploads. Failed uploads of Compliance results are kept and can be uploaded again:

Failed uploads of Compliance results
orachk -checkservicefaileduploads    # list failed uploads
orachk -uploadservicefailed          # upload them again

7.1.3. Collect data and upload it immediately

The registered client uploads Compliance results and TFA collections automatically. For a check in the web interface, a collection can be started manually:

Compliance check with upload (profile ahf: about 1 minute)
orachk -usediscovery -profile ahf -showpass -tag manual_check -readenvconfig

The output ends with <name> successfully uploaded to Autonomous Health Framework Service. Other profiles (orachk -profile -h), e.g. dba or clusterware, take longer. Without -profile, all checks are executed.

TFA collection of the last hour with AHF Insights and upload
tfactl diagcollect -insights -last 1h -silent

The dashboard of Fleet Insights is built from AHF Insights data. The clients collect it at 05:00 and 17:00, -insights uploads it immediately (about 2 minutes until the data is processed). -silent starts the collection in the background without questions. Without it, tfactl diagcollect asks for an event or an event time (e.g. on hosts with Grid Infrastructure). The status is shown by tfactl print actions and tfactl print collections.

7.1.4. Logs and directories

Table 15. Logs on the database server (default ahf_loc / ahf_data_dir)
Path Content

/opt/oracle.ahf/data/<host>/diag

Logs of AHF (requested by Oracle Support for AHF-00005)

/opt/oracle.ahf/data/<host>/orachk/user_root/output

Compliance results (orachk_<host>_<date>_<tag>.zip, HTML report)

/opt/oracle.ahf/data/repository

TFA collections and Insights reports

/opt/oracle.ahf/data/ahf/diag/ahf

Log of the installation (ahf_install_*.log)

7.1.5. Known errors

Table 16. Known errors on the database server
Message Cause Solution

AHF-00014: AHF Data Location …​ is not owned by root in directory hierarchy

ahf_data_dir below a directory of oracle_user, e.g. oracle_base or /u01

ahf_data_dir in a path owned by root (default /opt)

AHF-00026: Perl is not owned by root

ahf_setup uses the Perl of the GI-Home (Oracle Restart, RAC)

ahf_perl_home: /usr (default)

AHF-00074: Required Perl Modules not found

only perl-interpreter is installed

package perl (ahf_packages)

No scheduler for any ID

ahfctl stopahf -compliance removed the autoruns

ahf_compliance_autostart: true, the role recreates them with orachk -autostart

AUTORUN_SCHEDULE is a mandatory field to setup autorun entries

orachk -set without AUTORUN_SCHEDULE or with an unknown autorun ID

the role adds the current schedule, the ID is used without orachk.

CERTIFICATE_VERIFY_FAILED …​ self-signed certificate

certificate of Fleet Insights is unknown to the client

ahf_fleet_insights_public_cert

CERTIFICATE_VERIFY_FAILED …​ Hostname mismatch

certificate of Fleet Insights without SAN or the URL uses another name

ahf_fi_cert_generate / ahf_fi_cert_names on the server, a name of the SAN in ahf_fleet_insights_url

AHF-07275: Restrict the certificate file to the owner only

certificate file readable by others

mode 0600 (done by the role)

AHF-02119: …​ the REST Agent was not started

registration without OS user for the REST access

ahf_fleet_insights_os_user (default oracle_user)

7.2. AHF Fleet Insights server

7.2.1. Status

Table 17. Status of Fleet Insights (as ahf_fi_install_user in ahf_fi_install_dir)
Command Description

./ahffi status

Status of the web application and the collection processing engine

./ahffi info

URL of the web interface and registration command for the clients

./ahffi version

Installed version

./ahffi diagnose

Diagnostics of Fleet Insights

./ahffi start / ./ahffi stop / ./ahffi restart

Start and stop of all processes

crontab -l

Cron entries, which start and monitor the processes (no systemd unit)

ss -ltnp | grep 5005

Nginx listens on ahf_fi_port

Certificate of Fleet Insights (CN and SAN)
echo | openssl s_client -connect <host>:5005 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName -dates

7.2.2. Uploads of the clients

The access log of Nginx shows the registrations and uploads of all clients:

Registrations and uploads in the access log
LOG=<ahf_fi_install_dir>/ahf_service/third_party/nginx/logs/access.log
grep '"POST /ahfservice/register' $LOG                    # registrations
grep '"PUT /ahfservice/v1/collectionstorage' $LOG         # uploads

The uploads contain the hostname of the client in the path, e.g. …​/collections/tfa/<host>/orachk_<host>_<date>_<tag>.zip (Compliance results), …​/PERIODICPERFDATA_srdc_insights_collection_…​zip (Insights data) and checkserviceupload_*.txt / TestUploadFile.txt (tests).

7.2.3. Logs and directories

Table 18. Logs on the Fleet Insights server
Path Content

<ahf_fi_install_dir>/ahf_service/log/manage_app.log

Start, stop, status and importcert

<ahf_fi_install_dir>/ahf_service/third_party/nginx/logs/access.log

Requests of the browsers and the clients

<ahf_fi_install_dir>/ahf_service/third_party/nginx/logs/error.log

Errors of Nginx

<ahf_fi_install_dir>/ahf_service/certs/cert.pem

Certificate of the web interface

<ahf_fi_stage_dir>/tmp/ahf_fleet_insights_log

Log of the installation (removed with the stage directory after the installation)

7.2.4. Known errors

Table 19. Known errors on the Fleet Insights server
Message Cause Solution

Path to Java, 'JAVA_HOME' must be a valid directory

ahf_fi_java_home does not exist. The Oracle JDK RPM installs into a directory with the full version

ahf_fi_java_home: "" (default): the role uses the newest /usr/lib/jvm/jdk-*-oracle-x64

The installer will fail if run with root privileges

installation as root

ahf_fi_install_user (default oracle_user)

web interface not reachable after a reboot

processes are started by cron, crond is not running

systemctl enable --now crond, ./ahffi start (the role starts Fleet Insights, when it is not running)

Collection Processing Engine | Not Running after a reboot, uploads are not processed

the cron jobs of Fleet Insights restart the server and the collection processing engine at the same time. The restart of the engine removes its own cron entry and is interrupted (observed with Fleet Insights 25.2.1)

./ahffi start - starts all processes and adds the cron entries again. The role ahf_fleet_insights does it, when not all processes are running. Check with ./ahffi status and crontab -l (4 entries) after a reboot

clients fail with Hostname mismatch

certificate of the installer has no SAN

ahf_fi_cert_generate: true (default), ahf_fi_cert_names

login with fleet_admin not possible

password forgotten

see Reset the password of fleet_admin

2.11 - Out-of-Place Patching - Switch ORACLE_HOME

Important
Out-of-Place Patching is supported for Single Instance primary databases without and with Oracle Restart.
The switch of RAC and RAC One Node databases is not supported.
The Grid Infrastructure home of Oracle Restart and of Grid Infrastructure (cluster) 26ai can be switched as well, see Switch of the Grid Infrastructure home (Oracle Restart and cluster).
Terms (Oracle Restart, Grid Infrastructure, RAC): see Featurelist.
The guide describes the concept, all dependencies and the gaps in the current implementation.

Out-of-Place Patching switches a database from its current ORACLE_HOME to another, already installed and patched ORACLE_HOME. The installation and patching of the new ORACLE_HOME is not part of Out-of-Place Patching. It is done before with other roles (oraswdb_install, oraswdb_manage_patches or from a Golden Image).

Advantages compared to In-Place Patching with opatch apply:

  • The new ORACLE_HOME is installed and patched before the switch without downtime, because no database is running from it.

  • The downtime is reduced to a restart of the database and datapatch.

  • Fallback is easy: the old ORACLE_HOME is still available.

Note
A Golden Image is recommended, but not required.
The new ORACLE_HOME can also be installed and patched with ansible-oracle on the database server. The switch of the database is independent from the way the new ORACLE_HOME was created. See Preparation of the new ORACLE_HOME.

1. Requirements

  • Oracle Database 19c or newer

  • Read-Only Oracle Homes (readonly_home: true) are recommended, but not required

    • Configuration files like SPFile and password file are not part of the ORACLE_HOME and are shared between all Read-Only `ORACLE_HOME`s.

    • The switch copies SPFile, PFile and password file, when the location differs between old and new ORACLE_HOME (e.g. switch from a Read-Write into a Read-Only ORACLE_HOME).

    • readonly_home must not be changed for an installed ORACLE_HOME.

  • Each Read-Only ORACLE_HOME needs 2 attributes in db_homes_config:

    db_homes_config:
      db1932-si-ee:
        readonly_home: true
        oracle_home_name: db1932siee
  • oracle_home_name is mandatory:

    • It cannot be derived from the key in db_homes_config. Oracle allows only characters, numbers and _ in the name of an ORACLE_HOME in the Oracle Inventory. YAML keys are much less restrictive (e.g. db1932-si-ee is a valid key, but not a valid oracle_home_name).

    • It must be unique over all ORACLE_HOME`s on a server. It defines the `ORACLE_BASE_HOME ($ORACLE_BASE/homes/<oracle_home_name>), which must not be shared between the old and the new ORACLE_HOME.

  • Enough disk space for at least 2 `ORACLE_HOME`s at the same time

2. Read-Only Oracle Home

A Read-Only Oracle Home separates the software from the configuration. The locations are reported by orabasehome and orabaseconfig.

Table 1. Locations in a Read-Only Oracle Home
Location Path Shared between ORACLE_HOMEs Content

ORACLE_HOME

e.g. /u01/app/oracle/product/19/db19_2610

no

Software only

ORACLE_BASE_CONFIG

$ORACLE_BASE/dbs

yes

SPFile, password file, hc_*.dat, lk*

ORACLE_BASE_HOME

$ORACLE_BASE/homes/<oracle_home_name>

no

network/admin (listener.ora, sqlnet.ora, tnsnames.ora), log, rdbms/log

Important
ORACLE_BASE_CONFIG is shared, but ORACLE_BASE_HOME is not.
All files in $ORACLE_BASE/homes/<oracle_home_name>/network/admin must exist in the new ORACLE_HOME before the switch.

3. Process overview

  1. Prepare the new ORACLE_HOME (no downtime)

    1. Install the new ORACLE_HOME with oraswdb_install / oraswdb_manage_patches (not part of Out-of-Place Patching), one of:

      1. from a Golden Image (recommended)

      2. from the base release, followed by opatch apply for all patches

    2. Create the network configuration in the new ORACLE_BASE_HOME

  2. Switch the database (downtime) - Out-of-Place Patching with oradb_manage_db

    1. Stop the database (and listener) from the old ORACLE_HOME

    2. Change the ORACLE_HOME in /etc/oratab or in Oracle Clusterware (srvctl)

    3. Start the listener and database from the new ORACLE_HOME

    4. Execute datapatch

  3. Post tasks

    1. APEX, time zone, statistics, etc. (optional)

    2. Remove the old ORACLE_HOME after a successful test period

4. Preparation of the new ORACLE_HOME

The new ORACLE_HOME can be prepared in 2 ways. Both are supported by ansible-oracle and both lead to the same result for the switch.

Table 2. Ways to prepare the new ORACLE_HOME
Topic Golden Image Install and patch on the server

Source

Golden Image (imagename or filesource in db_homes_config)

Base release (e.g. 19.3) + patches from oracle_sw_patches

Patching

Included in the Golden Image. Additional patches are possible like for the base release.

oraswdb_manage_patches with opatch/opatchauto from db_homes_config

Duration on the database server

Short (unzip + runInstaller)

Long (opatch apply for each patch)

Identical `ORACLE_HOME`s on all servers

Guaranteed by the Golden Image

Depends on identical patch lists in the inventory

Software needed on the server

Golden Image only

Base release, OPatch and all patches

Relink options (e.g. Unified Auditing, dNFS)

Included in the Golden Image, checked by oraswdb_install

Set by oraswdb_install

Downtime

None

None - no database is running from the new ORACLE_HOME, stop_processes is not needed

Recommendation: download the Golden Image created by Oracle with the role autoupgrade (gold_image in autoupgrade_download_patches or autoupgrade_download_gold_image). This is the way with the least effort, because no ORACLE_HOME has to be installed and patched for creating the Golden Image.

Alternative: create the Golden Image once from an ORACLE_HOME installed and patched by ansible-oracle (role oraswdb_golden_image), e.g. when one-off patches are needed, which are not part of the Golden Image from Oracle.

Use the Golden Image for all servers.

Important
The implementation of the switch must not depend on the way the new ORACLE_HOME was prepared.
The only requirement for the switch is an installed and fully patched ORACLE_HOME.

5. Dependencies

5.1. Registration of the ORACLE_HOME

Table 3. Registration of the ORACLE_HOME for a database
Environment Registration Switch

Single Instance without Oracle Restart

/etc/oratab

Replace the line <SID>:<old ORACLE_HOME>:<Y/N> with the new ORACLE_HOME.

Oracle Restart

Oracle Clusterware (OCR/OLR)

srvctl modify database -db <db_unique_name> -oraclehome <new ORACLE_HOME>
/etc/oratab is not maintained correctly by Oracle Clusterware. ansible-oracle writes the new ORACLE_HOME into /etc/oratab (flag N), but never reads it for the state of the database.

Grid Infrastructure (cluster): RAC, RAC One Node

Oracle Clusterware (OCR)

Rolling switch node by node. Not supported.

The following parts of ansible-oracle read the ORACLE_HOME from /etc/oratab and follow the switch automatically:

  • systemd service / manage_oracle_rdbms_procs.sh (start/stop of databases, without Oracle Restart only)

  • ocenv / .profile_<ORACLE_SID>

  • rman_backup.sh from role oradb_rman (with Oracle Restart from the database resource, crsctl)

5.2. Stop and Start

  • The database must be stopped from the old ORACLE_HOME.

  • With Oracle Restart the stop must be done with srvctl from the old ORACLE_HOME, before srvctl modify database is executed.

  • The start is done from the new ORACLE_HOME.

5.3. Listener

  • A listener running from the database ORACLE_HOME must be restarted from the new ORACLE_HOME.

  • All databases served by this listener must be switched together. Recommendation: run the listener from the Grid Infrastructure home of Oracle Restart or from a dedicated ORACLE_HOME.

  • Static registrations in SID_LIST_<LISTENER> contain the ORACLE_HOME:

    • Data Guard Broker (<db_unique_name>_DGMGRL)

    • extproc

    • Static service entries

5.4. Network configuration and wallets

  • sqlnet.ora, tnsnames.ora and listener.ora must exist in $ORACLE_BASE/homes/<new oracle_home_name>/network/admin. Alternative: a central TNS_ADMIN.

  • WALLET_LOCATION or ENCRYPTION_WALLET_LOCATION in sqlnet.ora must not point into the old ORACLE_HOME.

  • TDE with the init parameter WALLET_ROOT is independent from the ORACLE_HOME.

  • local_listener must not be an alias from tnsnames.ora of the old ORACLE_HOME. DBCA sets local_listener to LISTENER_<DB_NAME> and writes this alias into tnsnames.ora of the ORACLE_HOME. The alias is missing in the new ORACLE_HOME, the instance does not register at the listener (ORA-12514). orasw_meta requires local_listener with EZConnect in init_parameters of Single Instance databases, e.g. //localhost:1521 (see breaking_changes.adoc). Other entries from DBCA in tnsnames.ora of the old ORACLE_HOME are not copied.

5.5. datapatch

  • datapatch is mandatory after the start from the new ORACLE_HOME.

  • datapatch must be executed for the CDB and all PDBs.

  • OJVM patches may need a startup in upgrade mode, depending on the release.

  • Data Guard: datapatch is executed on the primary database only.

5.6. Directory objects

Directory objects can point into the old ORACLE_HOME. The OPatch directories are changed by datapatch, own directories are not.

Find directory objects in the old ORACLE_HOME
select directory_name, directory_path
from dba_directories
where directory_path like '/u01/app/oracle/product/19/db19_2601%';

5.7. Content of the ORACLE_HOME

The new ORACLE_HOME must contain all customizations of the old ORACLE_HOME:

  • Relink options (e.g. Unified Auditing, dNFS) - included in a Golden Image or set by oraswdb_install

  • One-off patches - included in a Golden Image or defined in db_homes_config[].opatch for the new ORACLE_HOME

  • oranfstab

  • Custom DBCA templates

5.8. Data Guard

  • The standby databases are switched first.

  • The primary database is switched afterwards, followed by datapatch.

  • Static listener registrations for the Data Guard Broker must be changed (see Listener).

5.8.1. Physical Standby

Important
Not implemented yet.
The current implementation opens every database after the switch and executes datapatch.

A physical standby database must be handled differently from a primary database:

  • The standby database is started in MOUNT only. Opening the database while Redo Apply is running uses Active Data Guard, which needs an extra license. This is valid even when the standby database was opened READ ONLY WITH APPLY before the switch.

  • datapatch must not be executed on a standby database. The SQL changes are applied with Redo Apply from the primary database.

The role of the database is read after startup mount from the controlfile:

startup mount
select database_role from v$database;
Table 4. Actions after startup mount depending on DATABASE_ROLE
DATABASE_ROLE Open database datapatch

PRIMARY

yes (+ all PDBs)

yes

PHYSICAL STANDBY

no, remains in MOUNT

no

Redo Apply after the switch:

  • With Data Guard Broker (dg_broker_start=TRUE) the broker restarts Redo Apply automatically.

  • Without Data Guard Broker Redo Apply must be restarted manually. ansible-oracle does not start Redo Apply, because it does not manage Data Guard configurations.

    alter database recover managed standby database disconnect;

5.9. External dependencies

  • Enterprise Manager and other monitoring targets

  • Scripts and crontabs with a hard coded ORACLE_HOME

  • Applications with a local ORACLE_HOME (e.g. Bequeath connections)

6. Implementation in ansible-oracle

6.1. Existing features

Out-of-Place Patching itself is the switch of the ORACLE_HOME in oradb_manage_db. The other features prepare the new ORACLE_HOME and are used before the switch.

Table 5. Existing features used for Out-of-Place Patching
Feature Role Comment

Read-Only Oracle Home

oraswdb_install

readonly_home: true and oracle_home_name in db_homes_config

Install from base release

oraswdb_install

Without imagename in db_homes_config

Patch the new ORACLE_HOME

oraswdb_manage_patches

opatch/opatchauto in db_homes_config, apply_patches: true in db_homes_installed. No stop_processes needed, because no database is running from the new ORACLE_HOME

Download Golden Image from Oracle (recommended)

autoupgrade (download_patches.yml)

gold_image in autoupgrade_download_patches or autoupgrade_download_gold_image

Create Golden Image (optional)

oraswdb_golden_image

Install from Golden Image (optional)

oraswdb_install

imagename or filesource in db_homes_config

Relink options

oraswdb_install

Enforced for every ORACLE_HOME, independent from the source

Network configuration

oradb_manage_db

Files are created in ORACLE_BASE_HOME of the ORACLE_HOME of the listener (listener_installed[].home)

datapatch

oradb_datapatch

Remove ORACLE_HOME

oraswdb_install

state: absent in db_homes_installed

Switch ORACLE_HOME of database

oradb_manage_db (switch_home.yml)

Change of oracle_databases[].home. Single Instance without and with Oracle Restart, not Grid Infrastructure (cluster). Stop from old ORACLE_HOME, copy of SPFile/PFile/password file (when the location differs), change of /etc/oratab, start from new ORACLE_HOME, datapatch. Oracle Restart: stop/start with srvctl, srvctl modify database -oraclehome (and -spfile/-pwfile, when copied), start with the start option of the resource, datapatch for the role PRIMARY only. Flag file $ORACLE_BASE/switch_home_<SID>.pending for an incomplete switch.

Switch ORACLE_HOME of listener

oradb_manage_db (loop_listener_details.yml)

Change of listener_installed[].home. Stop from old ORACLE_HOME, start from new ORACLE_HOME.

/etc/oratab without duplicate entries

oradb_manage_db (manage-db.yml)

lineinfile with regexp replaces the entry for the SID. With Oracle Restart the entry <db_unique_name>:<ORACLE_HOME>:N is written as well.

ORACLE_HOME without database

orasw_meta, oraswdb_install

An ORACLE_HOME in db_homes_installed without a database in oracle_databases is valid (e.g. new ORACLE_HOME before the switch, dedicated listener home).

ORACLE_HOME of listener, tnsnames and sqlnet must be installed

orasw_meta (assert_sqlnet.yml)

home in listener_installed, sqlnet_installed and tnsnames_installed must be in db_homes_installed without state: absent (unless state: absent or use_gi_home: true for the entry).

local_listener with EZConnect

orasw_meta (assert_oracle_databases.yml)

local_listener is mandatory in init_parameters of Single Instance databases with state: present.

Switch Grid Infrastructure home of Oracle Restart

oraswgi_install (switch_home.yml)

Change of oracle_home_gi. Oracle Restart 26ai only. See Switch of the Grid Infrastructure home (Oracle Restart and cluster).

6.2. Gaps

Table 6. Missing features for Out-of-Place Patching
Gap Location Description

Incomplete check of oracle_home_name

roles/oraswdb_install/tasks/roohctl.yml

Only the existence of oracle_home_name is checked for readonly_home: true, and only during the installation. Missing: check for allowed characters, unique value over all ORACLE_HOME`s in `db_homes_installed, check in orasw_meta before any change on the server.

6.3. ORACLE_HOME without database

An ORACLE_HOME in db_homes_installed without a database in oracle_databases is a valid configuration:

  • The new ORACLE_HOME has no database before the switch.

  • The old ORACLE_HOME has no database after the switch, until it is removed.

  • Listeners can run from a dedicated ORACLE_HOME without database.

The oracle_db_type must still be identical for all databases in the same ORACLE_HOME. All roles and asserts must support an ORACLE_HOME without database.

7. Switch of the Grid Infrastructure home (Oracle Restart and cluster)

The Grid Infrastructure home of Oracle Restart and of Grid Infrastructure (cluster) is switched by oraswgi_install, when oracle_home_gi differs from crs_home in /etc/oracle/olr.loc. The new home is created from oracle_install_image_gi, normally a gold image of the new Release Update.

Important
Supported for Oracle Restart 26ai and Grid Infrastructure (cluster) 26ai inside the same release (e.g. 23.26.3 ⇒ 23.26.4).
Not supported for 19c: -switchGridHome is not supported by Oracle for Oracle Restart 19c (INS-45101, MOS 2764906.1), 19c Grid Infrastructure (cluster) is not implemented.
Grid Infrastructure (cluster): tested with 2 nodes and a RAC database (molecule scenario rac, side_effect.yml).
Table 7. Steps of oraswgi_install (switch_home.yml)
Step User Description

Extract oracle_install_image_gi into oracle_home_gi

grid

Without downtime.
Grid Infrastructure (cluster): on every node.

gridSetup.sh -silent -setupHomeAs <old home>

grid

Software only installation with Oracle base and groups of the old home. Registers the new home in the central inventory.
Without it, -switchGridHome fails with INS-45127. Without downtime.
Grid Infrastructure (cluster): on every node, one after the other. -setupHomeAs works on the local node only, -switchGridHome needs the new home on all nodes (INS-42016 otherwise).

gridSetup.sh -silent -switchGridHome

grid

Prepares the switch. Without downtime.
Grid Infrastructure (cluster): on the primary node (1st host of orasw_meta_cluster_hostgroup).

root.sh of the new home

root

Oracle Restart: roothas.pl -prepatch/-postpatch -dstcrshome <new home>: stops the stack in the old home and starts it in the new home.
Downtime of ASM, the listeners in the Grid Infrastructure home and all databases managed by Oracle Restart.
The databases are started with their start option. oracle-ohasd.service and the +ASM entry in /etc/oratab point to the new home.
Grid Infrastructure (cluster): rootcrs.pl -prepatch/-postpatch -dstcrshome <new home>, rolling: primary node first, then the other nodes one after the other (throttle: 1). Only the instances of the node in progress are stopped, the RAC databases stay available. rootcrs.pl -prepatch runs cluvfy stage -pre patch: /etc/oraInst.loc must be owned by root (PRVG-2031/PRVG-2032), oraswgi_install sets the owner before root.sh.

runInstaller -updateNodeList

grid

CRS=TRUE for the new home, CRS=FALSE for the old home in the central inventory (not changed by root.sh).
Grid Infrastructure (cluster): in the central inventory of every node (-local).

gi_ignoreprereq: true adds -ignorePrereqFailure to gridSetup.sh and -ignoreSysPrereqs to runInstaller.

Listeners running from the Grid Infrastructure home (e.g. LISTENER) are moved with the stack, listener.ora is copied into the new home. Listeners and databases in database homes are not changed.

The old Grid Infrastructure home is not removed by the switch.

Oracle Restart: a switch back to the old home is done in the same way by setting oracle_home_gi to the old home.

Grid Infrastructure (cluster):

  • A switch back into a former home is not implemented: the former running home is locked by root.sh (e.g. bin/crsctl.bin owned by root), oraswgi_install stops with an assert. Use a new oracle_home_gi.

  • When root.sh fails before the switch (e.g. the CVU check of rootcrs.pl -prepatch), the next run resumes with root.sh: -switchGridHome is skipped, when rootconfig.sh of the new home is already owned by root.

7.1. Removal of obsolete Grid Infrastructure homes

oraswgi_install_remove_obsolete_homes: true removes obsolete Grid Infrastructure homes with deinstall. Without it, old homes stay for a switch back.

The source is the central inventory only. Obsolete is every home in the central inventory

  • with the component oracle.crs (1st component in <home>/inventory/ContentsXML/comps.xml), database homes are never removed,

  • which is not crs_home in /etc/oracle/olr.loc and not oracle_home_gi.

Homes or directories, which are not registered in the central inventory, are not touched and must be removed manually. The removal is only done, when Oracle Restart runs from oracle_home_gi (completed switch).

Table 8. Steps of oraswgi_install (remove_obsolete_home.yml) for each obsolete home
Step User Description

<old home>/deinstall/deinstall -silent -checkonly -o <dir>

grid

Creates the response file. The role stops with an error, when deinstall detects a configuration in the home:
CRS_HOME=false, ASM_IN_HOME=false, ASM_DROP_DISKGROUPS=false and ORA_CRS_HOME=<running home> are required, the output must contain The home being deconfigured is NOT a configured Grid Infrastructure home.

<old home>/crs/install/roothas.sh -unlock -dstcrshome <old home>

root

Only for a locked home (owner root), a former running home.

<old home>/deinstall/deinstall -silent -paramfile <response file>

grid

Removes the software and the home from the central inventory. No downtime.

rootdeinstall.sh

root

Only, when requested in the output of deinstall. Removes the files owned by root and the directory of the home.

Note
deinstall of an obsolete home prints Oracle Restart is stopped and de-configured successfully and requests rootdeinstall.sh "to remove the configuration of the Oracle Restart". This is the standard text of deinstall: the running Oracle Restart in crs_home is not changed (tested with 23.26.3 ⇒ 23.26.4: resources, /etc/oracle/olr.loc, oracle-ohasd.service, +ASM in /etc/oratab and listener.ora of the running home unchanged).
Note
Oracle documents deinstall of the home itself (same release) after an unlock for the previous release Grid home after an upgrade ("Unlocking and Deinstalling the Previous Release Grid Home"). The removal of an old home of the same release after -switchGridHome is not described explicitly.
Inventory example
oracle_install_option_gi: HA_CONFIG
oracle_install_version_gi: 26.1.0.0
# 1st installation: gi_goldimage_26_03.zip, /u01/app/oracle/product/26/restart_26.03
oracle_install_image_gi: gi_goldimage_26_04.zip
oracle_home_gi: /u01/app/oracle/product/26/restart_26.04

8. Inventory example

The ORACLE_HOME for each Release Update gets its own entry in db_homes_config with a unique oracle_home and oracle_home_name. Both ways to prepare the new ORACLE_HOME can be mixed, e.g. the old ORACLE_HOME from a Golden Image and the new one installed and patched on the server.

Example db_homes_config with Golden Image
db_homes_config:
  db19_2601:
    version: 19.3.0.0
    oracle_home: /u01/app/oracle/product/19/db19_2601
    oracle_home_name: db19_2601
    readonly_home: true
    edition: EE
    imagename: db_home_19.30.zip
Example db_homes_config installed and patched on the server
db_homes_config:
  db19_2604:
    version: 19.3.0.0
    oracle_home: /u01/app/oracle/product/19/db19_2604
    oracle_home_name: db19_2604
    readonly_home: true
    edition: EE
    opatch_minversion: 12.2.0.1.48
    opatch:
      - patchid: <RU patch id>
        # Database Release Update 19.31
        state: present
      - patchid: <OJVM patch id>
        # Oracle JavaVM Component Release Update 19.31
        state: present
Note
stop_processes is not needed for the patches of the new ORACLE_HOME.
Example: switch of database ORCL from db19_2601 to db19_2604
db_homes_installed:
  - home: db19_2601
    state: present
  - home: db19_2604
    state: present

oracle_databases:
  - home: db19_2604    # (1)
    oracle_db_name: ORCL
    state: present
  1. Changing home is the trigger for the switch. See Existing features.

9. Open questions

  • oraswdb_install derives the type of an ORACLE_HOME (SI or cluster installation) from the databases in oracle_databases. An ORACLE_HOME without database is installed as SI. A new RAC ORACLE_HOME needs the cluster installation before the switch ⇒ explicit type in db_homes_config (e.g. oracle_db_type)?

  • Handling of a listener shared by databases in different `ORACLE_HOME`s

  • Fallback to the old ORACLE_HOME (datapatch rollback)

2.12 - Standby Databases

Important
Standby databases are experimental in ansible-oracle (Issue #65).
Implemented: inventory structure with asserts, creation of a physical standby database and of the Data Guard Broker configuration (role oradb_standby). See Open Points and TODOs for missing features. Variable names and attributes may change.

The inventory structure is shared by different standby technologies:

  • Oracle Data Guard (type: dataguard)

  • Dbvisit StandbyMP (type: dbvisit) - reserved, not planned for the first implementation

Attributes that apply to every technology are defined at the top level. Attributes for one technology are placed in a sub-dictionary named after it (dg for Data Guard, dbvisit for Dbvisit). No additional variables are needed when a new technology is added.

Only Oracle Database 19c and newer are supported.

1. Overview

Variable Location Description

db_standby_config

group_vars of all members

Standby configurations with technology, members and topology

oracle_databases[].standby_config

host_vars

Reference from a database to an entry in db_standby_config

oracle_databases[].oracle_db_unique_name

host_vars

db_unique_name of the local member

oracle_tnsnames_config / tnsnames_installed

group_vars

TNS aliases for redo transport, broker and RMAN duplicate

oracle_listeners_config / listener_installed

group_vars / host_vars

Listener with static entries for the instances

db_standby_config must be identical on all members of a configuration. Each member needs the complete topology, e.g. for log_archive_config, fal_server or ADD DATABASE in the broker. The topology is never collected from hostvars of other hosts. Only the current role of the other members (database_role from oradb_facts) is read from hostvars.

2. db_standby_config

List of standby configurations.

Table 1. Attributes of a standby configuration
Attribute Mandatory Description

name

yes

Name of the configuration. Referenced by oracle_databases[].standby_config. Used as name of the broker configuration for Data Guard.

type

yes

dataguard or dbvisit. No default value.

members

yes

List of members, see below.

dg

dataguard: for archivelog_deletion_policy

Data Guard attributes of the configuration. Only allowed with type: dataguard. Not needed, when archivelog_deletion_policy is defined in each member.

dbvisit

no

Dbvisit attributes of the configuration. Only allowed with type: dbvisit.

Table 2. Attributes of a member
Attribute Mandatory Description

hosts

yes

List of inventory_hostname of the member. More than 1 host for RAC.

db_unique_name

dataguard: yes, dbvisit: no

db_unique_name of the member. Default for dbvisit: oracle_db_name.

initial_role

yes

primary or physical_standby. Used during creation only, see initial_role.

dg

no

Data Guard attributes of the member. Only allowed with type: dataguard.

dbvisit

no

Dbvisit attributes of the member. Only allowed with type: dbvisit.

2.1. Data Guard attributes (dg)

Table 3. Configuration (db_standby_config[].dg)
Attribute Default Description

protection_mode

MaxPerformance

MaxPerformance, MaxAvailability or MaxProtection

create_method

rman_duplicate_active

Default method for the creation of the standby databases, see Creation of a standby database

create_tasks_file

-

Tasks file for create_method: custom

archivelog_deletion_policy

- (mandatory here or in each member)

RMAN CONFIGURE ARCHIVELOG DELETION POLICY TO <value> of all members, see Archivelog deletion policy

Table 4. Member (db_standby_config[].members[].dg)
Attribute Default Description

connect_identifier

-

TNS alias from oracle_tnsnames_config. Used for redo transport and as broker property DGConnectIdentifier.

log_xpt_mode

ASYNC

Broker property LogXptMode: ASYNC, SYNC or FASTSYNC

delay_mins

0

Broker property DelayMins (delay of redo apply in minutes)

reopen_secs

300

Broker property ReopenSecs: seconds until the redo transport to this member is retried after an error, e.g. while the standby database is restarted during a switchover

create_method

create_method of the configuration

Method for the creation of this standby database

create_tasks_file

create_tasks_file of the configuration

Tasks file for create_method: custom

archivelog_deletion_policy

archivelog_deletion_policy of the configuration

RMAN CONFIGURE ARCHIVELOG DELETION POLICY TO <value> of this member

Note
MaxAvailability and MaxProtection need SYNC or FASTSYNC for at least one standby member.

2.2. Dbvisit attributes (dbvisit)

Reserved for a later implementation.

3. oracle_databases

A database becomes a member of a standby configuration with the attribute standby_config.

Table 5. Additional attributes in oracle_databases
Attribute Description

standby_config

name of an entry in db_standby_config. The type is inherited from that entry.

oracle_db_unique_name

Mandatory for type: dataguard. Must match db_unique_name of the local member.

archivelog

Mandatory true for type: dataguard (ARCHIVELOG mode for redo transport and RMAN DUPLICATE).

force_logging

Must not be false for type: dataguard. oradb_standby enables FORCE LOGGING on the primary database, force_logging: false would disable it again.

listener_name

Mandatory for type: dataguard. Adds the static entries for the instance to listener.ora, including <db_unique_name>_DGMGRL (used by RMAN DUPLICATE and the broker). See LISTENER.md.

All technology specific attributes of a database are defined in its member in db_standby_config (e.g. members[].dg.connect_identifier), not in oracle_databases.

4. Assignment of a database to a member

The member of a database is found by the following rules:

  1. Search all members of the referenced configuration with inventory_hostname in hosts.

  2. When more than 1 member matches (e.g. primary and standby on the same host), the member with db_unique_name = oracle_db_unique_name is used.

  3. Exactly 1 member must match. Otherwise the play fails.

Setup Unique by

Data Guard, different hosts

host

Data Guard, same host

host + db_unique_name

Dbvisit (same db_unique_name on all members)

host

RAC

host (more than 1 entry in hosts)

5. initial_role

initial_role is only used when a member is created:

  • primary: the database is created with dbca.

  • physical_standby: the database is created as standby of the primary.

The role is never enforced afterwards. After a switchover or failover the inventory is not changed and ansible-oracle does not switch back. All decisions at runtime are based on database_role from v$database.

oradb_manage_db does not execute oracle_db (dbca) for a database of a standby configuration, when

  • the instance is running and database_role is not PRIMARY, or

  • the instance is not running/mounted and initial_role of the member is physical_standby.

Listener, tnsnames.ora, oratab and the systemd units are configured for all members.

Before dbca, oradb_manage_db creates the missing directories of a database with standby_config (orasw_meta/tasks/standby_prepare.yml): file destinations, audit_file_dest, diagnostic_dest and the directories of dg_broker_config_file1/2 from init_parameters. oradb_manage_parameters sets dg_broker_start=TRUE on the primary before oradb_standby is executed, the broker configuration files must be accessible at this time. Existing directories are not changed (owner, group and mode are kept).

The systemd unit of a database with standby_config uses ORACLE_START_MODE=auto: the database is started in MOUNT and only a PRIMARY database is opened. A physical standby database is never opened read only by the autostart (no Active Data Guard).

Important

Standby databases are supported with the systemd units of oradb_manage_db only (autostartup_service_mode: units, default since 5.0.0).

The legacy solution (oracle-rdbms.service with dbstart) does not know ORACLE_START_MODE=auto: it opens every database, a physical standby database is opened read only (Active Data Guard, separate license).

oradb_facts stores database_role in oracledb_facts[<db_unique_name>]. state is present for a PRIMARY database only and standby for all other roles. All roles which check state == 'present' (e.g. oradb_manage_pdb, oradb_manage_redo, oradb_manage_users) skip a standby database. oradb_manage_parameters changes the init_parameters of oracle_databases on a standby database too (state: standby), but not the parameters of PDBs and without a restart for scope: spfile. A database of a standby configuration that is not reachable (e.g. not created yet) gets state: unreachable without a failure of oradb_facts.

6. Creation of a standby database

The role oradb_standby (playbook manage_db.yml, after oradb_manage_parameters, only when db_standby_config is not empty) creates a missing standby database: a member with initial_role: physical_standby without an SPFile of the instance. An existing database is never changed by oradb_standby.

Table 6. create_method
Method Description

rman_duplicate_active

RMAN DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE USING COMPRESSED BACKUPSET from the standby host (default)

external

The standby database is created outside of ansible-oracle. A warning is shown while the database is missing.

custom

The tasks file create_tasks_file is included. The result must be a mounted physical standby database.

The SPFile of the standby database is created by rman_duplicate_active only. With external and custom the SPFile is the responsibility of the DBA.

Steps for rman_duplicate_active and custom:

  1. The primary database is searched in the facts of the other members: hostvars[<host>].oracledb_facts[<db_unique_name>].database_role = PRIMARY (oradb_facts). The hosts of the primary database must be part of the play.

  2. The primary database is prepared over its connect_identifier (idempotent): FORCE LOGGING and standby redo logs (number of online redo log groups + 1 per thread, OMF is needed). log_archive_config, fal_server and log_archive_dest_n are set by the Data Guard Broker (dgmgrl).

  3. The standby database is created with the method.

  4. The result is checked: SPFile exists and database_role = PHYSICAL STANDBY.

Details of rman_duplicate_active:

  • Password file in orabaseconfig/dbs, PFile in $ORACLE_BASE/admin/<db_unique_name>/pfile/init<SID>_duplicate.ora (an existing PFile in dbs is not overwritten), instance in NOMOUNT. The PFile contains db_name and audit_file_dest, diagnostic_dest from init_parameters (when defined). Without them the instance uses the defaults (e.g. $ORACLE_BASE/admin/<db_name>/adump) and the start fails, when these directories cannot be written. The PFile is kept after DUPLICATE for a manual repeat of RMAN DUPLICATE on the host.

  • target: connect_identifier of the primary, auxiliary: //<host>:<port>/<db_unique_name>_DGMGRL (host and port from oracle_tnsnames_config of the connect_identifier of the standby)

  • The SPFile of the primary is cloned (SPFILE PARAMETER_VALUE_CONVERT '<primary db_unique_name>','<standby db_unique_name>'). Different or additional parameters of the standby are read from init_parameters of the standby database in oracle_databases (state: present, scope not memory, sid *) and set with SET. The role sets in addition:

    • db_unique_name of the member (always)

    • control_files: <db_create_file_dest>/<db_unique_name>/controlfile/control01.ctl, unless defined in init_parameters

    • local_listener: empty, unless defined in init_parameters. The value of the primary is usually a TNS alias (e.g. LISTENER_<SID> from dbca), which does not exist on the standby host. An empty local_listener registers the instance at the default listener (local host, port 1521).

  • Missing directories of db_create_file_dest, db_create_online_log_dest_n, db_recovery_file_dest, audit_file_dest, diagnostic_dest, dg_broker_config_file1/2 from init_parameters are created before NOMOUNT. Existing directories are not changed (owner, group and mode are kept). Parameters of the cloned SPFile that are not defined in init_parameters keep the value of the primary (after PARAMETER_VALUE_CONVERT): their directories must exist on the standby host.

  • A failed DUPLICATE stops the auxiliary instance and removes the SPFile created by DUPLICATE. The next run starts a new DUPLICATE.

  • RMAN script duplicate_<db_unique_name>.rman and shell script duplicate_<db_unique_name>.sh in $ORACLE_BASE/admin/<db_unique_name>/pfile, without passwords. The shell script reads the SYS password from the environment variable ORADB_STANDBY_SYS_PASSWORD (or from stdin, when the variable is not set and stdin is not a terminal) and passes the connections with stdin to RMAN (not visible in the process list, connect target * in the logfile). Ansible uses the same scripts and passes the password with stdin, because the environment of a task with become is visible in the process list. Both files are kept for a manual repeat on the host:

    sqlplus / as sysdba <<< "startup nomount pfile='$ORACLE_BASE/admin/<db_unique_name>/pfile/init<SID>_duplicate.ora'"
    read -rs ORADB_STANDBY_SYS_PASSWORD; export ORADB_STANDBY_SYS_PASSWORD
    $ORACLE_BASE/admin/<db_unique_name>/pfile/duplicate_<db_unique_name>.sh
      The logfile is in `oradb_standby_rman_logdir`.
    - Redo Apply is started after `DUPLICATE` (`oradb_standby_start_apply`).
Important
local_listener of the standby database is empty after DUPLICATE, unless it is defined in init_parameters of the standby database in oracle_databases.
The DBA is responsible for the inventory: a listener with a different address or port than the default (local host, port 1521) needs local_listener in init_parameters of the standby database. Otherwise the instance is not registered at the listener and the dynamic services (e.g. <db_unique_name>) are missing.
Tip
Define local_listener with EZConnect in init_parameters of all members, e.g. - {name: local_listener, value: '//dbhost1:1521', scope: both, state: present}.
The primary gets a clean value instead of the alias LISTENER_<SID> from dbca (set by oradb_manage_parameters), the standby gets its own value with SET in RMAN DUPLICATE.

The SYS password is read from dbpasswords[<oracle_db_name>]['sys'] or default_dbpass, like dbca in oradb_manage_db.

7. Archivelog deletion policy

archivelog_deletion_policy is mandatory for type: dataguard: in dg of the configuration (all members) or in dg of each member. The policy decides, when RMAN and the Fast Recovery Area may delete an archive log, e.g. not before it is applied on all standby databases. It belongs to the Data Guard configuration and must be defined consciously for every member.

oradb_standby executes RMAN on every member, primary and physical standby, because the policy is stored in the controlfile of each member:

show archivelog deletion policy;
configure archivelog deletion policy to <archivelog_deletion_policy>;
  • CONFIGURE is only executed when the current policy differs (idempotent). SHOW prints TO DISK instead of TO DEVICE TYPE DISK, both are compared normalized.

  • The instance must be mounted. A missing standby database (e.g. create_method: external) is skipped.

  • The controlfile of a new standby database from RMAN DUPLICATE contains the policy of the primary, the policy of the member is configured afterwards.

  • The warning RMAN-08591: warning: invalid archived log deletion policy (e.g. no standby destination yet) is no error.

Table 7. Valid values (case insensitive)
Value Description

NONE

RMAN default: no deletion policy

APPLIED ON [ALL] STANDBY

Eligible after the archive log is applied on (all) standby databases

SHIPPED TO [ALL] STANDBY

Eligible after the archive log is shipped to (all) standby databases

BACKED UP <n> TIMES TO DEVICE TYPE DISK|SBT

Eligible after <n> backups, can be repeated for several devices

APPLIED ON ALL STANDBY BACKED UP <n> TIMES TO DEVICE TYPE DISK

Combination: APPLIED/SHIPPED first, then BACKED UP

Important
BACKED UP needs an RMAN catalog in a Data Guard configuration: without catalog the controlfile of a member knows only its own backups, e.g. the archive logs of a standby database are never eligible for deletion, when the backups run on the primary.
Example without RMAN catalog
db_standby_config:
  - name: DG1
    type: dataguard
    dg:
      archivelog_deletion_policy: APPLIED ON ALL STANDBY
Example with RMAN catalog and backups on the standby database
db_standby_config:
  - name: DG1
    type: dataguard
    dg:
      archivelog_deletion_policy: APPLIED ON ALL STANDBY BACKED UP 1 TIMES TO DEVICE TYPE DISK

8. Data Guard Broker configuration file

oradb_standby creates a dgmgrl script for each database with type: dataguard: $ORACLE_BASE/admin/<db_unique_name>/pfile/dgmgrl.cfg.

Each member gets its own file with the local database as primary database. The file is valid on the host where the database is the PRIMARY at execution time (e.g. after a switchover the file on the new primary is used). The content depends on the inventory only, not on the current role ⇒ it is identical on every run.

Content
  • CREATE CONFIGURATION '<name>' AS PRIMARY DATABASE IS '<local db_unique_name>' CONNECT IDENTIFIER IS '<connect_identifier>'

  • ADD DATABASE …​ MAINTAINED AS PHYSICAL for all other members

  • EDIT DATABASE …​ SET PROPERTY LogXptMode (log_xpt_mode), DelayMins (delay_mins) and ReopenSecs (reopen_secs) for all members

  • ENABLE CONFIGURATION

  • EDIT CONFIGURATION SET PROTECTION MODE (only when protection_mode is not MaxPerformance)

  • SHOW CONFIGURATION

Usage on the host of the primary database
dgmgrl / "@$ORACLE_BASE/admin/<db_unique_name>/pfile/dgmgrl.cfg"

Requirements: dg_broker_start=TRUE on all members and no existing broker configuration.

For an existing broker configuration oradb_standby compares the properties LogXptMode, DelayMins and ReopenSecs of all members on the host of the primary database (SHOW DATABASE …​ '<property>') and changes only the differing properties (EDIT DATABASE …​ SET PROPERTY).

Important
dg_broker_config_file1, dg_broker_config_file2, dg_broker_start and standby_file_management must be defined in init_parameters of all members (state: present, sid: '*'). orasw_meta checks this with an assert at the start of every play (before oradb_manage_parameters):
init_parameters:
  # before dg_broker_start: the files cannot be changed while the broker is running
  # read-only ORACLE_HOME: ORACLE_BASE/dbs (location of SPFile and password file)
  - {name: dg_broker_config_file1, value: '/u01/app/oracle/dbs/dr1<db_unique_name>.dat', scope: both, state: present, dbca: false}
  - {name: dg_broker_config_file2, value: '/u01/app/oracle/dbs/dr2<db_unique_name>.dat', scope: both, state: present, dbca: false}
  - {name: dg_broker_start, value: 'TRUE', scope: both, state: present, dbca: false}
  - {name: standby_file_management, value: 'AUTO', scope: both, state: present}
  • dg_broker_config_file1/2 must be different and must not be below the ORACLE_HOME: the default ($ORACLE_HOME/dbs) is lost with Out-of-Place Patching. Recommendation:

    • read-only ORACLE_HOME: $ORACLE_BASE/dbs (orabaseconfig, location of SPFile and password file)

    • read-write ORACLE_HOME: $ORACLE_BASE/admin/<db_unique_name>/dgbroker (dbs is below the ORACLE_HOME)

        The directories are created by `oradb_standby`.
      - `dg_broker_start` must be `TRUE`, the value of `standby_file_management` is not checked (e.g. `MANUAL` is allowed).
Warning
dg_broker_config_file1/2 can only be changed while the broker is stopped (dg_broker_start=FALSE), otherwise ORA-16573: attempt to change or access configuration file for an enabled broker configuration.
oradb_manage_parameters changes the parameters in the order of init_parameters ⇒ dg_broker_start must always be defined below dg_broker_config_file1 and dg_broker_config_file2 (checked by the assert in orasw_meta).
When the parameters are added to an existing environment with a running broker, the DBA must stop the broker on each member before the next run of ansible-oracle (alter system set dg_broker_start=FALSE) and copy the existing broker configuration files to the new location, if the configuration should be kept. The value is set by oradb_manage_parameters on the primary and on a mounted standby database (state: standby), a new standby database gets it with SET in RMAN DUPLICATE. oradb_standby executes the file once on the host of the primary database (oradb_standby_broker_create: true, default), after the creation of the standby databases, when
  • the local database is the PRIMARY (oradb_facts),

  • no broker configuration exists (show configuration returns ORA-16532) and

  • all other members are PHYSICAL STANDBY databases (oradb_facts of the hosts of the members). Otherwise a warning is shown, e.g. for a standby database with create_method: external that does not exist yet.

An existing broker configuration is never changed. Errors in the output of dgmgrl (Error:, ORA-, Syntax error, …​ was not found) fail the task, all members must be part of the configuration afterwards. A warning is shown, when the broker is not available (e.g. dg_broker_start not TRUE).

9. Role transitions outside of ansible-oracle

Important
This section describes the planned behavior. Only the current behavior is implemented.

Switchover, failover and Fast-Start Failover are usually executed outside of ansible-oracle (DBA, broker observer). ansible-oracle must handle the result of a role transition on the next run.

Current behavior after a failover
  • The old primary database needs a reinstatement (ORA-16661 in the broker configuration).

  • oradb_standby does nothing: the database of the old primary has an SPFile and initial_role: primary.

  • oradb_manage_db skips oracle_db while the instance of the old primary is running with a role other than PRIMARY.

  • oradb_manage_db does not start the systemd unit of a database that is skipped as standby database (it may not exist yet or be damaged), a warning is shown when the instance is not running.

    Warning
    When the instance of the old primary is not running, its role is unknown and initial_role is primary ⇒ oracle_db in oradb_manage_db would start and open the database (split brain). oradb_manage_db must check the facts of the other members before oracle_db, see Open Points and TODOs.

9.1. Case 1: Reinstate (automatic, not destructive)

The broker reports ORA-16661 for a member ⇒ REINSTATE DATABASE '<member>' on the current primary.

  • Requires Flashback Database on the old primary (flashback: true in oracle_databases).

  • Typical case after a failover, no RMAN DUPLICATE needed.

  • Planned switch: oradb_standby_reinstate.

9.2. Case 2: Missing member (automatic, not destructive)

The database of a member does not exist (e.g. a reinstalled server of the old primary) and another member is the PRIMARY (oradb_facts) ⇒ the member is created as standby database, independent of initial_role. initial_role is only used for the initial setup (no member is PRIMARY).

  • ENABLE DATABASE '<member>' (or ADD DATABASE) in the broker after the creation.

  • oradb_manage_db must use the same rule to skip dbca.

9.3. Case 3: Rebuild of an existing standby database (on request only, destructive)

Most frequent case in practice: a reinstatement is not possible (no Flashback Database) or the standby database is damaged.

The rebuild is never executed automatically. It is requested at runtime with the db_unique_name of the member, never in the inventory (otherwise every run would rebuild the standby database):

ansible-playbook -i <inventory> playbooks/standby_rebuild.yml -e '{"oradb_standby_rebuild": ["DB1_SITE1"]}'

The rebuild uses the current creation of a standby database (create_method: rman_duplicate_active). create_method: custom is not supported for a rebuild at the moment.

Table 8. Steps of the rebuild on the host of the member
Step Description

Checks

The member is not the PRIMARY (local state). Another member is the PRIMARY (oradb_facts). Otherwise the rebuild fails.

Broker

DISABLE DATABASE '<member>' on the primary (no failure, when the member is already disabled, e.g. after a failover).

Autostart

systemctl stop oracle-db@<SID> ⇒ no restart by systemd.

Drop

shutdown abort, startup mount restrict exclusive, SQL DROP DATABASE (data files, redo logs, control files, SPFile with OMF), remove the broker configuration files (dg_broker_config_file1/2). Backups and archived redo logs are not removed: backups of a standby database are valid for the whole configuration. A database that cannot be mounted (e.g. lost control files or data files) is not dropped: the SPFile and the broker configuration files are removed, a warning lists the remaining files below the file destinations of the member.

Creation

The SPFile does not exist ⇒ creation with rman_duplicate_active, see Creation of a standby database.

Broker

ENABLE DATABASE '<member>' (or ADD DATABASE) on the primary, check of the member in SHOW CONFIGURATION.

The playbook standby_rebuild.yml executes oradb_facts and oradb_standby on all hosts of the configuration only: oradb_manage_db is not executed (see the warning above), the hosts of the primary database must be part of the play.

10. Validation

The rules are checked by the role orasw_meta (roles/orasw_meta/tasks/assert_standby.yml). The asserts can be disabled with orasw_meta_assert_db_standby_config: false.

db_standby_config:

  • db_standby_config is a list.

  • name is defined and unique in db_standby_config.

  • type is defined and has an allowed value.

  • Only the sub-dictionary matching type is defined (dg or dbvisit) in the configuration and its members.

  • members is a non empty list.

  • hosts is a non empty list for each member. Each host exists in the inventory.

  • initial_role is primary or physical_standby. Exactly 1 member has initial_role: primary.

  • When the current host is part of a member, at least 1 database in oracle_databases references the configuration.

type: dataguard:

  • db_unique_name is defined for each member and unique in the configuration (case insensitive).

  • protection_mode is MaxPerformance, MaxAvailability or MaxProtection (case sensitive).

  • log_xpt_mode is ASYNC, SYNC or FASTSYNC.

  • delay_mins and reopen_secs are integers >= 0.

  • MaxAvailability and MaxProtection need SYNC or FASTSYNC for at least 1 member with initial_role: physical_standby.

  • connect_identifier is defined for each member and exists in oracle_tnsnames_config.

  • create_method is rman_duplicate_active, external or custom. custom needs create_tasks_file in the member or in the configuration.

  • archivelog_deletion_policy is defined for each member (in the member or in the configuration) and is a valid policy, see Archivelog deletion policy.

oracle_databases with standby_config:

  • dg and dbvisit are not defined.

  • standby_config references an existing entry.

  • Exactly 1 member matches the database, see Assignment of a database to a member.

  • type: dataguard: oracle_db_unique_name and listener_name are defined.

  • type: dataguard: archivelog: true, force_logging is not false.

  • oracle_db_unique_name matches db_unique_name of the member (case insensitive). Both default to oracle_db_name.

  • type: dataguard: init_parameters contain dg_broker_config_file1/2 (different, not below ORACLE_HOME), dg_broker_start=TRUE below both file parameters and standby_file_management.

11. Example: Data Guard with 2 hosts

Tip
A complete example with 2 VMs is the Data Guard Guide (example/dataguard).

Hosts dbhost1 (primary) and dbhost2 (standby) are members of the group dg_db1.

inventory/hosts.yml
all:
  children:
    dg_db1:
      hosts:
        dbhost1:
        dbhost2:
inventory/group_vars/dg_db1/standby.yml
db_standby_config:
  - name: DG1
    type: dataguard
    dg:
      protection_mode: MaxPerformance
      archivelog_deletion_policy: APPLIED ON ALL STANDBY
    members:
      - hosts: [dbhost1]
        db_unique_name: DB1_SITE1
        initial_role: primary
        dg:
          connect_identifier: DB1_SITE1
          log_xpt_mode: ASYNC
      - hosts: [dbhost2]
        db_unique_name: DB1_SITE2
        initial_role: physical_standby
        dg:
          connect_identifier: DB1_SITE2
          log_xpt_mode: ASYNC
          delay_mins: 0

oracle_tnsnames_config:
  DB1_SITE1:
    connect:
      service_name: DB1_SITE1
    address:
      - host: dbhost1
        port: 1521
  DB1_SITE2:
    connect:
      service_name: DB1_SITE2
    address:
      - host: dbhost2
        port: 1521

tnsnames_installed:
  - tnsname: DB1_SITE1
    home: db19-si-ee
    state: present
  - tnsname: DB1_SITE2
    home: db19-si-ee
    state: present
inventory/host_vars/dbhost1/databases.yml
oracle_databases:
  - home: db19-si-ee
    oracle_db_name: DB1
    oracle_db_unique_name: DB1_SITE1
    listener_name: LISTENER
    standby_config: DG1
    init_parameters:
      - {name: local_listener, value: '//dbhost1:1521', scope: both, state: present}
      - {name: dg_broker_config_file1, value: '/u01/app/oracle/dbs/dr1DB1_SITE1.dat', scope: both, state: present, dbca: false}
      - {name: dg_broker_config_file2, value: '/u01/app/oracle/dbs/dr2DB1_SITE1.dat', scope: both, state: present, dbca: false}
      - {name: dg_broker_start, value: 'TRUE', scope: both, state: present, dbca: false}
      - {name: standby_file_management, value: 'AUTO', scope: both, state: present}
    # ... other attributes of oracle_databases
inventory/host_vars/dbhost2/databases.yml
oracle_databases:
  - home: db19-si-ee
    oracle_db_name: DB1
    oracle_db_unique_name: DB1_SITE2
    listener_name: LISTENER
    standby_config: DG1
    init_parameters:
      - {name: local_listener, value: '//dbhost2:1521', scope: both, state: present}
      - {name: dg_broker_config_file1, value: '/u01/app/oracle/dbs/dr1DB1_SITE2.dat', scope: both, state: present, dbca: false}
      - {name: dg_broker_config_file2, value: '/u01/app/oracle/dbs/dr2DB1_SITE2.dat', scope: both, state: present, dbca: false}
      - {name: dg_broker_start, value: 'TRUE', scope: both, state: present, dbca: false}
      - {name: standby_file_management, value: 'AUTO', scope: both, state: present}
    # ... other attributes of oracle_databases

listener_name adds a static entry for the instance to listener.ora (see LISTENER.md). The static entry is needed for RMAN duplicate, because the auxiliary instance is in NOMOUNT.

12. Open Points and TODOs

12.1. Open Points

The following points are not decided yet:

Topic Description

oracle_db_unique_name in host_vars

oracle_databases must be placed in host_vars, because oracle_db_unique_name differs per member. Alternative: derive it in orasw_meta from the member. Then oracle_databases could be placed in group_vars, but all roles must use the derived value.

List vs. dictionary

db_standby_config is a list with name. oracle_listeners_config and oracle_tnsnames_config are dictionaries.

12.2. TODO

  • ❏ Standby redo logs with oradb_manage_redo
    The standby redo logs are created by oradb_standby on the primary database before DUPLICATE (number of online redo log groups + 1 per thread, size of the largest online redo log). They should be managed by oradb_manage_redo on all members (primary and standby), based on redolog_size and redolog_groups in oracle_databases. oradb_manage_redo skips a standby database at the moment.

  • ❏ RMAN backups with oradb_rman
    Backups depending on the current role of the database (e.g. backups on the standby database only), archivelog deletion policy APPLIED ON ALL STANDBY / SHIPPED TO ALL STANDBY, RMAN configuration (db_unique_name in the RMAN catalog).

  • ❏ Support for Oracle Restart
    srvctl add database -role PHYSICAL_STANDBY -startoption MOUNT for the standby database, SPFile and password file in ASM, no systemd units of oradb_manage_db. standby_state.yml and rman_duplicate_active support databases on filesystem without Oracle Restart only.

  • ❏ Management of database services
    Role based services with oradb_manage_services: services for the role PRIMARY or PHYSICAL_STANDBY (srvctl -role with Oracle Restart, a trigger or the broker for databases on filesystem), e.g. a service for the application on the primary database only.

  • ❏ Split brain protection in oradb_manage_db
    oracle_db must not be executed for a member, when another member is the PRIMARY (oradb_facts), see Role transitions outside of ansible-oracle.

  • ❏ Reinstate after a failover (case 1 in Role transitions outside of ansible-oracle), flashback: true in the molecule scenario.

  • ❏ Creation of a missing member independent of initial_role (case 2 in Role transitions outside of ansible-oracle).

  • ❏ Rebuild of a standby database on request (case 3 in Role transitions outside of ansible-oracle): oradb_standby_rebuild, playbooks/standby_rebuild.yml, molecule test: failover, rebuild, switchover back.

  • ❏ Changes of an existing broker configuration
    dgmgrl.cfg is executed only when no broker configuration exists. Changes of properties, protection mode or new members are not applied to an existing configuration.

  • ❏ Out-of-Place Patching
    switch_home.yml in oradb_manage_db starts the database with startup ⇒ opens a standby database read only. Datapatch must run on the primary database only.

  • ❏ RAC
    Members with more than 1 host (hosts) are allowed by the inventory structure, but not supported by oradb_standby.

2.13 - Breaking Changes - Upgrade Guide

This guide lists all changes in ansible-oracle which require an action in your inventory, playbooks or environment when upgrading to a new major version.

How to use this guide:

  1. Find your current version and the target version.

  2. Read the overview table of every major version in between.

  3. Check the column Affected if against your inventory. Only the rows that match need an action.

Note
The complete list of changes is in CHANGELOG.rst. This guide only covers the changes from the section Breaking Changes / Porting Guide and explains the required actions.

1. Version 5.0.0

1.1. Overview

Change Affected if Action

Minimum ansible-core 2.16

ansible-core 2.14 or 2.15 is used on the controller or in the execution environment

Upgrade to ansible-core 2.16 or newer

Supported operating systems on target hosts

ansible-core 2.17 or newer and target hosts with Oracle Linux / RHEL 8 (Python 3.6)

Use ansible-core 2.16 for these hosts

Collection dependencies community.general and community.crypto

community.general < 11.0.0 or >= 12.0.0, or community.crypto >= 3.0.0 is installed or pinned in your requirements.yml

Use community.general 11.x and community.crypto 2.x

Strict boolean conditionals with ansible-core 2.19

ansible-core 2.19 or newer is used and your own playbooks or roles use variables directly in conditionals

Use | bool in your conditionals. ansible-oracle itself accepts strings like "yes" or -e var=false

Templating changes with ansible-core 2.19

ansible-core 2.19 or newer is used and your inventory contains templates ({% if %}, {{ }}) which create values for ansible-oracle

Check the result types of your templates

Default of oracle_sw_copy and oracle_sw_unpack with install_from_nfs

install_from_nfs: true and oracle_sw_copy or oracle_sw_unpack are not set in inventory

Set oracle_sw_copy: true and oracle_sw_unpack: true to keep the old behavior or test the installation directly from NFS

Firewall enabled by default on RHEL/OL

Target hosts with RHEL/OL and firewalld is installed and disable_firewall is not set in inventory

Check the permanent firewalld config before the upgrade, or set disable_firewall: true and firewall_open_listener_ports: false to keep the old behavior

Supported versions in db_homes_config

db_homes_config contains an ORACLE_HOME with a version other than 19.3.0.0 or 26.1.0.0

Upgrade the databases to 19c or 26ai, then remove the old ORACLE_HOMEs from db_homes_config. Emergency switch: assert_db_homes_config: false

python-oracledb replaces cx_Oracle

Always: the modules require python-oracledb instead of cx_Oracle on the target hosts. Action needed if the target hosts have no access to the Python package index, a proxy is needed (use_proxy, http_proxy), install_cx_oracle / cx_oracle_source / cx_oracle3_source / cx_oracle_umask are set in inventory or the role cxoracle is used in own playbooks

Set the new variables pyoracledb_wheel_dir, pyoracledb_use_proxy and pyoracledb_http_proxy, replace the role cxoracle by pyoracledb

oracle_job, oracle_directory, oracle_grants and oracle_privs: names in double quotes are case sensitive

A name of a profile, user, role, object or directory is enclosed in " by mistake (profiles and grants, object_privs, directory_privs of users in oracle_databases / oracle_pdbs, or the modules in own playbooks), or an existing profile, user, role or object has a name in lower or mixed case

Remove the " from the name, or write the name exactly as stored in the data dictionary in "

oracle_db uses hostname for the database connection

The listener does not listen on oracle_hostname (default: ansible_fqdn), or own playbooks use oracle_db with hostname / host

Set oracle_hostname to an address of the listener, this is also the way to use another listener address

Quotas for users in oracle_user and oradb_manage_users

quotas is set for a user (new option, without quotas no quota is removed or changed), or own playbooks use quotas from the old module PR ('<tablespace>:<size>')

No action without quotas, the quotas of the user are not changed. With quotas: add the default tablespace to quotas, if the user needs a quota there, and use the format {tablespace: <name>, size: <size>}

Internal variables of oraasm_manage_diskgroups removed

Own playbooks or inventories use the internal variables _oraasm_manage_diskgroups_attr_name or _oraasm_manage_diskgroups_attr_value

No action for inventories with asm_diskgroups. Otherwise use attributes of asm_diskgroups

Autostart of databases with one systemd unit per database and listener

autostartup_service: true on a Single Instance without Grid Infrastructure / Oracle Restart with systemd

No action for the new solution, it replaces oracle-rdbms.service with the next run of oradb_manage_db. A crashed database is restarted after 2 minutes, set autostartup_service_restart: false to disable it. Set autostartup_service_mode: legacy before the upgrade to keep the solution of 4.x

Autostart of databases is enabled by default

Single Instance without Grid Infrastructure / Oracle Restart and autostartup_service is not set in the inventory

No action, if the databases should start with the server. Otherwise set autostartup_service: false

init_parameters for one instance: sid and dbca

An entry in init_parameters of oracle_databases has an attribute sid other than *and dbca: true

Remove dbca: true from the entry. The parameter is set by oradb_manage_parameters after the creation of the database

oradb_rman: control_file_record_keep_time in init_parameters

A database in oracle_databases has rman_jobs and control_file_record_keep_time is missing in init_parameters or smaller than the days of RECOVERY WINDOW OF <n> DAYS

Add control_file_record_keep_time to init_parameters. Emergency switch: oradb_rman_assert_control_file_record_keep_time: false

oradb_rman: logfiles of rman_backup.sh

A database in oracle_databases has rman_jobs and the RMAN logfiles are monitored, evaluated or rotated (e.g. checkmk logwatch, logrotate, own scripts), or oradb_rman_cron_logdir / rman_cron_logdir is set

Change the monitoring to the new logfile names in RMAN_LOGDIR, remove oradb_rman_cron_logdir / rman_cron_logdir and the old logfiles

listener_installed with Grid Infrastructure / Oracle Restart: listener in its home

Grid Infrastructure / Oracle Restart and an entry in listener_installed with home

Use use_gi_home: true for a listener, which must stay in the GI / Oracle Restart home. Check the ORACLE_HOME of the listener resources (srvctl config listener)

local_listener in init_parameters of Single Instance databases

A Single Instance database (also with Oracle Restart) in oracle_databases with state: present has no local_listener in init_parameters

Add local_listener with EZConnect to init_parameters, e.g. {name: local_listener, value: '//localhost:1521', scope: both, state: present}. Emergency switch: orasw_meta_assert_oracle_databases: false (disables all asserts of oracle_databases)

oracle_databases: is_container and omf are true by default

A 19c database in oracle_databases without is_container (non-CDB) or without omf (created without OMF)

Set is_container: false for a new non-CDB. OMF is strongly recommended, omf: false needs an own DBCA template without OMF (dbca_templatename) and is not tested

oracle_databases: db_create_file_dest and db_recovery_file_dest in init_parameters

A database in oracle_databases with state: present and without omf: false and db_create_file_dest or db_recovery_file_dest is missing in init_parameters

Add db_create_file_dest and db_recovery_file_dest to init_parameters

oracle_databases: datafile_dest and recoveryfile_dest are removed

A database in oracle_databases with datafile_dest or recoveryfile_dest

Move the values to db_create_file_dest and db_recovery_file_dest in init_parameters and remove datafile_dest and recoveryfile_dest

oracle_dbf_dir_asm and oracle_reco_dir_asm removed

A database in oracle_databases with storage_type: ASM and omf: false, or oracle_dbf_dir_asm / oracle_reco_dir_asm are set in the inventory

Use OMF with ASM (db_create_file_dest and db_recovery_file_dest in init_parameters), remove oracle_dbf_dir_asm and oracle_reco_dir_asm

oracle_databases: max_pdbs in init_parameters of Container Databases

A Container Database (is_container: true, default) in oracle_databases with state: present and max_pdbs is missing in init_parameters or greater than 3 (SE2) / 1024 (EE)

Add max_pdbs with the number of PDBs allowed by your license to init_parameters, e.g. {name: max_pdbs, value: '3', scope: both, state: present}. EE: more than 3 PDBs only with a license for the Multitenant Option

oracle_databases: control_management_pack_access in init_parameters of Enterprise Edition databases

A database of an Enterprise Edition home in oracle_databases with state: present and control_management_pack_access is missing in init_parameters or has a value other than NONE, DIAGNOSTIC or DIAGNOSTIC+TUNING, or a database of a Standard Edition 2 home with a value other than NONE

Add control_management_pack_access with the value allowed by your license to init_parameters, e.g. {name: control_management_pack_access, value: 'NONE', scope: both, state: present}

oracle_databases: sga_target and pga_aggregate_target in init_parameters

A database in oracle_databases with state: present and sga_target or pga_aggregate_target is missing in init_parameters, or oracle_db_mem_totalmb is set

Add sga_target and pga_aggregate_target to init_parameters, remove oracle_db_mem_totalmb

oracle_databases: no memory_target and memory_max_target with Hugepages

A database in oracle_databases with state: present and memory_target or memory_max_target in init_parameters and configure_hugepages is not false

Replace memory_target / memory_max_target by sga_target and pga_aggregate_target (state: absent for the old parameters), or set configure_hugepages: false

oracle_databases: processes in init_parameters

A database in oracle_databases with state: present and processes is missing in init_parameters

Add processes to init_parameters, e.g. {name: processes, value: '640', scope: spfile, state: present}. Usually irrelevant in practice, the default of processes is too small in most cases anyway

Role oraswahf_install replaced by ahf

Own playbooks use the role oraswahf_install

Use the new role ahf (playbook opitzconsulting.ansible_oracle.ahf)

Default of oracle_install_version_gi is 26ai

oracle_install_option_gi is HA_CONFIG or CRS_CONFIG and oracle_install_version_gi is not set in inventory

Set oracle_install_version_gi to the base release of the installation media, e.g. 19.3.0.0 for 19c. Usually irrelevant in practice, the version must match the installation media anyway

1.2. Minimum ansible-core 2.16

ansible-oracle 5.x supports ansible-core 2.16 - 2.19. ansible-oracle 4.x supports ansible-core 2.14 - 2.18, so ansible-core 2.19 requires ansible-oracle 5.x.

ansible-oracle ansible-core

4.x

2.14 - 2.18

5.x

2.16 - 2.19

The minimum version is defined by requires_ansible in meta/runtime.yml and min_ansible_version in meta/main.yml of all roles.

Check the version on the controller or in your execution environment:

ansible --version

1.2.1. Python on controller and target hosts

Each ansible-core version supports a fixed range of Python versions on the controller and on the target hosts:

ansible-core Python on controller Python on target host

2.16

3.10 - 3.12

2.7, 3.6 - 3.12

2.17

3.10 - 3.12

3.7 - 3.12

2.18

3.11 - 3.13

3.8 - 3.13

2.19

3.11 - 3.13

3.8 - 3.13

The Python on the target host is the system Python or the interpreter from ansible_python_interpreter.

1.2.2. Supported operating systems on target hosts

OS System Python ansible-core 2.16 ansible-core 2.17 - 2.19

Oracle Linux / RHEL 8

3.6

yes

no - see below

Oracle Linux / RHEL 9

3.9

yes

yes

Oracle Linux / RHEL 10

3.12

yes

yes

SLES / openSUSE Leap 15

3.6

yes

only with python311 (SLES 15 SP4 or newer) and ansible_python_interpreter: /usr/bin/python3.11 - not tested with ansible-oracle

Important
Use ansible-core 2.16 for Oracle Linux / RHEL 8.
The system Python 3.6 is not supported by ansible-core 2.17 or newer, even fact gathering fails. A newer Python from AppStream (e.g. python3.12 with ansible_python_interpreter: /usr/bin/python3.12) runs most modules, but ansible.builtin.dnf and ansible.builtin.yum fail, because the dnf Python bindings exist for Python 3.6 only: Could not import the dnf python module using /usr/bin/python3.12. The roles common, orahost, oraords and oraswgi_install install packages with these modules. Tested with ansible-core 2.19.14 and Oracle Linux 8.10.

The controller can use another OS than the target hosts. Oracle Linux 8 and 9 provide Python 3.11 and 3.12 as additional packages (python3.11, python3.12) for a controller with ansible-core 2.19.

1.3. Collection dependencies community.general and community.crypto

The dependencies in galaxy.yml are limited to versions, which support the minimum ansible-core version and Python 3.6 on the target hosts:

Collection 4.x 5.0.0

community.general

>=8.6.0

>=11.0.0,<12.0.0

community.crypto

>=2.21.1

>=2.21.1,<3.0.0 (3.x needs ansible-core >= 2.17)

ansible-galaxy collection install fails with a dependency conflict, when your requirements.yml pins a version outside of these ranges. Remove the pinning or adjust it to the ranges above.

1.4. Strict boolean conditionals with ansible-core 2.19

ansible-core 2.19 requires a real boolean as result of a conditional (when, failed_when, changed_when, until, assert: that). Older versions converted strings like "false" or "yes" silently. Now the task fails:

Conditional result (True) was derived from value of type 'str' at '...'. Conditionals must have a boolean result.

ansible-oracle 5.0.0 evaluates all boolean variables from the inventory with | bool. Strings like "true", "yes", "false" or extra-vars like -e oracle_sw_copy=false work as before.

Your own playbooks and roles are affected, when they use variables directly in conditionals:

# fails with ansible-core 2.19, when my_flag is a string ("true", "yes", -e my_flag=true)
when: my_flag

# works with all versions
when: my_flag | bool

The bool filter accepts true/false, yes/no, on/off, 1/0 (case-insensitive). Other values (e.g. "enabled" or an empty string) result in a deprecation warning and false. This will be an error in ansible-core 2.23.

Tip
ANSIBLE_ALLOW_BROKEN_CONDITIONALS=true restores the old behavior temporarily. Use it only to find the affected conditionals, not as permanent solution.

1.5. Templating changes with ansible-core 2.19

ansible-core 2.19 has a new templating engine. The result of a template has a different type in some cases. ansible-oracle 5.0.0 is adapted, but templates in your inventory are used as they are.

Template ansible-core < 2.19 ansible-core 2.19

"{% if x %}True{% else %}False{% endif %}"

bool

string "True" / "False"

"{% if x %}{'key': 1}{% endif %}", "{% if x %}[1, 2]{% endif %}"

dict / list

string

"{% if x %}-flag{% endif %}" with x false (empty result)

empty string ""

None

"{{ 1521 }}"

string "1521"

int 1521

Examples of failing expressions with ansible-core 2.19:

my_flag: "{% if foo %}True{% else %}False{% endif %}"
my_param: "{% if foo %}-flag{% endif %}"
my_port: "{{ 1521 }}"

# when: my_flag              -> fails: string instead of boolean
# when: my_param == ''       -> false, because the value is None
# "{{ my_param | length }}"  -> fails: None has no length
# "{{ 'host:' + my_port }}"  -> fails: string + int
# when: my_port == '1521'    -> false, because the value is an int

Recommendations:

  • Write expressions instead of text: my_flag: "{{ foo | bool }}" or my_flag: "{{ foo == 'x' }}".

  • Use YAML for lists and dictionaries instead of creating them as text.

  • Use | default('', true) when a template can be empty and a string is needed.

  • Use | int or | string for comparisons.

An empty template in environment: sets the environment variable to the text None, e.g. _JAVA_OPTIONS=None lets Java fail with Unrecognized option: None. Use "{{ my_value | default('', true) }}" for environment variables, which can be empty.

Embedding these values into other strings is not affected: "gridSetup.sh {{ my_param }}" renders an empty string for None in all versions.

1.6. Other ansible-core 2.19 changes for own playbooks and inventories

ansible-oracle 5.0.0 is checked for these changes. They are relevant for your own playbooks, inventories and ansible.cfg:

  • File modes must be quoted strings in inventories: mode: '0775' instead of mode: 775. An unquoted 775 is an integer and is passed through templates (for example mode: "{{ item.mode }}") as decimal 775, which is mode 1407. Before 2.19 the template converted the value to the string "775", which was interpreted as octal.

  • with_nested handles strings differently (not mentioned in the porting guide): an empty string "" is an empty list (the task is skipped completely), a templated string "{{ var }}" is split into single characters. Use lists: - [""] or - ["{{ var }}"].

  • A loop over an undefined list fails, although when is false, when delegate_to uses the loop variable (not mentioned in the porting guide). Use loop: "{{ my_list | default([]) }}".

  • Templates inside conditionals fail: that: swap >= {{ min_swap }} must be written as that: swap >= min_swap | int.

  • The ssh connection uses SSH_ASKPASS instead of sshpass for password authentication. Set password_mechanism = sshpass in section [ssh_connection] of ansible.cfg to keep the old behavior.

  • The bool filter warns for values other than true/false, yes/no, on/off, 1/0 (and None). This will be an error in ansible-core 2.23.

  • A timeout of become is an unreachable error. Use ignore_unreachable instead of ignore_errors.

  • The magic variable play_hosts is deprecated, use ansible_play_batch.

The complete list is in the ansible-core 2.19 Porting Guide.

1.7. Default of oracle_sw_copy and oracle_sw_unpack with install_from_nfs

The defaults of oracle_sw_copy and oracle_sw_unpack depend on install_from_nfs. Until 4.x the defaults were the strings "true" or "false". The string "false" is not empty and was evaluated as true in most conditionals. The documented behavior for install_from_nfs: true (no copy, no unpack) was therefore not active, unless both variables were set explicitly in the inventory.

As of 5.0.0 both defaults are real booleans.

install_from_nfs: true and …​ 4.x 5.0.0

oracle_sw_copy/oracle_sw_unpack not set

installation media are copied and unpacked to oracle_stage

installation media are used from oracle_stage_remote (NFS mount)

oracle_sw_copy/oracle_sw_unpack set as boolean

no change

no change

Affected variables with changed default value: oracle_sw_copy, oracle_sw_unpack, oracle_stage_install, oracle_patch_install.

Keep the behavior of 4.x:

install_from_nfs: true
oracle_sw_copy: true
oracle_sw_unpack: true

1.8. Firewall enabled by default on RHEL/OL

Until 4.x the role orahost stopped and disabled firewalld on RHEL/OL by default (disable_firewall: true). As of 5.0.0 firewalld stays active and the role opens the ports of the Oracle listeners:

Variable 4.x 5.0.0

disable_firewall

true

false

firewall_open_listener_ports

- (not available)

true (new)

The change applies only to RHEL/OL target hosts with installed firewalld. SUSE is not changed.

What orahost does with the new defaults:

  1. Checks, if the permanent firewalld config allows the SSH connection of Ansible (service ssh, port and target of the zone). The play fails, when starting firewalld would block SSH. Rich rules and zones bound to sources are not evaluated by this check.

  2. Starts and enables firewalld.

  3. Opens the following TCP ports in the permanent and the running config:

    • all ports from address in oracle_listeners_config with a host (IPC addresses are ignored, listener_port is used for addresses without port),

    • all ports from the new variable oracle_extra_firewall_ports,

    • oracle_scan_port with oracle_install_option_gi: CRS_CONFIG.

Other ports are not opened automatically, e.g. EM Express (5500), ORDS/APEX or the Enterprise Manager agent. Add them to oracle_extra_firewall_ports:

oracle_extra_firewall_ports:
  - 5500  # EM Express
Warning
Oracle RAC needs unrestricted network traffic on the private interconnect. Allow the interconnect in firewalld (for example with a trusted zone for the interconnect interfaces) or set disable_firewall: true on the cluster nodes.

Combinations of both variables:

disable_firewall firewall_open_listener_ports Result

false

true

Default in 5.0.0: firewalld is started and enabled, ports are opened immediately and permanently

true

false

Behavior of 4.x: firewalld is stopped and disabled

true

true

firewalld is stopped and disabled, ports are only added to the permanent config (prepared for a later start)

false

false

firewalld is not changed by orahost

Keep the behavior of 4.x:

disable_firewall: true
firewall_open_listener_ports: false

1.9. Supported versions in db_homes_config

The role orasw_meta checks db_homes_config. It is a dependency of nearly all roles, so the check runs in nearly every playbook. As of 5.0.0 only Oracle 19c and 26ai are accepted as version:

Version Allowed version in db_homes_config

4.x

26.1.0.0, 21.3.0.0, 19.3.0.0, 18.3.0.0, 12.2.0.1, 12.1.0.2, 11.2.0.4, 11.2.0.3

5.0.0

26.1.0.0, 19.3.0.0

version is the base release of the ORACLE_HOME. Release Updates are not part of it, e.g. an ORACLE_HOME with 19.32 uses version: 19.3.0.0.

An ORACLE_HOME with another version stops the playbook with a failed assert, even when the ORACLE_HOME is not used by the playbook. Upgrade the databases to 19c or 26ai, e.g. with the role autoupgrade, and remove the old ORACLE_HOMEs from db_homes_config afterwards.

The assert can be disabled in emergency cases:

assert_db_homes_config: false
Warning
assert_db_homes_config: false disables all checks of db_homes_config, not only the check of the version. Missing oracle_home, edition or opatch_minversion are no longer detected. ORACLE_HOMEs with other versions are not tested with ansible-oracle 5.x.

1.10. python-oracledb replaces cx_Oracle

python-oracledb (Python package oracledb) is the successor of cx_Oracle. All modules of ansible-oracle are migrated from cx_Oracle to python-oracledb. cx_Oracle is no longer used.

The new role pyoracledb installs python-oracledb with pip3 on the target hosts. The playbook os.yml executes pyoracledb instead of cxoracle.

Important
The role cxoracle and its variables are removed. Variables like install_cx_oracle or cx_oracle_source in the inventory have no effect anymore. Own playbooks using the role opitzconsulting.ansible_oracle.cxoracle fail, replace it by opitzconsulting.ansible_oracle.pyoracledb. cx_Oracle is not removed from existing target hosts.

The modules require python-oracledb on the target hosts instead of cx_Oracle. python-oracledb is used in thick mode, so the Oracle Client libraries must be found (ORACLE_HOME and LD_LIBRARY_PATH), like with cx_Oracle before.

Migrated modules:

  • oracle_asmdg

  • oracle_asmvol

  • oracle_awr

  • oracle_db

  • oracle_directory

  • oracle_facts

  • oracle_grants

  • oracle_job

  • oracle_jobclass

  • oracle_jobschedule

  • oracle_jobwindow

  • oracle_ldapuser

  • oracle_parameter

  • oracle_pdb

  • oracle_privs

  • oracle_profile

  • oracle_redo

  • oracle_role

  • oracle_rsrc_consgroup

  • oracle_services (python-oracledb is only used without Grid Infrastructure)

  • oracle_sql

  • oracle_stats_prefs

  • oracle_tablespace

  • oracle_user

The role pyoracledb installs a fixed version of python-oracledb, depending on the Python version of the target host (ansible_python_interpreter, needs gather_facts):

Python on the target host Variable Default

3.6 (Oracle Linux / RHEL 8, SLES 15)

pyoracledb_version_py36

1.4.2

3.7

pyoracledb_version_py37

2.3.0

3.8

pyoracledb_version_py38

3.0.0

3.9 (Oracle Linux / RHEL 9)

pyoracledb_version_py39

4.0.2

all other versions

pyoracledb_version

26.1.0 (updated by renovate)

Without changes in the inventory, pyoracledb installs this version from the Python package index (pip install oracledb==<version>). The installation fails, when the target hosts have no access to the package index.

The wheel files of python-oracledb need pip 19.3 or newer (manylinux2014). The system pip of Oracle Linux / RHEL 8 is 9.0.3, it would try to build python-oracledb from source, which fails. Therefore pyoracledb installs pip>=19.3 first, if pip is older (Python 3.6: pip 21.3.1 in /usr/local).

The role pyoracledb uses own variables with the prefix pyoracledb_. The variables of the removed role cxoracle are not used by pyoracledb, even use_proxy, http_proxy and extra_args:

cxoracle pyoracledb Description

install_cx_oracle

pyoracledb_install

Install the package? Default: true

cx_oracle_source, cx_oracle3_source

pyoracledb_wheel_dir (and pyoracledb_version*)

Directory with wheel files instead of a single package or file. Default: package index

cx_oracle_umask

pyoracledb_umask

umask for the pip installation

use_proxy

pyoracledb_use_proxy

Use a proxy for the pip installation. Default: false

http_proxy

pyoracledb_http_proxy

Proxy for the pip installation

extra_args

pyoracledb_extra_args

Additional arguments for pip, e.g. --index-url=…​ for an internal mirror. The default contains the proxy and the client certificates get_url_ssl_client_cert / get_url_ssl_client_key

cx_oracle_source / cx_oracle3_source pointed to one package or file. pyoracledb_wheel_dir points to a directory with wheel files of python-oracledb, pip selects the file matching the Python version (pip install --no-index --find-links <pyoracledb_wheel_dir> oracledb==<version>). One directory can contain the wheel files for all Python versions of the target hosts (e.g. cp36 and cp39):

  • local directory on the Ansible controller, copied to <oracle_stage>/pyoracledb when is_sw_source_local: true and oracle_sw_copy: true. With oracle_sw_copy: false the directory must exist on the target host (e.g. NFS).

  • URL (http://, https://) of a page with links to the wheel files, used directly by pip

use_proxy, http_proxy and extra_args can be kept in the inventory, if they are used for other purposes.

Example of the migration of the inventory:

# before (cxoracle)
cx_oracle_source: "file:///sw/cx_Oracle-8.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
use_proxy: true
http_proxy: proxy.example:3128

# after (pyoracledb)
pyoracledb_wheel_dir: /sw/python-oracledb
pyoracledb_use_proxy: true
pyoracledb_http_proxy: proxy.example:3128

Download the wheel files for the target hosts on a host with access to the package index, one command per Python version with the matching version from the table above:

pip download --no-deps --only-binary=:all: --python-version 3.6 \
  --platform manylinux2014_x86_64 -d /sw/python-oracledb oracledb==1.4.2
# pip for Python 3.6 (the system pip of OL8 is too old for the wheel files)
pip download --no-deps --only-binary=:all: --python-version 3.6 \
  -d /sw/python-oracledb pip==21.3.1
pip download --no-deps --only-binary=:all: --python-version 3.9 \
  --platform manylinux2014_x86_64 -d /sw/python-oracledb oracledb==4.0.2

Skip the installation of python-oracledb:

pyoracledb_install: false

1.11. oracle_profile, oracle_job, oracle_directory, oracle_grants and oracle_privs: names in double quotes are case sensitive

The modules oracle_profile, oracle_job, oracle_directory, oracle_grants and oracle_privs handle names like SQL (ANSI): a name in double quotes (") is case sensitive, a name without quotes is converted to uppercase. All other modules are not changed. The functions for this are in plugins/module_utils/oracle_identifier.py and can be used by more modules in the future. Such a change will be listed here.

Module Before Now

oracle_profile

The name was not quoted in the SQL statements, but compared case insensitive with DBA_PROFILES. A name in " was created case sensitive, but not found in the next run (ORA-02379).

A name in " is used case sensitive, e.g. name: '"Gestion/Monitorizacion"'. A name without " is used in uppercase and compared exactly with DBA_PROFILES.

oracle_job

A job_name with " failed with Invalid job name.

A part of job_name in " is case sensitive, e.g. job_name: 'SYSTEM."My_Job"'. convert_to_upper works as before for parts without ".

oracle_directory

The name was not quoted in the SQL statements and compared in uppercase with DBA_DIRECTORIES. A name in " was created case sensitive, but not found in the next run (ORA-00955).

A name in " is used case sensitive, e.g. directory_name: '"MyDir"'. "MyDir" and MYDIR are two different directories. A name without " is used in uppercase as before.

oracle_grants

The grantee (schema, role) was compared in uppercase, roles and objects in grants and object_privs were compared case insensitive, but not quoted in the SQL statements. A grantee or object in " was not found. Granting or revoking a privilege on an object with a lower or mixed case name failed (ORA-00942). With state: absent the names in grants had to be in lowercase. directory_privs needed sys.<directory>.

Grantee, roles in grants, owner and object in object_privs and the directory in directory_privs can be in " (case sensitive), e.g. schema: '"MyUser"', grants: ['"MyRole"'], object_privs: ['select:"MyOwner"."MyTable"']. Names without " are used in uppercase and compared exactly. state: absent compares in any case. An object without owner is in the current schema of the connection, sys. is optional for directories.

oracle_privs

Names with " failed with Invalid privilege, Invalid user/role or Invalid object. convert_to_upper was valid for all names in roles and objs. A role in privs was always converted to uppercase.

A name in " is case sensitive in roles, objs (owner and object, also with the wildcard %) and for a role in privs, e.g. roles: ['"MyUser"'], objs: ['"MyOwner".%'], privs: ['"MyRole"']. convert_to_upper works as before for names without ". No action needed, names without " are handled as before.

PDB names are not affected: Oracle stores them always in uppercase, oracle_pdb converts the name to uppercase as before.

For most inventories nothing changes, because names without " are stored in uppercase as before.

Important
Check names which are enclosed in " by mistake, e.g. from a copied SQL statement. They are case sensitive now and refer to a different object than before, so the module creates a new profile or directory with the exact name, or grants a privilege on a different object or role. The roles of ansible-oracle do not use oracle_directory, so only own playbooks are affected for directories.

An existing profile with a name in lower or mixed case (created outside of ansible-oracle) was found before with a name in any case. Now the name must be given exactly in ", otherwise the module creates a new profile in uppercase.

The same applies to oracle_grants: a grant on an existing object or role with a lower or mixed case name, which was found before with a name in any case, must be given exactly in ". Otherwise the module tries to grant the privilege on the uppercase name (ORA-00942 or ORA-01919) and, with grants_mode: enforce, revokes the existing grant.

Find objects and roles with a name in lower or mixed case
select owner, object_name, object_type from dba_objects where object_name <> upper(object_name) or owner <> upper(owner);
select role from dba_roles where role <> upper(role);
Find profiles with a name in lower or mixed case
select distinct profile from dba_profiles where profile <> upper(profile);
Profile with a mixed case name in the inventory
oracle_pdbs:
  - cdb: DB1
    pdb_name: ORCLPDB
    profiles:
      # before: MyProfile was found case insensitive
      # - name: MyProfile
      - name: '"MyProfile"'
        state: present
        attributes:
          - {name: password_life_time, value: unlimited}

1.12. oracle_db uses hostname for the database connection

This is a bugfix (#542), but it changes the address used for the database connection.

oracle_db ignored the option hostname (alias host) and always connected to the local host name (os.uname()[1]). This forced a listener on that address, which is not allowed in all environments. Now oracle_db connects to hostname, without hostname to os.uname()[1] as before.

The roles oradb_manage_db, oradb_manage_parameters and oradb_datapatch pass oracle_hostname as hostname, like all other oradb_manage_* roles already do. oracle_hostname defaults to ansible_fqdn, so all roles connect to ansible_fqdn unless oracle_hostname is set in inventory.

For most inventories nothing changes, because the other oradb_manage_* roles already need a listener on oracle_hostname.

Use another listener address
# default: ansible_fqdn
oracle_hostname: dbhost-lsnr.example.com
Note
oracle_hostname is also used as host name in the RDBMS installation and as node name for Grid Infrastructure.
Important
An explicit hostname: localhost for oracle_db in own playbooks was ignored before. Now the module connects to localhost, which works only, if the listener listens on this address. Remove hostname to keep the old behavior.

1.13. Quotas for users in oracle_user and oradb_manage_users

This is a new feature (#312), not a breaking change.

Note
Without quotas no quota is removed or changed, the existing quotas of a user are kept. quotas_mode has no effect without quotas. A user with default_tablespace gets QUOTA UNLIMITED on this tablespace as before.

Quotas are only removed, if the inventory says so: with size: 0 for a tablespace in quotas, or with quotas_mode: enforce for all tablespaces not in quotas.

oracle_user and the users of oracle_databases / oracle_pdbs (role oradb_manage_users) have two new options:

  • quotas: list of tablespace and size. size is the number of bytes with an optional unit K, M, G, T, P, E or unlimited. size: 0 removes the quota on the tablespace.

  • quotas_mode: append (default) changes only the tablespaces in quotas, enforce removes all other quotas of the user.

Important
With quotas, the default tablespace gets no automatic QUOTA UNLIMITED. Add the default tablespace to quotas, if the user needs a quota there. An existing quota on the default tablespace is kept with quotas_mode: append, but removed with quotas_mode: enforce, if the tablespace is not in quotas.

Oracle rounds a quota up to whole blocks of the tablespace, e.g. size: 1000 is stored as 8192 bytes with a block size of 8K. The comparison uses blocks, so the module is idempotent for such sizes.

User with quotas, all other quotas are removed
oracle_pdbs:
  - cdb: orcl
    pdb_name: ORCLPDB
    users:
      - schema: app
        state: present
        default_tablespace: app_data
        quotas_mode: enforce
        quotas:
          # without this entry, app has no quota on its default tablespace
          - tablespace: app_data
            size: unlimited
          - tablespace: app_index
            size: 500M
Note
The old pull request for quotas in ansible-oracle-modules (#158) used a list of strings '<tablespace>:<size>'. This format is not supported, use {tablespace: <name>, size: <size>}.

1.14. Internal variables of oraasm_manage_diskgroups removed

This is not a breaking change for inventories, the variables were internal (prefix _). It is listed here for own playbooks or roles which used them.

The role oraasm_manage_diskgroups built the attributes for oracle_asmdg in the variables _oraasm_manage_diskgroups_attr_name and _oraasm_manage_diskgroups_attr_value. For a disk group without attributes they contained the string None, which was passed to oracle_asmdg as attribute (#491). The variables are removed, the role passes attributes of asm_diskgroups directly to oracle_asmdg, a disk group without attributes gets no attributes.

Note
No action is needed for inventories with asm_diskgroups, attributes works as before.
Attributes of a disk group
asm_diskgroups:
  - diskgroup: data
    state: present
    attributes:
      - {name: compatible.asm, value: 19.0.0.0.0}
      - {name: compatible.rdbms, value: 19.0.0.0.0}
    disk:
      - {device: /dev/sdb, asmlabel: data01}

1.15. Autostart of databases with one systemd unit per database and listener

The autostart with autostartup_service: true (Single Instance without Grid Infrastructure / Oracle Restart) uses new systemd units (#265). The solution of 4.x is still available with autostartup_service_mode: legacy.

The service oracle-rdbms.service of 4.x had some problems:

  • systemd killed a database after 90 seconds, when shutdown immediate took longer (default timeout, KillMode=control-group).

  • A database without ~/.profile_<ORACLE_SID> was not shut down, but killed by systemd.

  • A database started outside of systemd (e.g. with sqlplus in a ssh session) was killed with the session during a shutdown of the server.

  • Remote file systems (e.g. NFS) could be unmounted before the database was stopped.

  • A failed start of a database was not reported, the service was active.

4.x (autostartup_service_mode: legacy) 5.x (autostartup_service_mode: units, default)

Units

oracle-rdbms.service for all databases in /etc/oratab, created by oraswdb_install

oracle-db@<ORACLE_SID>.service per database from oracle_databases and oracle-listener@<LISTENER_NAME>.service per listener from listener_installed (or listener_name of oracle_databases), grouped by oracle-databases.target and oracle-listeners.target, created by oradb_manage_db

Start/stop script

/usr/local/bin/manage_oracle_rdbms_procs.sh, listener from ~/.profile_<ORACLE_SID>

/usr/local/bin/oracle-systemd, environment in /etc/sysconfig/oracledb/db-<ORACLE_SID> and /etc/sysconfig/oracledb/listener-<LISTENER_NAME>

Timeouts

systemd default (90 seconds), then the database is killed

autostartup_service_start_timeout / autostartup_service_stop_timeout (default 15min), systemd never kills a database (KillMode=process)

Databases started outside of systemd

killed during a shutdown of the server

attached to their unit by oracle-adopt.timer (autostartup_service_adopt_interval, systemd API AttachProcessesToUnit) and at the start of the unit

Dependencies

autostartup_service_dependency (default network.target) in Requires= and After=

autostartup_service_dependency in Requires= and After= of all units, After=network-online.target remote-fs.target local-fs.target is always set

Start of a single database

not possible

systemctl start oracle-db@<ORACLE_SID>

Crash of a database

not detected, the service stays active

The unit monitors PMON. After a crash (no Instance shutdown complete / Instance shutdown (abort) complete in the alert log) systemd restarts the database after autostartup_service_restart_sec (default 2min), see Restart of a database after a crash. A shutdown in sqlplus is not restarted, the unit is inactive.

ORACLE_HOME of a database

from /etc/oratab

from /etc/oratab (start), from the running instance (stop)

The migration is done by the next run of oradb_manage_db (playbook manage_db.yml). The databases and listeners are not restarted: the new units are started and attach the running databases and listeners. oracle-rdbms.service is disabled. Its unit file is removed, when the service is inactive, otherwise in the first run after the next reboot. An active service without unit file would be stopped without its stop script during a shutdown.

1.15.1. Restart of a database after a crash

This is new behavior compared to 4.x: oracle-rdbms.service did not detect a crash, a crashed database stayed down until it was started manually.

The unit oracle-db@<ORACLE_SID>.service monitors PMON of the database every 10 seconds. When PMON is gone, the last entry in the alert log decides:

Last entry in the alert log Unit

Instance shutdown complete or Instance shutdown (abort) complete (shutdown in sqlplus, also shutdown abort)

inactive, no restart. The unit is started again by oracle-adopt.timer, when the database is started in sqlplus.

other entry, e.g. Instance terminated by …​ (crash)

autostartup_service_restart: true (default): restart after autostartup_service_restart_sec (default 2min), max. 10 starts of the unit within 1 hour. autostartup_service_restart: false: failed, no restart.

autostartup_service_restart can be set for all databases or per database in oracle_databases. A change is used by the next run of oradb_manage_db without a restart of the database.

Restart after a crash only for DB1
autostartup_service_restart: false

oracle_databases:
  - oracle_db_name: DB1
    autostartup_service_restart: true
    ...
Important
Check the restart, when a database must not start automatically after a crash, e.g. because a crash is analyzed before the restart or another tool restarts the database.
Important
Set autostartup_service_mode: legacy in the inventory before the upgrade to 5.x to keep the solution of 4.x. oraswdb_install creates oracle-rdbms.service as before and oradb_manage_db does not create the new units.
Keep the autostart of 4.x
autostartup_service: true
autostartup_service_mode: legacy

A switch from units back to legacy removes the new units in the next run of oradb_manage_db (the databases are not stopped). Active units are disabled and their unit files are removed in the first run after the next reboot. Run oraswdb_install (playbook swdb.yml) to create oracle-rdbms.service again.

Note
dbora for init (EL6) is not changed. Restart the databases with systemctl restart oracle-db@<ORACLE_SID> instead of sqlplus, then the database is always in its unit.

1.16. Autostart of databases is enabled by default

The default of autostartup_service is true since 5.0.0 (4.x: false). A Single Instance without Grid Infrastructure / Oracle Restart gets the autostart of the databases and listeners with the next run of oraswdb_install and oradb_manage_db, when autostartup_service is not set in the inventory. The solution is selected with autostartup_service_mode, see Autostart of databases with one systemd unit per database and listener.

autostartup_service is not used with Grid Infrastructure / Oracle Restart, the databases are started by the Clusterware.

The databases are written with the flag Y into /etc/oratab (as before with autostartup_service: true).

Keep the behavior of 4.x without autostart
autostartup_service: false

1.17. init_parameters for one instance: sid and dbca

init_parameters in oracle_databases and oracle_pdbs support the new attribute sid (#677). It is the SID clause of ALTER SYSTEM SET, e.g. for local_listener per RAC instance. Without sid or with sid: '*' the parameter is set for all instances as before.

dbca has no SID clause for initialization parameters. A parameter for one instance would be set for all instances during the creation of the database. Therefore sid other than * together with dbca: true is not allowed, the assert of oracle_databases in orasw_meta fails. Entries with sid and without dbca are not passed to dbca (default dbca: false for these entries), they are set by oradb_manage_parameters after the creation of the database.

Note
sid is case-sensitive like the SID clause of ALTER SYSTEM, use the instance name exactly as in V$INSTANCE.INSTANCE_NAME.
Not allowed
oracle_databases:
  - oracle_db_name: orcl
    init_parameters:
      - {name: local_listener, value: 'rac1-vip:1521', scope: both, state: present, sid: orcl1, dbca: true}
local_listener per instance
oracle_databases:
  - oracle_db_name: orcl
    init_parameters:
      - {name: local_listener, value: 'rac1-vip:1521', scope: both, state: present, sid: orcl1}
      - {name: local_listener, value: 'rac2-vip:1521', scope: both, state: present, sid: orcl2}

1.18. oradb_rman: control_file_record_keep_time in init_parameters

control_file_record_keep_time defines, how many days the controlfile keeps the records of backups. Without RMAN catalog, RMAN knows only the backups in the controlfile: a value smaller than the recovery window makes backups unusable for RMAN, although they exist.

As of 5.0.0 oradb_rman asserts for every database with rman_jobs:

  • control_file_record_keep_time is defined in init_parameters (state: present, sid: '*'), and

  • the value is >= <n> for the retention policy RECOVERY WINDOW OF <n> DAYS (rman_retention_policy of the database or oradb_rman_retention_policy_default).

The playbook stops with a failed assert, when the parameter is missing or too small.

Example for RECOVERY WINDOW OF 14 DAYS
oracle_databases:
  - oracle_db_name: DB1
    rman_retention_policy: 'RECOVERY WINDOW OF 14 DAYS'
    init_parameters:
      - {name: control_file_record_keep_time, value: '30', scope: both, state: present}
    rman_jobs:
      - {name: parameter}

The assert can be disabled in emergency cases:

oradb_rman_assert_control_file_record_keep_time: false

1.19. oradb_rman: logfiles of rman_backup.sh

The logging of rman_backup.sh and of the RMAN cron jobs was rebuilt. Before 5.0.0 the output was written into two growing files per job, which mixed the output of parallel executions and were only cleaned up by an external logrotate (e.g. orahost_logrotate).

Table 1. Logfiles before and as of 5.0.0
Before 5.0.0 As of 5.0.0

Cron output

<oradb_rman_cron_logdir>/rman_<oracle_db_name>_<job>.log (default /var/log/oracle/rman/log), appended

/dev/null: rman_backup.sh writes all output into its own logfile

Logfile of rman_backup.sh

<RMAN_LOGDIR>/<ORACLE_SID>_<action>.log, output of RMAN only, appended

<RMAN_LOGDIR>/<db_unique_name>_<action>_<YYYYmmdd>_<HHMMSS>_<pid>.log, one file per execution with the output of the script, sqlplus and RMAN

Last execution

-

Symlink <RMAN_LOGDIR>/<db_unique_name>_<action>.log to the logfile of the last execution

Cleanup

-

Logfiles older than oradb_rman_log_retention days (default 30, RMAN_LOG_RETENTION in rman_backup.cfg) are removed by rman_backup.sh

Parallel executions of the same action

executed, output mixed in one logfile

The 2nd execution stops with exit code 30 (lock file <RMAN_LOGDIR>/.<db_unique_name>_<action>.lock)

Changes in detail:

  • oradb_rman_cron_logdir and rman_cron_logdir are removed. The directory /var/log/oracle/rman/log is no longer created or written.

  • The prefix of the logfile is the db_unique_name instead of the ORACLE_SID. The name changes for every database with db_unique_name != ORACLE_SID, e.g. Data Guard or RAC.

  • The 1st execution renames an existing logfile <RMAN_LOGDIR>/<db_unique_name>_<action>.log of older versions to *.log.old and creates the symlink with this name.

  • Manual executions write the same logfiles as the cron jobs.

Who is affected:

  • Monitoring of the logfiles (e.g. checkmk logwatch, own scripts), which reads /var/log/oracle/rman/log/* or <RMAN_LOGDIR>/<ORACLE_SID>_<action>.log.

  • Monitoring of the exit code (e.g. mk-job): exit code 30 for a 2nd execution of a running action is new.

  • logrotate rules for the RMAN logfiles, e.g. the default of orahost_logrotate: rman_backup.sh removes old logfiles itself, logrotate must not rotate the logfiles with timestamp (logrotate refuses to rotate the symlink).

Required actions:

  1. Remove oradb_rman_cron_logdir and rman_cron_logdir from the inventory.

  2. Change the monitoring to the symlink <RMAN_LOGDIR>/<db_unique_name>_<action>.log or to the logfiles with timestamp.

  3. Remove logrotate rules for RMAN_LOGDIR and set oradb_rman_log_retention instead.

  4. Remove the old logfiles after the upgrade, when they are not needed anymore:

    rm -r /var/log/oracle/rman/log
    rm <RMAN_LOGDIR>/*.log.old

1.20. listener_installed with Grid Infrastructure / Oracle Restart: listener in its home

With Grid Infrastructure or Oracle Restart oradb_manage_db registers every listener of listener_installed with srvctl add/modify listener (module oracle_crs_listener). As of 5.0.0 the listener resource uses the ORACLE_HOME of the entry:

Table 2. Before and as of 5.0.0
Entry in listener_installed Before 5.0.0 As of 5.0.0

home: <db_homes_config key>

listener.ora in the ORACLE_HOME of home, but a new listener resource was added in the GI home (-oraclehome %CRS_HOME%)

listener.ora and the listener resource (srvctl …​ -oraclehome) in the ORACLE_HOME of home

use_gi_home: true

GI home from oracle_home_gi

GI home from crs_home in /etc/oracle/olr.loc (there is only one Grid Infrastructure / Oracle Restart per host)

Changes in detail:

  • A listener with home is registered with the ORACLE_HOME of home. An existing listener resource in the GI home is modified with srvctl modify listener -oraclehome <ORACLE_HOME of home>. A running listener is stopped before and started after the change, i.e. it runs from the new ORACLE_HOME.

  • A listener with use_gi_home: true stays in the GI / Oracle Restart home.

Who is affected:

  • Inventories with Grid Infrastructure / Oracle Restart and home in listener_installed, where the listener runs from the GI home, e.g. LISTENER with home of the database.

Required actions:

  1. Use use_gi_home: true without home for a listener, which must stay in the GI / Oracle Restart home.

  2. Check the ORACLE_HOME of the listener resources before the upgrade. oradb_manage_db restarts a moved listener, run it in a maintenance window:

    srvctl config listener -listener <listener_name>
Example
listener_installed:
  # listener in the GI / Oracle Restart home (crs_home from /etc/oracle/olr.loc)
  - listener_name: LISTENER
    use_gi_home: true
    state: present
  # additional listener in the ORACLE_HOME of the database, registered with srvctl in this home
  - listener_name: LISTENER2
    home: db19-gi-ee
    state: present

1.21. local_listener in init_parameters of Single Instance databases

As of 5.0.0 the assert of oracle_databases in orasw_meta requires local_listener in init_parameters for every Single Instance database (with and without Oracle Restart) with state: present. RAC and RAC One Node databases are not checked, Clusterware sets local_listener.

Why:

DBCA sets local_listener to an alias, e.g. LISTENER_<DB_NAME>, and writes the alias into tnsnames.ora of the ORACLE_HOME (with Read-Only Oracle Homes in $ORACLE_BASE/homes/<oracle_home_name>/network/admin). After a switch of the ORACLE_HOME (Out-of-Place Patching, see out_of_place_patching.adoc) the alias is missing in tnsnames.ora of the new ORACLE_HOME. The instance cannot resolve local_listener and does not register its services at the listener (ORA-12514 for clients). An EZConnect address in local_listener needs no entry in tnsnames.ora.

Who is affected:

  • Inventories with a Single Instance database in oracle_databases without local_listener in init_parameters. The playbooks fail in the assert of orasw_meta:

    local_listener is missing in init_parameters of <oracle_db_name>, ...

Required actions:

  1. Add local_listener with EZConnect (//<host>:<port>) to init_parameters of the database. localhost and the port of the listener avoid an extra entry in tnsnames.ora.

  2. Add one address per listener, if the instance must register at more than one listener, e.g. '(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1523)))'.

  3. Existing databases: oradb_manage_parameters changes local_listener with scope: both, the instance registers at the listener without restart. The entries of DBCA in tnsnames.ora are not removed by ansible-oracle.

Note
localhost requires a listener on the loopback address. A listener with the hostname in HOST listens on all addresses of the host, unless IP=FIRST is set in listener.ora. Use the hostname or the address of the listener otherwise, e.g. //{{ ansible_hostname }}:1521.
Example
oracle_databases:
  - oracle_db_name: DB1
    oracle_db_type: SI
    listener_port: 1521
    init_parameters:
      - {name: local_listener, value: '//localhost:1521', scope: both, state: present}

1.22. oracle_databases: is_container and omf are true by default

As of 5.0.0 the attributes is_container and omf of oracle_databases are true by default. They need not to be defined in oracle_databases anymore.

Why:

26ai supports only Container Databases and ansible-oracle uses Oracle Managed Files for tablespaces by default. The defaults simplify the inventory.

Who is affected:

  • Inventories with a 19c database in oracle_databases without is_container. Before 5.0.0 a non-CDB was created, now a CDB is created. The tasks for PDBs (oradb_manage_pdb), the timezone upgrade (oradb_tzupgrade) and the switch of the ORACLE_HOME treat the database as CDB.

  • Inventories with a database in oracle_databases without omf. Before 5.0.0 dbca was called with -useOMF false, now with -useOMF true. omf is used during the creation of a database with dbca only.

Required actions:

  1. Set is_container: false for a 19c non-CDB.

  2. Use OMF for new databases. OMF is strongly recommended in ansible-oracle.

  3. Without OMF: set omf: false and use an own DBCA template without OMF (dbca_templatename). The DBCA templates of ansible-oracle are made for OMF. Databases without OMF are not tested anymore.

Example
oracle_databases:
  - oracle_db_name: DB1
    home: db19-si-ee
    is_container: false   # non-CDB, 19c only
    # not recommended and not tested:
    # omf: false          # dbca -useOMF false
    # dbca_templatename: <own DBCA template without OMF>

1.23. oracle_databases: db_create_file_dest and db_recovery_file_dest in init_parameters

As of 5.0.0 the assert of oracle_databases in orasw_meta requires db_create_file_dest and db_recovery_file_dest in init_parameters for every database with state: present and omf: true (default).

Why:

The parameters are needed in different situations, e.g. for dbca, standby databases (RMAN duplicate) and the directories of a new database. They are defined directly in init_parameters instead of deriving them from other variables. dbca uses the values for the datafile and recovery area destination. The global defaults oracle_dbf_dir_fs and oracle_reco_dir_fs are only used with omf: false (only storage_type: FS, own DBCA template, not tested).

Who is affected:

  • Inventories with a database in oracle_databases without db_create_file_dest or db_recovery_file_dest in init_parameters. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: omf: true (default) needs db_create_file_dest and db_recovery_file_dest in init_parameters, ...

Required actions:

  1. Add db_create_file_dest and db_recovery_file_dest to init_parameters. Use the values of datafile_dest and recoveryfile_dest, if they were defined.

  2. Existing databases: use the current values of the database (show parameter db_create_file_dest, show parameter db_recovery_file_dest), otherwise oradb_manage_parameters changes them.

  3. Define db_recovery_file_dest_size before db_recovery_file_dest in init_parameters for existing databases without a recovery area (ORA-19802).

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: db_create_file_dest, value: '/u02/oradata', scope: both, state: present}
      - {name: db_recovery_file_dest_size, value: '10G', scope: both, state: present, dbca: false}
      - {name: db_recovery_file_dest, value: '/u02/fra', scope: both, state: present}

1.24. oracle_databases: datafile_dest and recoveryfile_dest are removed

As of 5.0.0 the attributes datafile_dest and recoveryfile_dest of oracle_databases are removed. They are redundant to db_create_file_dest and db_recovery_file_dest in init_parameters. datafile_dest in oracle_pdbs is not affected.

Who is affected:

  • Inventories with datafile_dest or recoveryfile_dest in oracle_databases. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: datafile_dest and recoveryfile_dest in oracle_databases are removed. ...

Required actions:

  1. Move the values to db_create_file_dest and db_recovery_file_dest in init_parameters.

  2. Remove datafile_dest and recoveryfile_dest from oracle_databases.

  3. Databases with omf: false: the destinations are oracle_dbf_dir_fs and oracle_reco_dir_fs (global per host).

Before
oracle_databases:
  - oracle_db_name: DB1
    is_container: true
    datafile_dest: /u02/oradata
    recoveryfile_dest: /u02/fra
    init_parameters:
      - {name: db_create_file_dest, value: '/u02/oradata', scope: both, state: present}
After
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: db_create_file_dest, value: '/u02/oradata', scope: both, state: present}
      - {name: db_recovery_file_dest, value: '/u02/fra', scope: both, state: present}

1.25. oracle_databases: omf false not allowed with ASM, oracle_dbf_dir_asm and oracle_reco_dir_asm removed

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database with storage_type: ASM and omf: false. ASM without OMF makes no sense in practice. The variables oracle_dbf_dir_asm and oracle_reco_dir_asm are removed, the disk groups are taken from db_create_file_dest and db_recovery_file_dest in init_parameters.

oradb_rman: the templates parameter_rac and parameter_fra_disk use db_create_file_dest from init_parameters for the snapshot controlfile instead of oracle_dbf_dir_asm. Before, parameter_fra_disk created a wrong name with two ` (`+DATA).

Who is affected:

  • Inventories with a database with storage_type: ASM and omf: false. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: omf: false is not allowed with storage_type: ASM. ...
  • Inventories with oracle_dbf_dir_asm or oracle_reco_dir_asm. The variables have no effect anymore.

Required actions:

  1. Remove omf: false from ASM databases and add db_create_file_dest and db_recovery_file_dest to init_parameters.

  2. Remove oracle_dbf_dir_asm and oracle_reco_dir_asm from the inventory.

Example
oracle_databases:
  - oracle_db_name: DB1
    storage_type: ASM
    init_parameters:
      - {name: db_create_file_dest, value: '+DATA', scope: both, state: present}
      - {name: db_recovery_file_dest_size, value: '10G', scope: both, state: present, dbca: false}
      - {name: db_recovery_file_dest, value: '+FRA', scope: both, state: present}

1.26. oracle_databases: max_pdbs in init_parameters of Container Databases

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a Container Database (is_container: true, default as of 5.0.0) with state: present without max_pdbs in init_parameters (without sid or sid: '*'). max_pdbs defines explicitly how many PDBs are allowed by the license. The value must be an integer:

Edition (db_homes_config) Maximum max_pdbs Remark

SE2 (SE)

3

EE

1024

More than 3 PDBs require a license for the Multitenant Option!

Important
Enterprise Edition without a license for the Multitenant Option allows only 3 PDBs, like Standard Edition 2. ansible-oracle has no switch for licensed options yet, so the assert allows up to 1024 PDBs for EE. Check your license before you set max_pdbs greater than 3.

Who is affected:

  • Inventories with a Container Database without max_pdbs in init_parameters, or with a value greater than 3 (SE2) or 1024 (EE). This includes 19c databases without is_container, which are Container Databases as of 5.0.0. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: is_container: true (default) needs max_pdbs in init_parameters with an integer value <= <limit> for edition <edition> ...

Required actions:

  1. Add max_pdbs with the number of PDBs allowed by your license to init_parameters. max_pdbs is set by dbca for a new database and changed by oradb_manage_parameters for an existing database.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: max_pdbs, value: '3', scope: both, state: present}

1.27. oracle_databases: control_management_pack_access in init_parameters of Enterprise Edition databases

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database of an Enterprise Edition home (edition: EE in db_homes_config) with state: present without control_management_pack_access in init_parameters (without sid or sid: '*'). control_management_pack_access defines explicitly which Management Packs are licensed. Without the parameter, the Oracle default for Enterprise Edition is DIAGNOSTIC+TUNING, which needs a license for the Diagnostics and Tuning Pack.

Value License

NONE

no Management Pack

DIAGNOSTIC

Diagnostics Pack

DIAGNOSTIC+TUNING

Diagnostics Pack and Tuning Pack

The parameter is optional for Standard Edition 2. If it is defined, the value must be NONE, the Management Packs are not available for Standard Edition 2.

Important
Set the value according to your license. The Management Packs are options of the Enterprise Edition. ansible-oracle has no switches for licensed options yet. Check if further settings are needed for your licensed options.

Who is affected:

  • Inventories with a database of an Enterprise Edition home without control_management_pack_access in init_parameters, or with another value than NONE, DIAGNOSTIC or DIAGNOSTIC+TUNING.

  • Inventories with a database of a Standard Edition 2 home with control_management_pack_access other than NONE. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: control_management_pack_access in init_parameters must be one of NONE, DIAGNOSTIC or DIAGNOSTIC+TUNING and is mandatory for Enterprise Edition ...

Required actions:

  1. Add control_management_pack_access with the value allowed by your license to init_parameters. For an existing database, oradb_manage_parameters changes the parameter to the value from the inventory.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: control_management_pack_access, value: 'NONE', scope: both, state: present}

1.28. oracle_databases: sga_target and pga_aggregate_target in init_parameters

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database with state: present without sga_target or pga_aggregate_target in init_parameters. These are the essential memory parameters of an Oracle database and must be defined explicitly. Entries with sid are accepted (instance specific values for RAC).

oracle_db_mem_totalmb (totalMemory in dbca) is not supported anymore, the assert fails if it is set. Before, the assert required either oracle_db_mem_totalmb or sga_target in init_parameters.

Who is affected:

  • Inventories with a database without sga_target or pga_aggregate_target in init_parameters, or with oracle_db_mem_totalmb. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: sga_target and pga_aggregate_target are essential memory parameters and must be defined in init_parameters ...

Required actions:

  1. Add sga_target and pga_aggregate_target to init_parameters.

  2. Remove oracle_db_mem_totalmb.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: sga_target, value: '2G', scope: spfile, state: present}
      - {name: pga_aggregate_target, value: '512M', scope: both, state: present}

1.29. oracle_databases: no memory_target and memory_max_target with Hugepages

As of 5.0.0 the assert of oracle_databases in orasw_meta fails for a database with state: present with memory_target or memory_max_target in init_parameters (also with sid) if Hugepages are configured (configure_hugepages: true, default of orahost). Automatic Memory Management (AMM) prevents the usage of Hugepages. Entries with state: absent are allowed to remove the parameters from the spfile.

Who is affected:

  • Inventories with a database with memory_target or memory_max_target in init_parameters and without configure_hugepages: false. The playbooks fail in the assert of orasw_meta:

    <oracle_db_name>: memory_target and memory_max_target are not allowed in init_parameters with Hugepages ...

Required actions:

  1. Use sga_target and pga_aggregate_target (Automatic Shared Memory Management) instead of AMM.

  2. Set state: absent for memory_target and memory_max_target to remove them from the spfile of existing databases, or set configure_hugepages: false if Hugepages are not used.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: memory_target, value: '0', scope: spfile, state: absent}
      - {name: memory_max_target, value: '0', scope: spfile, state: absent}
      - {name: sga_target, value: '2G', scope: spfile, state: present}
      - {name: pga_aggregate_target, value: '512M', scope: both, state: present}

1.30. Role oraswahf_install replaced by ahf

The role oraswahf_install was an empty placeholder for the installation of Oracle Autonomous Health Framework (AHF) - it had no tasks and no variables. It is removed and replaced by the new role ahf, which installs, upgrades and configures AHF. The central web interface AHF Fleet Insights is installed with the new role ahf_fleet_insights.

Note
AHF is not installed by oraswahf_install, existing installations are not affected. Only playbooks, which reference the role, fail with the role 'oraswahf_install' was not found.
Before: own playbook
- hosts: dbfs
  become: true
  roles:
    - opitzconsulting.ansible_oracle.oraswahf_install
After: own playbook or playbooks/ahf.yml
- hosts: dbfs
  become: true
  roles:
    - opitzconsulting.ansible_oracle.ahf

The variables and the decisions for an installation are described in Oracle Autonomous Health Framework (AHF).

1.31. oracle_databases: processes in init_parameters

As of 5.0.0 the assert of oracle_databases in orahost_meta fails for a database with state: present without processes in init_parameters, or with a value which is not an integer > 0. Entries with sid are accepted (instance specific values for RAC).

processes is needed to calculate kernel.sem in orahost_meta and by further asserts. Before, a database without processes failed with an undefined variable (oracle_databases_processes_max), or kernel.sem was calculated without the databases lacking processes.

Note
In practice the breaking change is usually irrelevant: the default of processes is too small in most cases anyway and should be set explicitly.

The assert is in orahost_meta, because orahost_meta runs before the asserts of orasw_meta and the role orahost uses only orahost_meta. It is disabled together with the other asserts of oracle_databases by orasw_meta_assert_oracle_databases: false.

Who is affected:

  • Inventories with a database without processes in init_parameters. The playbooks fail in the assert of orahost_meta:

    <oracle_db_name>: processes must be defined in init_parameters with an integer value > 0 ...

Required actions:

  1. Add processes to init_parameters. For an existing database, use the current value (show parameter processes) to avoid a change of the spfile and a restart.

Example
oracle_databases:
  - oracle_db_name: DB1
    init_parameters:
      - {name: processes, value: '640', scope: spfile, state: present}

1.32. Default of oracle_install_version_gi is 26ai

As of 5.0.0 the default of oracle_install_version_gi is 26.1.0.0 (26ai) instead of 19.3.0.0 (19c). New installations should use the current release, an older release as default makes no sense anymore.

Note
In practice the breaking change is usually irrelevant: oracle_install_version_gi must match the installation media of Grid Infrastructure (oracle_sw_image_gi, oracle_install_image_gi) and should be set in every inventory with Grid Infrastructure or Oracle Restart.

oracle_install_version_gi is only used with oracle_install_option_gi: HA_CONFIG or CRS_CONFIG. Inventories without Grid Infrastructure or Oracle Restart are not affected.

Who is affected:

  • Inventories with oracle_install_option_gi: HA_CONFIG or CRS_CONFIG without oracle_install_version_gi. The variable selects the response file, the task file and the installation media of oraswgi_install, and the key in gi_patches.

  • The default of oracle_home_gi contains the version: {{ oracle_base }}/{{ oracle_install_version_gi }}/grid (Oracle Restart) and /u01/app/{{ oracle_install_version_gi }}/grid (Grid Infrastructure). Without oracle_install_version_gi and without oracle_home_gi in inventory, oracle_home_gi changes from …​/19.3.0.0/grid to …​/26.1.0.0/grid.

    Warning
    For an installed Oracle Restart, a different oracle_home_gi starts the switch into a new home (Out-of-Place Patching, switch_home.yml of oraswgi_install). Set oracle_install_version_gi (and oracle_home_gi) before the first run with 5.0.0.

Required actions:

  1. Set oracle_install_version_gi to the base release of the installation media (19c: 19.3.0.0, 26ai: 26.1.0.0).

  2. Recommended: set oracle_home_gi as well, to be independent from the default.

Example: Oracle Restart 19c
oracle_install_option_gi: HA_CONFIG
oracle_install_version_gi: 19.3.0.0
oracle_home_gi: /u01/app/oracle/19.3.0.0/grid   # the former default

2. Adding new breaking changes

Every changelog fragment with a breaking_changes entry needs an entry in this guide:

  1. Add a row to the overview table of the next major version. Create the version section, if it does not exist.

  2. Describe the change in an own subsection: what changed, why, who is affected, before/after and the required action with an example.

  3. Reference this guide in the changelog fragment (see doc/guides/breaking_changes.adoc).

2.14 - Setup of Oracle Restart and Grid Infrastructure

1. Setup of Oracle Restart and Grid Infrastructure

This guide describes the setup of the software of Grid Infrastructure with ansible-oracle in 2 independent parts:

  • Oracle Restart: Grid Infrastructure for a Standalone Server, Single Instance databases with ASM on one host.

  • Grid Infrastructure (cluster): Grid Infrastructure for a Cluster, the prerequisite for RAC and RAC One Node.

Both parts are complete on their own. Some variables are described in both parts on purpose, because their meaning and their defaults differ between Oracle Restart and Grid Infrastructure. Read only the part you need.

Note
Terms (Oracle Restart, Grid Infrastructure, RAC): see Featurelist.
Not tested in this guide means: not covered by the molecule scenarios. Untested combinations should work, as long as they are not explicitly excluded and are supported by Oracle.
Both Oracle Restart and Grid Infrastructure use the software of Grid Infrastructure (oracle_home_gi). The variable oracle_install_option_gi decides what is configured.
Table 1. Oracle Restart and Grid Infrastructure at a glance
Oracle Restart Grid Infrastructure (cluster)

oracle_install_option_gi

HA_CONFIG

CRS_CONFIG

State in ansible-oracle

Oracle Restart 26ai is supported, tested with databases 19c and 26ai (molecule scenario has-ol9).

Grid Infrastructure 26ai is supported, tested with 2 nodes and a RAC database 26ai (molecule scenario rac).
Grid Infrastructure 19c, RAC databases 19c and RAC One Node are not tested.

Hosts

every host is configured on its own

all nodes of the cluster are configured together
(inventory group orasw_meta_cluster_hostgroup)

Default of oracle_home_gi

{{ oracle_base }}/{{ oracle_install_version_gi }}/grid

/u01/app/{{ oracle_install_version_gi }}/grid

Default of grid_base

oracle_base

/u01/app/grid/base

oracle_home_gi and grid_base

oracle_home_gi must be below grid_base

oracle_home_gi must not be below grid_base

Storage for ASM

local disks

shared disks, visible on all nodes

Network

no special requirements

public and private network, SCAN, VIP for each node

SSH user equivalence

not needed

configured by orahost_ssh for the grid user (and oracle_user)

1.1. Playbooks and roles

The same playbooks are used for Oracle Restart and Grid Infrastructure:

Order Playbook Content for Oracle Restart / Grid Infrastructure

1

opitzconsulting.ansible_oracle.os

orahost: users, groups, kernel parameters, packages, firewall.
orahost_storage: partitions and device persistence (asmlib, udev) of the ASM disks.
orahost_ssh: SSH user equivalence between the nodes (Grid Infrastructure only).

2

opitzconsulting.ansible_oracle.swgi

oraswgi_install: installation and configuration of Grid Infrastructure (gridSetup.sh, root.sh, ConfigTools).
oraswgi_manage_patches: patches for oracle_home_gi.
oraasm_manage_diskgroups: all ASM disk groups of asm_diskgroups except oracle_asm_init_dg.

3

opitzconsulting.ansible_oracle.swdb

Installation of the RDBMS software (db_homes_installed). The version of a database home must not be newer than Grid Infrastructure.

4

opitzconsulting.ansible_oracle.manage_db

Listener, databases and PDBs.

The playbooks use the variable hostgroup (default: all) as target hosts.

1.2. Common basics for both parts

1.2.1. Software of Grid Infrastructure

Variable Default Description

oracle_install_version_gi

26.1.0.0

Base release of the software, e.g. 26.1.0.0 or 19.3.0.0. It selects the response file template (grid-install.rsp.<version>.j2), the task file of oraswgi_install, the default installation media in oracle_sw_image_gi, the key in gi_patches and the default of oracle_home_gi. It is the base release, not the Release Update: a Golden Image with 19.33 is still 19.3.0.0, 23.26.3 is 26.1.0.0. Always set it in the inventory, it must match the installation media.

oracle_sw_image_gi

list of the base release images

List of installation media with filename and version. The entry with version: oracle_install_version_gi is unpacked into oracle_home_gi, when oracle_install_image_gi is not defined.
No need to change it: the default contains all supported releases.

oracle_install_image_gi

not defined

Filename of the installation media. When it is defined, it is used instead of the filename from oracle_sw_image_gi, e.g. for a Golden Image (gi_goldimage_26_03.zip).
Recommended: always install a Golden Image with the Release Update from Oracle and use a new oracle_home_gi for every Release Update (Out-of-Place Patching, see below).

oracle_sw_copy, is_sw_source_local, oracle_stage_remote

Source of the installation media (copied into oracle_stage or used directly from oracle_stage_remote). See Install and Patch Settings.

oracle_home_gi

derived, see below

ORACLE_HOME of Grid Infrastructure. The default depends on oracle_install_option_gi: oracle_home_gi_so for Oracle Restart, oracle_home_gi_cl for Grid Infrastructure. Set oracle_home_gi directly when the path should not contain the base release, e.g. for Golden Images with a Release Update.

Important
The default of oracle_install_version_gi is 26.1.0.0 (26ai) as of 5.0.0 (19c before). Set oracle_install_version_gi in every inventory with Oracle Restart or Grid Infrastructure, especially for existing 19c installations without oracle_home_gi in the inventory: the default of oracle_home_gi contains the version. See Breaking Changes (Default of oracle_install_version_gi is 26ai).

1.2.2. Passwords

Variable Default Description

default_gipass

''

Default password for SYS (SYSASM) and ASMSNMP of ASM. Mandatory, as long as sysasmpassword and asmmonitorpassword are not defined.

sysasmpassword

{{ default_gipass }}

Password of SYS in ASM (sysasmPassword in the response file).

asmmonitorpassword

{{ default_gipass }}

Password of ASMSNMP (asmsnmpPassword in the response file).

1.2.3. Patching during the installation

Variable Default Description

apply_patches_gi

true

Apply the patches from gi_patches to oracle_home_gi.

patch_before_rootsh

true

true: the Release Update (opatchauto patch with state: present) is applied by gridSetup.sh -applyRU before root.sh.
Only used together with apply_patches_gi: true.

gi_patches

{}

Patches for Grid Infrastructure per base release (opatchauto, opatch). See the example in role oraswgi_meta and Install and Patch Settings.

Tip
Recommended is a Golden Image with the Release Update from Oracle in oracle_install_image_gi instead of patching the base release. Then set apply_patches_gi: false and patch_before_rootsh: false. A new Release Update is installed as new Golden Image into a new oracle_home_gi (Out-of-Place Patching), not with opatchauto into the running home.

1.2.4. ASM disk groups

asm_diskgroups defines all disk groups, for Oracle Restart and for Grid Infrastructure.

Example asm_diskgroups
asm_diskgroups:
  - diskgroup: crs                   # oracle_asm_init_dg => created by gridSetup.sh
    state: present
    properties:
      - {redundancy: external, ausize: 4}
    attributes:
      - {name: compatible.rdbms, value: 19.0.0.0.0}
      - {name: compatible.asm, value: 23.0.0.0.0}
    disk:
      - {device: /dev/sdc, asmlabel: crs01}
  - diskgroup: data                  # created by oraasm_manage_diskgroups
    state: present
    properties:
      - {redundancy: external}
    attributes:
      - {name: compatible.rdbms, value: 19.0.0.0.0}
      - {name: compatible.asm, value: 23.0.0.0.0}
      - {name: au_size, value: 4M}
    disk:
      - {device: /dev/sdd, asmlabel: data01}
Table 2. Attributes of an entry in asm_diskgroups
Attribute Description

diskgroup

Name of the disk group (lower case in the inventory, ASM uses upper case).

state

present or absent.

properties

List with 1 dictionary: redundancy (external, normal, high) and ausize (in MB).
ausize in properties is used only for oracle_asm_init_dg (response file of gridSetup.sh). Use the attribute au_size for all other disk groups.

attributes

ASM attributes of the disk group (name, value), e.g. compatible.asm, compatible.rdbms, au_size.

disk

List of disks:

* device: device of the disk (e.g. /dev/sdc). * asmlabel: label of the disk for asmlib, udev and asmfd (see device_persistence). * failure_group (optional): name of the failure group. Disks with the same name are in the same failure group. Without failure_group, ASM creates a failure group for every disk. For oracle_asm_init_dg set failure_group for all disks or for none. * quorum (optional): true for a quorum failure group (voting files only). Must be the same for all disks of a failure group.

oracle_asm_init_dg (default: crs) is the 1st disk group. It must be an entry of asm_diskgroups. It is created during the configuration of Grid Infrastructure (gridSetup.sh, root.sh) and contains the SPFile of ASM, with Grid Infrastructure additionally the OCR and the voting files. All other disk groups are created later by oraasm_manage_diskgroups.

1.2.5. Device persistence of the ASM disks

device_persistence defines how the ASM disks are made persistent. It controls 3 things together with oracle_asm_disk_string:

  1. the preparation of the disks by orahost_storage or oraswgi_install,

  2. the path of each disk in the response file of gridSetup.sh (diskList of oracle_asm_init_dg),

  3. the ASM discovery string (asm_diskstring, diskString in the response file).

Table 3. device_persistence
Value Preparation Path of a disk Discovery string

'' (default)

nothing, the devices must already exist with owner _grid_install_user and group asmadmin_group.

device

oracle_asm_disk_string

asmlib

orahost_storage: oracleasm createdisk <asmlabel> <device><partition_suffix>

oracle_asm_disk_string without trailing * + asmlabel (upper case), e.g. ORCL:DATA01

oracle_asm_disk_string (default: ORCL:*)

udev

orahost_storage: udev rules with a symlink <oracle_asm_disk_string without leading /dev/><asmlabel> per disk

oracle_asm_disk_string + asmlabel ⇒ oracle_asm_disk_string must end with / (no *), e.g. /dev/oracle/

oracle_asm_disk_string

asmfd

oraswgi_install: installation and configuration of the ASM Filter Driver, asmcmd afd_label <asmlabel> <device>1

AFD:<ASMLABEL>

oracle_asmfd_disk_string (mandatory for asmfd)

Variable Default Description

oracle_asm_disk_string

ORCL:*

ASM discovery string (asm_diskstring). The default fits asmlib only. Set it for all other values of device_persistence, e.g. /dev/oracleasm/* for ''.

oracle_asmfd_disk_string

not defined

ASM discovery string with asmfd, e.g. AFD:*.

partition_devices

true

Create 1 partition on every disk of asm_diskgroups with parted (GPT). asmlib uses <device><partition_suffix>, asmfd uses <device>1. Set false when the disks must not be partitioned (e.g. device_persistence: '' with existing devices).

Warning
Only device_persistence: '' is tested by the molecule scenarios of ansible-oracle. asmlib, udev and asmfd are not tested with Oracle Linux 9 and 26ai.

2. Oracle Restart

Oracle Restart is Grid Infrastructure for a Standalone Server (oracle_install_option_gi: HA_CONFIG). It manages ASM, listeners and Single Instance databases on one host.

Oracle Restart 26ai is supported and tested with databases 19c and 26ai (molecule scenario has-ol9). Every host is configured on its own; there is no dependency between hosts.

2.1. Requirements

  • Oracle Linux / RHEL 8 or 9, see Featurelist.

  • Local disks for ASM (at least for oracle_asm_init_dg).

  • oracle_install_version_gi must be the same or newer than the version of all database homes.

2.2. Example inventory

host_vars/<host>/restart.yml
oracle_install_option_gi: HA_CONFIG
oracle_install_version_gi: 26.1.0.0
oracle_install_image_gi: gi_goldimage_26_03.zip   # Golden Image with RU 23.26.3
oracle_home_gi: /u01/app/oracle/product/26/restart_26.03

apply_patches_gi: false        # the Golden Image contains the Release Update
patch_before_rootsh: false

role_separation: false         # GI software owned by oracle_user
default_gipass: "{{ vault_default_gipass }}"

device_persistence: ''
partition_devices: false
oracle_asm_disk_string: /dev/oracleasm/*
oracle_asm_init_dg: data

asm_diskgroups:
  - diskgroup: data
    state: present
    properties:
      - {redundancy: external, ausize: 4}
    attributes:
      - {name: compatible.rdbms, value: 19.0.0.0.0}
      - {name: compatible.asm, value: 23.0.0.0.0}
    disk:
      - {device: /dev/oracleasm/data01, asmlabel: data01}
  - diskgroup: fra
    state: present
    properties:
      - {redundancy: external}
    attributes:
      - {name: compatible.rdbms, value: 19.0.0.0.0}
      - {name: compatible.asm, value: 23.0.0.0.0}
      - {name: au_size, value: 4M}
    disk:
      - {device: /dev/oracleasm/fra01, asmlabel: fra01}

2.3. Installation type

Variable Value Description

oracle_install_option_gi

HA_CONFIG

Configure Oracle Restart. An empty string (default) means: no Grid Infrastructure software on the host, databases use file systems.

With HA_CONFIG:

  • orasw_meta_primary_node is always true: every host runs all steps itself.

  • orasw_meta_cluster_hostgroup, oracle_scan, oracle_vip and all network variables of Grid Infrastructure are not used.

2.4. ORACLE_HOME and ORACLE_BASE

Variable Default for Oracle Restart Description

oracle_base

/u01/app/oracle

ORACLE_BASE of the databases.

grid_base

{{ oracle_base }}

ORACLE_BASE of Oracle Restart. For Oracle Restart it is the same as oracle_base by default.

oracle_home_gi_so

{{ oracle_base }}/{{ oracle_install_version_gi }}/grid

Default for oracle_home_gi with Oracle Restart (so = stand alone).

oracle_home_gi

{{ oracle_home_gi_so }}

ORACLE_HOME of Oracle Restart. It must be below grid_base. Recommended: an own path per Release Update, e.g. /u01/app/oracle/product/26/restart_26.03. That is the prerequisite for the switch into a new home, see below.

oracle_inventory_loc

/u01/app/oraInventory

Central inventory.

Important
Oracle Restart: oracle_home_gi must be a subdirectory of grid_base, e.g. grid_base: /u01/app/oracle and oracle_home_gi: /u01/app/oracle/product/26/restart_26.03.
This is the opposite of Grid Infrastructure (cluster), where oracle_home_gi must not be below grid_base. Keep this in mind, when an inventory is changed from Oracle Restart to Grid Infrastructure or vice versa.

2.5. Users and groups

Variable Default Description

role_separation

false

false: Oracle Restart is installed and owned by oracle_user.
true: Oracle Restart is installed and owned by grid_user.

oracle_user

oracle

Owner of the database software.

grid_user

grid

Owner of Oracle Restart with role_separation: true.

asmadmin_group, asmdba_group, asmoper_group

asmadmin, asmdba, asmoper

OS groups OSASM, OSDBA and OSOPER for ASM (OSASM, OSDBA, OSOPER in the response file). The ASM disks must be owned by the install user and asmadmin_group.

The install user of Oracle Restart is derived from both variables: _grid_install_user is grid_user with role_separation: true, otherwise oracle_user. It is the owner of oracle_home_gi, of grid_base and of the ASM disks.

2.6. Installation steps

oraswgi_install executes the following steps. Steps 5 to 8 are only executed when /etc/oracle/olr.loc does not exist (Oracle Restart is not configured yet).

  1. Unpack the installation media into oracle_home_gi, when the home is not registered in the central inventory.

  2. Install cvuqdisk (only with device_persistence: asmfd).

  3. Create the response file <oracle_rsp_stage>/grid-<oracle_cluster_name>.rsp.

  4. Run cluvfy (skipped with gi_ignoreprereq: true).

  5. With device_persistence: asmfd: configure the ASM Filter Driver and label the disks.

  6. gridSetup.sh -silent -responseFile …​ (with -applyRU, when apply_patches_gi and patch_before_rootsh are true).

  7. orainstRoot.sh and root.sh. root.sh configures Oracle Restart and creates oracle_asm_init_dg.

  8. gridSetup.sh -executeConfigTools (run_configtoolallcommand: true): listener LISTENER in oracle_home_gi, ASM post configuration, CVU.

  9. CRS flag (CRS=TRUE) of oracle_home_gi in the central inventory.

  10. Patches (oraswgi_manage_patches) and all other disk groups (oraasm_manage_diskgroups).

2.7. Prerequisite checks and ConfigTools

Variable Default Description

gi_ignoreprereq

false

true: cluvfy is not executed and gridSetup.sh is started with -ignorePrereq. Failures of the Cluster Verification Utility (CVU) in -executeConfigTools are ignored as well. Failures of all other configuration assistants (NETCA, ASMCA) still stop the installation. runInstaller -updateNodeList is started with -ignoreSysPrereqs (e.g. for missing swap space).

run_configtoolallcommand

true

Run gridSetup.sh -executeConfigTools after root.sh.

2.8. Listener and databases with Oracle Restart

Databases on Oracle Restart are created by oradb_manage_db (playbook manage_db) with storage_type: ASM.

  • The listener in oracle_home_gi is defined in listener_installed with use_gi_home: true (no home). The ORACLE_HOME of Oracle Restart is read from /etc/oracle/olr.loc.

  • A listener in a database home is defined with home and is registered in Oracle Restart with srvctl.

  • The ORACLE_HOME of a database must not be newer than oracle_home_gi.

  • db_create_file_dest and db_recovery_file_dest in init_parameters point to the disk groups (e.g. +DATA, +FRA).

listener_installed:
  - listener_name: LISTENER
    use_gi_home: true
    state: present

oracle_databases:
  - home: db19-gi-ee
    oracle_db_name: DBHAS
    oracle_db_type: SI
    storage_type: ASM
    init_parameters:
      - {name: db_create_file_dest, value: '+DATA', scope: both, state: present}
      - {name: db_recovery_file_dest, value: '+FRA', scope: both, state: present}
      ...

2.9. Out-of-Place Patching of Oracle Restart

With 26ai the home of Oracle Restart can be switched into a new oracle_home_gi (new Release Update), see Out-of-Place Patching. This is the recommended way for Release Updates: install the Golden Image of the new Release Update with oracle_install_image_gi into a new oracle_home_gi (e.g. /u01/app/oracle/product/26/restart_26.04), the switch is done by oraswgi_install. Obsolete homes can be removed with oraswgi_install_remove_obsolete_homes: true.

3. Grid Infrastructure (cluster)

Grid Infrastructure for a Cluster (oracle_install_option_gi: CRS_CONFIG) is the prerequisite for RAC and RAC One Node.

Important
Grid Infrastructure 26ai is supported: tested with 2 nodes on Oracle Linux 9 and a RAC database 26ai (molecule scenario rac, see Test environment: molecule scenario rac).
Grid Infrastructure 19c, RAC databases 19c and RAC One Node are not tested.

All nodes of a cluster are configured together in one play. Most steps run on the 1st node only; gridSetup.sh copies the software to the other nodes with SSH.

3.1. Requirements

  • All nodes in one inventory group (orasw_meta_cluster_hostgroup), all nodes in the same play.

  • Shared disks for ASM, visible with the same path and the same owner on all nodes.

  • 2 networks with the same interface names on all nodes:

    • public network: IP of the node, VIP of every node, SCAN,

    • private network: interconnect (and ASM network with Flex ASM).

  • Name resolution of the nodes, the VIPs and the SCAN on all nodes (DNS or /etc/hosts). The hostname of a node must resolve to its public IP only.

  • sshd on all nodes and SSH logins allowed for the grid user (and oracle_user).

  • Time synchronization (chrony). Without it, the Cluster Time Synchronization Service (CTSS) runs in active mode.

3.2. Inventory structure

The cluster is defined by an inventory group. orasw_meta_cluster_hostgroup contains the name of this group. The order of the hosts in the group is important: the 1st host is the primary node.

hosts.yml
all:
  children:
    rac:                  # orasw_meta_cluster_hostgroup
      hosts:
        rac-1:            # primary node: gridSetup.sh, 1st root.sh
        rac-2:
group_vars/rac/gi.yml
oracle_install_option_gi: CRS_CONFIG
oracle_install_version_gi: 26.1.0.0
oracle_install_image_gi: gi_goldimage_26_03.zip
oracle_home_gi: /u01/app/gridinfra/26.03

orasw_meta_cluster_hostgroup: rac
oracle_cluster_name: cluster-rac
oracle_gi_cluster_type: STANDARD

oracle_scan: rac-scan.example.com
oracle_scan_port: 1521
oracle_gi_nic_pub: eth0
oracle_gi_nic_priv: eth1

role_separation: true          # grid user for GI, oracle user for the databases
default_gipass: "{{ vault_default_gipass }}"

apply_patches_gi: false
patch_before_rootsh: false

device_persistence: udev      # not tested, see 'Device persistence of the ASM disks'
partition_devices: true
oracle_asm_disk_string: /dev/oracle/
oracle_asm_init_dg: crs

asm_diskgroups:
  - diskgroup: crs
    state: present
    properties:
      - {redundancy: normal, ausize: 4}
    attributes:
      - {name: compatible.rdbms, value: 19.0.0.0.0}
      - {name: compatible.asm, value: 23.0.0.0.0}
    disk:
      - {device: /dev/sdc, asmlabel: crs01, failure_group: fg1}
      - {device: /dev/sdd, asmlabel: crs02, failure_group: fg2}
      - {device: /dev/sde, asmlabel: crs03, failure_group: fg3}
  - diskgroup: data
    state: present
    properties:
      - {redundancy: external}
    attributes:
      - {name: compatible.rdbms, value: 19.0.0.0.0}
      - {name: compatible.asm, value: 23.0.0.0.0}
      - {name: au_size, value: 4M}
    disk:
      - {device: /dev/sdf, asmlabel: data01}
host_vars/rac-1/gi.yml (rac-2 accordingly)
oracle_node_vip: rac-1-vip.example.com

3.3. Installation type and cluster

Variable Default Description

oracle_install_option_gi

''

CRS_CONFIG: configure Grid Infrastructure for a Cluster.

orasw_meta_cluster_hostgroup

''

Name of the inventory group with all nodes of the cluster. Mandatory for CRS_CONFIG; the group must exist in the inventory (assert in orahost_meta).

orasw_meta_primary_node

derived

true for the 1st host of groups[orasw_meta_cluster_hostgroup], false for all other nodes. Do not set it in the inventory.

oracle_cluster_name

{{ orasw_meta_cluster_hostgroup }}

Name of the cluster (clusterName in the response file). Oracle allows at most 15 characters: letters, digits and -, starting with a letter. Set it explicitly when the group name contains _ or is too long. It is also part of the name of the response file (grid-<oracle_cluster_name>.rsp).

oracle_gi_cluster_type

STANDARD

Type of the cluster: STANDARD or STANDALONE (assert in oraswgi_install). Only STANDARD is tested.

oracle_asm_storage_option

FLEX_ASM_STORAGE (12.2+)

Storage option of ASM in the response file. It changes the usage of the private interface in networkInterfaceList, see Networks.

3.3.1. Primary node and the other nodes

orasw_meta_primary_node decides which node executes a step:

Step Primary node Other nodes

Users, groups, kernel parameters, packages (orahost)

x

x

Partitions of the ASM disks (partition_devices), asmlib createdisk

x

udev rules (device_persistence: udev)

x

x

SSH user equivalence (orahost_ssh)

x

x

Unpack the installation media into oracle_home_gi

x

Install cvuqdisk (copied from the primary node via the Ansible controller)

x

x

Response file, cluvfy, gridSetup.sh (copies the home to all nodes)

x

orainstRoot.sh

x

x

root.sh: 1st on the primary node, then on the other nodes one after the other (throttle: 1)

x

x

gridSetup.sh -executeConfigTools

x

CRS flag of oracle_home_gi in the central inventory (runInstaller -updateNodeList -local)

x

x

Disk groups (oraasm_manage_diskgroups)

x

Important
Run the playbooks always for all nodes of the cluster. Many steps on the other nodes use facts or results of the primary node (hostvars).

3.4. ORACLE_HOME and ORACLE_BASE

Variable Default for Grid Infrastructure Description

oracle_home_gi_cl

/u01/app/{{ oracle_install_version_gi }}/grid

Default for oracle_home_gi with Grid Infrastructure (cl = cluster).

oracle_home_gi

{{ oracle_home_gi_cl }}

ORACLE_HOME of Grid Infrastructure. Same path on all nodes. It must not be below grid_base (and not below oracle_base): root.sh changes the owner of the home and its parent directories to root.

grid_base

/u01/app/grid/base

ORACLE_BASE of Grid Infrastructure. It must differ from oracle_base with role_separation: true (assert in orasw_meta).

oracle_base

/u01/app/oracle

ORACLE_BASE of the databases.

Important
Grid Infrastructure (cluster): oracle_home_gi must not be a subdirectory of grid_base, e.g. grid_base: /u01/app/grid/base and oracle_home_gi: /u01/app/gridinfra/26.03.
This is the opposite of Oracle Restart, where oracle_home_gi must be below grid_base. The default oracle_home_gi_cl (/u01/app/<version>/grid) is outside of the default grid_base.

3.5. Users and groups

The variables are the same as for Oracle Restart (role_separation, grid_user, oracle_user, asmadmin_group, …​). For Grid Infrastructure role_separation: true is recommended (and tested):

  • grid_user owns oracle_home_gi, grid_base and the ASM disks,

  • oracle_user owns the database homes.

The install user _grid_install_user is grid_user with role_separation: true, otherwise oracle_user.

3.6. Networks

3.6.1. Public and private network

Variable Default Description

oracle_gi_nic_pub

eth0

Interface of the public network.

oracle_gi_nic_priv

eth1

Interface of the private network (interconnect).

Both interfaces must exist with an IPv4 address on all nodes and have the same name on all nodes. The response file is created on the primary node from its facts (ansible_<interface>.ipv4.network):

networkInterfaceList=<oracle_gi_nic_pub>:<public network>:1,<oracle_gi_nic_priv>:<private network>:5

The interface type of the private network depends on oracle_asm_storage_option:

  • FLEX_ASM_STORAGE (default for 12.2+): 5 = interconnect and ASM network,

  • LOCAL_ASM_STORAGE: 2 = interconnect only.

Grid Infrastructure uses Highly Available IP addresses (HAIP, 169.254.x.x) on the private interface. The private network must allow these addresses between the nodes (no filter on the subnet of the private network).

Note
configure_interconnect and oracle_ic_net of orahost write ifcfg files of the network scripts. They are not usable with Oracle Linux 9. Configure the private network outside of ansible-oracle.

3.6.2. SCAN

Variable Default Description

oracle_scan

not defined

Name of the Single Client Access Name (scanName). Mandatory for CRS_CONFIG (assert in oraswgi_install). scanType is always LOCAL_SCAN.

oracle_scan_port

1521

Port of the SCAN listener. orahost opens it in firewalld together with the listener ports (firewall_open_listener_ports, default true).

The SCAN should resolve to 3 IPs in DNS. A SCAN with 1 IP in /etc/hosts works, but the Cluster Verification Utility reports PRVG-1101 (see Prerequisite checks and ConfigTools for the cluster).

3.6.3. VIPs of the nodes

The response file contains every node of orasw_meta_cluster_hostgroup with its VIP:

clusterNodes=<ansible_fqdn of node 1>:<VIP of node 1>,<ansible_fqdn of node 2>:<VIP of node 2>
Variable Default Description

oracle_node_vip (host variable)

not defined

Name of the VIP of this node, e.g. rac-1-vip.example.com. Recommended: set it in host_vars for every node.

oracle_vip

-vip

Suffix for the VIP, when oracle_node_vip is not defined: <ansible_hostname><oracle_vip>[.<ansible_domain>], e.g. rac-1-vip.example.com.

3.6.4. Name resolution

Without DNS, orahost can write the entries into /etc/hosts:

Variable Default Description

configure_etc_hosts

false

true: add <etc_hosts_ip> <ansible_hostname> <ansible_fqdn> of the node and all etc_hosts_entries to /etc/hosts.

etc_hosts_ip

ansible_default_ipv4.address

IP of the node in /etc/hosts. Must be the public IP.

etc_hosts_entries

[]

Additional entries, e.g. other nodes, VIPs and the SCAN (fqdn, ip, aliases).

configure_etc_hosts: true
etc_hosts_entries:
  - {fqdn: rac-1.example.com, ip: 192.168.56.11}
  - {fqdn: rac-2.example.com, ip: 192.168.56.12}
  - {fqdn: rac-1-vip.example.com, ip: 192.168.56.21}
  - {fqdn: rac-2-vip.example.com, ip: 192.168.56.22}
  - {fqdn: rac-scan.example.com, ip: 192.168.56.30}
Important
The hostname must resolve to exactly 1 IP (the public IP) on all nodes. A 2nd entry with the private IP stops gridSetup.sh with PRVH-1541 / PRVG-13632.

The Grid Naming Service (GNS) is not supported: configureGNS is always false in the response file.

3.7. SSH user equivalence

gridSetup.sh copies oracle_home_gi from the primary node to the other nodes with SSH. orahost_ssh (playbook os) configures the user equivalence automatically for CRS_CONFIG for oracle_user and, with role_separation: true, for grid_user:

  • creates a key pair per user and node (orahost_ssh_key_type, default rsa, orahost_ssh_key_size, default 4096),

  • adds the public keys of all nodes into authorized_keys on all nodes,

  • adds the host keys (ssh-keyscan -t <orahost_ssh_hostkeytypes> for ansible_hostname) into known_hosts on all nodes.

configure_ssh is not needed for Grid Infrastructure.

sshd must run on all nodes and allow logins of these users. Typical failures: /run/nologin exists, AllowUsers in sshd_config. gridSetup.sh stops with PRVF-4098 : User equivalence not found for node.

3.8. Shared storage for ASM

The ASM disks must be shared between all nodes:

  • Every device of asm_diskgroups must exist on every node with the same path. With device_persistence: '' the owner (_grid_install_user) and the group (asmadmin_group) must be set before gridSetup.sh.

  • Partitions (partition_devices) and asmlib labels are created on the primary node only.

  • oracle_asm_init_dg contains the OCR and the voting files. The number of voting files depends on the redundancy: external 1, normal 3, high 5 disks (failure groups). With normal and 2 storage systems use a quorum failure group (quorum: true) for the 3rd voting file.

3.9. Prerequisite checks and ConfigTools for the cluster

Variable Default Description

gi_ignoreprereq

false

true: no cluvfy before the installation, gridSetup.sh -ignorePrereq, failures of the post check with CVU in -executeConfigTools are ignored (e.g. PRVG-1101 for a SCAN without DNS), runInstaller -updateNodeList -ignoreSysPrereqs. Failures of NETCA or ASMCA still stop the installation.

run_configtoolallcommand

true

Run gridSetup.sh -executeConfigTools on the primary node after root.sh on all nodes.

Tip
Start with gi_ignoreprereq: false. Use true only for known and accepted failures of cluvfy, e.g. in test environments.

3.10. RAC databases

A RAC database needs 2 things on top of Grid Infrastructure: an ORACLE_HOME on all nodes (playbook swdb) and the database itself (playbook manage_db).

3.10.1. ORACLE_HOME of a RAC database

The database home is defined in db_homes_config and installed with db_homes_installed, as for Single Instance databases. oraswdb_install decides from oracle_databases how the home is installed: when a database with oracle_db_type: RAC or RACONENODE uses the home, it is installed as cluster home.

Step Primary node Other nodes

Unpack the installation media into the ORACLE_HOME

x

runInstaller with clusterNodes = all hosts of orasw_meta_cluster_hostgroup (copies the home to all nodes)

x

root.sh of the database home (other nodes only after runInstaller on the primary node)

x

x

  • The version of the database home must not be newer than Grid Infrastructure, e.g. a database home with 23.26.3 needs Grid Infrastructure with 23.26.3 or newer.

  • oracle_databases must be defined for swdb, not only for manage_db: without a RAC database in oracle_databases, the home is installed as Single Instance home on every node.

  • All databases of a home must have the same oracle_db_type (assert in orasw_meta).

  • Read-Only Oracle Homes (readonly_home: true with oracle_home_name) are supported for RAC as well.

group_vars/rac/db.yml: database home
db_homes_config:
  db26-rac-ee:
    version: 26.1.0.0
    oracle_home: /u01/app/oracle/product/26/db_26.03
    imagename: db_home_26.03.zip      # Golden Image with RU 23.26.3
    edition: EE
    readonly_home: true
    oracle_home_name: db2603racee

db_homes_installed:
  - home: db26-rac-ee
    state: present
    apply_patches: false

3.10.2. Database

oradb_manage_db creates the database with dbca on the primary node:

  • nodelist in the response file of dbca contains all hosts of orasw_meta_cluster_hostgroup.

  • The instances are named <oracle_db_name><n> (e.g. RACCDB1 on the 1st node, RACCDB2 on the 2nd node).

  • dbca registers the database in Grid Infrastructure (srvctl config database), the database is administrator managed.

  • /etc/oratab gets an entry <oracle_db_name>:<ORACLE_HOME>:N on all nodes (start and stop by Clusterware, not by dbstart).

Attribute in oracle_databases Value Description

oracle_db_type

RAC

RAC database on all nodes of orasw_meta_cluster_hostgroup. (RACONENODE is not tested.)

storage_type

ASM

The datafiles are in the disk group of db_create_file_dest.

init_parameters

local_listener is not needed: Clusterware sets local_listener (VIP of the node) and remote_listener (SCAN). The assert for local_listener applies to Single Instance databases only.
db_create_file_dest, db_recovery_file_dest (with dbca: false for db_recovery_file_dest_size), processes, sga_target, pga_aggregate_target and control_management_pack_access are mandatory as for every database.

Variable Default Description

oradb_manage_db_dbca_ignore_prereq_failure

{{ gi_ignoreprereq }}

true: dbca -ignorePrereqFailure. dbca executes its prerequisite checks for RAC databases (e.g. SCAN, runlevel), but failures do not stop the creation of the database. The default follows gi_ignoreprereq.

group_vars/rac/db.yml: database
oracle_databases:
  - home: db26-rac-ee
    oracle_db_name: RACCDB
    oracle_db_type: RAC
    storage_type: ASM
    oracle_database_type: MULTIPURPOSE
    redolog_size: 50M
    redolog_groups: 2
    listener_port: 1521
    archivelog: false
    flashback: false
    force_logging: false
    state: present
    init_parameters:
      - {name: max_pdbs, value: '3', scope: both, state: present}
      - {name: control_management_pack_access, value: 'NONE', scope: both, state: present}
      - {name: db_create_file_dest, value: '+DATA', scope: both, state: present}
      - {name: db_recovery_file_dest_size, value: '8G', scope: both, state: present, dbca: false}
      - {name: db_recovery_file_dest, value: '+FRA', scope: both, state: present}
      - {name: pga_aggregate_target, value: '256M', scope: both, state: present}
      - {name: processes, value: '320', scope: spfile, state: present}
      - {name: sga_target, value: '2560M', scope: spfile, state: present}

Sizing hints from the tests with 26ai:

  • dbca checks the free space of the disk group of the Fast Recovery Area before the creation (DBT-06604, about 13 GB for a new Container Database), independent from db_recovery_file_dest_size.

  • sga_target: 1536M was too small: datapatch during dbca failed with ORA-04031 in the java pool and the instance hung. 2560M works.

3.11. Limitations

  • Out-of-Place Patching of Grid Infrastructure 26ai (switch into a new oracle_home_gi) is supported, root.sh runs rolling, see Out-of-Place Patching. A switch back into a former home of Grid Infrastructure is not implemented (assert in oraswgi_install). The switch of a RAC database into a new ORACLE_HOME is not supported.

  • oraswgi_install_remove_obsolete_homes is supported for Oracle Restart only.

  • RAC databases are tested with 26ai only (2 nodes, administrator managed, Container Database without PDB).

  • RAC One Node is not tested.

  • Grid Infrastructure 19c is not tested.

  • Grid Infrastructure (cluster) on hosts with FIPS (ansible_fips) is not supported: oracle_tmp_stage is not /tmp, _JAVA_OPTIONS (-Djava.io.tmpdir) is passed to root.sh and java prints Picked up _JAVA_OPTIONS: …​. rootcrs.pl parses this line as output of cluutil and stops with CLSRSC-732. Oracle Restart is not affected.

3.12. Test environment: molecule scenario rac

The molecule scenario extensions/molecule/rac installs Grid Infrastructure 26ai on 2 containers with Oracle Linux 9 and creates the RAC database RACCDB (26ai, instances RACCDB1 and RACCDB2). It is a test environment, not a template for production:

  • ASM disks are loop devices on sparse files (device_persistence: '').

  • SCAN with 1 IP and VIPs in /etc/hosts ⇒ gi_ignoreprereq: true.

  • Container specific workarounds (init.ohasd with cgroup v2, /run/nologin, entries of Docker in /etc/hosts).

  • converge.yml starts only with at least 12 GB usable memory on the Docker host (MemAvailable + memory of running containers of the scenario), override with MOLECULE_RAC_MIN_FREE_MB=<MB>.

Inventory: extensions/molecule/shared_config/inventory/group_vars/rac (gi.yml, db.yml) and host_vars/rac-*.yml.
verify.yml checks the cluster stack, SCAN, VIPs, ASM, voting files, OCR, disk groups and the open instances of the RAC databases.
verify.yml uses the running home of Grid Infrastructure (crs_home in /etc/oracle/olr.loc).
side_effect.yml: Out-of-Place Patching of Grid Infrastructure (gold image 23.26.3 ⇒ 23.26.4, root.sh rolling), PDB ORCLPDB1, tnsnames.ora, sqlnet.ora, wallet and the module tests (module_tests.yml) on the 1st node.

2.15 - RMAN Backups with oradb_rman

This guide describes the configuration of RMAN backups with the role oradb_rman and the backup script rman_backup.sh.

1. Overview

oradb_rman is executed by the playbook opitzconsulting.ansible_oracle.manage_db (last role). It configures for every database in oracle_databases with rman_jobs:

Table 1. Files created by oradb_rman
File Description

$ORACLE_BASE/bin/rman_backup.sh

Backup script, executes an RMAN script

<RMAN_SCRIPTDIR>/<job>.rman

RMAN script of a job, from the template <job>.rman.j2

$ORACLE_BASE/admin/<db_unique_name>/rman/rman_backup.cfg

Configuration of rman_backup.sh for the database (mode 0600)

/etc/cron.d/oracle_rman_ansible

Crontab with one entry per job (oradb_rman_cronfile)

<oradb_rman_tns_admin>/tnsnames.ora, sqlnet.ora

Connection to the RMAN catalog (rman_tnsalias)

<oradb_rman_wallet_loc>

Wallet with the credential of the RMAN catalog (rman_wallet: true)

The crontab contains no passwords and no directories:

10 01 * * 0 oracle /u01/app/oracle/bin/rman_backup.sh -a online_level0 -s DB1 > /dev/null 2>&1

All other settings are read by rman_backup.sh from rman_backup.cfg. The output is written by rman_backup.sh to a logfile per execution, see Logfiles.

2. Inventory

2.1. rman_jobs

rman_jobs is a list in an entry of oracle_databases. Every job executes the RMAN script <name>.rman.

Table 2. Attributes of rman_jobs
Attribute Mandatory Description

name

yes

Name of the job = name of the template <name>.rman.j2 and of the RMAN script <name>.rman

state

no

present (default) or absent (removes the crontab entry)

minute, hour, day, weekday

for cron

Schedule of the crontab entry. A job without schedule gets no crontab entry (e.g. parameter).

disabled

no

true: the crontab entry is commented out

immediate

no

true: the job is executed during the playbook (without catalog), e.g. for parameter. service and role are used as in the crontab.

service

no

Backup only on the node where the service is running (Grid Infrastructure / Oracle Restart), rman_backup.sh --service. Not together with role.

role

no

primary or standby: backup only when the database has this role (Data Guard), rman_backup.sh --role. Not together with service.

Important
service and role are mutually exclusive in a job, an assert stops the role when both are defined. Both select the member or node which executes the backup, a combination makes no sense. For Data Guard use role.

2.2. Attributes of oracle_databases

Table 3. RMAN attributes of an entry in oracle_databases
Attribute Description

rman_jobs

List of jobs, see above

rman_retention_policy

CONFIGURE RETENTION POLICY in the template parameter, default: oradb_rman_retention_policy_default

rman_channel_disk

CONFIGURE CHANNEL DEVICE TYPE DISK, default: oradb_rman_channel_disk_default

rman_controlfile_autobackup_disk

CONFIGURE CONTROLFILE AUTOBACKUP FORMAT, default: oradb_rman_controlfile_autobackup_disk_default

rman_script_dir

Directory of the RMAN scripts of the database, default: oradb_rman_script_dir

rman_log_dir

Directory of the RMAN logfiles of the database, default: oradb_rman_log_dir

rman_tnsalias

TNS alias of the RMAN catalog (entry in oracle_tnsnames_config)

rman_user

Owner of the RMAN catalog, password from dbpasswords[<rman_tnsalias>][<rman_user>]

rman_wallet

true: the password is stored in a wallet (oradb_rman_wallet_loc), the connect is /@<rman_tnsalias>

oracle_db_unique_name

Directory of rman_backup.cfg: $ORACLE_BASE/admin/<db_unique_name>/rman, default: oracle_db_name

rman_password in oracle_databases is deprecated. Use dbpasswords instead.

2.3. control_file_record_keep_time

Best practice: control_file_record_keep_time is defined in init_parameters of every database with rman_jobs. The controlfile keeps the records of the backups for this number of days. Without catalog, RMAN knows only the backups in the controlfile.

oradb_rman asserts:

  • control_file_record_keep_time is defined in init_parameters (state: present, sid: '*'), and

  • the value is >= <n> for the retention policy RECOVERY WINDOW OF <n> DAYS.

init_parameters:
  - {name: control_file_record_keep_time, value: '30', scope: both, state: present}

The assert can be disabled with oradb_rman_assert_control_file_record_keep_time: false.

2.4. Global variables

The variables of the role are described in the README of oradb_rman.

Table 4. Important variables
Variable Default Description

oradb_rman_script_dir

$ORACLE_BASE/rman

RMAN scripts (RMAN_SCRIPTDIR)

oradb_rman_log_dir

$ORACLE_BASE/rman/log

Logfiles of rman_backup.sh (RMAN_LOGDIR)

oradb_rman_log_retention

30

Days to keep the logfiles (RMAN_LOG_RETENTION), 0: keep all

oradb_rman_cronfile

oracle_rman_ansible

File in /etc/cron.d

oradb_rman_tns_admin

$ORACLE_BASE/rman/network/admin

TNS_ADMIN for the catalog (RMAN_TNS_ADMIN)

oradb_rman_cron_mkjob

false

Prefix mk-job for checkmk

Important
The template parameter uses rman_device_type_disk (e.g. 'PARALLELISM 1 BACKUP TYPE TO COMPRESSED BACKUPSET'), the templates *_fra_disk use rman_fra_backupdir. The role has no default for these variables, define them in the inventory when the templates are used.

2.5. RMAN templates

Table 5. Templates of oradb_rman
Name Description

parameter

RMAN configuration: retention policy, controlfile autobackup, channel

parameter_standby

Like parameter without CONFIGURE RETENTION POLICY (not configurable on a standby database), use it with role: standby

online_level0

Online incremental level 0 backup, archive logs, delete obsolete <rman_retention_policy>

online_level1

Online incremental level 1 backup, archive logs, delete obsolete

offline_level0

Offline level 0 backup: the database is restarted in MOUNT, opened afterwards

archivelog

Backup of the archive logs, deletes the archive logs backed up 1 time

*_fra_disk, parameter_rac

Variants for backups of the FRA to disk and for RAC. The snapshot controlfile is created in db_create_file_dest from init_parameters

Own templates <name>.rman.j2 are found by Ansible in the templates directory of the playbook (Ansible search path), the job uses the same name.

2.6. Example

Database with RMAN catalog and Data Guard
oracle_databases:
  - oracle_db_name: DB1
    oracle_db_unique_name: DB1_SITE1
    ...
    rman_retention_policy: 'RECOVERY WINDOW OF 14 DAYS'
    rman_tnsalias: RMANCAT
    rman_user: rman_db1
    rman_jobs:
      - {name: parameter, role: primary, immediate: true}
      - {name: parameter_standby, role: standby, immediate: true}
      - {name: online_level0, role: standby, weekday: "0", hour: "01", minute: "10", day: "*"}
      - {name: online_level1, role: standby, weekday: "1-6", hour: "01", minute: "10", day: "*"}
      - {name: archivelog, weekday: "*", hour: "*", minute: "30", day: "*"}

rman_device_type_disk: 'PARALLELISM 1 BACKUP TYPE TO COMPRESSED BACKUPSET'

dbpasswords:
  RMANCAT:
    rman_db1: <password>

3. rman_backup.sh

3.1. Usage

rman_backup.sh -a <action> [-s <ORACLE_SID|DB_NAME>] [--admin <Directory>]
               [-r <Directory>] [-l <Directory>] [-c <CATALOGCONNECT>] [-t <TARGETCONNECT>]
               [--service <Service>] [--role <PRIMARY|STANDBY>] [--nocatalog]
rman_backup.sh -h

-a is the only mandatory parameter. All other settings are read from the command line, the environment or the configuration file.

Interactive usage as oracle
export ORACLE_SID=DB1
$ORACLE_BASE/bin/rman_backup.sh -a archivelog
$ORACLE_BASE/bin/rman_backup.sh -a online_level0 --nocatalog

3.2. Order of the settings

The first value wins:

  1. parameter on the command line

  2. environment variable

  3. configuration file <ORACLE_ADMIN>/rman/rman_backup.cfg

  4. default of rman_backup.sh

Table 6. Parameters, environment variables and defaults
Parameter Environment / rman_backup.cfg Default Description

-a/--action

-

-

RMAN script <RMAN_SCRIPTDIR>/<action>.rman

-s/--ORACLE_SID

ORACLE_SID

-

ORACLE_SID, DB_NAME in RAC environments (the instance is determined with srvctl)

--admin

ORACLE_ADMIN

see below

Directory of rman/rman_backup.cfg

-r/--rmanscriptdir

RMAN_SCRIPTDIR

<ORACLE_ADMIN>/rman

RMAN scripts

-l/--logdir

RMAN_LOGDIR

<RMAN_SCRIPTDIR>/log

Directory of the logfiles, see Logfiles

-

RMAN_LOG_RETENTION

30

Remove logfiles older than <n> days, 0: keep all

-c/--catalogconnect

RMAN_CATALOGCONNECT

no catalog

connect catalog <value>

--nocatalog

-

-

No catalog, even when RMAN_CATALOGCONNECT is set

-t/--targetconnect

RMAN_TARGETCONNECT

/

connect target <value>

--service

RMAN_SERVICE

-

Backup only when the service runs on the current node (GI / Oracle Restart)

--role

RMAN_ROLE

-

PRIMARY or STANDBY (= PHYSICAL STANDBY). Use either --service or --role.

-

RMAN_TNS_ADMIN

-

TNS_ADMIN for RMAN

The old environment variables RMANSCRIPTDIR, RMANLOGDIR, CATALOGCONNECT, TARGETCONNECT and RMANTNS_ADMIN are still supported.

Warning
Parameters are visible in the process list. Use rman_backup.cfg for the password of the catalog, not -c.

3.3. ORACLE_ADMIN

rman_backup.sh determines ORACLE_ADMIN in the following order:

  1. --admin or the environment variable ORACLE_ADMIN

  2. $ORACLE_BASE/admin/<db_unique_name>: db_unique_name is read from the running instance (v$parameter, sqlplus / as sysdba, works in NOMOUNT)

  3. $ORACLE_BASE/admin/<ORACLE_SID>, when the instance is not running

The db_unique_name makes the configuration unique on every member of a Data Guard configuration: the ORACLE_SID is identical on all members, the db_unique_name is different.

3.4. rman_backup.cfg

The configuration file contains lines with KEY=VALUE. It is read line by line and not sourced: shell code is not executed.

# Managed by Ansible
RMAN_SCRIPTDIR=/u01/app/oracle/rman
RMAN_LOGDIR=/u01/app/oracle/rman/log
RMAN_LOG_RETENTION=30
RMAN_TNS_ADMIN=/u01/app/oracle/rman/network/admin
RMAN_CATALOGCONNECT=rman_db1/<password>@RMANCAT
  • Allowed keys: RMAN_SCRIPTDIR, RMAN_LOGDIR, RMAN_LOG_RETENTION, RMAN_TARGETCONNECT, RMAN_CATALOGCONNECT, RMAN_SERVICE, RMAN_ROLE, RMAN_TNS_ADMIN. Unknown keys and invalid lines are ignored with a warning.

  • One pair of quotes around the value is removed.

  • Empty lines and lines starting with # are ignored.

  • The file could contain the password of the catalog: mode 0600. rman_backup.sh warns, when the file is readable by other users.

  • oradb_rman creates the file. Manual changes are overwritten by the next execution of the role.

RMAN_SERVICE and RMAN_ROLE are set per job in the crontab (--service, --role) and not in the file, because the jobs of a database could use different values.

3.5. Catalog

rman_backup.sh checks the connection to the catalog before the backup. The backup runs without catalog, when the catalog is not reachable.

3.6. Logfiles

rman_backup.sh writes all output of the script, sqlplus and RMAN to stdout and to a logfile per execution. Manual executions are logged the same way as the cron jobs, the crontab redirects the output to /dev/null.

<RMAN_LOGDIR>/<db_unique_name>_<action>_<YYYYmmdd>_<HHMMSS>_<pid>.log
<RMAN_LOGDIR>/<db_unique_name>_<action>.log -> logfile of the last execution
  • Every execution has its own logfile: parallel executions do not mix their output.

  • The symlink points to the logfile of the last execution of the action (for monitoring and tail).

  • Messages before the logfile is opened (e.g. reading rman_backup.cfg) are written to the logfile afterwards.

  • Logfiles of the database and action older than RMAN_LOG_RETENTION days are removed.

  • Errors before the logfile is opened (e.g. ORACLE_HOME of the ORACLE_SID not found) and the major actions are logged in syslog (tag rman_backup.sh).

  • <db_unique_name> is the name of the directory ORACLE_ADMIN, when the instance is not running.

3.7. Parallel executions

Only one execution of an action is allowed for a database (lock file <RMAN_LOGDIR>/.<db_unique_name>_<action>.lock, flock). A 2nd execution of the same action stops immediately with exit code 30, e.g. an hourly archivelog while the last execution is still running. Different actions of a database run in parallel, e.g. archivelog during online_level0.

3.8. Exit codes

Table 7. Exit codes of rman_backup.sh
Code Description

0

RMAN successful, or backup skipped (--service not running on this node, --role does not match)

1

Wrong parameters, service not existing

10, 11, 12

ORACLE_HOME of the ORACLE_SID not found (/etc/oratab, with Grid Infrastructure / Oracle Restart the database resource ora.<ORACLE_SID>.db from crsctl), ORACLE_HOME or ORACLE_BASE not existing

13

Database role could not be determined (--role, instance not mounted)

14

rman_backup.cfg not readable

21, 22, 23

Log directory, RMAN script or logfile not existing

30

The action is running already for the database

99

RMAN failed

4. Data Guard

All members of a Data Guard configuration get the same rman_jobs. role decides, on which member a job executes the backup:

  • role: standby: backups of the database on the physical standby, the primary is not loaded

  • role: primary: backups on the primary only

  • without role: the job runs on every member

The CONFIGURE commands are stored in the controlfile of each member and must be executed on all members:

  • parameter with role: primary

  • parameter_standby with role: standby: without CONFIGURE RETENTION POLICY, the retention policy is not configurable on a standby database

online_level0 uses rman_retention_policy in delete obsolete. Therefore it works on a standby database, whose controlfile (e.g. from RMAN DUPLICATE) does not contain the retention policy, and on a new primary after a switchover.

After a switchover the backups follow the role automatically, the inventory is not changed.

Example: CONFIGURE on all members, backups on the primary only
oracle_databases:
  - oracle_db_name: DB1
    rman_jobs:
      # executed during the playbook: parameter on the primary, parameter_standby on the standby
      - {name: parameter, role: primary, immediate: true}
      - {name: parameter_standby, role: standby, immediate: true}
      # role primary: crontab entry on every member, rman_backup.sh --role primary skips it on the standby
      - {name: online_level0, role: primary, weekday: "0", hour: "01", minute: "10", day: "*"}
      - {name: archivelog, role: primary, weekday: "*", hour: "*", minute: "30", day: "*"}

All members get the same crontab entries. rman_backup.sh checks database_role in v$database at every execution and skips the backup with exit code 0, when the role does not match. Valid values of role are primary and standby (checked by an assert).

Important
Use an RMAN catalog for Data Guard. Backups of a physical standby database can be used for the primary database (and vice versa), the catalog makes the backups known to all members.
Note
archivelog deletes all archive logs that were backed up once. The ARCHIVELOG DELETION POLICY (e.g. APPLIED ON ALL STANDBY) is configured by oradb_standby with the mandatory attribute archivelog_deletion_policy in db_standby_config, see Standby Databases - Archivelog deletion policy, to prevent the deletion of archive logs which are not yet applied on the standby database.

5. Migration from older versions

  • The crontab entries contained the directories and the catalog connect (-r, -l, -c) or the environment variables RMANLOGDIR, RMANSCRIPTDIR and RMANTNS_ADMIN in /etc/cron.d. oradb_rman removes the environment variables and recreates the crontab entries. The values are in rman_backup.cfg now.

  • Existing calls of rman_backup.sh with all parameters still work.

  • The logfiles are written to RMAN_LOGDIR per execution. An existing logfile <RMAN_LOGDIR>/<name>_<action>.log of older versions is renamed to *.log.old by the first execution. The cron output in /var/log/oracle/rman/log (oradb_rman_cron_logdir) is no longer written, the directory can be removed.

  • Before this change, the attributes service, rman_retention_policy, rman_channel_disk, rman_controlfile_autobackup_disk, rman_log_dir, rman_script_dir and the catalog connect of a database were ignored by oradb_rman (bug). They are used now: check the values in the inventory before the update.

2.16 - Data Guard Guide

This guide installs an Oracle AI Database 26ai with Data Guard on two Oracle Linux 9 VMs with ansible-oracle:

  • dataguard-dbfs1: primary database DB1_SITE1 (container database DB1 with the PDB ORCLPDB)

  • dataguard-dbfs2: physical standby database DB1_SITE2, managed by the Data Guard Broker

The 1st VM exports its installation media with NFS. AutoUpgrade downloads the gold image on the 1st VM only, the 2nd VM mounts the installation media with NFS.

The 1st VM exports a 2nd NFS share for the RMAN backups, the 2nd VM mounts it permanently. A weekly level 0 backup and an hourly archivelog backup run on the current primary database.

The guide is based on the Beginners Guide. Steps that are identical are referenced and not repeated.

See Standby Databases for the details of the Data Guard implementation in ansible-oracle.

1. Overview

1.1. Architecture overview

Architecture

1.2. What are we going to do?

  1. Prepare the Ansible controller: Ansible in Ubuntu on WSL2 on Windows.

  2. Create two Oracle Linux 9 VMs on Hyper-V.

  3. Configure the inventory with the IP addresses and login user of the VMs.

  4. Start the playbook playbooks/do_all.yml. It executes all needed playbooks:

    1. opitzconsulting.ansible_oracle.os: prepare both VMs

    2. playbooks/nfs_server.yml: NFS server on dataguard-dbfs1, export of the installation media /u01/sw and of the RMAN backups /u01/app/oracle/backup, permanent mount of the RMAN backups on dataguard-dbfs2

    3. playbooks/autoupgrade.yml: install AutoUpgrade on dataguard-dbfs1 and download a gold image from My Oracle Support

    4. opitzconsulting.ansible_oracle.single_instance_fs on both VMs:

      1. install the ORACLE_HOME on dataguard-dbfs1 from /u01/sw and on dataguard-dbfs2 from the NFS share,

      2. create the primary database DB1_SITE1 with dbca,

      3. create the physical standby database DB1_SITE2 with RMAN DUPLICATE …​ FROM ACTIVE DATABASE,

      4. create the Data Guard Broker configuration DG1,

      5. configure the RMAN backups with cron (role oradb_rman).

1.3. Defaults

Table 1. Defaults used in this guide
Value Description

~/git/ansible-oracle

git repository on the Ansible controller

~/git/ansible-oracle/example/dataguard/ansible

Working directory for all Ansible commands

dataguard-dbfs1

Name of the 1st VM in the inventory: initial primary, NFS server

192.168.66.166

IP address of the 1st VM (ansible_host)

dataguard-dbfs2

Name of the 2nd VM in the inventory: initial physical standby, NFS client

192.168.66.167

IP address of the 2nd VM (ansible_host)

ol

Login user on the VMs (ansible_user)

/u01/sw

Installation media: target of the download on dataguard-dbfs1, NFS mount point on dataguard-dbfs2

/u01/app/oracle/backup

RMAN backups: directory on dataguard-dbfs1, NFS mount point on dataguard-dbfs2

/u01/stage

Staging directory on the VMs (oracle_stage)

2. Requirements

2.1. Oracle Linux 9 VMs

Two VMs with the requirements of the Beginners Guide are needed.

In addition:

  • Both VMs reach each other on the fixed IP addresses: SSH is not needed between the VMs, but the listener port 1521 (Data Guard) and NFS from dataguard-dbfs2 to dataguard-dbfs1. The playbooks open the ports in firewalld.

  • Internet access for My Oracle Support is needed on dataguard-dbfs1 only.

2.2. Create the VMs with Hyper-V and Packer

Build the Oracle Linux 9 template as described in Create the VM with Hyper-V and Packer of the Beginners Guide.

Important
All steps in this chapter are executed in PowerShell on Windows, not in WSL.
Create the VMs from the template
cd OL9
.\create-vm.ps1 -NewVMName dataguard-dbfs1 -Hostname dataguard-dbfs1 -ExternalSwitch intern_66 -FixedIP 192.168.66.166 -CPUs 2 -MemoryGB 8
.\create-vm.ps1 -NewVMName dataguard-dbfs2 -Hostname dataguard-dbfs2 -ExternalSwitch intern_66 -FixedIP 192.168.66.167 -CPUs 2 -MemoryGB 8
Important
The template has a disk with 80 GB, but the guide needs 81 GB free space in the volume group ol.
Increase the disk of both VMs, e.g. to 130 GB, before you start the installation.

2.3. Ansible controller and My Oracle Support

The requirements are identical to the Beginners Guide:

3. Setup Ansible controller

Follow Setup Ansible controller of the Beginners Guide, but install the collections in the working directory of this guide.

Install collections
cd ~/git/ansible-oracle/example/dataguard/ansible
ansible-galaxy collection install -r requirements.yml
Important
Data Guard needs ansible-oracle 5.0.0 or newer (role oradb_standby).
Use the development entry in requirements.yml to install the collection from the git repository, as long as 5.0.0 is not released.

4. Configure inventory

4.1. IP addresses and login user

The VMs are configured in inventory/hosts.yml. Change ansible_host and ansible_user for your VMs.

inventory/hosts.yml
---
all:
  children:
    # both database servers of the Data Guard configuration DG1
    dbfs:
      hosts:
        dataguard-dbfs1:
          # IP address or DNS name of the 1st Oracle Linux 9 VM (initial primary)
          ansible_host: 192.168.66.166
          # Login user on the VM with sudo privileges (SSH key login)
          ansible_user: ol
        dataguard-dbfs2:
          # IP address or DNS name of the 2nd Oracle Linux 9 VM (initial physical standby)
          ansible_host: 192.168.66.167
          ansible_user: ol

    # NFS server for the installation media (playbooks/nfs_server.yml)
    # AutoUpgrade downloads the gold image on this host only.
    nfs_server:
      hosts:
        dataguard-dbfs1:

    # Database servers which mount the installation media from nfs_server
    nfs_client:
      hosts:
        dataguard-dbfs2:

ansible_host is used for the connect identifiers of the databases (group_vars/dbfs/tnsnames.yml), for local_listener (group_vars/dbfs/database_DB1.yml) and for the NFS export. No DNS is needed between the VMs.

Note
The host names dataguard-dbfs1 and dataguard-dbfs2 are used in db_standby_config (group_vars/dbfs/standby.yml), in group_vars/dbfs/tnsnames.yml and as directories in host_vars. Change all of them, when you rename a host.

4.2. SSH key, connection test, credentials and passwords

Follow the Beginners Guide for both VMs:

4.3. Data Guard configuration

Table 2. Inventory files for Data Guard
File Content

group_vars/dbfs/standby.yml

db_standby_config: configuration DG1 with the members DB1_SITE1 (initial_role: primary) and DB1_SITE2 (initial_role: physical_standby), archivelog_deletion_policy: APPLIED ON ALL STANDBY (mandatory)

group_vars/dbfs/tnsnames.yml

Connect identifiers DB1_SITE1 and DB1_SITE2 with the IP addresses of the VMs

group_vars/dbfs/database_DB1.yml

Database DB1 with standby_config: DG1 for both members

host_vars/<host>/databases.yml

db1_unique_name: db_unique_name of the member on the host

The database is defined once for both members. Only the db_unique_name differs, it is set per host with db1_unique_name.

Table 3. Data Guard specific settings of the database in group_vars/dbfs/database_DB1.yml
Setting Description

oracle_db_unique_name: "{{ db1_unique_name }}"

DB1_SITE1 or DB1_SITE2

standby_config: DG1

Assignment to the Data Guard configuration

listener_name: LISTENER

Static listener entry <db_unique_name>_DGMGRL for RMAN DUPLICATE and the broker

archivelog, force_logging, flashback

true

local_listener

//<ansible_host>:1521

db_create_file_dest, db_create_online_log_dest_1

Oracle Managed Files (OMF) are mandatory

dg_broker_config_file1/2

/u01/app/oracle/dbs/dr1<db_unique_name>.dat: outside of the read-only ORACLE_HOME

dg_broker_start

TRUE, below dg_broker_config_file1/2

standby_file_management

AUTO

4.4. Installation media with NFS

AutoUpgrade is installed and executed on dataguard-dbfs1 only (group nfs_server). The download of the gold image works as in the Beginners Guide, see AutoUpgrade on the VM.

playbooks/nfs_server.yml configures dataguard-dbfs1 as NFS server:

  • package nfs-utils, service nfs-server

  • directory /u01/sw (owner oracle), target of the AutoUpgrade download

  • export of /u01/sw read only for the IP addresses of the group nfs_client (/etc/exports.d/oracle-sw.exports)

  • services nfs, rpc-bind and mountd in firewalld, when firewalld is running

dataguard-dbfs2 (group nfs_client) mounts the share during the installation of the ORACLE_HOME (role oraswdb_install) and unmounts it afterwards.

Table 4. NFS settings in inventory/group_vars/all/software_src.yml
Variable Value Description

install_from_nfs

false, true in host_vars/dataguard-dbfs2/software_src.yml

Mount the NFS share during the installation

nfs_server_sw

ansible_host of the 1st host of the group nfs_server

NFS server

nfs_server_sw_path

/u01/sw

Exported directory on the NFS server

oracle_stage_remote

/u01/sw

Source of the installation media: mount point on the NFS client, local directory on the NFS server

oracle_sw_copy

false

The ORACLE_HOME is extracted directly from oracle_stage_remote

The mount point is identical to the directory on the NFS server. Therefore the symlink db_home_26_latest.zip of the gold image works on both hosts.

Tip
Use the same settings for any database server, which mounts its installation media from an existing NFS server: install_from_nfs: true, nfs_server_sw, nfs_server_sw_path and oracle_stage_remote.

4.5. RMAN backups with NFS

playbooks/nfs_server.yml configures the NFS share for the RMAN backups as well:

  • dataguard-dbfs1: directory /u01/app/oracle/backup and one subdirectory per oracle_db_name (DB1), owner oracle, mode 0750 (RMAN does not create directories)

  • dataguard-dbfs1: export of /u01/app/oracle/backup read write for the group nfs_client (/etc/exports.d/oracle-backup.exports)

  • dataguard-dbfs2: permanent mount (/etc/fstab) on the same path

Both members write their backups into the same directory. Backups of the primary can be used on the standby and vice versa.

Table 5. Backup settings in inventory/group_vars/all/backup.yml
Variable Value Description

nfs_server_backup

ansible_host of the 1st host of the group nfs_server

NFS server

nfs_server_backup_path

/u01/app/oracle/backup

Exported directory and mount point

nfs_client_backup_opts

rw,bg,hard,tcp,timeo=600,rsize=1048576,wsize=1048576

Mount options on the NFS client

rman_device_type_disk

PARALLELISM 1 BACKUP TYPE TO COMPRESSED BACKUPSET

CONFIGURE DEVICE TYPE DISK

The RMAN settings are part of oracle_database_db1 in group_vars/dbfs/database_DB1.yml:

RMAN settings of DB1
  rman_retention_policy: 'RECOVERY WINDOW OF 7 DAYS'
  rman_channel_disk: "format '/u01/app/oracle/backup/%d/%d_%T_%U'"
  rman_controlfile_autobackup_disk: "'/u01/app/oracle/backup/%d/%d_{{ db1_unique_name }}_%F'"
  rman_jobs:
    - {name: parameter, role: primary, immediate: true}
    - {name: parameter_standby, role: standby, immediate: true}
    - {name: online_level0, role: primary, weekday: "0", hour: "01", minute: "10", day: "*"}
    - {name: archivelog, role: primary, weekday: "*", hour: "*", minute: "30", day: "*"}
Table 6. RMAN jobs
Job Schedule Executed on

parameter

during the playbook

current primary: CONFIGURE …​ in the controlfile

parameter_standby

during the playbook

current standby: CONFIGURE …​ without the retention policy (not configurable on a standby)

online_level0

Sunday 01:10

current primary, delete obsolete with the retention policy of the inventory

archivelog

hourly at minute 30

current primary

Both members get the same crontab entries. rman_backup.sh --role primary skips the backup on the physical standby (exit code 0). After a switchover the backups run on the new primary, the inventory is not changed.

%F contains the DBID, which is identical on all members. Therefore the format of the controlfile autobackup contains the db_unique_name.

control_file_record_keep_time (30) is greater than the recovery window (7 days), see RMAN Guide.

Logfiles of the backups
ls -l /u01/app/oracle/rman/log

oradb_standby configures ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY on both members (archivelog_deletion_policy in group_vars/dbfs/standby.yml): archivelog deletes only archive logs, which are applied on the standby database. BACKED UP …​ is not used: without catalog the standby database does not know the backups of the primary and its archive logs would never be eligible for deletion.

Note
The example uses no RMAN catalog. The backups of a member are only known in its own controlfile.
Warning
The share is mounted with hard: RMAN hangs on dataguard-dbfs2, while dataguard-dbfs1 is not available. Use a separate NFS server for production systems.

5. Install databases with Ansible

Start installation
cd ~/git/ansible-oracle/example/dataguard/ansible
ansible-playbook playbooks/do_all.yml
Note
The execution takes approx. 60 minutes plus the download of the gold image.

single_instance_fs is executed for both VMs in one play. oradb_standby needs the facts of the primary database on dataguard-dbfs1 to create the standby database on dataguard-dbfs2.

Table 7. Configuration of the databases
Parameter dataguard-dbfs1 dataguard-dbfs2

ORACLE_BASE

/u01/app/oracle

ORACLE_HOME

/u01/app/oracle/product/db26_si_ee (read-only)

ORACLE_SID

DB1

db_unique_name

DB1_SITE1

DB1_SITE2

initial role

primary

physical standby

Created by

dbca

RMAN DUPLICATE …​ FROM ACTIVE DATABASE

PDB

ORCLPDB (open on the primary only)

db_create_file_dest

/u02/oradata

db_recovery_file_dest

/u02/fra

Listener

LISTENER, port 1521

Data Guard Broker

configuration DG1, MaxPerformance, LogXptMode ASYNC

Archivelog deletion policy

APPLIED ON ALL STANDBY

The systemd unit oracle-db@DB1.service starts the database in MOUNT and opens a primary database only. The physical standby database is not opened read only (no Active Data Guard).

6. How to work with the Data Guard configuration

Login into the 1st VM and set the environment
ssh ol@192.168.66.166
sudo -iu oracle
ocenv
DB1
Show the broker configuration
dgmgrl / "show configuration"
Example
Configuration - DG1

  Protection Mode: MaxPerformance
  Members:
  DB1_SITE1 - Primary database
    DB1_SITE2 - Physical standby database

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS
Note
The broker needs approx. 1 minute after the creation until the status is SUCCESS.
Switchover to DB1_SITE2 (password of SYS)
dgmgrl sys@DB1_SITE1
DGMGRL> validate database DB1_SITE2;
DGMGRL> switchover to DB1_SITE2;
Important
The inventory is not changed after a switchover. initial_role is used for the creation of the databases only, ansible-oracle does not switch back. See Role transitions outside of ansible-oracle.

3 - Ansible Roles

All Roles from ansible-oracle.

The pages are generated from the README.md of each role, which is created by ansible-doctor.

3.1 - Overview

1. Roles

1.1. common

These roles are used to configure settings common to all machines

  • Install some generic packages

  • Configure ntp

1.2. orahost

Configures the host-specific Oracle settings:

  • Add a user & group

  • Create directory structures

  • Handle filesystem storage (partition devices, creates vg/lv and a filesystem (ext4, xfs, btrfs) etc).
    If you want to create your database on a filesystem (instead of ASM) this is where you define the layout.

  • Install required OS packages

  • Change kernel parameters

  • Set up pam.d/limits config

  • Configures Hugepages (as a percentage of total RAM)

  • Disables transparent hugepages

  • Disables NUMA (if needed)

  • Configures the interconnect network (if needed)

  • Configures Oracle ASMLib (if needed)

1.3. orahost-ssh

Configures passwordless ssh between clusternodes if setting up RAC (configure_cluster=True)

  • Uses existing ssh-keys

1.4. orahost-storage

This role configures storage to be used by ASM.

  • Partitions devices (using parted)

  • Create ASMlib labels or sets up udev-rules for device-name persistence

1.5. oraswgi-install

This role installs and configures Oracle Restart (Grid Infrastructure for a Standalone Server). The tasks for Grid Infrastructure for a Cluster (RAC) are not tested.

  • Adds a .profile_grid to the oracle user

  • Sets up directory structures

  • Copies the install-files to the servers, or installs from a remote location (e.g nfs share)

  • Install Oracle Grid Infrastructure software and configure Oracle Restart

  • Out-of-Place Patching of Oracle Restart 26ai: switch into a new oracle_home_gi

1.6. oraasm-manage-diskgroups

This role statefully manages the lifecycle of an ASM diskgroup

  • Uses the oracle_asmdg module

  • Create/delete diskgroup.

  • Add/remove disks

  • Manage attributes for the DG

1.7. oraswdb-install

This role installs the oracle database server(s). It is possible to run more than 1 database from each home. It performs Single Instance installations (RAC installations are not tested).

  • Creates a .profile with the correct environment

  • Creates directory structures

  • Installs the database-server(s)

1.8. oradb-manage-db

This role statefully manages the lifecycle of a database

  • Uses the oracle_db module

  • Creates/deletes: state: present/absent

  • Maintains archivelog/force_logging True/False

1.9. oraswgi-manage-patches

Manage patches in a GI environment

  • Uses the oracle_opatch module

  • Manages opatchauto type of patches as well as 'normal' one-offs

1.10. oraswdb-manage-patches

Statefully manage patches in a DB environment

  • Uses the oracle_opatch module

  • Manages opatchauto type of patches as well as 'normal' one-offs

1.11. pyoracledb

1.12. orahost-cron

  • Configures cron schedules if needed

1.13. orahost-logrotate

Logs grow. Log rotation solves the problem of always-growing logs.

1.14. oradb-manage-<*>

Statefully manages various aspects of the DB. They all use modules from ansible-oracle-modules

  • oradb-manage-pdb

  • oradb-manage-tablespace

  • oradb-manage-parameters

  • oradb-manage-roles

  • oradb-manage-users

  • oradb-manage-grants

  • oradb-manage-redo

  • oradb-manage-services

3.2 - orahost_meta

Meta role used by other roles to share variable defaults.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

asm_diskgroups

ASM Diskgroupdefinition for Oracle Restart/Grid-Infrastructure

Failure groups (optional) per disk in disk:

  • failure_group: name of the failure group. Disks with the same name are in the same failure group.
  • quorum: true for a quorum failure group (only voting files), must be the same for all disks of a failure group.

Without failure_group, ASM creates a failure group for every disk. The failure group of an existing disk is not changed. For the initial disk group (oracle_asm_init_dg, created by gridSetup), set failure_group for all disks or for none.

Default value

asm_diskgroups: []

Example usage

asm_diskgroups:
 - diskgroup: crs
   properties:
     - {redundancy: normal}
   attributes:
     - {name: compatible.asm, value: 12.1.0.2.0}
     - {name: compatible.rdbms, value: 11.2.0.4.0}
     - {name: au_size, value: 4m}
   disk:
     - {device: /dev/sdc, asmlabel: crs01, failure_group: storage01}
     - {device: /dev/sdd, asmlabel: crs02, failure_group: storage02}
     - {device: /dev/sde, asmlabel: crs03, failure_group: nfs, quorum: true}
 - diskgroup: data
   properties:
     - {redundancy: external}
   attributes:
     - {name: compatible.asm, value: 12.1.0.2.0}
     - {name: compatible.rdbms, value: 11.2.0.4.0}
     - {name: au_size, value: 4m}
   disk:
     - {device: /dev/sdf, asmlabel: data01}
 - diskgroup: fra
   properties:
    - {redundancy: external}
   attributes:
     - {name: compatible.asm, value: 12.1.0.2.0}
     - {name: compatible.rdbms, value: 11.2.0.4.0}
     - {name: au_size, value: 4m}
   disk:
     - {device: /dev/sdg, asmlabel: fra01}

# Defining ausize in `properties` is still supported for backward compatibility.
# But, except for initial ASM diskgroup, it still won't be considered when creating the diskgroup, though.
asm_diskgroups:
 - diskgroup: crs
   properties:
     - {redundancy: normal, ausize: 4}
   attributes:
     - {name: compatible.asm, value: 12.1.0.2.0}
     - {name: compatible.rdbms, value: 11.2.0.4.0}
   ...

asmadmin_group

The os-group for asmadmin role in Oracle ASM.

Default value

asmadmin_group: asmadmin

asmdba_group

The os-group for asmdba role in Oracle ASM.

Default value

asmdba_group: asmdba

asmoper_group

The os-group for asmoper role in Oracle ASM.

Default value

asmoper_group: asmoper

configure_host_disks

Should the specified directories be on their devices -> (true), or do they live in the root-filesystem (/) -> (false). mountpoints are described in host_fs_layout

Default value

configure_host_disks: false

dba_group

The os-group for sysdba role in Oracle RDBMS.

Default value

dba_group: dba

device_persistence

Defines the device persistency in ansible-oracle.

Values:

  • asmlib
  • asmfd
  • ’’ - no special device configuration

Default value

device_persistence: ''

Example usage

device_persistence: asmlib

device_persistence: asmfd

grid_user

Defines the os-User for Oracle Restart/Grid-Infrastructure, when role_separation is true.

Default value

grid_user: grid

grid_user_home

home directory for grid_user.

Only used, when role_seperation: true which is false by default.

Default value

grid_user_home: /home/grid

oper_group

The os-group for sysoper role in Oracle RDBMS.

Default value

oper_group: oper

oracle_group

The name for the oinstall group.

Default value

oracle_group: oinstall

oracle_inventory_loc

Directory for central Oracle Inventory.

Default value

oracle_inventory_loc: /u01/app/oraInventory

oracle_nr_bg_processes

Estimated number of background processes of an Oracle instance. Used to calculate kernel SEMMNS

Default value

oracle_nr_bg_processes: 130

oracle_rsp_stage

Defines the directory for response files for installation.

There is usually no need to change this variable.

Default value

oracle_rsp_stage: '{{ oracle_stage }}/rsp'

oracle_script_env

(Minimum) environment settings to pass to Oracle scripts. Usually passed to shell: or command: through “environment:” keyword

_JAVA_OPTIONS is only part of the environment, when orahost_meta_java_options is not empty (orahost_meta_java_env).

Default value

oracle_script_env: >-
  {{ {'CV_ASSUME_DISTID': orahost_meta_cv_assume_distid | default('', true),
      'TMPDIR': orahost_meta_tmpdir | default('', true)}
     | combine(orahost_meta_java_env) }}

oracle_seclimits

ulimit definition for orahost role.

Default value

oracle_seclimits:
  - {name: soft nproc, value: 16384}
  - {name: hard nproc, value: 16384}
  - {name: soft nofile, value: 4096}
  - {name: hard nofile, value: 65536}
  - {name: soft stack, value: 10240}
  - {name: hard stack, value: 32768}
  - {name: soft memlock, value: '{{ ((0.91 * ansible_memtotal_mb) * 1024) | round | int }}'}
  - {name: hard memlock, value: '{{ ((0.91 * ansible_memtotal_mb) * 1024) | round | int }}'}

oracle_stage

Defines the base directory for response files, configuration firles etc. for ansible-oracle.

There is usually no need to change this variable.

Default value

oracle_stage: /u01/stage

oracle_tmp_stage

Defines the temporary directory to be used by Oracle scripts. (on hardened systems, /tmp usually is noexec-flagged and thus not usable to execute scripts)

There is usually no need to change this variable.

Owner and permissions of /tmp and /var/tmp are defined by the operating system. They are never changed by the roles, see orahost_meta_tmp_stage_os_managed.

Default value

oracle_tmp_stage: >-
  {% if ansible_fips | default(false) %}{{ oracle_stage }}{%- endif %}/tmp

oracle_user

Defines the os-User for Oracle Database installation. Is also used as the grid owner, when role_separation is false.

Default value

oracle_user: oracle

oracle_user_home

home directory for oracle_user.

Default value

oracle_user_home: /home/oracle

orahost_meta_cv_assume_distid

The variable is used by oracle_script_env and passed to shell: or command: through “environment:” keyword

Riles:

  • Redhat/OL and ansible_distribution_major_version <= 8

OL{{ ansible_distribution_major_version }}

  • Redhat/OL and ansible_distribution_major_version = 9

OL8

  • SuSE

SLES15

Default value

orahost_meta_cv_assume_distid: |-
  {% if ansible_os_family == 'RedHat' %}OL
  {%- if ansible_distribution_major_version is version('8', '<=') %}{{ ansible_distribution_major_version }}
  {%- elif ansible_distribution_major_version is version('9', '=') %}8
  {%- endif %}
  {%- elif ansible_os_family in ('SuSe', 'Suse') %}SUSE{{ ansible_distribution_major_version }}
  {%- endif %}

orahost_meta_java_env

_JAVA_OPTIONS for Oracle scripts, only when orahost_meta_java_options is not empty.

Java prints Picked up _JAVA_OPTIONS: ... for every start, even for an empty value. Oracle scripts, which parse the output of java tools, fail with this line, e.g. root.sh of Grid Infrastructure (cluster) with CLSRSC-732 (cluutil -doesHomeExist).

Default value

orahost_meta_java_env: >-
  {{ (orahost_meta_java_options | default('', true) | trim | length > 0)
     | ternary({'_JAVA_OPTIONS': orahost_meta_java_options | default('', true) | trim}, {}) }}

orahost_meta_java_options

The variable is used by oracle_script_env and passed to shell: or command: through “environment:” keyword

Default value

orahost_meta_java_options: >-
  {% if oracle_tmp_stage != '/tmp' -%}
  -Djava.io.tmpdir={{ oracle_tmp_stage -}}
  {% endif %}

orahost_meta_tmp_stage_os_managed

true, when oracle_tmp_stage is /tmp or /var/tmp. Owner and permissions of these directories are defined by the operating system (root:root, sticky bit). The roles do not change them.

There is no need to change this variable.

Default value

orahost_meta_tmp_stage_os_managed: "{{ (oracle_tmp_stage | trim | regex_replace('/+$', '')) in ['/tmp', '/var/tmp'] }}"

orahost_meta_tmpdir

Default value

orahost_meta_tmpdir: >-
  {% if ansible_fips | default(false) %}{{ oracle_stage }}{%- endif %}/tmp

orahost_min_swap_mb

Minimum amount of swap space (in MB) required for DB server. Note: We observed ansible_memory_mb.swap.total is 1MB less than configured swap (e.g. 16383 instead of 16384 for 16GB)

Type: integer

Default value

orahost_min_swap_mb: 16383

orahost_ssh_hostkeytypes

SSH host key types to collect/deploy among hosts Please note, ed25519 is not supported on FIPS enabled systems and though better not collected

Default value

orahost_ssh_hostkeytypes:
  - dsa
  - rsa
  - ecdsa

orahost_ssh_key_size

SSH key size of {{ orahost_ssh_key_type }} key

Default value

orahost_ssh_key_size: 4096

orahost_ssh_key_type

SSH key type for oracle and grid users’ SSH Keys

Default value

orahost_ssh_key_type: rsa

orasw_meta_primary_node

The state of orasw_meta_primary_node is: Single-Instance / Oracle Restart: true Cluster 1st node: true Cluster other nodes: false

Type: boolean

Default value

orasw_meta_primary_node: >
  {%- if oracle_install_option_gi | default('') | upper != 'CRS_CONFIG' -%}
    {%- set _orasw_meta_primary_node = true -%}
  {%- elif groups[orasw_meta_cluster_hostgroup][0] == inventory_hostname -%}
    {%- set _orasw_meta_primary_node = true -%}
  {%- else -%}
    {%- set _orasw_meta_primary_node = false -%}
  {%- endif -%}
  {{ _orasw_meta_primary_node }}

role_separation

Should role separation be used for Oracle Restart/Grid-Infrastructure. See grid_user and oracle_user for Grid-Infrastructure user.

Default value

role_separation: false

scripts_folder

Folder under Oracle user home dir to place scripts in

Default value

scripts_folder: .Scripts

sysctl_kernel_sem_force

Force setting kernel.sem depending on configured instances (collections: oracle_databases, oracle_asm_instance), even if calculated values are lower than current ones

Default value

sysctl_kernel_sem_force: false

Discovered Tags

always

assert_ansible_oracle

Dependencies

  • oraswgi_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.3 - ahf

Experimental: the role is under development. Breaking changes can happen at any time and are not always documented.

Install and configure Oracle Autonomous Health Framework (AHF) on database servers.

The role installs AHF from the installation media in the software repository (AHF-LINUX_v<version>.zip or patch 30166242 downloaded with AutoUpgrade), upgrades an existing installation when a newer version is found, activates or deactivates the components of AHF and registers the server as client of AHF Fleet Insights (role ahf_fleet_insights).

Task file Description
main.yml Install, configure and register (or uninstall with ahf_state: absent)
assert.yml Packages, check variables, Perl and owner of ahf_loc / ahf_data_dir
install.yml Install or upgrade AHF
configure.yml Components and settings of TFA / Compliance (orachk)
fleet_insights_client.yml Register/deregister AHF Fleet Insights
uninstall.yml Uninstall AHF

See doc/guides/ahf.adoc for decisions about the installation.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

ahf_ansible_state_file

File with the settings applied by the role. Used to detect changes in ahf_tfa_settings, ahf_compliance_settings and the registration of AHF Fleet Insights.

Default value

ahf_ansible_state_file: '{{ ahf_loc }}/oracle.ahf.ansible.json'

ahf_command_timeout

Timeout in seconds for interactive commands (registration of AHF Fleet Insights).

Default value

ahf_command_timeout: 300

ahf_compliance_autostart

Start the scheduler for Compliance checks (ahfctl startahf -compliance).

Default schedule of Oracle (autorun IDs, orachk -get all -id all):

Autorun ID AUTORUN_SCHEDULE Checks COLLECTION_RETENTION
autostart_client_oratier1 3 2 * * 1,2,3,4,5,6 profile oratier1 7 days
autostart_client 3 3 * * 0 all 14 days

Change it with ahf_compliance_settings.

Default value

ahf_compliance_autostart: false

ahf_compliance_settings

Requires ahf_compliance_autostart: true: the autoruns exist only with a running Compliance scheduler (ahfctl stopahf -compliance removes them).

Settings of the Compliance autoruns per autorun ID - executed as orachk -set "<key>=<value>;..." -id <autorun ID>. Same behavior as ahf_tfa_settings, the settings of an ID are compared as a whole.

The settings are stored per autorun ID by AHF (e.g. AUTORUN_SCHEDULE, AUTORUN_FLAGS, COLLECTION_RETENTION). Show them with orachk -get all -id all. The ID is used with or without the prefix orachk. shown by orachk -get.

orachk -set requires AUTORUN_SCHEDULE (cron expression with 5 fields) in every call. The role adds the current value, when it is not part of the settings. A new autorun ID needs AUTORUN_SCHEDULE and AUTORUN_FLAGS. Values must not contain ;.

Default value

ahf_compliance_settings: {}

Example usage

ahf_compliance_settings:
  autostart_client_oratier1:
    AUTORUN_SCHEDULE: "3 2 * * 1-6"
    COLLECTION_RETENTION: 7
  autostart_client:
    COLLECTION_RETENTION: 30

ahf_data_dir

Parent directory of the AHF repository (collections, Insights reports, Compliance results). ahf_setup creates oracle.ahf/data below this directory.

Oracle requires at least 5 GB, 10 GB are recommended.

For ahf_install_mode: root all directories in this path must be owned by root (ahf_setup fails with AHF-00014). A directory below oracle_base or a mount point owned by oracle_user (e.g. /u01) is not possible. The default is ahf_loc (/opt/oracle.ahf/data), the default location of Oracle. Use a filesystem of its own for /opt/oracle.ahf with enough space.

Default value

ahf_data_dir: "{{ '/opt' if ahf_install_mode == 'root' else oracle_base }}"

ahf_data_dir_min_free_mb

Minimum free space in MB in ahf_data_dir for a new installation.

Default value

ahf_data_dir_min_free_mb: 5120

ahf_fleet_insights_client

Register the host as client of AHF Fleet Insights (ahf configuration set --type fleet-insights). The client uploads Compliance results and TFA collections automatically.

false deregisters a client, which was registered by this role.

Requires AHF 24.9 or newer and ahf_install_mode: root. Oracle documents the registration for clusters - check single instance environments.

Default value

ahf_fleet_insights_client: false

ahf_fleet_insights_force_register

Register again, even when URL and user are unchanged - e.g. after a password change.

Default value

ahf_fleet_insights_force_register: false

ahf_fleet_insights_manage

Manage the registration in AHF Fleet Insights (ahf_fleet_insights_client).

false: the registration is not changed - no registration, no deregistration. The state file keeps the last registration. Useful, when Fleet Insights is not reachable, e.g. during a maintenance of the Fleet Insights server.

Default value

ahf_fleet_insights_manage: true

ahf_fleet_insights_os_user

OS user for the REST access of Fleet Insights (ahf configuration set --os-user). Without it the registration reports AHF-02119: ... the REST Agent was not started (no local AHF user with the role rest-server). Empty: --os-user is not used.

Default value

ahf_fleet_insights_os_user: '{{ oracle_user }}'

ahf_fleet_insights_password

Password of ahf_fleet_insights_user. Use Ansible Vault.

Default value

ahf_fleet_insights_password: ''

ahf_fleet_insights_public_cert

Public certificate (PEM) of AHF Fleet Insights for the registration (ahf configuration set --public-cert). Needed for the self-signed certificate created by the installer of Fleet Insights, otherwise the registration fails with CERTIFICATE_VERIFY_FAILED. Role ahf_fleet_insights provides it as fact ahf_fi_public_cert or as file (ahf_fi_public_cert_fetch).

Default value

ahf_fleet_insights_public_cert: ''

Example usage

ahf_fleet_insights_public_cert: "{{ lookup('ansible.builtin.file', inventory_dir + '/files/ahffi_cert.pem') }}"

ahf_fleet_insights_url

Registration URL of AHF Fleet Insights. Shown by ahffi info on the Fleet Insights server - without /ahfservice.

Default value

ahf_fleet_insights_url: ''

Example usage

ahf_fleet_insights_url: https://ahffi.example.com:5005

ahf_fleet_insights_user

Generic registration user of AHF Fleet Insights.

Default value

ahf_fleet_insights_user: ''

ahf_install_mode

root (default): Installation as root with TFA daemon (systemd), automatic diagnostic collections, Compliance scheduler and AHF Fleet Insights client. Recommended by Oracle.

extract: Installation as oracle_user with ahf_setup -extract. No daemon, no automatic collections, only on-demand usage of orachk / tfactl as oracle_user. Settings for TFA and AHF Fleet Insights are ignored.

Default value

ahf_install_mode: root

ahf_installer_archive

Filename of the AHF installation media in the software repository.

Empty (default): the newest file (modification time) matching ahf_installer_patterns is used from oracle_sw_source_local on the Ansible controller (is_sw_source_local: true, oracle_sw_copy: true) or from oracle_stage_remote on the target host (oracle_sw_copy: false). Must be set for is_sw_source_local: false (oracle_sw_source_www).

Default value

ahf_installer_archive: ''

Example usage

ahf_installer_archive: AHF-LINUX_v26.10.0.zip

ahf_installer_patterns

Filename patterns for the search of the installation media (ahf_installer_archive: "").

AHF-LINUX_v*.zip is the name of the media in My Oracle Support (Doc ID 2550798.1). p30166242_*.zip is the patch “DOWNLOAD LATEST AHF” - e.g. downloaded by AutoUpgrade with AHF in autoupgrade_download_patches.

Default value

ahf_installer_patterns:
  - AHF-LINUX_v*.zip
  - p30166242_*.zip

ahf_installer_version

Version of the installation media, e.g. 26.10.0.

Normally the version is taken from the filename AHF-LINUX_v<version>.zip (also inside of patch 30166242). Set it, when the filename does not contain the version.

Default value

ahf_installer_version: ''

ahf_loc

Parent directory of the AHF installation. ahf_setup creates oracle.ahf below this directory.

For ahf_install_mode: root all directories in this path must be owned by root, because the AHF binaries are executed by root. A directory below oracle_base is owned by oracle_user, who could replace the binaries. This is checked by the role.

Default value

ahf_loc: "{{ '/opt' if ahf_install_mode == 'root' else oracle_base }}"

ahf_manage_packages

Install ahf_packages (ahf_install_mode: root only).

Default value

ahf_manage_packages: true

ahf_packages

Packages for AHF. The package perl contains all Perl modules required by AHF (e.g. File::Copy, FindBin, Math::BigInt, Net::Ping, AHF-00074). perl-interpreter alone is not enough.

Default value

ahf_packages:
  - perl
  - openssl
  - unzip

ahf_perl_home

Perl for AHF (ahf_setup -perlhome), <ahf_perl_home>/bin/perl is used.

ahf_install_mode: root requires a Perl owned by root (AHF-00026). Without -perlhome, ahf_setup uses the Perl of the Grid Infrastructure home on hosts with Oracle Restart/RAC, which is owned by the GI owner => the default is the Perl of the OS. Empty: ahf_setup selects the Perl.

Default value

ahf_perl_home: /usr

ahf_properties

AHF properties - executed as ahf configuration set --property <key> --value <value> (ahf_install_mode: root only). Same behavior as ahf_tfa_settings.

Show the supported properties with ahf configuration get --help and the current value with ahf configuration get --property <key>. Properties of AHF 26.10:

Property Default Description
ahf.fleet-insights.upload-only-minimal-files true Upload only minimal files to Fleet Insights (not documented by Oracle)
ahf.collectors.alert-history on Alert History, only for ASM (dismount, offline, mount)
ahf.collectors.enhanced_os_metrics on Enhanced OS metrics
ahf.insights.max-collection-interval 4 not documented by Oracle
ahf.compliance.excluded-check-ids Check IDs excluded from the Compliance checks

Default value

ahf_properties: {}

Example usage

ahf_properties:
  ahf.fleet-insights.upload-only-minimal-files: "false"
  ahf.collectors.alert-history: "on"

ahf_settings_force

Execute all settings and component states, even when they are unchanged since the last run of the role.

Default value

ahf_settings_force: false

ahf_setup_extra_args

Additional parameters for ahf_setup.

-local is always added for ahf_install_mode: root. AHF is installed on each host of the play. Use tfactl syncnodes for clusters.

Default value

ahf_setup_extra_args: []

Example usage

ahf_setup_extra_args:
  - -tmp_loc
  - /var/tmp

ahf_stage_dir

Directory on the target host for the extraction of the installation media. The directory is removed after the installation.

Default value

ahf_stage_dir: '{{ oracle_stage }}/ahf'

ahf_state

present: install, upgrade and configure AHF.

absent: uninstall AHF (ahfctl uninstall -silent).

Default value

ahf_state: present

ahf_tfa_directories

Additional directories for TFA (tfactl directory add), ahf_install_mode: root only.

TFA discovers the directories of GI, ASM, listener and databases (diag_dest) automatically (tfactl print directories). Add directories, which are not discovered, e.g. audit files or a log directory of an application.

Attribute Default Description
path directory (mandatory)
component RDBMS RDBMS, CRS, ASM, INSTALL, OS, CFGTOOLS, TNS, DBWLM, ACFS, IPS
database / instance database and instance for component: RDBMS
public true collection by all users, which can run tfactl diagcollect
collection exclusions exclusions, noexclusions (time restrictions only) or collectall
state present absent removes a directory added by the role

Directories added by the role are removed, when they are removed from the list.

Default value

ahf_tfa_directories: []

Example usage

ahf_tfa_directories:
  - path: /u01/app/oracle/admin/DB1/adump
    component: RDBMS
    database: db1
    instance: DB1
    collection: noexclusions

ahf_tfa_enabled

Start and enable the TFA daemon (ahf_install_mode: root only).

false stops the daemon and disables the automatic start. The software stays installed and can be used on-demand.

Default value

ahf_tfa_enabled: true

ahf_tfa_settings

Settings for TFA - executed as tfactl set <key>=<value> (ahf_install_mode: root only).

A setting is executed only, when it differs from the last run of the role. The applied settings are stored in ahf_ansible_state_file. Manual changes are not detected - use ahf_settings_force: true.

Default value

ahf_tfa_settings: {}

Example usage

ahf_tfa_settings:
  autodiagcollect: "OFF"
  reposizeMB: 10240
  minfileagetopurge: 48
  ahfnotificationaddress: dba@example.com

ahf_uninstall_delete_repo

Delete the repository in ahf_data_dir during the uninstall (-deleterepo).

Default value

ahf_uninstall_delete_repo: false

ahf_upgrade

Upgrade an existing installation, when the installation media has a newer version.

Default value

ahf_upgrade: true

ahf_verify_signature

Verify the signature of ahf_setup with openssl and the public key from the installation media before the installation.

Default value

ahf_verify_signature: true

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.4 - oradb_manage_db

Create, modify and remove Oracle Databases

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

dbca_templatename

Default template name used by DBCA during execution.

Default value

dbca_templatename: General_Purpose.dbc

hostgroup_hub

Default value

hostgroup_hub: '{{ hostgroup }}-hub'

listener_name

Default name for LISTENER

Default value

listener_name: LISTENER

oracle_gi_cluster_type

Default value

oracle_gi_cluster_type: STANDARD

oradb_manage_db_dbca_ignore_prereq_failure

Create databases with dbca -ignorePrereqFailure: dbca executes the prerequisite checks, but failures do not stop the creation of the database (e.g. a SCAN without DNS for RAC databases).

The default follows gi_ignoreprereq (prerequisite checks of Grid Infrastructure).

Default value

oradb_manage_db_dbca_ignore_prereq_failure: '{{ gi_ignoreprereq | default(false) }}'

Discovered Tags

always

autostartup_service

create_cdb,dotprofile_db

create_db

create_db,dbca,customdbcatemplate,dotprofile_db,listener2

create_db,dotprofile_db

customdbcatemplate

dbca

dbcatemplate

dotprofile_db

listener

listener2

listener_install

manage_db

molecule-idempotence-notest

odb_assert

psout

remove_db,dbca

responsefile_netca, listener_install

set_fact

sql_script

sqlnet

sqlnet2

switch_home

tnsnames

tnsnames2

update_oratab

Open Tasks

  • (bug): replace netca with new listener_details tasks

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

[Mikael Sandström]

3.5 - oradb_manage_redo

Manage redolog groups in Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

redolog

Dependencies

  • orasw_meta

License

license (MIT)

Author

  • Mikael Sandström
  • Thorsten Bruhns

3.6 - orasw_meta

Important

The description for variables is work in progress.!

Meta role used by other roles to share variable defaults.

This role has a dependency to orahost_meta.

There are a lot of variables who are used by orasw_meta

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

_www_download_bin

The variable will be removed soon. The download will be changed to get_url to simplify the code.

Default value

_www_download_bin: curl

apply_patches_db

Apply Patches from db_homes_config for installed ORACLE_HOME?

This is a global switch to enable/disable DB-Patching for all ORACLE_HOMEs.

Default value

apply_patches_db: true

assert_db_homes_config

Switch for enable/disable assert on db_homes_config.

The assert allows only the versions 19.3.0.0 and 26.1.0.0. false disables all checks of db_homes_config, not only the check of the version.

Please change the state only when really needed!

Default value

assert_db_homes_config: true

autostartup_service

Enable autostart of database during system startup.

This switch is only used, when Single Instance without Grid Infrastructure / Restart is installed.

The solution is selected with autostartup_service_mode.

Default true since 5.0.0 (4.x: false).

Default value

autostartup_service: true

autostartup_service_adopt_interval

Interval of oracle-adopt.timer (autostartup_service_mode: units), which attaches databases and listeners started outside of systemd to their unit. An inactive unit of a database, which was started outside of systemd, is started.

Default value

autostartup_service_adopt_interval: 2min

autostartup_service_dependency

Units which are required by the autostart and started before the databases and listeners (Requires= and After=), e.g. a service which mounts the file systems of the databases. Several units are separated by a blank.

Used by both values of autostartup_service_mode. With units, the units network-online.target, remote-fs.target and local-fs.target are always used in After=.

Default value

autostartup_service_dependency: network.target

autostartup_service_mode

Solution for the autostart of databases and listeners with autostartup_service: true.

  • units (default since 5.0.0): one systemd unit per database (oracle-db@<ORACLE_SID>.service) and listener (oracle-listener@<LISTENER_NAME>.service) from oracle_databases and listener_installed, grouped by oracle-databases.target and oracle-listeners.target. Created by oradb_manage_db. Databases and listeners started outside of systemd are attached to their unit by the timer oracle-adopt.timer, so they are stopped cleanly during a shutdown of the server.
  • legacy: the solution before 5.0.0 with one service oracle-rdbms.service for all databases in /etc/oratab. Created by oraswdb_install.

Switching the mode removes the units of the other solution without stopping the databases. See the Breaking Changes guide for the migration.

Default value

autostartup_service_mode: units

autostartup_service_restart

Restart a database after a crash (autostartup_service_mode: units).

The unit oracle-db@<ORACLE_SID>.service monitors PMON of the database. When PMON is gone and the last entry in the alert log is not Instance shutdown complete (or Instance shutdown (abort) complete), the database crashed. With true, systemd restarts the unit after autostartup_service_restart_sec (max. 10 starts of the unit within 1 hour), with false the unit fails.

A shutdown outside of systemd (e.g. shutdown immediate or shutdown abort in sqlplus) is not restarted.

Can be set per database with autostartup_service_restart in oracle_databases. A change is used without a restart of the database.

Default value

autostartup_service_restart: true

Example usage

oracle_databases:
  - oracle_db_name: DB1
    autostartup_service_restart: false

autostartup_service_restart_sec

RestartSec of the database units after a crash (autostartup_service_restart: true), for all databases.

Default value

autostartup_service_restart_sec: 2min

autostartup_service_shutdown_mode

Shutdown mode of the databases (autostartup_service_mode: units): immediate, transactional, normal or abort.

Default value

autostartup_service_shutdown_mode: immediate

autostartup_service_start_timeout

TimeoutStartSec of the database units (autostartup_service_mode: units).

The start of a database with crash recovery can take a long time.

Default value

autostartup_service_start_timeout: 15min

autostartup_service_stop_timeout

TimeoutStopSec of the database units (autostartup_service_mode: units).

systemd does not kill a database after the timeout (KillMode=process).

Default value

autostartup_service_stop_timeout: 15min

db_homes_config

This is a central variable for ORACLE_HOME configuration.

Defines the known ORACLE_HOMEs with a lot of additional informations but not the installation itself.

See db_homes_installed for a list of installed ORACLE_HOMEs.

The dictionary holds data for:

Attribute Description
imagename Set an optional name for a golden Image to install from. The archiv is read from same directory as the normal installation medias from Oracle.
filesource imagename can be replaced/overridden by filesource to provide an absolute path/url to the golden image (when not available in the normal installation place)
edition allowed values: SE, SE2, EE. default value:
opatch_minversion Is needed for patching. Automatically installs a new version of OPatch, when existing version is older then opatch_minversion
oracle_home
oracle_home_name Mandatory variable, when readonly_home: true. Oracle allows only characters, numbers and ‘_’ as value in oracle_home_name. Do not use ‘-’ as a value!
opatchauto Bundle patches to be installed/removed using opatchauto
opatch One-off patches to be installed/removed using opatch
readonly_home Should ansible-oracle install this ORACLE_HOME as readonly home? Do NOT change this attribute for an installed ORACLE_HOME. default value: false
version The base version for the ORACLE_HOME. Use the version from the official 1st release of Oracle.

See examples for allowed values.

Example usage

db_homes_config:
  21300_base: # 21c without patching - you should never use this in production!
    home: db1_base
    version: 21.3.0.0
    edition: EE
  19300_base: # 19c without patching - you should never use this in production!
    home: db1_base
    version: 19.3.0.0
    edition: EE
  1931_se2:
    oracle_home: /u01/app/oracle/product/19.0.0/dbhome_1
    version: 19.3.0.0
    edition: SE2
    opatch_minversion: "12.2.0.1.51"
    opatchauto:
      - patchid: 39062956
        patchversion: 19.31.0.0.260421
        state: present
        path: 39062956/39062956/39036936
        subpatches:
          - 39034528 # Database
          - 39039430 # OCW
          - 39055473 # ACFS
          - 39107855 # Tomcat
          - 39107825 # DBWLM
        apply_options:
          - "-deleteInactivePatches"
    opatch:
      - patchid: 39473469
        state: present
        path: 39473469/39473469/39473469
        apply_options:
          - "-force_conflict"

db_homes_installed

Example usage

db_homes_installed:
  - home: 19300-base
    apply_patches: true
    state: present

db_standby_config

Defines the standby configurations (Data Guard, Dbvisit).

Not set by default. Must be identical on all members of a configuration. A database is assigned with standby_config in oracle_databases.

The inventory structure is described in doc/guides/standby_databases.adoc.

Type dataguard: the standby databases and the broker configuration are created by the role oradb_standby.

IMPORTANT! Only the asserts are implemented for type dbvisit at the moment.

Example usage

db_standby_config:
  - name: DG1
    type: dataguard
    dg:
      protection_mode: MaxPerformance
      archivelog_deletion_policy: APPLIED ON ALL STANDBY
    members:
      - hosts: [dbhost1]
        db_unique_name: DB1_SITE1
        initial_role: primary
        dg:
          connect_identifier: DB1_SITE1
          log_xpt_mode: ASYNC
      - hosts: [dbhost2]
        db_unique_name: DB1_SITE2
        initial_role: physical_standby
        dg:
          connect_identifier: DB1_SITE2
          log_xpt_mode: ASYNC

dbenvdir

Define the directory for db environment configurations.

Used during installation of ocenv.sh.

Default value

dbenvdir: '{{ oracle_user_home }}/dbenv'

dbpasswords

Define the passwords for DB-Users in nonCDB, CDB and PDBs.

Default value

dbpasswords: {}

Example usage


nonCDB with db_name: orcl

dbpasswords:
  <db_name>:
    <db_user>: <db_password>

dbpasswords:
  orcl:
    SYS: Oracle_456
    SYSTEM: Oracle_456
    DBSNMP: Oracle_456

CDB with `db_name: orcl` and `PDB: orclpdb`

dbpasswords:
  <CDB db_name>:
    <CDB db_user>: <db_password>
    <PDB name>:
      <PDB db_user>: <db_password>

dbpasswords:
  orcl:
    SYS: Oracle_456
    SYSTEM: Oracle_456
    DBSNMP: Oracle_456
    ORCLPDB:
      PDBADMIN: Oracle_789

default_dbpass

Set the default password for all DB-Users not defined in dbpasswords.

Default value

default_dbpass: >-
  {% if item is defined and item.oracle_db_passwd is defined %}{{ item.oracle_db_passwd -}}
  {%- elif dbh is defined and dbh.oracle_db_passwd is defined %}{{ dbh.oracle_db_passwd -}}
  {%- endif %}

Example usage

default_dbpass: topeS3cr§t

deploy_ocenv

Install the ocenv.sh environment script.

Source is from: https://github.com/opitzconsulting/oracle-scripts

Default value

deploy_ocenv: true

disable_ee_options

Global switch to define if Oracle options should be changed in binary for Enterprise-Edition.

Default value

disable_ee_options: 'true'

Example usage

disable_ee_options: true # change options in binary
disable_ee_options: false # do not change options in binary

get_url_ssl_client_cert

PEM formatted certificate chain file to be used for SSL client authentication with ansible.builtin.get_url

Type: path

Example usage

/etc/pki/ca-trust/source/anchors/client-certchain.pem

get_url_ssl_client_key

PEM formatted file that contains your private key to be used for SSL client authentication with ansible.builtin.get_url

Type: path

Example usage

/etc/pki/tls/private/client-cert.pem

grid_base

ORACLE_BASE for Grid Infrastructure/Restart

Important!

ORACLE_BASE for Grid-Infrastructure must be different the ORACLE_BASE for RDBMS.

ORACLE_BASE for Oracle Rstart is same as RDBMS.

Default value

grid_base: >-
  {% if oracle_install_option_gi == 'CRS_CONFIG' -%}
  /u01/app/grid/base{% else %}{{ oracle_base }}{% endif %}

hostgroup

Defines the hostgroup with nodes for a Grid-Infrastructure Cluster.

The variable needs a refactoring.

Default value

hostgroup: '{{ group_names[0] }}'

http_proxy

Define the http proxy for downloads

Default value

http_proxy: ''

https_proxy

Define the https proxy for downloads

Default value

https_proxy: ''

install_from_nfs

Mount NFS-Server for installation media?

nfs_server_sw and nfs_server_sw_path are needed, when install_from_nfs: true

Default value

install_from_nfs: false

is_sw_source_local

Default value

is_sw_source_local: true

listener_port

The global default port for listener when no dedicated port is configured in listener itself.

Default value

listener_port: 1521

nfs_server_sw

Defines the NFS-Server used to mount the installation media from.

Example usage

nfs_server_sw: nfs-server.example.com

nfs_server_sw_path

Path to installation medias on NFS-Ser.

Important

ansible-oracle expects a fixed structure for installation media and patches!

Example usage

nfs_server_sw_path: /orasw

no_proxy

Define no_proxy list für downlads.

Default value

no_proxy: ''

ocenv_bashrc_init

Add ocenv.sh to bashrc of oracle user?

deploy_ocenv: true is needed for the installation.

Default value

ocenv_bashrc_init: true

ocenv_bashrc_init_section

Define the conntents to add to .bashr when ocenv_bashrc_init: true.

Default value

ocenv_bashrc_init_section: |
  echo "execute ocenv to source Oracle Environment"
  alias ocenv='. "{{ dbenvdir }}/ocenv"'

opatch_conflict_check

When calling oracle_opatch for DB or GI, decide if analyze stage of opatch/opatchauto should be executed. Will be overridden by opatch_db_conflict_check and opatch_gi_conflict_check.

Type: boolean

Default value

opatch_conflict_check: true

oracle_all_editions_options_state

Intended state of edition independent database options, as defined in {{ oracle_all_editions_options }}

Default value

oracle_all_editions_options_state:
  - {option: dnfs, enabled: false}
  - {option: uniaud, enabled: false}

oracle_asm_disk_string

Default value

oracle_asm_disk_string: ORCL:*

oracle_base

ORACLE_BASE for Oracle RDBMS

Default value

oracle_base: /u01/app/oracle

oracle_databases

Defines the list of databases on a host.

There are diffent sub list to define Profiles, Services, Tablespaces, Users …

Attributes (selection)

Attribute Default Description
home key in db_homes_config (mandatory)
oracle_db_name DB_NAME (mandatory)
state present or absent (mandatory)
is_container true create a Container Database. Only true is allowed for 26ai. Set is_container: false for a non-CDB with 19c.
omf true Oracle Managed Files (dbca -useOMF). omf: true needs db_create_file_dest and db_recovery_file_dest in init_parameters. OMF is strongly recommended. omf: false is only allowed with storage_type: FS, needs an own DBCA template without OMF (dbca_templatename) and is not tested.
storage_type FS FS or ASM. ASM requires omf: true.

Container Databases (is_container: true, default) need max_pdbs in init_parameters (assert) with the number of PDBs allowed by the license: max. 3 for SE2, max. 1024 for EE. IMPORTANT! EE allows more than 3 PDBs only with a license for the Multitenant Option.

Databases of an EE home need control_management_pack_access in init_parameters (assert) with NONE, DIAGNOSTIC or DIAGNOSTIC+TUNING. It is optional for SE2 and must be NONE if defined. IMPORTANT! DIAGNOSTIC needs a license for the Diagnostics Pack, DIAGNOSTIC+TUNING for the Diagnostics and Tuning Pack.

Every database needs processes in init_parameters (assert in orahost_meta, used for kernel.sem). Every database needs sga_target and pga_aggregate_target in init_parameters (assert). oracle_db_mem_totalmb is not supported anymore. With Hugepages (configure_hugepages: true, default) memory_target and memory_max_target are not allowed in init_parameters (assert), Automatic Memory Management prevents the usage of Hugepages.

datafile_dest and recoveryfile_dest are removed from oracle_databases (assert fails), they are replaced by db_create_file_dest and db_recovery_file_dest in init_parameters.

File destinations in dbca:

omf storage_type datafile destination recovery area destination
true (default) FS or ASM db_create_file_dest in init_parameters db_recovery_file_dest in init_parameters
false FS oracle_dbf_dir_fs oracle_reco_dir_fs
false ASM not allowed (assert fails)

The values in init_parameters are also used for standby databases (RMAN duplicate) and oradb_rman.

IMPORTANT! OMF is strongly recommended in ansible-oracle. Databases without OMF are not tested. Use an own DBCA template without OMF (dbca_templatename) for omf: false.

Sub-Sections

statspack

Attribute Description
purgedays Purgedays for snapshots
snaplevel snaplevel used in job
state create (present) or remove (absent) statspack from nonCDB, CDB or PDB

tablespaces

Defines the Tablespace to add, drop or modify to the database.

Known limitations:

Multiple files with dedicated file names are not supported.

Use OMF instead, which is the default during creation of Tablespaces.

Attribute Description
name
size
autoextend
next
maxsize
content
state
bigfile
numfiles mutually exclusive with datafile
datafile mutually exclusive with numfiles
See examples for allowed values.

init_parameters

Initialization parameters, managed by oradb_manage_parameters (also in oracle_pdbs).

Attribute Description
name name of the parameter
value value of the parameter
scope both (default), spfile or memory
state present, absent or reset
sid instance name for the SID clause, default * (all instances). Case-sensitive, e.g. for local_listener per RAC instance. The instance does not need to run, then only the spfile is changed.
dbca false: not used during creation with dbca (only oracle_databases). Default true, false for entries with sid other than *. dbca: true with sid other than * is not allowed (dbca has no SID clause).

Single Instance databases (also with Oracle Restart) need local_listener in init_parameters, e.g. {name: local_listener, value: '//localhost:1521', scope: both, state: present}. The alias from DBCA in tnsnames.ora is missing after a switch of the ORACLE_HOME.

Example usage


# IMPORTANT! This following example shows the general structure of oracle_databases.
# Do not use it as a real example.

oracle_databases:
  - home: 19300-base
    oracle_db_name: orcl
    state: present
    statspack:
      purgedays: 14
      snaplevel: 5
      state: present
    tablespaces:
      - {name: system, size: 10M, autoextend: true, next: 50M, maxsize: 4G, content: permanent, state: present, bigfile: false}
    init_parameters:
      - {name: audit_trail, value: 'NONE', scope: spfile, state: present}
      # RAC: one entry per instance
      - {name: local_listener, value: 'rac1-vip:1521', scope: both, state: present, sid: orcl1}
      - {name: local_listener, value: 'rac2-vip:1521', scope: both, state: present, sid: orcl2}
    profiles:
      - name: DEFAULT
    users:
      - schema: dbsnmp

oracle_databases:
  - home: 19300-base
    oracle_db_name: orcl
    oracle_db_type: SI
    storage_type: FS
    oracle_database_type: MULTIPURPOSE
    redolog_size: 100M
    redolog_groups: 3
    archivelog: false
    flashback: false
    force_logging: false
    listener_name: LISTENER
    state: present
    statspack:
      purgedays: 14
      snaplevel: 5
      state: present
    tablespaces:
      - {name: system, size: 10M, autoextend: true, next: 50M, maxsize: 4G, content: permanent, state: present, bigfile: false}
      - {name: sysaux, size: 10M, autoextend: true, next: 50M, maxsize: 4G, content: permanent, state: present, bigfile: false}
      - {name: undotbs1, size: 10M, autoextend: true, next: 50M, maxsize: 8G, content: permanent, state: present, bigfile: false}
      - {name: users, size: 10M, autoextend: true, next: 50M, maxsize: 2G, content: permanent, state: present, bigfile: false}
      - {name: temp, size: 10M, autoextend: true, next: 50M, maxsize: 4G, content: permanent, state: present, bigfile: false}
    init_parameters:
      - {name: audit_trail, value: 'NONE', scope: spfile, state: present}
      - {name: control_management_pack_access, value: 'NONE', scope: both, state: present}
      - {name: control_file_record_keep_time, value: '30', scope: both, state: present}
      - {name: db_files, value: '200', scope: spfile, state: present}
      - {name: deferred_segment_creation, value: 'false', scope: both, state: present}
      - {name: filesystemio_options, value: 'setall', scope: spfile, state: present}
      - {name: job_queue_processes, value: '10', scope: both, state: present}
      # Disable forcing hugepages on really small systems
      #  - {name: use_large_pages ,value: 'ONLY', scope: spfile, state: present}
      - {name: log_archive_dest_1, value: 'location=USE_DB_RECOVERY_FILE_DEST', scope: both, state: present}
      - {name: log_buffer, value: '64M', scope: spfile, state: present}
      - {name: pga_aggregate_target, value: '200M', scope: both, state: present, dbca: false}
      - {name: sga_target, value: '1800M', scope: spfile, state: present, dbca: false}
      - {name: recyclebin, value: 'off', scope: spfile, state: present}
      - {name: streams_pool_size, value: '152M', scope: spfile, state: present}
      - {name: "_cursor_obsolete_threshold", value: '1024', scope: spfile, state: present}
      - {name: max_pdbs, value: '3', scope: both, state: present}
      - {name: clonedb, value: 'true', scope: spfile, state: present, dbca: false}
      - {name: db_create_file_dest, value: '/u02/oradata', scope: both, state: present}
      - {name: db_create_online_log_dest_1, value: '/u02/oradata', scope: both, state: present}
      - {name: db_recovery_file_dest_size, value: '10G', scope: both, state: present, dbca: false}
      - {name: db_recovery_file_dest, value: '/u02/fra', scope: both, state: present}
    profiles:
      - name: DEFAULT
        state: present
        attributes:
          - {name: password_life_time, value: unlimited}
    users:
      - schema: dbsnmp
        state: unlocked
        update_password: always

oracle_dbf_dir_fs

Datafile destination in DBCA for databases with omf: false (only storage_type: FS).

Databases with omf: true (default) use db_create_file_dest from init_parameters.

Default value

oracle_dbf_dir_fs: /u02/oradata/

oracle_ee_options_112

Define the enabled/disabled options for 11.2 binaries.

Default value

oracle_ee_options_112:
  - {option: dm, state: false}
  - {option: dv, state: false}
  - {option: lbac, state: false}
  - {option: olap, state: false}
  - {option: partitioning, state: false}
  - {option: rat, state: false}

oracle_ee_options_121

Define the enabled/disabled options for 12.1 binaries.

Default value

oracle_ee_options_121:
  - {option: dm, state: false}
  - {option: olap, state: false}
  - {option: partitioning, state: false}
  - {option: rat, state: false}

oracle_ee_options_122

Define the enabled/disabled options for 12.2 binaries.

Default value

oracle_ee_options_122:
  - {option: oaa, state: false}
  - {option: olap, state: false}
  - {option: partitioning, state: false}
  - {option: rat, state: false}

oracle_ee_options_183

Define the enabled/disabled options for 18c binaries.

Default value

oracle_ee_options_183:
  - {option: oaa, state: false}
  - {option: olap, state: false}
  - {option: partitioning, state: false}
  - {option: rat, state: false}

oracle_ee_options_193

Define the enabled/disabled options for 19c binaries.

Default value

oracle_ee_options_193:
  - {option: oaa, state: false}
  - {option: olap, state: false}
  - {option: partitioning, state: false}
  - {option: rat, state: false}

oracle_ee_options_213

Define the enabled/disabled options for 21c binaries.

Default value

oracle_ee_options_213:
  - {option: oaa, state: false}
  - {option: olap, state: false}
  - {option: partitioning, state: false}
  - {option: rat, state: false}

oracle_ee_options_261

Define the enabled/disabled options for 26ai binaries.

Default value

oracle_ee_options_261:
  - {option: partitioning, state: false}
  - {option: rat, state: false}

oracle_home_gi_cl

Custom setting for CRS_HOME when Grid-Infrastructure is installed.

The variable is used as a default for oracle_home_gi.

Do not forget `` for Cluster installations.

Default value

oracle_home_gi_cl: /u01/app/{{ oracle_install_version_gi }}/grid

oracle_home_gi_so

Custom setting for CRS_HOME when Oracle Restart is installed.

The variable is used as a default for the internal variable oracle_home_gi.

Default value

oracle_home_gi_so: '{{ oracle_base }}/{{ oracle_install_version_gi }}/grid'

oracle_hostname

Grid-Infrastructure nodename.

Used as hostname for all oradb_manage_-connections and as hostname in RDBMS installation.

Default value

oracle_hostname: '{{ ansible_fqdn }}'

oracle_install_option_gi

Define the installation type for Grid Infrastructure or Oracle Restart.

Value Description
"" Install Single Instance (Default)
CRS_CONFIG Install Grid-Infrastructure
HA_CONFIG Install Oracle Restart

Default value

oracle_install_option_gi: ''

Example usage


oracle_install_option_gi: ''

oracle_install_option_gi: CRS_CONFIG

oracle_install_option_gi: HA_CONFIG

oracle_install_version_gi

Define the version (base release) for Grid-Infrastructure or Oracle Restart.

Important

Do not forget to set oracle_install_option_gi.

Set the version in every inventory with Grid Infrastructure or Oracle Restart. It must match the installation media (oracle_sw_image_gi, oracle_install_image_gi). The default is 26ai (26.1.0.0) as of 5.0.0 (19c before).

Default value

oracle_install_version_gi: 26.1.0.0

Example usage


oracle_install_version_gi: 26.1.0.0

oracle_install_version_gi: 19.3.0.0

oracle_opatch_patch

Mapping from OPatch ZIP-archive to Oracle Release.

The variable is configured for all supported Oracle Release by default.

Default value

oracle_opatch_patch:
  - filename: p6880880_230000_Linux-x86-64.zip
    version: 26.1.0.0
  - filename: p6880880_210000_Linux-x86-64.zip
    version: 21.3.0.0
  - filename: p6880880_190000_Linux-x86-64.zip
    version: 19.3.0.0
  - filename: p6880880_180000_Linux-x86-64.zip
    version: 18.3.0.0
  - filename: p6880880_122010_Linux-x86-64.zip
    version: 12.2.0.1
  - filename: p6880880_122010_Linux-x86-64.zip
    version: 12.1.0.2
  - filename: p6880880_121010_Linux-x86-64.zip
    version: 12.1.0.1
  - filename: p6880880_112000_Linux-x86-64.zip
    version: 11.2.0.4
  - filename: p6880880_112000_Linux-x86-64.zip
    version: 11.2.0.3

oracle_pdbs

Define the list of PDBs in CDB.

Important!

For each listelement in oracle_pdbs an element in oracle_databases with cdb = oracle_db_name must exists..

Otherwise the assert for oracle_pdbs will fail!

Example usage

oracle_pdbs:
  - home: 19300-base
    listener_port: 1521
    cdb: orcl
    pdb_name: ORCLPDB
    state: present
    statspack:
      purgedays: 14
      snaplevel: 7
      state: present
    tablespaces:
      - {name: system, size: 10M, autoextend: true, next: 50M, maxsize: 4G, content: permanent, state: present, bigfile: false}
      - {name: sysaux, size: 10M, autoextend: true, next: 50M, maxsize: 4G, content: permanent, state: present, bigfile: false}
      - {name: undotbs1, size: 10M, autoextend: true, next: 50M, maxsize: 8G, content: permanent, state: present, bigfile: false}
      - {name: users, size: 10M, autoextend: true, next: 50M, maxsize: 2G, content: permanent, state: present, bigfile: false}
      - {name: temp, size: 10M, autoextend: true, next: 50M, maxsize: 4G, content: permanent, state: present, bigfile: false}
    users:
      # quotas: list of tablespace/size, size in bytes with optional K, M, G, T or unlimited.
      # With quotas, the default_tablespace gets no automatic quota unlimited.
      # quotas_mode: append (default) keeps other quotas, enforce removes them.
      # size 0 removes the quota on a tablespace.
      - schema: app
        state: present
        default_tablespace: users
        quotas_mode: enforce
        quotas:
          - tablespace: users
            size: unlimited
          - tablespace: sysaux
            size: 100M

oracle_profile_template

Define which template is used to create .profile scripts.

Important

This variable is only used when deploy_ocenv: false. The default is true.

Default value

oracle_profile_template: dotprofile-home.j2

oracle_reco_dir_fs

Recovery area destination in DBCA for databases with omf: false (only storage_type: FS).

Databases with omf: true (default) use db_recovery_file_dest from init_parameters.

Default value

oracle_reco_dir_fs: /u02/fra/

oracle_stage_remote

Default value

oracle_stage_remote: '{{ oracle_stage }}'

oracle_sw_patches

Defines the list of known Patches in ansible-oracle.

Patch files are expected to be found by their filename under oracle_sw_source_local, or oracle_sw_source_www respectively, unless a filesource dict element provides a full path / complete URL to the patch file.

Usage of this variable:

If a complete software repository with patches is used with a nfs-mount, this variable is not needed.

Default value

oracle_sw_patches: []

Example usage

oracle_sw_patches:
  - filename: p28183653_122010_Linux-x86-64.zip
    filesource: /mnt/patches/p28183653_122010_Linux-x86-64.zip
    patchid: 28183653
    version: 12.2.0.1
    patchversion: 12.2.0.1.180717
    description: GI-RU-July-2018
    creates: 28183653/28163133/files/suptools/orachk.zip
  - filename: p27468969_122010_Linux-x86-64.zip
    filesource: https://downloadserver/patches?id=27468969
    patchid: 27468969
    version: 12.2.0.1
    patchversion: 12.2.0.1.180417
    description: GI-RU-April-2018
    creates: 27468969/27674384/README.txt
  - filename: p28140658_12201180417DBAPR2018RU_Linux-x86-64.zip
    patchid: 28140658
    version: 12.2.0.1
    patchversion: 12201180417DBAPR2018RU
    description: 'PARALLEL QUERY Patch for Bug# 28140658 for Linux-x86-64 Platforms'
    creates: online/files/hpatch/bug28140658.pch

oracle_sw_source_local

Define the directory when `` is set.

The archives are directly read from this directory.

Default value

oracle_sw_source_local: /tmp

oracle_sw_source_www

Define the URL for downloading installation medias and patches from a central server during software installation and patching.

Default value

oracle_sw_source_www: http://www/orasw

orasw_meta_assert_db_standby_config

Switch for enable/disable assert on db_standby_config and standby_config in oracle_databases.

Please change the state only when really needed!

Default value

orasw_meta_assert_db_standby_config: true

orasw_meta_assert_oracle_databases

Switch for enable/disable assert on oracle_databases.

Please change the state only when really needed!

Default value

orasw_meta_assert_oracle_databases: true

orasw_meta_cluster_hostgroup

Ansible Inventory hostgroup for RAC-Cluster.

Default value

orasw_meta_cluster_hostgroup: ''

orasw_meta_forced_lang

Certain modules (e.g. oracle_db and oracle_opatch) rely on English language outputs. This causes trouble if system has different locale settings. That’s why we force the language in script environments.

Default value

orasw_meta_forced_lang: en_US.UTF-8

proxy_env

This is an internal variable for downloading patches. Usually no need to change it.

Default value

proxy_env:
  http_proxy: '{{ http_proxy }}'
  https_proxy: '{{ https_proxy }}'
  no_proxy: '{{ no_proxy }}'

set_oracle_all_editions_options_state

Switch to globally enable/disable linking of edition independent database options

Default value

set_oracle_all_editions_options_state: true

shell_aliases

Define shell Aliases for oracle user.

Default value

shell_aliases:
  - asmcmd='. oraenv ;rlwrap asmcmd -p'
  - sqlsyso='. oraenv ;rlwrap sqlplus "/ as sysdba"'
  - dgmgrl='rlwrap dgmgrl'
  - rman='rlwrap rman'
  - sid='export ORACLE_SID=$(ps -ef | grep "ora_pmon_$ORACLE_DBNAME" |grep -v grep | sed 's/^.*pmon_//g')'
  - sqlp='rlwrap sqlplus'
  - sqlsys='rlwrap sqlplus "/ as sysdba"'
  - dbh='cd $ORACLE_HOME'
  - dbb='cd $ORACLE_BASE'
  - talert='tail -500f $ORACLE_BASE/diag/rdbms/$ORA_DB_UNQ_NAME/$ORACLE_SID/trace/alert_$ORACLE_SID.log'
  - lalert='less $ORACLE_BASE/diag/rdbms/$ORA_DB_UNQ_NAME/$ORACLE_SID/trace/alert_$ORACLE_SID.log'
  - lsnrstart='lsnrctl start $LSNRNAME'
  - lsnrstop='lsnrctl stop $LSNRNAME'
  - lsnrstatus='lsnrctl status $LSNRNAME'
  - lsnrservice='lsnrctl services $LSNRNAME'

shell_ps1

Configure shell prompt for OS-User oracle

Default value

shell_ps1: "'[$LOGNAME'@'$ORACLE_SID `basename $PWD`]$'"

ulimit_systemd_mapping

Mapping of oracle_seclimits to the limits of the systemd units for the autostart.

Default value

ulimit_systemd_mapping:
  hard nproc: {name: LimitNPROC}
  hard nofile: {name: LimitNOFILE}
  hard stack: {name: LimitSTACK, sysctlfactor: 1024}
  hard memlock: {name: LimitMEMLOCK, sysctlfactor: 1024}

use_proxy

Enable Proxy for Download

Default value

use_proxy: false

Discovered Tags

always

assert_ansible
 Assert version of Ansible Core

assert_ansible_oracle
 Assert inventory variables from ansible-oracle

nfsmountdb

nfsumountdb

Open Tasks

  • (bug): add assert for install_from_nfs, nfs_server_sw, nfs_server_sw_path
  • (bug): why do we need oracle_stage_remote?
  • (bug): is_sw_source_local really needed with default or as dependency from other vars?
  • (bug): Open Issue with changed behavior for _oraswgi_meta_configure_cluster
  • (bug): Variable hosgroup needs a refactoring
  • (bug): Check if shell_ps1 is used for oracle and grid
  • (bug): Check when shell_aliases is used in ansible-oracle and change description
  • (bug): check if assert for deploy_ocenv + ocenv_bashrc_init is existing
  • (information): variable description is missing
  • (information): variable description is missing
  • (information): db_homes_installed not used for a long time…
  • (information): variable description is missing
  • (information): variable description is missing
  • (todo): Remove variable _www_download_bin

Dependencies

  • orahost_meta
  • orasw_meta_internal

License

license (MIT)

Author

[Thorsten Bruhns]

3.7 - oraswgi_install

Install Grid Infrastructure / ORacle Restart software.

This role has a dependency to orahost_meta and orasw_meta for default parameter.

Known Issues from Oracle:

  • TOP Note: Solutions for Typical Grid Infrastructure/RAC Database runInstaller/DBCA for RAC Issues (Doc ID 1056713.1)
  • INS-06006 GI RunInstaller Fails If OpenSSH Is Upgraded to 8.x (Doc ID 2555697.1)

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

cvuqdisk_rpm

Name of RPM for cvuqdisk.

RPM is installed from {{ oracle_home_gi }}/cv/rpm/

Default value

cvuqdisk_rpm: cvuqdisk-1.0.10-1.rpm

default_dbpass

Default value

default_dbpass: '{% if item.0.oracle_db_passwd is defined %}{{ item.0.oracle_db_passwd }}{% else %}Oracle123{% endif %}'

default_gipass

Default password for Grid-Infrastructure and ASM-Users.

Important

It is mandatory to set this variable in your inventory!

Default value

default_gipass: ''

endoracle_scan_port

Port for SCAN-Listener

gi_ignoreprereq

false => Do not ignore failed runcluvfy.sh true => Ignore failed runcluvfy.sh

Default value

gi_ignoreprereq: false

oracle_asm_init_dg

1st Diskgroup where ASM SPFile is placed.

Default value

oracle_asm_init_dg: crs

oracle_asm_storage_option

Default value

oracle_asm_storage_option: "{% if oracle_install_version_gi is version('12.2', '>=') %}FLEX_ASM_STORAGE{% else %}LOCAL_ASM_STORAGE{% endif %}"

oracle_cluster_mgmdb

Create _MGMTBD on cluster.

Default value

oracle_cluster_mgmdb: false

oracle_cluster_name

Name of Grid-Infrastructure Cluster.

The maximum length allowed for clustername is 63 characters. The name can be any combination of lower and uppercase alphabets (A - Z), (0 - 9) and hyphens (-).

Only set this variable, when orasw_meta_cluster_hostgroup contains a ‘_’.

Important! Ansible hostgrouds could not contain a ‘-’ in name!

Default value

oracle_cluster_name: '{{ orasw_meta_cluster_hostgroup }}'

oracle_gi_cluster_type

Define clusterware type.

Default value

oracle_gi_cluster_type: STANDARD

oracle_gi_gns_subdomain

Define ths GNS subdomain for Cluster

oracle_gi_gns_vip

Define GNS VIP for Clusterware.

Default value

oracle_gi_gns_vip:

oracle_gi_nic_priv

Name of private network interface.

Default value

oracle_gi_nic_priv: eth1

oracle_gi_nic_pub

Name of public network interface.

Default value

oracle_gi_nic_pub: eth0

oracle_ic_net

Defines the network for the interconnect.

Important!

Only used, when configure_interconnect=true and ansible_os_family='RedHat' during cluster installations.

Default value

oracle_ic_net: 3.3.3.{{ ansible_all_ipv4_addresses[0].split(".")[-1] }}

oracle_scan

SCAN DNS-Name

oracle_scan_port

Default value

oracle_scan_port: 1521

oracle_sw_image_gi

List of version sepcific GI installation images

NOTE: Image files are expected to be found by their filename under oracle_sw_source_local, or oracle_sw_source_www respectively, unless a filesource dict element provides a full path / complete URL to the image file.

Default value

oracle_sw_image_gi:
  - {filename: LINUX.X64_2326100_grid_home.zip, version: 26.1.0.0, creates: install/.img.bin}
  - {filename: LINUX.X64_213000_grid_home.zip, version: 21.3.0.0, creates: install/.img.bin}
  - {filename: LINUX.X64_193000_grid_home.zip, version: 19.3.0.0, creates: install/.img.bin}
  - {filename: LINUX.X64_180000_grid_home.zip, version: 18.3.0.0, creates: install/.img.bin}
  - {filename: linuxx64_12201_grid_home.zip, version: 12.2.0.1, creates: xdk/mesg/lsxja.msb}
  - {filename: linuxamd64_12102_grid_1of2.zip, version: 12.1.0.2, creates: grid/stage/sizes/oracle.crs.12.1.0.2.0.sizes.properties}
  - {filename: linuxamd64_12102_grid_2of2.zip, version: 12.1.0.2, creates: grid/install/.oui}
  - {filename: linuxamd64_12c_grid_1of2.zip, version: 12.1.0.1}
  - {filename: linuxamd64_12c_grid_2of2.zip, version: 12.1.0.1}

Example usage

oracle_sw_image_gi:
  # LINUX.X64_213000_grid_home.zip located under `oracle_sw_source_local`
  - {filename: LINUX.X64_213000_grid_home.zip, version: 21.3.0.0, creates: 'install/.img.bin'}
  # LINUX.X64_193000_grid_home.zip located under /mnt/images
  - {filename: LINUX.X64_193000_grid_home.zip, filesource: /mnt/images/LINUX.X64_193000_grid_home.zip, version: 19.3.0.0, creates: 'install/.img.bin'}
  # LINUX.X64_180000_grid_home.zip download
  - {filename: LINUX.X64_180000_grid_home.zip, filesource: https://downloadserver/images?id=180000_grid_home, version: 18.3.0.0, creates: 'install/.img.bin'}

oracle_vip

suffix added to hostnames for VIPs.

{{ ansible_hostname }}{{ oracle_vip }}

Important!

oracle_node_vip defines a fixed hostname for the VIP.

That replaces the logic from oracle_vip for the VIP!

Default value

oracle_vip: -vip

oraswgi_install_remove_obsolete_homes

Remove obsolete Grid Infrastructure homes of Oracle Restart with deinstall.

Obsolete homes are all Grid Infrastructure homes in the central inventory except crs_home in /etc/oracle/olr.loc and oracle_home_gi, e.g. the old home after an Out-of-Place Patching.

The removal is done only, when Oracle Restart runs from oracle_home_gi and deinstall -checkonly reports the home as not configured.

Homes, which are not registered in the central inventory, are not touched.

Default value

oraswgi_install_remove_obsolete_homes: false

run_configtoolallcommand

Run configtoolcommand during installation.

Do not disable this!

Default value

run_configtoolallcommand: true

Discovered Tags

always

asmfd

crsctl

cvuqdisk

directories

dsset

glogingi

nfsmountdb

nfsumountdb

opatchls

oragridinstall

oragridsw

oragridswunpack

responsefileconfigtool

responsefilegi

runcluvfy

runconfigtool

runroot

updatenodelist

Open Tasks

  • (bug): ConfigTools should not depend on olr.loc…
  • (bug): ConfigTools should not depend on olr.loc…
  • (bug): ConfigTools should not depend on olr.loc…
  • (information): add selectattr to asm_diskgroups
  • (information): Check if path for patches is ok with patch_id/patch_id
  • (information): add selectattr to asm_diskgroups
  • (information): Check if path for patches is ok with patch_id/patch_id
  • (information): add selectattr to asm_diskgroups
  • (information): Check if path for patches is ok with patch_id/patch_id

Dependencies

  • orahost_meta
  • orasw_meta
  • oraswgi_meta

License

license (MIT)

Author

Mikael Sandström, Thorsten Bruhns

3.8 - ahf_fleet_insights

Experimental: the role is under development. Breaking changes can happen at any time and are not always documented.

Install Oracle AHF Fleet Insights as central web interface for the evaluation of AHF data (Compliance results, TFA collections, Insights) from many database servers.

The AHF clients (role ahf with ahf_fleet_insights_client: true) upload their data to Fleet Insights. The database servers are not contacted for the evaluation.

Fleet Insights requires a repository database (19c or newer) with the schema user from create_db_user.sql of the installation media.

Fleet Insights has no systemd unit, its processes are started by cron entries of ahf_fi_install_user. The role starts Fleet Insights (ahffi start), when it is not running, and waits for the web application on ahf_fi_port.

See doc/guides/ahf.adoc.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

ahf_fi_cert_days

Validity of the generated certificate in days.

Default value

ahf_fi_cert_days: 730

ahf_fi_cert_file

Own certificate (PEM) for Fleet Insights on the Ansible controller, e.g. from an internal CA. Imported with ahffi importcert together with ahf_fi_cert_key_file. Empty: ahf_fi_cert_generate is used.

Default value

ahf_fi_cert_file: ''

ahf_fi_cert_generate

Create a self-signed certificate with Subject Alternative Names (ahf_fi_cert_names) and import it with ahffi importcert.

The certificate of the installer has no Subject Alternative Name. The AHF clients (AHF 26.x) check only the SAN and reject it with CERTIFICATE_VERIFY_FAILED ... Hostname mismatch. Ignored, when ahf_fi_cert_file is set.

Default value

ahf_fi_cert_generate: true

ahf_fi_cert_key_file

Private key (PEM) of ahf_fi_cert_file on the Ansible controller.

Default value

ahf_fi_cert_key_file: ''

ahf_fi_cert_names

DNS names for the Subject Alternative Name of the generated certificate. The clients must use one of them in ahf_fleet_insights_url. The first name is the CN.

Default value

ahf_fi_cert_names: '{{ [ansible_hostname, ansible_fqdn] | unique }}'

ahf_fi_clamscan

Path to clamscan for a virus scan of the uploaded collections (CLAMSCAN). Increases the processing time.

Default value

ahf_fi_clamscan: ''

ahf_fi_db_host

Hostname of the repository database (DB_HOST). Oracle Database 19c or newer.

Default value

ahf_fi_db_host: '{{ inventory_hostname }}'

ahf_fi_db_password

Password of ahf_fi_db_user (DB_PASSWORD). Use Ansible Vault.

Default value

ahf_fi_db_password: ''

ahf_fi_db_port

Listener port of the repository database (DB_PORT).

Default value

ahf_fi_db_port: 1521

ahf_fi_db_service

Service name of the repository database (DB_SERVICE).

Default value

ahf_fi_db_service: ''

ahf_fi_db_user

Schema user in the repository database (DB_USER). Create it with create_db_user.sql from the installation media.

Default value

ahf_fi_db_user: AHFFI

ahf_fi_db_wallet

Wallet for the connection to the repository database (DB_WALLET).

Default value

ahf_fi_db_wallet: ''

ahf_fi_firewall

Open ahf_fi_port in firewalld, when firewalld is running.

Default value

ahf_fi_firewall: true

ahf_fi_install_dir

Installation directory of Fleet Insights (INSTALL_DIR). Plan 4 GB per registered cluster.

Default value

ahf_fi_install_dir: '{{ oracle_base }}/ahffi'

ahf_fi_install_user

OS user for the installation and the processes of Fleet Insights. The installer fails with root.

Default value

ahf_fi_install_user: '{{ oracle_user }}'

ahf_fi_installer_archive

Filename of the installation media in the software repository (My Oracle Support Doc ID 3043060.1).

Empty (default): the newest file matching AHFFI-LINUX_v*.zip is used from oracle_sw_source_local on the Ansible controller or from oracle_stage_remote (oracle_sw_copy: false). Must be set for oracle_sw_source_www.

Default value

ahf_fi_installer_archive: ''

Example usage

ahf_fi_installer_archive: AHFFI-LINUX_v25.2.0.zip

ahf_fi_instant_client

Directory of Oracle Instant Client (INSTANT_CLIENT).

Default value

ahf_fi_instant_client: /usr/lib/oracle/23/client64

ahf_fi_instantclient_repo

Yum repository for Oracle Instant Client on Oracle Linux. Empty: no repository is configured.

Default value

ahf_fi_instantclient_repo: >-
  https://yum.oracle.com/repo/OracleLinux/OL{{ ansible_distribution_major_version }}/oracle/instantclient23/x86_64/

ahf_fi_java_home

Java home (Java 22 or newer) for Fleet Insights (JAVA_HOME).

Empty (default): the newest Oracle JDK in /usr/lib/jvm/jdk-*-oracle-x64 is used. The Oracle JDK RPM installs into a directory with the full version, e.g. /usr/lib/jvm/jdk-25.0.5.0.3-oracle-x64, which changes with every update.

Default value

ahf_fi_java_home: ''

ahf_fi_manage_packages

Install the required packages (ahf_fi_packages) and the yum repository for Oracle Instant Client (ahf_fi_instantclient_repo).

Default value

ahf_fi_manage_packages: true

ahf_fi_packages

Packages for Fleet Insights: cronie, iproute, hostname, Java 22 or newer and Oracle Instant Client Basic + SQL*Plus.

The Oracle JDK is used under the Oracle No-Fee Terms and Conditions (NFTC).

Default value

ahf_fi_packages:
  - cronie
  - iproute
  - hostname
  - https://download.oracle.com/java/25/latest/jdk-25_linux-x64_bin.rpm
  - oracle-instantclient-basic
  - oracle-instantclient-sqlplus

ahf_fi_port

Port of the web application (WEBAPP_PORT, 1024 - 49151). Must be reachable from all AHF clients and the browsers.

Default value

ahf_fi_port: 5005

ahf_fi_public_cert_fetch

Path on the Ansible controller for the public certificate of Fleet Insights (<ahf_fi_install_dir>/ahf_service/certs/cert.pem, self-signed by the installer). The AHF clients need it for the registration (role ahf: ahf_fleet_insights_public_cert). The certificate is also available as fact ahf_fi_public_cert. Empty: the certificate is not fetched.

Default value

ahf_fi_public_cert_fetch: ''

Example usage

ahf_fi_public_cert_fetch: "{{ inventory_dir }}/files/ahffi_cert.pem"

ahf_fi_registration_password

Password of ahf_fi_registration_user (GENERIC_REGISTRATION_PASSWORD). At least 8 characters with a digit, a special character and an uppercase letter. Use Ansible Vault.

Default value

ahf_fi_registration_password: ''

ahf_fi_registration_user

Generic registration user for the AHF clients (GENERIC_REGISTRATION_USER). Created by the installer, when user and password are set.

Default value

ahf_fi_registration_user: ''

ahf_fi_stage_dir

Directory on the target host for the installation media. The directory is removed after the installation, because the properties file contains passwords.

Default value

ahf_fi_stage_dir: '{{ oracle_stage }}/ahffi'

ahf_fi_start_timeout

Seconds to wait for the web application on ahf_fi_port after the installation or start. The role starts Fleet Insights (ahffi start), when ahffi status does not report it as running.

Default value

ahf_fi_start_timeout: 300

ahf_fi_upgrade

Patch an existing installation, when the installation media has a newer version.

Default value

ahf_fi_upgrade: true

ahf_fi_verify_signature

Verify the signature of the installation media with openssl.

Default value

ahf_fi_verify_signature: true

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.9 - orasw_meta_internal

Meta role used to store internal variables from ansible-oracle.

Do not use any of the variables in your inventory!

This will create issues and problems in ansible-oracle and is not supported.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

_db_password_cdb

The variable is internal used only.

Do not set it in inventory!

Default value

_db_password_cdb: _internal_used_

_db_password_pdb

The variable is internal used only.

Do not set it in inventory!

Default value

_db_password_pdb: _internal_used_

_db_service_name

The variable is internal used only.

Do not set it in inventory!

Default value

_db_service_name: _internal_used_

_db_service_pdb

The variable is internal used only.

Do not set it in inventory!

Get the service_name for a PDB.

Requires opdb as loop_var.

Default value

_db_service_pdb: _internal_used_

_db_unique_name_for_pdb

The variable is internal used only.

Do not set it in inventory!

get db_unique_name from CDB for current pdb Requires opdb as loop_var.

Default value

_db_unique_name_for_pdb: _internal_used_

_grid_env

The variable is used for shell, command tasks to set environment Variables.

Do not set it in inventory!

Default value

_grid_env:
  ORACLE_HOME: '{{ oracle_home_gi }}'
  LD_LIBRARY_PATH: '{{ oracle_home_gi }}/lib'

_listener_port_cdb

The variable is internal used only.

Do not set it in inventory!

Default value

_listener_port_cdb: _internal_used_

_listener_port_pdb

The variable is internal used only.

Do not set it in inventory!

Default value

_listener_port_pdb: _internal_used_

_odb_loop_helper

The variable is internal used only.

Do not set it in inventory!

Default value

_odb_loop_helper: _internal_used_

_odb_standby_archivelog_deletion_policy

The variable is internal used only.

Do not set it in inventory!

RMAN CONFIGURE ARCHIVELOG DELETION POLICY TO <value> of the current member: archivelog_deletion_policy of the member or of the configuration (mandatory, checked by orasw_meta).

Default value

_odb_standby_archivelog_deletion_policy: _internal_used_

_odb_standby_config

The variable is internal used only.

Do not set it in inventory!

Entry of db_standby_config referenced by standby_config of the current database (_odb_loop_helper). Empty dictionary for a database without standby_config.

Default value

_odb_standby_config: _internal_used_

_odb_standby_create_method

The variable is internal used only.

Do not set it in inventory!

Method for the creation of the standby database of the current member: create_method of the member, of the configuration or rman_duplicate_active.

Default value

_odb_standby_create_method: _internal_used_

_odb_standby_member

The variable is internal used only.

Do not set it in inventory!

Member of _odb_standby_config for the current database and host: member with inventory_hostname in hosts, db_unique_name decides when more than 1 member matches. Empty dictionary when no or more than 1 member matches (checked by the asserts in orasw_meta).

Default value

_odb_standby_member: _internal_used_

_odb_standby_others

The variable is internal used only.

Do not set it in inventory!

All other members of _odb_standby_config (without _odb_standby_member).

Default value

_odb_standby_others: _internal_used_

_opdb_home

Default value

_opdb_home: "{{ (oracle_databases | selectattr('oracle_db_name', 'equalto', _opdb_loop_helper['cdb']))[0]['home'] }}"

_opdb_loop_helper

The variable is internal used only.

Do not set it in inventory!

Default value

_opdb_loop_helper: _internal_used_

_oracle_all_editions_options

Defines linkable options available for all editions of oracle database (e.g. Unified auditing, DirectNFS) Dictionary key (dnfs, uniaud, etc.), suffixed by _on/_off, must match the make target in {{ oracle_home_db }}/rdbms/lib/ins_rdbms.mk match_file: File relative to {{ oracle_home_db }} where to grep for current state of the option enabled_matches: Pattern that matches in match_file if option currently is enabled

_oracle_db_instance_name

The variable is internal used only.

Do not set it in inventory!

Default value

_oracle_db_instance_name: _internal_used_

_oracle_db_unique_name

The variable is internal used only.

Do not set it in inventory!

Default value

_oracle_db_unique_name: _internal_used_

_oracle_ee_opiton_dict

This is an internal variable in ansible-oracle.

IMPORTANT

Do not set this variable in inventory, set_fact …!

Default value

_oracle_ee_opiton_dict:
  11.2.0.4: '{{ oracle_ee_options_112 }}'
  12.1.0.1: '{{ oracle_ee_options_121 }}'
  12.1.0.2: '{{ oracle_ee_options_121 }}'
  12.2.0.1: '{{ oracle_ee_options_122 }}'
  18.3.0.0: '{{ oracle_ee_options_183 }}'
  19.3.0.0: '{{ oracle_ee_options_193 }}'
  21.3.0.0: '{{ oracle_ee_options_213 }}'
  26.1.0.0: '{{ oracle_ee_options_261 }}'

This is an internal variable in ansible-oracle.

Maps the chopt option names from oracle_ee_options_* to the make target in $ORACLE_HOME/rdbms/lib/ins_rdbms.mk (suffixed by _on/_off) and to the object in libknlopt.a, which is present when the option is enabled. All options are linked by one make call with a single ioracle at the end.

IMPORTANT

Do not set this variable in inventory, set_fact …!

Default value

_oracle_ee_options_link:
  oaa:
    make_target: dm
    match_file: rdbms/lib/libknlopt.a
    enabled_matches: \bdmwdm\.
  olap:
    make_target: olap
    match_file: rdbms/lib/libknlopt.a
    enabled_matches: \bxsyeolap\.
  partitioning:
    make_target: part
    match_file: rdbms/lib/libknlopt.a
    enabled_matches: \bkkpoban\.
  rat:
    make_target: rat
    match_file: rdbms/lib/libknlopt.a
    enabled_matches: \bkecwr\.

_oracle_ee_options_valid

This is an internal variable in ansible-oracle.

Options from _oracle_ee_options_link, which are valid for a release. Same as the options in $ORACLE_HOME/bin/chopt.ini. 26ai has no oaa and olap anymore.

IMPORTANT

Do not set this variable in inventory, set_fact …!

Default value

_oracle_ee_options_valid:
  19.3.0.0: [oaa, olap, partitioning, rat]
  21.3.0.0: [oaa, olap, partitioning, rat]
  26.1.0.0: [partitioning, rat]

_oracle_env

The variable is used for shell, command tasks to set environment Variables.

Do not set it in inventory!

Default value

_oracle_env:
  ORACLE_HOME: '{{ _oracle_home_db }}'
  LD_LIBRARY_PATH: '{{ _oracle_home_db }}/lib'

_oracle_env_pdb

Default value

_oracle_env_pdb:
  ORACLE_HOME: '{{ _oracle_home_db_pdb }}'
  LD_LIBRARY_PATH: '{{ _oracle_home_db_pdb }}/lib'

_oracle_home_db

This is an internal variable in ansible-oracle.

Do not set it in inventory!

Default value

_oracle_home_db: _internal_used_

_oracle_home_db_pdb

Default value

_oracle_home_db_pdb: "{{ db_homes_config[_opdb_home]['oracle_home'] }}"

_orasw_meta_standby_sid

The variable is internal used only.

Do not set it in inventory!

ORACLE_SID of the current database (_odb_loop_helper).

Default value

_orasw_meta_standby_sid: _internal_used_

cluster_master

Default value

cluster_master: '{{ ansible_play_batch[0] }}'

db_mode

Default value

db_mode: sysdba

db_password

Default value

db_password: >-
  {% if dbpasswords is defined
      and dbpasswords[item.oracle_db_name] is defined
      and dbpasswords[item.oracle_db_name][db_user] is defined -%}
    {{- dbpasswords[item.oracle_db_name][db_user] }}
  {%- else %}{{ default_dbpass }}
  {%- endif %}

db_service_name

Deprecated: since v4.0.0

Default value

db_service_name: '{% if item is defined -%} {%- if item.oracle_db_unique_name is defined -%}{{ item.oracle_db_unique_name }}{%- elif item.oracle_db_instance_name is defined -%}{{ item.oracle_db_instance_name }}{%- else -%}{{ item.oracle_db_name }}{%- endif -%}{%- endif %}'

db_user

Default value

db_user: sys

db_version

This is an internal variable in ansible-oracle.

IMPORTANT

Do not set this variable in inventory, set_fact …!

Deprecated: since v4.0.0

Default value

db_version: _unset_

grid_env

The variable is used for shell, command tasks to set environment Variables.

Do not set it in inventory!

Deprecated: since v4.0.0

Default value

grid_env:
  ORACLE_HOME: '{{ oracle_home_gi }}'
  LD_LIBRARY_PATH: '{{ oracle_home_gi }}/lib'

listener_home

Deprecated: since v4.0.0

Default value

listener_home: "{%- if lsnrinst is defined -%}{%- if db_homes_config[lsnrinst.home]['oracle_home'] is defined -%}{{ db_homes_config[lsnrinst.home]['oracle_home'] }}{%- else -%}{{ oracle_base }}/{{ db_homes_config[lsnrinst.home]['version'] }}/{{ db_homes_config[lsnrinst.home]['home'] }}{%- endif -%}{%- endif -%}"

listener_port_template

Deprecated: since v4.0.0

Default value

listener_port_template: '{% if item.listener_port is defined %}{{ item.listener_port }}{% else %}{{ listener_port }}{% endif %}'

listener_protocols

Deprecated: since v4.0.0

Default value

listener_protocols: TCP

ocm_response_file

Default value

ocm_response_file: '{{ oracle_patch_stage }}/{{ db_version }}/ocm.rsp'

oracle_all_editions_options

Default value

oracle_all_editions_options:
  26.1.0.0: &261_all_editions_options
    dnfs:
      match_file: rdbms/lib/odm/libnfsodm??.so
      enabled_matches: .*
    uniaud:
      match_file: rdbms/lib/libknlopt.a
      enabled_matches: \bkzaiang\.
  21.3.0.0:
    <<: *261_all_editions_options
  19.3.0.0:
    <<: *261_all_editions_options
  18.3.0.0:
    <<: *261_all_editions_options
  12.2.0.1:
    <<: *261_all_editions_options
  12.1.0.2:
    <<: *261_all_editions_options
  12.1.0.1:
    <<: *261_all_editions_options
  11.2.0.4: &1124_all_editions_options
    dnfs:
      match_file: rdbms/lib/odm/libnfsodm??.so
      enabled_matches: .*
  11.2.0.3:
    <<: *1124_all_editions_options

oracle_env

The variable is used for shell, command tasks to set environment Variables.

Do not set it in inventory!

Deprecated: since v4.0.0

Default value

oracle_env:
  ORACLE_HOME: '{{ oracle_home_db }}'
  LD_LIBRARY_PATH: '{{ oracle_home_db }}/lib'

oracle_env_lsnrctl

The variable is used for shell, command tasks to set environment Variables.

Do not set it in inventory!

Deprecated: since v4.0.0

Default value

oracle_env_lsnrctl:
  ORACLE_BASE: '{{ oracle_base }}'
  ORACLE_HOME: '{{ listener_home }}'
  LD_LIBRARY_PATH: '{{ listener_home }}/lib'
  PATH: '{{ listener_home }}/bin:$PATH:/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin'

oracle_home_db

This is an internal variable in ansible-oracle.

The variable is deprecated and removed in a future version.

IMPORTANT

Do not set this variable in inventory, set_fact …!

Deprecated: since v4.0.0

Default value

oracle_home_db: _unset_

oracle_home_gi

Custom setting for CRS_HOME.

The default value depends on _oraswgi_meta_configure_cluster and oracle_home_gi_cl or oracle_home_gi_so.

Default value

oracle_home_gi: '{% if oracle_install_version_gi is defined -%}{%- if _oraswgi_meta_configure_cluster -%}{{ oracle_home_gi_cl }}{%- else -%}{{ oracle_home_gi_so }}{%- endif -%}{%- endif %}'

oracle_patch_install

Default value

oracle_patch_install: '{% if not oracle_sw_copy | bool and not oracle_sw_unpack | bool %}{{ oracle_patch_stage_remote }}{% else %}{{ oracle_patch_stage }}{% endif %}'

oracle_patch_stage

Default value

oracle_patch_stage: '{{ oracle_stage }}/patches'

oracle_patch_stage_remote

Default value

oracle_patch_stage_remote: '{{ oracle_stage_remote }}/patches'

oracle_stage_install

This is an internal variable. Do not set it in Inventory.

Default value

oracle_stage_install: '{% if not oracle_sw_copy | bool and not oracle_sw_unpack | bool %}{{ oracle_stage_remote }}{% else %}{{ oracle_stage }}{% endif %}'

oracle_sw_copy

Default value

oracle_sw_copy: '{{ not (install_from_nfs | bool) }}'

oracle_sw_extract_path

Default value

oracle_sw_extract_path: "{%- if '18' in db_version -%}{{ oracle_home_db }}{%- else -%}{{ oracle_stage }}/{{ item[0].version }}{%- endif -%}"

oracle_sw_unpack

Default value

oracle_sw_unpack: '{{ not (install_from_nfs | bool) }}'

Dependencies

None.

License

license (MIT)

Author

[Thorsten Bruhns]

3.10 - oraswdb_install

Install Oracle Database Software

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

autostartup_service

Force linking of all options from oracle_ee_options and oracle_all_editions_options_state in ORACLE_HOME.

The current state of an option is read from the libraries in ORACLE_HOME. Only options not in intended state are linked, all of them in one make call with a single relink of oracle (ioracle). true links all options, even when they are already in intended state.

configure_oracle_profile

Create .profile_-environment scripts for databases in oracle_databases.

Mandatory when listener_installed is defined, autostartup_service: true and autostartup_service_mode: legacy. Otherwise the listener will not start!

Default value

configure_oracle_profile: true

glogin_default_cdb

content of glogin.sql for CDB/PDB databases

Default value

glogin_default_cdb:
  - define gname=idle
  - column global_name new_value gname
  - set heading off
  - set termout off
  - col global_name noprint
  - select upper(sys_context ('userenv', 'instance_name') || ':' || sys_context('userenv', 'con_name')) global_name from dual;
  - set sqlprompt '_user @ &gname:>'
  - set heading on
  - set termout on
  - set time on

glogin_default_nocdb

Default value

glogin_default_nocdb:
  - set sqlprompt "_user @ _connect_identifier:>"
  - set time on

hostgroup

Default value

hostgroup: '{{ group_names[0] }}'

hostgroup_hub

Default value

hostgroup_hub: '{{ hostgroup }}-hub'

hostgroup_leaf

Default value

hostgroup_leaf: '{{ hostgroup }}-leaf'

hostinitdaemon

The start daemon of the OS.

Usually no need to change this value!

Default value

hostinitdaemon: '{{ ansible_service_mgr }}'

oracle_ee_options

Default value

oracle_ee_options: "{{ _oracle_ee_opiton_dict[db_homes_config[dbh.home]['version']] }}"

oracle_sw_image_db

Mapping for installation media for Oracle image files are expected to be found by their filename under oracle_sw_source_local, or oracle_sw_source_www respectively, unless a filesource dict element provides a full path / complete URL to the patch file.

Formerly, this dict was defined directly as vars/_oraswdb_install_oracle_sw_image_db, where it still will be copied to for compatibility reasons

Default value

oracle_sw_image_db:
  - {filename: LINUX.X64_2326100_db_home.zip, version: 26.1.0.0, creates: install/.img.bin}
  - {filename: LINUX.X64_213000_db_home.zip, version: 21.3.0.0, creates: install/.img.bin}
  - {filename: LINUX.X64_193000_db_home.zip, version: 19.3.0.0, creates: install/.img.bin}
  - {filename: LINUX.X64_180000_db_home.zip, version: 18.3.0.0, creates: install/.img.bin}
  - {filename: linuxx64_12201_database.zip, version: 12.2.0.1, creates: database/runInstaller}
  - {filename: linuxamd64_12102_database_1of2.zip, version: 12.1.0.2, creates: database/stage/sizes/oracle.server.Custom.sizes.properties}
  - {filename: linuxamd64_12102_database_2of2.zip, version: 12.1.0.2, creates: database/install/.oui}
  - {filename: linuxamd64_12c_database_1of2.zip, version: 12.1.0.1, creates: database/runInstaller}
  - {filename: linuxamd64_12c_database_2of2.zip, version: 12.1.0.1, creates: database/runInstaller}
  - {filename: p13390677_112040_Linux-x86-64_1of7.zip, version: 11.2.0.4, creates: database/install/resource/cons_zh_TW.nls}
  - {filename: p13390677_112040_Linux-x86-64_2of7.zip, version: 11.2.0.4, creates: database/stage/Components/oracle.db/11.2.0.4.0/1/DataFiles/filegroup18.jar}
  - {filename: p10404530_112030_Linux-x86-64_1of7.zip, version: 11.2.0.3, creates: database/readme.html}
  - filename: p10404530_112030_Linux-x86-64_2of7.zip
    version: 11.2.0.3
    creates: database/stage/Components/oracle.sysman.console.db/11.2.0.3.0/1/DataFiles/filegroup2.jar

Example usage

oracle_sw_image_db:
  - {filename: LINUX.X64_2326100_db_home.zip, version: 26.1.0.0, creates: 'install/.img.bin'}
  - {filename: LINUX.X64_213000_db_home.zip, version: 21.3.0.0, creates: 'install/.img.bin'}
  - {filename: LINUX.X64_193000_db_home.zip, version: 19.3.0.0, creates: 'install/.img.bin', filesource: /mnt/software/LINUX.X64_193000_db_home.zip}
  - {filename: LINUX.X64_180000_db_home.zip, version: 18.3.0.0, creates: 'install/.img.bin', filesource: "https://downloadserver/dbsw?version=18.3.0.0"}
  - {filename: linuxx64_12201_database.zip, version: 12.2.0.1, creates: 'database/runInstaller'}
  - {filename: linuxamd64_12102_database_1of2.zip, version: 12.1.0.2, creates: 'database/stage/sizes/oracle.server.Custom.sizes.properties'}
  - {filename: linuxamd64_12102_database_2of2.zip, version: 12.1.0.2, creates: 'database/install/.oui'}
  - {filename: linuxamd64_12c_database_1of2.zip, version: 12.1.0.1, creates: 'database/runInstaller'}
  - {filename: linuxamd64_12c_database_2of2.zip, version: 12.1.0.1, creates: 'database/runInstaller'}
  - {filename: p13390677_112040_Linux-x86-64_1of7.zip, version: 11.2.0.4, creates: 'database/install/resource/cons_zh_TW.nls'}
  - {filename: p13390677_112040_Linux-x86-64_2of7.zip, version: 11.2.0.4, creates: 'database/stage/Components/oracle.db/11.2.0.4.0/1/DataFiles/filegroup18.jar'}
  - {filename: p10404530_112030_Linux-x86-64_1of7.zip, version: 11.2.0.3, creates: 'database/readme.html'}
  - filename: p10404530_112030_Linux-x86-64_2of7.zip
    version: 11.2.0.3
    creates: 'database/stage/Components/oracle.sysman.console.db/11.2.0.3.0/1/DataFiles/filegroup2.jar'

oraswdb_install_forcechopt

Default value

oraswdb_install_forcechopt: false

oraswdb_install_remove_install_images

Remove installation media from staging after installation when oracle_sw_copy: true.

Default value

oraswdb_install_remove_install_images: true

Discovered Tags

always

assert

autostartup_service

checkdbswinstall

create_db,dotprofile_db

dbchopt

directoriesdb

existing_dbhome

glogindb

install_home

nfsmountdb

nfsumountdb

opatchls

oradbinstall

oradbinstall,dbchopt

oradbsw

oradbswunpack

orainst

responsefileswdb

roohctl

runroot

seclimit

Open Tasks

  • (information): hostgroup, hostgroup_hub, hostgroup_leaf needs some more tests

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

[Mikael Sandström]

3.11 - oradb_rman

Oracle RMAN Backup for ansible-oracle

Please use only oradb_rman_ variables from role oradb_rman.

All other role variables from oradb_rman are deprecated and will be removed in a future release.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oradb_rman_assert_control_file_record_keep_time

Assert control_file_record_keep_time in init_parameters of databases with rman_jobs (state: present, sid: '*').

With the retention policy RECOVERY WINDOW OF <n> DAYS the value must be >= <n>. Otherwise the controlfile reuses the records of backups, which are needed by RMAN without catalog.

Default value

oradb_rman_assert_control_file_record_keep_time: true

oradb_rman_autofs

Configure autofs for RMAN Backups?

Default value

oradb_rman_autofs: '{{ rmanautofs | default(false) }}'

oradb_rman_channel_disk_default

Defines the format for disk target in RMAN-Templates from role.

Used for CONFIGURE CHANNEL DEVICE TYPE DISK <value> => the value starts with format.

Default value

oradb_rman_channel_disk_default: >-
  {% set __channel_disk_default = "format '/u10/rmanbackup/%d/%d_%T_%U'" -%}
  {{ rman_channel_disk_default | default(__channel_disk_default) -}}

oradb_rman_controlfile_autobackup_disk_default

Defines the contolfile autobackup target directory for the RMAN-Templates from role.

Default value

oradb_rman_controlfile_autobackup_disk_default: >-
  {% set __autobackup_disk_default = "'/u10/rmanbackup/%d/%d_%F'" -%}
  {{ rman_controlfile_autobackup_disk_default | default(__autobackup_disk_default) -}}

oradb_rman_cron_mkjob

Add mk-job to all cronjobs in /etc/cron.d for RMAN backups.

This is only needed when RMAN backups are monitored by checkmk.

Default value

oradb_rman_cron_mkjob: '{{ rman_cron_mkjob | default(false) }}'

oradb_rman_cronfile

Name for file for crontab in /etc/cron.d

Default value

oradb_rman_cronfile: oracle_rman_ansible

oradb_rman_log_dir

Lgofiledirectory for rman_wrapper.sh.

Default value

oradb_rman_log_dir: "{{ rman_log_dir | default((odb.0 | default(odb)).rman_log_dir | default(oracle_base + '/rman/log')) }}"

oradb_rman_log_retention

Days to keep the logfiles of rman_backup.sh in oradb_rman_log_dir (RMAN_LOG_RETENTION).

rman_backup.sh writes one logfile per execution and removes the logfiles of the database and action, which are older than this number of days. 0 keeps all logfiles.

Default value

oradb_rman_log_retention: 30

oradb_rman_retention_policy_default

Defines the policy for the RMAN-Templates from role.

Default value

oradb_rman_retention_policy_default: "{{ rman_retention_policy_default | default('RECOVERY WINDOW OF 14 DAYS') }}"

oradb_rman_script_dir

Directory for *.rman-Files.

Default value

oradb_rman_script_dir: "{{ rman_script_dir | default((odb.0 | default(odb)).rman_script_dir | default(oracle_base + '/rman')) }}"

oradb_rman_tns_admin

TNS_ADMIN for rman_wrapper.sh. This is needed for RMAN-Catalogconnections.

Default value

oradb_rman_tns_admin: "{{ rman_tns_admin | default(oracle_base + '/rman/network/admin') }}"

oradb_rman_tnsnames_installed

Defines custom entries in tnsnames.ora in oradb_rman_tns_admin.

Format is same as tnsnames_installed.

Example usage

oradb_rman_tnsnames_installed:
  - home: db19-si-ee
    tnsname: orclpdb
    state: present

oradb_rman_wallet_loc

Directory for Oracle wallet.

Default value

oradb_rman_wallet_loc: "{{ rman_wallet_loc | default(oracle_base + '/rman/network/wallet') }}"

oradb_rman_wallet_password

Password for Orale wallet.

Default value

oradb_rman_wallet_password: "{{ rman_wallet_password | default('oracleWallet1') }}"

Discovered Tags

always

assert

assert_rman_tns_admin

autofs

notest

rmancfg

rmancopy

rmancron

rmanexecute

rmanregister

tns

wallet

wallet_contents

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.12 - oradb_standby

Creates standby databases for the standby configurations in db_standby_config.

The method for the creation is selected with create_method in db_standby_config:

  • rman_duplicate_active: RMAN DUPLICATE ... FOR STANDBY FROM ACTIVE DATABASE (default)
  • external: the standby database is created outside of ansible-oracle
  • custom: tasks file from create_tasks_file

The inventory structure is described in doc/guides/standby_databases.adoc.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oradb_standby_broker_create

Create the Data Guard Broker configuration with dgmgrl.cfg on the host of the primary database, when no broker configuration exists and all other members are physical standby databases.

false: dgmgrl.cfg is created on all members, but not executed.

Default value

oradb_standby_broker_create: true

oradb_standby_rman_compressed

Use USING COMPRESSED BACKUPSET for DUPLICATE ... FROM ACTIVE DATABASE. false uses USING BACKUPSET.

Default value

oradb_standby_rman_compressed: true

oradb_standby_rman_logdir

Directory for the logfiles of RMAN DUPLICATE.

Default value

oradb_standby_rman_logdir: '{{ oracle_base }}/cfgtoollogs/oradb_standby'

oradb_standby_rman_parallel

Number of RMAN channels on the primary and on the standby database for create_method: rman_duplicate_active.

Default value

oradb_standby_rman_parallel: 2

oradb_standby_start_apply

Start Redo Apply (RECOVER MANAGED STANDBY DATABASE DISCONNECT) after the creation of the standby database.

Default value

oradb_standby_start_apply: true

Discovered Tags

oradb_standby

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

  • Thorsten Bruhns

3.13 - common

sets up the host generic stuff

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

common_packages

This is an internal variable only. Do not define it!

Default value

common_packages: _unset_

common_packages_el10

List of RPMs for RHEL10 or OL10

Default value

common_packages_el10:
  - bc
  - binutils
  - elfutils-libelf
  - fontconfig
  - glibc
  - glibc-devel
  - ksh
  - libaio
  - libgcc
  - libibverbs
  - libstdc++
  - libvirt-libs
  - libxcb
  - libX11
  - libXau
  - libXi
  - libXrender
  - libXtst
  - libxcrypt-compat
  - make
  - policycoreutils
  - policycoreutils-python-utils
  - smartmontools
  - sysstat
  - xz-devel
  - acl
  - autofs
  - bind-utils
  - ethtool
  - expect
  - git
  - grubby
  - initscripts
  - libaio-devel
  - libnsl
  - libstdc++-devel
  - lsof
  - lvm2
  - module-init-tools
  - nc
  - net-tools
  - nfs-utils
  - openssh-clients
  - pam
  - parted
  - procps
  - psmisc
  - python3
  - python3-pip
  - python3-packaging
  - rlwrap
  - tar
  - unzip
  - util-linux-ng
  - xfsprogs

common_packages_el6

List of RPMs for RHEL6 or OL6

Default value

common_packages_el6:
  - screen
  - facter
  - procps
  - module-init-tools
  - ethtool
  - lsof
  - bc
  - nc
  - bind-utils
  - nfs-utils
  - make
  - sysstat
  - unzip
  - openssh-clients
  - compat-libcap1
  - collectl
  - rlwrap
  - tigervnc-server
  - ntp
  - expect
  - git
  - lvm2
  - xfsprogs
  - btrfs-progs
  - tmux
  - python-devel
  - python-pip
  - libselinux-python
  - twm
  - autofs
  - parted
  - ksh

common_packages_el7

List of RPMs for RHEL7 or OL7

Default value

common_packages_el7:
  - screen
  - facter
  - procps
  - module-init-tools
  - ethtool
  - lsof
  - bc
  - nc
  - bind-utils
  - nfs-utils
  - make
  - sysstat
  - unzip
  - openssh-clients
  - compat-libcap1
  - collectl
  - rlwrap
  - tigervnc-server
  - ntp
  - expect
  - git
  - lvm2
  - xfsprogs
  - btrfs-progs
  - python-devel
  - python-pip
  - libselinux-python
  - autofs
  - parted
  - mlocate
  - ksh
  - psmisc
  - grubby

common_packages_el8

List of RPMs for RHEL8 or OL8

Default value

common_packages_el8:
  - facter
  - procps
  - module-init-tools
  - ethtool
  - lsof
  - bc
  - binutils
  - elfutils-libelf
  - elfutils-libelf-devel
  - fontconfig-devel
  - glibc
  - glibc-devel
  - ksh
  - libaio
  - libaio-devel
  - libXrender
  - libX11
  - libXau
  - libXi
  - libXtst
  - libgcc
  - libnsl
  - librdmacm
  - libstdc++
  - libstdc++-devel
  - libxcb
  - libibverbs
  - make
  - smartmontools
  - sysstat
  - nc
  - bind-utils
  - nfs-utils
  - unzip
  - openssh-clients
  - rlwrap
  - tigervnc-server
  - expect
  - git
  - lvm2
  - xfsprogs
  - autofs
  - parted
  - mlocate
  - psmisc
  - python3
  - python3-pip
  - grubby

common_packages_el9

List of RPMs for RHEL9 or OL9

Default value

common_packages_el9:
  - autofs
  - bind-utils
  - binutils
  - ethtool
  - expect
  - facter
  - fontconfig
  - git
  - glibc
  - glibc-devel
  - grubby
  - initscripts
  - ksh
  - libaio
  - libaio-devel
  - libgcc
  - libnsl
  - libstdc++
  - libstdc++-devel
  - lsof
  - lvm2
  - make
  - mlocate
  - module-init-tools
  - nc
  - net-tools
  - nfs-utils
  - openssh-clients
  - pam
  - parted
  - policycoreutils
  - policycoreutils-python-utils
  - procps
  - psmisc
  - python3
  - python3-pip
  - python3-packaging
  - rlwrap
  - smartmontools
  - sysstat
  - tar
  - unzip
  - util-linux-ng
  - xfsprogs
  - xorg-x11-utils
  - xorg-x11-xauth

common_packages_sles

List of RPMs for SuSE Linux Enterprise Server

Default value

common_packages_sles:
  - screen
  - procps
  - module-init-tools
  - ethtool
  - bc
  - bind-utils
  - make
  - sysstat
  - unzip
  - chrony
  - expect
  - lvm2
  - autofs

configure_epel_repo

Default value

configure_epel_repo: true

configure_motd

Configure Message of the day

Default value

configure_motd: true

configure_ntp

Configure ntpd or chrony on target system. The chrony or ntp is automatically chosen by ntp_type.

Default value

configure_ntp: true

configure_public_yum_repo

Default value

configure_public_yum_repo: true

epel10_rpm

URL for epel-release-latest-10.noarch.rpm

Default value

epel10_rpm: oracle-epel-release-el10

epel6_rpm

Url for epel-release-latest-6.noarch.rpm

Default value

epel6_rpm: https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm

epel7_rpm

Url for epel-release-latest-7.noarch.rpm

Default value

epel7_rpm: https://archives.fedoraproject.org/pub/archive/epel/7/x86_64/Packages/e/epel-release-7-14.noarch.rpm

epel8_rpm

Url for epel-release-latest-8.noarch.rpm

Default value

epel8_rpm: https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm

epel9_rpm

Url for epel-release-latest-9.noarch.rpm

Default value

epel9_rpm: oracle-epel-release-el9

http_proxy

Define the http proxy for downloads

Default value

http_proxy: ''

https_proxy

Define the https proxy for downloads

Default value

https_proxy: ''

install_os_packages

Default value

install_os_packages: true

motd_template

Used templatename for Message of the day

Default value

motd_template: motd.j2

no_proxy

Define no_proxy list für downlads.

Default value

no_proxy: ''

ntp_type

This is an internal variable only. Do not define it!

Default value

ntp_type: _unset_

ol6_repo_file

The variable is used to cleanup the yum repolist for old installations.

Default value

ol6_repo_file: public-yum-ol6.repo

ol7_repo_file

The variable is used to cleanup the yum repolist for old installations.

Default value

ol7_repo_file: public-yum-ol7.repo

proxy_env

This is an internal variable for downloading patches. Usually no need to change it.

Default value

proxy_env:
  http_proxy: '{{ http_proxy }}'
  https_proxy: '{{ https_proxy }}'
  no_proxy: '{{ no_proxy }}'

use_proxy

Enable Proxy for Download

Default value

use_proxy: false

Discovered Tags

common_assert

commonpackages

epelrepo

motd

olrepo

Dependencies

  • global_handlers

License

license (MIT)

Author

[Mikael Sandström]

3.14 - pyoracledb

Install python-oracledb with pip.

python-oracledb is the successor of cx_Oracle and is used by the modules of ansible-oracle. The role replaces the removed role cxoracle.

This role has a dependency to orasw_meta.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

pyoracledb_extra_args

Define optional arguments for extra_args during pip installation. The variable is used by pyoracledb_use_proxy and pyoracledb_http_proxy and supports client certificates known from orasw_meta. Set it for other pip options, e.g. --index-url=https://pypi.example.com/simple for an internal mirror.

Default value

pyoracledb_extra_args: ''

pyoracledb_http_proxy

Define the http_proxy for the pip installation.

Needed when pyoracledb_use_proxy: true.

Example usage

pyoracledb_http_proxy: proxy.example:3128

pyoracledb_install

Install python-oracledb?

Default value

pyoracledb_install: true

pyoracledb_umask

Define umask for pip installation of python-oracledb

pyoracledb_use_proxy

Use a http_proxy for the pip installation

Default value

pyoracledb_use_proxy: false

pyoracledb_version

Version of python-oracledb for Python versions without an own variable pyoracledb_version_py<major><minor>.

The version is updated by renovate. The version is selected with the Python version of the target host (ansible_python_interpreter).

Default value

pyoracledb_version: 26.1.0

pyoracledb_version_py36

Version of python-oracledb for Python 3.6 (Oracle Linux / RHEL 8, SLES 15). Last release for Python 3.6, not updated by renovate.

Default value

pyoracledb_version_py36: 1.4.2

pyoracledb_version_py37

Version of python-oracledb for Python 3.7. Last release for Python 3.7, not updated by renovate.

Default value

pyoracledb_version_py37: 2.3.0

pyoracledb_version_py38

Version of python-oracledb for Python 3.8. Last release for Python 3.8, not updated by renovate.

Default value

pyoracledb_version_py38: 3.0.0

pyoracledb_version_py39

Version of python-oracledb for Python 3.9 (Oracle Linux / RHEL 9). Last release for Python 3.9, not updated by renovate.

Default value

pyoracledb_version_py39: 4.0.2

pyoracledb_wheel_dir

Directory with wheel files of python-oracledb for an installation without the Python package index.

pip selects the wheel file matching the Python version of the target host (pip install --no-index --find-links <pyoracledb_wheel_dir> oracledb==<version>), so one directory can contain the wheel files for all Python versions (e.g. cp36 and cp39).

  • local directory on the Ansible controller, copied to <oracle_stage>/pyoracledb on the target host when is_sw_source_local: true and oracle_sw_copy: true. With oracle_sw_copy: false the directory must exist on the target host (e.g. NFS).
  • URL (http://, https://) of a page with links to the wheel files, used directly by pip

The role ensures pip >= 19.3 (needed for manylinux2014 wheels, the system pip of OL8 is 9.0.3). Add a pip wheel to the directory for target hosts with an older pip, e.g. pip-21.3.1-py3-none-any.whl for Python 3.6.

Download the wheel files on a host with access to the package index, e.g.: pip download --no-deps --only-binary=:all: --python-version 3.9 --platform manylinux2014_x86_64 -d <dir> oracledb==4.0.2

Example usage

pyoracledb_wheel_dir: /sw/python-oracledb

Discovered Tags

pyoracledb

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.15 - orahost

Role to configure the hostsystem for ansible-oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

asmlib_rpm

Install oracleasm-support from RPM-Repo on OracleLinux. Value depends on OS-Release from RHEL/OL. Uses variables asmlib_rpm_el6, asmlib_rpm_el7 or asmlib_rpm_el8

Default value

asmlib_rpm: Value from `asmlib_rpm_el6`, `asmlib_rpm_el7` or `asmlib_rpm_el8`

asmlib_rpm_el6

Name / Url for rpm oracleasm-support for RHEL6/OL6.

Default value

asmlib_rpm_el6: http://download.oracle.com/otn_software/asmlib/oracleasmlib-2.0.4-1.el6.x86_64.rpm

asmlib_rpm_el7

Name / Url for rpm oracleasm-support for RHEL7/OL7.

Default value

asmlib_rpm_el7: http://download.oracle.com/otn_software/asmlib/oracleasmlib-2.0.12-1.el7.x86_64.rpm

asmlib_rpm_el8

Name / Url for rpm oracleasm-support for RHEL8/OL8.

Default value

asmlib_rpm_el8: https://download.oracle.com/otn_software/asmlib/oracleasmlib-2.0.17-1.el8.x86_64.rpm

asmlib_rpm_sles

Name / Url for rpm oracleasm-support for SLES.

Default value

asmlib_rpm_sles: http://oss.oracle.com/projects/oracleasm-support/dist/files/RPMS/sles12/amd64/2.1.8/oracleasm-support-2.1.8-1.SLE12.x86_64.rpm

asmlibsupport_rpm

Install oracleasmlib-support from RPM-Repo on OracleLinux. Value depends on OS-Release from RHEL/OL.

important

Do NOT set this variable.

Set the used variables asmlibsupport_rpm_el6, asmlibsupport_rpm_el7 or asmlibsupport_rpm_el8.

Default value

asmlibsupport_rpm: Value from `asmlibsupport_rpm_el6`, `asmlibsupport_rpm_el7` or `asmlibsupport_rpm_el8`

asmlibsupport_rpm_el6

Default value

asmlibsupport_rpm_el6: http://oss.oracle.com/projects/oracleasm-support/dist/files/RPMS/rhel6/amd64/2.1.8/oracleasm-support-2.1.8-1.el6.x86_64.rpm

asmlibsupport_rpm_el7

Default value

asmlibsupport_rpm_el7: https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracleasm-support-2.1.11-2.el7.x86_64.rpm

asmlibsupport_rpm_el8

Default value

asmlibsupport_rpm_el8: https://yum.oracle.com/repo/OracleLinux/OL8/latest/x86_64/getPackage/oracleasm-support-2.1.11-2.el8.x86_64.rpm

configure_etc_hosts

Add {{ ansible_hostname }} {{ ansible_fqdn }} to /etc/hosts`?

Default value

configure_etc_hosts: false

configure_hugepages

Configure Hugepages?

Default value

configure_hugepages: true

configure_hugepages_by

Defines if percent_hugepages or size_in_gb_hugepages is used to define the Hugepages. Allowed values: percentage or memory.

Default value

configure_hugepages_by: memory

Example usage

configure_hugepages_by: memory

configure_hugepages_by: percentage

configure_interconnect

Should the Interconnect network be configured by Ansible

Default value

configure_interconnect: false

configure_limits

Configure /etc/security.d/limits.d/99-oracle-limits.conf?

Default value

configure_limits: true

configure_limits_pam

Configure /etc/pam.d/limits?

Default value

configure_limits_pam: true

configure_oracle_sudo

Add oracle to sudoers for root.

Default value

configure_oracle_sudo: false

configure_ssh

Should passwordless ssh be configured between clusternodes. Only applicable to RAC-installs

Default value

configure_ssh: false

disable_firewall

Should the Linux firewall be disabled? Only applicable to RHEL/OL at the moment.

Default value

disable_firewall: false

disable_numa_boot

Disable numa support during boot.

Default value

disable_numa_boot: true

disable_selinux

Default value

disable_selinux: true

etc_hosts_entries

List of additional entries, optionally along with aliases, to be put into /etc/hosts. E.g. on non-DNS environments or if we don’t rely on DNS

Default value

etc_hosts_entries: []

Example usage

etc_hosts_entries:
  - fqdn: clusternode1.example.com
    ip: 192.168.1.1
  - fqdn: clusternode2.example.com
    ip: 192.168.1.2
    aliases:
      - myalias.example.com
would create following entries in /etc/hosts:
192.168.1.1 clusternode1  clusternode1.example.com
192.168.1.2 clusternode2  clusternode2.example.com  myalias.example.com

etc_hosts_ip

Set IP to 2nd Interface on virtualbox and 1st for all otehr installations

Default value

etc_hosts_ip: "{% if 'virtualbox' in ansible_virtualization_type %}{{ ansible_all_ipv4_addresses[1] }}{% else %}{{ ansible_default_ipv4.address }}{% endif %}"

extra_hugepages_per_instance

According to MOS KB151310’s hugepages_settings.sh we’ve to add 1 page per shm segment. Empirically, instances allocate 4 segments each on Linux. This overhead is considered when computing nr_hugepages_memory

Type: integer

Default value

extra_hugepages_per_instance: 4

extrarepos_disabled

List of disabled yum repos during installation for RHEL/OL.

Default value

extrarepos_disabled: '[]'

extrarepos_enabled

Default value

extrarepos_enabled: "{%- if ansible_distribution == 'OracleLinux' -%}ol{{ ansible_distribution_major_version }}_addons{%- else -%}{%- endif %}"

firewall_open_listener_ports

Should the Listener ports be opened on the Linux firewall? Only applicable to RHEL/OL at the moment.

Default value

firewall_open_listener_ports: true

firewall_service

Used firewall service in OS. Value depends on used Distribution and version.

Default value

firewall_service: firewalld or iptables

grid_users

grid OS-User

Default value

grid_users:
  - username: grid
    uid: 54320
    primgroup: '{{ oracle_group }}'
    othergroups: '{{ asmadmin_group }},{{ asmdba_group }},{{ asmoper_group }},{{ dba_group }}'

host_fs_layout

Define physical Disk, Volume Group, logical Volume, Filesystem and swap Devices. See example configuration

Default value

host_fs_layout: '[]'

Example usage

host_fs_layout:
  - vgname: vgora
    state: present
    filesystem:
      - { mntp: /u01, lvname: lvorabase, lvsize: 25G, fstype: xfs }
      - { mntp: /u02, lvname: lvoradata, lvsize: 25G, fstype: xfs, fsopts: "-m reflink=1 -m crc=1" }
    disk:
      - { device: /dev/sdb, pvname: /dev/sdb1 }

install_os_packages

Install addional RPMs for Oracle?

Default value

install_os_packages: true

keyfile

Default value

keyfile: /tmp/known_hosts

max_size_in_gb_hugepages

Cap HugePages to 70% of physical memory to prevent overcomitting. Only valid when configure_hugepages_by: memory

Default value

max_size_in_gb_hugepages: '{{ ansible_memtotal_mb / 1024 * 0.7 }}'

nr_hugepages

This is an internal variable only. Do not define it!

Default value

nr_hugepages: _unset_

nr_hugepages_memory

This is an internal variable only. Do not define it!

Default value

nr_hugepages_memory: _unset_

nr_hugepages_percent

This is an internal variable only. Do not define it!

Default value

nr_hugepages_percent: _unset_

old_ssh_config

Default value

old_ssh_config: true

oracle_asm_packages

List of RPMs installed during ASM preparation for RHEL/OL.

There should be no reason to change this variable.

Default value

oracle_asm_packages:
  - '{{ asmlib_rpm }}'
  - '{{ asmlibsupport_rpm }}'
  - kmod-oracleasm

oracle_asm_packages_sles

List of RPMs installed during ASM preparation for SLES.

There should be no reason to change this variable.

Default value

oracle_asm_packages_sles:
  - oracleasm-kmp-default
  - oracleasm-kmp-xen
  - '{{ asmlib_rpm_sles }}'

oracle_extra_firewall_ports

Define additional ports to open on the OS firewall.

Default value

oracle_extra_firewall_ports: '[]'

Example usage

oracle_extra_firewall_ports:
  - 5500 # EM Express

oracle_groups

List of OS-groups for Oracle Dependent variables are defined in orahost_meta/defaults/main.yml

Default value

oracle_groups:
  - {group: '{{ asmdba_group }}', gid: 54318}
  - {group: '{{ asmoper_group }}', gid: 54319}
  - {group: '{{ asmadmin_group }}', gid: 54320}
  - {group: '{{ oracle_group }}', gid: 54321}
  - {group: '{{ dba_group }}', gid: 54322}
  - {group: '{{ oper_group }}', gid: 54324}
  - {group: backupdba, gid: 54323}
  - {group: dgdba, gid: 54325}
  - {group: kmdba, gid: 54326}

oracle_hugepages

This is an internal variable. Do not change it!

Default value

oracle_hugepages:
  - {name: vm.nr_hugepages, value: '{{ nr_hugepages }}'}
  - {name: vm.hugetlb_shm_group, value: "{{ oracle_user_getent['ansible_facts']['getent_passwd'][oracle_user][2] }}"}

oracle_hugepages_sysctl_file

Allows to specify the file in which sysctl settings for huge pages will be stored. When unspecified it will first fallback to be oracle_sysctl_file and then to module defaults (/etc/sysctl.conf) should that one also be not defined.

Default value

oracle_hugepages_sysctl_file: _unset_

Example usage

oracle_hugepages_sysctl_file: '/etc/sysctl.d/oracle-hugepages.conf'

oracle_ic_net

Picks the last octet from the public ip to use for cluster-interconnect ip (e.g 3.3.3.51)

Default value

oracle_ic_net: 3.3.3.{{ ansible_all_ipv4_addresses[0].split(".")[-1] }}

oracle_packages

List of additinal RPMs for RHEL/OL.

install_os_packages: true is needed to install the RPMs.

Default value

oracle_packages:
  - bind-utils
  - nfs-utils
  - util-linux-ng
  - xorg-x11-utils
  - xorg-x11-xauth
  - binutils
  - compat-libstdc++-33
  - compat-libstdc++-33.i686
  - unixODBC-devel
  - unixODBC-devel.i686
  - gcc
  - gcc-c++
  - glibc
  - glibc.i686
  - glibc-devel
  - glibc-devel.i686
  - libaio
  - libaio-devel
  - libaio.i686
  - libaio-devel.i686
  - libgcc
  - libgcc.i686
  - libstdc++
  - libstdc++-devel
  - libstdc++.i686
  - libstdc++-devel.i686
  - libXext
  - libXext.i686
  - zlib-devel
  - zlib-devel.i686
  - make
  - sysstat
  - openssh-clients
  - compat-libcap1
  - xorg-x11-xauth
  - xorg-x11-xinit
  - libXtst
  - xdpyinfo
  - xterm
  - xsetroot
  - libXp
  - libXt
  - libXau
  - libXau.i686
  - libXi
  - libXi.i686
  - libX11
  - libX11.i686
  - smartmontools
  - elfutils-libelf-devel.i686
  - elfutils-libelf-devel
  - cpp
  - lsof
  - compat-openssl11
  - fontconfig
  - glibc-langpack-en

oracle_packages_sles_multi

List of additinal RPMs for different SLES version.

List is based on: https://docs.oracle.com/en/database/oracle/oracle-database/19/ladbi/database-installation-guide-linux.pdf

install_os_packages: true is needed to install the RPMs.

Default value

oracle_packages_sles_multi:
  - name: SLES common packages
    condition: true
    packages:
      - bc
      - binutils
      - glibc
      - glibc-devel
      - libaio-devel
      - libaio1
      - libcap-ng-utils
      - libcap-ng0
      - libcap-progs
      - libcap2
      - libgcc_s1
      - libpcap1
      - libpcre1
      - libpcre16-0
      - libpng16-16
      - libstdc++6
      - libtiff5
      - libXau6
      - libXrender1
      - libXtst6
      - make
      - mksh
      - pixz
      - rdma-core
      - rdma-core-devel
      - smartmontools
      - sysstat
      - xorg-x11-libs
      - xz
  - name: SLES 12 packages
    condition: "{{ ansible_distribution_major_version == '12' }}"
    packages:
      - libcap1
      - libelf-devel
      - libjpeg-turbo
      - libjpeg62
      - libjpeg62-turbo
      - libX11
  - name: SLES 15 packages
    condition: "{{ ansible_distribution_major_version == '15' }}"
    packages:
      - insserv-compat
      - libelf1
      - libgfortran4
      - libjpeg8
      - libX11-6
      - libXext-devel
      - libXext6
      - libXi-devel
      - libXi6
      - libXrender-devel
  - name: SLES 15 SP3+ extra packages
    condition: "{{ ansible_distribution_version is version('15.3', 'ge') }}"
    packages:
      - compat-libpthread-nonshared

oracle_sysctl

Configure parameter in sysctl.

Important

Do not add configurations for Hugepages here!

Default value

oracle_sysctl:
  - {name: kernel.shmall, value: 4294967296}
  - {name: kernel.shmmax, value: 68719476736}
  - {name: kernel.shmmni, value: 4096}
  - {name: kernel.sem, value: 250 32000 100 128}
  - {name: fs.file-max, value: 6815744}
  - {name: fs.aio-max-nr, value: 3145728}
  - {name: net.ipv4.ip_local_port_range, value: 9000 65500}
  - {name: net.core.rmem_default, value: 262144}
  - {name: net.core.rmem_max, value: 4194304}
  - {name: net.core.wmem_default, value: 262144}
  - {name: net.core.wmem_max, value: 1048576}
  - {name: kernel.panic_on_oops, value: 1}
  - {name: vm.min_free_kbytes, value: 524288}

oracle_sysctl_file

Allows to specify the file in which sysctl settings will be stored. When unspecified it will be put to /etc/sysctl.conf by the module defaults (omit)

Default value

oracle_sysctl_file: _unset_

Example usage

oracle_sysctl_file: '/etc/sysctl.d/oracle.conf'

oracle_users

oracle OS-User

Default value

oracle_users:
  - username: oracle
    uid: 54321
    primgroup: '{{ oracle_group }}'
    othergroups: '{{ dba_group }},{{ asmadmin_group }},{{ asmdba_group }},{{ asmoper_group }},backupdba,dgdba,kmdba,{{ oper_group }}'

os_family_supported

Support is limited to RHE/OL and SuSE

Default value

os_family_supported: "{% if ansible_os_family == 'Suse' %}Suse{% else %}RedHat{% endif %}"

os_min_supported_version

Minimum supported versions for SLES is 12.1 and RHEL/OL >= 6.4

Default value

os_min_supported_version: "{% if ansible_os_family == 'Suse' %}12.1{% else %}6.4{% endif %}"

percent_hugepages

Define percentage from RAM for Hugepages. Only valud when configure_hugepages_by: percentage

Default value

percent_hugepages: 50

size_in_gb_hugepages

Size in GB for Hugepages. Only valud when configure_hugepages_by: memory

Default value

size_in_gb_hugepages: 1

ssh_keys

Default value

ssh_keys:
  - /tmp/id_rsa
  - /tmp/id_rsa.pub
  - /tmp/authorized_keys

sudoers_template

Used ansible template for sudoers configuration.

Default value

sudoers_template: sudoers.j2

transparent_hugepage_disable

Disable Transparent Hugepages during boot.

Important

It is strongly recommended to disable Transparent Hugepages. Do not change this variable.

Default value

transparent_hugepage_disable:
  - {disable: echo never >, path: /sys/kernel/mm/transparent_hugepage/enabled, rclocal: /etc/rc.d/rc.local}
  - {disable: echo never >, path: /sys/kernel/mm/transparent_hugepage/defrag, rclocal: /etc/rc.d/rc.local}

transparent_hugepage_disable_by_grub

Alternatively to dynamically disabling transparent hugepages using rc.local, disable transparent hugepages using kernel command line.

Note: Setting transparent_hugepage_disable_by_grub true obsoletes transparent_hugepage_disable

Default value

transparent_hugepage_disable_by_grub: false

Discovered Tags

always

asmlibconfig

etchosts

eth1

group

hostfs

hugepages

iptables,firewalld

molecule-idempotence-notest

nozeroconf

orahost_assert

os_packages, oscheck

os_packages, oscheck, asm1

oscheck

pamconfig

seclimit

selinux

sshkeys

stagedir

sudoadd

sysctl

tphnuma

tphnuma,molecule-idempotence-notest

user

Open Tasks

  • (improvement): SSH-Setup needs a rework…

Dependencies

  • global_handlers
  • orahost_meta

License

license (MIT)

Author

[Mikael Sandström]

3.16 - autoupgrade

Manage Oracle AutoUpgrade.

The role has no tasks/main.yml. Each area of AutoUpgrade has its own task file, which must be called with tasks_from:

Task file Description
assert.yml Check variables and Java
install.yml Install autoupgrade.jar into autoupgrade_home
download_patches.yml Download patches from My Oracle Support with AutoUpgrade
upgrade_analyze.yml Analyze phase for the Unplug/Plug upgrade of PDBs (oracle_pdbs): AutoUpgrade analyze
upgrade_fixups.yml Fixups phase: AutoUpgrade fixups in the source CDB/PDBs
upgrade_deploy.yml Unplug/Plug upgrade of PDBs: analyze phase + AutoUpgrade deploy

See doc/guides/autoupgrade_upgrade.adoc for the upgrade of PDBs.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

autoupgrade_download_dir

Value for global.download_folder. Downloaded patches are placed here.

Default value

autoupgrade_download_dir: '{{ oracle_sw_source_local }}'

autoupgrade_download_filename_regex

Regex for filename in oracle_sw_patches. Only matching entries are downloaded by AutoUpgrade (database patches for autoupgrade_download_platform).

Default value

autoupgrade_download_filename_regex: ^p[0-9]+_[0-9A-Za-z]+_Linux-x86-64\.zip$

autoupgrade_download_gold_image

Value for patch<n>.gold_image in the AutoUpgrade config file for all patch sections. Can be overwritten with attribute gold_image in autoupgrade_download_patches.

NO: no gold image is downloaded. AUTO, YES, ALL: see Oracle documentation for AutoUpgrade.

Empty: parameter is not written and the default from AutoUpgrade (AUTO) is used.

Default value

autoupgrade_download_gold_image: ''

Example usage

autoupgrade_download_gold_image: "NO"

autoupgrade_download_gold_image_latest

Create a symlink to the latest Gold Image of each release (autoupgrade_download_gold_image_rename: true).

The symlink is named autoupgrade_download_gold_image_prefix + major release + _latest.zip and points to the renamed Gold Image with the highest release update in autoupgrade_download_dir:

Renamed Gold Images Symlink
db_home_19.31.zip, db_home_19.32.zip db_home_19_latest.zip -> db_home_19.32.zip
db_home_26.03.zip, db_home_26.04.zip db_home_26_latest.zip -> db_home_26.04.zip

The symlink is changed only, when a newer Gold Image exists. The download of an older release update does not change the symlink.

Use the symlink as imagename in db_homes_config for an inventory independent of the release update.

Default value

autoupgrade_download_gold_image_latest: false

autoupgrade_download_gold_image_prefix

Prefix for the new filename of a Gold Image (autoupgrade_download_gold_image_rename: true).

Default value

autoupgrade_download_gold_image_prefix: db_home_

autoupgrade_download_gold_image_rename

Rename downloaded Gold Images after the download.

AutoUpgrade creates unique filenames with a timestamp, e.g. db_goldimage_19_32_20261021112350.zip. The file is renamed to autoupgrade_download_gold_image_prefix + release + .zip:

Gold Image (AutoUpgrade) Renamed file
db_goldimage_19_32_<timestamp>.zip (19.32) db_home_19.32.zip
db_goldimage_23_26_3_<timestamp>.zip (23.26.3) db_home_26.03.zip

A symlink with the original filename is created for the renamed file. AutoUpgrade finds the file under the original name and skips a new download. The symlinks can be removed for cleanup. They are not created again.

Release and filename are taken from patches_info.json in autoupgrade_download_dir. An existing file with the new name is never replaced.

Default value

autoupgrade_download_gold_image_rename: false

autoupgrade_download_latest

Download the latest autoupgrade.jar from autoupgrade_jar_url into the software repository before the installation.

The target depends on the location of the installation media:

Installation media Download to
oracle_sw_copy: true or autoupgrade_run_local: true Ansible controller (run_once, no become): autoupgrade_jar_filesource or oracle_sw_source_local/autoupgrade_jar. Requires is_sw_source_local: true.
oracle_sw_copy: false target host as oracle_user: autoupgrade_jar_filesource or oracle_stage_remote/autoupgrade_jar. The directory must exist and be writable for oracle_user.

Existing installations are only replaced with autoupgrade_force_update: true.

Default value

autoupgrade_download_latest: false

autoupgrade_download_patches

List of patches to download with download_patches.yml. Each element creates a patch<n> section in the AutoUpgrade config file.

Attribute Description
target_version mandatory: release, e.g. 19, 23
patch mandatory: e.g. RECOMMENDED or RU,OPATCH,OJVM,DPBP or RU:19.28,OPATCH
platform optional: default autoupgrade_download_platform
gold_image optional: NO, AUTO, YES, ALL - default autoupgrade_download_gold_image

Default value

autoupgrade_download_patches: []

Example usage

autoupgrade_download_patches:
  - target_version: 19
    patch: RU,OPATCH,OJVM,DPBP
  - target_version: 23
    patch: RECOMMENDED
    platform: LINUX.X64
  - target_version: 19
    patch: RU,OPATCH,OJVM,DPBP
    gold_image: "NO"

autoupgrade_download_platform

Default platform for the download, when platform is not set in autoupgrade_download_patches.

Default value

autoupgrade_download_platform: LINUX.X64

autoupgrade_download_supported_releases

Releases supported by AutoUpgrade for downloading patches.

Default value

autoupgrade_download_supported_releases: [19, 21, 23, 26]

autoupgrade_download_use_oracle_sw_patches

Use the same variables as role orasw_download_patches for the download:

  • oracle_sw_patches: each entry is added to the AutoUpgrade patch list of the release from version (e.g. 19.3.0.0 -> target_version=19). AutoUpgrade does not accept Release Updates by patch number. The keyword is derived:
Entry in oracle_sw_patches AutoUpgrade
attribute autoupgrade_patch value, e.g. RU:19.24, OJVM, DPBP
attribute ru_version (Release Update), e.g. 19.24.0.0.240716 RU:19.24
description contains OJVM OJVM
others patchid (one-off)
  • db_homes_installed / db_homes_config and oracle_install_version_gi (oracle_install_option_gi: CRS_CONFIG or HA_CONFIG): OPATCH is downloaded for each release

The result is added to autoupgrade_download_patches.

See autoupgrade_run_local for multiple hosts in the play. Only entries from oracle_sw_patches are used, where filename matches autoupgrade_download_filename_regex and the release from version is in autoupgrade_download_supported_releases. Others (e.g. APEX, cvupack) are ignored with a warning.

The My Oracle Support credentials (mos_username / mos_password) are read by AutoUpgrade from the keystore autoupgrade_keystore.

Default value

autoupgrade_download_use_oracle_sw_patches: true

autoupgrade_force_update

Update an existing autoupgrade.jar in the AutoUpgrade home.

false: An existing file is never replaced.

true: The file is replaced, when it differs from the file in the software repository.

Default value

autoupgrade_force_update: false

autoupgrade_home

Directory for autoupgrade.jar and the generated AutoUpgrade config files on the target host.

Default value

autoupgrade_home: '{{ oracle_base }}/product/autoupgrade'

autoupgrade_jar

Filename of AutoUpgrade. The file is expected under oracle_sw_source_local / oracle_sw_source_www.

On the Ansible controller the file is always taken from oracle_sw_source_local (is_sw_source_local: true) or oracle_sw_source_www - oracle_sw_copy is ignored.

Default value

autoupgrade_jar: autoupgrade.jar

autoupgrade_jar_filesource

If autoupgrade_jar is not placed under oracle_sw_source_local / oracle_sw_source_www, path can be forced using autoupgrade_jar_filesource instead. autoupgrade_jar_filesource must be the full path/URL, including the filename.

Example usage

autoupgrade_jar_filesource: /orasw/autoupgrade/autoupgrade.jar

autoupgrade_jar_url

URL for the latest version of AutoUpgrade (used by autoupgrade_download_latest).

Default value

autoupgrade_jar_url: https://download.oracle.com/otn-pub/otn_software/autoupgrade.jar

autoupgrade_java_home

JAVA_HOME used for AutoUpgrade on the target host. java from PATH is used, when autoupgrade_java_home is empty.

Default value

autoupgrade_java_home: ''

Example usage

autoupgrade_java_home: /u01/app/oracle/product/19/db1/jdk

autoupgrade_java_options

Additional Java options for each call of autoupgrade.jar, e.g. a truststore for a proxy with TLS inspection.

With proxy credentials (autoupgrade_proxy_username or credentials in https_proxy) -Djdk.http.auth.tunneling.disabledSchemes= is added automatically, because Java disables Basic authentication for HTTPS tunneling by default.

Default value

autoupgrade_java_options: []

Example usage

autoupgrade_java_options:
  - -Djavax.net.ssl.trustStore=/etc/pki/java/cacerts
  - -Djavax.net.ssl.trustStorePassword=changeit

autoupgrade_keystore

Value for global.keystore in the AutoUpgrade config files.

The keystore holds the My Oracle Support credentials (mos_username, mos_password) and is managed by keystore.yml (included by download_patches.yml).

Default value

autoupgrade_keystore: '{{ _autoupgrade_home }}/keystore'

autoupgrade_keystore_fail_on_invalid_credentials

Fail, when the credentials in the keystore cannot login into My Oracle Support.

Default value

autoupgrade_keystore_fail_on_invalid_credentials: true

autoupgrade_keystore_manage

Create/update the keystore with mos_username / mos_password in download_patches.yml.

false: The keystore must exist. It is not changed by the role.

Requires the Python module pexpect on the host executing AutoUpgrade.

Default value

autoupgrade_keystore_manage: true

autoupgrade_keystore_no_log

Hide the output of tasks with passwords for the keystore console. Set to false for debugging only!

Default value

autoupgrade_keystore_no_log: true

autoupgrade_keystore_password

Password for the AutoUpgrade keystore. At least 16 characters are required.

When autoupgrade_keystore_password is empty, the SHA256 hash of mos_password is used. When mos_password is changed, the keystore cannot be opened for changes anymore. The keystore is then removed and created again with the new credentials. The same happens, when autoupgrade_keystore_password is changed.

Default value

autoupgrade_keystore_password: ''

autoupgrade_keystore_recreate

Remove and create the keystore in each execution.

Default value

autoupgrade_keystore_recreate: false

autoupgrade_keystore_timeout

Timeout in seconds for each prompt of the keystore console. The console connects to My Oracle Support for checking the credentials.

Default value

autoupgrade_keystore_timeout: 300

autoupgrade_local_home

Directory for autoupgrade.jar and the generated AutoUpgrade config files on the Ansible controller (autoupgrade_run_local: true).

Default value

autoupgrade_local_home: "{{ lookup('ansible.builtin.env', 'HOME') }}/autoupgrade"

autoupgrade_local_java_home

JAVA_HOME used for AutoUpgrade on the Ansible controller (autoupgrade_run_local: true). java from PATH is used, when autoupgrade_local_java_home is empty.

Default value

autoupgrade_local_java_home: ''

autoupgrade_log_dir

Value for global.global_log_dir in the AutoUpgrade config files.

Default value

autoupgrade_log_dir: >-
  {{ _autoupgrade_run_local | bool
     | ternary(_autoupgrade_home + '/log', oracle_base + '/cfgtoollogs/autoupgrade') }}

autoupgrade_proxy_check

Check the connection to Oracle before AutoUpgrade (download_patches.yml) or get_url (autoupgrade_download_latest) is executed.

The check uses the same host, user and proxy settings (http_proxy, https_proxy, no_proxy, autoupgrade_proxy_username, autoupgrade_proxy_password) as the later download. Any HTTP response of the target counts as success. Errors are explained (e.g. proxy authentication failed, proxy not reachable, no route to the internet), before they lead to misleading errors of AutoUpgrade or of the keystore.

The upgrade of PDBs does not need a connection to the internet and does not execute the check.

Default value

autoupgrade_proxy_check: true

autoupgrade_proxy_check_timeout

Timeout in seconds for each URL of the check of the connection.

Default value

autoupgrade_proxy_check_timeout: 30

autoupgrade_proxy_check_urls

URLs for the check of the connection in download_patches.yml. These are the hosts used by AutoUpgrade 26 for the login into My Oracle Support and the download of patches. For autoupgrade_download_latest the host of autoupgrade_jar_url is checked.

Default value

autoupgrade_proxy_check_urls:
  - https://login-ext.identity.oraclecloud.com
  - https://transport.oracle.com
  - https://updates.oracle.com
  - https://aru-akam.oracle.com

autoupgrade_proxy_password

Password for an HTTP proxy with authentication. See autoupgrade_proxy_username.

Default value

autoupgrade_proxy_password: ''

autoupgrade_proxy_username

Username for an HTTP proxy with authentication.

The proxy itself is defined with http_proxy, https_proxy and no_proxy (same variables as for other downloads in ansible-oracle). Username and password are added URL encoded to http_proxy and https_proxy: http://<user>:<password>@proxy:3128. Credentials in http_proxy / https_proxy are not changed.

The proxy is used by get_url (download of autoupgrade.jar) and by AutoUpgrade (keystore, download of patches). AutoUpgrade reads https_proxy. AutoUpgrade needs access to updates.oracle.com, login-ext.identity.oraclecloud.com and aru-akam.oracle.com.

Default value

autoupgrade_proxy_username: ''

Example usage

https_proxy: http://proxy.example.com:3128
no_proxy: localhost,.example.com
autoupgrade_proxy_username: proxyuser
autoupgrade_proxy_password: "{{ vault_proxy_password }}"

autoupgrade_run_local

Execute AutoUpgrade on the Ansible controller instead of the target host. The switch is valid for all task files (install.yml, keystore.yml, download_patches.yml).

true (default): Tasks are delegated to localhost with run_once and without become. autoupgrade_local_home and autoupgrade_local_java_home are used. This is useful for downloading patches into the software repository on the Ansible controller.

false: Tasks are executed on the target host as oracle_user, e.g. for the installation of AutoUpgrade on database servers.

Important

With true the tasks are executed only once (run_once) with the variables of the first host in the play (oracle_sw_patches, db_homes_installed, db_homes_config, oracle_install_version_gi, autoupgrade_download_patches). These variables must be the same for all hosts in the play - e.g. defined in group_vars/all for the whole environment. When they are defined per host, limit the playbook to one host (--limit <host>) or execute it for each host.

Default value

autoupgrade_run_local: true

autoupgrade_upgrade_clear_recovery_data

Discard the recovery data of AutoUpgrade (-clear_recovery_data) before the analyze phase.

AutoUpgrade keeps recovery data after each deploy - finished or not. The role handles it automatically:

Recovery data Behaviour
finished deploy, PDBs pending cleared automatically before analyze/fixups
finished deploy, all PDBs upgraded kept (needed for -restore)
unfinished deploy deploy phase: resumed. analyze/fixups phase: fail

true: the recovery data is discarded in any case, e.g. after a manual restore of the PDBs. An unfinished deploy cannot be resumed anymore!

Default value

autoupgrade_upgrade_clear_recovery_data: false

autoupgrade_upgrade_fail_on_precheck_errors

Fail the analyze phase and the fixups phase, when AutoUpgrade reports checks with severity ERROR, which cannot be fixed automatically by AutoUpgrade (no fixup available or runfix is NO).

The deploy phase is never started, when these checks fail.

Default value

autoupgrade_upgrade_fail_on_precheck_errors: true

autoupgrade_upgrade_global_parameters

Additional global parameters for the upgrade config files (global.<key>=<value>). global_log_dir is set by the role.

Default value

autoupgrade_upgrade_global_parameters: {}

Example usage

autoupgrade_upgrade_global_parameters:
  keystore: /u01/app/oracle/admin/autoupgrade/keystore

autoupgrade_upgrade_parameters

Default AutoUpgrade parameters for all AutoUpgrade jobs (upg1.<key>=<value>). Can be overwritten with autoupgrade.parameters in oracle_pdbs.

Values are written unchanged. Booleans are converted into yes/no.

Default value

autoupgrade_upgrade_parameters: {}

Example usage

autoupgrade_upgrade_parameters:
  timezone_upg: "yes"
  drop_grp_after_upgrade: "yes"

autoupgrade_upgrade_pdbs

Limit upgrade_analyze.yml / upgrade_fixups.yml / upgrade_deploy.yml to these PDBs (pdb_name in oracle_pdbs).

Empty (default): all PDBs in oracle_pdbs with attribute autoupgrade and state: present are processed.

The upgrade is an Unplug/Plug upgrade of PDBs into a CDB of the new release. oracle_pdbs defines the end state: cdb and home are the target CDB and target ORACLE_HOME. The source is defined with the attribute autoupgrade of the PDB:

Attribute Description
source_cdb mandatory: oracle_db_name of the source CDB
source_home optional: key in db_homes_config of the source ORACLE_HOME. Default: home of source_cdb in oracle_databases
source_sid optional: SID of the source CDB. Default: from source_cdb in oracle_databases, otherwise source_cdb
source_pdb_name optional: name of the PDB in the source CDB. Default: pdb_name
copy_option optional: upg1.target_pdb_copy_option.<pdb>, e.g. file_name_convert=NONE. Default: datafiles are reused (no copy)
restoration optional: true/false - default autoupgrade_upgrade_restoration
parameters optional: dict with additional AutoUpgrade parameters (upg1.<key>=<value>). Overrides autoupgrade_upgrade_parameters.

All PDBs with the same source_cdb and cdb are upgraded in one AutoUpgrade job. restoration and parameters must be identical for these PDBs.

sid, source_home, target_home, target_cdb, pdbs, log_dir and restoration are set by the role and must not be used in parameters.

Important: Do not execute playbook manage_db between the change of oracle_pdbs and the upgrade. oradb_manage_pdb would create a new, empty PDB in the target CDB.

Default value

autoupgrade_upgrade_pdbs: []

Example usage

autoupgrade_upgrade_pdbs:
  - ORCLPDB1

oracle_pdbs:
  - cdb: DB26              # target CDB (end state)
    home: db26-si-ee       # target ORACLE_HOME (end state)
    pdb_name: ORCLPDB1
    state: present
    autoupgrade:
      source_cdb: DB2      # source CDB in 19c
      source_home: db1932-si-ee
      parameters:
        timezone_upg: "yes"

autoupgrade_upgrade_poll

Poll interval in seconds for AutoUpgrade in deploy mode.

Default value

autoupgrade_upgrade_poll: 60

autoupgrade_upgrade_restoration

Value for upg1.restoration for all AutoUpgrade jobs. Can be overwritten with autoupgrade.restoration in oracle_pdbs.

false (default): AutoUpgrade creates no Guaranteed Restore Point before the upgrade (upg1.restoration=no). There is no automatic fallback - take a backup before the upgrade!

true: AutoUpgrade creates a Guaranteed Restore Point before the upgrade (upg1.restoration=yes). Requires a Fast Recovery Area and Enterprise Edition.

Default value

autoupgrade_upgrade_restoration: false

autoupgrade_upgrade_timeout

Maximum runtime in seconds for AutoUpgrade in deploy mode per AutoUpgrade job (async).

Default value

autoupgrade_upgrade_timeout: 21600

Discovered Tags

always

assert

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.17 - global_handlers

Collection of handlers includeable by other roles.

Make them available to your role by including it into the dependency list in meta/main.yml of your role, for instance.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

restart_on_requirement

Controls if reboot handler actually reboots the host (true) or just displays a reboot advice (false)

Type: bool

Default value

restart_on_requirement: false

Dependencies

None.

License

license (MIT)

Author

[Thilo Solbrig]

3.18 - oraapex

The role is in pre ALPHA state.

A lot of changes are planned during development at the moment.

Limitations:

  • Oracle RDBMS 19c+ - older versions may work but not tested anymore.
  • Installation in PDB only - no CDB or nonCDB installation at the moment
  • RAC not tested yet.

Documentation: https://github.com/oravirt/ansible-oracle/blob/master/doc/guides/apex_ords.adoc

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oraapex_base

oraapex_base is used as a prefix directory for unzip for apex.zip.

Default value

oraapex_base: >-
  {{ oracle_base }}/product

oraapex_default_admin_password

Password for apex_admin_user from oracle_databases or oracle_pdbs.

oraapex_default_files_tablespace

Default value

oraapex_default_files_tablespace: SYSAUX

oraapex_default_tablespace

Default value

oraapex_default_tablespace: SYSAUX

oraapex_default_temp_tablespace

Default value

oraapex_default_temp_tablespace: TEMP

oraapex_image_path

Default value

oraapex_image_path: /i/

oraapex_rac_primary_node_only

Default value

oraapex_rac_primary_node_only: true

oraapex_rac_primary_only

unarchive apex.zip in RAC only on 1st node or on all nodes?

This is only true, when ORDS runs on RAC nodes as well, because we need the images for ORDS. This should not be done on production setups!

Open Tasks

  • (information): oraapex_rac_primary_only not implemented yet.

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

  • Thorsten Bruhns

3.19 - oraasm_manage_diskgroups

Manages ASM diskgroups.

Important

All variables in this role are internal use only. Do not set them in inventory!

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

diskgroup

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Mikael Sandström]

3.20 - oracluvfy

Manage Cluster Verification Utility from Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oracluvfy_archive

ZIP Archive used by the role.

Default value

oracluvfy_archive: cvupack_linux_ol7_x86_64.zip

oracluvfy_archive_filesource

If oracluvfy_archive ist not placed under oracle_sw_source_local / oracle_sw_source_www, path can be forced using oracluvfy_archive_filesource instead. oracluvfy_archive_filesource must be the full path/URL, including the filename.

Example usage

oracluvfy_archive_filesource: /full/path/to/cvupack_linux_ol7_x86_64.zip

oracluvfy_force_update

Force unarchive of cluvfy in oracluvfy_home.

Default value

oracluvfy_force_update: false

oracluvfy_home

Default value

oracluvfy_home: '{{ oracle_base }}/product/cluvfy'

Discovered Tags

always

assert

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.21 - oradb_datapatch

Manage datapatch for Oracle Database

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oradb_datapatch_fail_on_db_not_exist

Should task for datapatch fail when database from oracle_databases is not existing?

Important! Do not use fail_on_db_not_exist anymore. The variable is deprecated and will be removed in a future release!

Default value

oradb_datapatch_fail_on_db_not_exist: '{{ fail_on_db_not_exist | default(false) }}'

Discovered Tags

datapatch

startdb

Open Tasks

  • (bug): Do we really need db-connection here?

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Mikael Sandström]

3.22 - oradb_facts

Gather Ansible Facts from database

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oradb_facts_db_user

The dbuser for connection to database.

Default value

oradb_facts_db_user: sys

Discovered Tags

db_facts

Open Tasks

  • (bug): parameter user, password and sysdba needs a refactoring

Dependencies

  • orasw_meta

License

license (MIT)

Author

Thorsten Bruhns

3.23 - oradb_manage_grants

Manage grants for users in Oracle Databases

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

grants

grants2

grants4

users

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

[Mikael Sandström]

3.24 - oradb_manage_parameters

Manage Oracle Database Parameters

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

restart_spparameter_changed

Bounce instane when parameter changes detected between SPFile and memory parameter.

IMPORTANT Note!

Some memory parameters are rounded internally by Oracle. Changing them in SPFile could lead to a bounce of the instance each time the role is executed. Change the paramter to the rounded value from Oracle to prevent this.

Default value

restart_spparameter_changed: false

Discovered Tags

initparams
 Configure parameter for nonCDB, CDB and PDB

initparams_cdb
 Configure parameter for nonCDB and CDB

initparams_pdb
 Configure parameter for PDB

spfile_bounce
 Bounce database when changed parameter need a restart.

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

[Mikael Sandström]

3.25 - oradb_manage_pdb

Manage pluggable databases in Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

pdbadmin_password

Password for pdb_admin user.

Default value

pdbadmin_password: >-
  {{ dbpasswords[odb.1.cdb][odb.1.pdb_name][pdbadmin_user] | default(default_dbpass) }}

pdbadmin_user

Default pdb_admin user for newly created PDBs.

Could be set in oracle_pdbs to define different pdb_admin user for each PDB.

Default value

pdbadmin_user: >-
  {{ odb[1].pdbadmin_user | default('PDBADMIN') }}

Discovered Tags

pdb

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Mikael Sandström]

3.26 - oradb_manage_profiles

Manage database profiles in Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

dbprofiles

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

  • Mikael Sandström
  • Thorsten Bruhns

3.27 - oradb_manage_roles

Manage roles in Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

grants

users

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

[Mikael Sandström]

3.28 - oradb_manage_services

Manage services in Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

create_service

services

start_service

Open Tasks

  • (bug): Module oracle_services does not support ‘as sysdba’. Connect User system is hard coded for the moment…
  • (bug): Role require Oracle Restart/GI at the moment

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Mikael Sandström]

3.29 - oradb_manage_statspack

Manage Statspack in Oracle.

Not RAC aware at the moment.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

purgedays

Global default variable for Statspack purgetime in days. Could be defined for each database with oracle_databases. An example is shown there.

Default value

purgedays: 35

purgeinterval

Global default variable for Statspack purge interval in scheduler job. Could be defined for each database with oracle_databases. An example is shown there.

Default value

purgeinterval: FREQ=daily;byhour=3;byminute=15;bysecond=0

snapinterval

Global default variable for Statspack snap interval in scheduler job. Could be defined for each database with oracle_databases. An example is shown there.

Default value

snapinterval: FREQ=hourly;byminute=0;bysecond=0

snaplevel

Global default variable for Statspack snaplevel. Could be defined for each database with oracle_databases. An example is shown there.

Default value

snaplevel: 7

Discovered Tags

spcreate
 Install Statspack in nonCDB, CDB or PDB

spdrop
 Remove Statspack from nonCDB, CDB or PDB

spjob
 Configure Statspack Scheduler Jobs

statspack
 Do all Tasks for Statspack

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

[Thorsten Bruhns]

3.30 - oradb_manage_tablespace

Manage Tablespaces in Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

tablespace

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

  • Mikael Sandström
  • Thorsten Bruhns

3.31 - oradb_manage_users

Manage Users in Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Discovered Tags

users

Dependencies

  • orasw_meta
  • oradb_facts

License

license (MIT)

Author

[Mikael Sandström]

3.32 - oradb_manage_wallet

Manage Wallets for Oracle with mkstore and orapki.

Multiple wallets with different locations are possible. Define a password for the wallet in oracle_wallet_password.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oracle_wallet_config

Default value

oracle_wallet_config: []

Example usage

oracle_wallet_config:
  - name: wallet1
    home: 19300_base
    path: /u01/app/oracle/wallet
    state: present
    dbcredentials:
      - tns_name: db1
        db_name: db1
        db_user: user1
        state: present
    certificates:
      - file: "/home/oracle/assets/certs/https/mysite.crt"
        type: "cert"
        extra_args: "-trusted_cert"
        state: present
      - file: "/home/oracle/assets/certs/oracle/test-server.pfx"
        type: "pkcs12"
        password: "secret123"
        state: present

oracle_wallet_password

Default value

oracle_wallet_password: {}

Example usage

oracle_wallet_password:
  wallet1: <password>
  wallet2: <password>

oracle_wallet_show_password

Show password during execution in loop label.

Default value

oracle_wallet_show_password: false

Discovered Tags

always

cert

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.33 - oradb_tzupgrade

Manage timezone upgrades for an Oracle Database

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Dependencies

  • orahost_meta
  • orasw_meta_internal

License

license (MIT)

Author

[Alexandru Tică]

3.34 - orahost_cron

Configure cronjobs for ansible-oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

cron_config

Define custom cronjobs for ansible-oracle. No job is existing by default.

Example usage

cron_config:
  - { user: oracle, name: "clean-up job", job: "some fancy thing", hour: "1", cron_file: oracle-cleanup, state: present }

Discovered Tags

cron

Dependencies

None.

License

license (MIT)

Author

[Mikael Sandström]

3.35 - orahost_logrotate

Configure logrotate for ansible-oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

logrotate_config

Configuration of logrotate definitions.

Default value

logrotate_config:
  - name: oracle_alert
    file: '{{ oracle_base }}/diag/rdbms/*/*/trace/*alert*.log {{ oracle_base }}/diag/asm/*/*/trace/alert*+ASM*.log'
    options:
      - missingok
      - notifempty
      - weekly
      - rotate 3
      - dateext
  - name: oracle_listener
    file: '{{ oracle_base }}/diag/tnslsnr/*/*/trace/*listener*.log'
    options:
      - missingok
      - notifempty
      - weekly
      - rotate 3
      - dateext
      - compress
  - name: oracle_rman
    file: "{{ rman_cron_logdir | default('/var/log/oracle/rman/log') }}/*.log {{ oracle_base }}/admin/*/rman/*.log {{ oracle_base }}/admin/*/rman/log/*.log"
    options:
      - missingok
      - notifempty
      - compress
      - weekly
      - rotate 24
      - dateext

oracle_cleanup_days

Define number of days for oracle_cleanup.sh logfiles and audit files.

Default value

oracle_cleanup_days: 14

oracle_home_gi

Default value

oracle_home_gi: '{% if _oraswgi_meta_configure_cluster %}{{ oracle_home_gi_cl }}{% else %}{{ oracle_home_gi_so }}{% endif %}'

oracle_home_gi_cl

Default value

oracle_home_gi_cl: /u01/app/{{ oracle_install_version_gi }}/grid

oracle_home_gi_so

Default value

oracle_home_gi_so: '{{ oracle_base }}/{{ oracle_install_version_gi }}/grid'

oracle_trace_cleanup_days

Define number of days for ADR in Oracle.

Default value

oracle_trace_cleanup_days: 7

orahost_logrotate_setup_logrotate

Setup of logrotate/cleanup is optional

Default value

orahost_logrotate_setup_logrotate: true

Open Tasks

  • (bug): oracle_home_gi variables require a central meta role

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.36 - orahost_ssh

SSH Setup for Oracle Grid-Infrastructure installations.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

orahost_ssh_keyname

The name of used key during role execution.

Example for oracle:

/home/oracle/.ssh/{{ orahost_ssh_keyname }}

Default value

orahost_ssh_keyname: id_{{ orahost_ssh_key_type }}

Dependencies

  • orahost_meta
  • orasw_meta_internal

License

license (MIT)

Author

[Thorsten Bruhns]

3.37 - orahost_storage

Role to configure the storage for oracle.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

asmlib_binary

Default value

asmlib_binary: /usr/sbin/oracleasm

multipath

Configure multipath

Default value

multipath: none

Example usage

multipath: dm-multipath

oradnfs

Defines the settings for dnfstab in Oracle.

Default value

oradnfs: _unset_

Example usage

oradnfs:
 - server: nfsserver
   ips:
     - local: dbserver
       path: nfsserver
   exports:
     - export: /nfs/oradata
       mount: /u02/oradata2
     - export: /nfs/oradata2
       mount: /u02/oradata

partition_devices

Create a partition on storage disk?

Default value

partition_devices: true

partition_suffix

Value of partition_suffix depends on vairable multipath. No need to set this variable.

Default value

partition_suffix: '1'

use_partition_devices

Deprecated variable. Use partition_devices as replacement.

Default value

use_partition_devices: true

Discovered Tags

asmlibconfig

asmstorage

kpartx

partition

udev

Open Tasks

  • (bug): why is variable multipath only used for dm-multipath?

Dependencies

  • orahost_meta

License

license (MIT)

Author

[Mikael Sandström]

3.38 - oraords

Install ORDS on Oracle Linux.

Defaults:

ORACLE_HOME: {{ oracle_base }}/product/ords

This role is limited to Oracle Linux, due to installation from yum Repository from Oracle.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

oraords_apex_image_context

APEX context path for Images.

oraords_apex_image_path

Directory for APEX Images on ORDS Host.

oraords_db_pools

List of configured target in ORDS.

Attributes:

db_pool:

admin_user: <Admin user for ORDS installation. Defaults to oraords_default_admin_user>

service:

port: <Listener Port. Defaults to oraords_default_port>

host: <Hostname for target. Defaults to inventory_hostname>

feature_db_api: <true / false (default)>

feature_rest_enabled_sql: <true / false (default)>

feature_sdw: <true / false (default)>

Default value

oraords_db_pools:
  - db_pool: default
    admin_user: sys
    service: orclpdb
    port: 1521

oraords_default_admin_user

Default value

oraords_default_admin_user: sys

oraords_default_port

Default value

oraords_default_port: 1521

oraords_java_rpm

Default value

oraords_java_rpm: java-21-openjdk

oraords_oracle_home

ORACLE_HOME for ORDS.

Default value

oraords_oracle_home: >-
  {{ oracle_base }}/product/ords

oraords_ords_bin

PATH for ords binary

Default value

oraords_ords_bin: >-
  /opt/oracle/ords/bin

oraords_ords_config

ORDS configuration directory.

Default value

oraords_ords_config: >-
  /etc/ords/config

oraords_ords_logs

ORDS logging directory.

Default value

oraords_ords_logs: >-
  /etc/ords/logs

Discovered Tags

always

ords_config

Dependencies

  • orahost_meta
  • orasw_meta

License

license (MIT)

Author

Thorsten Bruhns

3.39 - orasw_download_patches

Download all patches from Oracle

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

mos_login

Login name for My Oracle Support (required)

mos_password

Password for My Oracle Support (required)

opatchinfo

This is an internal variable for downloading patches. Usually no need to change it.

Default value

opatchinfo: []

oracle_patch_download_dir

Target directory for patch downloads

Default value

oracle_patch_download_dir: '{{ oracle_sw_source_local }}'

oracle_patch_download_host

delegate_to host for downloads

Default value

oracle_patch_download_host: localhost

oracle_plat_lang

This is an internal variable for downloading patches. Usually no need to change it.

Default value

oracle_plat_lang: 226P

Dependencies

  • orasw_meta

License

license (MIT)

Author

bartowl github@bartowl.eu

3.40 - oraswdb_golden_image

Create Golden-Images from Oracle Database Homes and Oracle Grid-Infrastructure/Restart

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

golden_image_dest

Set destination directory for Golden-Image extraction.

Variable has no default value.

oraswdb_golden_image_create

Crfeate Golden-Image for Database Home.

Default value

oraswdb_golden_image_create: false

Discovered Tags

always

golden_image_db

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.41 - oraswdb_manage_patches

Manage Patch Installation in Database ORACLE_HOMEs.

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

opatch_db_conflict_check

When calling oracle_opatch for DB, decide if analyze stage of opatch/opatchauto should be executed.

Type: boolean

Default value

opatch_db_conflict_check: '{{ opatch_conflict_check | bool }}'

oraswdb_manage_patches_cleanup_staging

Remove following list of directories after DB-Patching when oracle_sw_copy: true:

  • “{{ oracle_stage }}/patches”

Default value

oraswdb_manage_patches_cleanup_staging: true

oraswdb_manage_patches_force_opatch_upgrade

Upgrade OPatch without checking for existing version.

Needed for prepatch installations, because Home is not registered in central inventory.

Default value

oraswdb_manage_patches_force_opatch_upgrade: false

Discovered Tags

always

apply_patch_db

autopatch

directories

molecule-idempotence-notest

nfsmountdb

nfsumountdb

ocmconfig

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Mikael Sandström]

3.42 - oraswgi_golden_image

Create Golden-Images from Oracle Grid-Infrastructure/Restart

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

golden_image_dest

Set destination directory for Golden-Image extraction.

Variable has no default value.

oraswgi_golden_image_create

Crfeate Golden-Image for Grid-Infrastructure/Restart.

Default value

oraswgi_golden_image_create: false

oraswgi_golden_image_filename

Filename of created Image archive.

Default value

oraswgi_golden_image_filename: >-
  {% if oracle_install_option_gi == 'CRS_CONFIG' -%}
  gi_{% else %}restart_{% endif %}{{ oracle_install_version_gi | split('.') | first }}.zip

Discovered Tags

always

golden_image_gi

Dependencies

  • orasw_meta

License

license (MIT)

Author

[Thorsten Bruhns]

3.43 - oraswgi_manage_patches

Install/Remove Patches from Oracle Database Homes

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

opatch_gi_conflict_check

When calling oracle_opatch for GI, decide if analyze stage of opatch/opatchauto should be executed.

Type: boolean

Default value

opatch_gi_conflict_check: '{{ opatch_conflict_check | bool }}'

Discovered Tags

always

assert

current_opatch_version

Dependencies

  • orahost_meta
  • orasw_meta
  • oraswgi_meta

License

license (MIT)

Author

  • Mikael Sandström
  • Thorsten Bruhns

3.44 - oraswgi_meta

Important

The description for variables is work in progress.!

Meta role used by other roles to share variable defaults.

This role has a dependency to orahost_meta.

There are a lot of variables who are used by orasw_meta

Table of contents


Requirements

  • Minimum Ansible version: 2.16.0

Default Variables

_grid_install_user

This is an internal variable of ansible-oracle.

Do not change it!

Default value

_grid_install_user: '{% if role_separation %}{{ grid_user }}{% else %}{{ oracle_user }}{% endif %}'

_oraswgi_meta_configure_cluster

This is an internal variable of ansible-oracle.

Do not change it!

Default value

_oraswgi_meta_configure_cluster: "{{ oracle_install_option_gi == 'CRS_CONFIG' }}"

apply_patches_gi

Apply patches to Grid-Infrastructure/Restart?

Do not disable this!

Default value

apply_patches_gi: true

asmmonitorpassword

ASMSNMP Password for ASM.

Default value

asmmonitorpassword: '{{ default_gipass }}'

gi_patches

Dictionary of lists for opatch and opatchauto patches for Grid-Infrastructure/Restart.

Default value

gi_patches: {}

Example usage

gi_patches_config:
  19.16.0.0.220719:
    19.3.0.0:  # Base Release
      opatch_minversion: 12.2.0.1.30
      opatchauto:
        - patchid: 34130714
          patchversion: 19.16.0.0.220719
          state: present
          path: ./19.16.0.0.220719/gi/34130714/34130714
          subpatches:
            - 34160635  # OCW Release Update 19.16.0.0.220719
            - 33575402  # DBWLM Release Update
            - 34139601  # ACFS Release Update 19.16.0.0.220719
            - 34318175  # TOMCAT RELEASE UPDATE 19.0.0.0.0
            - 34133642  # Database Release Update 19.16.0.0.220719
          apply_options:
            - "-deleteInactivePatches"
      opatch:
          # Oracle JavaVM Component Release Update (OJVM RU) 19.16.0.0.220719
          stop_processes: true
          state: present
          path: 19.16.0.0.220719/ojvm/p34086870_190000_Linux-x86-64.zip
          apply_options:
            - "-force_conflict"
          # Oracle Database 19c Important Recommended One-off Patches (Doc ID 555.1)
gi_patches: "{{ gi_patches_config['19.16.0.0.220719'] }}"

patch_before_rootsh

Patch Grid-Infrastructure during gridSetup.sh

Default value

patch_before_rootsh: true

sysasmpassword

SYSASM Password for ASM.

Default value

sysasmpassword: '{{ default_gipass }}'

Discovered Tags

always

assert_ansible_oracle

Dependencies

None.

License

license (MIT)

Author

[Thorsten Bruhns]

4 - Development

Everything about the development of ansible-oracle.

4.1 - How to develop

1. How to develop in ansible-oracle?

Important
This is an example how most of the development in ansible-oracle is done.
A Pull-Request is only accepted, when github-Actions are valid.

1.1. Create Fork on github and contribute to the project

github has some great documentation with details about creating a fork and branch to contribute to ansible-oracle.

Important
The github-Actions will automatically start, when the branchname starts with pr or in each Pull-Request.
Please use a branch with 'pr'--prefix, when ansible-lint should be checked for each commit.

1.2. Development environment

You need an editor or IDE of your own choice and Bash as CLI. The tools for development (ansible-lint, ansible-navigator, ansible-doctor, pre-commit, …​) can be provided in two ways:

Option 1: nix-shell Option 2: local Ansible-Controller

Setup

Install Nix once, then nix-shell in the repository

Create and maintain venvs and tools manually

Tools

All tools and venvs are provided automatically

Each tool is installed by yourself

Recommended for

All developers

Developers with an existing Ansible-Controller or experience with Docker

Tip
nix-shell is the recommended way for developing in ansible-oracle.
Choose one option, the chapter Working with the tools is the same for both.

1.2.1. Option 1: nix-shell (recommended)

One command in the repository provides all tools, which are needed for development, tests and releases.

1.2.1.1. What is nix-shell?

Nix is a package manager for Linux and macOS, which works independent of the package manager of the OS (dnf, apt, …​). All packages are installed in /nix/store, each version in its own directory. Different versions of a tool can be installed in parallel without conflicts, the OS installation is not changed.

nix-shell starts a new shell with the packages from shell.nix in the repository. The tools are only available inside this shell, exit returns to the normal shell without any change in the OS. Packages are downloaded once and reused in all later sessions.

The shell.nix of ansible-oracle provides:

  • Tools from Nix: python313, shellcheck, go-task (task), jq, yq, gh (GitHub CLI), renovate, tig, ncdu and wslu for WSL2.

    Note
    gh is only needed for creating releases (task release:*) and for running renovate against a fork. This is only relevant for a few maintainers. For normal development and Pull-Requests gh is not needed and no login with gh auth login is required.
  • Python venvs in .venv/ of the repository, which are created automatically from tools/dev/requirements_*.txt at the first start:

    venv Usage

    .venv/ansible-oracle

    ansible-lint, ansible-navigator, molecule, pre-commit - activated in the shell

    .venv/ansible-doctor

    ansible-doctor (has conflicts with ansible-lint in the same venv)

    .venv/antsibull

    antsibull-changelog for changelog fragments and releases

    .venv/ansible-2.16

    tests with ansible-core 2.16

    .venv/ansible-2.19

    tests with ansible-core 2.19

1.2.1.2. Why nix-shell instead of containers?

Containers (see docker/) are an alternative, but they need much more effort in daily work:

  • No image build, no container runtime: There is no Dockerfile to maintain and no daemon to start. nix-shell works on every Linux, WSL2 and macOS with Nix installed.

  • Work directly in your repository: Editor, IDE and git work on the files as usual. There are no volume mounts and no problems with file owners or UIDs between container and host.

  • Your credentials are available: SSH agent and keys and the git configuration of your user are used directly, for maintainers also the login of gh. A container needs extra mounts for all of them.

  • pre-commit works as on GitHub: The hooks of pre-commit use the Python and tools from nix-shell. E.g. the ansible-lint hook fails outside of nix-shell with the Python of an older OS.

  • Same tools for all developers: Everybody uses the same tools and pip requirements from the repository. No manual installation of shellcheck, gh, jq, task or the venvs is needed.

  • All tasks work out of the box: task for molecule, renovate and releases (task release:pr, …​) needs exactly the tools from nix-shell.

  • Nothing is left in your OS: The tools are removed from PATH when the shell is left. The venvs are inside the repository in .venv/ and are not part of git.

1.2.1.3. Install Nix

Nix is installed once per machine, see nixos.org/download. The multi-user installation is recommended (needs sudo only for the installation):

sh <(curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install) --daemon
Note
For WSL2 the multi-user installation needs systemd in WSL2 (/etc/wsl.conf: [boot] systemd=true).
1.2.1.4. Using nix-shell
cd ansible-oracle
nix-shell

The first start takes some minutes, because packages are downloaded and the venvs are created. Afterwards nix-shell starts in seconds and .venv/ansible-oracle is activated.

# check the tools
task --list
ansible-lint --version

# leave nix-shell
exit

A single command can be executed without an interactive shell:

nix-shell --run 'task release:pr'
Tip
With direnv and nix-direnv the environment is loaded automatically, when you change into the repository. The repository contains a .envrc for this, which must be allowed once with direnv allow.
1.2.1.5. Update the venvs

The venvs are only created, when the directory in .venv/ does not exist. After a change of tools/dev/requirements_*.txt (e.g. by renovate) the venv must be updated manually. Errors like ModuleNotFoundError: No module named 'yaml' show an incomplete venv.

# update a venv in place
.venv/antsibull/bin/pip --require-virtualenv install -r tools/dev/requirements_antsibull.txt

# or recreate it with the next start of nix-shell
rm -rf .venv/antsibull
nix-shell
Note
shell.nix uses the nixpkgs channel of your system, the versions of the Nix tools can differ between developers. The versions of the Python tools are pinned in tools/dev/requirements_*.txt.

1.2.2. Option 2: local Ansible-Controller

Note
This option is only for developers, who want to use an existing Ansible-Controller or a container and have experience with venvs and Docker.
All tools must be installed and updated manually. nix-shell does all of this automatically, see Option 1: nix-shell (recommended).

The examples use venvs in ~/venv. Make sure to use a current Python 3, the pinned versions in tools/dev/requirements_*.txt need a recent Python. The activate script is used to change the Python environment in current shell.

1.2.2.1. venv for ansible-oracle

The venv contains ansible-lint, ansible-navigator, molecule and pre-commit.

configure venv for ansible-oracle
python3 -m venv ~/venv/ansible-oracle
. ~/venv/ansible-oracle/bin/activate
pip --require-virtualenv -v install -r tools/dev/requirements_dev.txt
Start ansible-navigator
. ~/venv/ansible-oracle/bin/activate
ansible-navigator --version
1.2.2.2. venv for ansible-doctor
Important
ansible-doctor has module dependencies with conflicts between ansible-lint. We have to use a dedicated venv for ansible-doctor.
configure venv for ansible-doctor
python3 -m venv ~/venv/ansible-doctor
. ~/venv/ansible-doctor/bin/activate
pip --require-virtualenv -v install -r tools/dev/requirements_doctor.txt
Start ansible-doctor
~/venv/ansible-doctor/bin/ansible-doctor --version
1.2.2.3. Ansible-Container

Instead of local venvs, the container from docker/ can be used as Ansible-Controller.

cd ansible-oracle/docker
docker-compose run --rm -w /git/ansible-oracle/example/beginner/ansible ansible bash
Note
Some pre-commit hooks (e.g. ansible-lint) need a recent Python and can fail with the Python of an older OS.

1.3. Working with the tools

The following chapters are the same for both options. With nix-shell the tools are in PATH, with a local Ansible-Controller the venv must be activated before.

1.3.1. pre-commit

Important
pre-commit is a nice tool for git.
Each commit is locally checked against multiple rules, to prevent failures in github-Actions after pushing commits to github.
This tool is recommended but not mandatory for contributing to ansible-oracle.
Install the git hook once (cd into repository before)
pre-commit install
Important
Do not forget to place change files in stage area of git before starting pre-commit.
pre-commit works only on the data of the stage area!
run outside git
pre-commit run

1.3.2. ansible-doctor

Start ansible-doctor with pre-commit
pre-commit run ansible-doctor
Start ansible-doctor to create new README.md file
cd ansible-oracle

# nix-shell
.venv/ansible-doctor/bin/ansible-doctor -f -r roles

# local Ansible-Controller
~/venv/ansible-doctor/bin/ansible-doctor -f -r roles

1.3.3. Start Playbook

Important
Don’t forget to set the working branch in requirements.yml.
Remove/Disable devsec.hardening for faster installation of Ansible collection, when devsec should not be tested.
Edit requirements.yml
---
collections:
  # - name: devsec.hardening
  #   version: 8.2.0
  - name: https://github.com/Rendanic/ansible-oracle.git
    type: git
    version: devbranch
Execute ansible-playbook
ansible-galaxy collection install --force -r requirements.yml && ansible-playbook -i inventory/hasfd -e hostgroup='all' playbooks/single-instance-asm.yml --limit '*19c*'

2. Pull-Requests

2.1. Important Information

The ansible-oracle project introduced antsibull-changelog for managing the CHANGELOG.rst based on fragments in changelogs/fragments.

The ID should point to the PR and the filename describe the PR in short form. The fragments are part of the PR. If multiple PRs are open, the upper rule makes sure that no duplicate files are created during merge.

Important
Each Pull-Requests needs a fragment from Release 3.0.0 onwards!

2.2. Create Pull-Requests with Claude Code

tools/claude/skills/pr contains the skill /pr for Claude Code. It creates a Pull-Request from the current state of the local working copy: create a branch, commit, add a changelog fragment, push into the fork and run gh pr create.

2.2.1. Setup

gh is part of shell.nix and must be logged in once (see Setup gh for renovate). Without a gh in the PATH the skill uses nix-shell -p gh.

Install the skill as personal skill for Claude Code:

mkdir -p ~/.claude/skills
ln -sfn "$(pwd)/tools/claude/skills/pr" ~/.claude/skills/pr
Note
The symlink points into the working copy. /pr is missing on branches without tools/claude. Use cp -r instead of ln -sfn for an independent copy.

2.2.2. Usage

/pr [draft] [base=<branch>] [milestone=<pattern>] [label=<p1,p2,...>] [notes on content]
Argument Description

draft

Create the Pull-Request as draft.

base=<branch>

Target branch. Default: default branch of the target repository.

milestone=<pattern>

Milestone in the target repository. The value is searched as case-insensitive regular expression in the titles of the open milestones (e.g. milestone=5.0 or milestone=5.0.*alpha). A number is the number of the milestone.

label=<p1,p2,…​>

Comma-separated labels in the target repository. Every entry is searched as case-insensitive regular expression in the label names (e.g. label=enh,bug,break).

any text

Hints for title and description of the Pull-Request.

Examples
/pr milestone=4.17 label=bug
/pr draft milestone=5.0.*alpha label=enh,break

2.2.3. Behavior

  • The target is the remote upstream, if it exists (Pull-Request from <fork-owner>:<branch> into oravirt/ansible-oracle), otherwise origin.

  • On the default branch a new branch is created.

  • A missing fragment in changelogs/fragments is created. The PR reference is added later with tools/release/fix_fragments.py.

  • Labels and milestones are resolved against the target repository before pushing. Only open milestones are considered. An exact name wins, otherwise the value is searched as regular expression. The skill stops when a value matches nothing or more than one name (the matches are listed), nothing is created. Setting labels or milestones in oravirt/ansible-oracle needs the triage permission.

  • An existing Pull-Request for the branch is updated (push, labels, milestone) instead of creating a new one.

  • The skill asks before a force push, a push into the default branch, unrelated uncommitted changes or merge conflicts.

Important
Invoking /pr allows Claude to push the branch and to create the Pull-Request without further confirmation.

3. Create new Releases in ansible-oracle

Important
This is only needed for creating new Releases in ansible-oracle - not for development!

3.1. Install antsibull-changelog

cd ansible-oracle/docker
docker-compose run --rm -w /git/ansible-oracle/example/beginner/ansible ansible bash

pip3 install antsibull-changelog

3.3. Add PR references to fragments

Each entry in a fragment should end with a reference to its Pull-Request, e.g. (oravirt#599). tools/release/fix_fragments.py adds missing references to all fragments in changelogs/fragments.

The Pull-Request is determined from the commits of the fragment file via the GitHub API, newest commit first. A merged Pull-Request of any of these commits wins over an open one. The open Release-Pull-Request is only used for fragments, which are not part of a merged Pull-Request. The reference is appended to every entry that does not end with it, even if the entry already references an issue.

# show what would be changed
tools/release/fix_fragments.py --dry-run

# update the fragments
tools/release/fix_fragments.py

Single fragments can be checked with -f / --fragment, e.g. by a developer after the Pull-Request for a new fragment has been created. The parameter accepts a path or a filename from changelogs/fragments and can be repeated. With --dry-run the script returns exit code 1 if the fragment needs to be updated.

# check a single fragment
tools/release/fix_fragments.py --dry-run -f blanks-in-gi-responsefile.yml

# update a single fragment
tools/release/fix_fragments.py -f changelogs/fragments/blanks-in-gi-responsefile.yml
Note
The Pull-Request must exist on GitHub, otherwise the fragment is reported as no pull request found.

Fragments without a Pull-Request and entries that cannot be updated automatically (e.g. broken quoting) are reported and must be fixed manually. The script returns exit code 1 in this case.

Without --fragment all fragments in changelogs/fragments are processed.

Note
Without a token the GitHub API allows only 60 requests per hour. The token is taken from GITHUB_TOKEN or GH_TOKEN. Without these variables the token stored by gh is used, when all fragments are processed (gh auth token or ~/.config/gh/hosts.yml of the active account). An invalid token is ignored with a warning.

This must be done before antsibull-changelog release, because the release removes the fragments.

3.4. Collection version in requirements.yml

The examples in example/*/ansible/requirements.yml must reference the collection version from galaxy.yml. The same is needed for the template tools/release/requirements.yml. tools/release/galaxy_version.sh checks or sets the version in all these files.

# check the versions
tools/release/galaxy_version.sh check

# set the version from galaxy.yml
tools/release/galaxy_version.sh fix

check returns exit code 1 if a file does not use the version from galaxy.yml. fix changes only the version of the collection entry, comments in the files are kept.

The script is also available as task example:check and task example:fix from the repository root.

3.5. Creating new releases

tools/release/build_release.sh executes the whole release process:

-m pr

Create the Release-Pull-Request with changelog.

-m release

Create the tag and a draft release for the Release-Pull-Request.

-m galaxy

Sync the branch of a published release in your fork and deploy the collection to Ansible Galaxy.

-m docs

Update the website, without creating a release.

Note
The whole release process should be done with a dedicated Pull-Request.

3.5.1. Release branches

Releases are built from master or from a maintenance branch release/<major>.x (e.g. release/4.x) for an older major version. The branch is the base of the Release-Pull-Request:

  • The release branch pr/<version> must be created from the base branch, e.g. git switch -c pr/4.17.1 upstream/release/4.x.

  • Without -b the base branch is taken from the version: master, when the major version is the same or higher than in galaxy.yml of master, otherwise release/<major>.x. Use -b, when a release for the same major version as master is built from a maintenance branch (e.g. -b release/4.x, while master is still 4.x).

  • The script aborts, when pr/<version> is not based on the current base branch. This prevents a Pull-Request with commits of another branch.

  • Only releases from master are marked as latest release on GitHub.

  • The website is only updated for releases from master.

  • antsibull-changelog writes the changelog of the base branch only. A release from a maintenance branch is not part of the changelog in master, until changelogs/changelog.yaml is merged.

Requirements:

  • The release branch is named pr/<major>.<minor>.<patch>, e.g. pr/4.16.0, and is created from the base branch.

  • origin is your fork on GitHub.

  • gh is logged in (gh auth status), jq and curl are installed and .venv/antsibull exists. gh, jq and the venv are provided by nix-shell.

  • The script is executed in nix-shell, because the pre-commit hooks of the version commit need it.

nix-shell

# release from master
git switch -c pr/4.18.0 upstream/master
tools/release/build_release.sh -m pr

# release from a maintenance branch
git switch -c pr/4.17.1 upstream/release/4.x
tools/release/build_release.sh -m pr -b release/4.x

Use -n (dry-run) to check all steps before: nothing is changed locally or on GitHub, the commands are shown instead.

3.5.2. Release-Pull-Request (-m pr)

The script executes the following steps:

  1. Determine the base branch (-b or from the version, see Release branches) and check that the release branch is based on it.

  2. Read the version from the branch name (pr/4.16.0 → 4.16.0) and set it in galaxy.yml.

  3. Set the version in all requirements.yml with tools/release/galaxy_version.sh fix.

  4. Commit galaxy.yml and all requirements.yml as Release <version>. This is the initial commit for the Pull-Request, GitHub refuses a Pull-Request without commits. Other changes in the working tree and the index are not part of this commit. The step is skipped, when the version is already committed.

  5. Push the branch to origin.

  6. Create the Pull-Request Release <version> against the base branch in oravirt/ansible-oracle. An existing open Pull-Request of the branch is used, the script aborts when it has another base branch.

  7. Add the PR references to the fragments with tools/release/fix_fragments.py. The script is aborted, when fragments cannot be updated.

  8. Create the changelog with .venv/antsibull/bin/antsibull-changelog release. antsibull-changelog reads the version from galaxy.yml and aborts, when the release already exists in CHANGELOG.rst. The fragments are removed.

  9. Replace the description of the Pull-Request with the release notes of the new version (Markdown, antsibull-changelog generate --only-latest).

The changes of fragments and changelog are not committed by the script. Review them, then commit and push them to the release branch.

3.5.3. Draft release (-m release)

tools/release/build_release.sh -m release

The script executes the following steps:

  1. Search the Pull-Request of the release branch from your fork, open or merged.

  2. Create the tag v<version> (e.g. v4.16.0) like the existing release tags. The tag points to the merge commit of the Pull-Request. The Pull-Request must be merged before, otherwise the script is aborted: a rebase merge creates new commits, so a tag on the last commit of the open Pull-Request would not be part of the branch. Only for tests against a fork (-r) the last commit of an open Pull-Request is used.

  3. Push the tag to the git remote of the GitHub repository (e.g. upstream for oravirt/ansible-oracle). An existing tag is used, when it points to the same commit, otherwise the script is aborted.

  4. Create the draft release Release <version> with the description of the Pull-Request as text. The text of an existing draft release is updated, an already published release aborts the script. Releases from master are created with --latest, releases from a maintenance branch with --latest=false.

  5. Update the website with tools/release/build_website.sh -m push, see website.adoc. The website is built from the local checkout of the release branch and published at once. This step is skipped for releases from a maintenance branch and for tests against a fork (-r other than oravirt/ansible-oracle).

The draft release must be published manually on GitHub. For a release from a maintenance branch, check that "Set as the latest release" is not selected when publishing.

Note
The website step needs docker, rsync and task and committed sources in website/, doc/, roles/ and docker/hugo/. When it fails, fix the problem and run -m release again: the existing tag and draft release are reused.

3.5.4. Update the website (-m docs)

tools/release/build_release.sh -m docs

Builds and publishes the website with tools/release/build_website.sh -m push, like the last step of -m release. Use it to update the website without a release, e.g. after changes in doc/ or website/, or to repeat a failed website step of -m release. No release branch is needed, the website is built from the current local checkout. The step is skipped with -r other than oravirt/ansible-oracle.

For more options (commit only, Pull-Request in the website repository) use tools/release/build_website.sh directly, see website.adoc.

3.5.5. Sync fork and deploy to Ansible Galaxy (-m galaxy)

# latest published release
tools/release/build_release.sh -m galaxy

# release from a maintenance branch
tools/release/build_release.sh -m galaxy -t v4.17.1

GitHub syncs the fork in the background. -m galaxy forces the sync at once, to deploy a release merged in upstream without waiting. The fork is <gh user>/ansible-oracle, the user is taken from the login of gh.

  1. Take the release from -t or the latest published release of the upstream repository. Draft releases are ignored, so the release must be published before. A release from a maintenance branch is not the latest release, use -t for it.

  2. Search the branch with the content of the release as last commit: master or release/<major>.x. The content (git tree) is compared and not the commit, because a rebase merge creates new commits with the same content. When the branch has newer changes than the release, nothing is deployed.

  3. Sync this branch in the fork with the upstream repository (gh repo sync). When the branch does not exist in the fork (e.g. release/4.x), it is created at the release commit.

  4. Start the workflow Deploy Collection in the fork on this branch, which uploads the collection to Ansible Galaxy. The script waits for the workflow and shows the progress of the steps (gh run watch). When the workflow fails, the log of the failed steps is shown and the script returns exit code 1. The workflow is not started, when the version is already on Ansible Galaxy, so -m galaxy can be repeated safely.

The mode works only on GitHub with gh (and the API of Ansible Galaxy), nothing is changed locally and no release branch is needed. The sync is refused, when the branch of the fork contains own commits - no hard reset is done.

3.5.6. Tasks

The modes are also available as tasks from the repository root. Options are passed after --.

task release:pr        # -m pr
task release:draft     # -m release (incl. website)
task release:docs      # -m docs
task release:galaxy    # -m galaxy

The creation of the Release-Pull-Request can be tested against your fork:

task release:pr -- -i -r <github user>/ansible-oracle

The Pull-Request is then created in your fork instead of oravirt/ansible-oracle.

Warning
fix_fragments.py searches the Pull-Requests of the fragments in your fork and not in upstream. The fragments are part of Pull-Requests in oravirt/ansible-oracle, so the results are wrong: fragments get the reference of the test Pull-Request in your fork (e.g. Rendanic#93) or are skipped with no pull request found. -i is needed, otherwise the script stops at the skipped fragments. Changelog and description of the test Pull-Request contain these wrong references, never use them for a real release. Revert all changes in the working tree after the test.

3.5.7. Options

-m pr|release|galaxy|docs

Mode of the script, see above.

-b <branch>

Base branch of the Release-Pull-Request (only -m pr, default: from the version, see Release branches).

-t <tag>

Release for -m galaxy, e.g. v4.17.1 (default: latest published release).

-n

Dry-run: show the commands, which would change something locally or on GitHub, without executing them. fix_fragments.py runs with --dry-run.

-r <owner/repo>

GitHub repository for the Pull-Request, the release, the lookup of the fragment Pull-Requests and source of the fork sync (default: oravirt/ansible-oracle).

-i

Continue, when fragments cannot be updated by fix_fragments.py (only -m pr).

A test against your fork is possible with -i -r <your account>/ansible-oracle, or -m release -r <your account>/ansible-oracle. The fragments get the reference of the Release-Pull-Request in the fork or are skipped, because the Pull-Requests of the fragments are in oravirt/ansible-oracle. Revert all changes in the working tree after such a test and remove the test tag and draft release (git tag -d v<version>, the tag and the release in your fork).

4. Check dependencies with renovate

Important
This is optional and not needed for the normal development in ansible-oracle.
It is used by maintainers to find updates for pip modules and container images.

renovate is part of shell.nix. The configuration is in renovate.json, the tasks are in tools/renovate/Taskfile.yml.

4.1. Local checks

The local checks read the working tree and do not change anything. No GitHub setup is needed. renovate.json is read from the working tree, but it must be tracked by git.

task renovate:check     # pip modules, container images, collections and github actions
task renovate:pip       # pip modules and pre-commit hooks
task renovate:docker    # container images only
task renovate:galaxy    # collections in galaxy.yml and requirements.yml
task renovate:report    # show the result of the last run again
task renovate:validate  # validate renovate.json
task renovate:ocenv     # check roles/oradb_manage_db/files/ocenv for local changes

The report shows only dependencies with updates. Add ONLY_UPDATES=false to show all dependencies including up-to-date and disabled, e.g. task renovate:check ONLY_UPDATES=false or task renovate:report ONLY_UPDATES=false.

Dependencies which are pinned intentionally (e.g. ansible-core or the molecule base images) are disabled with packageRules in renovate.json. They are shown as disabled in the report.

pip modules are checked against the python version, which installs the requirements file (constraints and constraintsFiltering in renovate.json). Versions, which do not support this python version (requires_python on PyPI), are not proposed:

  • python 3.13: venvs from shell.nix (requirements_dev_2.*.txt, requirements_doctor.txt, requirements_antsibull.txt)

  • python 3.11: execution environment (execution-environment.yml) and shell.nix use requirements_dev.txt, the lowest version is used.

Change the python version in renovate.json, when the python version in shell.nix or execution-environment.yml is changed. Dependencies between pip modules (e.g. a version of ansible-lint which needs a newer ansible-core) are not checked by renovate.

The collections in dependencies of galaxy.yml are checked against Ansible Galaxy. community.general and community.crypto are disabled, because the version ranges are set intentionally.

Renovate does not know requires_ansible of a collection and proposes versions, which need a newer ansible-core than requires_ansible in meta/runtime.yml. task renovate:galaxy therefore runs tools/renovate/galaxy_requires.py (task renovate:galaxy:requires) after the renovate check. It shows requires_ansible of each dependency in galaxy.yml and the newest version which can be installed with the minimum ansible-core version. The script fails, when a dependency needs a newer ansible-core. Only update to the version in column COMPATIBLE.

Renovate does not check the dependencies of a collection either. galaxy_requires.py checks the dependencies of every version against the version ranges in galaxy.yml and the minimum ansible-core version. COMPATIBLE is the newest version without a conflict, the script fails and shows the conflicting dependency, when the version in galaxy.yml has a conflict. Only one level is checked (dependencies of dependencies are not checked), test the installation with task molecule:collection after an update. opitzconsulting.ansible_oracle in requirements.yml is disabled, because the version is set by tools/release/galaxy_version.sh (see Collection version in requirements.yml).

Tools which are used in requirements, in .pre-commit-config.yaml and in the github workflows (ansible-doctor, ansible-lint, antsibull-changelog) are grouped with groupName. An update changes all files in one branch, so the versions are always the same. The github workflow for ansible-doctor installs tools/dev/requirements_doctor.txt. The versions of github actions (e.g. ansible/ansible-lint) and of pip install <module>==<version> in the workflows are checked as well (only with task renovate:check).

The pre-commit hooks are looked up with GitHub tags, which needs a token. The local checks use the token from gh auth token, if gh is logged in.

4.1.1. ocenv from oracle-scripts

roles/oradb_manage_db/files/ocenv is a copy of ocenv from opitzconsulting/oracle-scripts. The file is part of the collection, so no online access is needed during the installation.

Important
Do not change roles/oradb_manage_db/files/ocenv in ansible-oracle. Changes are made in oracle-scripts, the file is replaced only by renovate.
  • The upstream repository has no releases. The version is the committer date of the last commit of ocenv in UTC (YYYY.MMDD.HHMMSS, custom datasource ocenv in renovate.json).

  • tools/renovate/ocenv.version holds the version, the upstream commit and the git blob sha of the file.

  • For an update renovate runs tools/renovate/ocenv_update.sh as postUpgradeTasks. The script downloads ocenv of the matching upstream commit, compares git hash-object with the blob sha from GitHub and replaces the file. ocenv, tools/renovate/ocenv.version and the changelog fragment are committed by renovate into the update branch.

  • The git blob sha is the same in oracle-scripts and ansible-oracle. task renovate:ocenv compares the local file with the blob in tools/renovate/ocenv.version and fails after a local change, which would be overwritten by the next update.

4.1.2. Oracle Release Updates for molecule

The molecule scenarios use the current Release Update (RU) and the previous one (RU-1) for the patch tests. Both are set in extensions/molecule/shared_config/inventory/group_vars/all/oracle_ru.yml and updated by renovate:

Variable Example Custom datasource in renovate.json

molecule_ru_19

19.33

oracle-ru-19

molecule_ru_19_prev

19.32

oracle-ru-19-prev

molecule_ru_26

23.26.4

oracle-ru-26

molecule_ru_26_prev

23.26.3

oracle-ru-26-prev

  • The versions are derived from the quarterly Critical Patch Updates in the Oracle Security Alerts feed. *-prev is the same calculation, shifted by one quarter.

  • The RU of the database is used for Grid Infrastructure / Oracle Restart as well.

  • Short forms for ORACLE_HOME, gold images and oracle_home_name are derived in oracle_ru.yml: molecule_ru_19_nodot (1933), molecule_ru_26_short (26.04), molecule_ru_26_nodot (2604), molecule_ru_26_gi (26_04, gold image of Grid Infrastructure) and the same for *_prev. Use the variables in the scenarios instead of fixed versions.

  • The keys of db_homes_config are fixed, only the values (oracle_home, imagename, oracle_home_name) follow the RU: db19curr-si-ee, db19prev-si-ee, db26curr-si-ee, db26prev-si-ee in group_vars/all/oracle_db.yml. db19-si-ee (RU-1, patch tests) and db26-si-ee (current RU) are aliases for the scenarios without a specific RU.

  • Out-of-Place Patching tests (dbfs-sh, has-ol9, rac) install RU-1 in the converge and switch to the current RU in side_effect.yml.

  • All 4 variables are updated in one branch pr/renovate/oracle-ru-molecule.

  • Manual steps after an update (listed in the Pull-Request as well): create the gold images for the new RUs and update the RU patches in oracle_sw_patches. renovate does not know patch ids and file names of the RUs.

  • Keep the comment # renovate: datasource=…​ depName=…​ directly above the variable.

4.2. Setup gh for renovate

Important
The GitHub CLI gh is only needed for running renovate against your fork on GitHub (task renovate:fork) and for the Claude Code skill /pr (see Create Pull-Requests with Claude Code).
The local checks work without it.

gh is part of shell.nix. Login once with your GitHub account:

gh auth login     # GitHub.com, HTTPS, login with a web browser
gh auth status

The token of gh needs the scope repo for pushing branches into your fork and workflow for updates in .github/workflows. Both are part of the default scopes of gh auth login.

task renovate:fork takes the token from gh auth token for each run. It is passed only to renovate and not stored anywhere. A token in RENOVATE_TOKEN is used instead, if it is set.

4.3. Run renovate against your fork

renovate clones your fork from GitHub, creates a branch for each update and pushes it together with a Pull-Request into your fork. The configuration is taken from renovate.json in FORK_BASE of the fork, not from your working tree. renovate.json, tools/renovate/changelog_fragment.sh and tools/renovate/ocenv_update.sh must be pushed into FORK_BASE before the first run. Without renovate.json renovate skips the fork (disabled-no-config).

FORK_REPO is the fork on GitHub, FORK_BASE the branch for the updates (default: master).

# show what would be done
task renovate:fork:dry-run FORK_REPO=<github user>/ansible-oracle

# create branches and Pull-Requests in the fork
task renovate:fork FORK_REPO=<github user>/ansible-oracle

# with milestone and labels for the Pull-Requests
task renovate:fork FORK_REPO=<github user>/ansible-oracle M=<milestone> L=<label>,<label>

Optional parameters for the Pull-Requests:

  • M: number or title of a milestone in FORK_REPO. The task fails, when the title does not exist.

  • L: comma separated list of labels. Missing labels are created by GitHub.

Milestone and labels are set, when renovate creates a Pull-Request.

The tasks have no hourly limit for new Pull-Requests (prHourlyLimit is 2 in config:recommended), each run creates all Pull-Requests. The limit of 10 open Pull-Requests (prConcurrentLimit) is still active.

The branches can be tested locally after git fetch origin.

The branches are named pr/renovate/<update>, so the github-Actions are started for each push. Each update adds a changelog fragment changelogs/fragments/renovate-<dependency>.yml in section minor_changes, created by tools/renovate/changelog_fragment.sh. Grouped updates (e.g. ansible-lint in requirements, pre-commit and workflow) add one fragment renovate-<group>.yml for the whole group. The PR reference is added later with tools/release/fix_fragments.py.

Note
renovate keeps the clones and its cache in ~/.cache/renovate. The clone is reset by each run, do not use it as working copy.

4.4. Run renovate against upstream

Important
Only for maintainers with write access to oravirt/ansible-oracle.
The branches and Pull-Requests are created in the upstream repository and are public.

renovate runs directly on the upstream repository (UPSTREAM_REPO, default oravirt/ansible-oracle) and UPSTREAM_BASE (default master). The branches pr/renovate/<update> are pushed into the upstream repository, so they do not collide with the branches of task renovate:fork in your fork. The configuration is taken from renovate.json in UPSTREAM_BASE.

# show what would be done
task renovate:upstream:dry-run

# create branches and Pull-Requests in upstream
task renovate:upstream M=<milestone> L=<label>,<label>

The task fails, when your GitHub account has no write access to UPSTREAM_REPO. M and L work as described for task renovate:fork, the milestone is searched in UPSTREAM_REPO.

5. Update Vagrantbox on vagrantcloud for examples

Important
This is only an example how to do it, when custom images should be used.

5.1. Create new Box

git clone https://github.com/Rendanic/bento.git
cd bento
git checkout oc
cd packer_templates/oraclelinux/
./oc_oracle-7.x_vbox.sh oracle-7.9-x86_64.json

5.2. Upload new Version

Important
Change the boxname to an account with write privileges.
Upload new version after build:
boxname="Rendanic/oraclelinux-7.x"
vagrantversion=$(date +%y%m%d)

vagrant cloud version create ${boxname} "$vagrantversion"
vagrant cloud provider create ${boxname} virtualbox "$vagrantversion"
vagrant cloud provider upload ${boxname} virtualbox "$vagrantversion" ../../builds/oracle-7.9.virtualbox.box
vagrant cloud publish --release ${boxname} "$vagrantversion" virtualbox

6. ansible molecule

Warning
The timeout for pulling docker Container in molecule is 15s at the moment.
There is no parameter to increase the timeout. Pull container manually before starting the scenario. The image url is defined in molecule.yml.

The following scenarios are existing in the `ansible-oracle profect.

Stage Description

dbfs

Full stage for installation of RDBMS 19c + Patching and create database, AHF registered as client in AHF Fleet Insights of the scenario ahf (see Oracle Autonomous Health Framework (AHF)). Requires installation media in /vagrant on local host.

dbfs-ol9

Full stage for installation of RDBMS 19c + Patching on OL9 and create database. Requires installation media in /vagrant on local host.

dbfs-ol10

Same as dbfs on OL10: Oracle AI Database 26ai with module tests. Requires installation media in /vagrant on local host.

dataguard

Data Guard on OL10 with Oracle AI Database 26ai: 2 containers dataguard-1 (primary) and dataguard-2 (standby created by oradb_standby), broker configuration DG1. Side-effect: switchover tests, see Data Guard tests. Requires installation media in /vagrant on local host.

default

Stage for testing common and orahost roles with different Distributions.

download

Download Patches from support.oracle.com for dbfs stage.

golden

Create Golden-Image for installation from dbfs.

ahf

AHF Fleet Insights with repository in a container with Oracle Database Free and AHF registered as client: 2 containers ahf and ahf-db, network molecule-ahf. Requires a MOS login (downloads) and AHFFI-LINUX_v*.zip, see Oracle Autonomous Health Framework (AHF).

6.1. Directory for installation media and patches

The scenarios dbfs, dbfs-ol9, dbfs-ol10, dataguard, download, golden and ahf mount a local directory as /vagrant into the container. The local directory must be defined by MOLECULE_SW_DIR, there is no default. The path inside the container is always /vagrant.

Set the directory as environment variable
export MOLECULE_SW_DIR=/mnt/d/ORACLE/sw/linux64
or permanently in extensions/.env (ignored by git)
MOLECULE_SW_DIR=/mnt/d/ORACLE/sw/linux64

extensions/.env contains KEY=VALUE lines in shell syntax (no YAML). It is loaded by the Taskfile and tools/regression.sh with tools/load_env.sh. Variables already set in the environment have precedence over the file.

Important
molecule itself does not read extensions/.env. Use task, the wrapper tools/molecule.sh (e.g. tools/molecule.sh test -s dbfs) or load the file into the shell with set -a; . ./.env; set +a before calling molecule directly.

6.2. Taskfile

extensions/Taskfile.yml wraps the molecule commands. The scenario is selected with S= (default: default).

cd extensions
task --list
task pull                      # pull container images before the 1st run
task converge S=dbfs-ol9
task converge S=dbfs-ol9 -- -vv  # arguments after -- are passed to molecule
task converge S=dbfs-ol9 C=false # without reinstalling the collection
task login S=default H=ol9
task destroy S=dbfs-ol9
task collection                # reinstall collection after role changes

task converge and task test install the collection from the repository (task collection) before molecule is started. The dependency step of molecule installs the collection only when the version in galaxy.yml has changed. Without the installation, changes in plugins/ or roles/ are not used. C=false skips the installation.

Several molecule runs may run in parallel, but the installation must not replace the collection while another run uses it (missing files in the running scenario). A lock file (tools/lock.sh, default extensions/.molecule.lock in the checkout, the same for all shells) prevents this:

  • tools/molecule.sh holds a shared lock during the molecule run (not for login and list).

  • tools/collection_install.sh needs an exclusive lock and fails immediately, when another run is active. Start the second run with C=false.

  • tools/regression.sh installs the collection with the exclusive lock and keeps a shared lock for its scenarios.

The tasks are also available from the repository root as task molecule:<task>.

6.3. Test OS roles

Important
This scenario is used, when changes at OS roles should be tested against different OS Distribuitions.
Most of the tests are included in the dbfs scenario!

The execution time is ~10m for a full test.

The default scenario requires no parameter -s!

Start download
cd extensions
molecule test

6.4. Download Patches for dbfs stage

Important
Make sure that /vagrant has enough free space for installation media and patches.
set environment variables for support.oracle.com login
export MOS_USERNAME=Username
export MOS_PASSWORD=verySecret
or store them in extensions/.env (ignored by git)
MOS_USERNAME=Username
MOS_PASSWORD='verySecret'

Environment variables have precedence over extensions/.env. Quote the password with ' when it contains special characters of the shell like a blank, $, #, " or ;. Restrict the access to the file with chmod 600 extensions/.env.

Start download
cd extensions
tools/molecule.sh test -s download

molecule test does the full test of the scenario.

6.5. Test Single Instance in Filesystem with scenario dbfs

Important
Make sure that the installation media and patches are placed in /vagrant before starting molecule.
Use the scenario download for downloading the Patches from support.oracle.com.

The execution time is ~2h for a full test.

Start download
cd extensions
molecule test -s dbfs

6.6. Create Golden-Images from dbfs installation

Important
Make sure that all requirements for scenario dbfs are met.
Executing a full test with molicule test -s golden will destroy an existing installation from molecule converge -s dbfs!
Start Golden-Image creation
cd extensions
molecule test -s golden

6.7. Oracle Autonomous Health Framework (AHF)

The roles of Oracle Autonomous Health Framework (AHF) are tested in three scenarios. The scenario ahf is the AHF Fleet Insights server, dbfs and has-ol9 are clients and upload their data into it.

AHF is downloaded with AutoUpgrade in all of them (extensions/molecule/shared_config/playbooks/ahf_download.yml): latest autoupgrade.jar from Oracle, AHF with target_version: 19, platform: LINUX.X64, patch: AHF into /u01/stage/download in the container. The MOS login is taken from MOS_USERNAME / MOS_PASSWORD or extensions/.env like in the scenario download.

Table 1. Scenarios for AHF
Scenario Installation media Test

ahf

AHF: AutoUpgrade.
AHF Fleet Insights: AHFFI-LINUX_v*.zip from MOLECULE_SW_DIR or download from My Oracle Support (molecule_ahffi_file, molecule_ahffi_aru in host_vars/ahf.yml, Doc ID 3043060.1)

Containers ahf (Fleet Insights, AHF client) and ahf-db (repository database, image gvenzl/oracle-free:23-slim-faststart, no Ansible), network molecule-ahf.
prepare: downloads, Oracle Instant Client, schema user AHFFI in FREEPDB1 of ahf-db with the grants of create_db_user.sql
converge: role ahf_fleet_insights (certificate with SAN), role ahf registered in Fleet Insights
idempotence: second run without changes
verify: ahfctl statusahf, TFA daemon, ahffi status, web application on port 5005, registration, tables of AHFFI

has-ol9

AHF: AutoUpgrade (Java: JDK of the GI-Home)

AHF with Oracle Restart 26ai, ASM and a 19c database, client of Fleet Insights.
converge (after manage_db): role ahf with Compliance scheduler, registration in Fleet Insights
verify: ahfctl statusahf, TFA daemon, CRS/ASM/RDBMS discovered by TFA (tfactl print directories), Compliance autoruns, registration

dbfs

AHF: AutoUpgrade (Java: JDK of the DB-Home)

AHF with a 26ai Single Instance, client of Fleet Insights (extensions/molecule/dbfs/ahf.yml, after manage_db).
verify: ahfctl statusahf, TFA daemon, registration

The clients use the shared playbooks in extensions/molecule/shared_config/playbooks:

  • ahf_fleet_connect.yml: connects the container to the network molecule-ahf (docker network connect on the Ansible controller), checks https://ahf:5005/ahfservice and reads the certificate of Fleet Insights from the container ahf.

  • ahf_client.yml: role ahf and one TFA collection (tfactl diagcollect -last 1h) for the upload. Fleet Insights is optional for dbfs and has-ol9: without the scenario ahf, AHF is installed and verified, the registration is not changed (ahf_fleet_insights_manage: false) and the Fleet Insights checks of verify are skipped (extensions/molecule/shared_config/tasks/ahf_fleet_verify.yml). Only the scenario ahf requires Fleet Insights.

Run the scenarios
cd extensions
task converge S=ahf                # Fleet Insights server first
task verify S=ahf
task converge S=has-ol9 C=false    # clients, C=false while another run is active
task verify S=has-ol9
task converge S=dbfs C=false
task verify S=dbfs

Notes:

  • The variables are in extensions/molecule/shared_config/inventory/host_vars/ahf.yml (server) and group_vars/all/ahf.yml (URL, network and registration user for all scenarios).

  • The downloads are executed by prepare of ahf only once after create. They are repeated after destroy.

  • Fleet Insights needs Internet access for the Oracle JDK and Oracle Instant Client (yum.oracle.com, download.oracle.com).

  • molecule_ahf_collect: false skips the TFA collection of the clients.

  • Oracle recommends 16 GB RAM for Fleet Insights. The containers ahf and ahf-db need about 5 GB in idle state.

  • The data in Fleet Insights is checked in the web interface, there is no automatic check of the uploaded data.

  • The web interface is published on the host: https://localhost:5005/ahfservice (another port with MOLECULE_AHF_PORT, the mapping is created with the container). For a container created without the mapping: docker run -d --name ahf-proxy --network molecule-ahf -p 5005:5005 docker.io/alpine/socat tcp-listen:5005,fork,reuseaddr tcp-connect:ahf:5005

6.8. Data Guard tests

The side-effect of the scenario dataguard tests the Data Guard configuration created by converge (extensions/molecule/dataguard/side_effect.yml, tasks in extensions/molecule/dataguard/tasks):

  1. Initial state: broker configuration SUCCESS, DB1_SITE1 primary (READ WRITE), DB1_SITE2 physical standby (MOUNTED)

  2. VALIDATE DATABASE (repeated until Ready for Switchover: Yes) and switchover to DB1_SITE2

  3. Roles after the switchover, tempfiles of all temporary tablespaces of the new primary (RMAN DUPLICATE does not copy tempfiles, they are created when the standby is opened as primary)

  4. Switchover back to DB1_SITE1, roles and tempfiles

cd extensions
task side-effect S=dataguard

The tests connect with dgmgrl and sqlplus from dataguard-1 with the connect identifiers of db_standby_config, the SYS password is passed with stdin (no_log). After a failed test the configuration may stay switched over: the next run expects DB1_SITE1 as primary.

6.9. Module tests

The side-effect of the scenarios dbfs, dbfs-ol10 and has-ol9 tests the modules of opitzconsulting.ansible_oracle against an existing database. The tests are shared by the scenarios in extensions/molecule/shared_config/module_tests, only the scenario specific variables are in <scenario>/module_tests.yml.

Scenario Environment

dbfs

Oracle AI Database 26ai on filesystem without Grid Infrastructure (CDB DB1, PDB ORCLPDB)

dbfs-ol10

Same as dbfs on Oracle Linux 10

has-ol9

Oracle Restart 26ai with ASM, Oracle Database 19c in +DATA (CDB DBHAS, PDB ORCLPDB1)

The database is created once with converge, the tests can be repeated as often as needed.

6.9.1. Usage

cd extensions
task converge S=dbfs                                    # once (creates the database)
task module-test                                        # all module tests in dbfs
task module-test M=oracle_user,oracle_role              # selected modules
task module-test L=cx_oracle                            # result file dbfs/module_tests_results/cx_oracle.json
task module-test M=oracle_user C=false                  # without reinstalling the collection
task module-test S=dbfs-ol10                            # all module tests in dbfs-ol10
task module-test S=has-ol9                              # all module tests in has-ol9
task module-test S=has-ol9 M=oracle_asmdg               # selected modules in has-ol9

task module-test installs the collection from the repository (task collection) and runs molecule side-effect -s <scenario> with the environment variables MODULE_TESTS (comma separated list of modules) and MODULE_TESTS_LABEL (name of the result file).

Important
molecule side-effect alone does not install the collection.
Without task collection the tests use the code of the last task converge or task collection.

C=false skips task collection, e.g. for repeated runs when only the tests in module_tests/ have changed (they are read from the repository, not from the installed collection). Changes in plugins/ or roles/ are not used until the collection is installed again.

6.9.2. Structure

<scenario>/side_effect.yml imports shared_config/module_tests/module_tests.yml. The playbook loads vars.yml, known_bugs.yml and <scenario>/module_tests.yml (found with MOLECULE_SCENARIO_DIRECTORY).

Table 2. Variables in <scenario>/module_tests.yml
Variable Purpose

mt_all_modules

test files (without .yml) of the scenario

mt_oracle_home, mt_oracle_sid

ORACLE_HOME and ORACLE_SID of the database

mt_tns_admin

directory with tnsnames.ora and sqlnet.ora (wallet)

mt_cdb, mt_pdb

CDB and PDB for the tests

mt_datafile_dir

directory or ASM disk group for explicit data files

mt_known_bugs_scenario

known bugs of the scenario

mt_asm_*, mt_conn_asm*

ASM instance (only has-ol9)

Table 3. Files in shared_config/module_tests
File Purpose

module_tests.yml

playbook, imported by <scenario>/side_effect.yml

vars.yml

connection variants, environment, module selection

known_bugs.yml

known bugs in all scenarios (<check id>: <description>)

_module.yml

run the tests of one module, record an abort as failed check <module>.aborted

_check.yml

compare a registered module result with the expectation and record it

_sql.yml

independent verification with sqlplus / as sysdba (or / as sysasm)

<module>.yml

tests of one module

oracle_services.yml

oracle_services without Grid Infrastructure (DBMS_SERVICE, dbfs)

oracle_services_gi.yml

oracle_services with Grid Infrastructure (srvctl, has-ol9)

oracle_asmdg.yml

oracle_asmdg with an own disk group on the spare ASM disks (has-ol9)

oracle_crs_listener.yml

oracle_crs_listener with an own listener MOLTEST_LSNR (srvctl, has-ol9)

6.9.3. Result of a test run

A failed check does not stop the test run, the play fails at the end (Assert that all checks passed).

An error outside of a check (e.g. a failed setup or cleanup in _sql.yml, a template error in a test) aborts only the tests of this module. It is recorded as failed check <module>.aborted with the failed task and the error message, the other modules are tested anyway. Test objects left behind are removed by the cleanup at the beginning of the next run.

At the end the play shows

  • Summary per module: a table with the number of checks per module and in total: passed, failed, known (known bug), not repr. (known bug not reproduced) and time (runtime of the tests of the module, also for an aborted module)

  • Summary of module tests: the result file and the lists of the failed checks, the known bugs and the known bugs not reproduced

The runtime per module is written into <scenario>/module_tests_results/<label>.durations.json (list of module and duration_s) - useful to find slow modules.

Every check is written into <scenario>/module_tests_results/<label>.json on the controller (ignored by git), also after an abort:

Key Content

id

id of the check

module

test file of the module (entry of mt_modules)

expect

changed, ok or failed

actual

changed, ok, failed or aborted

status

passed, failed, known (known bug) or fixed (known bug not reproduced)

msg

message of the module (max. 500 characters)

Comparison before/after a change
task module-test L=before
task module-test L=after
diff molecule/dbfs/module_tests_results/before.json molecule/dbfs/module_tests_results/after.json

6.9.4. Known bugs

known_bugs.yml (mt_known_bugs_common) contains the ids of checks that fail because of a known bug in a module in all scenarios. Bugs that depend on the environment (database version, Grid Infrastructure) are in mt_known_bugs_scenario in <scenario>/module_tests.yml.

They are reported as KNOWN BUG and do not fail the test run. A check from these lists that passes is reported as KNOWN BUGS NOT REPRODUCED ⇒ remove the entry after the bug has been fixed.

6.9.5. Conventions for a module test

  • File module_tests/<module>.yml, added to mt_all_modules in <scenario>/module_tests.yml.

  • No scenario specific values in the tests: use mt_cdb, mt_pdb, mt_oracle_home, mt_datafile_dir etc.

  • All test objects start with MOLTEST_ (common objects in the CDB: C##MOLTEST_).

  • The test is repeatable and leaves the database unchanged: remove the objects at the beginning (cleanup, result ignored) and at the end. Changed parameters, AWR settings etc. are restored.

  • Every module call has register: _res and ignore_errors: true, followed by _check.yml with a unique id <module>.<cdb|pdb|asm>.<step> and the expectation:

    - name: oracle_role | create
      opitzconsulting.ansible_oracle.oracle_role:
        role: MOLTEST_ROLE
      register: _res
      ignore_errors: true
    - name: oracle_role | check create
      ansible.builtin.include_tasks: _check.yml
      vars: {mt_id: oracle_role.pdb.create, mt_res: "{{ _res }}", mt_expect: changed}
  • Typical steps: create (changed), same call again (ok), check mode if supported (changed, verify with sqlplus that nothing happened), change (changed), again (ok), verify with _sql.yml, drop (changed), drop again (ok), error case (failed).

  • The expectation is the documented behaviour (DOCUMENTATION of the module). If the module behaves differently because of a bug, the check keeps the documented expectation and the id goes into known_bugs.yml (all scenarios) or mt_known_bugs_scenario (only one scenario).

  • Connection: hostname, port, service_name, user, password and mode come from module_defaults in module_tests.yml. Default is mt_conn_pdb (system in mt_pdb). Switch it with vars: {mt_conn: "{{ mt_conn_cdb }}"} on the task. Variants in vars.yml: mt_conn_cdb, mt_conn_pdb, mt_conn_cdb_sysdba, mt_conn_pdb_sysdba, mt_conn_pdb_wallet, mt_conn_pdb_wrong_password. Every module test uses the wallet and sysdba at least once.

  • Verification with sqlplus (independent of the Python driver), in the ASM instance with mt_sql_asm: true (sqlplus / as sysasm):

    - name: oracle_role | verify create
      ansible.builtin.include_tasks: _sql.yml
      vars:
        mt_sql_container: "{{ mt_pdb }}"
        mt_sql: "select count(*) from dba_roles where role = 'MOLTEST_ROLE';"
        mt_sql_expect: "1"
        mt_sql_id: oracle_role.pdb.create_sql
  • Not tested: oracle_asmvol (no ADVM/ACFS in a container), oracle_ldapuser (LDAP), oracle_opatch, oracle_gi_facts, oracle_sqldba (no python-oracledb).

6.10. Controller-only tests of oracle_databases

task test:oracle_databases (in extensions/) tests combinations of attributes in oracle_databases on localhost without container, VM or database (about 20 seconds):

  • asserts of orasw_meta (assert_oracle_databases.yml): omf, is_container, storage_type, db_create_file_dest / db_recovery_file_dest in init_parameters, removed datafile_dest / recoveryfile_dest

  • destinations for dbca from oradb_manage_db/vars/main.yml

  • values in the dbca response file (19.3.0.0, 26.1.0.0), e.g. createAsContainerDatabase

The test cases are in extensions/tests/oracle_databases/cases.yml (expect: ok|failed, optional warn, dest and rsp). The playbook fails at the end with a list of all failed checks.

Run without Taskfile
ansible-playbook -i localhost, extensions/tests/oracle_databases/test_oracle_databases.yml

6.11. Regression tests

task molecule:regression:<preset> runs several scenarios with a report per run (extensions/Taskfile.regression.yml, extensions/tools/regression.sh).

  • The collection is installed once before all scenarios.

  • The scenarios run in parallel (J, default 6), the steps of a scenario one after the other.

  • A failed create or converge skips the remaining steps of the scenario.

Table 4. Presets
Task Steps

molecule:regression:final

destroy, converge, module-test

molecule:regression:full

destroy, converge, idempotence, module-test

molecule:regression:retest

module-test in the existing containers

molecule:regression:idempotence

idempotence, module-test in the existing containers

molecule:regression:run T=<steps>

free combination of destroy, create, converge, idempotence, module-test, verify

molecule:regression:report RUN=<run-id>

create and show summary.md (default: last run)

molecule:regression:list

last runs with the number of failed steps

Variables: S scenarios (comma separated, default dbfs,dbfs-sh,has-ol9,dataguard), J scenarios in parallel, M module tests (MODULE_TESTS).

Every run creates extensions/test-runs/<date>-<time>_<commit>[-dirty]/ (not in git), extensions/test-runs/latest points to the last run:

File Content

run.env

commit, branch, parameters, start and end

git-status.txt

uncommitted changes of the tested code

steps.jsonl

one JSON line per finished step: scenario, step, rc, duration, logfile

<scenario>-<step>.log

output of molecule without colors

module_tests/<scenario>.json

result of the module tests (MODULE_TESTS_LABEL=<run-id>)

module_durations/<scenario>.json

runtime per module of the module tests

summary.md

report: scenario x step, module tests, runtime per module (slowest first), changed tasks of idempotence, errors of failed steps

summary.md is updated after every step and can be read while the run is in progress. Failures with fatal: are shown first, failures of loop items (failed: [host] (item=…​)) are often rescued negative tests.

6.12. Run molecule tests with Claude Code

tools/claude/skills/aotest contains the skill /aotest for Claude Code. It runs the molecule actions of extensions/Taskfile.yml inside nix-shell and reports the result.

Install the skill like /pr (see Create Pull-Requests with Claude Code):

mkdir -p ~/.claude/skills
ln -sfn "$(pwd)/tools/claude/skills/aotest" ~/.claude/skills/aotest
Usage
/aotest [S=<scenario>] [T=full|destroy|converge|module[,...]] [M=<module>[,<module>...]]
Argument Default Description

S=<scenario>

dbfs

Scenario in extensions/molecule.

T=<action>[,…​]

module

Actions in the given order: full (task test), destroy, converge, module (task module-test).

M=<module>[,…​]

all modules

Modules for T=module, see Module tests.

Examples
/aotest                                   # module tests in dbfs
/aotest S=has-ol9 M=oracle_asmdg
/aotest S=dbfs T=destroy,converge,module
/aotest S=dbfs-ol10 T=full
  • Scenario, actions and modules are checked before the start.

  • Each action runs in the background with its own log file. A failed action stops the following actions.

  • T=module on a scenario without running instances is not started, the skill proposes T=converge,module.

  • The report contains the PLAY RECAP, the summary of the module tests and the failed checks with message. The skill does not change code or tests.

Important
Invoking /aotest allows Claude to run the requested actions, including destroy and converge, without further confirmation.

6.13. Oracle XE (not used at the moment!)

Important
This chapter was designed for testing the oradb_managed_-Roles.
It is not clear if this will be added or not.
Docker pull Oracle XE

Normal SSO-Login from Oracle is needed for login to docker registry.

docker login container-registry.oracle.com
docker pull container-registry.oracle.com/database/express:21.3.0-xe
Start Oracle Container for test
docker run -d --name oracle-xe \
  -e ORACLE_PWD=Oracle_123 \
  -p 1521:1521 \
  container-registry.oracle.com/database/express:21.3.0-xe

4.2 - Website

1. How to develop the documentation page?

The documentation is build with hugo and Docsy as template.
There is a container for building or starting a hugo server for easy development of the documentation.

The Setups between Docker or Podman is a little bit different.

2. Where is the content?

The pages of the documentation are not copied into website/. hugo reads them directly from the repository:

Source Page

doc/.adoc, doc/guides/.adoc, doc/*.md

Guides, features and development

roles/*/README.md

One page per role (generated by ansible-doctor)

website/content/

Start page, About and the introduction of each section (_index.md)

website/hugo.yaml mounts doc/ and roles/ below assets/. The content adapter website/content/docs/_content.gotmpl creates the pages from them:

  • The first heading of a file is used as the page title, unless a title is set in $settings of the content adapter.

  • Relative links (AsciiDoc link: macro or Markdown link) are rewritten to the pages of the website. Links to files without a page point to GitHub.

  • The "Edit this page" link points to the source file below doc/ or roles/.

  • "Last modified" shows the last commit of the source file. scripts/gitinfo.py writes it to website/data/gitinfo.json before each build (hugo would show the commit of the content adapter instead).

  • A new file in doc/guides/ appears automatically. New files in other directories need a rule in $rules of the content adapter.

Important
Do not use include:: in files below doc/. hugo passes the content to asciidoctor by stdin and GitHub does not render includes either. Use a link instead.

3. Tasks

website/Taskfile.yml contains the commands for building and testing the page. task is part of the nix-shell of ansible-oracle.

cd ansible-oracle/website
task                # list all tasks
task serve          # live server on http://localhost:1313
task build          # build the page into public/
task test           # build + check internal links
task test:a11y      # build + accessibility check (WCAG 2 AA) of all pages
task publish        # build + commit in the clone of the website repository
task publish:push   # build + commit + push => GitHub Pages publishes the website
task publish:pr     # build + commit + pull request in the website repository

The tasks can be started from the root of the repository with prefix website:, e.g. task website:test.

4. Publishing

The website is published with GitHub Pages from the directory docs/ in the branch main of Rendanic/ansible-oracle-website.

The publish tasks call tools/release/build_website.sh:

  • The sources in website/, doc/, roles/ and docker/hugo/ must be committed.

  • The legal notice must be published (no draft: true).

  • The website repository is cloned to ~/.cache/ansible-oracle-website with gh.

  • docs/ is replaced by the new build, CNAME is kept and .nojekyll is added (GitHub Pages ignores directories with a leading _ like _print/ without it).

Options of the script are passed after --, e.g. task publish — -a for an additional accessibility check or task publish — -f to ignore uncommitted changes and a missing legal notice (for tests only).

Podman is used with task build COMPOSE=podman-compose COMPOSE_USER=root.

The checks run in containers:

  • check:links uses lychee for all links in public/.

  • check:a11y uses pa11y-ci with the runners axe and HTML_CodeSniffer for all pages in sitemap.xml. The settings are in website/.pa11yci.json. The axe rule color-contrast is ignored: axe cannot determine the background below the fixed navbar and sidebar and reports hundreds of false positives. The contrast is still checked by HTML_CodeSniffer.

5. Colors and contrast

The whole site uses one polarity: dark text on a light background. Docsy’s dark navbar, cover blocks and footer are replaced in

  • website/layouts/partials/navbar.html (copy of Docsy with data-bs-theme="light")

  • website/assets/scss/_styles_project.scss (navbar, footer, buttons, links and Prism token colors)

All colors have a contrast ratio of at least 4.5:1 (WCAG 2 AA). Use blocks/lead or blocks/section with color="white" on new pages, not blocks/cover. Code blocks are highlighted by Prism (light theme), Chroma is disabled for Markdown code fences in hugo.yaml.

6. Updates of hugo and Docsy

File Version Updated by

docker/hugo/Dockerfile

hugo and asciidoctor (base image floryn90/hugo)

renovate

website/hugo.yaml

module.hugoVersion.min

manual

website/go.mod, website/go.sum

Docsy (github.com/google/docsy)

renovate (group docsy)

website/Taskfile.yml

lychee, puppeteer, pa11y-ci, http-server (# renovate: comments)

renovate

The image of the hugo container is tagged with the tag of the base image, e.g. rendanic/hugo:0.169.0-ext-ubuntu. A new version in the Dockerfile builds a new image automatically with the next task build.

renovate updates only website/go.mod and website/go.sum. go from shell.nix is needed for go.sum. The steps below are still manual, the Pull-Request of renovate (group docsy) lists them as a note. There is no github workflow which builds the website, so a Docsy Pull-Request is green even when the website is broken.

Steps for an update of Docsy:

  1. Read the release notes of Docsy (minimum version of hugo, breaking changes). Docsy 0.16 and later is a different Hugo module (github.com/docsy/docsy/theme) with Bootstrap and Font Awesome from npm. renovate.json allows only versions below 0.16.

  2. Update website/go.mod and website/go.sum. Run task clean:all afterwards: an old module in website/.cache/modules can remain as empty directories and is not downloaded again (error File to import not found or unknown output format).

  3. task docsy:diff shows the differences between the copied templates in website/layouts/ and the new Docsy version. Apply the changes of Docsy to the copies.

  4. Check website/assets/scss/_styles_project.scss: it uses the Docsy classes .td-navbar, .td-footer, .td-box and .td-content.

  5. task test:all and a look at the start page, a guide and a role page.

Note
security.exec.osEnv in website/hugo.yaml passes GEM_HOME to asciidoctor. Without it, asciidoctor does not find its gem in the base image.
Note
Since hugo 0.170, the SCSS of Docsy is compiled with Dart Sass (sass in the base image), libsass was removed. security.exec.allow in website/hugo.yaml must contain ^sass$. The deprecation warnings of Dart Sass come from Docsy and Bootstrap.

7. Container Setup

The setup of Docker or Podman is described in the Development Guide.

The Dockerfile and docker-compose.yaml of the hugo container are in docker/hugo/. The image is built automatically on the first task build or with task hugo:build in docker/.

8. hugo with Docker

8.1. hugo live server

Important
This only works when current uid in shell is same as ubuntu(1000) inside the container.
cd ansible-oracle/docker/hugo
docker compose run --rm -u ubuntu site -s /src/website server

8.2. Building the public page

Important
This only works when current uid in shell is same as ubuntu(1000) inside the container.
cd ansible-oracle/docker/hugo
docker compose run --rm -u ubuntu site -s /src/website

9. hugo with Podman

9.1. hugo live server

The default user inside the container is hugo with a different uid then the nonroot user of the podman Container.
This results in a permission denied when the uid of nonroot podman user is different then the uid of hugo inside the container while reading volume data. Starting with --user=root starts all processes in the same namespace as the nonroot user which allows access to the volume data.

Start hugo server with Podman
cd ansible-oracle/docker/hugo
~/venv/podman/bin/podman-compose run --rm --user=root site -s /src/website server --bind 0.0.0.0

9.2. Building the public page

cd ansible-oracle/docker/hugo
~/venv/podman/bin/podman-compose run --rm --user=root site -s /src/website