The examples for the guides are part of the project. They are located in example.
This is the multi-page printable view of this section. Click here to print.
Guides
- 1: Vagrant
- 1.1: Vagrant on Windows
- 1.2: Vagrant Basics
- 2: Beginners Guide
- 3: Advanced Guide
- 4: Ansible as a Docker Container
- 5: HOWTO: Local Installation of Ansible-Oracle
- 6: Installation & Patching Settings for the Inventory
- 7: Setup APEX and ORDS
- 8: Oracle AutoUpgrade
- 9: Upgrade of PDBs with AutoUpgrade (Unplug/Plug)
- 10: Oracle Autonomous Health Framework (AHF)
- 11: Out-of-Place Patching - Switch ORACLE_HOME
- 12: Standby Databases
- 13: Breaking Changes - Upgrade Guide
- 14: Setup of Oracle Restart and Grid Infrastructure
- 15: RMAN Backups with oradb_rman
- 16: Data Guard Guide
1 - Vagrant
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. |
-
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. |
bcdedit
The output should contain a line with hypervisorlaunchtype.
If the line is not shown or Off, Hyper-V is completely disabled.
# bcdedit Windows-Start-Manager --------------------- ... Windows-Startladeprogramm ------------------------- ... hypervisorlaunchtype Off
If it is Auto or On
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. |
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
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.
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. |
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!
|
ssh-keygen
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. |
code ~/.ssh/config Host * ForwardAgent yes
eval $(ssh-agent)
eval $(ssh-agent) Agent pid 16840
ssh-add ~/.ssh/id_rsa
$ ssh-add ~/.ssh/id_rsa Identity added: /c/Users/User/.ssh/id_rsa (User@unknown)
ssh-add -l
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
-
Basic command and setup of Vagrant: Preparation for beginner
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
- Download and install Vagrant
- 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
- hmm, cannot download that first OL box, let’s see the oracle doc https://yum.oracle.com/boxes/
- 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
- allows us to resize disks (optional)
In a DOS command prompt…
vagrant plugin install vagrant-disksize
- 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
- 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
- use the command “vagrant ssh” to access the VM per shh in your DOS command prompt
- 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 - 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
1.2. What are we going to do?
-
Prepare the Ansible controller: Ansible in Ubuntu on WSL2 on Windows.
-
Configure the inventory with the IP address and login user of the Oracle Linux 9 VM.
-
Start the playbook
playbooks/do_all.yml. It executes all needed playbooks:-
opitzconsulting.ansible_oracle.os: prepare the VM for AutoUpgrade -
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. -
opitzconsulting.ansible_oracle.single_instance_fs: configure the OS, install the ORACLE_HOME from the gold image and create the database.
-
1.3. Defaults
| Value | Description |
|---|---|
|
git repository on the Ansible controller |
|
Working directory for all Ansible commands |
|
Name of the VM in the inventory |
|
IP address of the VM ( |
|
Login user on the VM ( |
|
Installation media on the VM, target of the download ( |
|
Staging directory on the VM ( |
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.
| Item | Requirement |
|---|---|
Operating system |
Oracle Linux 9 x86_64 |
CPU |
2 vCPUs (recommended) |
Memory |
8 GB RAM (recommended) |
Disk |
|
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
( |
Login user |
User with SSH login and |
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
olwithsudoprivileges and SSH key login, -
the volume group
olon/dev/sda3, as expected byhost_fs_layoutin this guide, and -
the SSH public key
%USERPROFILE%\.ssh\id_ed25519.pub.
git clone https://github.com/Rendanic/packer-hyperv.git cd packer-hyperv
task hyperv:hyperv-add-admin-user
task hyperv:packer-ol9
task hyperv:packer-ol9 SSH_KEY_FILE=C:\path\to\key.pub
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 Switchwith DHCP for the internet access -
the switch from
-ExternalSwitchwith the fixed IP address from-FixedIP. Use this address foransible_hostininventory/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.
|
| Item | Requirement |
|---|---|
Python |
Python 3 with |
Ansible |
|
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. |
sudo apt update sudo apt install -y git python3-venv
mkdir -p ~/git cd ~/git git clone https://github.com/oravirt/ansible-oracle.git
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.
|
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.
---
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.
ssh-keygen -t ed25519
ssh-copy-id ol@192.168.66.161
4.3. Check the connection
cd ~/git/ansible-oracle/example/beginner/ansible ansible all -m ansible.builtin.ping
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.
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.
MOS_USERNAME=<your My Oracle Support login> MOS_PASSWORD=<your My Oracle Support password>
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
pexpectfor the keystore with the My Oracle Support credentials, -
a JDK for
autoupgrade.jarand -
the download directory
/u01/swon 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.
| Variable | Value | Description |
|---|---|---|
|
|
Download the latest |
|
|
Gold image for 26ai with all recommended patches |
|
|
Rename the gold image to |
|
|
Symlink |
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.
ls -l /u01/sw/db_home_*.zip
db_home_26.04.zip db_home_26_latest.zip -> db_home_26.04.zip
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
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. |
| Parameter | Value |
|---|---|
ORACLE_BASE |
|
ORACLE_HOME |
|
ORACLE_SID |
|
PDB |
|
db_create_file_dest |
|
db_recovery_file_dest |
|
Listener |
|
7. How to work with the installed database
ssh ol@192.168.66.161
sudo -iu oracle
ocenv
ocenv shows the ORACLE_HOMEs, databases and listeners on the host.
envhelp shows an overview of the commands.
DB1
sql
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
1.1.2. Defaults
| 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.
|
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.
|
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.
|
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. |
cp ~/.ssh/id_rsa.pub ~/git/ansible-oracle/ansible-oracle/example/beginner
eval $(ssh-agent)
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.
|
cd ~/git/ansible-oracle/ansible-oracle/example/beginner VAGRANT_EXPERIMENTAL=disks vagrant up
1.2.3.1. What happens when I start vagrant?
-
Using the vagrantfile, an Oracle Linux VM is installed (2x CPU, 4096MB RAM, 150GB HDD). IP = 192.168.56.161
-
A mount point /vagrant is available in the Oracle Linux VM. This is a shared folder from your Windows machine.
-
Your ssh key is used to connect to the VM in a secure way
-
docker is installed in the Oracle Linux VM
-
docker-compose is installed in the Oracle Linux VM
-
The ansible-oracle repository is cloned to the Oracle Linux VM
-
A docker container "Ansible Container" is built with docker-compose. This runs in the Oracle Linux VM
-
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! |
git+bashssh -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…
[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
[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. |
ansible@ansible-oracle:/git/ansible-oracle/example/beginner/ansible$ ansible-galaxy collection install -r requirements.yml
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. |
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
git+bashssh -A vagrant@192.168.56.161
1.3.6. Sudo oracle
[vagrant@beginner-dbfs-151-192-168-56-161 ~]$ sudo su - oracle
[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
[oracle@beginner-dbfs-151-192-168-56-161 ~]$ ocenv
[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
[oracle@beginner-dbfs-151-192-168-56-161] [] [~] $ DB1
[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
[oracle@beginner-dbfs-151-192-168-56-161] [DB1] [~] $ sql
[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>
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
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.
-
ansible-oracle zip file from GitHub (this very repository)
-
Ansible Collections: The versions mentioned here are specific for Ansible-Oracle 4.11 and Ansible 2.14. For other versions, check the dependency list in the file "galaxy.yml" in the root directory of this repository. When downloading from Ansible Galaxy, make sure to select modules for your version Ansible.
-
https://galaxy.ansible.com/ui/repo/published/opitzconsulting/ansible_oracle/
-
https://galaxy.ansible.com/ui/repo/published/ansible/posix/ 1.5.4
-
https://galaxy.ansible.com/ui/repo/published/ansible/utils/ 5.1.0
-
https://galaxy.ansible.com/ui/repo/published/community/general/?version=9.5.4 (for Ansible 2.14)
-
https://galaxy.ansible.com/ui/repo/published/community/crypto/
-
https://galaxy.ansible.com/ui/repo/published/devsec/hardening/ 8.8.0
-
https://galaxy.ansible.com/ui/repo/published/community/mysql/ (Dependency for Hardening)
-
-
Python Packages (for
pip install): Get them viapip download <package>-
oracledb (for the target hosts); If you
pip downloadthis, you’ll also get:-
pycparser
-
cffi
-
cryptography
-
-
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.
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:
-
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.
-
The binaries are stored in compressed form on NFS and should be copied over to the target, where they get unpacked and installed.
-
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.
-
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 |
|---|---|---|
|
|
|
|
|
Transfer archive to |
|
|
Unpack archive on the target |
|
|
Path on the Ansible control node where archives are read from |
|
|
Mount NFS on the target; sets both copy/unpack flags to |
|
|
Local staging directory on the target |
|
|
NFS mount point on the target |
|
|
Local patch staging directory on the target |
|
|
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 |
|---|---|---|---|---|
|
|
|
|
|
|
|
|
n/a |
n/a |
|
|
|
|
|
|
|
|
|
|
|
path on control node |
NFS mount on control node |
— |
— |
|
— |
— |
NFS mount on target |
NFS mount on target |
|
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.
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.ymlsupported 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.
| Value | Description |
|---|---|
|
The parameter is mandatory, because it is the only way to configure a password for the admin user at the moment. |
| Value | Description |
|---|---|
|
Default: |
|
Default: |
|
Default: |
|
Default: |
|
Default: |
2.2. APEX in PDB
APEX can be installed in each PDB.
| Value | Description |
|---|---|
|
Must be |
|
State for APEX installation. |
|
Version of APEX. |
| Value | Description |
|---|---|
|
Custom APEX Tablespace. |
|
Custom APEX Tablespace for files. |
|
Custom APEX temporary Tablespace. |
|
Custom image path for |
|
Default: |
|
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. |
oracle_pdbsoracle_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.
dbpasswords for APEX in a PDBdbpasswords:
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.
oracle_sw_patchesoracle_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. |
| Value | Description |
|---|---|
db_pool |
Database Pool. |
service |
Database Service Name |
| Value | Description |
|---|---|
host |
Database Hostname |
port |
Listener Port |
admin_user |
Admin user for the ORDS installation |
feature_db_api |
true / false (Default) |
feature_rest_enabled_sql |
true / false (Default) |
feature_sdw |
true / false (Default) |
| Value | Description |
|---|---|
|
Directory with the APEX images on the ORDS host ( |
|
Context path for the APEX images ( |
|
Default: |
|
Default: |
|
Default: |
|
Default: |
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.
|
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.jaron the database servers or on the Ansible controller -
Download of the latest
autoupgrade.jarfrom 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:
javafromPATHorautoupgrade_local_java_home
-
-
Python module
pexpecton the host executing AutoUpgrade for the keystore management (used byansible.builtin.expect). It is checked byinstall.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.
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.
| Variable | Description |
|---|---|
|
Username for the proxy (optional) |
|
Password for the proxy (optional). Use Ansible Vault. |
|
Additional Java options for AutoUpgrade, e.g. a 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.ymlwithautoupgrade_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.
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:
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.
| Error | Hint |
|---|---|
|
wrong or missing credentials for the proxy |
|
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 |
|
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.
|
| Variable | Default | Description |
|---|---|---|
|
|
|
|
hosts of AutoUpgrade 26 |
URLs for |
|
|
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.
|
| Task file | Description |
|---|---|
|
Check variables and Java. Included by the other task files. |
|
Install |
|
Create/update the keystore with the My Oracle Support credentials. Included by |
|
Download patches with AutoUpgrade. Includes |
|
Analyze phase for the Unplug/Plug upgrade of PDBs ( |
|
Fixups phase ( |
|
Unplug/Plug upgrade of PDBs. Executes |
- name: Install AutoUpgrade
ansible.builtin.import_role:
name: opitzconsulting.ansible_oracle.autoupgrade
tasks_from: install.yml
4. Playbooks
| Playbook | Description |
|---|---|
|
Install AutoUpgrade. |
|
Download patches with AutoUpgrade. |
|
Analyze phase for the upgrade of PDBs. |
|
Fixups phase for the upgrade of PDBs. |
|
Unplug/Plug upgrade of PDBs (analyze phase + deploy). |
ansible-playbook -i inventory/ -e hostgroup=dbservers -e autoupgrade_run_local=false \ playbooks/autoupgrade_install.yml
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.
autoupgrade_run_local |
Executed on | Directory | Java |
|---|---|---|---|
|
Ansible controller, |
|
|
|
target host as |
|
|
|
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.
|
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
pexpectfor the Python interpreter used by Ansible (keystore console).install.ymlchecks it at the beginning and fails with a clear message. The role does not installpexpect- install it e.g. with the packagepython3-pexpector withpip. -
With
autoupgrade_run_local: false:autoupgrade_download_dirmust be a directory on the target host, writable fororacle_user. The defaultoracle_sw_source_localis a directory on the Ansible controller. -
With
autoupgrade_run_local: false:oracle_usermust exist (playbookos).oracle_baseandoracle_base/cfgtoollogsare created byinstall.ymlwith the same attributes as inoraswdb_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 fromoracle_sw_source_localon the Ansible controller -
is_sw_source_local: false: download fromoracle_sw_source_www -
oracle_sw_copy: false: copy fromoracle_stage_remoteon the database server (e.g. NFS mount) -
autoupgrade_jar_filesource: full path toautoupgrade.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:
| Installation media | Download on | Target |
|---|---|---|
|
Ansible controller, |
|
|
target host as |
|
|
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.
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.
|
| Variable | Description |
|---|---|
|
Login for My Oracle Support |
|
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:
-
Keystore exists: check the credentials with
list(online check against My Oracle Support). Nothing is changed, when the credentials are valid. -
Credentials missing or invalid: add the credentials with
add. This requires the keystore password. -
Keystore password rejected, keystore missing or fingerprint changed (
mos_username): remove the keystore and create it again. -
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. |
| Variable | Default | Description |
|---|---|---|
|
|
|
|
|
Keystore password (min. 16 characters). Empty: SHA256 of |
|
|
Remove and create the keystore in each execution |
|
|
Fail, when the login into My Oracle Support is not possible |
|
|
|
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:
-
autoupgrade_download_patches: explicit entries with AutoUpgrade keywords -
oracle_sw_patches,db_homes_installed,db_homes_configandoracle_install_version_gi(same variables as roleorasw_download_patches), whenautoupgrade_download_use_oracle_sw_patches: true(default)
8.1. autoupgrade_download_patches
| Attribute | Mandatory | Description |
|---|---|---|
|
yes |
Release, e.g. |
|
yes |
AutoUpgrade keywords and/or patch numbers, e.g. |
|
no |
Default: |
|
no |
|
autoupgrade_download_patchesautoupgrade_download_use_oracle_sw_patches: false
autoupgrade_download_patches:
- target_version: 19
patch: RU,OPATCH,OJVM,DPBP
gold_image: "NO"
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.
| Keyword | Description |
|---|---|
|
Alias for |
|
Release Update. Without version: latest Release Update. Example: |
|
Latest OPatch for the release |
|
OJVM Release Update. Without version: version of |
|
Oracle Clusterware (Grid Infrastructure) patch. Without version: version of |
|
Data Pump Bundle Patch for the Release Update |
|
Latest Monthly Recommended Patch. Linux only, 19c and 26ai (from 23.26) |
|
AutoUpgrade |
|
One-off patch, e.g. |
|
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.
| Way | When to use |
|---|---|
Patch number in |
One-off patches without entry in |
Keyword in |
Patch types, e.g. |
New entry in |
Patches, which are installed by |
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"
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
filenameinoracle_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_patchescreates 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_installedfor the same release create two sections. This is accepted by AutoUpgrade. Setautoupgrade_download_use_oracle_sw_patches: falseto useautoupgrade_download_patchesonly.
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
-
filenamematchesautoupgrade_download_filename_regex(database patches for Linux x86-64, e.g.p36582781_190000_Linux-x86-64.zip) and -
the release from
versionis inautoupgrade_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:
Entry in oracle_sw_patches |
AutoUpgrade |
|---|---|
attribute |
value of the attribute, e.g. |
attribute |
|
|
|
others |
|
|
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).
oracle_sw_patchesoracle_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
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.
| Value | Description |
|---|---|
|
Default of AutoUpgrade. Resolved to |
|
No gold image. All patches are downloaded from My Oracle Support. For 23.x/26ai |
|
Gold image with the latest OCW and MRP patches. Other patches (e.g. one-offs) are downloaded separately. |
|
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
autoupgrade_download_patches:
- target_version: 19
patch: RU:19.24,OPATCH,OJVM,DPBP
gold_image: ALL
# 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_imageYESorALL). 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,YESorALL.
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_folderfor the creation of new Oracle homes (create_homemode). This is not implemented in the role yet.
db_homes_configsupports golden images (imagename,filesource) for the installation withoraswdb_install. Whether a gold image from AutoUpgrade can be used there, is not tested. -
Information:
patches_info.jsoninautoupgrade_download_dirlists the downloaded gold images with release update and included patches.
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_patchesand the derived entry fromdb_homes_installed/oracle_sw_patchesfor the same release create two sections in the config file. Setautoupgrade_download_use_oracle_sw_patches: false, when onlyautoupgrade_download_patchesshould be used. -
The filename of a downloaded gold image cannot be changed. Gold images are downloaded again in each execution.
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:
| Phase | Task file | Playbook | AutoUpgrade | Downtime | Database changed |
|---|---|---|---|---|---|
Analyze |
|
|
|
no |
no |
Fixups |
|
|
|
no |
yes, the source CDB/PDBs (e.g. statistics, recyclebin) |
Deploy |
|
|
analyze phase, then |
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 targetORACLE_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 As soon as a PDB in
|
2. Upgrade vs. Out-of-Place Patching
Both procedures move a database into a new ORACLE_HOME. They must not be mixed up.
| Topic | Upgrade (this guide) | Out-of-Place Patching |
|---|---|---|
Release of the new |
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 |
role |
Inventory |
|
change of |
Playbook |
|
|
Dictionary |
upgraded by AutoUpgrade |
|
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_HOMEare installed (db_homes_config,db_homes_installed, playbookswdb) -
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 playbookmanage_dbbefore the PDBs are changed inoracle_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_HOMEis used, whenautoupgrade_java_homeis empty -
AutoUpgrade is executed on the database server as
oracle_user. The playbooks setautoupgrade_run_local: false. The task files fail withautoupgrade_run_local: true. -
The Python module
pexpectis 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.
| Attribute | Mandatory | Description |
|---|---|---|
|
yes |
|
|
no |
Key in |
|
no |
SID of the source CDB. Default: |
|
no |
Name of the PDB in the source CDB. Default: |
|
no |
|
|
no |
|
|
no |
Dict with AutoUpgrade parameters ( |
The target is taken from the PDB itself (end state):
-
cdb: target CDB. It must be defined inoracle_databases. -
home: targetORACLE_HOME. It must be the same ashomeof the target CDB inoracle_databases.
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> -
restorationandparametersmust 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.
| AutoUpgrade | Value |
|---|---|
|
SID of the source CDB |
|
|
|
|
|
SID of |
|
PDBs in the source CDB ( |
|
|
|
|
|
|
|
|
|
|
sid, source_home, target_home, target_cdb, pdbs, log_dir and restoration
must not be used in parameters.
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.
| Variable | Scope | Result |
|---|---|---|
|
all jobs |
|
|
one job, overrides |
|
|
config file |
|
| Parameter | Description |
|---|---|
|
|
|
|
|
Recompile invalid objects after the upgrade |
|
Scripts before/after the upgrade |
4.4. Variables of the role
| Variable | Default | Description |
|---|---|---|
|
|
Limit to these PDBs ( |
|
|
Guaranteed Restore Point before the upgrade ( |
|
|
AutoUpgrade parameters for all jobs |
|
|
Additional |
|
|
Fail the analyze/fixups phase on errors without automatic fixup |
|
|
Discard the recovery data of AutoUpgrade before the analyze phase. See Recovery data of AutoUpgrade. |
|
|
Maximum runtime in seconds of the deploy per job |
|
|
Poll interval in seconds during the deploy |
|
|
JAVA_HOME. Empty: |
|
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.
copy_option |
Datafiles | Disk space | Duration | Fallback into the source CDB |
|---|---|---|---|---|
not set (default) |
|
none |
short, independent of the size |
no - the datafiles are upgraded to the new release |
|
copied as Oracle Managed Files into |
size of the PDB |
copy of all datafiles |
yes - the source datafiles stay unchanged |
|
copied, |
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 withalter database move datafilein 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. 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(orpdb_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 withinit_parametersof the target CDB inoracle_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:
| Value | Source CDB after the upgrade |
|---|---|
|
The PDB is dropped from the source CDB ( |
|
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:
-
Drop the upgraded PDB from the target CDB, if needed (
drop pluggable database ORCLPDB1 including datafiles- only with a copy, never with NOCOPY!) -
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 -
Change
oracle_pdbsback 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
| Situation | Option |
|---|---|
Big PDB, short downtime, backup available |
NOCOPY (default) |
Fallback into the source CDB needed, enough disk space |
|
OMF/ASM |
|
Fixed paths without OMF, new directory for the target CDB |
|
|
Important
|
Take a backup of the PDB before the deploy phase - independent of the option. |
6. Process overview
-
Preparation with
manage_db(no downtime) -oracle_pdbsstill points to the source CDB-
Install the target
ORACLE_HOMEwith playbookswdb(db_homes_installed) -
Add the target CDB to
oracle_databasesand create it with playbookmanage_db
-
-
Change the inventory to the end state
-
cdbandhomeof the PDBs inoracle_pdbs: target CDB and targetORACLE_HOME -
Add the attribute
autoupgradewithsource_cdbto the PDBs -
From now on: no
manage_dbuntil the upgrade is done!
-
-
Analyze phase (no downtime):
autoupgrade_upgrade_analyze.yml-
Install
autoupgrade.jaron the database server -
Read the PDBs of the source and the target CDB (
v$pdbs) -
AutoUpgrade
analyzefor the PDBs in the source CDB -
Evaluate the prechecks. Fail on errors without automatic fixup.
-
-
Fix the reported problems and repeat the analyze phase until it is successful
-
Fixups phase (no downtime, optional):
autoupgrade_upgrade_fixups.yml-
AutoUpgrade
fixupsfor the PDBs in the source CDB, e.g. some days before the deploy -
Evaluate the prechecks like the analyze phase
-
-
Deploy phase (downtime of the PDBs):
autoupgrade_upgrade.yml-
Analyze phase (again)
-
AutoUpgrade
deploy: prechecks, fixups, unplug, plug, upgrade, postupgrade -
Check that the PDBs are open
READ WRITEin the target CDB
-
-
Post tasks
-
Execute playbook
manage_db- the PDBs are in their end state now -
Remove the attribute
autoupgradefromoracle_pdbs(optional - upgraded PDBs are skipped) -
Remove the source CDB, when it is not needed anymore (
state: absentinoracle_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).
| Source CDB | Target CDB | State | Action |
|---|---|---|---|
PDB exists |
PDB missing |
|
AutoUpgrade |
PDB missing |
PDB exists |
|
nothing - the PDB is skipped |
PDB exists |
PDB exists |
|
fail. Usually |
PDB missing |
PDB 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 arepending. It is not needed anymore, when all PDBs areupgraded.
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:
severity |
fixup_available |
runfix |
Result |
|---|---|---|---|
|
not |
- |
blocking |
|
|
|
blocking |
|
|
|
fixed by AutoUpgrade in the deploy |
|
- |
- |
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.
"_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:
-
executes the analyze phase (
upgrade_analyze.yml) -
executes
autoupgrade.jar -config upgrade_<job>.cfg -mode deploy -noconsolefor each job in stateanalyzed(async:autoupgrade_upgrade_timeout,poll:autoupgrade_upgrade_poll) -
checks that all PDBs of the job are open
READ WRITEin the target CDB and are gone from the source CDB
The jobs are executed one after the other.
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:
| Recovery data | Analyze/fixups phase | Deploy phase |
|---|---|---|
none |
normal |
normal |
finished deploy ( |
cleared automatically ( |
cleared automatically, then normal |
finished deploy ( |
kept - needed for |
kept |
unfinished deploy (other status or no |
fails with a hint to resume with the deploy phase |
state |
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
autoupgradecan be removed fromoracle_pdbs. Upgraded PDBs are skipped anyway. -
Services,
tnsnames.oraentries 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: absentinoracle_databases), and the sourceORACLE_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.
| Step | Playbooks | Result |
|---|---|---|
|
|
19c and 26ai installed, |
|
|
|
|
|
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 scenariodownloadwithautoupgrade_download_gold_image_rename: true) -
LINUX.X64_2326100_db_home.zip(26ai) -
autoupgrade.jar
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.
| Value | Executed | Use case |
|---|---|---|
|
analyze, fixups, deploy |
complete test |
|
analyze phase only. The databases are not changed. |
analyze changes before the deploy, repeat as often as needed |
|
fixups phase only. The source CDB/PDB is changed, the PDB stays in the source CDB. |
test the fixups |
|
deploy phase only ( |
test the deploy without the separate analyze/fixups plays |
|
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_dbmust not be executed between the change oforacle_pdbsand 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.
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(exachkon 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
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.
| Location | Content | Owner | Remark |
|---|---|---|---|
|
AHF software: TFA, |
|
Replaced by an upgrade. No data. |
|
AHF repository: TFA collections, Compliance results, Insights reports, logs of AHF |
|
Primary storage of the data. Local filesystem (no NFS), size limit with |
|
Settings applied by the role |
|
Detection of changed settings, see Settings. |
|
Fleet Insights software, embedded Nginx, logs, processing of uploads |
|
Plan 4 GB per registered cluster. |
Repository database (19c or newer) |
Uploaded data of all clients: Compliance results and TFA collections |
schema |
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?
| 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 ( |
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
| Feature | root (default) |
extract (non-root) |
|---|---|---|
User for the installation |
|
|
TFA daemon (systemd), automatic collections |
yes |
no |
Compliance scheduler ( |
yes |
no |
Access to OS logs ( |
yes |
no |
AHF Fleet Insights client |
yes |
no |
Default |
|
|
Recommended by Oracle |
yes |
only when |
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).
| Variable | Default | Reason |
|---|---|---|
|
|
Default of Oracle. The binaries are executed by |
|
|
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.
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).
| Resource | Value | Source |
|---|---|---|
Disk: software |
1.2 GB |
measured |
Disk: data |
at least 5 GB, 10 GB recommended. Grows with collections and Compliance results, limit with |
Oracle |
Memory: TFA daemon |
about 170 MB RSS (Java with |
measured |
CPU: TFA daemon |
limit by default: the lower of 4 CPUs or 75% of the CPUs ( |
Oracle, measured |
Compliance checks ( |
only during the scheduled runs (default: daily 02:03, Sunday 03:03) |
not measured |
| 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 |
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):
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?
| Component | Variable | Default | Recommendation |
|---|---|---|---|
TFA daemon |
|
|
Active for GI and production. Disable on small test systems - |
Automatic diagnostic collections |
|
Oracle: |
|
Compliance scheduler ( |
|
|
Active, when the results are evaluated (mail or AHF Fleet Insights). |
AHF Insights |
|
Oracle: |
Insights are created with collections. Usable for the static web server (see below). |
AHF Fleet Insights client |
|
|
Active, when an AHF Fleet Insights server exists. |
ahf_tfa_enabled: false ahf_compliance_autostart: false
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 withAUTORUN_SCHEDULEof an autorun ID inahf_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.
| Source | Filename | Remark |
|---|---|---|
AutoUpgrade (role |
name from My Oracle Support |
|
My Oracle Support Doc ID 2550798.1 / patch 30166242 |
|
manual download 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-interpreteralone is not enough (AHF-00074: Required Perl Modules not found). The role installsperl,opensslandunzip(ahf_packages,ahf_manage_packages). -
Python module
pexpecton the database server for the registration in AHF Fleet Insights
The role executes these steps:
-
Check of variables, Perl and the owner of
ahf_loc -
Installation with
ahf_setup -silent -localwhen AHF is missing, or upgrade when the installation media is newer (ahf_upgrade) -
Check of the signature of
ahf_setup(ahf_verify_signature) -
Start/stop of TFA and the Compliance scheduler,
tfactl setandorachk -setfor changed settings -
Registration or deregistration in AHF Fleet Insights
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.):
| Autorun ID | AUTORUN_SCHEDULE |
Checks | COLLECTION_RETENTION |
|---|---|---|---|
|
|
profile |
7 days |
|
|
all checks |
14 days |
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
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 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.
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
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 }}"
ansible-playbook -i inventory/ opitzconsulting.ansible_oracle.ahf_fleet_insights -e hostgroup=ahffi
The role:
-
installs
cronie,iproute,hostname, the Oracle JDK and Oracle Instant Client (ahf_fi_packages) -
installs Fleet Insights with
ahf_fleet_setup -quiet <properties>asahf_fi_install_userand creates the registration user, or patches an existing installation when the installation media is newer -
opens
ahf_fi_portin firewalld -
starts Fleet Insights (
ahffi start), whenahffi statusdoes not report it as running, and waits for the web application onahf_fi_port(ahf_fi_start_timeout) -
provides the public certificate as fact
ahf_fi_public_certand optionally as file on the Ansible controller (ahf_fi_public_cert_fetch) -
shows
ahffi statusand the registration command fromahffi 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 SANahf_fi_cert_names(default: hostname and FQDN). The clients must use one of these names inahf_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.
| User | Password | Remark |
|---|---|---|
|
|
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. |
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
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:
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:
| 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 |
|
|
Problems, events, OS issues, system changes, patches, RPMs, space |
Insights (Detected Problems, Events, …), Space Analysis |
AHF Insights collection at 05:00 and 17:00 |
|
|
Compliance results ( |
Insights > Best Practice Issues |
Compliance scheduler |
|
|
Diagnostic collections with log and trace files |
collections of the clients |
automatic collections after incidents |
|
|
Capacity |
Fleetwide Capacity Analysis, Cluster-Wise Usage Trends |
capacity plugin of Fleet Insights and |
- |
not supported |
| Option | CLI (as root) |
Inventory (role ahf) |
|---|---|---|
Automatic diagnostic collections after incidents |
|
|
AHF Insights in automatic collections |
|
|
Size of the TFA repository |
|
|
Upload of complete collections (log and trace files) |
|
|
Alert History: timeline of ASM events (only ASM: |
|
|
Events of the alert logs of databases, ASM and Clusterware (base of the automatic collections), view with |
always active with a running TFA daemon |
|
Enhanced OS metrics |
|
|
Checks excluded from the Compliance checks |
|
|
Compliance scheduler |
|
|
Schedule and retention of a Compliance autorun |
|
|
Additional directory for collections |
|
|
TFA daemon |
|
|
Registration in Fleet Insights |
|
|
CPU and memory limit of TFA |
|
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:
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.
|
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.
-
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
-
The SSH key of the database server is restricted to a directory on the web server with
rrsync(command="rrsync -wo /srv/ahf/<host>"inauthorized_keys). -
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.
| 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
| Command | Description |
|---|---|
|
Status of TFA (PID, port, version) and the Compliance scheduler |
|
Installed versions of AHF, TFA and Compliance |
|
Settings of TFA ( |
|
Trace directories discovered by TFA, e.g. |
|
CPU and memory limits of TFA |
|
Compliance autoruns with |
|
Settings and registration applied by the role |
7.1.2. Connection to 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 roleahfagain - it registers the client again, when the certificate has changed.ahf_fleet_insights_force_register: trueregisters again in any case.
The client has no log of its uploads. Failed uploads of Compliance results are kept and can be uploaded again:
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:
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.
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
| Path | Content |
|---|---|
|
Logs of AHF (requested by Oracle Support for |
|
Compliance results ( |
|
TFA collections and Insights reports |
|
Log of the installation ( |
7.1.5. Known errors
| Message | Cause | Solution |
|---|---|---|
|
|
|
|
|
|
|
only |
package |
|
|
|
|
|
the role adds the current schedule, the ID is used without |
|
certificate of Fleet Insights is unknown to the client |
|
|
certificate of Fleet Insights without SAN or the URL uses another name |
|
|
certificate file readable by others |
mode |
|
registration without OS user for the REST access |
|
7.2. AHF Fleet Insights server
7.2.1. Status
| Command | Description |
|---|---|
|
Status of the web application and the collection processing engine |
|
URL of the web interface and registration command for the clients |
|
Installed version |
|
Diagnostics of Fleet Insights |
|
Start and stop of all processes |
|
Cron entries, which start and monitor the processes (no systemd unit) |
|
Nginx listens on |
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:
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
| Path | Content |
|---|---|
|
Start, stop, status and |
|
Requests of the browsers and the clients |
|
Errors of Nginx |
|
Certificate of the web interface |
|
Log of the installation (removed with the stage directory after the installation) |
7.2.4. Known errors
| Message | Cause | Solution |
|---|---|---|
|
|
|
|
installation as |
|
web interface not reachable after a reboot |
processes are started by cron, |
|
|
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) |
|
clients fail with |
certificate of the installer has no SAN |
|
login with |
password forgotten |
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_HOMEis 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_HOMEis 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_HOMEand 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-OnlyORACLE_HOME). -
readonly_homemust not be changed for an installedORACLE_HOME.
-
-
Each Read-Only
ORACLE_HOMEneeds 2 attributes indb_homes_config:db_homes_config: db1932-si-ee: readonly_home: true oracle_home_name: db1932siee -
oracle_home_nameis mandatory:-
It cannot be derived from the key in
db_homes_config. Oracle allows only characters, numbers and_in the name of anORACLE_HOMEin the Oracle Inventory. YAML keys are much less restrictive (e.g.db1932-si-eeis a valid key, but not a validoracle_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 newORACLE_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.
| Location | Path | Shared between ORACLE_HOMEs | Content |
|---|---|---|---|
|
e.g. |
no |
Software only |
|
|
yes |
SPFile, password file, |
|
|
no |
|
|
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
-
Prepare the new
ORACLE_HOME(no downtime)-
Install the new
ORACLE_HOMEwithoraswdb_install/oraswdb_manage_patches(not part of Out-of-Place Patching), one of:-
from a Golden Image (recommended)
-
from the base release, followed by
opatch applyfor all patches
-
-
Create the network configuration in the new
ORACLE_BASE_HOME
-
-
Switch the database (downtime) - Out-of-Place Patching with
oradb_manage_db-
Stop the database (and listener) from the old
ORACLE_HOME -
Change the
ORACLE_HOMEin/etc/oratabor in Oracle Clusterware (srvctl) -
Start the listener and database from the new
ORACLE_HOME -
Execute
datapatch
-
-
Post tasks
-
APEX, time zone, statistics, etc. (optional)
-
Remove the old
ORACLE_HOMEafter 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.
| Topic | Golden Image | Install and patch on the server |
|---|---|---|
Source |
Golden Image ( |
Base release (e.g. 19.3) + patches from |
Patching |
Included in the Golden Image. Additional patches are possible like for the base release. |
|
Duration on the database server |
Short (unzip + |
Long ( |
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 |
Set by |
Downtime |
None |
None - no database is running from the new |
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
| Environment | Registration | Switch |
|---|---|---|
Single Instance without Oracle Restart |
|
Replace the line |
Oracle Restart |
Oracle Clusterware (OCR/OLR) |
|
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.shfrom roleoradb_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
srvctlfrom the oldORACLE_HOME, beforesrvctl modify databaseis executed. -
The start is done from the new
ORACLE_HOME.
5.3. Listener
-
A listener running from the database
ORACLE_HOMEmust be restarted from the newORACLE_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 theORACLE_HOME:-
Data Guard Broker (
<db_unique_name>_DGMGRL) -
extproc -
Static service entries
-
5.4. Network configuration and wallets
-
sqlnet.ora,tnsnames.oraandlistener.oramust exist in$ORACLE_BASE/homes/<new oracle_home_name>/network/admin. Alternative: a centralTNS_ADMIN. -
WALLET_LOCATIONorENCRYPTION_WALLET_LOCATIONinsqlnet.oramust not point into the oldORACLE_HOME. -
TDE with the init parameter
WALLET_ROOTis independent from theORACLE_HOME. -
local_listenermust not be an alias fromtnsnames.oraof the oldORACLE_HOME. DBCA setslocal_listenertoLISTENER_<DB_NAME>and writes this alias intotnsnames.oraof theORACLE_HOME. The alias is missing in the newORACLE_HOME, the instance does not register at the listener (ORA-12514).orasw_metarequireslocal_listenerwith EZConnect ininit_parametersof Single Instance databases, e.g.//localhost:1521(see breaking_changes.adoc). Other entries from DBCA intnsnames.oraof the oldORACLE_HOMEare not copied.
5.5. datapatch
-
datapatchis mandatory after the start from the newORACLE_HOME. -
datapatchmust be executed for the CDB and all PDBs. -
OJVM patches may need a startup in upgrade mode, depending on the release.
-
Data Guard:
datapatchis 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.
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[].opatchfor the newORACLE_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
MOUNTonly. 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 openedREAD ONLY WITH APPLYbefore the switch. -
datapatchmust 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;
| DATABASE_ROLE | Open database | datapatch |
|---|---|---|
|
yes (+ all PDBs) |
yes |
|
no, remains in |
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-oracledoes 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.
| Feature | Role | Comment |
|---|---|---|
Read-Only Oracle Home |
|
|
Install from base release |
|
Without |
Patch the new |
|
|
Download Golden Image from Oracle (recommended) |
|
|
Create Golden Image (optional) |
|
|
Install from Golden Image (optional) |
|
|
Relink options |
|
Enforced for every |
Network configuration |
|
Files are created in |
|
|
|
Remove |
|
|
Switch |
|
Change of |
Switch |
|
Change of |
|
|
|
|
|
An |
|
|
|
|
|
|
Switch Grid Infrastructure home of Oracle Restart |
|
Change of |
6.2. Gaps
| Gap | Location | Description |
|---|---|---|
Incomplete check of |
|
Only the existence of |
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_HOMEhas no database before the switch. -
The old
ORACLE_HOMEhas no database after the switch, until it is removed. -
Listeners can run from a dedicated
ORACLE_HOMEwithout 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).
|
| Step | User | Description |
|---|---|---|
Extract |
grid |
Without downtime. |
|
grid |
Software only installation with Oracle base and groups of the old home. Registers the new home in the central inventory. |
|
grid |
Prepares the switch. Without downtime. |
|
root |
Oracle Restart: |
|
grid |
|
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.binowned byroot),oraswgi_installstops with an assert. Use a neworacle_home_gi. -
When
root.shfails before the switch (e.g. the CVU check ofrootcrs.pl -prepatch), the next run resumes withroot.sh:-switchGridHomeis skipped, whenrootconfig.shof the new home is already owned byroot.
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_homein/etc/oracle/olr.locand notoracle_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).
| Step | User | Description |
|---|---|---|
|
grid |
Creates the response file. The role stops with an error, when |
|
root |
Only for a locked home (owner |
|
grid |
Removes the software and the home from the central inventory. No downtime. |
|
root |
Only, when requested in the output of |
|
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.
|
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.
db_homes_config with Golden Imagedb_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
db_homes_config installed and patched on the serverdb_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.
|
ORCL from db19_2601 to db19_2604db_homes_installed:
- home: db19_2601
state: present
- home: db19_2604
state: present
oracle_databases:
- home: db19_2604 # (1)
oracle_db_name: ORCL
state: present
-
Changing
homeis the trigger for the switch. See Existing features.
9. Open questions
-
oraswdb_installderives the type of anORACLE_HOME(SI or cluster installation) from the databases inoracle_databases. AnORACLE_HOMEwithout database is installed asSI. A new RACORACLE_HOMEneeds the cluster installation before the switch ⇒ explicit type indb_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(datapatchrollback)
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 |
|---|---|---|
|
|
Standby configurations with technology, members and topology |
|
|
Reference from a database to an entry in |
|
|
|
|
|
TNS aliases for redo transport, broker and RMAN duplicate |
|
|
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.
| Attribute | Mandatory | Description |
|---|---|---|
|
yes |
Name of the configuration. Referenced by |
|
yes |
|
|
yes |
List of members, see below. |
|
|
Data Guard attributes of the configuration. Only allowed with |
|
no |
Dbvisit attributes of the configuration. Only allowed with |
| Attribute | Mandatory | Description |
|---|---|---|
|
yes |
List of |
|
|
|
|
yes |
|
|
no |
Data Guard attributes of the member. Only allowed with |
|
no |
Dbvisit attributes of the member. Only allowed with |
2.1. Data Guard attributes (dg)
| Attribute | Default | Description |
|---|---|---|
|
|
|
|
|
Default method for the creation of the standby databases, see Creation of a standby database |
|
- |
Tasks file for |
|
- (mandatory here or in each member) |
RMAN |
| Attribute | Default | Description |
|---|---|---|
|
- |
TNS alias from |
|
|
Broker property |
|
|
Broker property |
|
|
Broker property |
|
|
Method for the creation of this standby database |
|
|
Tasks file for |
|
|
RMAN |
|
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.
| Attribute | Description |
|---|---|
|
|
|
Mandatory for |
|
Mandatory |
|
Must not be |
|
Mandatory for |
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:
-
Search all members of the referenced configuration with
inventory_hostnameinhosts. -
When more than 1 member matches (e.g. primary and standby on the same host), the member with
db_unique_name=oracle_db_unique_nameis used. -
Exactly 1 member must match. Otherwise the play fails.
| Setup | Unique by |
|---|---|
Data Guard, different hosts |
host |
Data Guard, same host |
host + |
Dbvisit (same |
host |
RAC |
host (more than 1 entry in |
5. initial_role
initial_role is only used when a member is created:
-
primary: the database is created withdbca. -
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_roleis notPRIMARY, or -
the instance is not running/mounted and
initial_roleof the member isphysical_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 The |
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.
| Method | Description |
|---|---|
|
RMAN |
|
The standby database is created outside of |
|
The tasks file |
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:
-
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. -
The primary database is prepared over its
connect_identifier(idempotent):FORCE LOGGINGand standby redo logs (number of online redo log groups + 1 per thread, OMF is needed).log_archive_config,fal_serverandlog_archive_dest_nare set by the Data Guard Broker (dgmgrl). -
The standby database is created with the method.
-
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 indbsis not overwritten), instance inNOMOUNT. The PFile containsdb_nameandaudit_file_dest,diagnostic_destfrominit_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 afterDUPLICATEfor a manual repeat of RMANDUPLICATEon the host. -
target:connect_identifierof the primary,auxiliary://<host>:<port>/<db_unique_name>_DGMGRL(host and port fromoracle_tnsnames_configof theconnect_identifierof 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 frominit_parametersof the standby database inoracle_databases(state: present,scopenotmemory,sid*) and set withSET. The role sets in addition:-
db_unique_nameof the member (always) -
control_files:<db_create_file_dest>/<db_unique_name>/controlfile/control01.ctl, unless defined ininit_parameters -
local_listener: empty, unless defined ininit_parameters. The value of the primary is usually a TNS alias (e.g.LISTENER_<SID>fromdbca), which does not exist on the standby host. An emptylocal_listenerregisters 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/2frominit_parametersare created beforeNOMOUNT. Existing directories are not changed (owner, group and mode are kept). Parameters of the cloned SPFile that are not defined ininit_parameterskeep the value of the primary (afterPARAMETER_VALUE_CONVERT): their directories must exist on the standby host. -
A failed
DUPLICATEstops the auxiliary instance and removes the SPFile created byDUPLICATE. The next run starts a newDUPLICATE. -
RMAN script
duplicate_<db_unique_name>.rmanand shell scriptduplicate_<db_unique_name>.shin$ORACLE_BASE/admin/<db_unique_name>/pfile, without passwords. The shell script reads the SYS password from the environment variableORADB_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 withbecomeis 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>;
-
CONFIGUREis only executed when the current policy differs (idempotent).SHOWprintsTO DISKinstead ofTO 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
DUPLICATEcontains 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.
| Value | Description |
|---|---|
|
RMAN default: no deletion policy |
|
Eligible after the archive log is applied on (all) standby databases |
|
Eligible after the archive log is shipped to (all) standby databases |
|
Eligible after |
|
Combination: |
|
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.
|
db_standby_config:
- name: DG1
type: dataguard
dg:
archivelog_deletion_policy: APPLIED ON ALL STANDBY
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.
-
CREATE CONFIGURATION '<name>' AS PRIMARY DATABASE IS '<local db_unique_name>' CONNECT IDENTIFIER IS '<connect_identifier>' -
ADD DATABASE … MAINTAINED AS PHYSICALfor all other members -
EDIT DATABASE … SET PROPERTYLogXptMode(log_xpt_mode),DelayMins(delay_mins) andReopenSecs(reopen_secs) for all members -
ENABLE CONFIGURATION -
EDIT CONFIGURATION SET PROTECTION MODE(only whenprotection_modeis notMaxPerformance) -
SHOW CONFIGURATION
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/2must be different and must not be below theORACLE_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(dbsis below theORACLE_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 configurationreturnsORA-16532) and -
all other members are
PHYSICAL STANDBYdatabases (oradb_factsof the hosts of the members). Otherwise a warning is shown, e.g. for a standby database withcreate_method: externalthat 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.
-
The old primary database needs a reinstatement (
ORA-16661in the broker configuration). -
oradb_standbydoes nothing: the database of the old primary has an SPFile andinitial_role: primary. -
oradb_manage_dbskipsoracle_dbwhile the instance of the old primary is running with a role other thanPRIMARY. -
oradb_manage_dbdoes 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.WarningWhen the instance of the old primary is not running, its role is unknown and initial_roleisprimary⇒oracle_dbinoradb_manage_dbwould start and open the database (split brain).oradb_manage_dbmust check the facts of the other members beforeoracle_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: trueinoracle_databases). -
Typical case after a failover, no RMAN
DUPLICATEneeded. -
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>'(orADD DATABASE) in the broker after the creation. -
oradb_manage_dbmust use the same rule to skipdbca.
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.
| Step | Description |
|---|---|
Checks |
The member is not the |
Broker |
|
Autostart |
|
Drop |
|
Creation |
The SPFile does not exist ⇒ creation with |
Broker |
|
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_configis a list. -
nameis defined and unique indb_standby_config. -
typeis defined and has an allowed value. -
Only the sub-dictionary matching
typeis defined (dgordbvisit) in the configuration and its members. -
membersis a non empty list. -
hostsis a non empty list for each member. Each host exists in the inventory. -
initial_roleisprimaryorphysical_standby. Exactly 1 member hasinitial_role: primary. -
When the current host is part of a member, at least 1 database in
oracle_databasesreferences the configuration.
type: dataguard:
-
db_unique_nameis defined for each member and unique in the configuration (case insensitive). -
protection_modeisMaxPerformance,MaxAvailabilityorMaxProtection(case sensitive). -
log_xpt_modeisASYNC,SYNCorFASTSYNC. -
delay_minsandreopen_secsare integers >= 0. -
MaxAvailabilityandMaxProtectionneedSYNCorFASTSYNCfor at least 1 member withinitial_role: physical_standby. -
connect_identifieris defined for each member and exists inoracle_tnsnames_config. -
create_methodisrman_duplicate_active,externalorcustom.customneedscreate_tasks_filein the member or in the configuration. -
archivelog_deletion_policyis 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:
-
dganddbvisitare not defined. -
standby_configreferences an existing entry. -
Exactly 1 member matches the database, see Assignment of a database to a member.
-
type: dataguard:oracle_db_unique_nameandlistener_nameare defined. -
type: dataguard:archivelog: true,force_loggingis notfalse. -
oracle_db_unique_namematchesdb_unique_nameof the member (case insensitive). Both default tooracle_db_name. -
type: dataguard:init_parameterscontaindg_broker_config_file1/2(different, not belowORACLE_HOME),dg_broker_start=TRUEbelow both file parameters andstandby_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.
all:
children:
dg_db1:
hosts:
dbhost1:
dbhost2:
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
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
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 |
|---|---|
|
|
List vs. dictionary |
|
12.2. TODO
-
❏ Standby redo logs with
oradb_manage_redo
The standby redo logs are created byoradb_standbyon the primary database beforeDUPLICATE(number of online redo log groups + 1 per thread, size of the largest online redo log). They should be managed byoradb_manage_redoon all members (primary and standby), based onredolog_sizeandredolog_groupsinoracle_databases.oradb_manage_redoskips 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 policyAPPLIED ON ALL STANDBY/SHIPPED TO ALL STANDBY, RMAN configuration (db_unique_namein the RMAN catalog). -
❏ Support for Oracle Restart
srvctl add database -role PHYSICAL_STANDBY -startoption MOUNTfor the standby database, SPFile and password file in ASM, no systemd units oforadb_manage_db.standby_state.ymlandrman_duplicate_activesupport databases on filesystem without Oracle Restart only. -
❏ Management of database services
Role based services withoradb_manage_services: services for the rolePRIMARYorPHYSICAL_STANDBY(srvctl -rolewith 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_dbmust not be executed for a member, when another member is thePRIMARY(oradb_facts), see Role transitions outside of ansible-oracle. -
❏ Reinstate after a failover (case 1 in Role transitions outside of ansible-oracle),
flashback: truein 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.cfgis 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.ymlinoradb_manage_dbstarts the database withstartup⇒ 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 byoradb_standby.
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:
-
Find your current version and the target version.
-
Read the overview table of every major version in between.
-
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 |
|---|---|---|
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 |
|
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 |
|
Use |
ansible-core 2.19 or newer is used and your own playbooks or roles use variables directly in conditionals |
Use |
|
ansible-core 2.19 or newer is used and your inventory contains templates ( |
Check the result types of your templates |
|
Default of oracle_sw_copy and oracle_sw_unpack with install_from_nfs |
|
Set |
Target hosts with RHEL/OL and |
Check the permanent |
|
|
Upgrade the databases to 19c or 26ai, then remove the old ORACLE_HOMEs from |
|
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 ( |
Set the new variables |
|
A name of a profile, user, role, object or directory is enclosed in |
Remove the |
|
The listener does not listen on |
Set |
|
|
No action without |
|
Own playbooks or inventories use the internal variables |
No action for inventories with |
|
Autostart of databases with one systemd unit per database and listener |
|
No action for the new solution, it replaces |
Single Instance without Grid Infrastructure / Oracle Restart and |
No action, if the databases should start with the server. Otherwise set |
|
An entry in |
Remove |
|
oradb_rman: control_file_record_keep_time in init_parameters |
A database in |
Add |
A database in |
Change the monitoring to the new logfile names in |
|
listener_installed with Grid Infrastructure / Oracle Restart: listener in its home |
Grid Infrastructure / Oracle Restart and an entry in |
Use |
local_listener in init_parameters of Single Instance databases |
A Single Instance database (also with Oracle Restart) in |
Add |
A 19c database in |
Set |
|
oracle_databases: db_create_file_dest and db_recovery_file_dest in init_parameters |
A database in |
Add |
oracle_databases: datafile_dest and recoveryfile_dest are removed |
A database in |
Move the values to |
A database in |
Use OMF with ASM ( |
|
oracle_databases: max_pdbs in init_parameters of Container Databases |
A Container Database ( |
Add |
oracle_databases: control_management_pack_access in init_parameters of Enterprise Edition databases |
A database of an Enterprise Edition home in |
Add |
oracle_databases: sga_target and pga_aggregate_target in init_parameters |
A database in |
Add |
oracle_databases: no memory_target and memory_max_target with Hugepages |
A database in |
Replace |
A database in |
Add |
|
Own playbooks use the role |
Use the new role |
|
|
Set |
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 |
|
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 |
|---|---|---|
|
|
|
|
|
|
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 |
|---|---|---|
|
bool |
string |
|
dict / list |
string |
|
empty string |
|
|
string |
int |
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 }}"ormy_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
| intor| stringfor 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 ofmode: 775. An unquoted775is an integer and is passed through templates (for examplemode: "{{ item.mode }}") as decimal 775, which is mode1407. Before 2.19 the template converted the value to the string"775", which was interpreted as octal. -
with_nestedhandles 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
whenis false, whendelegate_touses the loop variable (not mentioned in the porting guide). Useloop: "{{ my_list | default([]) }}". -
Templates inside conditionals fail:
that: swap >= {{ min_swap }}must be written asthat: swap >= min_swap | int. -
The
sshconnection usesSSH_ASKPASSinstead ofsshpassfor password authentication. Setpassword_mechanism = sshpassin section[ssh_connection]ofansible.cfgto keep the old behavior. -
The
boolfilter warns for values other thantrue/false,yes/no,on/off,1/0(andNone). This will be an error in ansible-core 2.23. -
A timeout of
becomeis an unreachable error. Useignore_unreachableinstead ofignore_errors. -
The magic variable
play_hostsis deprecated, useansible_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 |
|---|---|---|
|
installation media are copied and unpacked to |
installation media are used from |
|
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 |
|---|---|---|
|
|
|
|
- (not available) |
|
The change applies only to RHEL/OL target hosts with installed firewalld.
SUSE is not changed.
What orahost does with the new defaults:
-
Checks, if the permanent
firewalldconfig allows the SSH connection of Ansible (servicessh, port and target of the zone). The play fails, when startingfirewalldwould block SSH. Rich rules and zones bound to sources are not evaluated by this check. -
Starts and enables
firewalld. -
Opens the following TCP ports in the permanent and the running config:
-
all ports from
addressinoracle_listeners_configwith ahost(IPC addresses are ignored,listener_portis used for addresses withoutport), -
all ports from the new variable
oracle_extra_firewall_ports, -
oracle_scan_portwithoracle_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 |
|---|---|---|
|
|
Default in 5.0.0: |
|
|
Behavior of 4.x: |
|
|
|
|
|
|
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 |
|
5.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) |
|
1.4.2 |
3.7 |
|
2.3.0 |
3.8 |
|
3.0.0 |
3.9 (Oracle Linux / RHEL 9) |
|
4.0.2 |
all other versions |
|
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 the package? Default: |
|
|
Directory with wheel files instead of a single package or file. Default: package index |
|
|
umask for the pip installation |
|
|
Use a proxy for the pip installation. Default: |
|
|
Proxy for the pip installation |
|
|
Additional arguments for pip, e.g. |
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>/pyoracledbwhenis_sw_source_local: trueandoracle_sw_copy: true. Withoracle_sw_copy: falsethe 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 |
|---|---|---|
|
The name was not quoted in the SQL statements, but compared case insensitive with |
A name in |
|
A |
A part of |
|
The name was not quoted in the SQL statements and compared in uppercase with |
A name in |
|
The grantee ( |
Grantee, roles in |
|
Names with |
A name in |
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.
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);
select distinct profile from dba_profiles where profile <> upper(profile);
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.
# 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 oftablespaceandsize.sizeis the number of bytes with an optional unitK,M,G,T,P,Eorunlimited.size: 0removes the quota on the tablespace. -
quotas_mode:append(default) changes only the tablespaces inquotas,enforceremoves 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.
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.
|
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 immediatetook 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
sqlplusin 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 |
|
|
Start/stop script |
|
|
Timeouts |
systemd default (90 seconds), then the database is killed |
|
Databases started outside of systemd |
killed during a shutdown of the server |
attached to their unit by |
Dependencies |
|
|
Start of a single database |
not possible |
|
Crash of a database |
not detected, the service stays active |
The unit monitors PMON. After a crash (no |
ORACLE_HOME of a database |
from |
from |
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 |
|---|---|
|
inactive, no restart.
The unit is started again by |
other entry, e.g. |
|
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.
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.
|
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).
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.
|
oracle_databases:
- oracle_db_name: orcl
init_parameters:
- {name: local_listener, value: 'rac1-vip:1521', scope: both, state: present, sid: orcl1, dbca: true}
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_timeis defined ininit_parameters(state: present,sid: '*'), and -
the value is >=
<n>for the retention policyRECOVERY WINDOW OF <n> DAYS(rman_retention_policyof the database ororadb_rman_retention_policy_default).
The playbook stops with a failed assert, when the parameter is missing or too small.
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).
| Before 5.0.0 | As of 5.0.0 | |
|---|---|---|
Cron output |
|
|
Logfile of |
|
|
Last execution |
- |
Symlink |
Cleanup |
- |
Logfiles older than |
Parallel executions of the same action |
executed, output mixed in one logfile |
The 2nd execution stops with exit code 30 (lock file |
Changes in detail:
-
oradb_rman_cron_logdirandrman_cron_logdirare removed. The directory/var/log/oracle/rman/logis no longer created or written. -
The prefix of the logfile is the
db_unique_nameinstead of theORACLE_SID. The name changes for every database withdb_unique_name!=ORACLE_SID, e.g. Data Guard or RAC. -
The 1st execution renames an existing logfile
<RMAN_LOGDIR>/<db_unique_name>_<action>.logof older versions to*.log.oldand 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.shremoves old logfiles itself, logrotate must not rotate the logfiles with timestamp (logrotaterefuses to rotate the symlink).
Required actions:
-
Remove
oradb_rman_cron_logdirandrman_cron_logdirfrom the inventory. -
Change the monitoring to the symlink
<RMAN_LOGDIR>/<db_unique_name>_<action>.logor to the logfiles with timestamp. -
Remove logrotate rules for
RMAN_LOGDIRand setoradb_rman_log_retentioninstead. -
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:
Entry in listener_installed |
Before 5.0.0 | As of 5.0.0 |
|---|---|---|
|
|
|
|
GI home from |
GI home from |
Changes in detail:
-
A listener with
homeis registered with the ORACLE_HOME ofhome. An existing listener resource in the GI home is modified withsrvctl 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: truestays in the GI / Oracle Restart home.
Who is affected:
-
Inventories with Grid Infrastructure / Oracle Restart and
homeinlistener_installed, where the listener runs from the GI home, e.g.LISTENERwithhomeof the database.
Required actions:
-
Use
use_gi_home: truewithouthomefor a listener, which must stay in the GI / Oracle Restart home. -
Check the ORACLE_HOME of the listener resources before the upgrade.
oradb_manage_dbrestarts a moved listener, run it in a maintenance window:srvctl config listener -listener <listener_name>
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
See LISTENER.md.
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_databaseswithoutlocal_listenerininit_parameters. The playbooks fail in the assert oforasw_meta:local_listener is missing in init_parameters of <oracle_db_name>, ...
Required actions:
-
Add
local_listenerwith EZConnect (//<host>:<port>) toinit_parametersof the database.localhostand the port of the listener avoid an extra entry intnsnames.ora. -
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)))'. -
Existing databases:
oradb_manage_parameterschangeslocal_listenerwithscope: both, the instance registers at the listener without restart. The entries of DBCA intnsnames.oraare not removed byansible-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.
|
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_databaseswithoutis_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_databaseswithoutomf. Before 5.0.0 dbca was called with-useOMF false, now with-useOMF true.omfis used during the creation of a database with dbca only.
Required actions:
-
Set
is_container: falsefor a 19c non-CDB. -
Use OMF for new databases. OMF is strongly recommended in
ansible-oracle. -
Without OMF: set
omf: falseand use an own DBCA template without OMF (dbca_templatename). The DBCA templates ofansible-oracleare made for OMF. Databases without OMF are not tested anymore.
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_databaseswithoutdb_create_file_destordb_recovery_file_destininit_parameters. The playbooks fail in the assert oforasw_meta:<oracle_db_name>: omf: true (default) needs db_create_file_dest and db_recovery_file_dest in init_parameters, ...
Required actions:
-
Add
db_create_file_destanddb_recovery_file_desttoinit_parameters. Use the values ofdatafile_destandrecoveryfile_dest, if they were defined. -
Existing databases: use the current values of the database (
show parameter db_create_file_dest,show parameter db_recovery_file_dest), otherwiseoradb_manage_parameterschanges them. -
Define
db_recovery_file_dest_sizebeforedb_recovery_file_destininit_parametersfor existing databases without a recovery area (ORA-19802).
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_destorrecoveryfile_destinoracle_databases. The playbooks fail in the assert oforasw_meta:<oracle_db_name>: datafile_dest and recoveryfile_dest in oracle_databases are removed. ...
Required actions:
-
Move the values to
db_create_file_destanddb_recovery_file_destininit_parameters. -
Remove
datafile_destandrecoveryfile_destfromoracle_databases. -
Databases with
omf: false: the destinations areoracle_dbf_dir_fsandoracle_reco_dir_fs(global per host).
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}
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: ASMandomf: false. The playbooks fail in the assert oforasw_meta:<oracle_db_name>: omf: false is not allowed with storage_type: ASM. ...
-
Inventories with
oracle_dbf_dir_asmororacle_reco_dir_asm. The variables have no effect anymore.
Required actions:
-
Remove
omf: falsefrom ASM databases and adddb_create_file_destanddb_recovery_file_desttoinit_parameters. -
Remove
oracle_dbf_dir_asmandoracle_reco_dir_asmfrom the inventory.
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 |
|---|---|---|
|
3 |
|
|
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_pdbsininit_parameters, or with a value greater than 3 (SE2) or 1024 (EE). This includes 19c databases withoutis_container, which are Container Databases as of 5.0.0. The playbooks fail in the assert oforasw_meta:<oracle_db_name>: is_container: true (default) needs max_pdbs in init_parameters with an integer value <= <limit> for edition <edition> ...
Required actions:
-
Add
max_pdbswith the number of PDBs allowed by your license toinit_parameters.max_pdbsis set by dbca for a new database and changed byoradb_manage_parametersfor an existing database.
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 |
|---|---|
|
no Management Pack |
|
Diagnostics Pack |
|
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_accessininit_parameters, or with another value thanNONE,DIAGNOSTICorDIAGNOSTIC+TUNING. -
Inventories with a database of a Standard Edition 2 home with
control_management_pack_accessother thanNONE. The playbooks fail in the assert oforasw_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:
-
Add
control_management_pack_accesswith the value allowed by your license toinit_parameters. For an existing database,oradb_manage_parameterschanges the parameter to the value from the inventory.
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_targetorpga_aggregate_targetininit_parameters, or withoracle_db_mem_totalmb. The playbooks fail in the assert oforasw_meta:<oracle_db_name>: sga_target and pga_aggregate_target are essential memory parameters and must be defined in init_parameters ...
Required actions:
-
Add
sga_targetandpga_aggregate_targettoinit_parameters. -
Remove
oracle_db_mem_totalmb.
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_targetormemory_max_targetininit_parametersand withoutconfigure_hugepages: false. The playbooks fail in the assert oforasw_meta:<oracle_db_name>: memory_target and memory_max_target are not allowed in init_parameters with Hugepages ...
Required actions:
-
Use
sga_targetandpga_aggregate_target(Automatic Shared Memory Management) instead of AMM. -
Set
state: absentformemory_targetandmemory_max_targetto remove them from the spfile of existing databases, or setconfigure_hugepages: falseif Hugepages are not used.
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.
|
- hosts: dbfs
become: true
roles:
- opitzconsulting.ansible_oracle.oraswahf_install
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
processesininit_parameters. The playbooks fail in the assert oforahost_meta:<oracle_db_name>: processes must be defined in init_parameters with an integer value > 0 ...
Required actions:
-
Add
processestoinit_parameters. For an existing database, use the current value (show parameter processes) to avoid a change of the spfile and a restart.
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_CONFIGorCRS_CONFIGwithoutoracle_install_version_gi. The variable selects the response file, the task file and the installation media oforaswgi_install, and the key ingi_patches. -
The default of
oracle_home_gicontains the version:{{ oracle_base }}/{{ oracle_install_version_gi }}/grid(Oracle Restart) and/u01/app/{{ oracle_install_version_gi }}/grid(Grid Infrastructure). Withoutoracle_install_version_giand withoutoracle_home_giin inventory,oracle_home_gichanges from…/19.3.0.0/gridto…/26.1.0.0/grid.WarningFor an installed Oracle Restart, a different oracle_home_gistarts the switch into a new home (Out-of-Place Patching,switch_home.ymloforaswgi_install). Setoracle_install_version_gi(andoracle_home_gi) before the first run with 5.0.0.
Required actions:
-
Set
oracle_install_version_gito the base release of the installation media (19c:19.3.0.0, 26ai:26.1.0.0). -
Recommended: set
oracle_home_gias well, to be independent from the default.
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:
-
Add a row to the overview table of the next major version. Create the version section, if it does not exist.
-
Describe the change in an own subsection: what changed, why, who is affected, before/after and the required action with an example.
-
Reference this guide in the changelog fragment (
see doc/guides/breaking_changes.adoc).
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.
|
| Oracle Restart | Grid Infrastructure (cluster) | |
|---|---|---|
|
|
|
State in |
Oracle Restart 26ai is supported, tested with databases 19c and 26ai (molecule scenario |
Grid Infrastructure 26ai is supported, tested with 2 nodes and a RAC database 26ai (molecule scenario |
Hosts |
every host is configured on its own |
all nodes of the cluster are configured together |
Default of |
|
|
Default of |
|
|
|
|
|
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 |
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 |
|
|
2 |
|
|
3 |
|
Installation of the RDBMS software ( |
4 |
|
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 |
|---|---|---|
|
|
Base release of the software, e.g. |
|
list of the base release images |
List of installation media with |
|
not defined |
Filename of the installation media.
When it is defined, it is used instead of the |
|
Source of the installation media (copied into |
|
|
derived, see below |
|
|
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 password for |
|
|
Password of |
|
|
Password of |
1.2.3. Patching during the installation
| Variable | Default | Description |
|---|---|---|
|
|
Apply the patches from |
|
|
|
|
|
Patches for Grid Infrastructure per base release ( |
|
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.
asm_diskgroupsasm_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}
| Attribute | Description |
|---|---|
|
Name of the disk group (lower case in the inventory, ASM uses upper case). |
|
|
|
List with 1 dictionary: |
|
ASM attributes of the disk group ( |
|
List of disks: * |
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:
-
the preparation of the disks by
orahost_storageororaswgi_install, -
the path of each disk in the response file of
gridSetup.sh(diskListoforacle_asm_init_dg), -
the ASM discovery string (
asm_diskstring,diskStringin the response file).
| Value | Preparation | Path of a disk | Discovery string |
|---|---|---|---|
|
nothing, the devices must already exist with owner |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Variable | Default | Description |
|---|---|---|
|
|
ASM discovery string ( |
|
not defined |
ASM discovery string with |
|
|
Create 1 partition on every disk of |
|
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_gimust be the same or newer than the version of all database homes.
2.2. Example inventory
host_vars/<host>/restart.ymloracle_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 |
|---|---|---|
|
|
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_nodeis alwaystrue: every host runs all steps itself. -
orasw_meta_cluster_hostgroup,oracle_scan,oracle_vipand all network variables of Grid Infrastructure are not used.
2.4. ORACLE_HOME and ORACLE_BASE
| Variable | Default for Oracle Restart | Description |
|---|---|---|
|
|
|
|
|
|
|
|
Default for |
|
|
|
|
|
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 |
|---|---|---|
|
|
|
|
|
Owner of the database software. |
|
|
Owner of Oracle Restart with |
|
|
OS groups OSASM, OSDBA and OSOPER for ASM ( |
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).
-
Unpack the installation media into
oracle_home_gi, when the home is not registered in the central inventory. -
Install
cvuqdisk(only withdevice_persistence: asmfd). -
Create the response file
<oracle_rsp_stage>/grid-<oracle_cluster_name>.rsp. -
Run
cluvfy(skipped withgi_ignoreprereq: true). -
With
device_persistence: asmfd: configure the ASM Filter Driver and label the disks. -
gridSetup.sh -silent -responseFile …(with-applyRU, whenapply_patches_giandpatch_before_rootsharetrue). -
orainstRoot.shandroot.sh.root.shconfigures Oracle Restart and createsoracle_asm_init_dg. -
gridSetup.sh -executeConfigTools(run_configtoolallcommand: true): listenerLISTENERinoracle_home_gi, ASM post configuration, CVU. -
CRS flag (
CRS=TRUE) oforacle_home_giin the central inventory. -
Patches (
oraswgi_manage_patches) and all other disk groups (oraasm_manage_diskgroups).
2.7. Prerequisite checks and ConfigTools
| Variable | Default | Description |
|---|---|---|
|
|
|
|
|
Run |
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_giis defined inlistener_installedwithuse_gi_home: true(nohome). TheORACLE_HOMEof Oracle Restart is read from/etc/oracle/olr.loc. -
A listener in a database home is defined with
homeand is registered in Oracle Restart withsrvctl. -
The
ORACLE_HOMEof a database must not be newer thanoracle_home_gi. -
db_create_file_destanddb_recovery_file_destininit_parameterspoint 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. -
sshdon all nodes and SSH logins allowed for the grid user (andoracle_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.ymlall:
children:
rac: # orasw_meta_cluster_hostgroup
hosts:
rac-1: # primary node: gridSetup.sh, 1st root.sh
rac-2:
group_vars/rac/gi.ymloracle_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 |
|---|---|---|
|
|
|
|
|
Name of the inventory group with all nodes of the cluster.
Mandatory for |
|
derived |
|
|
|
Name of the cluster ( |
|
|
Type of the cluster: |
|
|
Storage option of ASM in the response file.
It changes the usage of the private interface in |
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 ( |
x |
x |
Partitions of the ASM disks ( |
x |
|
udev rules ( |
x |
x |
SSH user equivalence ( |
x |
x |
Unpack the installation media into |
x |
|
Install |
x |
x |
Response file, |
x |
|
|
x |
x |
|
x |
x |
|
x |
|
CRS flag of |
x |
x |
Disk groups ( |
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 |
|---|---|---|
|
|
Default for |
|
|
|
|
|
|
|
|
|
|
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_userownsoracle_home_gi,grid_baseand the ASM disks, -
oracle_userowns 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 |
|---|---|---|
|
|
Interface of the public network. |
|
|
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 |
|---|---|---|
|
not defined |
Name of the Single Client Access Name ( |
|
|
Port of the SCAN listener. |
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 |
|---|---|---|
|
not defined |
Name of the VIP of this node, e.g. |
|
|
Suffix for the VIP, when |
3.6.4. Name resolution
Without DNS, orahost can write the entries into /etc/hosts:
| Variable | Default | Description |
|---|---|---|
|
|
|
|
|
IP of the node in |
|
|
Additional entries, e.g. other nodes, VIPs and the SCAN ( |
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, defaultrsa,orahost_ssh_key_size, default4096), -
adds the public keys of all nodes into
authorized_keyson all nodes, -
adds the host keys (
ssh-keyscan -t <orahost_ssh_hostkeytypes>foransible_hostname) intoknown_hostson 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_diskgroupsmust exist on every node with the same path. Withdevice_persistence: ''the owner (_grid_install_user) and the group (asmadmin_group) must be set beforegridSetup.sh. -
Partitions (
partition_devices) andasmliblabels are created on the primary node only. -
oracle_asm_init_dgcontains the OCR and the voting files. The number of voting files depends on the redundancy:external1,normal3,high5 disks (failure groups). Withnormaland 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 |
|---|---|---|
|
|
|
|
|
Run |
|
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 |
x |
|
|
x |
|
|
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_databasesmust be defined forswdb, not only formanage_db: without a RAC database inoracle_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 inorasw_meta). -
Read-Only Oracle Homes (
readonly_home: truewithoracle_home_name) are supported for RAC as well.
group_vars/rac/db.yml: database homedb_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:
-
nodelistin the response file ofdbcacontains all hosts oforasw_meta_cluster_hostgroup. -
The instances are named
<oracle_db_name><n>(e.g.RACCDB1on the 1st node,RACCDB2on the 2nd node). -
dbcaregisters the database in Grid Infrastructure (srvctl config database), the database is administrator managed. -
/etc/oratabgets an entry<oracle_db_name>:<ORACLE_HOME>:Non all nodes (start and stop by Clusterware, not bydbstart).
Attribute in oracle_databases |
Value | Description |
|---|---|---|
|
|
RAC database on all nodes of |
|
|
The datafiles are in the disk group of |
|
|
| Variable | Default | Description |
|---|---|---|
|
|
|
group_vars/rac/db.yml: databaseoracle_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:
-
dbcachecks 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 fromdb_recovery_file_dest_size. -
sga_target: 1536Mwas too small:datapatchduringdbcafailed withORA-04031in the java pool and the instance hung.2560Mworks.
3.11. Limitations
-
Out-of-Place Patching of Grid Infrastructure 26ai (switch into a new
oracle_home_gi) is supported,root.shruns rolling, see Out-of-Place Patching. A switch back into a former home of Grid Infrastructure is not implemented (assert inoraswgi_install). The switch of a RAC database into a newORACLE_HOMEis not supported. -
oraswgi_install_remove_obsolete_homesis 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_stageis not/tmp,_JAVA_OPTIONS(-Djava.io.tmpdir) is passed toroot.shand java printsPicked up _JAVA_OPTIONS: ….rootcrs.plparses this line as output ofcluutiland stops withCLSRSC-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.ohasdwith cgroup v2,/run/nologin, entries of Docker in/etc/hosts). -
converge.ymlstarts only with at least 12 GB usable memory on the Docker host (MemAvailable+ memory of running containers of the scenario), override withMOLECULE_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.
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:
| File | Description |
|---|---|
|
Backup script, executes an RMAN script |
|
RMAN script of a job, from the template |
|
Configuration of |
|
Crontab with one entry per job ( |
|
Connection to the RMAN catalog ( |
|
Wallet with the credential of the RMAN catalog ( |
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.
| Attribute | Mandatory | Description |
|---|---|---|
|
yes |
Name of the job = name of the template |
|
no |
|
|
for cron |
Schedule of the crontab entry. A job without schedule gets no crontab entry (e.g. |
|
no |
|
|
no |
|
|
no |
Backup only on the node where the service is running (Grid Infrastructure / Oracle Restart), |
|
no |
|
|
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
| Attribute | Description |
|---|---|
|
List of jobs, see above |
|
|
|
|
|
|
|
Directory of the RMAN scripts of the database, default: |
|
Directory of the RMAN logfiles of the database, default: |
|
TNS alias of the RMAN catalog (entry in |
|
Owner of the RMAN catalog, password from |
|
|
|
Directory of |
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_timeis defined ininit_parameters(state: present,sid: '*'), and -
the value is >=
<n>for the retention policyRECOVERY 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.
| Variable | Default | Description |
|---|---|---|
|
|
RMAN scripts ( |
|
|
Logfiles of |
|
|
Days to keep the logfiles ( |
|
|
File in |
|
|
|
|
|
Prefix |
|
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
| Name | Description |
|---|---|
|
RMAN configuration: retention policy, controlfile autobackup, channel |
|
Like |
|
Online incremental level 0 backup, archive logs, |
|
Online incremental level 1 backup, archive logs, |
|
Offline level 0 backup: the database is restarted in |
|
Backup of the archive logs, deletes the archive logs backed up 1 time |
|
Variants for backups of the FRA to disk and for RAC. The snapshot controlfile is created in |
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
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.
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:
-
parameter on the command line
-
environment variable
-
configuration file
<ORACLE_ADMIN>/rman/rman_backup.cfg -
default of
rman_backup.sh
| Parameter | Environment / rman_backup.cfg | Default | Description |
|---|---|---|---|
|
- |
- |
RMAN script |
|
|
- |
ORACLE_SID, DB_NAME in RAC environments (the instance is determined with |
|
|
see below |
Directory of |
|
|
|
RMAN scripts |
|
|
|
Directory of the logfiles, see Logfiles |
- |
|
|
Remove logfiles older than |
|
|
no catalog |
|
|
- |
- |
No catalog, even when |
|
|
|
|
|
|
- |
Backup only when the service runs on the current node (GI / Oracle Restart) |
|
|
- |
|
- |
|
- |
|
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:
-
--adminor the environment variableORACLE_ADMIN -
$ORACLE_BASE/admin/<db_unique_name>:db_unique_nameis read from the running instance (v$parameter,sqlplus / as sysdba, works inNOMOUNT) -
$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.shwarns, when the file is readable by other users. -
oradb_rmancreates 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_RETENTIONdays 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 directoryORACLE_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
| Code | Description |
|---|---|
0 |
RMAN successful, or backup skipped ( |
1 |
Wrong parameters, service not existing |
10, 11, 12 |
ORACLE_HOME of the ORACLE_SID not found ( |
13 |
Database role could not be determined ( |
14 |
|
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:
-
parameterwithrole: primary -
parameter_standbywithrole: standby: withoutCONFIGURE 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.
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 variablesRMANLOGDIR,RMANSCRIPTDIRandRMANTNS_ADMINin/etc/cron.d.oradb_rmanremoves the environment variables and recreates the crontab entries. The values are inrman_backup.cfgnow. -
Existing calls of
rman_backup.shwith all parameters still work. -
The logfiles are written to
RMAN_LOGDIRper execution. An existing logfile<RMAN_LOGDIR>/<name>_<action>.logof older versions is renamed to*.log.oldby 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_dirand the catalog connect of a database were ignored byoradb_rman(bug). They are used now: check the values in the inventory before the update.
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 databaseDB1_SITE1(container databaseDB1with the PDBORCLPDB) -
dataguard-dbfs2: physical standby databaseDB1_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
1.2. What are we going to do?
-
Prepare the Ansible controller: Ansible in Ubuntu on WSL2 on Windows.
-
Create two Oracle Linux 9 VMs on Hyper-V.
-
Configure the inventory with the IP addresses and login user of the VMs.
-
Start the playbook
playbooks/do_all.yml. It executes all needed playbooks:-
opitzconsulting.ansible_oracle.os: prepare both VMs -
playbooks/nfs_server.yml: NFS server ondataguard-dbfs1, export of the installation media/u01/swand of the RMAN backups/u01/app/oracle/backup, permanent mount of the RMAN backups ondataguard-dbfs2 -
playbooks/autoupgrade.yml: install AutoUpgrade ondataguard-dbfs1and download a gold image from My Oracle Support -
opitzconsulting.ansible_oracle.single_instance_fson both VMs:-
install the ORACLE_HOME on
dataguard-dbfs1from/u01/swand ondataguard-dbfs2from the NFS share, -
create the primary database
DB1_SITE1withdbca, -
create the physical standby database
DB1_SITE2with RMANDUPLICATE … FROM ACTIVE DATABASE, -
create the Data Guard Broker configuration
DG1, -
configure the RMAN backups with cron (role
oradb_rman).
-
-
1.3. Defaults
| Value | Description |
|---|---|
|
git repository on the Ansible controller |
|
Working directory for all Ansible commands |
|
Name of the 1st VM in the inventory: initial primary, NFS server |
|
IP address of the 1st VM ( |
|
Name of the 2nd VM in the inventory: initial physical standby, NFS client |
|
IP address of the 2nd VM ( |
|
Login user on the VMs ( |
|
Installation media: target of the download on |
|
RMAN backups: directory on |
|
Staging directory on the VMs ( |
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 fromdataguard-dbfs2todataguard-dbfs1. The playbooks open the ports infirewalld. -
Internet access for My Oracle Support is needed on
dataguard-dbfs1only.
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. |
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.
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.
---
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:
-
SSH key:
ssh-copy-idforol@192.168.66.166andol@192.168.66.167 -
My Oracle Support credentials (
.envinexample/dataguard/ansible)
4.3. Data Guard configuration
| File | Content |
|---|---|
|
|
|
Connect identifiers |
|
Database |
|
|
The database is defined once for both members.
Only the db_unique_name differs, it is set per host with db1_unique_name.
| Setting | Description |
|---|---|
|
|
|
Assignment to the Data Guard configuration |
|
Static listener entry |
|
|
|
|
|
Oracle Managed Files (OMF) are mandatory |
|
|
|
|
|
|
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, servicenfs-server -
directory
/u01/sw(owneroracle), target of the AutoUpgrade download -
export of
/u01/swread only for the IP addresses of the groupnfs_client(/etc/exports.d/oracle-sw.exports) -
services
nfs,rpc-bindandmountdinfirewalld, whenfirewalldis running
dataguard-dbfs2 (group nfs_client) mounts the share during the installation of the ORACLE_HOME
(role oraswdb_install) and unmounts it afterwards.
| Variable | Value | Description |
|---|---|---|
|
|
Mount the NFS share during the installation |
|
|
NFS server |
|
|
Exported directory on the NFS server |
|
|
Source of the installation media: mount point on the NFS client, local directory on the NFS server |
|
|
The ORACLE_HOME is extracted directly from |
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/backupand one subdirectory peroracle_db_name(DB1), owneroracle, mode0750(RMAN does not create directories) -
dataguard-dbfs1: export of/u01/app/oracle/backupread write for the groupnfs_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.
| Variable | Value | Description |
|---|---|---|
|
|
NFS server |
|
|
Exported directory and mount point |
|
|
Mount options on the NFS client |
|
|
|
The RMAN settings are part of oracle_database_db1 in group_vars/dbfs/database_DB1.yml:
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: "*"}
| Job | Schedule | Executed on |
|---|---|---|
|
during the playbook |
current primary: |
|
during the playbook |
current standby: |
|
Sunday 01:10 |
current primary, |
|
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.
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
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.
| Parameter | dataguard-dbfs1 | dataguard-dbfs2 |
|---|---|---|
ORACLE_BASE |
|
|
ORACLE_HOME |
|
|
ORACLE_SID |
|
|
db_unique_name |
|
|
initial role |
primary |
physical standby |
Created by |
|
RMAN |
PDB |
|
|
db_create_file_dest |
|
|
db_recovery_file_dest |
|
|
Listener |
|
|
Data Guard Broker |
configuration |
|
Archivelog deletion policy |
|
|
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
ssh ol@192.168.66.166 sudo -iu oracle ocenv DB1
dgmgrl / "show configuration"
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.
|
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.
|